File indexing completed on 2025-09-16 09:07:59
0001
0002 #ifndef RIVET_Analysis_HH
0003 #define RIVET_Analysis_HH
0004
0005 #include "Rivet/Config/RivetCommon.hh"
0006 #include "Rivet/AnalysisInfo.hh"
0007 #include "Rivet/Event.hh"
0008 #include "Rivet/Projection.hh"
0009 #include "Rivet/ProjectionApplier.hh"
0010 #include "Rivet/ProjectionHandler.hh"
0011 #include "Rivet/AnalysisLoader.hh"
0012 #include "Rivet/Tools/Cuts.hh"
0013 #include "Rivet/Tools/Logging.hh"
0014 #include "Rivet/Tools/ParticleUtils.hh"
0015 #ifdef HAVE_H5
0016 #include "Rivet/Tools/RivetHDF5.hh"
0017 #endif
0018 #include "Rivet/Tools/HistoGroup.hh"
0019 #include "Rivet/Tools/RivetMT2.hh"
0020 #include "Rivet/Tools/RivetPaths.hh"
0021 #include "Rivet/Tools/RivetYODA.hh"
0022 #include "Rivet/Tools/Percentile.hh"
0023 #include "Rivet/Tools/Cutflow.hh"
0024 #include "Rivet/Projections/CentralityProjection.hh"
0025 #include "Rivet/Projections/FastJets.hh"
0026 #include <tuple>
0027
0028
0029
0030
0031 #define vetoEvent \
0032 do { MSG_DEBUG("Vetoing event on line " << __LINE__ << " of " << __FILE__); return; } while(0)
0033
0034
0035 namespace Rivet {
0036
0037
0038
0039 using std::cout;
0040 using std::cerr;
0041 using std::endl;
0042 using std::tuple;
0043 using std::stringstream;
0044 using std::swap;
0045 using std::numeric_limits;
0046
0047
0048
0049 class AnalysisHandler;
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070 class Analysis : public ProjectionApplier {
0071 public:
0072
0073
0074 friend class AnalysisHandler;
0075
0076
0077
0078 Analysis(const std::string& name);
0079
0080
0081 virtual ~Analysis() {}
0082
0083
0084 Analysis& operator = (const Analysis&) = delete;
0085
0086
0087 public:
0088
0089
0090
0091
0092
0093
0094
0095 virtual void init() { }
0096
0097
0098
0099
0100
0101 virtual void analyze(const Event& event) = 0;
0102
0103
0104
0105
0106
0107
0108 virtual void finalize() { }
0109
0110
0111
0112
0113
0114
0115
0116
0117 virtual void preInit() { }
0118
0119 virtual void postInit() { }
0120
0121 virtual void preAnalyze(const Event&) { }
0122
0123 virtual void postAnalyze(const Event&) { }
0124
0125 virtual void preFinalize() { }
0126
0127 virtual void postFinalize() { }
0128
0129
0130
0131
0132 void syncDeclQueue() {
0133 this->_syncDeclQueue();
0134 this->markAsOwned();
0135 }
0136
0137
0138
0139
0140 public:
0141
0142
0143
0144
0145
0146
0147
0148
0149 void loadInfo() { info().parseInfoFile(); }
0150
0151
0152 const AnalysisInfo& info() const {
0153 if (!_info) throw Error("No AnalysisInfo object :-O");
0154 return *_info;
0155 }
0156
0157
0158
0159
0160
0161
0162
0163
0164 virtual std::string name() const {
0165 return ( (info().name().empty()) ? _defaultname : info().name() ) + _optstring;
0166 }
0167
0168
0169
0170
0171
0172 std::string analysisDataPath(const std::string& extn, const std::string& suffix="") {
0173 string filename = name() + (suffix.empty() ? "" : "-") + suffix + "." + extn;
0174 return findAnalysisDataFile(filename);
0175 }
0176
0177
0178 virtual std::string inspireID() const {
0179 return info().inspireID();
0180 }
0181
0182
0183 virtual std::string spiresID() const {
0184 return info().spiresID();
0185 }
0186
0187
0188
0189
0190
0191 virtual std::vector<std::string> authors() const {
0192 return info().authors();
0193 }
0194
0195
0196
0197
0198
0199
0200 virtual std::string summary() const {
0201 return info().summary();
0202 }
0203
0204
0205
0206
0207
0208
0209
0210 virtual std::string description() const {
0211 return info().description();
0212 }
0213
0214
0215
0216
0217
0218
0219 virtual std::string runInfo() const {
0220 return info().runInfo();
0221 }
0222
0223
0224 virtual std::string experiment() const {
0225 return info().experiment();
0226 }
0227
0228
0229 virtual std::string collider() const {
0230 return info().collider();
0231 }
0232
0233
0234 virtual std::string year() const {
0235 return info().year();
0236 }
0237
0238
0239 virtual double luminosityfb() const {
0240 return info().luminosityfb();
0241 }
0242
0243 virtual double luminosity() const {
0244 return info().luminosity();
0245 }
0246
0247 double luminositypb() const { return luminosity(); }
0248
0249
0250 virtual std::vector<std::string> references() const {
0251 return info().references();
0252 }
0253
0254
0255 virtual std::string bibKey() const {
0256 return info().bibKey();
0257 }
0258
0259
0260 virtual std::string bibTeX() const {
0261 return info().bibTeX();
0262 }
0263
0264
0265 virtual std::string status() const {
0266 return (info().status().empty()) ? "UNVALIDATED" : info().status();
0267 }
0268
0269
0270 virtual std::string warning() const {
0271 return info().warning();
0272 }
0273
0274
0275 virtual std::vector<std::string> todos() const {
0276 return info().todos();
0277 }
0278
0279
0280 virtual std::vector<std::string> validation() const {
0281 return info().validation();
0282 }
0283
0284
0285 virtual bool reentrant() const {
0286 return info().reentrant();
0287 }
0288
0289
0290 virtual const std::vector<std::string>& keywords() const {
0291 return info().keywords();
0292 }
0293
0294
0295 virtual std::string refMatch() const {
0296 return info().refMatch();
0297 }
0298
0299
0300 virtual std::string refUnmatch() const {
0301 return info().refUnmatch();
0302 }
0303
0304
0305 virtual std::string writerDoublePrecision() const {
0306 return info().writerDoublePrecision();
0307 }
0308
0309
0310 virtual const std::vector<PdgIdPair>& requiredBeamIDs() const {
0311 return info().beamIDs();
0312 }
0313
0314 virtual Analysis& setRequiredBeamIDs(const std::vector<PdgIdPair>& beamids) {
0315 info().setBeamIDs(beamids);
0316 return *this;
0317 }
0318
0319
0320 virtual const std::vector<std::pair<double, double> >& requiredBeamEnergies() const {
0321 return info().energies();
0322 }
0323
0324 virtual Analysis& setRequiredBeamEnergies(const std::vector<std::pair<double, double> >& energies) {
0325 info().setEnergies(energies);
0326 return *this;
0327 }
0328
0329
0330
0331 virtual std::string refFile() const {
0332 return info().refFile();
0333 }
0334
0335 virtual std::string refDataName() const {
0336 return (info().getRefDataName().empty()) ? _defaultname : info().getRefDataName();
0337 }
0338
0339 virtual void setRefDataName(const std::string& ref_data="") {
0340 info().setRefDataName(!ref_data.empty() ? ref_data : name());
0341 }
0342
0343
0344
0345
0346
0347 AnalysisInfo& info() {
0348 if (!_info) throw Error("No AnalysisInfo object :-O");
0349 return *_info;
0350 }
0351
0352
0353
0354
0355
0356
0357
0358
0359 bool merging() const {
0360 return sqrtS() <= 0.0;
0361 }
0362
0363
0364 bool compatibleWithRun() const;
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374 const ParticlePair& beams() const;
0375
0376
0377 PdgIdPair beamIDs() const;
0378
0379
0380 pair<double,double> beamEnergies() const;
0381
0382
0383 vector<double> allowedEnergies() const;
0384
0385
0386 double sqrtS() const;
0387
0388
0389 bool beamsMatch(const ParticlePair& beams) const;
0390
0391
0392 bool beamsMatch(PdgId beam1, PdgId beam2, double e1, double e2) const;
0393
0394
0395 bool beamsMatch(const PdgIdPair& beams, const std::pair<double,double>& energies) const;
0396
0397
0398 bool beamIDsMatch(PdgId beam1, PdgId beam2) const;
0399
0400
0401 bool beamIDsMatch(const PdgIdPair& beamids) const;
0402
0403
0404 bool beamEnergiesMatch(double e1, double e2) const;
0405
0406
0407 bool beamEnergiesMatch(const std::pair<double,double>& energies) const;
0408
0409
0410 bool beamEnergyMatch(const std::pair<double,double>& energies) const;
0411
0412
0413 bool beamEnergyMatch(double sqrts) const;
0414
0415
0416 bool isCompatibleWithSqrtS(double energy, double tolerance=1e-5) const;
0417
0418
0419
0420
0421
0422 AnalysisHandler& handler() const { return *_analysishandler; }
0423
0424
0425 const Event& currentEvent() const {
0426 if (!_currentevent) throw Error("No current event set: did you try to access it in init() or finalize()?");
0427 return *_currentevent;
0428 }
0429
0430
0431 protected:
0432
0433
0434 Log& getLog() const;
0435
0436
0437 double crossSection() const;
0438
0439
0440
0441 double crossSectionPerEvent() const;
0442
0443
0444 double crossSectionError() const;
0445
0446
0447
0448 double crossSectionErrorPerEvent() const;
0449
0450
0451
0452
0453 size_t numEvents() const;
0454
0455
0456
0457
0458 double sumW() const;
0459
0460 double sumOfWeights() const { return sumW(); }
0461
0462
0463
0464
0465 double sumW2() const;
0466
0467
0468 protected:
0469
0470
0471
0472
0473
0474
0475
0476
0477 const std::string histoDir() const;
0478
0479
0480 const std::string histoPath(const std::string& hname) const;
0481
0482
0483 const std::string histoPath(unsigned int datasetID, unsigned int xAxisID, unsigned int yAxisID) const;
0484
0485
0486 const std::string mkAxisCode(unsigned int datasetID, unsigned int xAxisID, unsigned int yAxisID) const;
0487
0488
0489
0490
0491 #ifdef HAVE_H5
0492
0493
0494
0495
0496 H5::File auxFile() const {
0497 return H5::readFile(name()+".h5");
0498 }
0499
0500
0501 template <typename T>
0502 bool auxData(const string& dsname, T& rtndata) {
0503
0504 return H5::readData(name()+".h5", dsname, rtndata);
0505 }
0506
0507 template <typename T>
0508 T auxData(const string& dsname) {
0509
0510 return H5::readData<T>(name()+".h5", dsname);
0511 }
0512
0513
0514 #endif
0515
0516
0517
0518
0519
0520
0521 const std::map<std::string, YODA::AnalysisObjectPtr>& refData() const {
0522 _cacheRefData();
0523 return _refdata;
0524 }
0525
0526
0527
0528
0529 template <typename T=YODA::Estimate1D>
0530 const T& refData(const string& hname) const {
0531 _cacheRefData();
0532 MSG_TRACE("Using histo bin edges for " << name() << ":" << hname);
0533 if (!_refdata[hname]) {
0534 MSG_ERROR("Can't find reference histogram " << hname);
0535 throw Exception("Reference data " + hname + " not found.");
0536 }
0537 try {
0538 return dynamic_cast<T&>(*_refdata[hname]);
0539 } catch (...) {
0540 throw Exception("Expected type " + _refdata[hname]->type()+" for reference data \"" + hname + "\".\n");
0541 }
0542 }
0543
0544
0545
0546
0547 template <typename T=YODA::Estimate1D>
0548 const T& refData(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId) const {
0549 const string hname = mkAxisCode(datasetId, xAxisId, yAxisId);
0550 return refData<T>(hname);
0551 }
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563 CounterPtr& book(CounterPtr&, const std::string& name);
0564
0565
0566
0567
0568 CounterPtr& book(CounterPtr&, unsigned int datasetID, unsigned int xAxisID, unsigned int yAxisID);
0569
0570
0571
0572
0573
0574
0575
0576
0577 Estimate0DPtr& book(Estimate0DPtr&, const std::string& name);
0578
0579
0580
0581
0582 Estimate0DPtr& book(Estimate0DPtr&, unsigned int datasetID, unsigned int xAxisID, unsigned int yAxisID);
0583
0584
0585
0586
0587
0588
0589
0590
0591 template<size_t DbnN, typename... AxisT, typename = YODA::enable_if_all_CAxisT<AxisT...>>
0592 BinnedDbnPtr<DbnN, AxisT...>& book(BinnedDbnPtr<DbnN, AxisT...>& ao,
0593 const std::string& name, const std::vector<size_t>& nbins,
0594 const std::vector<std::pair<double,double>>& loUpPairs) {
0595 if (nbins.size() != loUpPairs.size()) {
0596 throw RangeError("Vectors should have the same size!");
0597 }
0598 const string path = histoPath(name);
0599
0600 YODA::BinnedDbn<DbnN, AxisT...> yao(nbins, loUpPairs, path);
0601 _setWriterPrecision(path, yao);
0602
0603 return ao = registerAO(yao);
0604 }
0605
0606
0607 Histo1DPtr& book(Histo1DPtr& ao, const std::string& name,
0608 const size_t nbins, const double lower, const double upper) {
0609 return book(ao, name, vector<size_t>{nbins},
0610 vector<pair<double,double>>{{lower,upper}});
0611 }
0612
0613 Profile1DPtr& book(Profile1DPtr& ao, const std::string& name,
0614 const size_t nbins, const double lower, const double upper) {
0615 return book(ao, name, vector<size_t>{nbins},
0616 vector<pair<double,double>>{{lower,upper}});
0617 }
0618
0619
0620 Histo2DPtr& book(Histo2DPtr& ao, const std::string& name,
0621 const size_t nbinsX, const double lowerX, const double upperX,
0622 const size_t nbinsY, const double lowerY, const double upperY) {
0623 return book(ao, name, vector<size_t>{nbinsX,nbinsY},
0624 vector<pair<double,double>>{{lowerX,upperX}, {lowerY,upperY}});
0625 }
0626
0627 Profile2DPtr& book(Profile2DPtr& ao, const std::string& name,
0628 const size_t nbinsX, const double lowerX, const double upperX,
0629 const size_t nbinsY, const double lowerY, const double upperY) {
0630 return book(ao, name, vector<size_t>{nbinsX,nbinsY},
0631 vector<pair<double,double>>{{lowerX,upperX}, {lowerY,upperY}});
0632 }
0633
0634
0635 Histo3DPtr& book(Histo3DPtr& ao, const std::string& name,
0636 const size_t nbinsX, const double lowerX, const double upperX,
0637 const size_t nbinsY, const double lowerY, const double upperY,
0638 const size_t nbinsZ, const double lowerZ, const double upperZ) {
0639 return book(ao, name, vector<size_t>{nbinsX,nbinsY,nbinsZ},
0640 vector<pair<double,double>>{{lowerX,upperX}, {lowerY,upperY}, {lowerZ,upperZ}});
0641 }
0642
0643 Profile3DPtr& book(Profile3DPtr& ao, const std::string& name,
0644 const size_t nbinsX, const double lowerX, const double upperX,
0645 const size_t nbinsY, const double lowerY, const double upperY,
0646 const size_t nbinsZ, const double lowerZ, const double upperZ) {
0647 return book(ao, name, vector<size_t>{nbinsX,nbinsY,nbinsZ},
0648 vector<pair<double,double>>{{lowerX,upperX}, {lowerY,upperY}, {lowerZ,upperZ}});
0649 }
0650
0651
0652 template<size_t DbnN, typename... AxisT>
0653 BinnedDbnPtr<DbnN, AxisT...>& book(BinnedDbnPtr<DbnN, AxisT...>& ao, const std::string& name,
0654 const std::vector<AxisT>&... binedges) {
0655 const string path = histoPath(name);
0656 YODA::BinnedDbn<DbnN, AxisT...> yao(binedges..., path);
0657 _setWriterPrecision(path, yao);
0658
0659 return ao = registerAO(yao);
0660 }
0661
0662
0663 template<size_t DbnN, typename... AxisT>
0664 BinnedDbnPtr<DbnN, AxisT...>& book(BinnedDbnPtr<DbnN, AxisT...>& ao, const std::string& name,
0665 const std::initializer_list<AxisT>&... binedges) {
0666 return book(ao, name, vector<AxisT>{binedges} ...);
0667 }
0668
0669
0670 template<size_t DbnN, typename... AxisT>
0671 BinnedDbnPtr<DbnN, AxisT...>& book(BinnedDbnPtr<DbnN, AxisT...>& ao, const std::string& name,
0672 const YODA::BinnedEstimate<AxisT...>& refest) {
0673 const string path = histoPath(name);
0674
0675 YODA::BinnedDbn<DbnN, AxisT...> yao(refest.binning(), path);
0676 for (const string& a : yao.annotations()) {
0677 if (a != "Path") yao.rmAnnotation(a);
0678 }
0679 _setWriterPrecision(path, yao);
0680 return ao = registerAO(yao);
0681 }
0682
0683
0684 template<size_t DbnN, typename... AxisT>
0685 BinnedDbnPtr<DbnN, AxisT...>& book(BinnedDbnPtr<DbnN, AxisT...>& ao, const std::string& name) {
0686 return book(ao, name, refData<YODA::BinnedEstimate<AxisT...>>(name));
0687 }
0688
0689
0690
0691
0692 template<size_t DbnN, typename... AxisT>
0693 BinnedDbnPtr<DbnN, AxisT...>& book(BinnedDbnPtr<DbnN, AxisT...>& ao, const unsigned int datasetID,
0694 const unsigned int xAxisID, const unsigned int yAxisID) {
0695 const string name = mkAxisCode(datasetID, xAxisID, yAxisID);
0696 return book(ao, name);
0697 }
0698
0699
0700
0701
0702
0703
0704 template <typename GroupAxisT, typename... AxisT>
0705 HistoGroupPtr<GroupAxisT, AxisT...>& book(HistoGroupPtr<GroupAxisT, AxisT...>& ao,
0706 const std::vector<GroupAxisT>& edges,
0707 const std::vector<std::string>& names) {
0708 ao = make_shared<HistoGroup<GroupAxisT, AxisT...>>(edges);
0709 if (ao->numBins() != names.size()) {
0710 throw RangeError("Binning and reference-data names don't match!");
0711 }
0712 for (auto& b : ao->bins()) {
0713 const string& refname = names[b.index()-1];
0714 book(b, refname, refData<YODA::BinnedEstimate<AxisT...>>(refname));
0715 }
0716 return ao;
0717 }
0718
0719 template <typename GroupAxisT, typename... AxisT>
0720 HistoGroupPtr<GroupAxisT, AxisT...>& book(HistoGroupPtr<GroupAxisT, AxisT...>& ao,
0721 const std::vector<GroupAxisT>& edges) {
0722 return ao = make_shared<HistoGroup<GroupAxisT, AxisT...>>(edges);
0723 }
0724
0725 template <typename GroupAxisT, typename... AxisT>
0726 HistoGroupPtr<GroupAxisT, AxisT...>& book(HistoGroupPtr<GroupAxisT, AxisT...>& ao,
0727 std::initializer_list<GroupAxisT>&& edges) {
0728 return ao = make_shared<HistoGroup<GroupAxisT, AxisT...>>(std::move(edges));
0729 }
0730
0731
0732
0733
0734
0735
0736
0737 template<typename... AxisT, typename = YODA::enable_if_all_CAxisT<AxisT...>>
0738 BinnedEstimatePtr<AxisT...>& book(BinnedEstimatePtr<AxisT...>& ao,
0739 const std::string& name, const std::vector<size_t>& nbins,
0740 const std::vector<std::pair<double,double>>& loUpPairs) {
0741 if (nbins.size() != loUpPairs.size()) {
0742 throw RangeError("Vectors should have the same size!");
0743 }
0744 const string path = histoPath(name);
0745
0746 YODA::BinnedEstimate<AxisT...> yao(nbins, loUpPairs, path);
0747 _setWriterPrecision(path, yao);
0748
0749 return ao = registerAO(yao);
0750 }
0751
0752
0753
0754 Estimate1DPtr& book(Estimate1DPtr& ao, const std::string& name,
0755 const size_t nbins, const double lower, const double upper) {
0756 return book(ao, name, vector<size_t>{nbins},
0757 vector<pair<double,double>>{{lower,upper}});
0758 }
0759
0760
0761 Estimate2DPtr& book(Estimate2DPtr& ao, const std::string& name,
0762 const size_t nbinsX, const double lowerX, const double upperX,
0763 const size_t nbinsY, const double lowerY, const double upperY) {
0764 return book(ao, name, vector<size_t>{nbinsX,nbinsY},
0765 vector<pair<double,double>>{{lowerX,upperX}, {lowerY,upperY}});
0766 }
0767
0768
0769 Estimate3DPtr& book(Estimate3DPtr& ao, const std::string& name,
0770 const size_t nbinsX, const double lowerX, const double upperX,
0771 const size_t nbinsY, const double lowerY, const double upperY,
0772 const size_t nbinsZ, const double lowerZ, const double upperZ) {
0773 return book(ao, name, vector<size_t>{nbinsX,nbinsY,nbinsZ},
0774 vector<pair<double,double>>{{lowerX,upperX}, {lowerY,upperY}, {lowerZ,upperZ}});
0775 }
0776
0777
0778 template<typename... AxisT>
0779 BinnedEstimatePtr<AxisT...>& book(BinnedEstimatePtr<AxisT...>& ao, const std::string& name,
0780 const std::vector<AxisT>&... binedges) {
0781 const string path = histoPath(name);
0782 YODA::BinnedEstimate<AxisT...> yao(binedges..., path);
0783 _setWriterPrecision(path, yao);
0784
0785 return ao = registerAO(yao);
0786 }
0787
0788
0789 template<typename... AxisT>
0790 BinnedEstimatePtr<AxisT...>& book(BinnedEstimatePtr<AxisT...>& ao, const std::string& name,
0791 const std::initializer_list<AxisT>&... binedges) {
0792 return book(ao, name, vector<AxisT>{binedges} ...);
0793 }
0794
0795
0796 template<typename... AxisT>
0797 BinnedEstimatePtr<AxisT...>& book(BinnedEstimatePtr<AxisT...>& ao, const std::string& name) {
0798
0799 const string path = histoPath(name);
0800 YODA::BinnedEstimate<AxisT...> yao;
0801 try {
0802 yao = YODA::BinnedEstimate<AxisT...>(refData<YODA::BinnedEstimate<AxisT...>>(name).binning());
0803 } catch (...) {
0804 MSG_DEBUG("Couldn't retrieve reference binning, continue with nullary AO constructor.");
0805 }
0806 yao.setPath(path);
0807 _setWriterPrecision(path, yao);
0808 return ao = registerAO(yao);
0809 }
0810
0811
0812
0813
0814 template<typename... AxisT>
0815 BinnedEstimatePtr<AxisT...>& book(BinnedEstimatePtr<AxisT...>& ao, const unsigned int datasetID,
0816 const unsigned int xAxisID, const unsigned int yAxisID) {
0817 const string name = mkAxisCode(datasetID, xAxisID, yAxisID);
0818 return book(ao, name);
0819 }
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837 template<size_t N>
0838 ScatterNDPtr<N>& book(ScatterNDPtr<N>& snd, const string& name, const bool copy_pts = false) {
0839 const string path = histoPath(name);
0840 YODA::ScatterND<N> scat(path);
0841 if (copy_pts) {
0842 const YODA::ScatterND<N> ref = refData<YODA::EstimateND<N-1>>(name).mkScatter();
0843 for (YODA::PointND<N> p : ref.points()) {
0844 p.setVal(N-1, 0.0);
0845 p.setErr(N-1, 0.0);
0846 scat.addPoint(std::move(p));
0847 }
0848 }
0849 _setWriterPrecision(path, scat);
0850 return snd = registerAO(scat);
0851 }
0852
0853
0854
0855
0856
0857
0858
0859
0860
0861
0862
0863 template<size_t N>
0864 ScatterNDPtr<N>& book(ScatterNDPtr<N>& snd, const unsigned int datasetID, const unsigned int xAxisID,
0865 const unsigned int yAxisID, const bool copy_pts = false) {
0866 const string axisCode = mkAxisCode(datasetID, xAxisID, yAxisID);
0867 return book(snd, axisCode, copy_pts);
0868 }
0869
0870
0871
0872
0873
0874
0875 Scatter2DPtr& book(Scatter2DPtr& snd, const string& name,
0876 const size_t npts, const double lower, const double upper) {
0877 const string path = histoPath(name);
0878
0879 Scatter2D scat(path);
0880 const double binwidth = (upper-lower)/npts;
0881 for (size_t pt = 0; pt < npts; ++pt) {
0882 const double bincentre = lower + (pt + 0.5) * binwidth;
0883 scat.addPoint(bincentre, 0, binwidth/2.0, 0);
0884 }
0885 _setWriterPrecision(path, scat);
0886
0887 return snd = registerAO(scat);
0888 }
0889
0890 Scatter3DPtr& book(Scatter3DPtr& snd, const string& name,
0891 const size_t nptsX, const double lowerX, const double upperX,
0892 const size_t nptsY, const double lowerY, const double upperY) {
0893 const string path = histoPath(name);
0894
0895 Scatter3D scat(path);
0896 const double xbinwidth = (upperX-lowerX)/nptsX;
0897 const double ybinwidth = (upperY-lowerY)/nptsY;
0898 for (size_t xpt = 0; xpt < nptsX; ++xpt) {
0899 const double xbincentre = lowerX + (xpt + 0.5) * xbinwidth;
0900 for (size_t ypt = 0; ypt < nptsY; ++ypt) {
0901 const double ybincentre = lowerY + (ypt + 0.5) * ybinwidth;
0902 scat.addPoint(xbincentre, ybincentre, 0, 0.5*xbinwidth, 0.5*ybinwidth, 0);
0903 }
0904 }
0905 _setWriterPrecision(path, scat);
0906
0907 return snd = registerAO(scat);
0908 }
0909
0910
0911
0912
0913
0914
0915 Scatter2DPtr& book(Scatter2DPtr& snd, const string& name,
0916 const std::vector<double>& binedges) {
0917 const string path = histoPath(name);
0918
0919 Scatter2D scat(path);
0920 for (size_t pt = 0; pt < binedges.size()-1; ++pt) {
0921 const double bincentre = (binedges[pt] + binedges[pt+1]) / 2.0;
0922 const double binwidth = binedges[pt+1] - binedges[pt];
0923 scat.addPoint(bincentre, 0, binwidth/2.0, 0);
0924 }
0925 _setWriterPrecision(path, scat);
0926
0927 return snd = registerAO(scat);
0928 }
0929
0930 Scatter3DPtr& book(Scatter3DPtr& snd, const string& name,
0931 const std::vector<double>& binedgesX,
0932 const std::vector<double>& binedgesY) {
0933 const string path = histoPath(name);
0934
0935 Scatter3D scat(path);
0936 for (size_t xpt = 0; xpt < binedgesX.size()-1; ++xpt) {
0937 const double xbincentre = (binedgesX[xpt] + binedgesX[xpt+1]) / 2.0;
0938 const double xbinwidth = binedgesX[xpt+1] - binedgesX[xpt];
0939 for (size_t ypt = 0; ypt < binedgesY.size()-1; ++ypt) {
0940 const double ybincentre = (binedgesY[ypt] + binedgesY[ypt+1]) / 2.0;
0941 const double ybinwidth = binedgesY[ypt+1] - binedgesY[ypt];
0942 scat.addPoint(xbincentre, ybincentre, 0, 0.5*xbinwidth, 0.5*ybinwidth, 0);
0943 }
0944 }
0945 _setWriterPrecision(path, scat);
0946
0947 return snd = registerAO(scat);
0948 }
0949
0950
0951 template<size_t N>
0952 ScatterNDPtr<N>& book(ScatterNDPtr<N>& snd, const string& name, const YODA::ScatterND<N>& refscatter) {
0953 const string path = histoPath(name);
0954
0955 YODA::ScatterND<N> scat(refscatter, path);
0956 for (const string& a : scat.annotations()) {
0957 if (a != "Path") scat.rmAnnotation(a);
0958 }
0959 _setWriterPrecision(path, scat);
0960
0961 return snd = registerAO(scat);
0962 }
0963
0964
0965
0966
0967
0968
0969
0970 CutflowPtr& book(CutflowPtr& ao, const string& name, const std::vector<std::string>& edges) {
0971 const string path = histoPath(name);
0972 Cutflow yao(edges, path);
0973 _setWriterPrecision(path, yao);
0974 return ao = registerAO(yao);
0975 }
0976
0977
0978 CutflowPtr& book(CutflowPtr& ao, const string& name, const std::initializer_list<std::string>& edges) {
0979 return book(ao, name, vector<std::string>{edges});
0980 }
0981
0982
0983
0984
0985
0986
0987 CutflowsPtr& book(CutflowsPtr& ao, const std::vector<std::string>& edges,
0988 const std::vector<std::vector<std::string>>& innerEdges) {
0989 ao = make_shared<Cutflows>(edges);
0990 if (ao->numBins() !=innerEdges.size()) {
0991 throw RangeError("Outer and Inner edges don't match");
0992 }
0993 for (auto& b : ao->bins()) {
0994 book(b, b.xEdge(), innerEdges[b.index()-1]);
0995 }
0996 return ao;
0997 }
0998
0999 CutflowsPtr& book(CutflowsPtr& ao, const std::vector<std::string>& edges) {
1000 return ao = make_shared<Cutflows>(edges);
1001 }
1002
1003 CutflowsPtr& book(CutflowsPtr& ao, std::initializer_list<std::string>&& edges) {
1004 return ao = make_shared<Cutflows>(std::move(edges));
1005 }
1006
1007
1008
1009
1010
1011
1012
1013 virtual void rawHookIn(YODA::AnalysisObjectPtr yao) {
1014 (void) yao;
1015 }
1016
1017
1018
1019
1020 virtual void rawHookOut(const vector<MultiplexAOPtr>& raos, size_t iW) {
1021 (void) raos;
1022 (void) iW;
1023 }
1024
1025
1026 public:
1027
1028
1029
1030
1031
1032 const std::map<std::string,std::string>& options() const {
1033 return _options;
1034 }
1035
1036
1037 std::string getOption(std::string optname, string def="") const {
1038 if ( _options.find(optname) != _options.end() )
1039 return _options.find(optname)->second;
1040 return def;
1041 }
1042
1043
1044
1045
1046
1047 std::string getOption(std::string optname, const char* def) {
1048 return getOption<std::string>(optname, def);
1049 }
1050
1051
1052
1053
1054
1055
1056
1057
1058 template<typename T>
1059 T getOption(std::string optname, T def) const {
1060 if (_options.find(optname) == _options.end()) return def;
1061 std::stringstream ss;
1062 ss.exceptions(std::ios::failbit);
1063 T ret;
1064 ss << _options.find(optname)->second;
1065 try {
1066 ss >> ret;
1067 } catch (...) {
1068 throw ReadError("Could not read user-provided option into requested type");
1069 }
1070 return ret;
1071 }
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085 bool getOption(std::string optname, bool def) const {
1086 if (_options.find(optname) == _options.end()) return def;
1087 const std::string val = getOption(optname);
1088 const std::string lval = toLower(val);
1089 if (lval.empty()) return false;
1090 if (lval == "true" || lval == "yes" || lval == "on") return true;
1091 if (lval == "false" || lval == "no" || lval == "off") return false;
1092 return bool(getOption<int>(optname, 0));
1093 }
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117 const CentralityProjection&
1118 declareCentrality(const SingleValueProjection &proj,
1119 string calAnaName, string calHistName,
1120 const string projName,
1121 PercentileOrder pctorder=PercentileOrder::DECREASING);
1122
1123
1124
1125
1126
1127
1128
1129
1130 template<typename T>
1131 Percentile<T> book(const string& projName,
1132 const vector<pair<double, double>>& centralityBins,
1133 const vector<tuple<size_t, size_t, size_t>>& ref) {
1134
1135 using RefT = typename ReferenceTraits<T>::RefT;
1136 using WrapT = MultiplexPtr<Multiplexer<T>>;
1137
1138 Percentile<T> pctl(this, projName);
1139
1140 const size_t nCent = centralityBins.size();
1141 for (size_t iCent = 0; iCent < nCent; ++iCent) {
1142 const string axisCode = mkAxisCode(std::get<0>(ref[iCent]),
1143 std::get<1>(ref[iCent]),
1144 std::get<2>(ref[iCent]));
1145 const RefT& refscatter = refData<RefT>(axisCode);
1146
1147 WrapT wtf(_weightNames(), T(refscatter, histoPath(axisCode)));
1148 wtf = addAnalysisObject(wtf);
1149
1150 CounterPtr cnt(_weightNames(), Counter(histoPath("TMP/COUNTER/" + axisCode)));
1151 cnt = addAnalysisObject(cnt);
1152
1153 pctl.add(wtf, cnt, centralityBins[iCent]);
1154 }
1155 return pctl;
1156 }
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194 private:
1195
1196
1197
1198
1199 vector<string> _weightNames() const;
1200
1201
1202 YODA::AnalysisObjectPtr _getPreload (const string& name) const;
1203
1204
1205 MultiplexAOPtr _getOtherAnalysisObject(const std::string & ananame, const std::string& name);
1206
1207
1208 void _checkBookInit() const;
1209
1210
1211 bool _inInit() const;
1212
1213
1214 bool _inFinalize() const;
1215
1216
1217 template <typename YODAT>
1218 void _setWriterPrecision(const string& path, YODAT& yao) {
1219 const string re = _info->writerDoublePrecision();
1220 if (re != "") {
1221 std::smatch match;
1222 const bool needsDP = std::regex_search(path, match, std::regex(re));
1223 if (needsDP) yao.setAnnotation("WriterDoublePrecision", "1");
1224 }
1225 }
1226
1227
1228 private:
1229
1230
1231 class CounterAdapter {
1232 public:
1233
1234 CounterAdapter(double x) : x_(x) {}
1235
1236 CounterAdapter(const YODA::Counter& c) : x_(c.val()) {}
1237
1238 CounterAdapter(const YODA::Estimate& e) : x_(e.val()) {}
1239
1240 CounterAdapter(const YODA::Scatter1D& s) : x_(s.points()[0].x()) {
1241 if (s.numPoints() != 1) throw RangeError("Can only scale by a single value.");
1242 }
1243
1244 operator double() const { return x_; }
1245
1246 private:
1247 double x_;
1248
1249 };
1250
1251
1252 public:
1253
1254 double dbl(double x) { return x; }
1255 double dbl(const YODA::Counter& c) { return c.val(); }
1256 double dbl(const YODA::Estimate0D& e) { return e.val(); }
1257 double dbl(const YODA::Scatter1D& s) {
1258 if ( s.numPoints() != 1 ) throw RangeError("Only scatter with single value supported.");
1259 return s.points()[0].x();
1260 }
1261
1262
1263 protected:
1264
1265
1266
1267
1268
1269
1270 template<typename T>
1271 void scale(MultiplexPtr<Multiplexer<T>>& ao, CounterAdapter factor) {
1272 if (!ao) {
1273 MSG_WARNING("Failed to scale AnalysisObject=NULL in analysis "
1274 << name() << " (scale=" << double(factor) << ")");
1275 return;
1276 }
1277 if (std::isnan(double(factor)) || std::isinf(double(factor))) {
1278 MSG_WARNING("Failed to scale AnalysisObject=" << ao->path() << " in analysis: "
1279 << name() << " (invalid scale factor = " << double(factor) << ")");
1280 factor = 0;
1281 }
1282 MSG_TRACE("Scaling AnalysisObject " << ao->path() << " by factor " << double(factor));
1283 try {
1284 if constexpr( isFillable<T>::value ) {
1285 ao->scaleW(factor);
1286 }
1287 else {
1288 ao->scale(factor);
1289 }
1290 }
1291 catch (YODA::Exception& we) {
1292 MSG_WARNING("Could not scale AnalysisObject " << ao->path());
1293 return;
1294 }
1295 }
1296
1297
1298 template<typename GroupAxisT, typename... AxisT>
1299 void scale(HistoGroupPtr<GroupAxisT, AxisT...>& group, CounterAdapter factor) {
1300 if (!group) {
1301 MSG_WARNING("Failed to scale AnalysisObject=NULL in analysis "
1302 << name() << " (scale=" << double(factor) << ")");
1303 return;
1304 }
1305 if (std::isnan(double(factor)) || std::isinf(double(factor))) {
1306 MSG_WARNING("Failed to scale histo group in analysis: "
1307 << name() << " (invalid scale factor = " << double(factor) << ")");
1308 factor = 0;
1309 }
1310 MSG_TRACE("Scaling histo group by factor " << double(factor));
1311 try {
1312 group->scaleW(factor);
1313 }
1314 catch (YODA::Exception& we) {
1315 MSG_WARNING("Could not scale histo group.");
1316 return;
1317 }
1318 }
1319
1320
1321 template<typename GroupAxisT, typename... AxisT>
1322 void scale(HistoGroupPtr<GroupAxisT, AxisT...>& group, const vector<double>& factors) {
1323 if (!group) {
1324 MSG_WARNING("Failed to scale AnalysisObject=NULL in analysis " << name());
1325 return;
1326 }
1327 if (group->numBins(true) != factors.size()) {
1328 throw RangeError(name() + ": Number of scale factors does not match group binning");
1329 return;
1330 }
1331 for (auto& b : group->bins(true)) {
1332 if (!b.get()) continue;
1333 double factor = factors[b.index()];
1334 if (std::isnan(factor) || std::isinf(factor)) {
1335 MSG_WARNING("Failed to scale componment of histo group in analysis: "
1336 << name() << " (invalid scale factor = " << factor << ")");
1337 factor = 0;
1338 }
1339 MSG_TRACE("Scaling histo group element by factor " << factor);
1340 try {
1341 b->scaleW(factor);
1342 }
1343 catch (YODA::Exception& we) {
1344 MSG_WARNING("Could not scale component of histo group.");
1345 }
1346 }
1347 }
1348
1349
1350 void scale(CutflowsPtr& group, CounterAdapter factor) {
1351 if (!group) {
1352 MSG_WARNING("Failed to scale AnalysisObject=NULL in analysis "
1353 << name() << " (scale=" << double(factor) << ")");
1354 return;
1355 }
1356 if (std::isnan(double(factor)) || std::isinf(double(factor))) {
1357 MSG_WARNING("Failed to scale histo group in analysis: "
1358 << name() << " (invalid scale factor = " << double(factor) << ")");
1359 factor = 0;
1360 }
1361 MSG_TRACE("Scaling histo group by factor " << double(factor));
1362 try {
1363 group->scale(factor);
1364 }
1365 catch (YODA::Exception& we) {
1366 MSG_WARNING("Could not scale histo group.");
1367 return;
1368 }
1369 }
1370
1371
1372 template<typename T, typename U>
1373 void scale(std::map<T, U>& aos, CounterAdapter factor) {
1374 for (auto& item : aos) scale(item.second, factor);
1375 }
1376
1377
1378 template <typename AORange, typename = std::enable_if_t<YODA::isIterable<AORange>>>
1379 void scale(AORange& aos, CounterAdapter factor) {
1380 for (auto& ao : aos) scale(ao, factor);
1381 }
1382
1383
1384 template <typename T>
1385 void scale(std::initializer_list<T> aos, CounterAdapter factor) {
1386 for (auto& ao : std::vector<T>{aos}) scale(ao, factor);
1387 }
1388
1389
1390 template<typename T, typename U>
1391 void scale(std::map<T, U>& aos, const vector<double>& factors) {
1392 for (auto& item : aos) scale(item.second, factors);
1393 }
1394
1395
1396 template <typename AORange, typename = std::enable_if_t<YODA::isIterable<AORange>>>
1397 void scale(AORange& aos, const vector<double>& factors) {
1398 for (auto& ao : aos) scale(ao, factors);
1399 }
1400
1401
1402 template <typename T>
1403 void scale(std::initializer_list<T> aos, const vector<double>& factors) {
1404 for (auto& ao : std::vector<T>{aos}) scale(ao, factors);
1405 }
1406
1407
1408 template<typename GroupAxisT, typename... AxisT>
1409 void divByGroupWidth(HistoGroupPtr<GroupAxisT, AxisT...>& group) {
1410 if (!group) {
1411 MSG_WARNING("Failed to scale HistoGroup=NULL in analysis "
1412 << name() << " by group axis width");
1413 return;
1414 }
1415 group->divByGroupWidth();
1416 }
1417
1418
1419 template<typename T, typename U>
1420 void divByGroupWidth(std::map<T, U>& aos) {
1421 for (auto& item : aos) divByGroupWidth(item.second);
1422 }
1423
1424
1425 template <typename AORange, typename = std::enable_if_t<YODA::isIterable<AORange>>>
1426 void divByGroupWidth(AORange& aos) {
1427 for (auto& ao : aos) divByGroupWidth(ao);
1428 }
1429
1430
1431 template <typename T>
1432 void divByGroupWidth(std::initializer_list<T> aos) {
1433 for (auto& ao : std::vector<T>{aos}) divByGroupWidth(ao);
1434 }
1435
1436
1437
1438 template <size_t DbnN, typename... AxisT>
1439 void normalize(BinnedDbnPtr<DbnN, AxisT...> ao, const CounterAdapter norm=1.0, const bool includeoverflows=true) {
1440 if (!ao) {
1441 MSG_WARNING("Failed to normalize histo=NULL in analysis " << name() << " (norm=" << double(norm) << ")");
1442 return;
1443 }
1444 MSG_TRACE("Normalizing histo " << ao->path() << " to " << double(norm));
1445 try {
1446 const double hint = ao->integral(includeoverflows);
1447 if (hint == 0) MSG_DEBUG("Skipping histo with null area " << ao->path());
1448 else ao->normalize(norm, includeoverflows);
1449 }
1450 catch (YODA::Exception& we) {
1451 MSG_WARNING("Could not normalize histo " << ao->path());
1452 return;
1453 }
1454 }
1455
1456
1457 template <typename GroupAxisT, typename... AxisT>
1458 void normalize(HistoGroupPtr<GroupAxisT, AxisT...> group, const CounterAdapter norm=1.0, const bool includeoverflows=true) {
1459 if (!group) {
1460 MSG_WARNING("Failed to normalize histo=NULL in analysis " << name() << " (norm=" << double(norm) << ")");
1461 return;
1462 }
1463 MSG_TRACE("Normalizing histo group to " << double(norm));
1464 try {
1465 const double hint = group->integral(includeoverflows);
1466 if (hint == 0) MSG_DEBUG("Skipping histo group with null area.");
1467 else group->normalize(norm, includeoverflows);
1468 }
1469 catch (YODA::Exception& we) {
1470 MSG_WARNING("Could not normalize histo group.");
1471 return;
1472 }
1473 }
1474
1475
1476
1477 template <typename AORange, typename = std::enable_if_t<YODA::isIterable<AORange>>>
1478 void normalize(AORange& aos, const CounterAdapter norm=1.0, const bool includeoverflows=true) {
1479 for (auto& ao : aos) normalize(ao, norm, includeoverflows);
1480 }
1481
1482
1483 template<typename T>
1484 void normalize(std::initializer_list<T>&& aos, const CounterAdapter norm=1.0, const bool includeoverflows=true) {
1485 for (auto& ao : aos) normalize(ao, norm, includeoverflows);
1486 }
1487
1488
1489 template<typename T, typename U>
1490 void normalize(std::map<T, U>& aos,
1491 const CounterAdapter norm=1.0, const bool includeoverflows=true) {
1492 for (auto& item : aos) normalize(item.second, norm, includeoverflows);
1493 }
1494
1495
1496 template <typename GroupAxisT, typename... AxisT>
1497 void normalizeGroup(HistoGroupPtr<GroupAxisT, AxisT...> group, const CounterAdapter norm=1.0, const bool includeoverflows=true) {
1498 if (!group) {
1499 MSG_WARNING("Failed to normalize histo=NULL in analysis " << name() << " (norm=" << double(norm) << ")");
1500 return;
1501 }
1502 MSG_TRACE("Normalizing histo group to " << double(norm));
1503 try {
1504 const double hint = group->integral(includeoverflows);
1505 if (hint == 0) MSG_DEBUG("Skipping histo group with null area.");
1506 else group->normalizeGroup(norm, includeoverflows);
1507 }
1508 catch (YODA::Exception& we) {
1509 MSG_WARNING("Could not normalize histo group.");
1510 return;
1511 }
1512 }
1513
1514
1515 template <typename AORange, typename = std::enable_if_t<YODA::isIterable<AORange>>>
1516 void normalizeGroup(AORange& aos, const CounterAdapter norm=1.0, const bool includeoverflows=true) {
1517 for (auto& ao : aos) normalizeGroup(ao, norm, includeoverflows);
1518 }
1519
1520
1521 template<typename T>
1522 void normalizeGroup(std::initializer_list<T>&& aos, const CounterAdapter norm=1.0, const bool includeoverflows=true) {
1523 for (auto& ao : aos) normalizeGroup(ao, norm, includeoverflows);
1524 }
1525
1526
1527 template<typename T, typename U>
1528 void normalizeGroup(std::map<T, U>& aos,
1529 const CounterAdapter norm=1.0, const bool includeoverflows=true) {
1530 for (auto& item : aos) normalizeGroup(item.second, norm, includeoverflows);
1531 }
1532
1533
1534
1535
1536
1537
1538 template<size_t DbnN, typename... AxisT>
1539 void barchart(BinnedDbnPtr<DbnN, AxisT...> ao, BinnedEstimatePtr<AxisT...> est) const {
1540 const string path = est->path();
1541 *est = ao->mkEstimate(path, "stats", false);
1542 }
1543
1544
1545
1546
1547 void divide(CounterPtr c1, CounterPtr c2, Estimate0DPtr est) const;
1548
1549
1550
1551
1552 void divide(const YODA::Counter& c1, const YODA::Counter& c2, Estimate0DPtr est) const;
1553
1554
1555
1556
1557 void divide(Estimate0DPtr e1, Estimate0DPtr e2, Estimate0DPtr est) const;
1558
1559
1560
1561
1562 void divide(const YODA::Estimate0D& e1, const YODA::Estimate0D& e2, Estimate0DPtr est) const;
1563
1564
1565
1566
1567
1568 template<size_t DbnN, typename... AxisT>
1569 void divide(const YODA::BinnedDbn<DbnN, AxisT...>& h1, const YODA::BinnedDbn<DbnN, AxisT...>& h2,
1570 BinnedEstimatePtr<AxisT...> est) const {
1571 const string path = est->path();
1572 *est = h1 / h2;
1573 est->setPath(path);
1574 }
1575
1576 template<size_t DbnN, typename... AxisT>
1577 void divide(BinnedDbnPtr<DbnN, AxisT...> h1, BinnedDbnPtr<DbnN, AxisT...> h2,
1578 BinnedEstimatePtr<AxisT...> est) const {
1579 return divide(*h1, *h2, est);
1580 }
1581
1582
1583
1584
1585 template<typename... AxisT>
1586 void divide(const YODA::BinnedEstimate<AxisT...>& e1, const YODA::BinnedEstimate<AxisT...>& e2,
1587 BinnedEstimatePtr<AxisT...> est) const {
1588 const string path = est->path();
1589 *est = e1 / e2;
1590 est->setPath(path);
1591 }
1592
1593 template<typename... AxisT>
1594 void divide(BinnedEstimatePtr<AxisT...> e1, BinnedEstimatePtr<AxisT...> e2,
1595 BinnedEstimatePtr<AxisT...> est) const {
1596 return divide(*e1, *e2, est);
1597 }
1598
1599
1600
1601
1602
1603
1604 void efficiency(CounterPtr c1, CounterPtr c2, Estimate0DPtr est) const {
1605 efficiency(*c1, *c2, est);
1606 }
1607
1608
1609
1610
1611 void efficiency(const YODA::Counter& c1, const YODA::Counter& c2, Estimate0DPtr est) const {
1612 const string path = est->path();
1613 *est = YODA::efficiency(c1, c2);
1614 est->setPath(path);
1615 }
1616
1617
1618
1619
1620
1621
1622 template<size_t DbnN, typename... AxisT>
1623 void efficiency(const YODA::BinnedDbn<DbnN, AxisT...>& h1, const YODA::BinnedDbn<DbnN, AxisT...>& h2,
1624 BinnedEstimatePtr<AxisT...> est) const {
1625 const string path = est->path();
1626 *est = YODA::efficiency(h1, h2);
1627 est->setPath(path);
1628 }
1629
1630 template<size_t DbnN, typename... AxisT>
1631 void efficiency(BinnedDbnPtr<DbnN, AxisT...> h1, BinnedDbnPtr<DbnN, AxisT...> h2,
1632 BinnedEstimatePtr<AxisT...> est) const {
1633 efficiency(*h1, *h2, est);
1634 }
1635
1636
1637
1638
1639
1640 template<typename... AxisT>
1641 void efficiency(const YODA::BinnedEstimate<AxisT...>& e1, const YODA::BinnedEstimate<AxisT...>& e2,
1642 BinnedEstimatePtr<AxisT...> est) const {
1643 const string path = est->path();
1644 *est = YODA::efficiency(e1, e2);
1645 est->setPath(path);
1646 }
1647
1648 template<typename... AxisT>
1649 void efficiency(BinnedEstimatePtr<AxisT...> e1, BinnedEstimatePtr<AxisT...> e2,
1650 BinnedEstimatePtr<AxisT...> est) const {
1651 efficiency(*e1, *e2, est);
1652 }
1653
1654
1655
1656
1657
1658 template<size_t DbnN, typename... AxisT>
1659 void asymm(const YODA::BinnedDbn<DbnN, AxisT...>& h1, const YODA::BinnedDbn<DbnN, AxisT...>& h2,
1660 BinnedEstimatePtr<AxisT...> est) const {
1661 const string path = est->path();
1662 *est = YODA::asymm(h1, h2);
1663 est->setPath(path);
1664 }
1665
1666 template<size_t DbnN, typename... AxisT>
1667 void asymm(BinnedDbnPtr<DbnN, AxisT...> h1, BinnedDbnPtr<DbnN, AxisT...> h2,
1668 BinnedEstimatePtr<AxisT...> est) const {
1669 asymm(*h1, *h2, est);
1670 }
1671
1672
1673
1674
1675 template<typename... AxisT>
1676 void asymm(const YODA::BinnedEstimate<AxisT...>& e1, const YODA::BinnedEstimate<AxisT...>& e2,
1677 BinnedEstimatePtr<AxisT...> est) const {
1678 const string path = est->path();
1679 *est = YODA::asymm(e1, e2);
1680 est->setPath(path);
1681 }
1682
1683 template<typename... AxisT>
1684 void asymm(BinnedEstimatePtr<AxisT...> e1, BinnedEstimatePtr<AxisT...> e2,
1685 BinnedEstimatePtr<AxisT...> est) const {
1686 asymm(*e1, *e2, est);
1687 }
1688
1689
1690
1691
1692 template<size_t DbnN, typename... AxisT>
1693 void integrate(const YODA::BinnedDbn<DbnN, AxisT...>& h, BinnedEstimatePtr<AxisT...> est) const {
1694 const string path = est->path();
1695 *est = mkIntegral(h);
1696 est->setPath(path);
1697 }
1698
1699 template<size_t DbnN, typename... AxisT>
1700 void integrate(BinnedDbnPtr<DbnN, AxisT...>& h, BinnedEstimatePtr<AxisT...> est) const {
1701 integrate(*h, est);
1702 }
1703
1704
1705
1706
1707 public:
1708
1709
1710 const vector<MultiplexAOPtr>& analysisObjects() const {
1711 return _analysisobjects;
1712 }
1713
1714
1715 protected:
1716
1717
1718
1719
1720
1721 size_t defaultWeightIndex() const;
1722
1723
1724 template <typename YODAT>
1725 shared_ptr<YODAT> getPreload(const string& path) const {
1726 return dynamic_pointer_cast<YODAT>(_getPreload(path));
1727 }
1728
1729
1730
1731 template <typename YODAT>
1732 MultiplexPtr< Multiplexer<YODAT> > registerAO(const YODAT& yao) {
1733 using MultiplexerT = Multiplexer<YODAT>;
1734 using YODAPtrT = shared_ptr<YODAT>;
1735 using RAOT = MultiplexPtr<MultiplexerT>;
1736
1737 if ( !_inInit() && !_inFinalize() ) {
1738 MSG_ERROR("Can't book objects outside of init() or finalize()");
1739 throw UserError(name() + ": Can't book objects outside of init() or finalize().");
1740 }
1741
1742
1743
1744
1745 for (auto& waold : analysisObjects()) {
1746 if ( yao.path() == waold.get()->basePath() ) {
1747 const string msg = "Found double-booking of " + yao.path() + " in " + name();
1748 if ( _inInit() ) {
1749 MSG_ERROR(msg);
1750 throw LookupError(msg);
1751 } else {
1752 MSG_WARNING(msg + ". Keeping previous booking");
1753 }
1754 return RAOT(dynamic_pointer_cast<MultiplexerT>(waold.get()));
1755 }
1756 }
1757
1758 shared_ptr<MultiplexerT> wao = make_shared<MultiplexerT>();
1759 wao->_basePath = yao.path();
1760 YODAPtrT yaop = make_shared<YODAT>(yao);
1761
1762 for (const string& weightname : _weightNames()) {
1763
1764
1765 string finalpath = yao.path();
1766 if ( weightname != "" ) finalpath += "[" + weightname + "]";
1767 YODAPtrT preload = getPreload<YODAT>(finalpath);
1768 if ( preload ) {
1769 if ( !bookingCompatible(preload, yaop) ) {
1770
1771 MSG_WARNING("Found incompatible pre-existing data object with same base path "
1772 << finalpath << " for " << name());
1773 preload = nullptr;
1774 } else {
1775 MSG_TRACE("Using preloaded " << finalpath << " in " <<name());
1776 wao->_final.push_back(make_shared<YODAT>(*preload));
1777 }
1778 }
1779 else {
1780 wao->_final.push_back(make_shared<YODAT>(yao));
1781 wao->_final.back()->setPath(finalpath);
1782 }
1783
1784
1785 string rawpath = "/RAW" + finalpath;
1786 preload = getPreload<YODAT>(rawpath);
1787 if ( preload ) {
1788 if ( !bookingCompatible(preload, yaop) ) {
1789 MSG_WARNING("Found incompatible pre-existing data object with same base path "
1790 << rawpath << " for " << name());
1791 preload = nullptr;
1792 } else {
1793 MSG_TRACE("Using preloaded " << rawpath << " in " <<name());
1794 wao->_persistent.push_back(make_shared<YODAT>(*preload));
1795 }
1796 }
1797 else {
1798 wao->_persistent.push_back(make_shared<YODAT>(yao));
1799 wao->_persistent.back()->setPath(rawpath);
1800 }
1801 }
1802 MultiplexPtr<MultiplexerT> ret(wao);
1803
1804 ret.get()->unsetActiveWeight();
1805 if ( _inFinalize() ) {
1806
1807
1808 ret.get()->pushToFinal();
1809 ret.get()->setActiveFinalWeightIdx(0);
1810 }
1811 _analysisobjects.push_back(ret);
1812
1813 return ret;
1814 }
1815
1816
1817
1818 template <typename AO=MultiplexAOPtr>
1819 AO addAnalysisObject(const AO& aonew) {
1820 _checkBookInit();
1821
1822 for (const MultiplexAOPtr& ao : analysisObjects()) {
1823
1824
1825 ao.get()->setActiveWeightIdx(defaultWeightIndex());
1826 aonew.get()->setActiveWeightIdx(defaultWeightIndex());
1827 if (ao->path() != aonew->path()) continue;
1828
1829
1830
1831 AO aoold = AO(dynamic_pointer_cast<typename AO::value_type>(ao.get()));
1832 if ( !aoold || !bookingCompatible(aonew, aoold) ) {
1833 MSG_WARNING("Found incompatible pre-existing data object with same base path "
1834 << aonew->path() << " for " << name());
1835 throw LookupError("Found incompatible pre-existing data object with same base path during AO booking");
1836 }
1837
1838
1839 for (size_t weightIdx = 0; weightIdx < _weightNames().size(); ++weightIdx) {
1840 aoold.get()->setActiveWeightIdx(weightIdx);
1841 aonew.get()->setActiveWeightIdx(weightIdx);
1842 if (aoold->path() != aonew->path()) {
1843 MSG_WARNING("Found incompatible pre-existing data object with different weight-path "
1844 << aonew->path() << " for " << name());
1845 throw LookupError("Found incompatible pre-existing data object with same weight-path during AO booking");
1846 }
1847 }
1848
1849
1850 aoold.get()->unsetActiveWeight();
1851 MSG_TRACE("Bound pre-existing data object " << aoold->path() << " for " << name());
1852 return aoold;
1853 }
1854
1855
1856 MSG_TRACE("Registered " << aonew->annotation("Type") << " " << aonew->path() << " for " << name());
1857 aonew.get()->unsetActiveWeight();
1858
1859 _analysisobjects.push_back(aonew);
1860 return aonew;
1861 }
1862
1863
1864 void removeAnalysisObject(const std::string& path);
1865
1866
1867 void removeAnalysisObject(const MultiplexAOPtr& ao);
1868
1869
1870 template <typename AO=MultiplexAOPtr>
1871 const AO getAnalysisObject(const std::string& aoname) const {
1872 for (const MultiplexAOPtr& ao : analysisObjects()) {
1873 ao.get()->setActiveWeightIdx(defaultWeightIndex());
1874 if (ao->path() == histoPath(aoname)) {
1875
1876 return AO(dynamic_pointer_cast<typename AO::value_type>(ao.get()));
1877 }
1878 }
1879 throw LookupError("Data object " + histoPath(aoname) + " not found");
1880 }
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904 template <typename AO=MultiplexAOPtr>
1905 AO getAnalysisObject(const std::string& ananame,
1906 const std::string& aoname) {
1907 MultiplexAOPtr ao = _getOtherAnalysisObject(ananame, aoname);
1908
1909 return AO(dynamic_pointer_cast<typename AO::value_type>(ao.get()));
1910 }
1911
1912
1913
1914
1915
1916
1917
1918 template <
1919 typename... Args, typename CONTAINER,
1920 typename = std::enable_if_t<
1921 is_citerable_v<CONTAINER>,
1922 Jet
1923 >
1924 >
1925 static CONTAINER reclusterJets(const CONTAINER &jetsIn, Args&&... args){
1926 return FastJets::reclusterJets(jetsIn, std::forward<Args>(args)...);
1927 }
1928
1929 template <typename T, typename U, typename... Args>
1930 static std::map<T, U> reclusterJets(const std::map<T, U> &jetsMap, Args&&... args){
1931 return FastJets::reclusterJets(jetsMap, std::forward<Args>(args)...);
1932 }
1933
1934 template <
1935 JetAlg JETALG, typename... Args, typename CONTAINER,
1936 typename = std::enable_if_t<
1937 is_citerable_v<CONTAINER>,
1938 Jet
1939 >
1940 >
1941 static CONTAINER reclusterJets(const CONTAINER &jetsIn, Args&&... args){
1942 return FastJets::reclusterJets<JETALG>(jetsIn, std::forward<Args>(args)...);
1943 }
1944
1945 template <JetAlg JETALG, typename T, typename U, typename... Args>
1946 static std::map<T, U> reclusterJets(const std::map<T, U> &jetsMap, Args&&... args){
1947 return FastJets::reclusterJets<JETALG>(jetsMap, std::forward<Args>(args)...);
1948 }
1949
1950
1951
1952
1953 private:
1954
1955
1956 string _defaultname;
1957
1958
1959 unique_ptr<AnalysisInfo> _info;
1960
1961
1962
1963 vector<MultiplexAOPtr> _analysisobjects;
1964
1965
1966
1967 double _crossSection;
1968 bool _gotCrossSection;
1969
1970
1971
1972 AnalysisHandler* _analysishandler;
1973
1974
1975 const Event* _currentevent = nullptr;
1976
1977
1978
1979 mutable std::map<std::string, YODA::AnalysisObjectPtr> _refdata;
1980
1981
1982 map<string, string> _options;
1983
1984
1985 string _optstring;
1986
1987
1988 private:
1989
1990
1991
1992
1993
1994 void _cacheRefData() const;
1995
1996
1997
1998 };
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008 }
2009
2010
2011
2012 #include "Rivet/AnalysisBuilder.hh"
2013
2014
2015
2016
2017
2018
2019
2020 #define RIVET_DECLARE_PLUGIN(clsname) ::Rivet::AnalysisBuilder<clsname> plugin_ ## clsname
2021
2022
2023
2024 #define RIVET_DECLARE_ALIASED_PLUGIN(clsname, alias) RIVET_DECLARE_PLUGIN(clsname)( #alias )
2025
2026
2027
2028 #define RIVET_DEFAULT_ANALYSIS_CTOR(clsname) clsname() : Analysis(# clsname) {}
2029
2030
2031
2032 #define RIVET_REGISTER_TYPE(...) handler().registerType<__VA_ARGS__>()
2033
2034
2035
2036 #define RIVET_REGISTER_BINNED_SET(...) { \
2037 RIVET_REGISTER_TYPE(YODA::BinnedHisto<__VA_ARGS__>); \
2038 RIVET_REGISTER_TYPE(YODA::BinnedProfile<__VA_ARGS__>); \
2039 RIVET_REGISTER_TYPE(YODA::BinnedEstimate<__VA_ARGS__>); }
2040
2041
2042
2043
2044 #endif