Rivet API documentation

Rivet 4.1.3
RivetYODA.hh
1#ifndef RIVET_RIVETYODA_HH
2#define RIVET_RIVETYODA_HH
3
4#include "Rivet/Config/RivetCommon.hh"
5#include "Rivet/Tools/TypeTraits.hh"
6#include "YODA/AnalysisObject.h"
7#include "YODA/Counter.h"
8#include "YODA/Histo.h"
9#include "YODA/Profile.h"
10#include "YODA/Estimate0D.h"
11#include "YODA/BinnedEstimate.h"
12#include "YODA/Scatter.h"
13
14// Use execinfo for backtrace if available
15#ifdef HAVE_EXECINFO_H
16#include <execinfo.h>
17#endif
18
19#include <map>
20#include <unordered_map>
21#include <valarray>
22
23
24namespace YODA {
25
26 template<size_t DbnN, typename ... AxisT>
27 using BinnedDbnPtr = std::shared_ptr<YODA::BinnedDbn<DbnN, AxisT...>>;
28
29 template<typename ... AxisT>
30 using BinnedHistoPtr = BinnedDbnPtr<sizeof...(AxisT), AxisT...>;
31
32 template<typename ... AxisT>
33 using BinnedProfilePtr = BinnedDbnPtr<sizeof...(AxisT)+1, AxisT...>;
34
35 template<typename ... AxisT>
36 using BinnedEstimatePtr = std::shared_ptr<YODA::BinnedEstimate<AxisT...>>;
37
38 template<size_t N>
39 using ScatterNDPtr = std::shared_ptr<YODA::ScatterND<N>>;
40
41 using AnalysisObjectPtr = std::shared_ptr<YODA::AnalysisObject>;
42 using CounterPtr = std::shared_ptr<YODA::Counter>;
43 using Estimate0DPtr = std::shared_ptr<YODA::Estimate0D>;
44 using Histo1DPtr = BinnedHistoPtr<double>;
45 using Histo2DPtr = BinnedHistoPtr<double,double>;
46 using Histo3DPtr = BinnedHistoPtr<double,double,double>;
47 using Profile1DPtr = BinnedProfilePtr<double>;
48 using Profile2DPtr = BinnedProfilePtr<double,double>;
49 using Profile3DPtr = BinnedProfilePtr<double,double,double>;
50 using Estimate1DPtr = BinnedEstimatePtr<double>;
51 using Estimate2DPtr = BinnedEstimatePtr<double,double>;
52 using Estimate3DPtr = BinnedEstimatePtr<double,double,double>;
53 using Scatter1DPtr = ScatterNDPtr<1>;
54 using Scatter2DPtr = ScatterNDPtr<2>;
55 using Scatter3DPtr = ScatterNDPtr<3>;
56
57}
58
59namespace Rivet {
60
63 template <typename T>
64 bool copyAO(YODA::AnalysisObjectPtr src, YODA::AnalysisObjectPtr dst, const double scale=1.0) {
65 if (dst->hasAnnotation("Type") && src->type() != dst->type()) {
66 throw YODA::LogicError("Operation requries types to be the same!");
67 }
68 for (const std::string& a : src->annotations()) {
69 dst->setAnnotation(a, src->annotation(a));
70 }
71 shared_ptr<T> dstPtr = std::static_pointer_cast<T>(dst);
72 *dstPtr = *std::static_pointer_cast<T>(src);
73 if constexpr (isFillable<T>::value) { dstPtr->scaleW(scale); }
74 return true;
75 }
76
77
79 struct TypeBaseHandle {
80
81 TypeBaseHandle() = default;
82
83 virtual ~TypeBaseHandle() { }
84
85 virtual bool copyAO(YODA::AnalysisObjectPtr src,
86 YODA::AnalysisObjectPtr dst,
87 const double scale = 1.0) const = 0;
88
89 virtual bool addAO(YODA::AnalysisObjectPtr src,
90 YODA::AnalysisObjectPtr& dst,
91 const double scale = 1.0) const = 0;
92
93 };
94
95
96
99 template<typename T>
100 struct TypeHandle : public TypeBaseHandle {
101
102 bool addAO(YODA::AnalysisObjectPtr src,
103 YODA::AnalysisObjectPtr& dst,
104 const double scale = 1.0) const {
105 if constexpr (isFillable<T>::value) {
106 std::shared_ptr<T> srcPtr = std::static_pointer_cast<T>(src);
107 srcPtr->scaleW(scale);
108 if (dst == nullptr) { dst = src; return true; }
109 try { *std::static_pointer_cast<T>(dst) += *srcPtr; }
110 catch (YODA::BinningError&) { return false; }
111 return true;
112 }
113 else if (dst == nullptr) { dst = src; return true; }
114 return false;
115 }
116
117 bool copyAO(YODA::AnalysisObjectPtr src,
118 YODA::AnalysisObjectPtr dst,
119 const double scale = 1.0) const {
120 return ::Rivet::copyAO<T>(src, dst, scale);
121 }
122
123 };
124
125
133
135 using Weight = double;
136
138 template<typename T>
139 using Fill = pair<typename T::FillType, Weight>;
140
142 template<typename T>
143 using Fills = vector<Fill<T>>;
144
145
146
157 template<typename T>
159
160
162 template<>
163 class FillCollector<YODA::Counter> : public YODA::Counter {
164 public:
165
166 using YAO = YODA::Counter;
167 using Ptr = shared_ptr<FillCollector<YAO>>;
168 using YAO::operator =;
169
170 FillCollector() : YAO() { }
171
179 FillCollector(typename YAO::Ptr yao) : YAO(yao->path()) { }
180
185 int fill(const double weight=1.0, const double fraction = 1.0) {
186 (void)fraction; // suppress unused variable warning
187 _fills.insert(_fills.end(), { YAO::FillType(), weight } );
188 return 0;
189 }
190
192 void reset() { _fills.clear(); }
193
195 const Fills<YAO>& fills() const { return _fills; }
196
197 private:
198
199 Fills<YAO> _fills;
200
201 };
202
203
205 template <size_t DbnN, typename... AxisT>
206 class FillCollector<YODA::BinnedDbn<DbnN, AxisT...>>
207 : public YODA::BinnedDbn<DbnN, AxisT...> {
208 public:
209
210 using YAO = YODA::BinnedDbn<DbnN, AxisT...>;
211 using Ptr = shared_ptr<FillCollector<YAO>>;
212 using YAO::operator =;
213
214 FillCollector() : YAO() { }
215
224 FillCollector(typename YAO::Ptr yao) : YAO(yao->binning()) {
225 YAO::setPath(yao->path());
226 }
227
232 int fill(typename YAO::FillType&& fillCoords,
233 const double weight=1.0, const double fraction=1.0) {
234 (void)fraction; // suppress unused variable warning
235 if (YODA::containsNan(fillCoords)) {
236 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
237 return -1;
238 }
239 // Could be that DbnN > number of binned axes, so should
240 // extract subset of bin coordinates to pinpoint bin
241 typename YAO::BinningT::EdgeTypesTuple binCoords{};
242 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
243 std::get<I>(binCoords) = std::get<I>(fillCoords);
244 };
245 MetaUtils::staticFor<sizeof...(AxisT)>(extractBinCoords);
246 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
247 return (int)YAO::_binning.globalIndexAt(binCoords);
248 }
249
251 void reset() noexcept { _fills.clear(); }
252
254 const Fills<YAO>& fills() const { return _fills; }
255
256 private:
257
258 Fills<YAO> _fills;
259
260 };
261
262 template <typename AxisT>
263 class FillCollector<YODA::BinnedDbn<1, AxisT>>
264 : public YODA::BinnedDbn<1, AxisT> {
265 public:
266
267 using YAO = YODA::BinnedDbn<1, AxisT>;
268 using Ptr = shared_ptr<FillCollector<YAO>>;
269 using YAO::operator =;
270
271 FillCollector() : YAO() { }
272
274 FillCollector(typename YAO::Ptr yao) : YAO(yao->binning()) {
275 YAO::setPath(yao->path());
276 }
277
282 int fill(typename YAO::FillType&& fillCoords,
283 const double weight=1.0, const double fraction=1.0) {
284 (void)fraction; // suppress unused variable warning
285 if (YODA::containsNan(fillCoords)) {
286 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
287 return -1;
288 }
289 // Could be that DbnN > number of binned axes, so should
290 // extract subset of bin coordinates to pinpoint bin
291 typename YAO::BinningT::EdgeTypesTuple binCoords{};
292 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
293 std::get<I>(binCoords) = std::get<I>(fillCoords);
294 };
295 MetaUtils::staticFor<1>(extractBinCoords);
296 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
297 return (int)YAO::_binning.globalIndexAt(binCoords);
298 }
299 //
300 int fill(const AxisT x, const double weight=1.0, const double fraction=1.0) {
301 return fill(typename YAO::FillType{x}, weight, fraction);
302 }
303
305 void reset() noexcept { _fills.clear(); }
306
308 const Fills<YAO>& fills() const { return _fills; }
309
310 private:
311
312 Fills<YAO> _fills;
313
314 };
315
316 template <typename AxisT1, typename AxisT2>
317 class FillCollector<YODA::BinnedDbn<2, AxisT1, AxisT2>>
318 : public YODA::BinnedDbn<2, AxisT1, AxisT2> {
319 public:
320
321 using YAO = YODA::BinnedDbn<2, AxisT1, AxisT2>;
322 using Ptr = shared_ptr<FillCollector<YAO>>;
323 using YAO::operator =;
324
325 FillCollector() : YAO() { }
326
328 FillCollector(typename YAO::Ptr yao) : YAO(yao->binning()) {
329 YAO::setPath(yao->path());
330 }
331
336 int fill(typename YAO::FillType&& fillCoords,
337 const double weight=1.0, const double fraction=1.0) {
338 (void)fraction; // suppress unused variable warning
339 if (YODA::containsNan(fillCoords)) {
340 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
341 return -1;
342 }
343 // Could be that DbnN > number of binned axes, so should
344 // extract subset of bin coordinates to pinpoint bin
345 typename YAO::BinningT::EdgeTypesTuple binCoords{};
346 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
347 std::get<I>(binCoords) = std::get<I>(fillCoords);
348 };
349 MetaUtils::staticFor<1>(extractBinCoords);
350 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
351 return (int)YAO::_binning.globalIndexAt(binCoords);
352 }
353 //
354 int fill(const AxisT1 x, const AxisT2 y, const double weight=1.0, const double fraction=1.0) {
355 return fill(typename YAO::FillType{x,y}, weight, fraction);
356 }
357
359 void reset() noexcept { _fills.clear(); }
360
362 const Fills<YAO>& fills() const { return _fills; }
363
364 private:
365
366 Fills<YAO> _fills;
367
368 };
369
370 template <typename AxisT1, typename AxisT2, typename AxisT3>
371 class FillCollector<YODA::BinnedDbn<3, AxisT1, AxisT2, AxisT3>>
372 : public YODA::BinnedDbn<3, AxisT1, AxisT2, AxisT3> {
373 public:
374
375 using YAO = YODA::BinnedDbn<3, AxisT1, AxisT2, AxisT3>;
376 using Ptr = shared_ptr<FillCollector<YAO>>;
377 using YAO::operator =;
378
379 FillCollector() : YAO() { }
380
382 FillCollector(typename YAO::Ptr yao) : YAO(yao->binning()) {
383 YAO::setPath(yao->path());
384 }
385
390 int fill(typename YAO::FillType&& fillCoords,
391 const double weight=1.0, const double fraction=1.0) {
392 (void)fraction; // suppress unused variable warning
393 if (YODA::containsNan(fillCoords)) {
394 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
395 return -1;
396 }
397 // Could be that DbnN > number of binned axes, so should
398 // extract subset of bin coordinates to pinpoint bin
399 typename YAO::BinningT::EdgeTypesTuple binCoords{};
400 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
401 std::get<I>(binCoords) = std::get<I>(fillCoords);
402 };
403 MetaUtils::staticFor<1>(extractBinCoords);
404 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
405 return (int)YAO::_binning.globalIndexAt(binCoords);
406 }
407 //
408 int fill(const AxisT1 x, const AxisT2 y, const AxisT3 z, const double weight=1.0, const double fraction=1.0) {
409 return fill(typename YAO::FillType{x,y,z}, weight, fraction);
410 }
411
413 void reset() noexcept { _fills.clear(); }
414
416 const Fills<YAO>& fills() const { return _fills; }
417
418 private:
419
420 Fills<YAO> _fills;
421
422 };
423
424 template <typename AxisT>
425 class FillCollector<YODA::BinnedDbn<2, AxisT>>
426 : public YODA::BinnedDbn<2, AxisT> {
427 public:
428
429 using YAO = YODA::BinnedDbn<2, AxisT>;
430 using Ptr = shared_ptr<FillCollector<YAO>>;
431 using YAO::operator =;
432
433 FillCollector() : YAO() { }
434
436 FillCollector(typename YAO::Ptr yao) : YAO(yao->binning()) {
437 YAO::setPath(yao->path());
438 }
439
444 int fill(typename YAO::FillType&& fillCoords,
445 const double weight=1.0, const double fraction=1.0) {
446 (void)fraction; // suppress unused variable warning
447 if (YODA::containsNan(fillCoords)) {
448 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
449 return -1;
450 }
451 // Could be that DbnN > number of binned axes, so should
452 // extract subset of bin coordinates to pinpoint bin
453 typename YAO::BinningT::EdgeTypesTuple binCoords{};
454 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
455 std::get<I>(binCoords) = std::get<I>(fillCoords);
456 };
457 MetaUtils::staticFor<1>(extractBinCoords);
458 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
459 return (int)YAO::_binning.globalIndexAt(binCoords);
460 }
461 //
462 int fill(const AxisT x, const double y, const double weight=1.0, const double fraction=1.0) {
463 return fill(typename YAO::FillType{x,y}, weight, fraction);
464 }
465
467 void reset() noexcept { _fills.clear(); }
468
470 const Fills<YAO>& fills() const { return _fills; }
471
472 private:
473
474 Fills<YAO> _fills;
475
476 };
477
478 template <typename AxisT1, typename AxisT2>
479 class FillCollector<YODA::BinnedDbn<3, AxisT1, AxisT2>>
480 : public YODA::BinnedDbn<3, AxisT1, AxisT2> {
481 public:
482
483 using YAO = YODA::BinnedDbn<3, AxisT1, AxisT2>;
484 using Ptr = shared_ptr<FillCollector<YAO>>;
485 using YAO::operator =;
486
487 FillCollector() : YAO() { }
488
490 FillCollector(typename YAO::Ptr yao) : YAO(yao->binning()) {
491 YAO::setPath(yao->path());
492 }
493
498 int fill(typename YAO::FillType&& fillCoords,
499 const double weight=1.0, const double fraction=1.0) {
500 (void)fraction; // suppress unused variable warning
501 if (YODA::containsNan(fillCoords)) {
502 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
503 return -1;
504 }
505 // Could be that DbnN > number of binned axes, so should
506 // extract subset of bin coordinates to pinpoint bin
507 typename YAO::BinningT::EdgeTypesTuple binCoords{};
508 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
509 std::get<I>(binCoords) = std::get<I>(fillCoords);
510 };
511 MetaUtils::staticFor<1>(extractBinCoords);
512 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
513 return (int)YAO::_binning.globalIndexAt(binCoords);
514 }
515 //
516 int fill(const AxisT1 x, const AxisT2 y, const double z, const double weight=1.0, const double fraction=1.0) {
517 return fill(typename YAO::FillType{x,y,z}, weight, fraction);
518 }
519
521 void reset() noexcept { _fills.clear(); }
522
524 const Fills<YAO>& fills() const { return _fills; }
525
526 private:
527
528 Fills<YAO> _fills;
529
530 };
531
532 template <typename AxisT1, typename AxisT2, typename AxisT3>
533 class FillCollector<YODA::BinnedDbn<4, AxisT1, AxisT2, AxisT3>>
534 : public YODA::BinnedDbn<4, AxisT1, AxisT2, AxisT3> {
535 public:
536
537 using YAO = YODA::BinnedDbn<4, AxisT1, AxisT2, AxisT3>;
538 using Ptr = shared_ptr<FillCollector<YAO>>;
539 using YAO::operator =;
540
541 FillCollector() : YAO() { }
542
544 FillCollector(typename YAO::Ptr yao) : YAO(yao->binning()) {
545 YAO::setPath(yao->path());
546 }
547
552 int fill(typename YAO::FillType&& fillCoords,
553 const double weight=1.0, const double fraction=1.0) {
554 (void)fraction; // suppress unused variable warning
555 if (YODA::containsNan(fillCoords)) {
556 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
557 return -1;
558 }
559 // Could be that DbnN > number of binned axes, so should
560 // extract subset of bin coordinates to pinpoint bin
561 typename YAO::BinningT::EdgeTypesTuple binCoords{};
562 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
563 std::get<I>(binCoords) = std::get<I>(fillCoords);
564 };
565 MetaUtils::staticFor<1>(extractBinCoords);
566 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
567 return (int)YAO::_binning.globalIndexAt(binCoords);
568 }
569 //
570 int fill(const AxisT1 x, const AxisT2 y, const AxisT3 z, const double zPlus, const double weight=1.0, const double fraction=1.0) {
571 return fill(typename YAO::FillType{x,y,z,zPlus}, weight, fraction);
572 }
573
575 void reset() noexcept { _fills.clear(); }
576
578 const Fills<YAO>& fills() const { return _fills; }
579
580 private:
581
582 Fills<YAO> _fills;
583
584 };
585
586
588 template<>
589 class FillCollector<YODA::Estimate0D> : public YODA::Estimate0D {
590 public:
591
592 using YAO = YODA::Estimate0D;
593 using Ptr = shared_ptr<FillCollector<YAO>>;
594 using YAO::operator =;
595
596 FillCollector() : YAO() { }
597
605 FillCollector(typename YAO::Ptr yao) : YAO(yao->path()) { }
606
607 };
608
610 template<typename ... AxisT>
611 class FillCollector<YODA::BinnedEstimate<AxisT...>>
612 : public YODA::BinnedEstimate<AxisT...> {
613 public:
614
615 using YAO = YODA::BinnedEstimate<AxisT...>;
616 using Ptr = shared_ptr<FillCollector<YAO>>;
617 using YAO::operator =;
618
619 FillCollector() : YAO() { }
620
628 FillCollector(typename YAO::Ptr yao) : YAO(yao->path()) { }
629
630 };
631
633 template <size_t N>
634 class FillCollector<YODA::ScatterND<N>> : public YODA::ScatterND<N> {
635 public:
636
637 using YAO = YODA::ScatterND<N>;
638 using Ptr = shared_ptr<FillCollector<YAO>>;
639 using YAO::operator =;
640
641 FillCollector() : YAO() { }
642
650 FillCollector(typename YAO::Ptr yao) : YAO(yao->path()) { }
651
652 };
653
655
657 namespace {
658
659 template<typename... Args>
660 double distance(const std::tuple<Args...>& a, const std::tuple<Args...>& b) {
661 double rtn = 0;
662 auto calculateDistance = [&](auto I) {
663 if constexpr (std::is_floating_point<std::tuple_element_t<I,
664 std::tuple<Args...>>>::value) {
665 rtn += Rivet::sqr(std::get<I>(a) - std::get<I>(b));
666 }
667 };
668 MetaUtils::staticFor<sizeof...(Args)>(calculateDistance);
669 return rtn;
670 }
671
674 template<typename T>
675 struct SubwindowType;
676 //
677 template<typename... Args>
678 struct SubwindowType<std::tuple<Args...>> {
679 using type = YODA::Binning<std::decay_t<decltype(std::declval<YODA::Axis<Args>>())>...>;
680 };
681
683 template<typename T>
684 struct WindowType;
685 //
686 template<typename... Args>
687 struct WindowType<std::tuple<Args...>> {
688 using type = std::tuple<std::decay_t<decltype(std::declval<vector<Args>>())>...>;
689 };
690
698 template<typename YAO>
699 vector<std::tuple<typename YAO::FillType, std::valarray<double>, double>>
700 mkFillWindows(const vector<typename FillCollector<YAO>::Ptr>& subevents, const std::string& path,
701 const vector<std::valarray<double>>& weights, const double fsmear=-1.0) {
702
703 // Placeholder for the return type: a tuple of {FillType, multi-weights, fill fraction}
704 vector<std::tuple<typename YAO::FillType, std::valarray<double>, double>> rtn;
705
706 using WindowT = typename WindowType<typename YAO::FillType>::type;
707 using SubwindowT = typename SubwindowType<typename YAO::FillType>::type;
708 SubwindowT subwindows;
709
710 // calculate the maximum number of fills
711 size_t fidx = 0;
712 const size_t nSubevents = subevents.size();
713 for (size_t sidx=0; sidx < nSubevents; ++sidx) {
714 const size_t nFills = subevents[sidx]->fills().size();
715 if (nFills == 0) continue;
716 fidx = std::max(fidx, nFills);
717 }
718
719 while (fidx--) { // loop over fills, back to front
720
721 WindowT windows;
722
723 auto constructWindows = [&](auto I) {
724
725 using FillAxisT = typename SubwindowT::template getAxisT<I>;
726 using isContinuous = typename SubwindowT::template is_CAxis<I>;
727 using EdgeT = typename FillAxisT::EdgeT;
728
729 if constexpr(!isContinuous::value) { // discrete axes don't need smearing
730 vector<EdgeT> edges; edges.resize(nSubevents);
731 for (const auto& subevt : subevents) {
732 if (fidx >= subevt->fills().size()) continue;
733 edges.push_back( std::get<I>(subevt->fills()[fidx].first) );
734 }
735 subwindows.template axis<I>() = FillAxisT(edges);
736 std::get<I>(windows) = std::move(edges);
737 return;
738 }
739 else { // continuous axes need windowing
740 vector<EdgeT>& edges = std::get<I>(windows);
741 edges.reserve(2*nSubevents);
742
743 if constexpr(I < YAO::BinningT::Dimension::value) {
744 // this fill axis is binned: window sizes will depend on bin width
745 const auto& axis = subevents[0]->binning().template axis<I>();
746 size_t over = 0, under = 0;
747 const EdgeT edgeMax = subevents[0]->template max<I>();
748 const EdgeT edgeMin = subevents[0]->template min<I>();
749 const size_t binLast = axis.numBins(); // index of last visible bin
750
751 for (const auto& subevt : subevents) {
752 if (fidx >= subevt->fills().size()) continue;
753 const EdgeT coord = std::get<I>(subevt->fills()[fidx].first);
754 size_t idx = axis.index(coord);
755 if (coord >= edgeMax) {
756 if (coord > edgeMax) ++over;
757 idx = binLast; // cut off at highest visible bin
758 }
759 else if (coord < edgeMin) {
760 ++under;
761 idx = 1; // cut off at lowest visible bin
762 }
763 // find index of closest neighbouring bin
764 size_t ibn = idx;
765 if (coord > axis.mid(idx)) {
766 if (idx != binLast) ++ibn;
767 }
768 else {
769 if (idx != 1) --ibn;
770 }
771
772 // construct rectangular windows of width = 2*delta
773 EdgeT lo, hi;
774 const EdgeT ibw = axis.width(idx) < axis.width(ibn)? idx : ibn;
775 if ( fsmear > 0.0 ) {
776 const EdgeT delta = 0.5*fsmear*axis.width(ibw);
777 lo = coord - delta;
778 hi = coord + delta;
779 }
780 else {
781 const EdgeT delta = 0.5*axis.width(ibw);
782 if (coord > edgeMax) {
783 lo = max(edgeMax, coord - delta);
784 hi = max(edgeMax + 2*delta, coord + delta);
785 }
786 else if (coord < edgeMin) {
787 lo = min(edgeMin - 2*delta, coord - delta);
788 hi = min(edgeMin, coord + delta);
789 }
790 else {
791 lo = axis.min(idx);
792 hi = axis.max(idx);
793 }
794 }
795 edges.push_back(lo);
796 edges.push_back(hi);
797 }
798 for (size_t i = 0; i < edges.size(); i+=2) {
799 const EdgeT wsize = edges[i+1] - edges[i];
800 if (over == nSubevents && edges[i] < edgeMax && edges[i+1] > edgeMax) {
801 edges[i] = edgeMax;
802 edges[i+1] = edgeMax + wsize;
803 }
804 else if (over == 0 && edges[i] < edgeMax && edges[i+1] > edgeMax) {
805 edges[i] = edgeMax - wsize;
806 edges[i+1] = edgeMax;
807 }
808 else if (under == nSubevents && edges[i] < edgeMin && edges[i+1] > edgeMin) {
809 edges[i] = edgeMin - wsize;
810 edges[i+1] = edgeMin;
811 }
812 else if (under == 0 && edges[i] < edgeMin && edges[i+1] > edgeMin) {
813 edges[i] = edgeMin;
814 edges[i+1] = edgeMin + wsize;
815 }
816 }
817 } // end of constexpr-check for binned axes
818 else {
819 // this fill axis is unbinned (e.g. in Profiles)
820 for (const auto& subevt : subevents) {
821 if (fidx >= subevt->fills().size()) continue;
826 const EdgeT coord = std::get<I>(subevt->fills()[fidx].first);
827 const EdgeT delta = 0.1*std::abs(coord);
828 edges.push_back(coord - delta);
829 edges.push_back(coord + delta);
830 }
831 }
832 // create CAxis with subwindows from the set of window edges
833 vector<EdgeT> subwindowEdges = edges;
834 std::sort(subwindowEdges.begin(), subwindowEdges.end());
835 subwindowEdges.erase( std::unique(subwindowEdges.begin(), subwindowEdges.end()), subwindowEdges.end() );
836 subwindows.template axis<I>() = FillAxisT(std::move(subwindowEdges));
837 } // end of if constexpr isContinuous
838 };
839 // execute for each fill dimension
840 MetaUtils::staticFor<YAO::FillDimension::value>(constructWindows);
841
842 // Subwindows are given by visible bins of the SubwindowT,
843 // so we can skip all under-/overflows
844 const vector<size_t> overflows = subwindows.calcOverflowBinsIndices();
845 const auto& itEnd = overflows.cend();
846 size_t nSubwindows = subwindows.numBins();
847 for (size_t i = 0; i < nSubwindows; ++i) {
848 if (std::find(overflows.cbegin(), itEnd, i) != itEnd) continue;
849
850 const auto coords = subwindows.edgeTuple(i);
851 const double subwindowArea = subwindows.dVol(i);
852 size_t nSubfills = 0;
853 double windowFrac = 0.;
854 std::valarray<double> sumw(0.0, weights[0].size());
855 for (size_t sidx=0, eidx=0; sidx < nSubevents; ++sidx) {
856 if (fidx >= subevents[sidx]->fills().size()) continue;
857 bool pass = true;
858 double windowArea = 1.0;
859 auto checkSubwindowOverlap = [&](auto I) {
860 using isContinuous = typename SubwindowT::template is_CAxis<I>;
861 using EdgeT = typename SubwindowT::template getAxisT<I>::EdgeT;
862 const EdgeT coord = std::get<I>(coords);
863 const vector<EdgeT>& edges = std::get<I>(windows);
864 if constexpr (isContinuous::value) {
865 pass &= (edges[2*eidx] <= coord && coord <= edges[2*eidx+1]);
866 windowArea *= edges[2*eidx+1] - edges[2*eidx];
867 }
868 else {
869 pass &= (coord == edges[eidx]);
870 }
871 };
872 MetaUtils::staticFor<YAO::FillDimension::value>(checkSubwindowOverlap);
873 if (pass) {
874 windowFrac = subwindowArea/windowArea;
875 sumw += subevents[sidx]->fills()[fidx].second * weights[sidx];
876 ++nSubfills;
877 }
878 ++eidx;
879 }
880 if (nSubfills) {
881 const double fillFrac = (double)nSubfills/(double)nSubevents;
882 rtn.emplace_back(coords, sumw/fillFrac, fillFrac*windowFrac); // normalise to a single fill
883 }
884 }
885 } // end of loop over fills
886 return rtn;
887 } // end of applyFillWindows
888
889 } // end of anonymous name space
890
891
894
903 public:
904
905 virtual ~MultiplexedAO() { }
906
908 using Inner = YODA::AnalysisObject;
909
911 virtual void newSubEvent() = 0;
912
914 virtual void collapseEventGroup(const vector<std::valarray<double>>& weight, const double nlowfrac=-1.0) = 0;
915
917 virtual void pushToFinal() = 0;
918
920 virtual YODA::AnalysisObjectPtr activeAO() const = 0;
921
923 virtual string basePath() const = 0;
924
926 virtual YODA::AnalysisObject* operator -> () = 0;
927
929 virtual YODA::AnalysisObject* operator -> () const = 0;
930
932 virtual const YODA::AnalysisObject& operator * () const = 0;
933
935 virtual void setActiveWeightIdx(size_t iWeight) = 0;
936
938 virtual void setActiveFinalWeightIdx(size_t iWeight) = 0;
939
941 virtual void unsetActiveWeight() = 0;
942
944 virtual void initBootstrap() = 0;
945
947 bool operator == (const MultiplexedAO& p) { return (this == &p); }
948
950 bool operator != (const MultiplexedAO& p) { return (this != &p); }
951
952 const vector<bool>& fillOutcomes() const { return _fillOutcomes; }
953
954 const vector<double>& fillFractions() const { return _fillFractions; }
955
956 protected:
957
958 vector<bool> _fillOutcomes;
959
960 vector<double> _fillFractions;
961
962 };
963
964
965
981 template<typename T>
982 class Multiplexer : public MultiplexedAO {
983
984 public:
985
986 friend class Analysis;
987 //friend class AnalysisHandler;
988
990 using Inner = T;
991 using MultiplexedAO::_fillOutcomes;
992 using MultiplexedAO::_fillFractions;
993
994 Multiplexer() = default;
995
996 Multiplexer(const vector<string>& weightNames, const T& p) {
997 _basePath = p.path();
998 _baseName = p.name();
999 for (const string& weightname : weightNames) {
1000 _persistent.push_back(make_shared<T>(p));
1001 _final.push_back(make_shared<T>(p));
1002
1003 typename T::Ptr obj = _persistent.back();
1004 obj->setPath("/RAW" + obj->path());
1005 typename T::Ptr final = _final.back();
1006 if (weightname != "") {
1007 obj->setPath(obj->path() + "[" + weightname + "]");
1008 final->setPath(final->path() + "[" + weightname + "]");
1009 }
1010 }
1011 }
1012
1013 ~Multiplexer() = default;
1014
1017 typename T::Ptr active() const {
1018 if ( !_active ) {
1019 #ifdef HAVE_BACKTRACE
1020 void* buffer[4];
1021 backtrace(buffer, 4);
1022 backtrace_symbols_fd(buffer, 4 , 1);
1023 #endif
1024 assert(false && "No active pointer set. Was this object booked in init()?");
1025 }
1026 return _active;
1027 }
1028
1029 template <typename U = T>
1030 auto binning() const -> std::enable_if_t<hasBinning<T>::value, const typename U::BinningT&> {
1031 return _persistent.back()->binning();
1032 }
1033
1035 string basePath() const { return _basePath; }
1036
1038 string baseName() const { return _baseName; }
1039
1040
1044 explicit operator bool() const { return static_cast<bool>(_active); }
1045
1049 bool operator ! () const { return !_active; }
1050
1051
1053 T* operator -> () { return active().get(); }
1054
1056 T* operator -> () const { return active().get(); }
1057
1059 T& operator * () { return *active(); }
1060
1062 const T& operator * () const { return *active(); }
1063
1064
1066 friend bool operator == (const Multiplexer& a, const Multiplexer& b){
1067 if (a._persistent.size() != b._persistent.size()) {
1068 return false;
1069 }
1070 // also test for binning compatibility
1071 for (size_t i = 0; i < a._persistent.size(); ++i) {
1072 if (a._persistent.at(i) != b._persistent.at(i)) {
1073 return false;
1074 }
1075 }
1076 return true;
1077 }
1078
1080 friend bool operator != (const Multiplexer& a, const Multiplexer& b) {
1081 return !(a == b);
1082 }
1083
1085 friend bool operator < (const Multiplexer a, const Multiplexer& b) {
1086 if (a._persistent.size() >= b._persistent.size()) {
1087 return false;
1088 }
1089 for (size_t i = 0; i < a._persistent.size(); ++i) {
1090 if (*(a._persistent.at(i)) >= *(b._persistent.at(i))) {
1091 return false;
1092 }
1093 }
1094 return true;
1095 }
1096
1097
1099
1102
1104 void setActiveWeightIdx(size_t iWeight) {
1105 _active = _persistent.at(iWeight);
1106 }
1107
1109 void setActiveFinalWeightIdx(size_t iWeight) {
1110 _active = _final.at(iWeight);
1111 }
1112
1114 void unsetActiveWeight() { _active.reset(); }
1115
1117 void reset() { active()->reset(); }
1118
1119
1126 _evgroup.emplace_back(new FillCollector<T>(_persistent[0]));
1127 _active = _evgroup.back();
1128 assert(_active);
1129 }
1130
1132 void collapseEventGroup(const vector<std::valarray<double>>& weights, const double nlowfrac=-1.0) {
1133
1135 if constexpr( isFillable<T>::value ) {
1136
1137 // Should have as many subevent fills as subevent weights
1138 assert( _evgroup.size() == weights.size() );
1139
1140 if (_evgroup.size() == 1) { // Have we had subevents at all?
1141 // ensure vector length matches size of multiplexed AO
1142 if (_fillOutcomes.empty()) initBootstrap();
1143 // reset fill positions
1144 std::fill(_fillOutcomes.begin(), _fillOutcomes.end(), false);
1145 std::fill(_fillFractions.begin(), _fillFractions.end(), 0.0);
1146
1147 // Simple replay of all collected fills:
1148 // each fill is inserted into every persistent AO
1149 for (auto f : _evgroup[0]->fills()) {
1150 int pos = -1;
1151 double frac = 0.0;
1152 for (size_t m = 0; m < _persistent.size(); ++m) { //< m is the variation index
1153 if (!m) frac = f.second;
1154 pos = _persistent[m]->fill( std::move(f.first), std::move(f.second) * weights[0][m] );
1155 }
1156 if (pos >= 0) {
1157 _fillOutcomes[pos] = true;
1158 _fillFractions[pos] += frac;
1159 }
1160 }
1161 }
1162 else {
1163 collapseSubevents(weights, nlowfrac);
1164 }
1165 }
1166
1167 _evgroup.clear();
1168 _active.reset();
1169 }
1170
1174 void collapseSubevents(const vector<std::valarray<double>>& weights, const double nlowfrac) {
1175 if (_evgroup.empty()) return;
1176 if constexpr( isFillable<T>::value ) {
1177 if constexpr (!std::is_same<T, YODA::Counter>::value ) { // binned objects
1178 for (auto&& fw : mkFillWindows<T>(_evgroup, _persistent[0]->path(), weights, nlowfrac)) {
1179 for ( size_t m = 0; m < _persistent.size(); ++m ) { // for each multiweight
1180 _persistent[m]->fill( typename T::FillType(std::move(std::get<0>(fw))), //< coords
1181 std::move(std::get<1>(fw)[m]), //< weight
1182 std::move(std::get<2>(fw)) ); //< fraction
1183 }
1184 } // end of loop over fill windows
1185 }
1186 else {
1187 for (size_t m = 0; m < _persistent.size(); ++m) { //< m is the variation index
1188 vector<double> sumfw{0.0}; // final fill weights (one per fill)
1189 for (size_t n = 0; n < _evgroup.size(); ++n) { //< n is the correlated sub-event index
1190 const auto& fills = _evgroup[n]->fills();
1191 // resize if this subevent has an
1192 // even larger number of fills
1193 if (fills.size() > sumfw.size()) {
1194 sumfw.resize(fills.size(), 0.0);
1195 }
1196 size_t fi = 0;
1197 for (const auto& f : fills) { // collapse sub-events and aggregate final fill weights
1198 sumfw[fi++] += f.second * weights[n][m]; // f.second is optional user-supplied scaling
1199 }
1200 }
1201 for (double fw : sumfw) { // fill persistent Counters
1202 _persistent[m]->fill(std::move(fw));
1203 }
1204 } // end of loop over weights
1205 }
1206 } // end of isFillable<T>::value
1207 }
1208
1212 for ( size_t m = 0; m < _persistent.size(); ++m ) { //< variation weight index
1213 _final.at(m)->clearAnnotations(); // in case this is a repeat call
1214 copyAO<T>(_persistent.at(m), _final.at(m));
1215 // Remove the /RAW prefix, if there is one, from the final copy
1216 if ( _final[m]->path().substr(0,4) == "/RAW" )
1217 _final[m]->setPath(_final[m]->path().substr(4));
1218 }
1219 }
1220
1223 const vector<typename T::Ptr>& persistent() const {
1224 return _persistent;
1225 }
1226
1228 typename T::Ptr persistent(const size_t iWeight) { return _persistent.at(iWeight); }
1229
1232 const vector<typename T::Ptr>& final() const {
1233 return _final;
1234 }
1235
1237 typename T::Ptr final(const size_t iWeight) { return _final.at(iWeight); }
1238
1240 YODA::AnalysisObjectPtr activeAO() const { return _active; }
1241
1244 if constexpr( isFillable<T>::value ) {
1245 size_t nPos = 1; // Counter only has a single fill position
1246 if constexpr (!std::is_same<T, YODA::Counter>::value ) { // binned objects
1247 nPos = _persistent.back()->numBins(true, true);
1248 }
1249 _fillOutcomes.resize(nPos);
1250 _fillFractions.resize(nPos);
1251 }
1252 }
1253
1255
1256 private:
1257
1260
1262 vector<typename T::Ptr> _persistent;
1263
1265 vector<typename T::Ptr> _final;
1266
1268 vector<typename FillCollector<T>::Ptr> _evgroup;
1269
1272 typename T::Ptr _active;
1273
1276 string _basePath;
1277
1280 string _baseName;
1281
1283
1284 };
1285
1286
1295 template <typename T>
1296 class MultiplexPtr {
1297
1298 public:
1299
1300 using value_type = T;
1301
1302 MultiplexPtr() = default;
1303
1304 MultiplexPtr(decltype(nullptr)) : _p(nullptr) { }
1305
1307 MultiplexPtr(const vector<string>& weightNames, const typename T::Inner& p)
1308 : _p( make_shared<T>(weightNames, p) ) { }
1309
1310 // Ensure a shared_ptr<T> can be instantiated from a shared_ptr<U>
1311 template <typename U, typename = decltype(shared_ptr<T>(shared_ptr<U>{}))>
1312 MultiplexPtr(const shared_ptr<U>& p) : _p(p) { }
1313
1314 // Ensure a shared_ptr<T> can be instantiated from a shared_ptr<U>
1315 template <typename U, typename = decltype(shared_ptr<T>(shared_ptr<U>{}))>
1316 MultiplexPtr(const MultiplexPtr<U>& p) : _p(p.get()) { }
1317
1320 if (_p == nullptr) {
1321 throw Error("Dereferencing null AnalysisObject pointer. Is there an unbooked histogram variable?");
1322 }
1323 return *_p;
1324 }
1325
1326 template <typename U = T>
1327 auto binning() const -> std::enable_if_t<hasBinning<typename T::Inner>::value, const typename U::Inner::BinningT&> {
1328 if (_p == nullptr) {
1329 throw Error("Dereferencing null AnalysisObject pointer. Is there an unbooked histogram variable?");
1330 }
1331 return _p->binning();
1332 }
1333
1334
1336 const T& operator -> () const {
1337 if (_p == nullptr) {
1338 throw Error("Dereferencing null AnalysisObject pointer. Is there an unbooked histogram variable?");
1339 }
1340 return *_p;
1341 }
1342
1344 typename T::Inner& operator * () { return **_p; }
1345 const typename T::Inner& operator * () const { return **_p; }
1346
1348 explicit operator bool() const { return _p && bool(*_p); }
1349
1351 bool operator ! () const { return !_p || !(*_p); }
1352
1354 bool operator == (const MultiplexPtr& other) const {
1355 return _p == other._p;
1356 }
1357
1359 bool operator != (const MultiplexPtr& other) const {
1360 return _p != other._p;
1361 }
1362
1364 bool operator < (const MultiplexPtr& other) const {
1365 return _p < other._p;
1366 }
1367
1369 bool operator > (const MultiplexPtr other) const {
1370 return _p > other._p;
1371 }
1372
1374 bool operator <= (const MultiplexPtr& other) const {
1375 return _p <= other._p;
1376 }
1377
1379 bool operator >= (const MultiplexPtr& other) const {
1380 return _p >= other._p;
1381 }
1382
1384 shared_ptr<T> get() const { return _p; }
1385
1386 private:
1387
1389 shared_ptr<T> _p;
1390
1391 };
1392
1394
1395
1402
1403 using MultiplexAOPtr = MultiplexPtr<MultiplexedAO>;
1404
1405 template<size_t DbnN, typename... AxisT>
1406 using BinnedDbnPtr = MultiplexPtr<Multiplexer<YODA::BinnedDbn<DbnN, AxisT...>>>;
1407
1408 template<typename... AxisT>
1409 using BinnedHistoPtr = BinnedDbnPtr<sizeof...(AxisT), AxisT...>;
1410
1411 template<typename... AxisT>
1412 using BinnedProfilePtr = BinnedDbnPtr<sizeof...(AxisT)+1, AxisT...>;
1413
1414 template<typename... AxisT>
1415 using BinnedEstimatePtr = MultiplexPtr<Multiplexer<YODA::BinnedEstimate<AxisT...>>>;
1416
1417 template<size_t N>
1418 using ScatterNDPtr = MultiplexPtr<Multiplexer<YODA::ScatterND<N>>>;
1419
1420 using CounterPtr = MultiplexPtr<Multiplexer<YODA::Counter>>;
1421 using Estimate0DPtr = MultiplexPtr<Multiplexer<YODA::Estimate0D>>;
1422 using Histo1DPtr = BinnedHistoPtr<double>;
1423 using Histo2DPtr = BinnedHistoPtr<double,double>;
1424 using Histo3DPtr = BinnedHistoPtr<double,double,double>;
1425 using Profile1DPtr = BinnedProfilePtr<double>;
1426 using Profile2DPtr = BinnedProfilePtr<double,double>;
1427 using Profile3DPtr = BinnedProfilePtr<double,double,double>;
1428 using Estimate1DPtr = BinnedEstimatePtr<double>;
1429 using Estimate2DPtr = BinnedEstimatePtr<double,double>;
1430 using Estimate3DPtr = BinnedEstimatePtr<double,double,double>;
1431 using Scatter1DPtr = ScatterNDPtr<1>;
1432 using Scatter2DPtr = ScatterNDPtr<2>;
1433 using Scatter3DPtr = ScatterNDPtr<3>;
1434
1435 using YODA::Counter;
1436 using YODA::Estimate0D;
1437 using YODA::Histo1D;
1438 using YODA::Histo2D;
1439 using YODA::Histo3D;
1440 using YODA::Profile1D;
1441 using YODA::Profile2D;
1442 using YODA::Profile3D;
1443 using YODA::Estimate1D;
1444 using YODA::Estimate2D;
1445 using YODA::Estimate3D;
1446 using YODA::Scatter1D;
1447 using YODA::Scatter2D;
1448 using YODA::Scatter3D;
1449 using YODA::Point1D;
1450 using YODA::Point2D;
1451 using YODA::Point3D;
1452
1454
1455
1458
1459 inline bool isTmpPath(const std::string& path, const bool tmp_only = false) {
1460 if (tmp_only) return path.find("/TMP/") != string::npos;
1461 return path.find("/TMP/") != string::npos || path.find("/_") != string::npos;
1462 }
1463
1466 map<string, YODA::AnalysisObjectPtr> getRefData(const string& papername);
1467
1469
1471 string getDatafilePath(const string& papername);
1472
1473
1476 template<typename T>
1477 struct ReferenceTraits { };
1478
1479 template<>
1480 struct ReferenceTraits<YODA::Counter> {
1481 using RefT = YODA::Estimate0D;
1482 };
1483
1484 template<>
1485 struct ReferenceTraits<YODA::Estimate0D> {
1486 using RefT = YODA::Estimate0D;
1487 };
1488
1489 template<typename... AxisT>
1490 struct ReferenceTraits<YODA::BinnedEstimate<AxisT...>> {
1491 using RefT = YODA::BinnedEstimate<AxisT...>;
1492 };
1493
1494 template<size_t DbnN, typename... AxisT>
1495 struct ReferenceTraits<YODA::BinnedDbn<DbnN, AxisT...>> {
1496 using RefT = YODA::ScatterND<sizeof...(AxisT)+1>;
1497 };
1498
1499 template<size_t N>
1500 struct ReferenceTraits<YODA::ScatterND<N>> {
1501 using RefT = YODA::ScatterND<N>;
1502 };
1503
1506 template <typename TPtr>
1507 inline bool bookingCompatible(TPtr a, TPtr b) {
1508 return *a == *b;
1509 }
1510 //
1511 inline bool bookingCompatible(CounterPtr, CounterPtr) {
1512 return true;
1513 }
1514 //
1515 inline bool bookingCompatible(YODA::CounterPtr, YODA::CounterPtr) {
1516 return true;
1517 }
1518 //
1519 inline bool bookingCompatible(Estimate0DPtr, Estimate0DPtr) {
1520 return true;
1521 }
1522 //
1523 inline bool bookingCompatible(YODA::Estimate0DPtr, YODA::Estimate0DPtr) {
1524 return true;
1525 }
1526 //
1527 template<size_t N>
1528 inline bool bookingCompatible(ScatterNDPtr<N> a, ScatterNDPtr<N> b) {
1529 return a->numPoints() == b->numPoints();
1530 }
1531 //
1532 template<size_t N>
1533 inline bool bookingCompatible(YODA::ScatterNDPtr<N> a, YODA::ScatterNDPtr<N> b) {
1534 return a->numPoints() == b->numPoints();
1535 }
1536
1537 inline bool beamInfoCompatible(YODA::AnalysisObjectPtr a, YODA::AnalysisObjectPtr b) {
1538 YODA::BinnedEstimatePtr<string> beamsA = std::dynamic_pointer_cast<YODA::BinnedEstimate<string>>(a);
1539 YODA::BinnedEstimatePtr<string> beamsB = std::dynamic_pointer_cast<YODA::BinnedEstimate<string>>(b);
1540 return beamsA && beamsB && (*beamsA == *beamsB) && beamsA->numBins() == 2 &&
1541 fuzzyEquals(beamsA->bin(1).val(), beamsB->bin(1).val()) &&
1542 fuzzyEquals(beamsA->bin(2).val(), beamsB->bin(2).val());
1543 }
1544
1546
1547
1548
1550 class AOPath {
1551 public:
1552
1554 AOPath(string fullpath)
1555 : _valid(false), _path(fullpath), _raw(false), _tmp(false), _ref(false) {
1556 _valid = init(fullpath);
1557 }
1558
1560 string path() const { return _path; }
1561
1563 string analysis() const { return _analysis; }
1564
1566 string analysisWithOptions() const { return _analysis + _optionstring; }
1567
1569 string name() const { return _name; }
1570
1572 string weight() const { return _weight; }
1573
1575 string weightComponent() const {
1576 if (_weight == "") return _weight;
1577 return "[" + _weight + "]";
1578 }
1579
1581 bool isRaw() const { return _raw; }
1582
1583 // Is this a temporary (filling) object?
1584 bool isTmp() const { return _tmp; }
1585
1587 bool isRef() const { return _ref; }
1588
1590 string optionString() const { return _optionstring; }
1591
1593 bool hasOptions() const { return !_options.empty(); }
1594
1596 void removeOption(string opt) { _options.erase(opt); fixOptionString(); }
1597
1599 void setOption(string opt, string val) { _options[opt] = val; fixOptionString(); }
1600
1602 bool hasOption(string opt) const { return _options.find(opt) != _options.end(); }
1603
1605 string getOption(string opt) const {
1606 auto it = _options.find(opt);
1607 if ( it != _options.end() ) return it->second;
1608 return "";
1609 }
1610
1612 void fixOptionString();
1613
1615 string mkPath() const;
1616 string setPath() { return _path = mkPath(); }
1617
1619 void debug() const;
1620
1622 bool operator<(const AOPath & other) const {
1623 return _path < other._path;
1624 }
1625
1627 bool valid() const { return _valid; };
1628 bool operator!() const { return !valid(); }
1629
1630 private:
1631
1633 bool init(string fullpath);
1634 bool chopweight(string & fullpath);
1635 bool chopoptions(string & anal);
1636
1637 bool _valid;
1638 string _path;
1639 string _analysis;
1640 string _optionstring;
1641 string _name;
1642 string _weight;
1643 bool _raw;
1644 bool _tmp;
1645 bool _ref;
1646 map<string,string> _options;
1647
1648 };
1649
1650}
1651
1652#endif
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:274
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:308
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:305
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:282
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:359
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:328
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:336
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:362
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:467
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:470
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:444
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:436
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:413
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:382
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:416
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:390
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:524
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:490
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:521
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:498
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:552
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:578
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:544
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:575
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:251
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:224
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:254
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:232
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:628
int fill(const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:185
void reset()
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:192
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:195
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:179
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:605
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:650
FillCollectors which are used to temporarily cache unaggregated fills until collapsed by the Multiple...
Definition RivetYODA.hh:158
T & operator->()
Goes right through to the active Multiplexer<YODA> object's members.
Definition RivetYODA.hh:1319
bool operator>(const MultiplexPtr other) const
Greater-than for ptr ordering.
Definition RivetYODA.hh:1369
shared_ptr< T > get() const
Get the internal shared ptr.
Definition RivetYODA.hh:1384
T::Inner & operator*()
The active YODA object.
Definition RivetYODA.hh:1344
bool operator<(const MultiplexPtr &other) const
Less-than for ptr ordering.
Definition RivetYODA.hh:1364
MultiplexPtr(const vector< string > &weightNames, const typename T::Inner &p)
Convenience constructor, pass through to the Multiplexer constructor.
Definition RivetYODA.hh:1307
bool operator!() const
Object invalidity check.
Definition RivetYODA.hh:1351
bool operator<=(const MultiplexPtr &other) const
Less-equals for ptr ordering.
Definition RivetYODA.hh:1374
bool operator!=(const MultiplexPtr &other) const
Object invalidity check.
Definition RivetYODA.hh:1359
bool operator==(const MultiplexPtr &other) const
Object validity check.
Definition RivetYODA.hh:1354
bool operator>=(const MultiplexPtr &other) const
Greater-equals for ptr ordering.
Definition RivetYODA.hh:1379
Multiplexer base class.
Definition RivetYODA.hh:902
virtual string basePath() const =0
The histogram path, without a variation suffix.
virtual YODA::AnalysisObject * operator->()=0
Access the active analysis object for function calls.
virtual void unsetActiveWeight()=0
Unset the active-object pointer.
bool operator==(const MultiplexedAO &p)
Test for equality.
Definition RivetYODA.hh:947
virtual void pushToFinal()=0
Sync the persistent histograms to the final collection.
virtual YODA::AnalysisObjectPtr activeAO() const =0
A shared pointer to the active YODA AO.
virtual void newSubEvent()=0
Add a new layer of subevent fill staging.
YODA::AnalysisObject Inner
The type being represented is a generic AO.
Definition RivetYODA.hh:908
bool operator!=(const MultiplexedAO &p)
Test for inequality.
Definition RivetYODA.hh:950
virtual const YODA::AnalysisObject & operator*() const =0
Access the active analysis object as a reference.
virtual void collapseEventGroup(const vector< std::valarray< double > > &weight, const double nlowfrac=-1.0)=0
Sync the fill proxies to the persistent histogram.
virtual void initBootstrap()=0
Set the size of the bootstrap vectors.
virtual void setActiveWeightIdx(size_t iWeight)=0
Set active object for analyze.
virtual void setActiveFinalWeightIdx(size_t iWeight)=0
Set active object for finalize.
Type-specific multiplexed YODA analysis object.
Definition RivetYODA.hh:982
void initBootstrap()
Helper method to resize aux vectors to AO size.
Definition RivetYODA.hh:1243
friend bool operator<(const Multiplexer a, const Multiplexer &b)
Less-than operator.
Definition RivetYODA.hh:1085
string baseName() const
Get the AO name of the object, without variation suffix.
Definition RivetYODA.hh:1038
T & operator*()
Forwarding dereference operator.
Definition RivetYODA.hh:1059
void newSubEvent()
Create a new FillCollector for the next sub-event.
Definition RivetYODA.hh:1125
void collapseEventGroup(const vector< std::valarray< double > > &weights, const double nlowfrac=-1.0)
Pushes the (possibly collapsed) fill(s) into the persistent objects.
Definition RivetYODA.hh:1132
void pushToFinal()
Definition RivetYODA.hh:1211
void reset()
Clear the active object pointer.
Definition RivetYODA.hh:1117
T::Ptr active() const
Definition RivetYODA.hh:1017
const vector< typename T::Ptr > & final() const
Definition RivetYODA.hh:1232
bool operator!() const
Definition RivetYODA.hh:1049
string basePath() const
Get the AO path of the object, without variation suffix.
Definition RivetYODA.hh:1035
friend bool operator!=(const Multiplexer &a, const Multiplexer &b)
Inequality operator.
Definition RivetYODA.hh:1080
friend bool operator==(const Multiplexer &a, const Multiplexer &b)
Equality operator.
Definition RivetYODA.hh:1066
void setActiveFinalWeightIdx(size_t iWeight)
Set the active-object pointer to point at a variation in the final set.
Definition RivetYODA.hh:1109
void unsetActiveWeight()
Unset the active-object pointer.
Definition RivetYODA.hh:1114
void collapseSubevents(const vector< std::valarray< double > > &weights, const double nlowfrac)
Definition RivetYODA.hh:1174
const vector< typename T::Ptr > & persistent() const
Definition RivetYODA.hh:1223
T::Ptr persistent(const size_t iWeight)
Direct access to the persistent object in weight stream iWeight.
Definition RivetYODA.hh:1228
void setActiveWeightIdx(size_t iWeight)
Set the active-object pointer to point at a variation in the persistent set.
Definition RivetYODA.hh:1104
T * operator->()
Forwarding dereference-call operator.
Definition RivetYODA.hh:1053
YODA::AnalysisObjectPtr activeAO() const
Get the currently active analysis object.
Definition RivetYODA.hh:1240
T Inner
Typedef for the YODA type being represented.
Definition RivetYODA.hh:990
STL class.
vector< Fill< T > > Fills
A collection of several Fill objects.
Definition RivetYODA.hh:143
double Weight
Typedef for weights.
Definition RivetYODA.hh:135
pair< typename T::FillType, Weight > Fill
A single fill is a (FillType, Weight) pair.
Definition RivetYODA.hh:139
map< string, YODA::AnalysisObjectPtr > getRefData(const string &papername)
bool bookingCompatible(TPtr a, TPtr b)
Definition RivetYODA.hh:1507
string getDatafilePath(const string &papername)
Get the file system path to the reference file for this paper.
double p(const ParticleBase &p)
Unbound function access to p.
Definition ParticleBaseUtils.hh:653
Definition MC_CENT_PPB_Projections.hh:10
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 >, signed_if_mixed_t< N1, N2 > > max(N1 a, N2 b)
Get the maximum of two numbers.
Definition MathUtils.hh:115
std::enable_if_t< std::is_arithmetic_v< NUM >, NUM > sqr(NUM a)
Named number-type squaring operation.
Definition MathUtils.hh:218
bool copyAO(YODA::AnalysisObjectPtr src, YODA::AnalysisObjectPtr dst, const double scale=1.0)
Definition RivetYODA.hh:64
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 >, signed_if_mixed_t< N1, N2 > > min(N1 a, N2 b)
Get the minimum of two numbers.
Definition MathUtils.hh:104
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 > &&(std::is_floating_point_v< N1 >||std::is_floating_point_v< N2 >), bool > fuzzyEquals(N1 a, N2 b, double tolerance=1e-5)
Compare two numbers for equality with a degree of fuzziness.
Definition MathUtils.hh:61
STL namespace.
Generic runtime Rivet error.
Definition Exceptions.hh:12
The type-specific handle that can perform type-specific operations for objects of type T.
Definition RivetYODA.hh:100