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/BinnedEstimate.h"
8#include "YODA/Counter.h"
9#include "YODA/Estimate0D.h"
10#include "YODA/Histo.h"
11#include "YODA/Profile.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) {
74 dstPtr->scaleW(scale);
75 }
76 return true;
77 }
78
79
81 struct TypeBaseHandle {
82
83 TypeBaseHandle() = default;
84
85 virtual ~TypeBaseHandle() { }
86
87 virtual bool copyAO(YODA::AnalysisObjectPtr src,
88 YODA::AnalysisObjectPtr dst,
89 const double scale = 1.0) const = 0;
90
91 virtual bool addAO(YODA::AnalysisObjectPtr src,
92 YODA::AnalysisObjectPtr& dst,
93 const double scale = 1.0) const = 0;
94 };
95
96
99 template <typename T>
100 struct TypeHandle : public TypeBaseHandle {
101
102 bool addAO(YODA::AnalysisObjectPtr src, YODA::AnalysisObjectPtr& dst, const double scale = 1.0) const {
103 if constexpr (isFillable<T>::value) {
104 std::shared_ptr<T> srcPtr = std::static_pointer_cast<T>(src);
105 srcPtr->scaleW(scale);
106 if (dst == nullptr) {
107 dst = src;
108 return true;
109 }
110 try {
111 *std::static_pointer_cast<T>(dst) += *srcPtr;
112 }
113 catch (YODA::BinningError&) {
114 return false;
115 }
116 return true;
117 }
118 else if (dst == nullptr) {
119 dst = src;
120 return true;
121 }
122 return false;
123 }
124
125 bool copyAO(YODA::AnalysisObjectPtr src, YODA::AnalysisObjectPtr dst, const double scale = 1.0) const {
126 return ::Rivet::copyAO<T>(src, dst, scale);
127 }
128 };
129
130
138
140 using Weight = double;
141
143 template <typename T>
144 using Fill = pair<typename T::FillType, Weight>;
145
147 template <typename T>
148 using Fills = vector<Fill<T>>;
149
150
161 template <typename T>
163
164
166 template <>
167 class FillCollector<YODA::Counter> : public YODA::Counter {
168 public:
169
170 using YAO = YODA::Counter;
171 using Ptr = shared_ptr<FillCollector<YAO>>;
172 using YAO::operator=;
173
174 FillCollector()
175 : YAO() { }
176
184 FillCollector(typename YAO::Ptr yao)
185 : YAO(yao->path()) { }
186
191 int fill(const double weight = 1.0, const double fraction = 1.0) {
192 (void)fraction; // suppress unused variable warning
193 _fills.insert(_fills.end(), {YAO::FillType(), weight});
194 return 0;
195 }
196
198 void reset() {
199 _fills.clear();
200 }
201
203 const Fills<YAO>& fills() const {
204 return _fills;
205 }
206
207 private:
208
209 Fills<YAO> _fills;
210 };
211
212
214 template <size_t DbnN, typename... AxisT>
215 class FillCollector<YODA::BinnedDbn<DbnN, AxisT...>> : public YODA::BinnedDbn<DbnN, AxisT...> {
216 public:
217
218 using YAO = YODA::BinnedDbn<DbnN, AxisT...>;
219 using Ptr = shared_ptr<FillCollector<YAO>>;
220 using YAO::operator=;
221
222 FillCollector()
223 : YAO() { }
224
233 FillCollector(typename YAO::Ptr yao)
234 : YAO(yao->binning()) {
235 YAO::setPath(yao->path());
236 }
237
242 int fill(typename YAO::FillType&& fillCoords, const double weight = 1.0, const double fraction = 1.0) {
243 (void)fraction; // suppress unused variable warning
244 if (YODA::containsNan(fillCoords)) {
245 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
246 return -1;
247 }
248 // Could be that DbnN > number of binned axes, so should
249 // extract subset of bin coordinates to pinpoint bin
250 typename YAO::BinningT::EdgeTypesTuple binCoords{};
251 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
252 std::get<I>(binCoords) = std::get<I>(fillCoords);
253 };
254 MetaUtils::staticFor<sizeof...(AxisT)>(extractBinCoords);
255 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
256 return (int)YAO::_binning.globalIndexAt(binCoords);
257 }
258
260 void reset() noexcept {
261 _fills.clear();
262 }
263
265 const Fills<YAO>& fills() const {
266 return _fills;
267 }
268
269 private:
270
271 Fills<YAO> _fills;
272 };
273
274 template <typename AxisT>
275 class FillCollector<YODA::BinnedDbn<1, AxisT>> : public YODA::BinnedDbn<1, AxisT> {
276 public:
277
278 using YAO = YODA::BinnedDbn<1, AxisT>;
279 using Ptr = shared_ptr<FillCollector<YAO>>;
280 using YAO::operator=;
281
282 FillCollector()
283 : YAO() { }
284
286 FillCollector(typename YAO::Ptr yao)
287 : YAO(yao->binning()) {
288 YAO::setPath(yao->path());
289 }
290
295 int fill(typename YAO::FillType&& fillCoords, const double weight = 1.0, const double fraction = 1.0) {
296 (void)fraction; // suppress unused variable warning
297 if (YODA::containsNan(fillCoords)) {
298 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
299 return -1;
300 }
301 // Could be that DbnN > number of binned axes, so should
302 // extract subset of bin coordinates to pinpoint bin
303 typename YAO::BinningT::EdgeTypesTuple binCoords{};
304 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
305 std::get<I>(binCoords) = std::get<I>(fillCoords);
306 };
307 MetaUtils::staticFor<1>(extractBinCoords);
308 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
309 return (int)YAO::_binning.globalIndexAt(binCoords);
310 }
311 //
312 int fill(const AxisT x, const double weight = 1.0, const double fraction = 1.0) {
313 return fill(typename YAO::FillType{x}, weight, fraction);
314 }
315
317 void reset() noexcept {
318 _fills.clear();
319 }
320
322 const Fills<YAO>& fills() const {
323 return _fills;
324 }
325
326 private:
327
328 Fills<YAO> _fills;
329 };
330
331 template <typename AxisT1, typename AxisT2>
332 class FillCollector<YODA::BinnedDbn<2, AxisT1, AxisT2>> : public YODA::BinnedDbn<2, AxisT1, AxisT2> {
333 public:
334
335 using YAO = YODA::BinnedDbn<2, AxisT1, AxisT2>;
336 using Ptr = shared_ptr<FillCollector<YAO>>;
337 using YAO::operator=;
338
339 FillCollector()
340 : YAO() { }
341
343 FillCollector(typename YAO::Ptr yao)
344 : YAO(yao->binning()) {
345 YAO::setPath(yao->path());
346 }
347
352 int fill(typename YAO::FillType&& fillCoords, const double weight = 1.0, const double fraction = 1.0) {
353 (void)fraction; // suppress unused variable warning
354 if (YODA::containsNan(fillCoords)) {
355 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
356 return -1;
357 }
358 // Could be that DbnN > number of binned axes, so should
359 // extract subset of bin coordinates to pinpoint bin
360 typename YAO::BinningT::EdgeTypesTuple binCoords{};
361 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
362 std::get<I>(binCoords) = std::get<I>(fillCoords);
363 };
364 MetaUtils::staticFor<1>(extractBinCoords);
365 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
366 return (int)YAO::_binning.globalIndexAt(binCoords);
367 }
368 //
369 int fill(const AxisT1 x, const AxisT2 y, const double weight = 1.0, const double fraction = 1.0) {
370 return fill(typename YAO::FillType{x, y}, weight, fraction);
371 }
372
374 void reset() noexcept {
375 _fills.clear();
376 }
377
379 const Fills<YAO>& fills() const {
380 return _fills;
381 }
382
383 private:
384
385 Fills<YAO> _fills;
386 };
387
388 template <typename AxisT1, typename AxisT2, typename AxisT3>
389 class FillCollector<YODA::BinnedDbn<3, AxisT1, AxisT2, AxisT3>>
390 : public YODA::BinnedDbn<3, AxisT1, AxisT2, AxisT3> {
391 public:
392
393 using YAO = YODA::BinnedDbn<3, AxisT1, AxisT2, AxisT3>;
394 using Ptr = shared_ptr<FillCollector<YAO>>;
395 using YAO::operator=;
396
397 FillCollector()
398 : YAO() { }
399
401 FillCollector(typename YAO::Ptr yao)
402 : YAO(yao->binning()) {
403 YAO::setPath(yao->path());
404 }
405
410 int fill(typename YAO::FillType&& fillCoords, const double weight = 1.0, const double fraction = 1.0) {
411 (void)fraction; // suppress unused variable warning
412 if (YODA::containsNan(fillCoords)) {
413 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
414 return -1;
415 }
416 // Could be that DbnN > number of binned axes, so should
417 // extract subset of bin coordinates to pinpoint bin
418 typename YAO::BinningT::EdgeTypesTuple binCoords{};
419 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
420 std::get<I>(binCoords) = std::get<I>(fillCoords);
421 };
422 MetaUtils::staticFor<1>(extractBinCoords);
423 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
424 return (int)YAO::_binning.globalIndexAt(binCoords);
425 }
426 //
427 int fill(const AxisT1 x,
428 const AxisT2 y,
429 const AxisT3 z,
430 const double weight = 1.0,
431 const double fraction = 1.0) {
432 return fill(typename YAO::FillType{x, y, z}, weight, fraction);
433 }
434
436 void reset() noexcept {
437 _fills.clear();
438 }
439
441 const Fills<YAO>& fills() const {
442 return _fills;
443 }
444
445 private:
446
447 Fills<YAO> _fills;
448 };
449
450 template <typename AxisT>
451 class FillCollector<YODA::BinnedDbn<2, AxisT>> : public YODA::BinnedDbn<2, AxisT> {
452 public:
453
454 using YAO = YODA::BinnedDbn<2, AxisT>;
455 using Ptr = shared_ptr<FillCollector<YAO>>;
456 using YAO::operator=;
457
458 FillCollector()
459 : YAO() { }
460
462 FillCollector(typename YAO::Ptr yao)
463 : YAO(yao->binning()) {
464 YAO::setPath(yao->path());
465 }
466
471 int fill(typename YAO::FillType&& fillCoords, const double weight = 1.0, const double fraction = 1.0) {
472 (void)fraction; // suppress unused variable warning
473 if (YODA::containsNan(fillCoords)) {
474 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
475 return -1;
476 }
477 // Could be that DbnN > number of binned axes, so should
478 // extract subset of bin coordinates to pinpoint bin
479 typename YAO::BinningT::EdgeTypesTuple binCoords{};
480 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
481 std::get<I>(binCoords) = std::get<I>(fillCoords);
482 };
483 MetaUtils::staticFor<1>(extractBinCoords);
484 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
485 return (int)YAO::_binning.globalIndexAt(binCoords);
486 }
487 //
488 int fill(const AxisT x, const double y, const double weight = 1.0, const double fraction = 1.0) {
489 return fill(typename YAO::FillType{x, y}, weight, fraction);
490 }
491
493 void reset() noexcept {
494 _fills.clear();
495 }
496
498 const Fills<YAO>& fills() const {
499 return _fills;
500 }
501
502 private:
503
504 Fills<YAO> _fills;
505 };
506
507 template <typename AxisT1, typename AxisT2>
508 class FillCollector<YODA::BinnedDbn<3, AxisT1, AxisT2>> : public YODA::BinnedDbn<3, AxisT1, AxisT2> {
509 public:
510
511 using YAO = YODA::BinnedDbn<3, AxisT1, AxisT2>;
512 using Ptr = shared_ptr<FillCollector<YAO>>;
513 using YAO::operator=;
514
515 FillCollector()
516 : YAO() { }
517
519 FillCollector(typename YAO::Ptr yao)
520 : YAO(yao->binning()) {
521 YAO::setPath(yao->path());
522 }
523
528 int fill(typename YAO::FillType&& fillCoords, const double weight = 1.0, const double fraction = 1.0) {
529 (void)fraction; // suppress unused variable warning
530 if (YODA::containsNan(fillCoords)) {
531 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
532 return -1;
533 }
534 // Could be that DbnN > number of binned axes, so should
535 // extract subset of bin coordinates to pinpoint bin
536 typename YAO::BinningT::EdgeTypesTuple binCoords{};
537 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
538 std::get<I>(binCoords) = std::get<I>(fillCoords);
539 };
540 MetaUtils::staticFor<1>(extractBinCoords);
541 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
542 return (int)YAO::_binning.globalIndexAt(binCoords);
543 }
544 //
545 int fill(const AxisT1 x,
546 const AxisT2 y,
547 const double z,
548 const double weight = 1.0,
549 const double fraction = 1.0) {
550 return fill(typename YAO::FillType{x, y, z}, weight, fraction);
551 }
552
554 void reset() noexcept {
555 _fills.clear();
556 }
557
559 const Fills<YAO>& fills() const {
560 return _fills;
561 }
562
563 private:
564
565 Fills<YAO> _fills;
566 };
567
568 template <typename AxisT1, typename AxisT2, typename AxisT3>
569 class FillCollector<YODA::BinnedDbn<4, AxisT1, AxisT2, AxisT3>>
570 : public YODA::BinnedDbn<4, AxisT1, AxisT2, AxisT3> {
571 public:
572
573 using YAO = YODA::BinnedDbn<4, AxisT1, AxisT2, AxisT3>;
574 using Ptr = shared_ptr<FillCollector<YAO>>;
575 using YAO::operator=;
576
577 FillCollector()
578 : YAO() { }
579
581 FillCollector(typename YAO::Ptr yao)
582 : YAO(yao->binning()) {
583 YAO::setPath(yao->path());
584 }
585
590 int fill(typename YAO::FillType&& fillCoords, const double weight = 1.0, const double fraction = 1.0) {
591 (void)fraction; // suppress unused variable warning
592 if (YODA::containsNan(fillCoords)) {
593 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
594 return -1;
595 }
596 // Could be that DbnN > number of binned axes, so should
597 // extract subset of bin coordinates to pinpoint bin
598 typename YAO::BinningT::EdgeTypesTuple binCoords{};
599 auto extractBinCoords = [&binCoords, &fillCoords](auto I) {
600 std::get<I>(binCoords) = std::get<I>(fillCoords);
601 };
602 MetaUtils::staticFor<1>(extractBinCoords);
603 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
604 return (int)YAO::_binning.globalIndexAt(binCoords);
605 }
606 //
607 int fill(const AxisT1 x,
608 const AxisT2 y,
609 const AxisT3 z,
610 const double zPlus,
611 const double weight = 1.0,
612 const double fraction = 1.0) {
613 return fill(typename YAO::FillType{x, y, z, zPlus}, weight, fraction);
614 }
615
617 void reset() noexcept {
618 _fills.clear();
619 }
620
622 const Fills<YAO>& fills() const {
623 return _fills;
624 }
625
626 private:
627
628 Fills<YAO> _fills;
629 };
630
631
633 template <>
634 class FillCollector<YODA::Estimate0D> : public YODA::Estimate0D {
635 public:
636
637 using YAO = YODA::Estimate0D;
638 using Ptr = shared_ptr<FillCollector<YAO>>;
639 using YAO::operator=;
640
641 FillCollector()
642 : YAO() { }
643
651 FillCollector(typename YAO::Ptr yao)
652 : YAO(yao->path()) { }
653 };
654
656 template <typename... AxisT>
657 class FillCollector<YODA::BinnedEstimate<AxisT...>> : public YODA::BinnedEstimate<AxisT...> {
658 public:
659
660 using YAO = YODA::BinnedEstimate<AxisT...>;
661 using Ptr = shared_ptr<FillCollector<YAO>>;
662 using YAO::operator=;
663
664 FillCollector()
665 : YAO() { }
666
674 FillCollector(typename YAO::Ptr yao)
675 : YAO(yao->path()) { }
676 };
677
679 template <size_t N>
680 class FillCollector<YODA::ScatterND<N>> : public YODA::ScatterND<N> {
681 public:
682
683 using YAO = YODA::ScatterND<N>;
684 using Ptr = shared_ptr<FillCollector<YAO>>;
685 using YAO::operator=;
686
687 FillCollector()
688 : YAO() { }
689
697 FillCollector(typename YAO::Ptr yao)
698 : YAO(yao->path()) { }
699 };
700
702
704 namespace {
705
706 template <typename... Args>
707 double distance(const std::tuple<Args...>& a, const std::tuple<Args...>& b) {
708 double rtn = 0;
709 auto calculateDistance = [&](auto I) {
710 if constexpr (std::is_floating_point<std::tuple_element_t<I, std::tuple<Args...>>>::value) {
711 rtn += Rivet::sqr(std::get<I>(a) - std::get<I>(b));
712 }
713 };
714 MetaUtils::staticFor<sizeof...(Args)>(calculateDistance);
715 return rtn;
716 }
717
720 template <typename T>
721 struct SubwindowType;
722 //
723 template <typename... Args>
724 struct SubwindowType<std::tuple<Args...>> {
725 using type = YODA::Binning<std::decay_t<decltype(std::declval<YODA::Axis<Args>>())>...>;
726 };
727
729 template <typename T>
730 struct WindowType;
731 //
732 template <typename... Args>
733 struct WindowType<std::tuple<Args...>> {
734 using type = std::tuple<std::decay_t<decltype(std::declval<vector<Args>>())>...>;
735 };
736
744 template <typename YAO>
745 vector<std::tuple<typename YAO::FillType, std::valarray<double>, double>> mkFillWindows(
746 const vector<typename FillCollector<YAO>::Ptr>& subevents,
747 const std::string& path,
748 const vector<std::valarray<double>>& weights,
749 const double fsmear = -1.0) {
750
751 // Placeholder for the return type: a tuple of {FillType, multi-weights, fill fraction}
752 vector<std::tuple<typename YAO::FillType, std::valarray<double>, double>> rtn;
753
754 using WindowT = typename WindowType<typename YAO::FillType>::type;
755 using SubwindowT = typename SubwindowType<typename YAO::FillType>::type;
756 SubwindowT subwindows;
757
758 // calculate the maximum number of fills
759 size_t fidx = 0;
760 const size_t nSubevents = subevents.size();
761 for (size_t sidx = 0; sidx < nSubevents; ++sidx) {
762 const size_t nFills = subevents[sidx]->fills().size();
763 if (nFills == 0) continue;
764 fidx = std::max(fidx, nFills);
765 }
766
767 while (fidx--) { // loop over fills, back to front
768
769 WindowT windows;
770
771 auto constructWindows = [&](auto I) {
772 using FillAxisT = typename SubwindowT::template getAxisT<I>;
773 using isContinuous = typename SubwindowT::template is_CAxis<I>;
774 using EdgeT = typename FillAxisT::EdgeT;
775
776 if constexpr (!isContinuous::value) { // discrete axes don't need smearing
777 vector<EdgeT> edges;
778 edges.resize(nSubevents);
779 for (const auto& subevt : subevents) {
780 if (fidx >= subevt->fills().size()) continue;
781 edges.push_back(std::get<I>(subevt->fills()[fidx].first));
782 }
783 subwindows.template axis<I>() = FillAxisT(edges);
784 std::get<I>(windows) = std::move(edges);
785 return;
786 }
787 else { // continuous axes need windowing
788 vector<EdgeT>& edges = std::get<I>(windows);
789 edges.reserve(2 * nSubevents);
790
791 if constexpr (I < YAO::BinningT::Dimension::value) {
792 // this fill axis is binned: window sizes will depend on bin width
793 const auto& axis = subevents[0]->binning().template axis<I>();
794 size_t over = 0, under = 0;
795 const EdgeT edgeMax = subevents[0]->template max<I>();
796 const EdgeT edgeMin = subevents[0]->template min<I>();
797 const size_t binLast = axis.numBins(); // index of last visible bin
798
799 for (const auto& subevt : subevents) {
800 if (fidx >= subevt->fills().size()) continue;
801 const EdgeT coord = std::get<I>(subevt->fills()[fidx].first);
802 size_t idx = axis.index(coord);
803 if (coord >= edgeMax) {
804 if (coord > edgeMax) ++over;
805 idx = binLast; // cut off at highest visible bin
806 }
807 else if (coord < edgeMin) {
808 ++under;
809 idx = 1; // cut off at lowest visible bin
810 }
811 // find index of closest neighbouring bin
812 size_t ibn = idx;
813 if (coord > axis.mid(idx)) {
814 if (idx != binLast) ++ibn;
815 }
816 else {
817 if (idx != 1) --ibn;
818 }
819
820 // construct rectangular windows of width = 2*delta
821 EdgeT lo, hi;
822 const EdgeT ibw = axis.width(idx) < axis.width(ibn) ? idx : ibn;
823 if (fsmear > 0.0) {
824 const EdgeT delta = 0.5 * fsmear * axis.width(ibw);
825 lo = coord - delta;
826 hi = coord + delta;
827 }
828 else {
829 const EdgeT delta = 0.5 * axis.width(ibw);
830 if (coord > edgeMax) {
831 lo = max(edgeMax, coord - delta);
832 hi = max(edgeMax + 2 * delta, coord + delta);
833 }
834 else if (coord < edgeMin) {
835 lo = min(edgeMin - 2 * delta, coord - delta);
836 hi = min(edgeMin, coord + delta);
837 }
838 else {
839 lo = axis.min(idx);
840 hi = axis.max(idx);
841 }
842 }
843 edges.push_back(lo);
844 edges.push_back(hi);
845 }
846 for (size_t i = 0; i < edges.size(); i += 2) {
847 const EdgeT wsize = edges[i + 1] - edges[i];
848 if (over == nSubevents && edges[i] < edgeMax && edges[i + 1] > edgeMax) {
849 edges[i] = edgeMax;
850 edges[i + 1] = edgeMax + wsize;
851 }
852 else if (over == 0 && edges[i] < edgeMax && edges[i + 1] > edgeMax) {
853 edges[i] = edgeMax - wsize;
854 edges[i + 1] = edgeMax;
855 }
856 else if (under == nSubevents && edges[i] < edgeMin && edges[i + 1] > edgeMin) {
857 edges[i] = edgeMin - wsize;
858 edges[i + 1] = edgeMin;
859 }
860 else if (under == 0 && edges[i] < edgeMin && edges[i + 1] > edgeMin) {
861 edges[i] = edgeMin;
862 edges[i + 1] = edgeMin + wsize;
863 }
864 }
865 } // end of constexpr-check for binned axes
866 else {
867 // this fill axis is unbinned (e.g. in Profiles)
868 for (const auto& subevt : subevents) {
869 if (fidx >= subevt->fills().size()) continue;
874 const EdgeT coord = std::get<I>(subevt->fills()[fidx].first);
875 const EdgeT delta = 0.1 * std::abs(coord);
876 edges.push_back(coord - delta);
877 edges.push_back(coord + delta);
878 }
879 }
880 // create CAxis with subwindows from the set of window edges
881 vector<EdgeT> subwindowEdges = edges;
882 std::sort(subwindowEdges.begin(), subwindowEdges.end());
883 subwindowEdges.erase(std::unique(subwindowEdges.begin(), subwindowEdges.end()),
884 subwindowEdges.end());
885 subwindows.template axis<I>() = FillAxisT(std::move(subwindowEdges));
886 } // end of if constexpr isContinuous
887 };
888 // execute for each fill dimension
889 MetaUtils::staticFor<YAO::FillDimension::value>(constructWindows);
890
891 // Subwindows are given by visible bins of the SubwindowT,
892 // so we can skip all under-/overflows
893 const vector<size_t> overflows = subwindows.calcOverflowBinsIndices();
894 const auto& itEnd = overflows.cend();
895 size_t nSubwindows = subwindows.numBins();
896 for (size_t i = 0; i < nSubwindows; ++i) {
897 if (std::find(overflows.cbegin(), itEnd, i) != itEnd) continue;
898
899 const auto coords = subwindows.edgeTuple(i);
900 const double subwindowArea = subwindows.dVol(i);
901 size_t nSubfills = 0;
902 double windowFrac = 0.;
903 std::valarray<double> sumw(0.0, weights[0].size());
904 for (size_t sidx = 0, eidx = 0; sidx < nSubevents; ++sidx) {
905 if (fidx >= subevents[sidx]->fills().size()) continue;
906 bool pass = true;
907 double windowArea = 1.0;
908 auto checkSubwindowOverlap = [&](auto I) {
909 using isContinuous = typename SubwindowT::template is_CAxis<I>;
910 using EdgeT = typename SubwindowT::template getAxisT<I>::EdgeT;
911 const EdgeT coord = std::get<I>(coords);
912 const vector<EdgeT>& edges = std::get<I>(windows);
913 if constexpr (isContinuous::value) {
914 pass &= (edges[2 * eidx] <= coord && coord <= edges[2 * eidx + 1]);
915 windowArea *= edges[2 * eidx + 1] - edges[2 * eidx];
916 }
917 else {
918 pass &= (coord == edges[eidx]);
919 }
920 };
921 MetaUtils::staticFor<YAO::FillDimension::value>(checkSubwindowOverlap);
922 if (pass) {
923 windowFrac = subwindowArea / windowArea;
924 sumw += subevents[sidx]->fills()[fidx].second * weights[sidx];
925 ++nSubfills;
926 }
927 ++eidx;
928 }
929 if (nSubfills) {
930 const double fillFrac = (double)nSubfills / (double)nSubevents;
931 rtn.emplace_back(coords, sumw / fillFrac, fillFrac * windowFrac); // normalise to a single fill
932 }
933 }
934 } // end of loop over fills
935 return rtn;
936 } // end of applyFillWindows
937
938 } // end of anonymous name space
939
940
943
952 public:
953
954 virtual ~MultiplexedAO() { }
955
957 using Inner = YODA::AnalysisObject;
958
960 virtual void newSubEvent() = 0;
961
963 virtual void collapseEventGroup(const vector<std::valarray<double>>& weight,
964 const double nlowfrac = -1.0) = 0;
965
967 virtual void pushToFinal() = 0;
968
970 virtual YODA::AnalysisObjectPtr activeAO() const = 0;
971
973 virtual string basePath() const = 0;
974
976 virtual YODA::AnalysisObject* operator->() = 0;
977
979 virtual YODA::AnalysisObject* operator->() const = 0;
980
982 virtual const YODA::AnalysisObject& operator*() const = 0;
983
985 virtual void setActiveWeightIdx(size_t iWeight) = 0;
986
988 virtual void setActiveFinalWeightIdx(size_t iWeight) = 0;
989
991 virtual void unsetActiveWeight() = 0;
992
994 virtual void initBootstrap() = 0;
995
998 return (this == &p);
999 }
1000
1003 return (this != &p);
1004 }
1005
1006 const vector<bool>& fillOutcomes() const {
1007 return _fillOutcomes;
1008 }
1009
1010 const vector<double>& fillFractions() const {
1011 return _fillFractions;
1012 }
1013
1014 protected:
1015
1016 vector<bool> _fillOutcomes;
1017
1018 vector<double> _fillFractions;
1019 };
1020
1021
1037 template <typename T>
1038 class Multiplexer : public MultiplexedAO {
1039
1040 public:
1041
1042 friend class Analysis;
1043 //friend class AnalysisHandler;
1044
1046 using Inner = T;
1047 using MultiplexedAO::_fillFractions;
1048 using MultiplexedAO::_fillOutcomes;
1049
1050 Multiplexer() = default;
1051
1052 Multiplexer(const vector<string>& weightNames, const T& p) {
1053 _basePath = p.path();
1054 _baseName = p.name();
1055 for (const string& weightname : weightNames) {
1056 _persistent.push_back(make_shared<T>(p));
1057 _final.push_back(make_shared<T>(p));
1058
1059 typename T::Ptr obj = _persistent.back();
1060 obj->setPath("/RAW" + obj->path());
1061 typename T::Ptr final = _final.back();
1062 if (weightname != "") {
1063 obj->setPath(obj->path() + "[" + weightname + "]");
1064 final->setPath(final->path() + "[" + weightname + "]");
1065 }
1066 }
1067 }
1068
1069 ~Multiplexer() = default;
1070
1073 typename T::Ptr active() const {
1074 if (!_active) {
1075#ifdef HAVE_BACKTRACE
1076 void* buffer[4];
1077 backtrace(buffer, 4);
1078 backtrace_symbols_fd(buffer, 4, 1);
1079#endif
1080 assert(false && "No active pointer set. Was this object booked in init()?");
1081 }
1082 return _active;
1083 }
1084
1085 template <typename U = T>
1086 auto binning() const -> std::enable_if_t<hasBinning<T>::value, const typename U::BinningT&> {
1087 return _persistent.back()->binning();
1088 }
1089
1091 string basePath() const {
1092 return _basePath;
1093 }
1094
1096 string baseName() const {
1097 return _baseName;
1098 }
1099
1100
1104 explicit operator bool() const {
1105 return static_cast<bool>(_active);
1106 }
1107
1111 bool operator!() const {
1112 return !_active;
1113 }
1114
1115
1118 return active().get();
1119 }
1120
1122 T* operator->() const {
1123 return active().get();
1124 }
1125
1128 return *active();
1129 }
1130
1132 const T& operator*() const {
1133 return *active();
1134 }
1135
1136
1138 friend bool operator==(const Multiplexer& a, const Multiplexer& b) {
1139 if (a._persistent.size() != b._persistent.size()) {
1140 return false;
1141 }
1142 // also test for binning compatibility
1143 for (size_t i = 0; i < a._persistent.size(); ++i) {
1144 if (a._persistent.at(i) != b._persistent.at(i)) {
1145 return false;
1146 }
1147 }
1148 return true;
1149 }
1150
1152 friend bool operator!=(const Multiplexer& a, const Multiplexer& b) {
1153 return !(a == b);
1154 }
1155
1157 friend bool operator<(const Multiplexer a, const Multiplexer& b) {
1158 if (a._persistent.size() >= b._persistent.size()) {
1159 return false;
1160 }
1161 for (size_t i = 0; i < a._persistent.size(); ++i) {
1162 if (*(a._persistent.at(i)) >= *(b._persistent.at(i))) {
1163 return false;
1164 }
1165 }
1166 return true;
1167 }
1168
1169
1171
1174
1176 void setActiveWeightIdx(size_t iWeight) {
1177 _active = _persistent.at(iWeight);
1178 }
1179
1181 void setActiveFinalWeightIdx(size_t iWeight) {
1182 _active = _final.at(iWeight);
1183 }
1184
1187 _active.reset();
1188 }
1189
1191 void reset() {
1192 active()->reset();
1193 }
1194
1195
1202 _evgroup.emplace_back(new FillCollector<T>(_persistent[0]));
1203 _active = _evgroup.back();
1204 assert(_active);
1205 }
1206
1208 void collapseEventGroup(const vector<std::valarray<double>>& weights, const double nlowfrac = -1.0) {
1209
1211 if constexpr (isFillable<T>::value) {
1212
1213 // Should have as many subevent fills as subevent weights
1214 assert(_evgroup.size() == weights.size());
1215
1216 if (_evgroup.size() == 1) { // Have we had subevents at all?
1217 // ensure vector length matches size of multiplexed AO
1218 if (_fillOutcomes.empty()) initBootstrap();
1219 // reset fill positions
1220 std::fill(_fillOutcomes.begin(), _fillOutcomes.end(), false);
1221 std::fill(_fillFractions.begin(), _fillFractions.end(), 0.0);
1222
1223 // Simple replay of all collected fills:
1224 // each fill is inserted into every persistent AO
1225 for (auto f : _evgroup[0]->fills()) {
1226 int pos = -1;
1227 double frac = 0.0;
1228 for (size_t m = 0; m < _persistent.size(); ++m) { //< m is the variation index
1229 if (!m) frac = f.second;
1230 pos = _persistent[m]->fill(std::move(f.first), std::move(f.second) * weights[0][m]);
1231 }
1232 if (pos >= 0) {
1233 _fillOutcomes[pos] = true;
1234 _fillFractions[pos] += frac;
1235 }
1236 }
1237 }
1238 else {
1239 collapseSubevents(weights, nlowfrac);
1240 }
1241 }
1242
1243 _evgroup.clear();
1244 _active.reset();
1245 }
1246
1250 void collapseSubevents(const vector<std::valarray<double>>& weights, const double nlowfrac) {
1251 if (_evgroup.empty()) return;
1252 if constexpr (isFillable<T>::value) {
1253 if constexpr (!std::is_same<T, YODA::Counter>::value) { // binned objects
1254 for (auto&& fw : mkFillWindows<T>(_evgroup, _persistent[0]->path(), weights, nlowfrac)) {
1255 for (size_t m = 0; m < _persistent.size(); ++m) { // for each multiweight
1256 _persistent[m]->fill(typename T::FillType(std::move(std::get<0>(fw))), //< coords
1257 std::move(std::get<1>(fw)[m]), //< weight
1258 std::move(std::get<2>(fw))); //< fraction
1259 }
1260 } // end of loop over fill windows
1261 }
1262 else {
1263 for (size_t m = 0; m < _persistent.size(); ++m) { //< m is the variation index
1264 vector<double> sumfw{0.0}; // final fill weights (one per fill)
1265 for (size_t n = 0; n < _evgroup.size(); ++n) { //< n is the correlated sub-event index
1266 const auto& fills = _evgroup[n]->fills();
1267 // resize if this subevent has an
1268 // even larger number of fills
1269 if (fills.size() > sumfw.size()) {
1270 sumfw.resize(fills.size(), 0.0);
1271 }
1272 size_t fi = 0;
1273 for (const auto& f : fills) { // collapse sub-events and aggregate final fill weights
1274 sumfw[fi++] += f.second * weights[n][m]; // f.second is optional user-supplied scaling
1275 }
1276 }
1277 for (double fw : sumfw) { // fill persistent Counters
1278 _persistent[m]->fill(std::move(fw));
1279 }
1280 } // end of loop over weights
1281 }
1282 } // end of isFillable<T>::value
1283 }
1284
1288 for (size_t m = 0; m < _persistent.size(); ++m) { //< variation weight index
1289 _final.at(m)->clearAnnotations(); // in case this is a repeat call
1290 copyAO<T>(_persistent.at(m), _final.at(m));
1291 // Remove the /RAW prefix, if there is one, from the final copy
1292 if (_final[m]->path().substr(0, 4) == "/RAW") _final[m]->setPath(_final[m]->path().substr(4));
1293 }
1294 }
1295
1298 const vector<typename T::Ptr>& persistent() const {
1299 return _persistent;
1300 }
1301
1303 typename T::Ptr persistent(const size_t iWeight) {
1304 return _persistent.at(iWeight);
1305 }
1306
1309 const vector<typename T::Ptr>& final() const {
1310 return _final;
1311 }
1312
1314 typename T::Ptr final(const size_t iWeight) {
1315 return _final.at(iWeight);
1316 }
1317
1319 YODA::AnalysisObjectPtr activeAO() const {
1320 return _active;
1321 }
1322
1325 if constexpr (isFillable<T>::value) {
1326 size_t nPos = 1; // Counter only has a single fill position
1327 if constexpr (!std::is_same<T, YODA::Counter>::value) { // binned objects
1328 nPos = _persistent.back()->numBins(true, true);
1329 }
1330 _fillOutcomes.resize(nPos);
1331 _fillFractions.resize(nPos);
1332 }
1333 }
1334
1336
1337 private:
1338
1341
1343 vector<typename T::Ptr> _persistent;
1344
1346 vector<typename T::Ptr> _final;
1347
1349 vector<typename FillCollector<T>::Ptr> _evgroup;
1350
1353 typename T::Ptr _active;
1354
1357 string _basePath;
1358
1361 string _baseName;
1362
1364 };
1365
1366
1375 template <typename T>
1376 class MultiplexPtr {
1377
1378 public:
1379
1380 using value_type = T;
1381
1382 MultiplexPtr() = default;
1383
1384 MultiplexPtr(decltype(nullptr))
1385 : _p(nullptr) { }
1386
1388 MultiplexPtr(const vector<string>& weightNames, const typename T::Inner& p)
1389 : _p(make_shared<T>(weightNames, p)) { }
1390
1391 // Ensure a shared_ptr<T> can be instantiated from a shared_ptr<U>
1392 template <typename U, typename = decltype(shared_ptr<T>(shared_ptr<U>{}))>
1393 MultiplexPtr(const shared_ptr<U>& p)
1394 : _p(p) { }
1395
1396 // Ensure a shared_ptr<T> can be instantiated from a shared_ptr<U>
1397 template <typename U, typename = decltype(shared_ptr<T>(shared_ptr<U>{}))>
1398 MultiplexPtr(const MultiplexPtr<U>& p)
1399 : _p(p.get()) { }
1400
1403 if (_p == nullptr) {
1404 throw Error("Dereferencing null AnalysisObject pointer. Is there an unbooked histogram variable?");
1405 }
1406 return *_p;
1407 }
1408
1409 template <typename U = T>
1410 auto binning() const
1411 -> std::enable_if_t<hasBinning<typename T::Inner>::value, const typename U::Inner::BinningT&> {
1412 if (_p == nullptr) {
1413 throw Error("Dereferencing null AnalysisObject pointer. Is there an unbooked histogram variable?");
1414 }
1415 return _p->binning();
1416 }
1417
1418
1420 const T& operator->() const {
1421 if (_p == nullptr) {
1422 throw Error("Dereferencing null AnalysisObject pointer. Is there an unbooked histogram variable?");
1423 }
1424 return *_p;
1425 }
1426
1428 typename T::Inner& operator*() {
1429 return **_p;
1430 }
1431 const typename T::Inner& operator*() const {
1432 return **_p;
1433 }
1434
1436 explicit operator bool() const {
1437 return _p && bool(*_p);
1438 }
1439
1441 bool operator!() const {
1442 return !_p || !(*_p);
1443 }
1444
1446 bool operator==(const MultiplexPtr& other) const {
1447 return _p == other._p;
1448 }
1449
1451 bool operator!=(const MultiplexPtr& other) const {
1452 return _p != other._p;
1453 }
1454
1456 bool operator<(const MultiplexPtr& other) const {
1457 return _p < other._p;
1458 }
1459
1461 bool operator>(const MultiplexPtr other) const {
1462 return _p > other._p;
1463 }
1464
1466 bool operator<=(const MultiplexPtr& other) const {
1467 return _p <= other._p;
1468 }
1469
1471 bool operator>=(const MultiplexPtr& other) const {
1472 return _p >= other._p;
1473 }
1474
1476 shared_ptr<T> get() const {
1477 return _p;
1478 }
1479
1480 private:
1481
1483 shared_ptr<T> _p;
1484 };
1485
1487
1488
1495
1496 using MultiplexAOPtr = MultiplexPtr<MultiplexedAO>;
1497
1498 template <size_t DbnN, typename... AxisT>
1499 using BinnedDbnPtr = MultiplexPtr<Multiplexer<YODA::BinnedDbn<DbnN, AxisT...>>>;
1500
1501 template <typename... AxisT>
1502 using BinnedHistoPtr = BinnedDbnPtr<sizeof...(AxisT), AxisT...>;
1503
1504 template <typename... AxisT>
1505 using BinnedProfilePtr = BinnedDbnPtr<sizeof...(AxisT) + 1, AxisT...>;
1506
1507 template <typename... AxisT>
1508 using BinnedEstimatePtr = MultiplexPtr<Multiplexer<YODA::BinnedEstimate<AxisT...>>>;
1509
1510 template <size_t N>
1511 using ScatterNDPtr = MultiplexPtr<Multiplexer<YODA::ScatterND<N>>>;
1512
1513 using CounterPtr = MultiplexPtr<Multiplexer<YODA::Counter>>;
1514 using Estimate0DPtr = MultiplexPtr<Multiplexer<YODA::Estimate0D>>;
1515 using Histo1DPtr = BinnedHistoPtr<double>;
1516 using Histo2DPtr = BinnedHistoPtr<double, double>;
1517 using Histo3DPtr = BinnedHistoPtr<double, double, double>;
1518 using Profile1DPtr = BinnedProfilePtr<double>;
1519 using Profile2DPtr = BinnedProfilePtr<double, double>;
1520 using Profile3DPtr = BinnedProfilePtr<double, double, double>;
1521 using Estimate1DPtr = BinnedEstimatePtr<double>;
1522 using Estimate2DPtr = BinnedEstimatePtr<double, double>;
1523 using Estimate3DPtr = BinnedEstimatePtr<double, double, double>;
1524 using Scatter1DPtr = ScatterNDPtr<1>;
1525 using Scatter2DPtr = ScatterNDPtr<2>;
1526 using Scatter3DPtr = ScatterNDPtr<3>;
1527
1528 using YODA::Counter;
1529 using YODA::Estimate0D;
1530 using YODA::Estimate1D;
1531 using YODA::Estimate2D;
1532 using YODA::Estimate3D;
1533 using YODA::Histo1D;
1534 using YODA::Histo2D;
1535 using YODA::Histo3D;
1536 using YODA::Point1D;
1537 using YODA::Point2D;
1538 using YODA::Point3D;
1539 using YODA::Profile1D;
1540 using YODA::Profile2D;
1541 using YODA::Profile3D;
1542 using YODA::Scatter1D;
1543 using YODA::Scatter2D;
1544 using YODA::Scatter3D;
1545
1547
1548
1551
1552 inline bool isTmpPath(const std::string& path, const bool tmp_only = false) {
1553 if (tmp_only) return path.find("/TMP/") != string::npos;
1554 return path.find("/TMP/") != string::npos || path.find("/_") != string::npos;
1555 }
1556
1559 map<string, YODA::AnalysisObjectPtr> getRefData(const string& papername);
1560
1562
1564 string getDatafilePath(const string& papername);
1565
1566
1569 template <typename T>
1570 struct ReferenceTraits { };
1571
1572 template <>
1573 struct ReferenceTraits<YODA::Counter> {
1574 using RefT = YODA::Estimate0D;
1575 };
1576
1577 template <>
1578 struct ReferenceTraits<YODA::Estimate0D> {
1579 using RefT = YODA::Estimate0D;
1580 };
1581
1582 template <typename... AxisT>
1583 struct ReferenceTraits<YODA::BinnedEstimate<AxisT...>> {
1584 using RefT = YODA::BinnedEstimate<AxisT...>;
1585 };
1586
1587 template <size_t DbnN, typename... AxisT>
1588 struct ReferenceTraits<YODA::BinnedDbn<DbnN, AxisT...>> {
1589 using RefT = YODA::ScatterND<sizeof...(AxisT) + 1>;
1590 };
1591
1592 template <size_t N>
1593 struct ReferenceTraits<YODA::ScatterND<N>> {
1594 using RefT = YODA::ScatterND<N>;
1595 };
1596
1599 template <typename TPtr>
1600 inline bool bookingCompatible(TPtr a, TPtr b) {
1601 return *a == *b;
1602 }
1603 //
1604 inline bool bookingCompatible(CounterPtr, CounterPtr) {
1605 return true;
1606 }
1607 //
1608 inline bool bookingCompatible(YODA::CounterPtr, YODA::CounterPtr) {
1609 return true;
1610 }
1611 //
1612 inline bool bookingCompatible(Estimate0DPtr, Estimate0DPtr) {
1613 return true;
1614 }
1615 //
1616 inline bool bookingCompatible(YODA::Estimate0DPtr, YODA::Estimate0DPtr) {
1617 return true;
1618 }
1619 //
1620 template <size_t N>
1621 inline bool bookingCompatible(ScatterNDPtr<N> a, ScatterNDPtr<N> b) {
1622 return a->numPoints() == b->numPoints();
1623 }
1624 //
1625 template <size_t N>
1626 inline bool bookingCompatible(YODA::ScatterNDPtr<N> a, YODA::ScatterNDPtr<N> b) {
1627 return a->numPoints() == b->numPoints();
1628 }
1629
1630 inline bool beamInfoCompatible(YODA::AnalysisObjectPtr a, YODA::AnalysisObjectPtr b) {
1631 YODA::BinnedEstimatePtr<string> beamsA = std::dynamic_pointer_cast<YODA::BinnedEstimate<string>>(a);
1632 YODA::BinnedEstimatePtr<string> beamsB = std::dynamic_pointer_cast<YODA::BinnedEstimate<string>>(b);
1633 return beamsA && beamsB && (*beamsA == *beamsB) && beamsA->numBins() == 2
1634 && fuzzyEquals(beamsA->bin(1).val(), beamsB->bin(1).val())
1635 && fuzzyEquals(beamsA->bin(2).val(), beamsB->bin(2).val());
1636 }
1637
1639
1640
1642 class AOPath {
1643 public:
1644
1646 AOPath(string fullpath)
1647 : _valid(false), _path(fullpath), _raw(false), _tmp(false), _ref(false) {
1648 _valid = init(fullpath);
1649 }
1650
1652 string path() const {
1653 return _path;
1654 }
1655
1657 string analysis() const {
1658 return _analysis;
1659 }
1660
1662 string analysisWithOptions() const {
1663 return _analysis + _optionstring;
1664 }
1665
1667 string name() const {
1668 return _name;
1669 }
1670
1672 string weight() const {
1673 return _weight;
1674 }
1675
1677 string weightComponent() const {
1678 if (_weight == "") return _weight;
1679 return "[" + _weight + "]";
1680 }
1681
1683 bool isRaw() const {
1684 return _raw;
1685 }
1686
1687 // Is this a temporary (filling) object?
1688 bool isTmp() const {
1689 return _tmp;
1690 }
1691
1693 bool isRef() const {
1694 return _ref;
1695 }
1696
1698 string optionString() const {
1699 return _optionstring;
1700 }
1701
1703 bool hasOptions() const {
1704 return !_options.empty();
1705 }
1706
1708 void removeOption(string opt) {
1709 _options.erase(opt);
1710 fixOptionString();
1711 }
1712
1714 void setOption(string opt, string val) {
1715 _options[opt] = val;
1716 fixOptionString();
1717 }
1718
1720 bool hasOption(string opt) const {
1721 return _options.find(opt) != _options.end();
1722 }
1723
1725 string getOption(string opt) const {
1726 auto it = _options.find(opt);
1727 if (it != _options.end()) return it->second;
1728 return "";
1729 }
1730
1732 void fixOptionString();
1733
1735 string mkPath() const;
1736 string setPath() {
1737 return _path = mkPath();
1738 }
1739
1741 void debug() const;
1742
1744 bool operator<(const AOPath& other) const {
1745 return _path < other._path;
1746 }
1747
1749 bool valid() const {
1750 return _valid;
1751 };
1752 bool operator!() const {
1753 return !valid();
1754 }
1755
1756 private:
1757
1759 bool init(string fullpath);
1760 bool chopweight(string& fullpath);
1761 bool chopoptions(string& anal);
1762
1763 bool _valid;
1764 string _path;
1765 string _analysis;
1766 string _optionstring;
1767 string _name;
1768 string _weight;
1769 bool _raw;
1770 bool _tmp;
1771 bool _ref;
1772 map<string, string> _options;
1773 };
1774
1775}
1776
1777#endif
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:286
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:322
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:317
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:295
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:374
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:343
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:352
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:379
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:493
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:498
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:471
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:462
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:436
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:401
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:441
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:410
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:559
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:519
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:554
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:528
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:590
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:622
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:581
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:617
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:260
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:233
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:265
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:242
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:674
int fill(const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:191
void reset()
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:198
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:203
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:184
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:651
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:697
FillCollectors which are used to temporarily cache unaggregated fills until collapsed by the Multiple...
Definition RivetYODA.hh:162
T & operator->()
Goes right through to the active Multiplexer<YODA> object's members.
Definition RivetYODA.hh:1402
bool operator>(const MultiplexPtr other) const
Greater-than for ptr ordering.
Definition RivetYODA.hh:1461
shared_ptr< T > get() const
Get the internal shared ptr.
Definition RivetYODA.hh:1476
T::Inner & operator*()
The active YODA object.
Definition RivetYODA.hh:1428
bool operator<(const MultiplexPtr &other) const
Less-than for ptr ordering.
Definition RivetYODA.hh:1456
const T & operator->() const
Goes right through to the active Multiplexer<YODA> object's members.
Definition RivetYODA.hh:1420
MultiplexPtr(const vector< string > &weightNames, const typename T::Inner &p)
Convenience constructor, pass through to the Multiplexer constructor.
Definition RivetYODA.hh:1388
bool operator!() const
Object invalidity check.
Definition RivetYODA.hh:1441
bool operator<=(const MultiplexPtr &other) const
Less-equals for ptr ordering.
Definition RivetYODA.hh:1466
bool operator!=(const MultiplexPtr &other) const
Object invalidity check.
Definition RivetYODA.hh:1451
bool operator==(const MultiplexPtr &other) const
Object validity check.
Definition RivetYODA.hh:1446
bool operator>=(const MultiplexPtr &other) const
Greater-equals for ptr ordering.
Definition RivetYODA.hh:1471
Multiplexer base class.
Definition RivetYODA.hh:951
virtual YODA::AnalysisObject * operator->() const =0
Access the active analysis object for const function calls.
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:997
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:957
bool operator!=(const MultiplexedAO &p)
Test for inequality.
Definition RivetYODA.hh:1002
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:1038
void initBootstrap()
Helper method to resize aux vectors to AO size.
Definition RivetYODA.hh:1324
const T & operator*() const
Forwarding dereference operator.
Definition RivetYODA.hh:1132
friend bool operator<(const Multiplexer a, const Multiplexer &b)
Less-than operator.
Definition RivetYODA.hh:1157
string baseName() const
Get the AO name of the object, without variation suffix.
Definition RivetYODA.hh:1096
T & operator*()
Forwarding dereference operator.
Definition RivetYODA.hh:1127
void newSubEvent()
Create a new FillCollector for the next sub-event.
Definition RivetYODA.hh:1201
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:1208
void pushToFinal()
Definition RivetYODA.hh:1287
void reset()
Clear the active object pointer.
Definition RivetYODA.hh:1191
T::Ptr active() const
Definition RivetYODA.hh:1073
const vector< typename T::Ptr > & final() const
Definition RivetYODA.hh:1309
bool operator!() const
Definition RivetYODA.hh:1111
string basePath() const
Get the AO path of the object, without variation suffix.
Definition RivetYODA.hh:1091
T * operator->() const
Forwarding dereference-call operator.
Definition RivetYODA.hh:1122
friend bool operator!=(const Multiplexer &a, const Multiplexer &b)
Inequality operator.
Definition RivetYODA.hh:1152
friend bool operator==(const Multiplexer &a, const Multiplexer &b)
Equality operator.
Definition RivetYODA.hh:1138
void setActiveFinalWeightIdx(size_t iWeight)
Set the active-object pointer to point at a variation in the final set.
Definition RivetYODA.hh:1181
void unsetActiveWeight()
Unset the active-object pointer.
Definition RivetYODA.hh:1186
void collapseSubevents(const vector< std::valarray< double > > &weights, const double nlowfrac)
Definition RivetYODA.hh:1250
const vector< typename T::Ptr > & persistent() const
Definition RivetYODA.hh:1298
T::Ptr persistent(const size_t iWeight)
Direct access to the persistent object in weight stream iWeight.
Definition RivetYODA.hh:1303
void setActiveWeightIdx(size_t iWeight)
Set the active-object pointer to point at a variation in the persistent set.
Definition RivetYODA.hh:1176
T * operator->()
Forwarding dereference-call operator.
Definition RivetYODA.hh:1117
YODA::AnalysisObjectPtr activeAO() const
Get the currently active analysis object.
Definition RivetYODA.hh:1319
T Inner
Typedef for the YODA type being represented.
Definition RivetYODA.hh:1046
STL class.
vector< Fill< T > > Fills
A collection of several Fill objects.
Definition RivetYODA.hh:148
double Weight
Typedef for weights.
Definition RivetYODA.hh:140
pair< typename T::FillType, Weight > Fill
A single fill is a (FillType, Weight) pair.
Definition RivetYODA.hh:144
map< string, YODA::AnalysisObjectPtr > getRefData(const string &papername)
bool bookingCompatible(TPtr a, TPtr b)
Definition RivetYODA.hh:1600
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:819
Definition LHCbCommon.hh:9
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:124
std::enable_if_t< std::is_arithmetic_v< NUM >, NUM > sqr(NUM a)
Named number-type squaring operation.
Definition MathUtils.hh:237
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:113
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:66
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