44 #ifndef ACG_HISTOGRAM_HH
45 #define ACG_HISTOGRAM_HH
52 #include <type_traits>
56 #include "../Config/ACGDefines.hh"
61 enum class LabelType {
67 const std::vector<size_t> &getBins()
const {
return bins_; }
68 const std::vector<double> &getBinWidths()
const {
return bin_widths_; }
69 virtual double getTotalWidth()
const = 0;
71 virtual LabelType getLabelType()
const = 0;
72 virtual QString getBoundaryLabel(
size_t )
const { assert(
false);
return QString();}
73 virtual QString getBinLabel (
size_t )
const { assert(
false);
return QString();}
76 std::vector<size_t> bins_;
77 std::vector<double> bin_widths_;
90 const std::vector<T> &bin_boundaries,
91 const std::vector<double> &bin_widths)
93 if (bins_.size() != bin_widths_.size()
94 || bins_.size() + 1 != bin_boundaries_.size()) {
95 throw std::runtime_error(
"Histogram constructor sizes don't match.");
98 bin_boundaries_ = bin_boundaries;
99 bin_widths_ = bin_widths;
100 double range = bin_boundaries.back() - bin_boundaries.front();
101 avg_bin_size_ = range / bins_.size();
104 template<
typename IterT>
105 HistogramT(IterT begin, IterT end,
size_t max_bins)
107 static_assert(std::is_assignable<T&, typename IterT::value_type>::value,
"IterT incompatible with T.");
108 static_assert(std::is_floating_point<typename IterT::value_type>::value,
"HistogramT currently only supports floating point values.");
109 assert(max_bins > 0);
110 const size_t n = std::distance(begin, end);
113 const auto minmax = std::minmax_element(begin, end);
114 const T min = *minmax.first;
115 const T max = *minmax.second;
116 const double min_dbl =
static_cast<double>(min);
117 const double range =
static_cast<double>(max) - min_dbl;
119 const size_t n_bins_max = std::min(max_bins, n);
120 bin_boundaries_.reserve(n_bins_max + 1);
122 T last_boundary = min;
123 bin_boundaries_.push_back(min);
124 for (
size_t i = 1; i < n_bins_max; ++i) {
132 T boundary =
static_cast<T
>(min + (i * range) / n_bins_max);
134 if (boundary != last_boundary || i == 0) {
135 bin_boundaries_.push_back(boundary);
136 bin_widths_.push_back(boundary - last_boundary);
138 last_boundary = boundary;
140 bin_boundaries_.push_back(max);
141 bin_widths_.push_back(max - last_boundary);
143 bin_boundaries_.shrink_to_fit();
144 size_t n_bins = bin_boundaries_.size() - 1;
145 bins_.resize(n_bins);
150 std::for_each(begin, end, [&](
const T &val) {
151 auto it = std::upper_bound(bin_boundaries_.begin(), bin_boundaries_.end(), val);
152 if (it == bin_boundaries_.end()) --it;
153 size_t idx = std::distance(bin_boundaries_.begin(), it);
157 avg_bin_size_ = range / n_bins;
160 const std::vector<T> &getBinBoundaries()
const {
161 return bin_boundaries_;
164 double getTotalWidth()
const override
166 return bin_boundaries_.back() - bin_boundaries_.front();
169 LabelType getLabelType()
const override
171 return LabelType::PerBoundary;
174 QString getBoundaryLabel (
size_t idx)
const override;
178 std::vector<T> bin_boundaries_;
179 double avg_bin_size_ = 0.0;
185 return QString::number(bin_boundaries_[idx]);
190 #endif // ACG_HISTOGRAM_HH
Namespace providing different geometric functions concerning angles.