File indexing completed on 2026-09-12 09:31:09
0001
0002
0003
0004
0005
0006 #ifndef YODA_FillableStorage_H
0007 #define YODA_FillableStorage_H
0008
0009 #include "YODA/BinnedStorage.h"
0010 #include "YODA/Dbn.h"
0011
0012 namespace YODA {
0013
0014
0015
0016 template <size_t FillDim, typename BinT>
0017 struct defaultAdapter;
0018
0019
0020
0021 template <size_t FillDim, template<size_t, typename, typename> class BinT, typename BinningT, size_t N>
0022 struct defaultAdapter<FillDim, BinT<N, double, BinningT>> {
0023
0024 using AdapterT = std::function<void(
0025 BinT<N, double, BinningT>&,
0026 typename BinningT::EdgeTypesTuple&&, double, double)>;
0027
0028 AdapterT _adapter = [](auto& storedNumber, auto&& ,
0029 double weight, double ) {
0030 storedNumber = storedNumber + weight;
0031 };
0032 };
0033
0034 namespace {
0035
0036
0037 template <size_t... Is>
0038 constexpr auto dblPadding(std::index_sequence<Is...>) {
0039 return std::tuple< std::decay_t<decltype((void)Is, std::declval<double>())>...>();
0040 }
0041 }
0042
0043
0044
0045
0046 template <size_t DbnN, template<size_t, typename, typename> class BinT, typename BinningT, size_t N>
0047 struct defaultAdapter<DbnN, BinT<N, Dbn<DbnN>, BinningT>> {
0048 static_assert(DbnN >= N, "Dimension of the Dbn needs to be at least as high as binning dimension!");
0049
0050
0051
0052
0053 using FillCoords = decltype(std::tuple_cat(std::declval<typename BinningT::EdgeTypesTuple>(),
0054 dblPadding(std::make_index_sequence<DbnN-BinningT::Dimension::value>{})));
0055
0056 using AdapterT = std::function<void(BinT<N, Dbn<DbnN>, BinningT>&, FillCoords&&, double, double)>;
0057
0058
0059
0060
0061
0062
0063 AdapterT _adapter = [](auto& dbn, auto&& coords, double weight, double fraction) {
0064 using CoordsArrT = std::array<double, DbnN>;
0065 CoordsArrT dblCoords;
0066 size_t binIdx = dbn.index();
0067 auto nullifyDiscrete = [&dblCoords, &binIdx, &coords](auto I){
0068 using isArithmetic = typename BinningT::template is_Arithmetic<I>;
0069 dblCoords[I] = nullifyIfDiscCoord(std::move(std::get<I>(coords)),
0070 std::integral_constant<bool,
0071 isArithmetic::value>{}, binIdx);
0072 };
0073 MetaUtils::staticFor<BinningT::Dimension::value>(nullifyDiscrete);
0074 if constexpr (DbnN > BinningT::Dimension::value)
0075 dblCoords[N] = std::move(std::get<N>(coords));
0076 dbn.fill(std::move(dblCoords), weight, fraction);
0077 };
0078 };
0079
0080
0081
0082
0083
0084
0085
0086 template <size_t FillDim, typename BinContentT, typename... AxisT>
0087 class FillableStorage
0088 : public BinnedStorage<BinContentT, AxisT...> {
0089
0090 static_assert((FillDim >= sizeof...(AxisT)),
0091 "Fill dimension should be at least as large as the binning dimension.");
0092
0093 protected:
0094
0095 using BaseT = BinnedStorage<BinContentT, AxisT...>;
0096 using BinningT = typename BaseT::BinningT;
0097 using BinT = Bin<sizeof...(AxisT), BinContentT, BinningT>;
0098 using AdapterWrapperT = defaultAdapter<FillDim, BinT>;
0099 using FillableT = FillableStorage<FillDim, BinContentT, AxisT...>;
0100 using FillCoordsT = decltype(std::tuple_cat(std::declval<typename BinningT::EdgeTypesTuple>(),
0101 dblPadding(std::make_index_sequence<FillDim-sizeof...(AxisT)>{})));
0102
0103 public:
0104
0105
0106 using FillType = FillCoordsT;
0107
0108
0109 using FillDimension = std::integral_constant<size_t, FillDim>;
0110
0111
0112
0113
0114
0115
0116 using FillAdapterT = std::function<void(BinT&, FillCoordsT&&, double, double)>;
0117
0118
0119
0120
0121
0122 FillableStorage(FillAdapterT adapter = AdapterWrapperT()._adapter)
0123 : BaseT(), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
0124
0125
0126 FillableStorage(const BinningT& binning, FillAdapterT adapter = AdapterWrapperT()._adapter)
0127 : BaseT(binning), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
0128
0129
0130 FillableStorage(BinningT&& binning, FillAdapterT adapter = AdapterWrapperT()._adapter)
0131 : BaseT(std::move(binning)), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
0132
0133
0134 FillableStorage(const std::vector<AxisT>&... edges, FillAdapterT adapter = AdapterWrapperT()._adapter)
0135 : BaseT(edges...), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
0136
0137
0138 FillableStorage(std::vector<AxisT>&&... edges, FillAdapterT adapter = AdapterWrapperT()._adapter)
0139 : BaseT(std::move(edges)...), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
0140
0141
0142 FillableStorage(const Axis<AxisT>&... axes, FillAdapterT adapter = AdapterWrapperT()._adapter)
0143 : BaseT(axes...), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
0144
0145
0146 FillableStorage(Axis<AxisT>&&... axes, FillAdapterT adapter = AdapterWrapperT()._adapter)
0147 : BaseT(std::move(axes)...), _fillAdapter(adapter), _nancount(0), _nansumw(0.), _nansumw2(0.) { }
0148
0149
0150 FillableStorage(const FillableStorage& other)
0151 : BaseT(other), _fillAdapter(other._fillAdapter),
0152 _nancount(other._nancount), _nansumw(other._nansumw), _nansumw2(other._nansumw2) { }
0153
0154
0155 FillableStorage(FillableStorage&& other)
0156 : BaseT(std::move(other)), _fillAdapter(std::move(other._fillAdapter)),
0157 _nancount(std::move(other._nancount)), _nansumw(std::move(other._nansumw)),
0158 _nansumw2(std::move(other._nansumw2)) { }
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 template <size_t... Is>
0170 int fill(FillCoordsT&& coords, std::index_sequence<Is...>,
0171 const double weight = 1.0, const double fraction = 1.0) noexcept {
0172
0173
0174
0175 if (containsNan(coords)) {
0176 _nancount += 1;
0177 _nansumw += weight*fraction;
0178 _nansumw2 += sqr(weight*fraction);
0179 return -1;
0180 }
0181
0182 auto binCoords = std::tuple<AxisT...>(std::get<Is>(coords)...);
0183 const size_t binIdx = FillableT::_binning.globalIndexAt(binCoords);
0184 _fillAdapter(BaseT::bin(binIdx), std::move(coords), weight, fraction);
0185 return int(binIdx);
0186 }
0187
0188
0189 int fill(FillCoordsT&& coords, const double weight = 1.0, const double fraction = 1.0) noexcept {
0190 return fill(std::move(coords), std::make_index_sequence<sizeof...(AxisT)>{}, weight, fraction);
0191 }
0192
0193
0194
0195
0196
0197
0198 size_t fillDim() const { return FillDim; }
0199
0200 size_t nanCount() const { return _nancount; }
0201
0202 double nanSumW() const { return _nansumw; }
0203
0204 double nanSumW2() const { return _nansumw2; }
0205
0206 void setNanLog(size_t count, double sumw, double sumw2) {
0207 _nancount = count;
0208 _nansumw = sumw;
0209 _nansumw2 = sumw2;
0210 }
0211
0212
0213
0214
0215 void reset() noexcept {
0216 _nancount = 0;
0217 _nansumw = _nansumw2 = 0.;
0218 BaseT::clearBins();
0219 }
0220
0221
0222
0223
0224
0225
0226
0227 FillableStorage& operator = (const FillableStorage& other) noexcept {
0228 if (this != &other) {
0229 _fillAdapter = other._fillAdapter;
0230 _nancount = other._nancount;
0231 _nansumw = other._nansumw;
0232 _nansumw2 = other._nansumw2;
0233 BaseT::operator=(other);
0234 }
0235 return *this;
0236 }
0237
0238
0239 FillableStorage& operator = (FillableStorage&& other) noexcept {
0240 if (this != &other) {
0241 _fillAdapter = std::move(other._fillAdapter);
0242 _nancount = std::move(other._nancount);
0243 _nansumw = std::move(other._nansumw);
0244 _nansumw2 = std::move(other._nansumw2);
0245 BaseT::operator=(std::move(other));
0246 }
0247 return *this;
0248 }
0249
0250
0251 FillableStorage& operator += (const FillableStorage& other) {
0252 if (*this != other)
0253 throw std::logic_error("YODA::BinnedStorage<" + std::to_string(sizeof...(AxisT)) +\
0254 ">: Cannot add BinnedStorages with different binnings.");
0255 size_t i = 0;
0256 for (auto& bin : FillableT::bins(true)) {
0257 bin += other.bin(i++);
0258 }
0259
0260 return *this;
0261 }
0262
0263
0264 FillableStorage& operator -= (const FillableStorage& other) {
0265 if (*this != other)
0266 throw std::logic_error("YODA::FillableStorage<" + std::to_string(sizeof...(AxisT)) +\
0267 ">: Cannot substract FillableStorages with different binnings.");
0268
0269 size_t i = 0;
0270 for (auto& bin : FillableT::bins(true)) {
0271 bin -= other.bin(i++);
0272 }
0273
0274 return *this;
0275 }
0276
0277
0278
0279 private:
0280
0281
0282 FillAdapterT _fillAdapter;
0283
0284 size_t _nancount;
0285
0286 double _nansumw, _nansumw2;
0287
0288 };
0289
0290
0291 }
0292
0293 #endif