ndm 0.2.5
Loading...
Searching...
No Matches
Axis.cc
1#include <iostream>
2#include <cmath>
3
4#include "ndm.hh"
5#include "Utils.hh"
6
7#include "Axis.hh"
8
9namespace NDM {
10Axis::Axis(double min, double max, EMode mode, double delta) : mMin(min), mMax(max), mMode(mode), mMinDelta(delta)
11{
15
16 // Chcek if min is higher then max. If it is switch min with max
17 if (min > max) {
18 spdlog::warn("Swaping min[{}] and max[{}] values entered by user, because min is higher then max !!!", min,
19 max);
20 mMax = min;
21 mMin = max;
22 }
23
25}
27{
31}
32
34{
38
39 // Checking for numer of decimels after dot
40 int decimalsMin = decimels_right(mMin);
41 int decimalsMax = decimels_right(mMax);
42
43 // If both decimels are zero then we check, if we can divide to lower number
44 if (decimalsMin == 0 && decimalsMax == 0) {
45
46 // Checking for numer of decimels before dot
47 decimalsMin = decimels_left(mMin);
48 decimalsMax = decimels_left(mMax);
49
50 // Calculate decimel minimum
51 int m = std::min(decimalsMin, decimalsMax);
52
53 // Sets coresponding values for mMultiply and mShift
54 mMultiply = 1 / std::pow(10, m);
56 }
57 else {
58
59 // Calculate decimel maximum
60 int m = std::max(decimalsMin, decimalsMax);
61
62 // Sets coresponding values for mMultiply and mShift
63 mMultiply = std::pow(10, m);
65 }
66
67 // Handle mode setting
68 if (mMode == kAligned)
69 mMaxB = std::pow(2, ceil(log2(maxb_user())));
70 else
71 mMaxB = maxb_user();
72}
73
74void Axis::minmax(double min, double max)
75{
79 mMin = min;
80 mMax = max;
81}
82
83void Axis::find(double v, double & min, double & max, std::string & path, int levelrequest, int levelmax)
84{
88
89 spdlog::trace("Finding value[{}] levelrequest[{}] levelmas[{}]...", v, levelrequest, levelmax);
90
91 // Reseting path
92 path = "";
93
94 int currentlevel = 0;
95 min = 0;
96 max = maxb();
97
98 if (v < mMin || v > mMax || NDM::Utils::is_equal(v, mMax)) {
99 spdlog::warn("Value '{}' is out of range <{},{}) !!!", v, mMin, mMax);
100 min = max = 0;
101 return;
102 }
103
104 v = to_internal(v);
105
106 find(v, levelrequest, levelmax, currentlevel, min, max, path);
108
109 // We should convert min and max to user format
110 min = to_user(min);
111 max = to_user(max);
112 spdlog::trace("Result value[{}] <{},{}) path[{}] level[{}] internal[<{},{})] ...", to_user(v), min, max, path,
113 currentlevel, to_internal(min), to_internal(max));
114}
115
116void Axis::find(double & v, int & levelrequest, int & levelmax, int & currentlevel, double & min, double & max,
117 std::string & path)
118{
122
123 if (NDM::Utils::is_equal(v, min)) {
124 if (currentlevel >= levelrequest) return;
125 }
126 if (NDM::Utils::is_equal(v, max)) {
127 if (currentlevel == 0) return;
128 double oldmax = max;
129 max += (max - min);
130 min = oldmax;
131 return;
132 }
133
134 if ((max - min) < mMinDelta) return;
135
136 if (currentlevel > levelmax) return;
137
138 currentlevel++;
139
140 double avg = (max + min) / 2;
141 spdlog::trace("min[{}]({}) max[{}]({}) avg[{}]({}) value[{}] ...", min, to_user(min), max, to_user(max), avg,
142 to_user(avg), to_user(v));
143 if (v >= avg) {
144 min = avg;
145 path += "1";
146 }
147 else {
148 max = avg;
149 path += "0";
150 }
151
152 spdlog::trace("level=[{}] path={}...", currentlevel, path);
153 find(v, levelrequest, levelmax, currentlevel, min, max, path);
154}
155
156void Axis::expand(char direction, int power)
157{
161 modify_range(direction, std::abs(power));
162}
163
164void Axis::shrink(char direction, int power)
165{
169 modify_range(direction, -std::abs(power));
170}
171
172void Axis::modify_range(char direction, int power)
173{
177
178 if (power == 0) {
179 spdlog::warn("Power is zero !!! Doing nothing ...");
180 return;
181 }
182
183 if ((power < 0) && std::pow(2, std::abs(power)) > mMaxB) {
184 print();
185 spdlog::warn("Divide is not possible !!! Reason : mMaxB[{}] < divide[{}]", mMaxB, std::pow(2, std::abs(power)));
186 return;
187 }
188
189 if (direction == '>') {
190 if (power > 0) {
191 for (int i = 0; i < power; ++i) mMax += (mMax - mMin);
192 }
193 else if (power < 0) {
194
195 for (int i = 0; i < std::abs(power); ++i) mMax -= (mMax - mMin) / 2;
196 }
197 }
198 else if (direction == '<') {
199 if (power > 0) {
200 for (int i = 0; i < power; ++i) mMin -= (mMax - mMin);
201 }
202 else if (power < 0) {
203
204 for (int i = 0; i < std::abs(power); ++i) mMin += (mMax - mMin) / 2;
205 }
206 }
207 else {
208 spdlog::error("Direction '{}' is not supported !!!");
209 spdlog::error(" Hint: Try '>' for right or '<' for left.");
210 }
211
213}
214
215void Axis::print() const
216{
220
221 spdlog::info("min[{}] max[{}] maxb[{}({})] mode[{}] level[{}] shift[{}] multiply[{}]", mMin, mMax, mMaxB, maxb_user(),
222 (int)mMode, mLevel, mShift, mMultiply);
223}
224
225int Axis::decimels_right(double num, double mult, double min, double max)
226{
230
231 int n = 0;
232 double fractpart, intpart, tmp;
233 fractpart = modf(num, &intpart);
234 spdlog::trace("L1 : num[{}] tmp[{}] intpart[{}] fractpart[{}]", num, tmp, intpart, fractpart);
235 while (fractpart > min && fractpart < max) {
236 tmp = fractpart * mult;
237 fractpart = modf(tmp, &intpart);
238 spdlog::trace("L2 : num[{}] tmp[{}] intpart[{}] fractpart[{}]", num, tmp, intpart, fractpart);
239 n++;
240 }
241
242 return n;
243}
244
245int Axis::decimels_left(double num, double mult, double min)
246{
250
251 if (num < 0.01) return 0;
252
253 int n = 0;
254 double fractpart, intpart, tmp;
255 fractpart = modf(num, &intpart);
256 spdlog::trace("H1 : num[{}] tmp[{}] intpart[{}] fractpart[{}]", num, tmp, intpart, fractpart);
257 while (fractpart < min) {
258 tmp = intpart / mult;
259 fractpart = modf(tmp, &intpart);
260 spdlog::trace("H2 : num[{}] tmp[{}] intpart[{}] fractpart[{}]", num, tmp, intpart, fractpart);
261 n++;
262 }
263 return n - 1;
264}
265
266void Axis::split(std::vector<double> & mins, int level)
267{
271 mins.clear();
272 double p2 = pow(2, level);
273 if (p2 > mMaxB) {
274 spdlog::error("Cannot split histogram with {} bins into {} levels because (2^{}={}) > {}. Stop.", mMaxB, level,
275 level, p2, mMaxB);
276 return;
277 }
278 double step = mMaxB / p2;
279
280 spdlog::debug("split: level[{}] max[{}] step[{}]", level, mMaxB, step);
281
282 for (double iMins = 0; iMins < mMaxB; iMins += step) {
283 if (iMins >= to_internal(mMax)) break;
284 mins.push_back(to_user(iMins));
285 }
286}
287
288} // namespace NDM
double min() const
Returns user defined minimum.
Definition Axis.hh:41
double mMin
User defined minimum.
Definition Axis.hh:66
void split(std::vector< double > &mins, int level)
Definition Axis.cc:266
unsigned int level() const
Returns level.
Definition Axis.hh:62
int decimels_right(double num, double mult=10, double min=0.01, double max=0.99)
Definition Axis.cc:225
virtual ~Axis()
Definition Axis.cc:26
double max() const
Returns user defined maximum.
Definition Axis.hh:43
void expand(char direction='>', int power=1)
Expand range.
Definition Axis.cc:156
EMode mMode
Axis mode.
Definition Axis.hh:69
void recalculate_range()
Definition Axis.cc:33
int decimels_left(double num, double mult=10, double min=0.01)
Definition Axis.cc:245
void shrink(char direction='>', int power=1)
Shrink range.
Definition Axis.cc:164
Axis(double min=0.0, double max=1.0, EMode mode=kAligned, double delta=1)
Definition Axis.cc:10
double to_user(double v) const
Convert interal to user format.
Definition Axis.hh:57
double mMinDelta
Minimal delta of axis range.
Definition Axis.hh:74
double maxb() const
Returns internal maximum.
Definition Axis.hh:47
double mShift
Shift to the internal min/max parameters.
Definition Axis.hh:71
double mMultiply
Multiply to the internal min/max parameters.
Definition Axis.hh:72
double mMax
User defined maximum.
Definition Axis.hh:67
void find(double v, double &min, double &max, std::string &path, int levelrequest=-1, int levelmax=100)
Find bin and print info for given value.
Definition Axis.cc:83
double mMaxB
Internal maximum.
Definition Axis.hh:70
double maxb_user() const
Returns internal maximum2.
Definition Axis.hh:49
void print() const
Prints axis info.
Definition Axis.cc:215
void modify_range(char direction='>', int power=1)
Definition Axis.cc:172
double to_internal(double v) const
Convert user to internal format.
Definition Axis.hh:59
unsigned int mLevel
Level of division.
Definition Axis.hh:73
void minmax(double min, double max)
Sets user defined minimum and maximum.
Definition Axis.cc:74
EMode
Mode for axis.
Definition Axis.hh:15