49 #include <type_traits> 54 #include "SmartPointer.hh" 55 #include "../Config/ACGDefines.hh" 60 enum class LabelType {
67 std::vector<double> &&bin_widths)
68 : bins_(std::move(bins)),
69 bin_widths_(std::move(bin_widths))
73 const std::vector<size_t> &getBins()
const {
return bins_; }
74 const std::vector<double> &getBinWidths()
const {
return bin_widths_; }
75 virtual double getTotalWidth()
const = 0;
77 virtual LabelType getLabelType()
const = 0;
78 virtual QString getBoundaryLabel(
size_t )
const { assert(
false);
return QString();}
79 virtual QString getBinLabel (
size_t )
const { assert(
false);
return QString();}
82 std::vector<size_t> bins_;
83 std::vector<double> bin_widths_;
87 inline QString formatValue (
int val) {
88 return QString::number(val);
90 inline QString formatValue (
unsigned int val) {
91 return QString::number(val);
93 inline QString formatValue (
double val) {
94 return QString::number(val,
'g', 3);
102 std::vector<T> &&bin_values)
104 std::vector<double>(bin_counts.size(), 1.)),
105 bin_values_(std::move(bin_values))
108 double getTotalWidth()
const override {
return bins_.size();};
109 LabelType getLabelType()
const override {
return LabelType::PerBin; };
110 QString getBinLabel (
size_t idx)
const override {
return formatValue(bin_values_[idx]);}
112 std::vector<T> bin_values_;
121 std::vector<T> &&bin_boundaries,
122 std::vector<double> &&bin_widths
124 :
Histogram(std::move(histogram), std::move(bin_widths)),
125 bin_boundaries_(std::move(bin_boundaries))
127 if (bins_.size() != bin_widths_.size()
128 || bins_.size() + 1 != bin_boundaries_.size()) {
129 throw std::runtime_error(
"Histogram constructor sizes don't match.");
133 const std::vector<T> &getBinBoundaries()
const {
134 return bin_boundaries_;
137 double getTotalWidth()
const override 139 return bin_boundaries_.back() - bin_boundaries_.front();
142 LabelType getLabelType()
const override 144 return LabelType::PerBoundary;
147 QString getBoundaryLabel (
size_t idx)
const override 150 return formatValue(bin_boundaries_[idx]);
155 std::vector<T> bin_boundaries_;
160 std::unique_ptr<Histogram> create_histogram_unbinned(
const std::map<T, size_t> &counts)
162 std::vector<T> values;
163 std::vector<size_t> histogram;
164 values.reserve(counts.size());
165 histogram.reserve(counts.size());
166 for (
const auto &entry: counts)
168 values.push_back(entry.first);
169 histogram.push_back(entry.second);
171 return ptr::make_unique<UnbinnedHistogram<T>>(std::move(histogram), std::move(values));
174 template<
typename T,
typename Iterable>
175 std::unique_ptr<Histogram> create_histogram_autorange(
const Iterable &range,
size_t max_bins = 50)
183 std::vector<T> bin_boundaries;
184 std::vector<size_t> bins;
185 std::vector<double> bin_widths;
187 const size_t n = std::distance(begin(range), end(range));
188 if (n == 0)
return {};
189 const auto minmax = std::minmax_element(begin(range), end(range));
190 const T min = *minmax.first;
191 const T max = *minmax.second;
193 const double min_dbl =
static_cast<double>(min);
194 const double val_range =
static_cast<double>(max) - min_dbl;
196 const size_t n_bins_max = std::min(max_bins, n);
197 bin_boundaries.reserve(n_bins_max + 1);
199 T last_boundary = min;
200 bin_boundaries.push_back(min);
201 for (
size_t i = 1; i < n_bins_max; ++i) {
209 T boundary =
static_cast<T
>(min + (i * val_range) / n_bins_max);
211 if (boundary != last_boundary || i == 0) {
212 bin_boundaries.push_back(boundary);
213 bin_widths.push_back(boundary - last_boundary);
215 last_boundary = boundary;
217 bin_boundaries.push_back(max);
218 bin_widths.push_back(max - last_boundary);
220 bin_boundaries.shrink_to_fit();
221 size_t n_bins = bin_boundaries.size() - 1;
227 std::for_each(begin(range), end(range), [&](
const T &val) {
228 auto it = std::upper_bound(bin_boundaries.begin(), bin_boundaries.end(), val);
229 if (it == bin_boundaries.end()) --it;
230 size_t idx = std::distance(bin_boundaries.begin(), it);
234 return ptr::make_unique<HistogramT<T>>(std::move(bins), std::move(bin_boundaries), std::move(bin_widths));
237 template<
typename Iterable>
238 std::unique_ptr<Histogram> create_histogram_auto(
const Iterable &range,
size_t max_bins = 50)
240 using T =
typename std::remove_cv<
241 typename std::remove_reference<
242 decltype(*begin(range))
245 const size_t n = std::distance(begin(range), end(range));
246 if (n == 0)
return {};
248 std::map<T, size_t> elem_counts;
249 bool too_many_unique =
false;
250 for (
const auto &v: range)
253 if (elem_counts.size() > max_bins)
255 too_many_unique =
true;
260 if (too_many_unique) {
261 return create_histogram_autorange<T>(range, max_bins);
263 return create_histogram_unbinned(elem_counts);
Namespace providing different geometric functions concerning angles.