yoda is hosted by Hepforge, IPPP Durham
YODA - Yet more Objects for Data Analysis 2.0.0
FillableStorage.h
Go to the documentation of this file.
1// -*- C++ -*-
2//
3// This file is part of YODA -- Yet more Objects for Data Analysis
4// Copyright (C) 2008-2023 The YODA collaboration (see AUTHORS for details)
5//
6#ifndef YODA_FillableStorage_H
7#define YODA_FillableStorage_H
8
10#include "YODA/Dbn.h"
11
12namespace YODA {
13
15 template <size_t FillDim, typename BinT>
17
18
20 template <size_t FillDim, template<size_t, typename, typename> class BinT, typename BinningT, size_t N>
21 struct defaultAdapter<FillDim, BinT<N, double, BinningT>> {
22
23 using AdapterT = std::function<void(
24 BinT<N, double, BinningT>&,
25 typename BinningT::EdgeTypesTuple&&, double, double)>;
26
27 AdapterT _adapter = [](auto& storedNumber, auto&& /* coords */,
28 double weight, double /* fraction */) {
29 storedNumber = storedNumber + weight;
30 };
31 };
32
33 namespace {
36 template <size_t... Is>
37 constexpr auto dblPadding(std::index_sequence<Is...>) {
38 return std::tuple< std::decay_t<decltype((void)Is, std::declval<double>())>...>();
39 }
40 }
41
45 template <size_t DbnN, template<size_t, typename, typename> class BinT, typename BinningT, size_t N>
46 struct defaultAdapter<DbnN, BinT<N, Dbn<DbnN>, BinningT>> {
47 static_assert(DbnN >= N, "Dimension of the Dbn needs to be at least as high as binning dimension!");
48
52 using FillCoords = decltype(std::tuple_cat(std::declval<typename BinningT::EdgeTypesTuple>(),
53 dblPadding(std::make_index_sequence<DbnN-BinningT::Dimension::value>{})));
54
55 using AdapterT = std::function<void(BinT<N, Dbn<DbnN>, BinningT>&, FillCoords&&, double, double)>;
56
62 AdapterT _adapter = [](auto& dbn, auto&& coords, double weight, double fraction) {
63 using CoordsArrT = std::array<double, DbnN>;
64 CoordsArrT dblCoords;
65 size_t binIdx = dbn.index();
66 auto nullifyDiscrete = [&dblCoords, &binIdx, &coords](auto I){
67 using isArithmetic = typename BinningT::template is_Arithmetic<I>;
68 dblCoords[I] = nullifyIfDiscCoord(std::move(std::get<I>(coords)),
69 std::integral_constant<bool,
70 isArithmetic::value>{}, binIdx);
71 };
72 MetaUtils::staticFor<BinningT::Dimension::value>(nullifyDiscrete);
73 if constexpr (DbnN > BinningT::Dimension::value)
74 dblCoords[N] = std::move(std::get<N>(coords));
75 dbn.fill(std::move(dblCoords), weight, fraction);
76 };
77 };
78
79
85 template <size_t FillDim, typename BinContentT, typename... AxisT>
87 : public BinnedStorage<BinContentT, AxisT...> {
88
89 static_assert((FillDim >= sizeof...(AxisT)),
90 "Fill dimension should be at least as large as the binning dimension.");
91
92 protected:
94 using BaseT = BinnedStorage<BinContentT, AxisT...>;
95 using BinningT = typename BaseT::BinningT;
96 using BinT = Bin<sizeof...(AxisT), BinContentT, BinningT>;
98 using FillableT = FillableStorage<FillDim, BinContentT, AxisT...>;
99 using FillCoordsT = decltype(std::tuple_cat(std::declval<typename BinningT::EdgeTypesTuple>(),
100 dblPadding(std::make_index_sequence<FillDim-sizeof...(AxisT)>{})));
101
102 public:
103
106
108 using FillDimension = std::integral_constant<size_t, FillDim>;
109
115 using FillAdapterT = std::function<void(BinT&, FillCoordsT&&, double, double)>;
116
118 // @{
119
122 : BaseT(), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
123
126 : BaseT(binning), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
127
130 : BaseT(std::move(binning)), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
131
133 FillableStorage(const std::vector<AxisT>&... edges, FillAdapterT adapter = AdapterWrapperT()._adapter)
134 : BaseT(edges...), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
135
137 FillableStorage(std::vector<AxisT>&&... edges, FillAdapterT adapter = AdapterWrapperT()._adapter)
138 : BaseT(std::move(edges)...), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
139
141 FillableStorage(const Axis<AxisT>&... axes, FillAdapterT adapter = AdapterWrapperT()._adapter)
142 : BaseT(axes...), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
143
146 : BaseT(std::move(axes)...), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
147
150 : BaseT(other), _fillAdapter(other._fillAdapter),
151 _nancount(other._nancount), _nansumw(other._nansumw), _nansumw2(other._nansumw2) { }
152
155 : BaseT(std::move(other)), _fillAdapter(std::move(other._fillAdapter)),
156 _nancount(std::move(other._nancount)), _nansumw(std::move(other._nansumw)),
157 _nansumw2(std::move(other._nansumw2)) { }
158
159 // @}
160
162 // @{
163
168 template <size_t... Is>
169 int fill(FillCoordsT&& coords, std::index_sequence<Is...>,
170 const double weight = 1.0, const double fraction = 1.0) noexcept {
171
172 // make sure the user isn't trying to fill with NaN ...
173 // include all fill coordinates here
174 if (containsNan(coords)) {
175 _nancount += 1;
176 _nansumw += weight*fraction;
177 _nansumw2 += sqr(weight*fraction);
178 return -1;
179 }
180 // select binned coordinates (possibly a subset of fill coordinates)
181 auto binCoords = std::tuple<AxisT...>(std::get<Is>(coords)...);
182 const size_t binIdx = FillableT::_binning.globalIndexAt(binCoords);
183 _fillAdapter(BaseT::bin(binIdx), std::move(coords), weight, fraction);
184 return int(binIdx);
185 }
186
188 int fill(FillCoordsT&& coords, const double weight = 1.0, const double fraction = 1.0) noexcept {
189 return fill(std::move(coords), std::make_index_sequence<sizeof...(AxisT)>{}, weight, fraction);
190 }
191
192
194 // @{
195
197 size_t fillDim() const { return FillDim; }
198
199 size_t nanCount() const { return _nancount; }
200
201 double nanSumW() const { return _nansumw; }
202
203 double nanSumW2() const { return _nansumw2; }
204
205 void setNanLog(size_t count, double sumw, double sumw2) {
206 _nancount = count;
207 _nansumw = sumw;
208 _nansumw2 = sumw2;
209 }
210
214 void reset() noexcept {
215 _nancount = 0;
216 _nansumw = _nansumw2 = 0.;
218 }
219
220 // @}
221
223 // @{
224
227 if (this != &other) {
228 _fillAdapter = other._fillAdapter;
229 _nancount = other._nancount;
230 _nansumw = other._nansumw;
231 _nansumw2 = other._nansumw2;
232 BaseT::operator=(other);
233 }
234 return *this;
235 }
236
239 if (this != &other) {
240 _fillAdapter = std::move(other._fillAdapter);
241 _nancount = std::move(other._nancount);
242 _nansumw = std::move(other._nansumw);
243 _nansumw2 = std::move(other._nansumw2);
244 BaseT::operator=(std::move(other));
245 }
246 return *this;
247 }
248
251 if (*this != other)
252 throw std::logic_error("YODA::BinnedStorage<" + std::to_string(sizeof...(AxisT)) +\
253 ">: Cannot add BinnedStorages with different binnings.");
254 size_t i = 0;
255 for (auto& bin : FillableT::bins(true)) {
256 bin += other.bin(i++);
257 }
258
259 return *this;
260 }
261
264 if (*this != other)
265 throw std::logic_error("YODA::FillableStorage<" + std::to_string(sizeof...(AxisT)) +\
266 ">: Cannot substract FillableStorages with different binnings.");
267
268 size_t i = 0;
269 for (auto& bin : FillableT::bins(true)) {
270 bin -= other.bin(i++);
271 }
272
273 return *this;
274 }
275
276 // @}
277
278 private:
279
281 FillAdapterT _fillAdapter;
282
283 size_t _nancount;
284
285 double _nansumw, _nansumw2;
286
287 };
288
289} // namespace YODA
290
291#endif
Discrete axis with edges of non-floating-point-type.
Definition BinnedAxis.h:91
generic Bin version that derives from BinBase
Definition Bin.h:265
BinnedStorage, stores the bins and coordinates access to them.
BinT & bin(size_t idx) noexcept
Returns reference to the bin at idx.
Binning< std::decay_t< decltype(std::declval< Axis< AxisT > >())>... > BinningT
Convenience alias to be used in constructor.
BinnedStorage & operator=(const BinnedStorage &other) noexcept
Copy assignment.
void clearBins() noexcept
Deletes all bins and creates empty new ones.
BinsVecWrapper< BinsVecT > bins(const bool includeOverflows=false, const bool includeMaskedBins=false) noexcept
Returns bins vector wrapper, which skips masked elements when iterated over.
const BinningT & binning() const noexcept
Returns dimension underlying binning object reference.
User-facing Dbn class inheriting from DbnBase.
Definition Dbn.h:637
FillableStorage, introduces FillAdapterT on top of BinnedStorage base class.
int fill(FillCoordsT &&coords, const double weight=1.0, const double fraction=1.0) noexcept
Triggers fill adapter on the bin corresponding to coords.
FillableStorage(const FillableStorage &other)
Copy constructor.
FillableStorage(FillableStorage &&other)
Move constructor.
typename BaseT::BinningT BinningT
std::function< void(BinT &, FillCoordsT &&, double, double)> FillAdapterT
Adapter type (type of lambda used to access stored object).
FillCoordsT FillType
Type of the fill coordinates.
FillableStorage(Axis< AxisT > &&... axes, FillAdapterT adapter=AdapterWrapperT()._adapter)
Constructs binning from an adapter and a sequence of Rvalue axes.
size_t fillDim() const
Returns the dimension of the filling tuple.
void setNanLog(size_t count, double sumw, double sumw2)
int fill(FillCoordsT &&coords, std::index_sequence< Is... >, const double weight=1.0, const double fraction=1.0) noexcept
Triggers fill adapter on the bin corresponding to coords.
FillableStorage & operator=(const FillableStorage &other) noexcept
Copy assignment.
FillableStorage(std::vector< AxisT > &&... edges, FillAdapterT adapter=AdapterWrapperT()._adapter)
Constructs binning from an adapter and Rvalue vectors of axes' edges.
FillableStorage(BinningT &&binning, FillAdapterT adapter=AdapterWrapperT()._adapter)
Constructs FillableStorage from Binning. Rvalue.
FillableStorage(const Axis< AxisT > &... axes, FillAdapterT adapter=AdapterWrapperT()._adapter)
Constructs binning from an adapter and a sequence of axes.
FillableStorage & operator-=(const FillableStorage &other)
Subtract another BinnedStorage from this one.
FillableStorage(FillAdapterT adapter=AdapterWrapperT()._adapter)
Nullary constructor for unique pointers etc.
decltype(std::tuple_cat(std::declval< typename BinningT::EdgeTypesTuple >(), dblPadding(std::make_index_sequence< FillDim-sizeof...(AxisT)>{}))) FillCoordsT
std::integral_constant< size_t, FillDim > FillDimension
Fill dimension.
FillableStorage & operator+=(const FillableStorage &other)
Add another BinnedStorage to this one.
FillableStorage(const std::vector< AxisT > &... edges, FillAdapterT adapter=AdapterWrapperT()._adapter)
Constructs binning from an adapter and vectors of axes' edges.
FillableStorage(const BinningT &binning, FillAdapterT adapter=AdapterWrapperT()._adapter)
Constructs FillableStorage from Binning.
defaultAdapter< FillDim, BinT > AdapterWrapperT
void reset() noexcept
Reset the Fillable.
Anonymous namespace to limit visibility.
bool containsNan(const std::tuple< Args... > &coords)
Checks if a coordinate tuple has a nan.
Definition Binning.h:30
double nullifyIfDiscCoord(CoordT &&, std::false_type, double null=0.0)
Nullifies coordinate if it is discrete.
Definition Binning.h:19
NUM sqr(NUM a)
Named number-type squaring operation.
Definition MathUtils.h:216
decltype(std::tuple_cat(std::declval< typename BinningT::EdgeTypesTuple >(), dblPadding(std::make_index_sequence< DbnN-BinningT::Dimension::value >{}))) FillCoords
std::function< void(BinT< N, Dbn< DbnN >, BinningT > &, FillCoords &&, double, double)> AdapterT
std::function< void(BinT< N, double, BinningT > &, typename BinningT::EdgeTypesTuple &&, double, double)> AdapterT
Type to adapter mapping used when user didn't provide type adapter.