1#ifndef RIVET_RIVETYODA_HH
2#define RIVET_RIVETYODA_HH
4#include "Rivet/Config/RivetCommon.hh"
5#include "Rivet/Tools/TypeTraits.hh"
6#include "YODA/AnalysisObject.h"
7#include "YODA/Counter.h"
9#include "YODA/Profile.h"
10#include "YODA/Estimate0D.h"
11#include "YODA/BinnedEstimate.h"
12#include "YODA/Scatter.h"
20#include <unordered_map>
26 template<
size_t DbnN,
typename ... AxisT>
27 using BinnedDbnPtr = std::shared_ptr<YODA::BinnedDbn<DbnN, AxisT...>>;
29 template<
typename ... AxisT>
30 using BinnedHistoPtr = BinnedDbnPtr<
sizeof...(AxisT), AxisT...>;
32 template<
typename ... AxisT>
33 using BinnedProfilePtr = BinnedDbnPtr<
sizeof...(AxisT)+1, AxisT...>;
35 template<
typename ... AxisT>
36 using BinnedEstimatePtr = std::shared_ptr<YODA::BinnedEstimate<AxisT...>>;
39 using ScatterNDPtr = std::shared_ptr<YODA::ScatterND<N>>;
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>;
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!");
68 for (
const std::string& a : src->annotations()) {
69 dst->setAnnotation(a, src->annotation(a));
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); }
79 struct TypeBaseHandle {
81 TypeBaseHandle() =
default;
83 virtual ~TypeBaseHandle() { }
85 virtual bool copyAO(YODA::AnalysisObjectPtr src,
86 YODA::AnalysisObjectPtr dst,
87 const double scale = 1.0)
const = 0;
89 virtual bool addAO(YODA::AnalysisObjectPtr src,
90 YODA::AnalysisObjectPtr& dst,
91 const double scale = 1.0)
const = 0;
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; }
113 else if (dst ==
nullptr) { dst = src;
return true; }
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);
139 using Fill = pair<typename T::FillType, Weight>;
163 class FillCollector<YODA::
Counter> :
public YODA::Counter {
166 using YAO = YODA::Counter;
167 using Ptr = shared_ptr<FillCollector<YAO>>;
168 using YAO::operator =;
170 FillCollector() : YAO() { }
185 int fill(
const double weight=1.0,
const double fraction = 1.0) {
187 _fills.insert(_fills.end(), { YAO::FillType(), weight } );
205 template <
size_t DbnN,
typename... AxisT>
206 class FillCollector<YODA::BinnedDbn<DbnN, AxisT...>>
207 :
public YODA::BinnedDbn<DbnN, AxisT...> {
210 using YAO = YODA::BinnedDbn<DbnN, AxisT...>;
211 using Ptr = shared_ptr<FillCollector<YAO>>;
212 using YAO::operator =;
214 FillCollector() : YAO() { }
225 YAO::setPath(yao->path());
232 int fill(
typename YAO::FillType&& fillCoords,
233 const double weight=1.0,
const double fraction=1.0) {
235 if (YODA::containsNan(fillCoords)) {
236 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
241 typename YAO::BinningT::EdgeTypesTuple binCoords{};
242 auto extractBinCoords = [&binCoords, &fillCoords](
auto I) {
243 std::get<I>(binCoords) = std::get<I>(fillCoords);
245 MetaUtils::staticFor<
sizeof...(AxisT)>(extractBinCoords);
246 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
247 return (
int)YAO::_binning.globalIndexAt(binCoords);
251 void reset() noexcept { _fills.clear(); }
262 template <
typename AxisT>
263 class FillCollector<YODA::BinnedDbn<1, AxisT>>
264 :
public YODA::BinnedDbn<1, AxisT> {
267 using YAO = YODA::BinnedDbn<1, AxisT>;
268 using Ptr = shared_ptr<FillCollector<YAO>>;
269 using YAO::operator =;
271 FillCollector() : YAO() { }
275 YAO::setPath(yao->path());
282 int fill(
typename YAO::FillType&& fillCoords,
283 const double weight=1.0,
const double fraction=1.0) {
285 if (YODA::containsNan(fillCoords)) {
286 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
291 typename YAO::BinningT::EdgeTypesTuple binCoords{};
292 auto extractBinCoords = [&binCoords, &fillCoords](
auto I) {
293 std::get<I>(binCoords) = std::get<I>(fillCoords);
295 MetaUtils::staticFor<1>(extractBinCoords);
296 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
297 return (
int)YAO::_binning.globalIndexAt(binCoords);
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);
305 void reset() noexcept { _fills.clear(); }
316 template <
typename AxisT1,
typename AxisT2>
317 class FillCollector<YODA::BinnedDbn<2, AxisT1, AxisT2>>
318 :
public YODA::BinnedDbn<2, AxisT1, AxisT2> {
321 using YAO = YODA::BinnedDbn<2, AxisT1, AxisT2>;
322 using Ptr = shared_ptr<FillCollector<YAO>>;
323 using YAO::operator =;
325 FillCollector() : YAO() { }
329 YAO::setPath(yao->path());
336 int fill(
typename YAO::FillType&& fillCoords,
337 const double weight=1.0,
const double fraction=1.0) {
339 if (YODA::containsNan(fillCoords)) {
340 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
345 typename YAO::BinningT::EdgeTypesTuple binCoords{};
346 auto extractBinCoords = [&binCoords, &fillCoords](
auto I) {
347 std::get<I>(binCoords) = std::get<I>(fillCoords);
349 MetaUtils::staticFor<1>(extractBinCoords);
350 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
351 return (
int)YAO::_binning.globalIndexAt(binCoords);
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);
359 void reset() noexcept { _fills.clear(); }
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> {
375 using YAO = YODA::BinnedDbn<3, AxisT1, AxisT2, AxisT3>;
376 using Ptr = shared_ptr<FillCollector<YAO>>;
377 using YAO::operator =;
379 FillCollector() : YAO() { }
383 YAO::setPath(yao->path());
390 int fill(
typename YAO::FillType&& fillCoords,
391 const double weight=1.0,
const double fraction=1.0) {
393 if (YODA::containsNan(fillCoords)) {
394 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
399 typename YAO::BinningT::EdgeTypesTuple binCoords{};
400 auto extractBinCoords = [&binCoords, &fillCoords](
auto I) {
401 std::get<I>(binCoords) = std::get<I>(fillCoords);
403 MetaUtils::staticFor<1>(extractBinCoords);
404 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
405 return (
int)YAO::_binning.globalIndexAt(binCoords);
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);
413 void reset() noexcept { _fills.clear(); }
424 template <
typename AxisT>
425 class FillCollector<YODA::BinnedDbn<2, AxisT>>
426 :
public YODA::BinnedDbn<2, AxisT> {
429 using YAO = YODA::BinnedDbn<2, AxisT>;
430 using Ptr = shared_ptr<FillCollector<YAO>>;
431 using YAO::operator =;
433 FillCollector() : YAO() { }
437 YAO::setPath(yao->path());
444 int fill(
typename YAO::FillType&& fillCoords,
445 const double weight=1.0,
const double fraction=1.0) {
447 if (YODA::containsNan(fillCoords)) {
448 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
453 typename YAO::BinningT::EdgeTypesTuple binCoords{};
454 auto extractBinCoords = [&binCoords, &fillCoords](
auto I) {
455 std::get<I>(binCoords) = std::get<I>(fillCoords);
457 MetaUtils::staticFor<1>(extractBinCoords);
458 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
459 return (
int)YAO::_binning.globalIndexAt(binCoords);
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);
467 void reset() noexcept { _fills.clear(); }
478 template <
typename AxisT1,
typename AxisT2>
479 class FillCollector<YODA::BinnedDbn<3, AxisT1, AxisT2>>
480 :
public YODA::BinnedDbn<3, AxisT1, AxisT2> {
483 using YAO = YODA::BinnedDbn<3, AxisT1, AxisT2>;
484 using Ptr = shared_ptr<FillCollector<YAO>>;
485 using YAO::operator =;
487 FillCollector() : YAO() { }
491 YAO::setPath(yao->path());
498 int fill(
typename YAO::FillType&& fillCoords,
499 const double weight=1.0,
const double fraction=1.0) {
501 if (YODA::containsNan(fillCoords)) {
502 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
507 typename YAO::BinningT::EdgeTypesTuple binCoords{};
508 auto extractBinCoords = [&binCoords, &fillCoords](
auto I) {
509 std::get<I>(binCoords) = std::get<I>(fillCoords);
511 MetaUtils::staticFor<1>(extractBinCoords);
512 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
513 return (
int)YAO::_binning.globalIndexAt(binCoords);
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);
521 void reset() noexcept { _fills.clear(); }
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> {
537 using YAO = YODA::BinnedDbn<4, AxisT1, AxisT2, AxisT3>;
538 using Ptr = shared_ptr<FillCollector<YAO>>;
539 using YAO::operator =;
541 FillCollector() : YAO() { }
545 YAO::setPath(yao->path());
552 int fill(
typename YAO::FillType&& fillCoords,
553 const double weight=1.0,
const double fraction=1.0) {
555 if (YODA::containsNan(fillCoords)) {
556 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
561 typename YAO::BinningT::EdgeTypesTuple binCoords{};
562 auto extractBinCoords = [&binCoords, &fillCoords](
auto I) {
563 std::get<I>(binCoords) = std::get<I>(fillCoords);
565 MetaUtils::staticFor<1>(extractBinCoords);
566 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
567 return (
int)YAO::_binning.globalIndexAt(binCoords);
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);
575 void reset() noexcept { _fills.clear(); }
589 class FillCollector<YODA::
Estimate0D> :
public YODA::Estimate0D {
592 using YAO = YODA::Estimate0D;
593 using Ptr = shared_ptr<FillCollector<YAO>>;
594 using YAO::operator =;
596 FillCollector() : YAO() { }
610 template<
typename ... AxisT>
611 class FillCollector<YODA::BinnedEstimate<AxisT...>>
612 :
public YODA::BinnedEstimate<AxisT...> {
615 using YAO = YODA::BinnedEstimate<AxisT...>;
616 using Ptr = shared_ptr<FillCollector<YAO>>;
617 using YAO::operator =;
619 FillCollector() : YAO() { }
634 class FillCollector<YODA::ScatterND<N>> :
public YODA::ScatterND<N> {
637 using YAO = YODA::ScatterND<N>;
638 using Ptr = shared_ptr<FillCollector<YAO>>;
639 using YAO::operator =;
641 FillCollector() : YAO() { }
659 template<
typename... Args>
660 double distance(
const std::tuple<Args...>& a,
const std::tuple<Args...>& b) {
662 auto calculateDistance = [&](
auto I) {
663 if constexpr (std::is_floating_point<std::tuple_element_t<I,
664 std::tuple<Args...>>>::value) {
665 rtn +=
Rivet::sqr(std::get<I>(a) - std::get<I>(b));
668 MetaUtils::staticFor<
sizeof...(Args)>(calculateDistance);
675 struct SubwindowType;
677 template<
typename... Args>
678 struct SubwindowType<std::tuple<Args...>> {
679 using type = YODA::Binning<std::decay_t<
decltype(std::declval<YODA::Axis<Args>>())>...>;
686 template<
typename... Args>
687 struct WindowType<std::tuple<Args...>> {
688 using type = std::tuple<std::decay_t<
decltype(std::declval<vector<Args>>())>...>;
698 template<
typename YAO>
699 vector<std::tuple<typename YAO::FillType, std::valarray<double>,
double>>
701 const vector<std::valarray<double>>& weights,
const double fsmear=-1.0) {
704 vector<std::tuple<typename YAO::FillType, std::valarray<double>,
double>> rtn;
706 using WindowT =
typename WindowType<typename YAO::FillType>::type;
707 using SubwindowT =
typename SubwindowType<typename YAO::FillType>::type;
708 SubwindowT subwindows;
712 const size_t nSubevents = subevents.size();
713 for (
size_t sidx=0; sidx < nSubevents; ++sidx) {
714 const size_t nFills = subevents[sidx]->fills().size();
715 if (nFills == 0)
continue;
716 fidx = std::max(fidx, nFills);
723 auto constructWindows = [&](
auto I) {
725 using FillAxisT =
typename SubwindowT::template getAxisT<I>;
726 using isContinuous =
typename SubwindowT::template is_CAxis<I>;
727 using EdgeT =
typename FillAxisT::EdgeT;
729 if constexpr(!isContinuous::value) {
730 vector<EdgeT> edges; edges.resize(nSubevents);
731 for (
const auto& subevt : subevents) {
732 if (fidx >= subevt->fills().size())
continue;
733 edges.push_back( std::get<I>(subevt->fills()[fidx].first) );
735 subwindows.template axis<I>() = FillAxisT(edges);
736 std::get<I>(windows) = std::move(edges);
740 vector<EdgeT>& edges = std::get<I>(windows);
741 edges.reserve(2*nSubevents);
743 if constexpr(I < YAO::BinningT::Dimension::value) {
745 const auto& axis = subevents[0]->binning().template axis<I>();
746 size_t over = 0, under = 0;
747 const EdgeT edgeMax = subevents[0]->template
max<I>();
748 const EdgeT edgeMin = subevents[0]->template
min<I>();
749 const size_t binLast = axis.numBins();
751 for (
const auto& subevt : subevents) {
752 if (fidx >= subevt->fills().size())
continue;
753 const EdgeT coord = std::get<I>(subevt->fills()[fidx].first);
754 size_t idx = axis.index(coord);
755 if (coord >= edgeMax) {
756 if (coord > edgeMax) ++over;
759 else if (coord < edgeMin) {
765 if (coord > axis.mid(idx)) {
766 if (idx != binLast) ++ibn;
774 const EdgeT ibw = axis.width(idx) < axis.width(ibn)? idx : ibn;
775 if ( fsmear > 0.0 ) {
776 const EdgeT delta = 0.5*fsmear*axis.width(ibw);
781 const EdgeT delta = 0.5*axis.width(ibw);
782 if (coord > edgeMax) {
783 lo =
max(edgeMax, coord - delta);
784 hi =
max(edgeMax + 2*delta, coord + delta);
786 else if (coord < edgeMin) {
787 lo =
min(edgeMin - 2*delta, coord - delta);
788 hi =
min(edgeMin, coord + delta);
798 for (
size_t i = 0; i < edges.size(); i+=2) {
799 const EdgeT wsize = edges[i+1] - edges[i];
800 if (over == nSubevents && edges[i] < edgeMax && edges[i+1] > edgeMax) {
802 edges[i+1] = edgeMax + wsize;
804 else if (over == 0 && edges[i] < edgeMax && edges[i+1] > edgeMax) {
805 edges[i] = edgeMax - wsize;
806 edges[i+1] = edgeMax;
808 else if (under == nSubevents && edges[i] < edgeMin && edges[i+1] > edgeMin) {
809 edges[i] = edgeMin - wsize;
810 edges[i+1] = edgeMin;
812 else if (under == 0 && edges[i] < edgeMin && edges[i+1] > edgeMin) {
814 edges[i+1] = edgeMin + wsize;
820 for (
const auto& subevt : subevents) {
821 if (fidx >= subevt->fills().size())
continue;
826 const EdgeT coord = std::get<I>(subevt->fills()[fidx].first);
827 const EdgeT delta = 0.1*std::abs(coord);
828 edges.push_back(coord - delta);
829 edges.push_back(coord + delta);
833 vector<EdgeT> subwindowEdges = edges;
834 std::sort(subwindowEdges.begin(), subwindowEdges.end());
835 subwindowEdges.erase( std::unique(subwindowEdges.begin(), subwindowEdges.end()), subwindowEdges.end() );
836 subwindows.template axis<I>() = FillAxisT(std::move(subwindowEdges));
840 MetaUtils::staticFor<YAO::FillDimension::value>(constructWindows);
844 const vector<size_t> overflows = subwindows.calcOverflowBinsIndices();
845 const auto& itEnd = overflows.cend();
846 size_t nSubwindows = subwindows.numBins();
847 for (
size_t i = 0; i < nSubwindows; ++i) {
848 if (std::find(overflows.cbegin(), itEnd, i) != itEnd)
continue;
850 const auto coords = subwindows.edgeTuple(i);
851 const double subwindowArea = subwindows.dVol(i);
852 size_t nSubfills = 0;
853 double windowFrac = 0.;
854 std::valarray<double> sumw(0.0, weights[0].size());
855 for (
size_t sidx=0, eidx=0; sidx < nSubevents; ++sidx) {
856 if (fidx >= subevents[sidx]->fills().size())
continue;
858 double windowArea = 1.0;
859 auto checkSubwindowOverlap = [&](
auto I) {
860 using isContinuous =
typename SubwindowT::template is_CAxis<I>;
861 using EdgeT =
typename SubwindowT::template getAxisT<I>::EdgeT;
862 const EdgeT coord = std::get<I>(coords);
863 const vector<EdgeT>& edges = std::get<I>(windows);
864 if constexpr (isContinuous::value) {
865 pass &= (edges[2*eidx] <= coord && coord <= edges[2*eidx+1]);
866 windowArea *= edges[2*eidx+1] - edges[2*eidx];
869 pass &= (coord == edges[eidx]);
872 MetaUtils::staticFor<YAO::FillDimension::value>(checkSubwindowOverlap);
874 windowFrac = subwindowArea/windowArea;
875 sumw += subevents[sidx]->fills()[fidx].second * weights[sidx];
881 const double fillFrac = (double)nSubfills/(
double)nSubevents;
882 rtn.emplace_back(coords, sumw/fillFrac, fillFrac*windowFrac);
914 virtual void collapseEventGroup(
const vector<std::valarray<double>>& weight,
const double nlowfrac=-1.0) = 0;
920 virtual YODA::AnalysisObjectPtr
activeAO()
const = 0;
952 const vector<bool>& fillOutcomes()
const {
return _fillOutcomes; }
954 const vector<double>& fillFractions()
const {
return _fillFractions; }
958 vector<bool> _fillOutcomes;
960 vector<double> _fillFractions;
986 friend class Analysis;
991 using MultiplexedAO::_fillOutcomes;
992 using MultiplexedAO::_fillFractions;
994 Multiplexer() =
default;
996 Multiplexer(
const vector<string>& weightNames,
const T&
p) {
997 _basePath =
p.path();
998 _baseName =
p.name();
999 for (
const string& weightname : weightNames) {
1000 _persistent.push_back(make_shared<T>(
p));
1001 _final.push_back(make_shared<T>(
p));
1003 typename T::Ptr obj = _persistent.back();
1004 obj->setPath(
"/RAW" + obj->path());
1005 typename T::Ptr
final = _final.back();
1006 if (weightname !=
"") {
1007 obj->setPath(obj->path() +
"[" + weightname +
"]");
1008 final->setPath(
final->path() +
"[" + weightname +
"]");
1019 #ifdef HAVE_BACKTRACE
1021 backtrace(buffer, 4);
1022 backtrace_symbols_fd(buffer, 4 , 1);
1024 assert(
false &&
"No active pointer set. Was this object booked in init()?");
1029 template <
typename U = T>
1030 auto binning() const ->
std::enable_if_t<hasBinning<T>::value, const typename U::BinningT&> {
1031 return _persistent.back()->binning();
1044 explicit operator bool()
const {
return static_cast<bool>(_active); }
1067 if (a._persistent.size() != b._persistent.size()) {
1071 for (
size_t i = 0; i < a._persistent.size(); ++i) {
1072 if (a._persistent.at(i) != b._persistent.at(i)) {
1080 friend bool operator != (
const Multiplexer& a,
const Multiplexer& b) {
1085 friend bool operator < (
const Multiplexer a,
const Multiplexer& b) {
1086 if (a._persistent.size() >= b._persistent.size()) {
1089 for (
size_t i = 0; i < a._persistent.size(); ++i) {
1090 if (*(a._persistent.at(i)) >= *(b._persistent.at(i))) {
1105 _active = _persistent.at(iWeight);
1110 _active = _final.at(iWeight);
1127 _active = _evgroup.back();
1135 if constexpr( isFillable<T>::value ) {
1138 assert( _evgroup.size() == weights.size() );
1140 if (_evgroup.size() == 1) {
1144 std::fill(_fillOutcomes.begin(), _fillOutcomes.end(),
false);
1145 std::fill(_fillFractions.begin(), _fillFractions.end(), 0.0);
1149 for (
auto f : _evgroup[0]->fills()) {
1152 for (
size_t m = 0; m < _persistent.size(); ++m) {
1153 if (!m) frac = f.second;
1154 pos = _persistent[m]->fill( std::move(f.first), std::move(f.second) * weights[0][m] );
1157 _fillOutcomes[pos] =
true;
1158 _fillFractions[pos] += frac;
1175 if (_evgroup.empty())
return;
1176 if constexpr( isFillable<T>::value ) {
1177 if constexpr (!std::is_same<T, YODA::Counter>::value ) {
1178 for (
auto&& fw : mkFillWindows<T>(_evgroup, _persistent[0]->path(), weights, nlowfrac)) {
1179 for (
size_t m = 0; m < _persistent.size(); ++m ) {
1180 _persistent[m]->fill(
typename T::FillType(std::move(std::get<0>(fw))),
1181 std::move(std::get<1>(fw)[m]),
1182 std::move(std::get<2>(fw)) );
1187 for (
size_t m = 0; m < _persistent.size(); ++m) {
1188 vector<double> sumfw{0.0};
1189 for (
size_t n = 0; n < _evgroup.size(); ++n) {
1190 const auto& fills = _evgroup[n]->fills();
1193 if (fills.size() > sumfw.size()) {
1194 sumfw.resize(fills.size(), 0.0);
1197 for (
const auto& f : fills) {
1198 sumfw[fi++] += f.second * weights[n][m];
1201 for (
double fw : sumfw) {
1202 _persistent[m]->fill(std::move(fw));
1212 for (
size_t m = 0; m < _persistent.size(); ++m ) {
1213 _final.at(m)->clearAnnotations();
1214 copyAO<T>(_persistent.at(m), _final.at(m));
1216 if ( _final[m]->path().substr(0,4) ==
"/RAW" )
1217 _final[m]->setPath(_final[m]->path().substr(4));
1228 typename T::Ptr
persistent(
const size_t iWeight) {
return _persistent.at(iWeight); }
1232 const vector<typename T::Ptr>&
final()
const {
1237 typename T::Ptr
final(
const size_t iWeight) {
return _final.at(iWeight); }
1240 YODA::AnalysisObjectPtr
activeAO()
const {
return _active; }
1244 if constexpr( isFillable<T>::value ) {
1246 if constexpr (!std::is_same<T, YODA::Counter>::value ) {
1247 nPos = _persistent.back()->numBins(
true,
true);
1249 _fillOutcomes.resize(nPos);
1250 _fillFractions.resize(nPos);
1262 vector<typename T::Ptr> _persistent;
1265 vector<typename T::Ptr> _final;
1268 vector<typename FillCollector<T>::Ptr> _evgroup;
1272 typename T::Ptr _active;
1295 template <
typename T>
1296 class MultiplexPtr {
1300 using value_type = T;
1302 MultiplexPtr() =
default;
1304 MultiplexPtr(
decltype(
nullptr)) : _p(
nullptr) { }
1308 : _p( make_shared<T>(weightNames,
p) ) { }
1311 template <typename U, typename = decltype(shared_ptr<T>(shared_ptr<U>{}))>
1312 MultiplexPtr(
const shared_ptr<U>&
p) : _p(
p) { }
1315 template <typename U, typename = decltype(shared_ptr<T>(shared_ptr<U>{}))>
1316 MultiplexPtr(
const MultiplexPtr<U>&
p) : _p(
p.
get()) { }
1320 if (_p ==
nullptr) {
1321 throw Error(
"Dereferencing null AnalysisObject pointer. Is there an unbooked histogram variable?");
1326 template <
typename U = T>
1327 auto binning() const ->
std::enable_if_t<hasBinning<typename T::Inner>::value, const typename U::Inner::BinningT&> {
1328 if (_p ==
nullptr) {
1329 throw Error(
"Dereferencing null AnalysisObject pointer. Is there an unbooked histogram variable?");
1331 return _p->binning();
1337 if (_p ==
nullptr) {
1338 throw Error(
"Dereferencing null AnalysisObject pointer. Is there an unbooked histogram variable?");
1345 const typename T::Inner&
operator * ()
const {
return **_p; }
1348 explicit operator bool()
const {
return _p && bool(*_p); }
1355 return _p == other._p;
1360 return _p != other._p;
1365 return _p < other._p;
1370 return _p > other._p;
1375 return _p <= other._p;
1380 return _p >= other._p;
1384 shared_ptr<T>
get()
const {
return _p; }
1403 using MultiplexAOPtr = MultiplexPtr<MultiplexedAO>;
1405 template<
size_t DbnN,
typename... AxisT>
1406 using BinnedDbnPtr = MultiplexPtr<Multiplexer<YODA::BinnedDbn<DbnN, AxisT...>>>;
1408 template<
typename... AxisT>
1409 using BinnedHistoPtr = BinnedDbnPtr<
sizeof...(AxisT), AxisT...>;
1411 template<
typename... AxisT>
1412 using BinnedProfilePtr = BinnedDbnPtr<
sizeof...(AxisT)+1, AxisT...>;
1414 template<
typename... AxisT>
1415 using BinnedEstimatePtr = MultiplexPtr<Multiplexer<YODA::BinnedEstimate<AxisT...>>>;
1418 using ScatterNDPtr = MultiplexPtr<Multiplexer<YODA::ScatterND<N>>>;
1420 using CounterPtr = MultiplexPtr<Multiplexer<YODA::Counter>>;
1421 using Estimate0DPtr = MultiplexPtr<Multiplexer<YODA::Estimate0D>>;
1422 using Histo1DPtr = BinnedHistoPtr<double>;
1423 using Histo2DPtr = BinnedHistoPtr<double,double>;
1424 using Histo3DPtr = BinnedHistoPtr<double,double,double>;
1425 using Profile1DPtr = BinnedProfilePtr<double>;
1426 using Profile2DPtr = BinnedProfilePtr<double,double>;
1427 using Profile3DPtr = BinnedProfilePtr<double,double,double>;
1428 using Estimate1DPtr = BinnedEstimatePtr<double>;
1429 using Estimate2DPtr = BinnedEstimatePtr<double,double>;
1430 using Estimate3DPtr = BinnedEstimatePtr<double,double,double>;
1431 using Scatter1DPtr = ScatterNDPtr<1>;
1432 using Scatter2DPtr = ScatterNDPtr<2>;
1433 using Scatter3DPtr = ScatterNDPtr<3>;
1435 using YODA::Counter;
1436 using YODA::Estimate0D;
1437 using YODA::Histo1D;
1438 using YODA::Histo2D;
1439 using YODA::Histo3D;
1440 using YODA::Profile1D;
1441 using YODA::Profile2D;
1442 using YODA::Profile3D;
1443 using YODA::Estimate1D;
1444 using YODA::Estimate2D;
1445 using YODA::Estimate3D;
1446 using YODA::Scatter1D;
1447 using YODA::Scatter2D;
1448 using YODA::Scatter3D;
1449 using YODA::Point1D;
1450 using YODA::Point2D;
1451 using YODA::Point3D;
1459 inline bool isTmpPath(
const std::string& path,
const bool tmp_only =
false) {
1460 if (tmp_only)
return path.find(
"/TMP/") != string::npos;
1461 return path.find(
"/TMP/") != string::npos || path.find(
"/_") != string::npos;
1466 map<string, YODA::AnalysisObjectPtr>
getRefData(
const string& papername);
1476 template<
typename T>
1477 struct ReferenceTraits { };
1480 struct ReferenceTraits<YODA::
Counter> {
1481 using RefT = YODA::Estimate0D;
1486 using RefT = YODA::Estimate0D;
1489 template<
typename... AxisT>
1490 struct ReferenceTraits<YODA::BinnedEstimate<AxisT...>> {
1491 using RefT = YODA::BinnedEstimate<AxisT...>;
1494 template<
size_t DbnN,
typename... AxisT>
1495 struct ReferenceTraits<YODA::BinnedDbn<DbnN, AxisT...>> {
1496 using RefT = YODA::ScatterND<
sizeof...(AxisT)+1>;
1500 struct ReferenceTraits<YODA::ScatterND<N>> {
1501 using RefT = YODA::ScatterND<N>;
1506 template <
typename TPtr>
1529 return a->numPoints() == b->numPoints();
1533 inline bool bookingCompatible(YODA::ScatterNDPtr<N> a, YODA::ScatterNDPtr<N> b) {
1534 return a->numPoints() == b->numPoints();
1537 inline bool beamInfoCompatible(YODA::AnalysisObjectPtr a, YODA::AnalysisObjectPtr b) {
1538 YODA::BinnedEstimatePtr<string> beamsA = std::dynamic_pointer_cast<YODA::BinnedEstimate<string>>(a);
1539 YODA::BinnedEstimatePtr<string> beamsB = std::dynamic_pointer_cast<YODA::BinnedEstimate<string>>(b);
1540 return beamsA && beamsB && (*beamsA == *beamsB) && beamsA->numBins() == 2 &&
1541 fuzzyEquals(beamsA->bin(1).val(), beamsB->bin(1).val()) &&
1542 fuzzyEquals(beamsA->bin(2).val(), beamsB->bin(2).val());
1554 AOPath(
string fullpath)
1555 : _valid(false), _path(fullpath), _raw(false), _tmp(false), _ref(false) {
1556 _valid = init(fullpath);
1560 string path()
const {
return _path; }
1563 string analysis()
const {
return _analysis; }
1566 string analysisWithOptions()
const {
return _analysis + _optionstring; }
1569 string name()
const {
return _name; }
1572 string weight()
const {
return _weight; }
1575 string weightComponent()
const {
1576 if (_weight ==
"")
return _weight;
1577 return "[" + _weight +
"]";
1581 bool isRaw()
const {
return _raw; }
1584 bool isTmp()
const {
return _tmp; }
1587 bool isRef()
const {
return _ref; }
1590 string optionString()
const {
return _optionstring; }
1593 bool hasOptions()
const {
return !_options.empty(); }
1596 void removeOption(
string opt) { _options.erase(opt); fixOptionString(); }
1599 void setOption(
string opt,
string val) { _options[opt] = val; fixOptionString(); }
1602 bool hasOption(
string opt)
const {
return _options.find(opt) != _options.end(); }
1605 string getOption(
string opt)
const {
1606 auto it = _options.find(opt);
1607 if ( it != _options.end() )
return it->second;
1612 void fixOptionString();
1615 string mkPath()
const;
1616 string setPath() {
return _path = mkPath(); }
1622 bool operator<(
const AOPath & other)
const {
1623 return _path < other._path;
1627 bool valid()
const {
return _valid; };
1628 bool operator!()
const {
return !valid(); }
1633 bool init(
string fullpath);
1634 bool chopweight(
string & fullpath);
1635 bool chopoptions(
string & anal);
1640 string _optionstring;
1646 map<string,string> _options;
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:274
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:308
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:305
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:282
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:359
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:328
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:336
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:362
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:467
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:470
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:444
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:436
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:413
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:382
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:416
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:390
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:524
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:490
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:521
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:498
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:552
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:578
FillCollector(typename YAO::Ptr yao)
Constructor.
Definition RivetYODA.hh:544
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:575
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:251
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:224
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:254
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:232
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:628
int fill(const double weight=1.0, const double fraction=1.0)
Definition RivetYODA.hh:185
void reset()
Empty the subevent stack (for start of new event group).
Definition RivetYODA.hh:192
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition RivetYODA.hh:195
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:179
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:605
FillCollector(typename YAO::Ptr yao)
Definition RivetYODA.hh:650
FillCollectors which are used to temporarily cache unaggregated fills until collapsed by the Multiple...
Definition RivetYODA.hh:158
T & operator->()
Goes right through to the active Multiplexer<YODA> object's members.
Definition RivetYODA.hh:1319
bool operator>(const MultiplexPtr other) const
Greater-than for ptr ordering.
Definition RivetYODA.hh:1369
shared_ptr< T > get() const
Get the internal shared ptr.
Definition RivetYODA.hh:1384
T::Inner & operator*()
The active YODA object.
Definition RivetYODA.hh:1344
bool operator<(const MultiplexPtr &other) const
Less-than for ptr ordering.
Definition RivetYODA.hh:1364
MultiplexPtr(const vector< string > &weightNames, const typename T::Inner &p)
Convenience constructor, pass through to the Multiplexer constructor.
Definition RivetYODA.hh:1307
bool operator!() const
Object invalidity check.
Definition RivetYODA.hh:1351
bool operator<=(const MultiplexPtr &other) const
Less-equals for ptr ordering.
Definition RivetYODA.hh:1374
bool operator!=(const MultiplexPtr &other) const
Object invalidity check.
Definition RivetYODA.hh:1359
bool operator==(const MultiplexPtr &other) const
Object validity check.
Definition RivetYODA.hh:1354
bool operator>=(const MultiplexPtr &other) const
Greater-equals for ptr ordering.
Definition RivetYODA.hh:1379
Multiplexer base class.
Definition RivetYODA.hh:902
virtual string basePath() const =0
The histogram path, without a variation suffix.
virtual YODA::AnalysisObject * operator->()=0
Access the active analysis object for function calls.
virtual void unsetActiveWeight()=0
Unset the active-object pointer.
bool operator==(const MultiplexedAO &p)
Test for equality.
Definition RivetYODA.hh:947
virtual void pushToFinal()=0
Sync the persistent histograms to the final collection.
virtual YODA::AnalysisObjectPtr activeAO() const =0
A shared pointer to the active YODA AO.
virtual void newSubEvent()=0
Add a new layer of subevent fill staging.
YODA::AnalysisObject Inner
The type being represented is a generic AO.
Definition RivetYODA.hh:908
bool operator!=(const MultiplexedAO &p)
Test for inequality.
Definition RivetYODA.hh:950
virtual const YODA::AnalysisObject & operator*() const =0
Access the active analysis object as a reference.
virtual void collapseEventGroup(const vector< std::valarray< double > > &weight, const double nlowfrac=-1.0)=0
Sync the fill proxies to the persistent histogram.
virtual void initBootstrap()=0
Set the size of the bootstrap vectors.
virtual void setActiveWeightIdx(size_t iWeight)=0
Set active object for analyze.
virtual void setActiveFinalWeightIdx(size_t iWeight)=0
Set active object for finalize.
Type-specific multiplexed YODA analysis object.
Definition RivetYODA.hh:982
void initBootstrap()
Helper method to resize aux vectors to AO size.
Definition RivetYODA.hh:1243
friend bool operator<(const Multiplexer a, const Multiplexer &b)
Less-than operator.
Definition RivetYODA.hh:1085
string baseName() const
Get the AO name of the object, without variation suffix.
Definition RivetYODA.hh:1038
T & operator*()
Forwarding dereference operator.
Definition RivetYODA.hh:1059
void newSubEvent()
Create a new FillCollector for the next sub-event.
Definition RivetYODA.hh:1125
void collapseEventGroup(const vector< std::valarray< double > > &weights, const double nlowfrac=-1.0)
Pushes the (possibly collapsed) fill(s) into the persistent objects.
Definition RivetYODA.hh:1132
void pushToFinal()
Definition RivetYODA.hh:1211
void reset()
Clear the active object pointer.
Definition RivetYODA.hh:1117
T::Ptr active() const
Definition RivetYODA.hh:1017
const vector< typename T::Ptr > & final() const
Definition RivetYODA.hh:1232
bool operator!() const
Definition RivetYODA.hh:1049
string basePath() const
Get the AO path of the object, without variation suffix.
Definition RivetYODA.hh:1035
friend bool operator!=(const Multiplexer &a, const Multiplexer &b)
Inequality operator.
Definition RivetYODA.hh:1080
friend bool operator==(const Multiplexer &a, const Multiplexer &b)
Equality operator.
Definition RivetYODA.hh:1066
void setActiveFinalWeightIdx(size_t iWeight)
Set the active-object pointer to point at a variation in the final set.
Definition RivetYODA.hh:1109
void unsetActiveWeight()
Unset the active-object pointer.
Definition RivetYODA.hh:1114
void collapseSubevents(const vector< std::valarray< double > > &weights, const double nlowfrac)
Definition RivetYODA.hh:1174
const vector< typename T::Ptr > & persistent() const
Definition RivetYODA.hh:1223
T::Ptr persistent(const size_t iWeight)
Direct access to the persistent object in weight stream iWeight.
Definition RivetYODA.hh:1228
void setActiveWeightIdx(size_t iWeight)
Set the active-object pointer to point at a variation in the persistent set.
Definition RivetYODA.hh:1104
T * operator->()
Forwarding dereference-call operator.
Definition RivetYODA.hh:1053
YODA::AnalysisObjectPtr activeAO() const
Get the currently active analysis object.
Definition RivetYODA.hh:1240
T Inner
Typedef for the YODA type being represented.
Definition RivetYODA.hh:990
vector< Fill< T > > Fills
A collection of several Fill objects.
Definition RivetYODA.hh:143
double Weight
Typedef for weights.
Definition RivetYODA.hh:135
pair< typename T::FillType, Weight > Fill
A single fill is a (FillType, Weight) pair.
Definition RivetYODA.hh:139
map< string, YODA::AnalysisObjectPtr > getRefData(const string &papername)
bool bookingCompatible(TPtr a, TPtr b)
Definition RivetYODA.hh:1507
string getDatafilePath(const string &papername)
Get the file system path to the reference file for this paper.
double p(const ParticleBase &p)
Unbound function access to p.
Definition ParticleBaseUtils.hh:653
Definition MC_CENT_PPB_Projections.hh:10
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 >, signed_if_mixed_t< N1, N2 > > max(N1 a, N2 b)
Get the maximum of two numbers.
Definition MathUtils.hh:115
std::enable_if_t< std::is_arithmetic_v< NUM >, NUM > sqr(NUM a)
Named number-type squaring operation.
Definition MathUtils.hh:218
bool copyAO(YODA::AnalysisObjectPtr src, YODA::AnalysisObjectPtr dst, const double scale=1.0)
Definition RivetYODA.hh:64
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 >, signed_if_mixed_t< N1, N2 > > min(N1 a, N2 b)
Get the minimum of two numbers.
Definition MathUtils.hh:104
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 > &&(std::is_floating_point_v< N1 >||std::is_floating_point_v< N2 >), bool > fuzzyEquals(N1 a, N2 b, double tolerance=1e-5)
Compare two numbers for equality with a degree of fuzziness.
Definition MathUtils.hh:61
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