rivet is hosted by Hepforge, IPPP Durham
Rivet 4.0.2
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
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 };
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 };
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 };
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 };
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 };
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 };
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 using namespace std;
660
661 template<typename... Args>
662 double distance(const tuple<Args...>& a, const tuple<Args...>& b) {
663 double rtn = 0;
664 auto calculateDistance = [&](auto I) {
665 if constexpr (std::is_floating_point<std::tuple_element_t<I,
666 std::tuple<Args...>>>::value) {
667 rtn += Rivet::sqr(get<I>(a) - get<I>(b));
668 }
669 };
670 MetaUtils::staticFor<sizeof...(Args)>(calculateDistance);
671 return rtn;
672 }
673
680 template <typename T>
681 vector<Fills<T>> applyEmptyFillPaddingAndTranspose(const vector<typename FillCollector<T>::Ptr>& subevents) {
682
683 static Fill<T> EmptyFill = { typename T::FillType{}, 0.0 };
684
685 vector<Fills<T>> matched;
686 matched.reserve(subevents.size());
687 // First just copy subevents into vectors and find the longest vector.
688 size_t maxFillLen = 0; // length of biggest vector
689 size_t maxFillPos = 0; // index position of biggest vector
690 for (const auto& subevt : subevents) {
691 auto&& fills = subevt->fills();
692 if (fills.size() > maxFillLen) {
693 maxFillLen = fills.size();
694 maxFillPos = matched.size();
695 }
696 matched.push_back(std::move(fills));
697 }
698
699 // Now, go through all subevents with missing fills.
700 const Fills<T>& maxFill = matched[maxFillPos]; // the longest fill
701 for (auto& fills : matched) {
702
703 if (fills.size() == maxFillLen) continue;
704
707 while (fills.size() < maxFillLen) {
708 fills.push_back(EmptyFill);
709 }
710
714 for (int i = maxFillLen - 1; i >= 0; --i) {
715 if (fills[i] == EmptyFill) continue;
716 int j = i;
717 while (j+1 < (int)maxFillLen &&
718 fills[j + 1] == EmptyFill &&
719 distance(fills[j].first,
720 maxFill[j].first) >
721 distance(fills[j].first,
722 maxFill[j+1].first)) {
723 swap(fills[j], fills[j+1]);
724 ++j;
725 }
726 }
727 }
728 // finally, transpose and we're done
729 vector<Fills<T>> result(maxFillLen, Fills<T>(matched.size()));
730 for (size_t i = 0; i < matched.size(); ++i) {
731 for (size_t j = 0; j < maxFillLen; ++j) {
732 result.at(j).at(i) = std::move(matched.at(i).at(j));
733 }
734 }
735 return result;
736 }
737
740 template<typename T>
741 struct SubwindowType;
742 //
743 template<typename... Args>
744 struct SubwindowType<tuple<Args...>> {
745 using type = YODA::Binning<std::decay_t<decltype(std::declval<YODA::Axis<Args>>())>...>;
746 };
747
755 template<typename YAO>
756 vector<std::tuple<typename YAO::FillType, valarray<double>, double>>
757 applyFillWindows(shared_ptr<YAO> ao, const Fills<YAO>& subevents,
758 const vector<valarray<double>>& weights, const double fsmear=0.5) {
759
760
761 using SubwindowT = typename SubwindowType<typename YAO::FillType>::type;
762 SubwindowT subwindows;
763
764 const size_t nFills = subevents.size();
765 vector<vector<double>> edgesLo, edgesHi;
766 edgesLo.resize(YAO::FillDimension::value);
767 edgesHi.resize(YAO::FillDimension::value);
768
769 auto constructWindows = [&](auto I) {
770
771 using FillAxisT = typename SubwindowT::template getAxisT<I>;
772 using isContinuous = typename SubwindowT::template is_CAxis<I>;
773
774 if constexpr(!isContinuous::value) { // discrete axes don't need smearing
775 // use single-edge axis for discrete coordinates
776 subwindows.template axis<I>() = FillAxisT({ std::get<I>(subevents[0].first) });
777 return;
778 }
779 else { // continuous axes need windowing
780 edgesHi[I].resize(nFills);
781 edgesLo[I].resize(nFills);
782
783 if constexpr(I < YAO::BinningT::Dimension::value) {
784 // this fill axis is binned: window sizes will depend on bin width
785 const auto& axis = ao->binning().template axis<I>();
786 size_t over = 0, under = 0;
787 const double edgeMax = ao->template max<I>();
788 const double edgeMin = ao->template min<I>();
789 const size_t binLast = axis.numBins(); // index of last visible bin
790
791 for (size_t i = 0; i < nFills; ++i) {
792 const double edge = get<I>(subevents[i].first);
793 size_t idx = axis.index(edge);
794 if (edge >= edgeMax) {
795 if (edge > edgeMax) ++over;
796 idx = binLast; // cut off at highest visible bin
797 }
798 else if (edge < edgeMin) {
799 ++under;
800 idx = 1; // cut off at lowest visible bin
801 }
802 // find index of closest neighbouring bin
803 size_t ibn = idx;
804 if (edge > axis.mid(idx)) {
805 if (idx != binLast) ++ibn;
806 }
807 else {
808 if (idx != 1) --ibn;
809 }
810
811 // construct rectangular windows of with = 2*delta
812 const double ibw = axis.width(idx) < axis.width(ibn)? idx : ibn;
813 if ( fsmear > 0.0 ) {
814 const double delta = 0.5*fsmear*axis.width(ibw);
815 edgesHi[I][i] = edge + delta;
816 edgesLo[I][i] = edge - delta;
817 }
818 else {
819 const double delta = 0.5*axis.width(ibw);
820 if (edge > edgeMax) {
821 edgesHi[I][i] = max(edgeMax + 2*delta, edge + delta);
822 edgesLo[I][i] = max(edgeMax, edge - delta);
823 }
824 else if (edge < edgeMin) {
825 edgesHi[I][i] = min(edgeMin, edge + delta);
826 edgesLo[I][i] = min(edgeMin - 2*delta, edge - delta);
827 }
828 else {
829 edgesHi[I][i] = axis.max(idx);
830 edgesLo[I][i] = axis.min(idx);
831 }
832 }
833 }
834 for (size_t i = 0; i < nFills; ++i) {
835 const double wsize = edgesHi[I][i] - edgesLo[I][i];
836 if (over == nFills && edgesLo[I][i] < edgeMax && edgesHi[I][i] > edgeMax) {
837 edgesHi[I][i] = edgeMax + wsize;
838 edgesLo[I][i] = edgeMax;
839 }
840 else if (over == 0 && edgesLo[I][i] < edgeMax && edgesHi[I][i] > edgeMax) {
841 edgesLo[I][i] = edgeMax - wsize;
842 edgesHi[I][i] = edgeMax;
843 }
844 else if (under == nFills && edgesLo[I][i] < edgeMin && edgesHi[I][i] > edgeMin) {
845 edgesLo[I][i] = edgeMin - wsize;
846 edgesHi[I][i] = edgeMin;
847 }
848 else if (under == 0 && edgesLo[I][i] < edgeMin && edgesHi[I][i] > edgeMin) {
849 edgesHi[I][i] = edgeMin + wsize;
850 edgesLo[I][i] = edgeMin;
851 }
852 }
853 } // end of constexpr-check for binned axes
854 else {
855 // this fill axis is unbinned (e.g. in Profiles)
856 for (size_t i = 0; i < nFills; ++i) {
859 const double edge = get<I>(subevents[i].first);
860 const double delta = 0.1*fabs(edge);
861 edgesHi[I][i] = edge + delta;
862 edgesLo[I][i] = edge - delta;
863 }
864 }
865 // create CAxis with subwindows from the set of window edges
866 vector<double> windowEdges;
867 std::copy(edgesLo[I].begin(), edgesLo[I].end(), std::back_inserter(windowEdges));
868 std::copy(edgesHi[I].begin(), edgesHi[I].end(), std::back_inserter(windowEdges));
869 std::sort(windowEdges.begin(), windowEdges.end());
870 windowEdges.erase( std::unique(windowEdges.begin(), windowEdges.end()), windowEdges.end() );
871 subwindows.template axis<I>() = FillAxisT(windowEdges);
872 } // end of if constexpr isContinuous
873 };
874 // execute for each fill dimension
875 MetaUtils::staticFor<YAO::FillDimension::value>(constructWindows);
876
877 // Placeholder for the return type: a tuple of {FillType, multi-weights, fill fraction}
878 vector<std::tuple<typename YAO::FillType, valarray<double>, double>> rtn;
879
880 // Subwindows are given by visible bins of the
881 // SubwindowT, so skip all under-/overflows
882 const vector<size_t> overflows = subwindows.calcOverflowBinsIndices();
883 const auto& itEnd = overflows.cend();
884 for (size_t i = 0; i < subwindows.numBins(); ++i) {
885 if (std::find(overflows.cbegin(), itEnd, i) != itEnd) continue;
886
887 const auto coords = subwindows.edgeTuple(i);
888 const double subwindowArea = subwindows.dVol(i);
889 size_t nSubfills = 0;
890 double windowFrac = 0.;
891 valarray<double> sumw(0.0, weights[0].size()); // one per multiweight
892 for (size_t j = 0; j < nFills; ++j) {
893 bool pass = true;
894 double windowArea = 1.0;
895 auto checkSubwindowOverlap = [&](auto I) {
896 using isContinuous = typename SubwindowT::template is_CAxis<I>;
897 if constexpr (isContinuous::value) {
898 const double edge = std::get<I>(coords);
899 pass &= (edgesLo[I][j] <= edge && edge <= edgesHi[I][j]);
900 windowArea *= edgesHi[I][j] - edgesLo[I][j];
901 }
902 };
903 MetaUtils::staticFor<YAO::FillDimension::value>(checkSubwindowOverlap);
904 if (pass) {
905 windowFrac = subwindowArea/windowArea;
906 sumw += subevents[j].second * weights[j];
907 ++nSubfills;
908 }
909 }
910 if (nSubfills) {
911 const double fillFrac = (double)nSubfills/(double)nFills;
912 rtn.emplace_back(coords, sumw/fillFrac, fillFrac*windowFrac); // normalise to a single fill
913 }
914 }
915 return rtn;
916 } // end of applyFillWindows
917
918 } // end of anonymous name space
919
920
923
932 public:
933
934 virtual ~MultiplexedAO() { }
935
937 using Inner = YODA::AnalysisObject;
938
940 virtual void newSubEvent() = 0;
941
943 virtual void collapseEventGroup(const vector<std::valarray<double>>& weight, const double nlowfrac=0.0) = 0;
944
946 virtual void pushToFinal() = 0;
947
949 virtual YODA::AnalysisObjectPtr activeAO() const = 0;
950
952 virtual string basePath() const = 0;
953
955 virtual YODA::AnalysisObject* operator -> () = 0;
956
958 virtual YODA::AnalysisObject* operator -> () const = 0;
959
961 virtual const YODA::AnalysisObject& operator * () const = 0;
962
964 virtual void setActiveWeightIdx(size_t iWeight) = 0;
965
967 virtual void setActiveFinalWeightIdx(size_t iWeight) = 0;
968
970 virtual void unsetActiveWeight() = 0;
971
973 virtual void initBootstrap() = 0;
974
976 bool operator == (const MultiplexedAO& p) { return (this == &p); }
977
979 bool operator != (const MultiplexedAO& p) { return (this != &p); }
980
981 const vector<bool>& fillOutcomes() const { return _fillOutcomes; }
982
983 const vector<double>& fillFractions() const { return _fillFractions; }
984
985 protected:
986
987 vector<bool> _fillOutcomes;
988
989 vector<double> _fillFractions;
990
991 };
992
993
994
1010 template<typename T>
1012
1013 public:
1014
1015 friend class Analysis;
1016 //friend class AnalysisHandler;
1017
1019 using Inner = T;
1020 using MultiplexedAO::_fillOutcomes;
1021 using MultiplexedAO::_fillFractions;
1022
1023 Multiplexer() = default;
1024
1025 Multiplexer(const vector<string>& weightNames, const T& p) {
1026 _basePath = p.path();
1027 _baseName = p.name();
1028 for (const string& weightname : weightNames) {
1029 _persistent.push_back(make_shared<T>(p));
1030 _final.push_back(make_shared<T>(p));
1031
1032 typename T::Ptr obj = _persistent.back();
1033 obj->setPath("/RAW" + obj->path());
1034 typename T::Ptr final = _final.back();
1035 if (weightname != "") {
1036 obj->setPath(obj->path() + "[" + weightname + "]");
1037 final->setPath(final->path() + "[" + weightname + "]");
1038 }
1039 }
1040 }
1041
1042 ~Multiplexer() = default;
1043
1046 typename T::Ptr active() const {
1047 if ( !_active ) {
1048 #ifdef HAVE_BACKTRACE
1049 void* buffer[4];
1050 backtrace(buffer, 4);
1051 backtrace_symbols_fd(buffer, 4 , 1);
1052 #endif
1053 assert(false && "No active pointer set. Was this object booked in init()?");
1054 }
1055 return _active;
1056 }
1057
1058 template <typename U = T>
1059 auto binning() const -> std::enable_if_t<hasBinning<T>::value, const typename U::BinningT&> {
1060 return _persistent.back()->binning();
1061 }
1062
1064 string basePath() const { return _basePath; }
1065
1067 string baseName() const { return _baseName; }
1068
1069
1073 explicit operator bool() const { return static_cast<bool>(_active); }
1074
1078 bool operator ! () const { return !_active; }
1079
1080
1082 T* operator -> () { return active().get(); }
1083
1085 T* operator -> () const { return active().get(); }
1086
1088 T& operator * () { return *active(); }
1089
1091 const T& operator * () const { return *active(); }
1092
1093
1095 friend bool operator == (const Multiplexer& a, const Multiplexer& b){
1096 if (a._persistent.size() != b._persistent.size()) {
1097 return false;
1098 }
1099 // also test for binning compatibility
1100 for (size_t i = 0; i < a._persistent.size(); ++i) {
1101 if (a._persistent.at(i) != b._persistent.at(i)) {
1102 return false;
1103 }
1104 }
1105 return true;
1106 }
1107
1109 friend bool operator != (const Multiplexer& a, const Multiplexer& b) {
1110 return !(a == b);
1111 }
1112
1114 friend bool operator < (const Multiplexer a, const Multiplexer& b) {
1115 if (a._persistent.size() >= b._persistent.size()) {
1116 return false;
1117 }
1118 for (size_t i = 0; i < a._persistent.size(); ++i) {
1119 if (*(a._persistent.at(i)) >= *(b._persistent.at(i))) {
1120 return false;
1121 }
1122 }
1123 return true;
1124 }
1125
1126
1128
1131
1133 void setActiveWeightIdx(size_t iWeight) {
1134 _active = _persistent.at(iWeight);
1135 }
1136
1138 void setActiveFinalWeightIdx(size_t iWeight) {
1139 _active = _final.at(iWeight);
1140 }
1141
1143 void unsetActiveWeight() { _active.reset(); }
1144
1146 void reset() { active()->reset(); }
1147
1148
1155 _evgroup.emplace_back(new FillCollector<T>(_persistent[0]));
1156 _active = _evgroup.back();
1157 assert(_active);
1158 }
1159
1161 void collapseEventGroup(const vector<std::valarray<double>>& weights, const double nlowfrac=0.0) {
1162
1164 if constexpr( isFillable<T>::value ) {
1165
1166 // Should have as many subevent fills as subevent weights
1167 assert( _evgroup.size() == weights.size() );
1168
1169 if (_evgroup.size() == 1) { // Have we had subevents at all?
1170 // ensure vector length matches size of multiplexed AO
1171 if (_fillOutcomes.empty()) initBootstrap();
1172 // reset fill positions
1173 std::fill(_fillOutcomes.begin(), _fillOutcomes.end(), false);
1174 std::fill(_fillFractions.begin(), _fillFractions.end(), 0.0);
1175
1176 // Simple replay of all collected fills:
1177 // each fill is inserted into every persistent AO
1178 for (auto f : _evgroup[0]->fills()) {
1179 int pos = -1;
1180 double frac = 0.0;
1181 for (size_t m = 0; m < _persistent.size(); ++m) { //< m is the variation index
1182 if (!m) frac = f.second;
1183 pos = _persistent[m]->fill( std::move(f.first), std::move(f.second) * weights[0][m] );
1184 }
1185 if (pos >= 0) {
1186 _fillOutcomes[pos] = true;
1187 _fillFractions[pos] += frac;
1188 }
1189 }
1190 }
1191 else {
1192 collapseSubevents(weights, nlowfrac);
1193 }
1194 }
1195
1196 _evgroup.clear();
1197 _active.reset();
1198 }
1199
1203 void collapseSubevents(const vector<std::valarray<double>>& weights, const double nlowfrac) {
1204 if constexpr( isFillable<T>::value ) {
1205 if constexpr (!std::is_same<T, YODA::Counter>::value ) { // binned objects
1211 for (const Fills<T>& subEvents : applyEmptyFillPaddingAndTranspose<T>(_evgroup)) {
1212 // construct fill windows with fractional fills
1213 for (const auto& f : applyFillWindows(_persistent[0], subEvents, weights, nlowfrac)) {
1214 for ( size_t m = 0; m < _persistent.size(); ++m ) { // for each multiweight
1215 _persistent[m]->fill( typename T::FillType(get<0>(f)), get<1>(f)[m], get<2>(f) );
1216 }
1217 } // end of loop over fill windows
1218 } // end of loop over subevents
1219 }
1220 else {
1221 for (size_t m = 0; m < _persistent.size(); ++m) { //< m is the variation index
1222 vector<double> sumfw{0.0}; // final fill weights (one per fill)
1223 for (size_t n = 0; n < _evgroup.size(); ++n) { //< n is the correlated sub-event index
1224 const auto& fills = _evgroup[n]->fills();
1225 // resize if this subevent has an
1226 // even larger number of fills
1227 if (fills.size() > sumfw.size()) {
1228 sumfw.resize(fills.size(), 0.0);
1229 }
1230 size_t fi = 0;
1231 for (const auto& f : fills) { // collapse sub-events and aggregate final fill weights
1232 sumfw[fi++] += f.second * weights[n][m]; // f.second is optional user-supplied scaling
1233 }
1234 }
1235 for (double fw : sumfw) { // fill persistent Counters
1236 _persistent[m]->fill(std::move(fw));
1237 }
1238 }
1239 }
1240 }
1241 }
1242
1246 for ( size_t m = 0; m < _persistent.size(); ++m ) { //< variation weight index
1247 _final.at(m)->clearAnnotations(); // in case this is a repeat call
1248 copyAO<T>(_persistent.at(m), _final.at(m));
1249 // Remove the /RAW prefix, if there is one, from the final copy
1250 if ( _final[m]->path().substr(0,4) == "/RAW" )
1251 _final[m]->setPath(_final[m]->path().substr(4));
1252 }
1253 }
1254
1257 const vector<typename T::Ptr>& persistent() const {
1258 return _persistent;
1259 }
1260
1262 typename T::Ptr persistent(const size_t iWeight) { return _persistent.at(iWeight); }
1263
1266 const vector<typename T::Ptr>& final() const {
1267 return _final;
1268 }
1269
1271 typename T::Ptr final(const size_t iWeight) { return _final.at(iWeight); }
1272
1274 YODA::AnalysisObjectPtr activeAO() const { return _active; }
1275
1278 if constexpr( isFillable<T>::value ) {
1279 size_t nPos = 1; // Counter only has a single fill position
1280 if constexpr (!std::is_same<T, YODA::Counter>::value ) { // binned objects
1281 nPos = _persistent.back()->numBins(true, true);
1282 }
1283 _fillOutcomes.resize(nPos);
1284 _fillFractions.resize(nPos);
1285 }
1286 }
1287
1289
1290 private:
1291
1294
1296 vector<typename T::Ptr> _persistent;
1297
1299 vector<typename T::Ptr> _final;
1300
1302 vector<typename FillCollector<T>::Ptr> _evgroup;
1303
1306 typename T::Ptr _active;
1307
1310 string _basePath;
1311
1314 string _baseName;
1315
1317
1318 };
1319
1320
1329 template <typename T>
1331
1332 public:
1333
1334 using value_type = T;
1335
1336 MultiplexPtr() = default;
1337
1338 MultiplexPtr(decltype(nullptr)) : _p(nullptr) { }
1339
1341 MultiplexPtr(const vector<string>& weightNames, const typename T::Inner& p)
1342 : _p( make_shared<T>(weightNames, p) ) { }
1343
1344 // Ensure a shared_ptr<T> can be instantiated from a shared_ptr<U>
1345 template <typename U, typename = decltype(shared_ptr<T>(shared_ptr<U>{}))>
1346 MultiplexPtr(const shared_ptr<U>& p) : _p(p) { }
1347
1348 // Ensure a shared_ptr<T> can be instantiated from a shared_ptr<U>
1349 template <typename U, typename = decltype(shared_ptr<T>(shared_ptr<U>{}))>
1350 MultiplexPtr(const MultiplexPtr<U>& p) : _p(p.get()) { }
1351
1354 if (_p == nullptr) {
1355 throw Error("Dereferencing null AnalysisObject pointer. Is there an unbooked histogram variable?");
1356 }
1357 return *_p;
1358 }
1359
1360 template <typename U = T>
1361 auto binning() const -> std::enable_if_t<hasBinning<typename T::Inner>::value, const typename U::Inner::BinningT&> {
1362 if (_p == nullptr) {
1363 throw Error("Dereferencing null AnalysisObject pointer. Is there an unbooked histogram variable?");
1364 }
1365 return _p->binning();
1366 }
1367
1368
1370 const T& operator -> () const {
1371 if (_p == nullptr) {
1372 throw Error("Dereferencing null AnalysisObject pointer. Is there an unbooked histogram variable?");
1373 }
1374 return *_p;
1375 }
1376
1378 typename T::Inner& operator * () { return **_p; }
1379 const typename T::Inner& operator * () const { return **_p; }
1380
1382 explicit operator bool() const { return _p && bool(*_p); }
1383
1385 bool operator ! () const { return !_p || !(*_p); }
1386
1388 bool operator == (const MultiplexPtr& other) const {
1389 return _p == other._p;
1390 }
1391
1393 bool operator != (const MultiplexPtr& other) const {
1394 return _p != other._p;
1395 }
1396
1398 bool operator < (const MultiplexPtr& other) const {
1399 return _p < other._p;
1400 }
1401
1403 bool operator > (const MultiplexPtr other) const {
1404 return _p > other._p;
1405 }
1406
1408 bool operator <= (const MultiplexPtr& other) const {
1409 return _p <= other._p;
1410 }
1411
1413 bool operator >= (const MultiplexPtr& other) const {
1414 return _p >= other._p;
1415 }
1416
1418 shared_ptr<T> get() const { return _p; }
1419
1420 private:
1421
1423 shared_ptr<T> _p;
1424
1425 };
1426
1428
1429
1436
1437 using MultiplexAOPtr = MultiplexPtr<MultiplexedAO>;
1438
1439 template<size_t DbnN, typename... AxisT>
1440 using BinnedDbnPtr = MultiplexPtr<Multiplexer<YODA::BinnedDbn<DbnN, AxisT...>>>;
1441
1442 template<typename... AxisT>
1443 using BinnedHistoPtr = BinnedDbnPtr<sizeof...(AxisT), AxisT...>;
1444
1445 template<typename... AxisT>
1446 using BinnedProfilePtr = BinnedDbnPtr<sizeof...(AxisT)+1, AxisT...>;
1447
1448 template<typename... AxisT>
1449 using BinnedEstimatePtr = MultiplexPtr<Multiplexer<YODA::BinnedEstimate<AxisT...>>>;
1450
1451 template<size_t N>
1452 using ScatterNDPtr = MultiplexPtr<Multiplexer<YODA::ScatterND<N>>>;
1453
1454 using CounterPtr = MultiplexPtr<Multiplexer<YODA::Counter>>;
1455 using Estimate0DPtr = MultiplexPtr<Multiplexer<YODA::Estimate0D>>;
1456 using Histo1DPtr = BinnedHistoPtr<double>;
1457 using Histo2DPtr = BinnedHistoPtr<double,double>;
1458 using Histo3DPtr = BinnedHistoPtr<double,double,double>;
1459 using Profile1DPtr = BinnedProfilePtr<double>;
1460 using Profile2DPtr = BinnedProfilePtr<double,double>;
1461 using Profile3DPtr = BinnedProfilePtr<double,double,double>;
1462 using Estimate1DPtr = BinnedEstimatePtr<double>;
1463 using Estimate2DPtr = BinnedEstimatePtr<double,double>;
1464 using Estimate3DPtr = BinnedEstimatePtr<double,double,double>;
1465 using Scatter1DPtr = ScatterNDPtr<1>;
1466 using Scatter2DPtr = ScatterNDPtr<2>;
1467 using Scatter3DPtr = ScatterNDPtr<3>;
1468
1469 using YODA::Counter;
1470 using YODA::Estimate0D;
1471 using YODA::Histo1D;
1472 using YODA::Histo2D;
1473 using YODA::Histo3D;
1474 using YODA::Profile1D;
1475 using YODA::Profile2D;
1476 using YODA::Profile3D;
1477 using YODA::Estimate1D;
1478 using YODA::Estimate2D;
1479 using YODA::Estimate3D;
1480 using YODA::Scatter1D;
1481 using YODA::Scatter2D;
1482 using YODA::Scatter3D;
1483 using YODA::Point1D;
1484 using YODA::Point2D;
1485 using YODA::Point3D;
1486
1488
1489
1492
1493 inline bool isTmpPath(const std::string& path, const bool tmp_only = false) {
1494 if (tmp_only) return path.find("/TMP/") != string::npos;
1495 return path.find("/TMP/") != string::npos || path.find("/_") != string::npos;
1496 }
1497
1500 map<string, YODA::AnalysisObjectPtr> getRefData(const string& papername);
1501
1503
1505 string getDatafilePath(const string& papername);
1506
1507
1510 template<typename T>
1511 struct ReferenceTraits { };
1512
1513 template<>
1514 struct ReferenceTraits<YODA::Counter> {
1515 using RefT = YODA::Estimate0D;
1516 };
1517
1518 template<>
1519 struct ReferenceTraits<YODA::Estimate0D> {
1520 using RefT = YODA::Estimate0D;
1521 };
1522
1523 template<typename... AxisT>
1524 struct ReferenceTraits<YODA::BinnedEstimate<AxisT...>> {
1525 using RefT = YODA::BinnedEstimate<AxisT...>;
1526 };
1527
1528 template<size_t DbnN, typename... AxisT>
1529 struct ReferenceTraits<YODA::BinnedDbn<DbnN, AxisT...>> {
1530 using RefT = YODA::ScatterND<sizeof...(AxisT)+1>;
1531 };
1532
1533 template<size_t N>
1534 struct ReferenceTraits<YODA::ScatterND<N>> {
1535 using RefT = YODA::ScatterND<N>;
1536 };
1537
1540 template <typename TPtr>
1541 inline bool bookingCompatible(TPtr a, TPtr b) {
1542 return *a == *b;
1543 }
1544 //
1545 inline bool bookingCompatible(CounterPtr, CounterPtr) {
1546 return true;
1547 }
1548 //
1549 inline bool bookingCompatible(YODA::CounterPtr, YODA::CounterPtr) {
1550 return true;
1551 }
1552 //
1553 inline bool bookingCompatible(Estimate0DPtr, Estimate0DPtr) {
1554 return true;
1555 }
1556 //
1557 inline bool bookingCompatible(YODA::Estimate0DPtr, YODA::Estimate0DPtr) {
1558 return true;
1559 }
1560 //
1561 template<size_t N>
1562 inline bool bookingCompatible(ScatterNDPtr<N> a, ScatterNDPtr<N> b) {
1563 return a->numPoints() == b->numPoints();
1564 }
1565 //
1566 template<size_t N>
1567 inline bool bookingCompatible(YODA::ScatterNDPtr<N> a, YODA::ScatterNDPtr<N> b) {
1568 return a->numPoints() == b->numPoints();
1569 }
1570
1571 inline bool beamInfoCompatible(YODA::AnalysisObjectPtr a, YODA::AnalysisObjectPtr b) {
1572 YODA::BinnedEstimatePtr<string> beamsA = std::dynamic_pointer_cast<YODA::BinnedEstimate<string>>(a);
1573 YODA::BinnedEstimatePtr<string> beamsB = std::dynamic_pointer_cast<YODA::BinnedEstimate<string>>(b);
1574 return beamsA && beamsB && (*beamsA == *beamsB) && beamsA->numBins() == 2 &&
1575 fuzzyEquals(beamsA->bin(1).val(), beamsB->bin(1).val()) &&
1576 fuzzyEquals(beamsA->bin(2).val(), beamsB->bin(2).val());
1577 }
1578
1580
1581
1582
1584 class AOPath {
1585 public:
1586
1588 AOPath(string fullpath)
1589 : _valid(false), _path(fullpath), _raw(false), _tmp(false), _ref(false) {
1590 _valid = init(fullpath);
1591 }
1592
1594 string path() const { return _path; }
1595
1597 string analysis() const { return _analysis; }
1598
1600 string analysisWithOptions() const { return _analysis + _optionstring; }
1601
1603 string name() const { return _name; }
1604
1606 string weight() const { return _weight; }
1607
1609 string weightComponent() const {
1610 if (_weight == "") return _weight;
1611 return "[" + _weight + "]";
1612 }
1613
1615 bool isRaw() const { return _raw; }
1616
1617 // Is this a temporary (filling) object?
1618 bool isTmp() const { return _tmp; }
1619
1621 bool isRef() const { return _ref; }
1622
1624 string optionString() const { return _optionstring; }
1625
1627 bool hasOptions() const { return !_options.empty(); }
1628
1630 void removeOption(string opt) { _options.erase(opt); fixOptionString(); }
1631
1633 void setOption(string opt, string val) { _options[opt] = val; fixOptionString(); }
1634
1636 bool hasOption(string opt) const { return _options.find(opt) != _options.end(); }
1637
1639 string getOption(string opt) const {
1640 auto it = _options.find(opt);
1641 if ( it != _options.end() ) return it->second;
1642 return "";
1643 }
1644
1646 void fixOptionString();
1647
1649 string mkPath() const;
1650 string setPath() { return _path = mkPath(); }
1651
1653 void debug() const;
1654
1656 bool operator<(const AOPath & other) const {
1657 return _path < other._path;
1658 }
1659
1661 bool valid() const { return _valid; };
1662 bool operator!() const { return !valid(); }
1663
1664 private:
1665
1667 bool init(string fullpath);
1668 bool chopweight(string & fullpath);
1669 bool chopoptions(string & anal);
1670
1671 bool _valid;
1672 string _path;
1673 string _analysis;
1674 string _optionstring;
1675 string _name;
1676 string _weight;
1677 bool _raw;
1678 bool _tmp;
1679 bool _ref;
1680 map<string,string> _options;
1681
1682 };
1683
1684}
1685
1686#endif
This is the base class of all analysis classes in Rivet.
Definition Analysis.hh:69
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
Definition RivetYODA.hh:1330
T & operator->()
Goes right through to the active Multiplexer<YODA> object's members.
Definition RivetYODA.hh:1353
bool operator>(const MultiplexPtr other) const
Greater-than for ptr ordering.
Definition RivetYODA.hh:1403
shared_ptr< T > get() const
Get the internal shared ptr.
Definition RivetYODA.hh:1418
T::Inner & operator*()
The active YODA object.
Definition RivetYODA.hh:1378
bool operator<(const MultiplexPtr &other) const
Less-than for ptr ordering.
Definition RivetYODA.hh:1398
MultiplexPtr(const vector< string > &weightNames, const typename T::Inner &p)
Convenience constructor, pass through to the Multiplexer constructor.
Definition RivetYODA.hh:1341
bool operator!() const
Object invalidity check.
Definition RivetYODA.hh:1385
bool operator<=(const MultiplexPtr &other) const
Less-equals for ptr ordering.
Definition RivetYODA.hh:1408
bool operator!=(const MultiplexPtr &other) const
Object invalidity check.
Definition RivetYODA.hh:1393
bool operator==(const MultiplexPtr &other) const
Object validity check.
Definition RivetYODA.hh:1388
bool operator>=(const MultiplexPtr &other) const
Greater-equals for ptr ordering.
Definition RivetYODA.hh:1413
Multiplexer base class.
Definition RivetYODA.hh:931
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:976
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.
virtual void collapseEventGroup(const vector< std::valarray< double > > &weight, const double nlowfrac=0.0)=0
Sync the fill proxies to the persistent histogram.
YODA::AnalysisObject Inner
The type being represented is a generic AO.
Definition RivetYODA.hh:937
bool operator!=(const MultiplexedAO &p)
Test for inequality.
Definition RivetYODA.hh:979
virtual const YODA::AnalysisObject & operator*() const =0
Access the active analysis object as a reference.
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:1011
void initBootstrap()
Helper method to resize aux vectors to AO size.
Definition RivetYODA.hh:1277
friend bool operator<(const Multiplexer a, const Multiplexer &b)
Less-than operator.
Definition RivetYODA.hh:1114
string baseName() const
Get the AO name of the object, without variation suffix.
Definition RivetYODA.hh:1067
T & operator*()
Forwarding dereference operator.
Definition RivetYODA.hh:1088
void newSubEvent()
Create a new FillCollector for the next sub-event.
Definition RivetYODA.hh:1154
void pushToFinal()
Definition RivetYODA.hh:1245
void reset()
Clear the active object pointer.
Definition RivetYODA.hh:1146
T::Ptr active() const
Definition RivetYODA.hh:1046
const vector< typename T::Ptr > & final() const
Definition RivetYODA.hh:1266
bool operator!() const
Definition RivetYODA.hh:1078
string basePath() const
Get the AO path of the object, without variation suffix.
Definition RivetYODA.hh:1064
void collapseEventGroup(const vector< std::valarray< double > > &weights, const double nlowfrac=0.0)
Pushes the (possibly collapsed) fill(s) into the persistent objects.
Definition RivetYODA.hh:1161
friend bool operator!=(const Multiplexer &a, const Multiplexer &b)
Inequality operator.
Definition RivetYODA.hh:1109
friend bool operator==(const Multiplexer &a, const Multiplexer &b)
Equality operator.
Definition RivetYODA.hh:1095
void setActiveFinalWeightIdx(size_t iWeight)
Set the active-object pointer to point at a variation in the final set.
Definition RivetYODA.hh:1138
void unsetActiveWeight()
Unset the active-object pointer.
Definition RivetYODA.hh:1143
void collapseSubevents(const vector< std::valarray< double > > &weights, const double nlowfrac)
Definition RivetYODA.hh:1203
const vector< typename T::Ptr > & persistent() const
Definition RivetYODA.hh:1257
T::Ptr persistent(const size_t iWeight)
Direct access to the persistent object in weight stream iWeight.
Definition RivetYODA.hh:1262
void setActiveWeightIdx(size_t iWeight)
Set the active-object pointer to point at a variation in the persistent set.
Definition RivetYODA.hh:1133
T * operator->()
Forwarding dereference-call operator.
Definition RivetYODA.hh:1082
YODA::AnalysisObjectPtr activeAO() const
Get the currently active analysis object.
Definition RivetYODA.hh:1274
T Inner
Typedef for the YODA type being represented.
Definition RivetYODA.hh:1019
double Weight
Typedef for weights.
Definition RivetYODA.hh:135
vector< Fill< T > > Fills
A collection of several Fill objects.
Definition RivetYODA.hh:143
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:1541
string getDatafilePath(const string &papername)
Get the file system path to the reference file for this paper.
Definition MC_CENT_PPB_Projections.hh:10
Cut operator!(const Cut &cptr)
Logical NOT operation on a cut.
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
A polymorphic base type for the AO type handles.
Definition RivetYODA.hh:79
The type-specific handle that can perform type-specific operations for objects of type T.
Definition RivetYODA.hh:100