]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | // Copyright 2019 Przemyslaw Bartosik |
2 | // Copyright 2019 Hans Dembinski | |
3 | // | |
4 | // Distributed under the Boost Software License, Version 1.0. | |
5 | // (See accompanying file LICENSE_1_0.txt | |
6 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | ||
8 | #include <boost/core/lightweight_test.hpp> | |
1e59de90 | 9 | #include <boost/histogram/accumulators/count.hpp> |
92f5a8d4 TL |
10 | #include <boost/histogram/accumulators/mean.hpp> |
11 | #include <boost/histogram/accumulators/ostream.hpp> | |
1e59de90 TL |
12 | #include <boost/histogram/accumulators/sum.hpp> |
13 | #include <boost/histogram/accumulators/thread_safe.hpp> | |
14 | #include <boost/histogram/accumulators/weighted_sum.hpp> | |
92f5a8d4 TL |
15 | #include <boost/histogram/axis/category.hpp> |
16 | #include <boost/histogram/axis/integer.hpp> | |
17 | #include <boost/histogram/axis/option.hpp> | |
18 | #include <boost/histogram/axis/regular.hpp> | |
19 | #include <boost/histogram/make_histogram.hpp> | |
20 | #include <boost/histogram/ostream.hpp> | |
21 | #include <limits> | |
22 | #include <sstream> | |
23 | #include <string> | |
24 | #include "throw_exception.hpp" | |
25 | #include "utility_histogram.hpp" | |
26 | ||
27 | using namespace boost::histogram; | |
28 | ||
29 | template <class Histogram> | |
30 | auto str(const Histogram& h, const unsigned width = 0) { | |
31 | std::ostringstream os; | |
32 | // BEGIN and END make nicer error messages | |
33 | os << "BEGIN\n" << std::setw(width) << h << "END"; | |
34 | return os.str(); | |
35 | } | |
36 | ||
37 | template <class Tag> | |
38 | void run_tests() { | |
39 | using R = axis::regular<>; | |
40 | using R2 = | |
41 | axis::regular<double, boost::use_default, axis::null_type, axis::option::none_t>; | |
42 | using R3 = axis::regular<double, axis::transform::log>; | |
43 | using C = axis::category<std::string>; | |
44 | using I = axis::integer<>; | |
45 | ||
46 | // regular | |
47 | { | |
48 | auto h = make(Tag(), R(3, -0.5, 1.0)); | |
49 | h.at(0) = 1; | |
50 | h.at(1) = 10; | |
51 | h.at(2) = 5; | |
52 | ||
53 | const auto expected = | |
54 | "BEGIN\n" | |
55 | "histogram(regular(3, -0.5, 1, options=underflow | overflow))\n" | |
1e59de90 TL |
56 | " ┌────────────────────────────────────────────────────────────┐\n" |
57 | "[-inf, -0.5) 0 │ │\n" | |
58 | "[-0.5, 0) 1 │█████▉ │\n" | |
59 | "[ 0, 0.5) 10 │███████████████████████████████████████████████████████████ │\n" | |
60 | "[ 0.5, 1) 5 │█████████████████████████████▌ │\n" | |
61 | "[ 1, inf) 0 │ │\n" | |
62 | " └────────────────────────────────────────────────────────────┘\n" | |
92f5a8d4 TL |
63 | "END"; |
64 | ||
20effc67 | 65 | BOOST_TEST_CSTR_EQ(str(h).c_str(), expected); |
92f5a8d4 TL |
66 | } |
67 | ||
68 | // regular, narrow | |
69 | { | |
70 | auto h = make(Tag(), R2(3, -0.5, 1.0)); | |
71 | h.at(0) = 1; | |
72 | h.at(1) = 10; | |
1e59de90 | 73 | h.at(2) = 5; |
92f5a8d4 TL |
74 | |
75 | const auto expected = "BEGIN\n" | |
76 | "histogram(regular(3, -0.5, 1, options=none))\n" | |
1e59de90 TL |
77 | " ┌───────────────────────┐\n" |
78 | "[-0.5, 0) 1 │██▎ │\n" | |
79 | "[ 0, 0.5) 10 │██████████████████████ │\n" | |
80 | "[ 0.5, 1) 5 │███████████ │\n" | |
81 | " └───────────────────────┘\n" | |
92f5a8d4 TL |
82 | "END"; |
83 | ||
20effc67 | 84 | BOOST_TEST_CSTR_EQ(str(h, 40).c_str(), expected); |
92f5a8d4 TL |
85 | |
86 | // too narrow | |
20effc67 TL |
87 | BOOST_TEST_CSTR_EQ(str(h, 10).c_str(), |
88 | "BEGIN\n" | |
89 | "histogram(regular(3, -0.5, 1, options=none))END"); | |
92f5a8d4 TL |
90 | } |
91 | ||
1e59de90 TL |
92 | // regular with accumulators::count |
93 | { | |
94 | auto h = | |
95 | make_s(Tag(), dense_storage<accumulators::count<double>>(), R2(3, -0.5, 1.0)); | |
96 | h.at(0) = 1; | |
97 | h.at(1) = 10; | |
98 | h.at(2) = 5; | |
99 | ||
100 | const auto expected = "BEGIN\n" | |
101 | "histogram(regular(3, -0.5, 1, options=none))\n" | |
102 | " ┌───────────────────────┐\n" | |
103 | "[-0.5, 0) 1 │██▎ │\n" | |
104 | "[ 0, 0.5) 10 │██████████████████████ │\n" | |
105 | "[ 0.5, 1) 5 │███████████ │\n" | |
106 | " └───────────────────────┘\n" | |
107 | "END"; | |
108 | ||
109 | BOOST_TEST_CSTR_EQ(str(h, 40).c_str(), expected); | |
110 | } | |
111 | ||
112 | // regular with thread-safe accumulators::count | |
113 | { | |
114 | auto h = make_s(Tag(), dense_storage<accumulators::count<double, true>>(), | |
115 | R2(3, -0.5, 1.0)); | |
116 | h.at(0) = 1; | |
117 | h.at(1) = 10; | |
118 | h.at(2) = 5; | |
119 | ||
120 | const auto expected = "BEGIN\n" | |
121 | "histogram(regular(3, -0.5, 1, options=none))\n" | |
122 | " ┌───────────────────────┐\n" | |
123 | "[-0.5, 0) 1 │██▎ │\n" | |
124 | "[ 0, 0.5) 10 │██████████████████████ │\n" | |
125 | "[ 0.5, 1) 5 │███████████ │\n" | |
126 | " └───────────────────────┘\n" | |
127 | "END"; | |
128 | ||
129 | BOOST_TEST_CSTR_EQ(str(h, 40).c_str(), expected); | |
130 | } | |
131 | ||
132 | // regular with accumulators::thread_safe | |
133 | { | |
134 | #include <boost/histogram/detail/ignore_deprecation_warning_begin.hpp> | |
135 | auto h = | |
136 | make_s(Tag(), dense_storage<accumulators::thread_safe<int>>(), R2(3, -0.5, 1.0)); | |
137 | h.at(0) = 1; | |
138 | h.at(1) = 10; | |
139 | h.at(2) = 5; | |
140 | ||
141 | const auto expected = "BEGIN\n" | |
142 | "histogram(regular(3, -0.5, 1, options=none))\n" | |
143 | " ┌───────────────────────┐\n" | |
144 | "[-0.5, 0) 1 │██▎ │\n" | |
145 | "[ 0, 0.5) 10 │██████████████████████ │\n" | |
146 | "[ 0.5, 1) 5 │███████████ │\n" | |
147 | " └───────────────────────┘\n" | |
148 | "END"; | |
149 | ||
150 | BOOST_TEST_CSTR_EQ(str(h, 40).c_str(), expected); | |
151 | #include <boost/histogram/detail/ignore_deprecation_warning_end.hpp> | |
152 | } | |
153 | ||
154 | // regular with accumulators::sum | |
155 | { | |
156 | auto h = make_s(Tag(), dense_storage<accumulators::sum<double>>(), R2(3, -0.5, 1.0)); | |
157 | h.at(0) = 1; | |
158 | h.at(1) = 10; | |
159 | h.at(2) = 5; | |
160 | ||
161 | const auto expected = "BEGIN\n" | |
162 | "histogram(regular(3, -0.5, 1, options=none))\n" | |
163 | " ┌───────────────────────┐\n" | |
164 | "[-0.5, 0) 1 │██▎ │\n" | |
165 | "[ 0, 0.5) 10 │██████████████████████ │\n" | |
166 | "[ 0.5, 1) 5 │███████████ │\n" | |
167 | " └───────────────────────┘\n" | |
168 | "END"; | |
169 | ||
170 | BOOST_TEST_CSTR_EQ(str(h, 40).c_str(), expected); | |
171 | } | |
172 | ||
173 | // regular with accumulators::weighted_sum | |
174 | { | |
175 | auto h = make_s(Tag(), dense_storage<accumulators::weighted_sum<double>>(), | |
176 | R2(3, -0.5, 1.0)); | |
177 | h.at(0) = 1; | |
178 | h.at(1) = 10; | |
179 | h.at(2) = 5; | |
180 | ||
181 | const auto expected = "BEGIN\n" | |
182 | "histogram(regular(3, -0.5, 1, options=none))\n" | |
183 | " ┌───────────────────────┐\n" | |
184 | "[-0.5, 0) 1 │██▎ │\n" | |
185 | "[ 0, 0.5) 10 │██████████████████████ │\n" | |
186 | "[ 0.5, 1) 5 │███████████ │\n" | |
187 | " └───────────────────────┘\n" | |
188 | "END"; | |
189 | ||
190 | BOOST_TEST_CSTR_EQ(str(h, 40).c_str(), expected); | |
191 | } | |
192 | ||
92f5a8d4 TL |
193 | // regular2 |
194 | { | |
195 | auto h = make(Tag(), R2(3, -0.5, 1.0)); | |
196 | h.at(0) = 1; | |
197 | h.at(1) = -5; | |
198 | h.at(2) = 2; | |
199 | ||
200 | const auto expected = | |
201 | "BEGIN\n" | |
202 | "histogram(regular(3, -0.5, 1, options=none))\n" | |
1e59de90 TL |
203 | " ┌─────────────────────────────────────────────────────────────┐\n" |
204 | "[-0.5, 0) 1 │ ████████▋ │\n" | |
205 | "[ 0, 0.5) -5 │███████████████████████████████████████████ │\n" | |
206 | "[ 0.5, 1) 2 │ █████████████████▏│\n" | |
207 | " └─────────────────────────────────────────────────────────────┘\n" | |
92f5a8d4 TL |
208 | "END"; |
209 | ||
20effc67 | 210 | BOOST_TEST_CSTR_EQ(str(h).c_str(), expected); |
92f5a8d4 TL |
211 | } |
212 | ||
213 | // regular with log | |
214 | { | |
215 | auto h = make(Tag(), R3(6, 1e-3, 1e3, "foo")); | |
216 | ||
217 | const auto expected = | |
218 | "BEGIN\n" | |
20effc67 TL |
219 | "histogram(regular(transform::log{}, 6, 0.001, 1000, metadata=\"foo\", " |
220 | "options=underflow | overflow))\n" | |
1e59de90 TL |
221 | " ┌───────────────────────────────────────────────────────────┐\n" |
222 | "[ 0, 0.001) 0 │ │\n" | |
223 | "[0.001, 0.01) 0 │ │\n" | |
224 | "[ 0.01, 0.1) 0 │ │\n" | |
225 | "[ 0.1, 1) 0 │ │\n" | |
226 | "[ 1, 10) 0 │ │\n" | |
227 | "[ 10, 100) 0 │ │\n" | |
228 | "[ 100, 1000) 0 │ │\n" | |
229 | "[ 1000, inf) 0 │ │\n" | |
230 | " └───────────────────────────────────────────────────────────┘\n" | |
92f5a8d4 TL |
231 | "END"; |
232 | ||
20effc67 | 233 | BOOST_TEST_CSTR_EQ(str(h).c_str(), expected); |
92f5a8d4 TL |
234 | } |
235 | ||
1e59de90 TL |
236 | // subsampling |
237 | { | |
238 | auto h = make(Tag(), I(-8, 9)); | |
239 | for (int i = -8; i < 9; ++i) h.at(i + 8) = i; | |
240 | ||
241 | const auto expected = "BEGIN\n" | |
242 | "histogram(integer(-8, 9, options=underflow | overflow))\n" | |
243 | " ┌───┐\n" | |
244 | "-9 0 │ │\n" | |
245 | "-8 -8 │█ │\n" | |
246 | "-7 -7 │█ │\n" | |
247 | "-6 -6 │█ │\n" | |
248 | "-5 -5 │█ │\n" | |
249 | "-4 -4 │█ │\n" | |
250 | "-3 -3 │ │\n" | |
251 | "-2 -2 │ │\n" | |
252 | "-1 -1 │ │\n" | |
253 | " 0 0 │ │\n" | |
254 | " 1 1 │ ▏ │\n" | |
255 | " 2 2 │ ▎ │\n" | |
256 | " 3 3 │ ▍ │\n" | |
257 | " 4 4 │ ▌ │\n" | |
258 | " 5 5 │ ▋ │\n" | |
259 | " 6 6 │ ▊ │\n" | |
260 | " 7 7 │ ▉ │\n" | |
261 | " 8 8 │ █ │\n" | |
262 | " 9 0 │ │\n" | |
263 | " └───┘\n" | |
264 | "END"; | |
265 | ||
266 | BOOST_TEST_CSTR_EQ(str(h, 11).c_str(), expected); | |
267 | } | |
268 | ||
92f5a8d4 TL |
269 | // integer |
270 | { | |
1e59de90 TL |
271 | auto h = make(Tag(), I(-8, 9)); |
272 | for (int i = -8; i < 9; ++i) h.at(i + 8) = i; | |
92f5a8d4 TL |
273 | |
274 | const auto expected = | |
275 | "BEGIN\n" | |
1e59de90 TL |
276 | "histogram(integer(-8, 9, options=underflow | overflow))\n" |
277 | " ┌──────────────────────────────────────────────────────────────────────┐\n" | |
278 | "-9 0 │ │\n" | |
279 | "-8 -8 │███████████████████████████████████ │\n" | |
280 | "-7 -7 │ ██████████████████████████████ │\n" | |
281 | "-6 -6 │ ██████████████████████████ │\n" | |
282 | "-5 -5 │ ██████████████████████ │\n" | |
283 | "-4 -4 │ █████████████████ │\n" | |
284 | "-3 -3 │ █████████████ │\n" | |
285 | "-2 -2 │ █████████ │\n" | |
286 | "-1 -1 │ ████ │\n" | |
287 | " 0 0 │ │\n" | |
288 | " 1 1 │ ████▍ │\n" | |
289 | " 2 2 │ ████████▋ │\n" | |
290 | " 3 3 │ ████████████▉ │\n" | |
291 | " 4 4 │ █████████████████▎ │\n" | |
292 | " 5 5 │ █████████████████████▌ │\n" | |
293 | " 6 6 │ █████████████████████████▉ │\n" | |
294 | " 7 7 │ ██████████████████████████████▎ │\n" | |
295 | " 8 8 │ ██████████████████████████████████▌│\n" | |
296 | " 9 0 │ │\n" | |
297 | " └──────────────────────────────────────────────────────────────────────┘\n" | |
92f5a8d4 TL |
298 | "END"; |
299 | ||
20effc67 | 300 | BOOST_TEST_CSTR_EQ(str(h).c_str(), expected); |
92f5a8d4 TL |
301 | } |
302 | ||
1e59de90 | 303 | // category<string> |
92f5a8d4 TL |
304 | { |
305 | auto h = make(Tag(), C({"a", "bb", "ccc", "dddd"})); | |
306 | h.at(0) = 1.23; | |
307 | h.at(1) = 1; | |
308 | h.at(2) = 1.2345789e-3; | |
309 | h.at(3) = 1.2345789e-12; | |
310 | h.at(4) = std::numeric_limits<double>::quiet_NaN(); | |
311 | ||
312 | const auto expected = | |
313 | "BEGIN\n" | |
314 | "histogram(category(\"a\", \"bb\", \"ccc\", \"dddd\", options=overflow))\n" | |
1e59de90 TL |
315 | " ┌────────────────────────────────────────────────────────────┐\n" |
316 | " a 1.23 │███████████████████████████████████████████████████████████ │\n" | |
317 | " bb 1 │████████████████████████████████████████████████ │\n" | |
318 | " ccc 0.001235 │ │\n" | |
319 | " dddd 1.235e-12 │ │\n" | |
320 | "other nan │ │\n" | |
321 | " └────────────────────────────────────────────────────────────┘\n" | |
92f5a8d4 TL |
322 | "END"; |
323 | ||
20effc67 | 324 | BOOST_TEST_CSTR_EQ(str(h).c_str(), expected); |
92f5a8d4 TL |
325 | } |
326 | ||
327 | // histogram with axis that has no value method | |
328 | { | |
329 | struct minimal_axis { | |
330 | int index(int x) const { return x % 2; } | |
331 | int size() const { return 2; } | |
332 | }; | |
333 | ||
334 | auto h = make(Tag(), minimal_axis{}); | |
335 | h.at(0) = 3; | |
336 | h.at(1) = 4; | |
337 | ||
338 | const auto expected = | |
339 | "BEGIN\n" | |
20effc67 TL |
340 | "histogram(" + |
341 | detail::type_name<minimal_axis>() + | |
342 | ")\n" | |
1e59de90 TL |
343 | " ┌────────────────────────────────────────────────────────────────────────┐\n" |
344 | "0 3 │█████████████████████████████████████████████████████▎ │\n" | |
345 | "1 4 │███████████████████████████████████████████████████████████████████████ │\n" | |
346 | " └────────────────────────────────────────────────────────────────────────┘\n" | |
92f5a8d4 TL |
347 | "END"; |
348 | ||
20effc67 | 349 | BOOST_TEST_CSTR_EQ(str(h).c_str(), expected.c_str()); |
92f5a8d4 TL |
350 | } |
351 | ||
352 | // fallback for 2D | |
353 | { | |
354 | auto h = make(Tag(), R(1, -1, 1), R(2, -4, 7)); | |
355 | h.at(-1, 0) = 1000; | |
356 | h.at(-1, -1) = 123; | |
357 | h.at(1, 0) = 1.23456789; | |
358 | h.at(-1, 2) = std::numeric_limits<double>::quiet_NaN(); | |
359 | ||
360 | const auto expected = | |
361 | "BEGIN\n" | |
362 | "histogram(\n" | |
363 | " regular(1, -1, 1, options=underflow | overflow)\n" | |
364 | " regular(2, -4, 7, options=underflow | overflow)\n" | |
365 | " (-1 -1): 123 ( 0 -1): 0 ( 1 -1): 0 (-1 0): 1000 \n" | |
366 | " ( 0 0): 0 ( 1 0): 1.235 (-1 1): 0 ( 0 1): 0 \n" | |
367 | " ( 1 1): 0 (-1 2): nan ( 0 2): 0 ( 1 2): 0 \n" | |
368 | ")END"; | |
369 | ||
20effc67 | 370 | BOOST_TEST_CSTR_EQ(str(h).c_str(), expected); |
92f5a8d4 TL |
371 | } |
372 | ||
373 | // fallback for profile | |
374 | { | |
375 | auto h = make_s(Tag(), profile_storage(), R(1, -1, 1)); | |
376 | h.at(0) = accumulators::mean<>(10, 100, 1000); | |
377 | ||
378 | const auto expected = "BEGIN\n" | |
379 | "histogram(\n" | |
380 | " regular(1, -1, 1, options=underflow | overflow)\n" | |
381 | " (-1): mean(0, 0, -0) ( 0): mean(10, 100, 1000)\n" | |
382 | " ( 1): mean(0, 0, -0) \n" | |
383 | ")END"; | |
384 | ||
20effc67 | 385 | BOOST_TEST_CSTR_EQ(str(h).c_str(), expected); |
92f5a8d4 TL |
386 | } |
387 | } | |
388 | ||
389 | int main() { | |
390 | run_tests<static_tag>(); | |
391 | run_tests<dynamic_tag>(); | |
392 | ||
393 | { | |
394 | // cannot make empty static histogram | |
395 | auto h = histogram<std::vector<axis::regular<>>>(); | |
396 | ||
397 | const auto expected = "BEGIN\n" | |
398 | "histogram()END"; | |
399 | ||
20effc67 | 400 | BOOST_TEST_CSTR_EQ(str(h).c_str(), expected); |
92f5a8d4 TL |
401 | } |
402 | ||
403 | return boost::report_errors(); | |
404 | } |