Alexandria  2.16
Please provide a description of the project.
Histogram.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2020 Euclid Science Ground Segment
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License as published by the Free
6  * Software Foundation; either version 3.0 of the License, or (at your option)
7  * any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
25 #ifndef ALEXANDRIA_HISTOGRAM_HISTOGRAM_H
26 #define ALEXANDRIA_HISTOGRAM_HISTOGRAM_H
27 
28 #include <cassert>
29 #include <cmath>
30 #include <algorithm>
31 #include <memory>
32 #include <utility>
33 #include <tuple>
34 #include <type_traits>
35 #include <vector>
38 
39 namespace Euclid {
40 namespace Histogram {
41 
48 template<typename VarType>
49 class BinStrategy {
50 public:
51 
57  BinStrategy() : m_nbins(0) {}
58 
62  virtual ~BinStrategy() = default;
63 
67  size_t getBinCount() const {
68  return m_nbins;
69  }
70 
79  virtual ssize_t getBinIndex(VarType value) const = 0;
80 
87  virtual std::vector<VarType> getEdges() const {
88  std::vector<VarType> edges(m_nbins + 1);
89  size_t i = 0;
90  std::generate(edges.begin(), edges.end(), [this, &i]() { return getEdge(i++); });
91  return edges;
92  }
93 
101  virtual std::pair<VarType, VarType> getBinEdges(size_t i) const {
102  return std::make_pair(getEdge(i), getEdge(i + 1));
103  }
104 
109  virtual VarType getEdge(size_t e) const = 0;
110 
121  virtual VarType getBin(size_t i) const {
122  auto edges = getBinEdges(i);
123  return (edges.second + edges.first) / 2;
124  }
125 
126 protected:
127  size_t m_nbins;
128 };
129 
137 template<typename VarType, typename WeightType = float>
138 class Histogram {
139 public:
140 
141  static_assert(std::is_arithmetic<VarType>::value, "Histogram only supports numerical types");
142  static_assert(std::is_arithmetic<WeightType>::value, "Histogram only supports numerical weights");
143 
157  template<typename IterType, typename BinType, typename=typename std::enable_if<std::is_move_constructible<BinType>::value>::type>
158  Histogram(IterType begin, IterType end, BinType&& bin_type) {
159  auto binning_impl = make_unique<ComputationImpl<BinType>>(std::move(bin_type));
160  binning_impl->computeBins(begin, end, ConstantWeight{});
161  m_binning_concept = std::move(binning_impl);
162  }
163 
185  template<typename IterType, typename WeightIterType, typename BinType, typename=typename std::enable_if<std::is_move_constructible<BinType>::value>::type>
186  Histogram(IterType begin, IterType end, WeightIterType wbegin, WeightIterType wend, BinType&& bin_type) {
187  assert(wend - wbegin == end - begin);
188  auto binning_impl = make_unique<ComputationImpl<BinType>>(std::move(bin_type));
189  binning_impl->computeBins(begin, end, wbegin);
190  m_binning_concept = std::move(binning_impl);
191  }
192 
196  Histogram(const Histogram& other) {
197  m_binning_concept = other.m_binning_concept->clone();
198  }
199 
203  Histogram(Histogram&&) = default;
204 
208  Histogram& operator=(const Histogram&) = default;
209 
213  Histogram& operator=(Histogram&&) = default;
214 
219  size_t size() const {
220  return m_binning_concept->size();
221  }
222 
228  return std::vector<WeightType>(m_binning_concept->m_counts->begin() + m_binning_concept->m_clip_left,
229  m_binning_concept->m_counts->begin() + m_binning_concept->m_clip_right + 1);
230  }
231 
239  return m_binning_concept->getBinStrategy().getEdges();
240  }
241 
247  std::vector<VarType> bins(m_binning_concept->m_counts->size());
248  size_t i = 0;
249  std::generate(bins.begin(), bins.end(), [this, &i]() { return m_binning_concept->getBinStrategy().getBin(i++); });
250  return bins;
251  }
252 
260  return m_binning_concept->getBinStrategy().getBinEdges(i);
261  }
262 
270  void clip(VarType min, VarType max) {
271  m_binning_concept->clip(min, max);
272  }
273 
290  return m_binning_concept->getStats();
291  }
292 
293 
294 private:
298  struct ConstantWeight {
300  return *this;
301  }
302 
303  WeightType operator*() const {
304  return 1;
305  }
306  };
307 
319 
320  ComputationInterface(): m_counts(new std::vector<WeightType>()) {}
321 
322  size_t size() const {
323  return m_clip_right - m_clip_left + 1;
324  }
325 
326  virtual const BinStrategy<VarType>& getBinStrategy() const = 0;
327 
328  virtual std::unique_ptr<ComputationInterface> clone() const = 0;
329 
330  virtual void clip(VarType min, VarType max) = 0;
331 
333  };
334 
340  template<typename BinType>
345  BinType m_binning;
346 
347  explicit ComputationImpl(BinType&& bin_type): m_binning(std::move(bin_type)) {
348  }
349 
350  ComputationImpl(const ComputationImpl& other) = default;
351 
352  const BinStrategy<VarType>& getBinStrategy() const final {
353  return m_binning;
354  }
355 
357  return make_unique<ComputationImpl<BinType>>(*this);
358  }
359 
373  template<typename IterType, typename WeightIterType>
374  void computeBins(IterType begin, IterType end, WeightIterType wbegin);
375 
376  void clip(VarType min, VarType max) final;
377 
379  };
380 
382 };
383 
384 } // end of namespace Histogram
385 } // end of namespace Euclid
386 
387 #include "Histogram/_impl/ComputationImpl.icpp"
388 
389 #endif // ALEXANDRIA_HISTOGRAM_HISTOGRAM_H
STL class.
virtual std::vector< VarType > getEdges() const
Definition: Histogram.h:87
std::vector< VarType > getEdges() const
Definition: Histogram.h:238
virtual VarType getBin(size_t i) const
Definition: Histogram.h:121
std::tuple< VarType, VarType, VarType > getStats() const
Definition: Histogram.h:289
T generate(T... args)
virtual ~BinStrategy()=default
virtual std::tuple< VarType, VarType, VarType > getStats() const =0
STL namespace.
std::vector< WeightType > getCounts() const
Definition: Histogram.h:227
T end(T... args)
virtual const BinStrategy< VarType > & getBinStrategy() const =0
virtual std::unique_ptr< ComputationInterface > clone() const =0
size_t getBinCount() const
Definition: Histogram.h:67
void clip(VarType min, VarType max) final
void clip(VarType min, VarType max)
Definition: Histogram.h:270
Histogram(IterType begin, IterType end, WeightIterType wbegin, WeightIterType wend, BinType &&bin_type)
Definition: Histogram.h:186
T make_pair(T... args)
virtual void clip(VarType min, VarType max)=0
T move(T... args)
std::unique_ptr< ComputationInterface > clone() const final
Definition: Histogram.h:356
const BinStrategy< VarType > & getBinStrategy() const final
Definition: Histogram.h:352
std::tuple< VarType, VarType, VarType > getStats() const final
virtual VarType getEdge(size_t e) const =0
Histogram(IterType begin, IterType end, BinType &&bin_type)
Definition: Histogram.h:158
virtual ssize_t getBinIndex(VarType value) const =0
STL class.
std::pair< VarType, VarType > getBinEdges(size_t i) const
Definition: Histogram.h:259
T begin(T... args)
virtual std::pair< VarType, VarType > getBinEdges(size_t i) const
Definition: Histogram.h:101
std::vector< VarType > getBins() const
Definition: Histogram.h:246
void computeBins(IterType begin, IterType end, WeightIterType wbegin)
std::unique_ptr< ComputationInterface > m_binning_concept
Definition: Histogram.h:381
std::shared_ptr< std::vector< WeightType > > m_counts
Definition: Histogram.h:317
Histogram & operator=(const Histogram &)=default
Histogram(const Histogram &other)
Definition: Histogram.h:196