File indexing completed on 2025-01-18 10:10:44
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef ROOT7_RHistData
0017 #define ROOT7_RHistData
0018
0019 #include <cmath>
0020 #include <vector>
0021 #include "ROOT/RSpan.hxx"
0022 #include "ROOT/RHistUtils.hxx"
0023
0024 namespace ROOT {
0025 namespace Experimental {
0026
0027 template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
0028 class RHist;
0029
0030
0031
0032
0033
0034
0035 template <int DIMENSIONS, class PRECISION>
0036 class RHistStatContent {
0037 public:
0038
0039 using CoordArray_t = Hist::CoordArray_t<DIMENSIONS>;
0040
0041 using Weight_t = PRECISION;
0042
0043 using Content_t = std::vector<PRECISION>;
0044
0045
0046
0047
0048
0049 class RConstBinStat {
0050 public:
0051 RConstBinStat(const RHistStatContent &stat, int index): fContent(stat.GetBinContent(index)) {}
0052 PRECISION GetContent() const { return fContent; }
0053
0054 private:
0055 PRECISION fContent;
0056 };
0057
0058
0059
0060
0061
0062 class RBinStat {
0063 public:
0064 RBinStat(RHistStatContent &stat, int index): fContent(stat.GetBinContent(index)) {}
0065 PRECISION &GetContent() const { return fContent; }
0066
0067 private:
0068 PRECISION &fContent;
0069 };
0070
0071 using ConstBinStat_t = RConstBinStat;
0072 using BinStat_t = RBinStat;
0073
0074 private:
0075
0076 int64_t fEntries = 0;
0077
0078
0079 Content_t fBinContent;
0080
0081
0082 Content_t fOverflowBinContent;
0083
0084 public:
0085 RHistStatContent() = default;
0086 RHistStatContent(size_t bin_size, size_t overflow_size): fBinContent(bin_size), fOverflowBinContent(overflow_size) {}
0087
0088
0089
0090
0091 Weight_t GetBinArray(int binidx) const
0092 {
0093 if (binidx < 0){
0094 return fOverflowBinContent[-binidx - 1];
0095 } else {
0096 return fBinContent[binidx - 1];
0097 }
0098 }
0099
0100
0101
0102
0103 Weight_t& GetBinArray(int binidx)
0104 {
0105 if (binidx < 0){
0106 return fOverflowBinContent[-binidx - 1];
0107 } else {
0108 return fBinContent[binidx - 1];
0109 }
0110 }
0111
0112
0113 void Fill(const CoordArray_t & , int binidx, Weight_t weight = 1.)
0114 {
0115 GetBinArray(binidx) += weight;
0116 ++fEntries;
0117 }
0118
0119
0120
0121 int64_t GetEntries() const { return fEntries; }
0122
0123
0124 size_t sizeNoOver() const noexcept { return fBinContent.size(); }
0125
0126
0127 size_t size() const noexcept { return fBinContent.size() + fOverflowBinContent.size(); }
0128
0129
0130 size_t sizeUnderOver() const noexcept { return fOverflowBinContent.size(); }
0131
0132
0133 Weight_t operator[](int binidx) const { return GetBinArray(binidx); }
0134
0135 Weight_t &operator[](int binidx) { return GetBinArray(binidx); }
0136
0137
0138 Weight_t GetBinContent(int binidx) const { return GetBinArray(binidx); }
0139
0140 Weight_t &GetBinContent(int binidx) { return GetBinArray(binidx); }
0141
0142
0143 const Content_t &GetContentArray() const { return fBinContent; }
0144
0145 Content_t &GetContentArray() { return fBinContent; }
0146
0147
0148 const Content_t &GetOverflowContentArray() const { return fOverflowBinContent; }
0149
0150 Content_t &GetOverflowContentArray() { return fOverflowBinContent; }
0151
0152
0153 void Add(const RHistStatContent& other) {
0154 assert(fBinContent.size() == other.fBinContent.size()
0155 && "this and other have incompatible bin configuration!");
0156 assert(fOverflowBinContent.size() == other.fOverflowBinContent.size()
0157 && "this and other have incompatible bin configuration!");
0158 fEntries += other.fEntries;
0159 for (size_t b = 0; b < fBinContent.size(); ++b)
0160 fBinContent[b] += other.fBinContent[b];
0161 for (size_t b = 0; b < fOverflowBinContent.size(); ++b)
0162 fOverflowBinContent[b] += other.fOverflowBinContent[b];
0163 }
0164 };
0165
0166
0167
0168
0169
0170 template <int DIMENSIONS, class PRECISION>
0171 class RHistStatTotalSumOfWeights {
0172 public:
0173
0174 using CoordArray_t = Hist::CoordArray_t<DIMENSIONS>;
0175
0176 using Weight_t = PRECISION;
0177
0178
0179
0180
0181
0182 class RBinStat {
0183 public:
0184 RBinStat(const RHistStatTotalSumOfWeights &, int) {}
0185 };
0186
0187 using ConstBinStat_t = RBinStat;
0188 using BinStat_t = RBinStat;
0189
0190 private:
0191
0192 PRECISION fSumWeights = 0;
0193
0194 public:
0195 RHistStatTotalSumOfWeights() = default;
0196 RHistStatTotalSumOfWeights(size_t, size_t) {}
0197
0198
0199 void Fill(const CoordArray_t & , int, Weight_t weight = 1.) { fSumWeights += weight; }
0200
0201
0202 Weight_t GetSumOfWeights() const { return fSumWeights; }
0203
0204
0205 void Add(const RHistStatTotalSumOfWeights& other) {
0206 fSumWeights += other.fSumWeights;
0207 }
0208 };
0209
0210
0211
0212
0213
0214 template <int DIMENSIONS, class PRECISION>
0215 class RHistStatTotalSumOfSquaredWeights {
0216 public:
0217
0218 using CoordArray_t = Hist::CoordArray_t<DIMENSIONS>;
0219
0220 using Weight_t = PRECISION;
0221
0222
0223
0224
0225
0226 class RBinStat {
0227 public:
0228 RBinStat(const RHistStatTotalSumOfSquaredWeights &, int) {}
0229 };
0230
0231 using ConstBinStat_t = RBinStat;
0232 using BinStat_t = RBinStat;
0233
0234 private:
0235
0236 PRECISION fSumWeights2 = 0;
0237
0238 public:
0239 RHistStatTotalSumOfSquaredWeights() = default;
0240 RHistStatTotalSumOfSquaredWeights(size_t, size_t) {}
0241
0242
0243 void Fill(const CoordArray_t & , int , Weight_t weight = 1.) { fSumWeights2 += weight * weight; }
0244
0245
0246 Weight_t GetSumOfSquaredWeights() const { return fSumWeights2; }
0247
0248
0249 void Add(const RHistStatTotalSumOfSquaredWeights& other) {
0250 fSumWeights2 += other.fSumWeights2;
0251 }
0252 };
0253
0254
0255
0256
0257
0258 template <int DIMENSIONS, class PRECISION>
0259 class RHistStatUncertainty {
0260
0261 public:
0262
0263 using CoordArray_t = Hist::CoordArray_t<DIMENSIONS>;
0264
0265 using Weight_t = PRECISION;
0266
0267 using Content_t = std::vector<PRECISION>;
0268
0269
0270
0271
0272
0273 class RConstBinStat {
0274 public:
0275 RConstBinStat(const RHistStatUncertainty &stat, int index): fSumW2(stat.GetSumOfSquaredWeights(index)) {}
0276 PRECISION GetSumW2() const { return fSumW2; }
0277
0278 double GetUncertaintyImpl() const { return std::sqrt(std::abs(fSumW2)); }
0279
0280 private:
0281 PRECISION fSumW2;
0282 };
0283
0284
0285
0286
0287
0288 class RBinStat {
0289 public:
0290 RBinStat(RHistStatUncertainty &stat, int index): fSumW2(stat.GetSumOfSquaredWeights(index)) {}
0291 PRECISION &GetSumW2() const { return fSumW2; }
0292
0293 double GetUncertaintyImpl() const { return std::sqrt(std::abs(fSumW2)); }
0294
0295 private:
0296 PRECISION &fSumW2;
0297 };
0298
0299 using ConstBinStat_t = RConstBinStat;
0300 using BinStat_t = RBinStat;
0301
0302 private:
0303
0304 Content_t fSumWeightsSquared;
0305
0306 Content_t fOverflowSumWeightsSquared;
0307
0308 public:
0309 RHistStatUncertainty() = default;
0310 RHistStatUncertainty(size_t bin_size, size_t overflow_size): fSumWeightsSquared(bin_size), fOverflowSumWeightsSquared(overflow_size) {}
0311
0312
0313
0314
0315 Weight_t GetBinArray(int binidx) const
0316 {
0317 if (binidx < 0){
0318 return fOverflowSumWeightsSquared[-binidx - 1];
0319 } else {
0320 return fSumWeightsSquared[binidx - 1];
0321 }
0322 }
0323
0324
0325
0326
0327 Weight_t& GetBinArray(int binidx)
0328 {
0329 if (binidx < 0){
0330 return fOverflowSumWeightsSquared[-binidx - 1];
0331 } else {
0332 return fSumWeightsSquared[binidx - 1];
0333 }
0334 }
0335
0336
0337 void Fill(const CoordArray_t & , int binidx, Weight_t weight = 1.)
0338 {
0339 GetBinArray(binidx) += weight * weight;
0340 }
0341
0342
0343
0344 double GetBinUncertaintyImpl(int binidx) const { return std::sqrt(GetBinArray(binidx)); }
0345
0346
0347 Weight_t GetSumOfSquaredWeights(int binidx) const { return GetBinArray(binidx); }
0348
0349 Weight_t &GetSumOfSquaredWeights(int binidx) { return GetBinArray(binidx); }
0350
0351
0352 const std::vector<double> &GetSumOfSquaredWeights() const { return fSumWeightsSquared; }
0353
0354 std::vector<double> &GetSumOfSquaredWeights() { return fSumWeightsSquared; }
0355
0356
0357 const std::vector<double> &GetOverflowSumOfSquaredWeights() const { return fOverflowSumWeightsSquared; }
0358
0359 std::vector<double> &GetOverflowSumOfSquaredWeights() { return fOverflowSumWeightsSquared; }
0360
0361
0362 void Add(const RHistStatUncertainty& other) {
0363 assert(fSumWeightsSquared.size() == other.fSumWeightsSquared.size()
0364 && "this and other have incompatible bin configuration!");
0365 assert(fOverflowSumWeightsSquared.size() == other.fOverflowSumWeightsSquared.size()
0366 && "this and other have incompatible bin configuration!");
0367 for (size_t b = 0; b < fSumWeightsSquared.size(); ++b)
0368 fSumWeightsSquared[b] += other.fSumWeightsSquared[b];
0369 for (size_t b = 0; b < fOverflowSumWeightsSquared.size(); ++b)
0370 fOverflowSumWeightsSquared[b] += other.fOverflowSumWeightsSquared[b];
0371 }
0372 };
0373
0374
0375
0376
0377 template <int DIMENSIONS, class PRECISION>
0378 class RHistDataMomentUncert {
0379 public:
0380
0381 using CoordArray_t = Hist::CoordArray_t<DIMENSIONS>;
0382
0383 using Weight_t = PRECISION;
0384
0385 using Content_t = std::vector<PRECISION>;
0386
0387
0388
0389
0390
0391 class RBinStat {
0392 public:
0393 RBinStat(const RHistDataMomentUncert &, int) {}
0394 };
0395
0396 using ConstBinStat_t = RBinStat;
0397 using BinStat_t = RBinStat;
0398
0399 private:
0400 std::array<Weight_t, DIMENSIONS> fMomentXW;
0401 std::array<Weight_t, DIMENSIONS> fMomentX2W;
0402
0403
0404 public:
0405 RHistDataMomentUncert() = default;
0406 RHistDataMomentUncert(size_t, size_t) {}
0407
0408
0409 void Fill(const CoordArray_t &x, int , Weight_t weight = 1.)
0410 {
0411 for (int idim = 0; idim < DIMENSIONS; ++idim) {
0412 const PRECISION xw = x[idim] * weight;
0413 fMomentXW[idim] += xw;
0414 fMomentX2W[idim] += x[idim] * xw;
0415 }
0416 }
0417
0418
0419
0420
0421 void Add(const RHistDataMomentUncert& other) {
0422 for (size_t d = 0; d < DIMENSIONS; ++d) {
0423 fMomentXW[d] += other.fMomentXW[d];
0424 fMomentX2W[d] += other.fMomentX2W[d];
0425 }
0426 }
0427 };
0428
0429
0430
0431
0432 template <int DIMENSIONS, class PRECISION>
0433 class RHistStatRuntime {
0434 public:
0435
0436 using CoordArray_t = Hist::CoordArray_t<DIMENSIONS>;
0437
0438 using Weight_t = PRECISION;
0439
0440 using Content_t = std::vector<PRECISION>;
0441
0442
0443
0444
0445
0446 class RBinStat {
0447 public:
0448 RBinStat(const RHistStatRuntime &, int) {}
0449 };
0450
0451 using ConstBinStat_t = RBinStat;
0452 using BinStat_t = RBinStat;
0453
0454 RHistStatRuntime() = default;
0455 RHistStatRuntime(size_t, size_t) {}
0456 virtual ~RHistStatRuntime() = default;
0457
0458 virtual void DoFill(const CoordArray_t &x, int binidx, Weight_t weightN) = 0;
0459 void Fill(const CoordArray_t &x, int binidx, Weight_t weight = 1.) { DoFill(x, binidx, weight); }
0460 };
0461
0462 namespace Detail {
0463
0464
0465
0466
0467 template <class DATA, class... BASES>
0468 class RHistBinStat: public BASES... {
0469 private:
0470
0471 template <class T>
0472 static auto HaveUncertainty(const T *This) -> decltype(This->GetUncertaintyImpl());
0473
0474 template <class T>
0475 static char HaveUncertainty(...);
0476
0477 public:
0478 RHistBinStat(DATA &data, int index): BASES(data, index)... {}
0479
0480
0481
0482 static constexpr bool HasBinUncertainty()
0483 {
0484 struct AllYourBaseAreBelongToUs: public BASES... {
0485 };
0486 return sizeof(HaveUncertainty<AllYourBaseAreBelongToUs>(nullptr)) == sizeof(double);
0487 }
0488
0489
0490 template <bool B = true, class = typename std::enable_if<B && HasBinUncertainty()>::type>
0491 double GetUncertainty() const
0492 {
0493 return this->GetUncertaintyImpl();
0494 }
0495
0496
0497
0498 template <bool B = true, class = typename std::enable_if<B && !HasBinUncertainty()>::type>
0499 double GetUncertainty(...) const
0500 {
0501 auto content = this->GetContent();
0502 return std::sqrt(std::fabs(content));
0503 }
0504 };
0505
0506
0507
0508
0509 template <int DIMENSIONS, class PRECISION, class STORAGE, template <int D_, class P_> class... STAT>
0510 class RHistData: public STAT<DIMENSIONS, PRECISION>... {
0511 private:
0512
0513 template <class T>
0514 static auto HaveUncertainty(const T *This) -> decltype(This->GetBinUncertaintyImpl(12));
0515
0516 template <class T>
0517 static char HaveUncertainty(...);
0518
0519 public:
0520
0521 using Hist_t = RHist<DIMENSIONS, PRECISION, STAT...>;
0522
0523
0524 using Weight_t = PRECISION;
0525
0526
0527 using CoordArray_t = Hist::CoordArray_t<DIMENSIONS>;
0528
0529
0530 using ConstHistBinStat_t =
0531 RHistBinStat<const RHistData, typename STAT<DIMENSIONS, PRECISION>::ConstBinStat_t...>;
0532
0533
0534 using HistBinStat_t = RHistBinStat<RHistData, typename STAT<DIMENSIONS, PRECISION>::BinStat_t...>;
0535
0536
0537 static constexpr int GetNDim() noexcept { return DIMENSIONS; }
0538
0539 RHistData() = default;
0540
0541
0542
0543 RHistData(size_t bin_size, size_t overflow_size): STAT<DIMENSIONS, PRECISION>(bin_size, overflow_size)... {}
0544
0545
0546 void Fill(const CoordArray_t &x, int binidx, Weight_t weight = 1.)
0547 {
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562 using trigger_base_fill = int[];
0563 (void)trigger_base_fill{(STAT<DIMENSIONS, PRECISION>::Fill(x, binidx, weight), 0)...};
0564 }
0565
0566
0567
0568
0569
0570
0571 template <typename OtherData>
0572 void Add(const OtherData &other)
0573 {
0574
0575 using trigger_base_add = int[];
0576 (void)trigger_base_add{(STAT<DIMENSIONS, PRECISION>::Add(other), 0)...};
0577 }
0578
0579
0580
0581 static constexpr bool HasBinUncertainty()
0582 {
0583 struct AllYourBaseAreBelongToUs: public STAT<DIMENSIONS, PRECISION>... {
0584 };
0585 return sizeof(HaveUncertainty<AllYourBaseAreBelongToUs>(nullptr)) == sizeof(double);
0586 }
0587
0588
0589
0590 template <bool B = true, class = typename std::enable_if<B && HasBinUncertainty()>::type>
0591 double GetBinUncertainty(int binidx) const
0592 {
0593 return this->GetBinUncertaintyImpl(binidx);
0594 }
0595
0596
0597
0598 template <bool B = true, class = typename std::enable_if<B && !HasBinUncertainty()>::type>
0599 double GetBinUncertainty(int binidx, ...) const
0600 {
0601 auto content = this->GetBinContent(binidx);
0602 return std::sqrt(std::fabs(content));
0603 }
0604
0605
0606 ConstHistBinStat_t GetView(int idx) const { return ConstHistBinStat_t(*this, idx); }
0607
0608 HistBinStat_t GetView(int idx) { return HistBinStat_t(*this, idx); }
0609 };
0610 }
0611
0612 }
0613 }
0614
0615 #endif