Line data Source code
1 : /* Copyright (c) 2016-2017, Human Brain Project
2 : * Ahmet.Bilgili@epfl.ch
3 : */
4 :
5 : #include "Histogram.h"
6 :
7 : #include <vmmlib/vector.hpp>
8 :
9 : namespace lexis
10 : {
11 : namespace render
12 : {
13 :
14 5 : Histogram::Histogram()
15 : {
16 5 : setMin( std::numeric_limits<float>::infinity( ));
17 5 : setMax( -std::numeric_limits<float>::infinity( ));
18 5 : }
19 :
20 1 : Histogram& Histogram::operator+=( const Histogram& histogram )
21 : {
22 1 : if( histogram.getBins().empty( ))
23 0 : return *this;
24 :
25 1 : if( getBins().empty( ))
26 : {
27 0 : *this = histogram;
28 0 : return *this;
29 : }
30 :
31 1 : if( histogram.getBins().size() != getBins().size( ))
32 0 : throw std::runtime_error( "Addition of incompatible histograms" );
33 :
34 1 : const uint64_t* srcBins = histogram.getBins().data();
35 :
36 1 : uint64_t* bins = getBins().data();
37 5 : for( size_t i = 0; i < getBins().size(); ++i )
38 4 : bins[ i ] += srcBins[ i ];
39 :
40 1 : setMin( std::min( getMin(), histogram.getMin()));
41 1 : setMax( std::max( getMax(), histogram.getMax()));
42 :
43 1 : return *this;
44 : }
45 :
46 7 : bool Histogram::operator==( const Histogram& rhs ) const
47 : {
48 7 : if( this == &rhs )
49 1 : return true;
50 :
51 12 : return getMin() == rhs.getMin() &&
52 11 : getMax() == rhs.getMax() &&
53 14 : getBins().size() == rhs.getBins().size() &&
54 3 : memcmp( getBins().data(), rhs.getBins().data(),
55 9 : getBins().size() * sizeof( uint64_t ) ) == 0;
56 : }
57 :
58 0 : bool Histogram::operator!=( const Histogram& rhs ) const
59 : {
60 0 : return !(*this == rhs);
61 : }
62 :
63 0 : size_t Histogram::getMinIndex() const
64 : {
65 0 : const uint64_t* bins = getBins().data();
66 0 : return std::distance( bins, std::min_element( bins, bins + getBins().size( )));
67 : }
68 :
69 0 : size_t Histogram::getMaxIndex() const
70 : {
71 0 : const uint64_t* bins = getBins().data();
72 0 : return std::distance( bins, std::max_element( bins, bins + getBins().size( )));
73 : }
74 :
75 4 : bool Histogram::isEmpty() const
76 : {
77 4 : const uint64_t* bins = getBins().data();
78 4 : for( size_t i = 0; i < getBins().size(); ++i )
79 : {
80 3 : if( bins[ i ] > 0 )
81 3 : return false;
82 : }
83 1 : return true;
84 : }
85 :
86 0 : uint64_t Histogram::getSum() const
87 : {
88 0 : const uint64_t* bins = getBins().data();
89 0 : uint64_t sum = 0;
90 0 : for( size_t i = 0; i < getBins().size(); ++i )
91 0 : sum += bins[ i ];
92 :
93 0 : return sum;
94 : }
95 :
96 0 : vmml::Vector2f Histogram::getRange() const
97 : {
98 0 : return { getMin(), getMax() };
99 : }
100 :
101 0 : double Histogram::getRatio( const size_t index ) const
102 : {
103 0 : if( index >= getBins().size( ))
104 0 : return 0.0f;
105 :
106 0 : const uint64_t sum = getSum();
107 0 : if( sum == 0 )
108 0 : return 0.0f;
109 :
110 0 : const uint64_t* bins = getBins().data();
111 0 : return (double)bins[ index ] / (double)sum;
112 : }
113 :
114 0 : void Histogram::resize( size_t newSize )
115 : {
116 0 : getBins().resize( newSize );
117 0 : }
118 :
119 : std::vector< vmml::Vector2f >
120 4 : Histogram::sampleCurve( const bool logScale, const vmml::Vector2f& range ) const
121 : {
122 4 : if( isEmpty( ))
123 1 : return {};
124 :
125 3 : const auto* bins = getBins().data();
126 3 : const auto maxIndex = std::distance( bins,
127 6 : std::max_element( bins, bins + getBins().size() ));
128 3 : const auto heightMax = bins[maxIndex];
129 3 : const float scale = 1.f/ (logScale ? std::log(heightMax) : heightMax);
130 :
131 3 : const size_t nbBins = std::ceil(getBins().size() * (range[1] - range[0]));
132 3 : const size_t offset( std::floor(getBins().size() * range[0] ));
133 :
134 6 : std::vector< vmml::Vector2f > points;
135 3 : points.reserve( nbBins );
136 13 : for( size_t i = 0; i < nbBins; ++i )
137 : {
138 10 : float value = bins[offset + i];
139 10 : if( logScale && value <= 1.0f )
140 1 : value = 1.0f;
141 40 : points.push_back( { float(i)/nbBins,
142 30 : 1.f - scale * (logScale ? std::log(value) : value) });
143 : }
144 3 : return points;
145 : }
146 :
147 : }
148 12 : }
|