histogram_custom_axis_test.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright 2018-2019 Hans Dembinski
  2. //
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt
  5. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #include <boost/core/lightweight_test.hpp>
  7. #include <boost/histogram/accumulators/mean.hpp>
  8. #include <boost/histogram/accumulators/weighted_mean.hpp>
  9. #include <boost/histogram/axis.hpp>
  10. #include <boost/histogram/axis/ostream.hpp>
  11. #include <boost/histogram/histogram.hpp>
  12. #include <boost/histogram/literals.hpp>
  13. #include <boost/histogram/make_histogram.hpp>
  14. #include <boost/histogram/ostream.hpp>
  15. #include <boost/histogram/storage_adaptor.hpp>
  16. #include <sstream>
  17. #include <stdexcept>
  18. #include <tuple>
  19. #include <utility>
  20. #include <vector>
  21. #include "throw_exception.hpp"
  22. #include "utility_histogram.hpp"
  23. using namespace boost::histogram;
  24. struct modified_axis : public axis::integer<> {
  25. using integer::integer; // inherit ctors of base
  26. // customization point: convert argument and call base class
  27. auto index(const char* s) const { return integer::index(std::atoi(s)); }
  28. };
  29. struct minimal {
  30. auto index(int x) const { return static_cast<axis::index_type>(x % 2); }
  31. auto size() const { return axis::index_type{2}; }
  32. };
  33. struct axis2d {
  34. auto index(const std::tuple<double, double>& x) const {
  35. return axis::index_type{std::get<0>(x) == 1 && std::get<1>(x) == 2};
  36. }
  37. auto size() const { return axis::index_type{2}; }
  38. };
  39. class axis2d_growing {
  40. public:
  41. auto index(std::tuple<double, double> xy) const {
  42. const auto x = std::get<0>(xy);
  43. const auto y = std::get<1>(xy);
  44. const auto r = std::sqrt(x * x + y * y);
  45. return std::min(static_cast<axis::index_type>(r), size());
  46. }
  47. auto update(std::tuple<double, double> xy) {
  48. const auto x = std::get<0>(xy);
  49. const auto y = std::get<1>(xy);
  50. const auto r = std::sqrt(x * x + y * y);
  51. const auto n = static_cast<int>(r);
  52. const auto old = size_;
  53. if (n >= size_) size_ = n + 1;
  54. return std::make_pair(n, old - size_);
  55. }
  56. axis::index_type size() const { return size_; }
  57. private:
  58. axis::index_type size_ = 0;
  59. };
  60. template <class Tag>
  61. void run_tests() {
  62. // one 2d axis
  63. {
  64. auto h = make(Tag(), axis2d());
  65. h(1, 2); // ok, forwards 2d tuple to axis
  66. h(std::make_tuple(1, 2)); // also ok, forwards 2d tuple to axis
  67. BOOST_TEST_THROWS(h(1), std::invalid_argument);
  68. BOOST_TEST_THROWS(h(1, 2, 3), std::invalid_argument);
  69. BOOST_TEST_EQ(h.at(0), 0); // ok, bin access is still 1d
  70. BOOST_TEST_EQ(h[std::make_tuple(1)], 2);
  71. // also works with weights
  72. h(1, 2, weight(2));
  73. h(std::make_tuple(weight(3), 1, 2));
  74. BOOST_TEST_EQ(h.at(0), 0);
  75. BOOST_TEST_EQ(h.at(1), 7);
  76. auto h2 = make_s(Tag(), profile_storage(), axis2d());
  77. h2(1, 2, sample(2));
  78. BOOST_TEST_EQ(h2[1].count(), 1);
  79. BOOST_TEST_EQ(h2[1].value(), 2);
  80. auto h3 = make_s(Tag(), weighted_profile_storage(), axis2d());
  81. h3(1, 2, weight(3), sample(2));
  82. BOOST_TEST_EQ(h3[1].sum_of_weights(), 3);
  83. BOOST_TEST_EQ(h3[1].value(), 2);
  84. }
  85. // several axes, one 2d
  86. {
  87. auto h = make(Tag(), modified_axis(0, 3), minimal(), axis2d());
  88. h("0", 1, std::make_tuple(1.0, 2.0));
  89. h("1", 2, std::make_tuple(2.0, 1.0));
  90. BOOST_TEST_EQ(h.rank(), 3);
  91. BOOST_TEST_EQ(h.at(0, 0, 0), 0);
  92. BOOST_TEST_EQ(h.at(0, 1, 1), 1);
  93. BOOST_TEST_EQ(h.at(1, 0, 0), 1);
  94. }
  95. // growing axis
  96. {
  97. auto h = make_s(Tag{}, std::vector<int>{}, axis2d_growing{});
  98. BOOST_TEST_EQ(h.size(), 0);
  99. h(0, 0);
  100. BOOST_TEST_EQ(h.size(), 1);
  101. h(1, 0);
  102. h(0, 1);
  103. BOOST_TEST_EQ(h.size(), 2);
  104. h(10, 0);
  105. BOOST_TEST_EQ(h.size(), 11);
  106. BOOST_TEST_EQ(h[0], 1);
  107. BOOST_TEST_EQ(h[1], 2);
  108. BOOST_TEST_EQ(h[10], 1);
  109. BOOST_TEST_THROWS(h(0), std::invalid_argument);
  110. }
  111. }
  112. int main() {
  113. run_tests<static_tag>();
  114. run_tests<dynamic_tag>();
  115. return boost::report_errors();
  116. }