File indexing completed on 2025-04-19 09:06:56
0001
0002 #ifndef RIVET_RivetHandler_HH
0003 #define RIVET_RivetHandler_HH
0004
0005 #include "Rivet/Config/RivetCommon.hh"
0006 #include "Rivet/Particle.hh"
0007 #include "Rivet/AnalysisLoader.hh"
0008 #include "Rivet/Tools/RivetYODA.hh"
0009 #include "Rivet/Tools/Utils.hh"
0010 #include "Rivet/ProjectionHandler.hh"
0011 #include "YODA/ReaderYODA.h"
0012
0013 #include <fstream>
0014 #include <unordered_map>
0015
0016 namespace Rivet {
0017
0018
0019
0020 class Analysis;
0021 using AnaHandle = std::shared_ptr<Analysis>;
0022
0023
0024
0025
0026
0027
0028
0029 class AnalysisHandler {
0030
0031 using TypeHandlePtr = std::shared_ptr<TypeBaseHandle>;
0032 using TypeRegister = std::unordered_map<string, TypeHandlePtr>;
0033 using TypeRegisterItr = typename TypeRegister::const_iterator;
0034
0035 public:
0036
0037 using Annotations = std::map<std::string, std::string>;
0038
0039
0040 AnalysisHandler([[deprecated]]const string& runname="");
0041
0042
0043 AnalysisHandler(const AnalysisHandler&) = delete;
0044
0045
0046 AnalysisHandler& operator=(const AnalysisHandler&) = delete;
0047
0048
0049 ~AnalysisHandler();
0050
0051
0052
0053
0054
0055
0056 string runName() const;
0057
0058
0059
0060
0061
0062
0063 size_t numEvents() const {
0064 const double N = _eventCounter.get()->persistent(defaultWeightIndex())->numEntries();
0065 return size_t(N + 0.5 - (N<0));
0066 }
0067
0068
0069
0070
0071
0072
0073 double effNumEvents() const {
0074 if ((bool)_eventCounter) { return _eventCounter->effNumEntries(); }
0075 return _eventCounter.get()->persistent(defaultWeightIndex())->effNumEntries();
0076 }
0077
0078
0079
0080
0081
0082 double sumW() const {
0083 if ((bool)_eventCounter) { return _eventCounter->sumW(); }
0084 return _eventCounter.get()->persistent(defaultWeightIndex())->sumW();
0085 }
0086
0087 double sumW2() const {
0088 if ((bool)_eventCounter) { return _eventCounter->sumW2(); }
0089 return _eventCounter.get()->persistent(defaultWeightIndex())->sumW2();
0090 }
0091
0092
0093
0094
0095
0096
0097
0098
0099 const vector<string>& weightNames() const { return _weightNames; }
0100
0101
0102 size_t numWeights() const { return _weightNames.size(); }
0103
0104
0105 bool haveNamedWeights() const;
0106
0107
0108 void setWeightNames(const GenEvent& ge);
0109
0110
0111 void setWeightNames(const vector<string>& weightNames);
0112
0113
0114 size_t defaultWeightIndex() const { return _rivetDefaultWeightIdx; }
0115
0116
0117 vector<double> weightSumWs() const;
0118
0119
0120 void setWeightCap(const double maxWeight) { _weightCap = maxWeight; }
0121
0122
0123 void setNominalWeightName(const std::string& name) { _nominalWeightName = name; }
0124
0125
0126 void skipMultiWeights(bool skip=false) { _skipMultiWeights = skip; }
0127
0128
0129 void matchWeightNames(const std::string& patterns) { _matchWeightNames = patterns; }
0130
0131
0132 void unmatchWeightNames(const std::string& patterns) { _unmatchWeightNames = patterns; }
0133
0134
0135 void setNLOSmearing(double frac) { _NLOSmearing = frac; }
0136
0137
0138
0139
0140
0141
0142
0143
0144 Estimate0DPtr crossSection() const { return _xs; }
0145
0146
0147 void setCrossSection(const vector<pair<double,double>>& xsecs, bool isUserSupplied = false);
0148
0149
0150 void setCrossSection(const pair<double, double>& xsec, bool isUserSupplied=false);
0151
0152
0153 void setCrossSection(double xsec, double xsecerr, bool isUserSupplied=false) {
0154 setCrossSection({xsec, xsecerr}, isUserSupplied);
0155 }
0156
0157
0158
0159
0160 void updateCrossSection();
0161
0162
0163 void notifyEndOfFile() { _isEndOfFile = true; }
0164
0165
0166 double nominalCrossSection() const;
0167
0168
0169 double nominalCrossSectionError() const;
0170
0171
0172
0173
0174
0175
0176
0177
0178 AnalysisHandler& setRunBeams(const ParticlePair& beams);
0179
0180
0181 const ParticlePair& runBeams() const { return _beams; }
0182
0183
0184 PdgIdPair runBeamIDs() const;
0185
0186
0187 pair<double,double> runBeamEnergies() const;
0188
0189
0190 double runSqrtS() const;
0191
0192
0193 void setCheckBeams(bool check=true) { _checkBeams = check; }
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207 std::vector<std::string> annotations() const {
0208 return _beaminfo->annotations();
0209 }
0210
0211
0212 bool hasAnnotation(const std::string& name) const {
0213 return _beaminfo->hasAnnotation(name);
0214 }
0215
0216
0217 const std::string& annotation(const std::string& name) const {
0218 return _beaminfo->annotation(name);
0219 }
0220
0221
0222 const std::string& annotation(const std::string& name, const std::string& defaultreturn) const {
0223 return _beaminfo->annotation(name, defaultreturn);
0224 }
0225
0226
0227
0228
0229 template <typename T>
0230 const T annotation(const std::string& name) const {
0231 return _beaminfo->annotation<T>(name);
0232 }
0233
0234
0235
0236
0237 template <typename T>
0238 const T annotation(const std::string& name, T&& defaultreturn) const {
0239 return _beaminfo->annotation<T>(name, std::forward<T>(defaultreturn));
0240 }
0241
0242
0243
0244
0245 template <typename T>
0246 void setAnnotation(const std::string& name, T&& value) {
0247 _beaminfo->annotation<T>(name, std::forward<T>(value));
0248 }
0249
0250
0251
0252 void setAnnotations(const Annotations& anns) {
0253 _beaminfo->setAnnotations(anns);
0254 }
0255
0256
0257 void rmAnnotation(const std::string& name) {
0258 _beaminfo->rmAnnotation(name);
0259 }
0260
0261
0262
0263 void clearAnnotations() {
0264 _beaminfo->clearAnnotations();
0265 }
0266
0267
0268
0269
0270
0271
0272
0273
0274 template<typename T>
0275 void registerType() {
0276 const std::string name = T().type();
0277 const TypeRegisterItr& res = _register.find(name);
0278 if (res == _register.end()) {
0279 _register[name] = make_shared<TypeHandle<T>>();
0280 }
0281 _reader.registerType<T>();
0282 }
0283
0284
0285
0286 bool copyAO(YODA::AnalysisObjectPtr src, YODA::AnalysisObjectPtr dst, const double scale=1.0);
0287
0288
0289
0290 bool addAO(YODA::AnalysisObjectPtr src, YODA::AnalysisObjectPtr& dst, const double scale);
0291
0292
0293
0294
0295
0296
0297
0298
0299 std::vector<std::string> analysisNames() const;
0300
0301
0302 std::vector<std::string> stdAnalysisNames() const;
0303
0304
0305 const std::map<std::string, AnaHandle>& analysesMap() const {
0306 return _analyses;
0307 }
0308
0309
0310 std::vector<AnaHandle> analyses() const {
0311 std::vector<AnaHandle> rtn;
0312 rtn.reserve(_analyses.size());
0313 for (const auto& apair : _analyses) rtn.push_back(apair.second);
0314 return rtn;
0315 }
0316
0317
0318 AnaHandle analysis(const std::string& analysisname) {
0319 if ( _analyses.find(analysisname) == _analyses.end() )
0320 throw LookupError("No analysis named '" + analysisname + "' registered in AnalysisHandler");
0321 try {
0322 return _analyses[analysisname];
0323 } catch (...) {
0324 throw LookupError("No analysis named '" + analysisname + "' registered in AnalysisHandler");
0325 }
0326 }
0327
0328
0329 AnalysisHandler& addAnalysis(Analysis* analysis);
0330
0331
0332
0333
0334
0335
0336 AnalysisHandler& addAnalysis(const std::string& analysisname);
0337
0338
0339 AnalysisHandler& addAnalysis(const std::string& analysisname, std::map<string, string> pars);
0340
0341
0342
0343
0344
0345
0346
0347 AnalysisHandler& addAnalyses(const std::vector<std::string>& analysisnames);
0348
0349
0350
0351 AnalysisHandler& removeAnalysis(const std::string& analysisname);
0352
0353
0354 AnalysisHandler& removeAnalyses(const std::vector<std::string>& analysisnames);
0355
0356
0357
0358
0359
0360
0361
0362
0363 void init(const GenEvent& event);
0364
0365
0366
0367
0368
0369
0370
0371 void analyze(GenEvent& event);
0372
0373
0374
0375
0376
0377 void analyze(GenEvent* event);
0378
0379
0380
0381 void finalize();
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391 void collapseEventGroup();
0392
0393
0394
0395
0396 void readData(std::istream& istr, const string& fmt, bool preload = true);
0397
0398
0399 void readData(const std::string& filename, bool preload = true);
0400
0401
0402
0403
0404 vector<YODA::AnalysisObjectPtr> getYodaAOs(const bool includeraw=false, const bool mkinert=true) const;
0405
0406
0407 vector<YODA::AnalysisObjectPtr> getRawAOs() const;
0408
0409
0410 vector<std::string> getRawAOPaths() const;
0411
0412
0413
0414 const YODA::AnalysisObjectPtr getPreload(const string& path) const {
0415 auto it = _preloads.find(path);
0416 if ( it == _preloads.end() ) return nullptr;
0417 return it->second;
0418 }
0419
0420
0421
0422
0423 void writeData(std::ostream& ostr, const string& fmt) const;
0424
0425
0426 void writeData(const string& filename) const;
0427
0428
0429
0430
0431
0432
0433 void setFinalizePeriod(const string& dumpfile, int period) {
0434 _dumpPeriod = period;
0435 _dumpFile = dumpfile;
0436 }
0437
0438 void setNoFinalizePeriod() {
0439 setFinalizePeriod("DUMMY", -1);
0440 }
0441
0442
0443 void setBootstrapFilename(const string& filename) {
0444 _bootstrapfilename = filename;
0445 }
0446
0447
0448 vector<pair<string,size_t>> fillLayout() const;
0449
0450
0451 vector<bool> fillOutcomes() const;
0452
0453
0454 vector<double> fillFractions() const;
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471 void mergeYODAs(const vector<string>& aofiles,
0472 const vector<string>& delopts=vector<string>(),
0473 const vector<string>& addopts=vector<string>(),
0474 const vector<string>& matches=vector<string>(),
0475 const vector<string>& unmatches=vector<string>(),
0476 const bool equiv=false, const bool reentrantOnly = true);
0477
0478
0479 void merge(AnalysisHandler &other);
0480
0481
0482
0483
0484
0485
0486 void loadAOs(const vector<string>& aoPaths, const vector<double>& aoData);
0487
0488
0489
0490
0491
0492
0493 vector<double> serializeContent(bool fixed_length = false) {
0494 if (!_initialised)
0495 throw Error("AnalysisHandler has not been initialised!");
0496
0497 collapseEventGroup();
0498
0499
0500 const vector<YODA::AnalysisObjectPtr> raos = getRawAOs();
0501 size_t total = 0;
0502 for (size_t i = 0; i < raos.size(); ++i) {
0503 total += raos[i]->lengthContent(fixed_length)+1;
0504 }
0505 total += _beaminfo->numBins()+1;
0506
0507
0508 std::vector<double> data;
0509 data.reserve(total);
0510
0511 data.push_back(_beaminfo->numBins());
0512 for (const string& beamID : _beaminfo->xEdges()) {
0513 data.push_back(_beamInfoLabelToID(beamID));
0514 }
0515
0516 for (size_t i = 0; i < raos.size(); ++i) {
0517 vector<double> tmp = raos[i]->serializeContent(fixed_length);
0518 data.push_back(tmp.size());
0519 data.insert(std::end(data),
0520 std::make_move_iterator(std::begin(tmp)),
0521 std::make_move_iterator(std::end(tmp)));
0522 }
0523 return data;
0524 }
0525
0526 void deserializeContent(const vector<double>& data, size_t nprocs = 0) {
0527 if (!_initialised)
0528 throw Error("AnalysisHandler has not been initialised!");
0529
0530 collapseEventGroup();
0531
0532
0533 vector<MultiplexAOPtr> raos = getRivetAOs();
0534
0535
0536
0537 size_t iAO = 0, iW = 0, nBeams = data[0], offset = 1;
0538 if (nprocs) nBeams /= nprocs;
0539 const auto itr = data.cbegin();
0540
0541 vector<int> edges{itr+offset, itr+offset+nBeams};
0542 vector<string> labels; labels.reserve(edges.size());
0543 size_t id = 0;
0544 for (int edge : edges) {
0545 if (nprocs >= 2) edge /= nprocs;
0546 labels.push_back(_mkBeamInfoLabel(++id, edge));
0547 }
0548
0549 _beaminfo = make_shared<YODA::BinnedEstimate<string>>(labels, "/TMP/_BEAMPZ");
0550 offset += nBeams;
0551
0552 size_t beamLen = *(itr + offset); ++offset;
0553 if (nprocs) beamLen /= nprocs;
0554 std::vector<double> energies{itr+offset, itr+offset+beamLen};
0555 if (nprocs >= 2) {
0556 for (double& e : energies) { e /= nprocs; }
0557 }
0558 _beaminfo->deserializeContent(energies);
0559 for (auto& b : _beaminfo->bins(true)) b.rmErrs();
0560 offset += beamLen;
0561
0562
0563 while (offset < data.size()) {
0564 if (iW < numWeights()) raos[iAO].get()->setActiveWeightIdx(iW);
0565 else {
0566 raos[iAO].get()->unsetActiveWeight();
0567 iW = 0; ++iAO;
0568 raos[iAO].get()->setActiveWeightIdx(iW);
0569 }
0570
0571
0572 size_t aoLen = *(itr + offset); ++offset;
0573 if (nprocs) aoLen /= nprocs;
0574 auto first = itr + offset;
0575 auto last = first + aoLen;
0576
0577 raos[iAO].get()->activeAO()->deserializeContent(std::vector<double>{first, last});
0578
0579 ++iW; offset += aoLen;
0580 }
0581 raos[iAO].get()->unsetActiveWeight();
0582
0583 _ntrials = 0.0;
0584 _fileCounter = CounterPtr(weightNames(), Counter("_FILECOUNT"));
0585 _xserr = CounterPtr(weightNames(), Counter("XSECERR"));
0586 if (nprocs >= 2) {
0587 for (size_t iW = 0; iW < numWeights(); ++iW) {
0588 *_fileCounter.get()->persistent(iW) = *_eventCounter.get()->persistent(iW);
0589 _xs.get()->persistent(iW)->scale(1.0/nprocs);
0590 }
0591 }
0592 }
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602 enum class Stage { OTHER, INIT, FINALIZE };
0603
0604
0605 Stage stage() const { return _stage; }
0606
0607
0608
0609 private:
0610
0611
0612
0613
0614
0615 Log& getLog() const;
0616
0617
0618 vector<MultiplexAOPtr> getRivetAOs() const;
0619
0620
0621 void stripOptions(YODA::AnalysisObjectPtr ao, const vector<string>& delopts) const;
0622
0623
0624 void mergeAOS(map<string, YODA::AnalysisObjectPtr> &allaos,
0625 const map<string, YODA::AnalysisObjectPtr> &newaos,
0626 map<string, std::array<double,4>> &allxsecs,
0627 const vector<string>& delopts=vector<string>(),
0628 const vector<string>& optAnas=vector<string>(),
0629 const vector<string>& optKeys=vector<string>(),
0630 const vector<string>& optVals=vector<string>(),
0631 const bool equiv=false,
0632 const bool overwrite_xsec = false,
0633 const double user_xsec = 1.0);
0634
0635
0636
0637
0638
0639
0640 void loadAOs(const map<string, YODA::AnalysisObjectPtr>& allAOs,
0641 const bool unscale = false, const bool reentrantOnly = true);
0642
0643
0644 void _setRunBeamInfo(const ParticlePair& beams);
0645
0646
0647 void _setRunBeamInfo(YODA::AnalysisObjectPtr ao);
0648
0649
0650 string _mkBeamInfoLabel(size_t n, PdgId id) {
0651 return "BEAM"+std::to_string(n)+"("+std::to_string(id)+")";
0652 }
0653
0654
0655 PdgId _beamInfoLabelToID(const string& label) {
0656 size_t pos = label.find("(");
0657 string beamID = label.substr(pos+1, label.size()-pos-2);
0658 return std::stoi(beamID);
0659 }
0660
0661
0662
0663
0664
0665 private:
0666
0667
0668 Stage _stage = Stage::OTHER;
0669
0670
0671 std::map<std::string, AnaHandle> _analyses;
0672
0673
0674
0675
0676 map<string,YODA::AnalysisObjectPtr> _preloads;
0677
0678
0679 vector<YODA::AnalysisObjectPtr> _finalizedAOs;
0680
0681
0682 template<typename... Args>
0683 void registerDefaultTypes();
0684
0685
0686 TypeRegister _register;
0687
0688
0689 YODA::Reader& _reader = YODA::ReaderYODA::create();
0690
0691
0692
0693
0694
0695
0696 std::vector<std::string> _weightNames;
0697 std::vector<std::valarray<double> > _subEventWeights;
0698
0699
0700
0701 std::vector<size_t> _weightIndices;
0702
0703
0704 std::string _runname;
0705
0706
0707 CounterPtr _eventCounter;
0708
0709
0710 Estimate0DPtr _xs;
0711
0712
0713 CounterPtr _xserr;
0714
0715
0716 YODA::BinnedEstimatePtr<string> _beaminfo;
0717
0718
0719 double _ntrials;
0720
0721
0722 CounterPtr _fileCounter;
0723
0724
0725 bool _isEndOfFile;
0726
0727
0728 std::pair<double,double> _userxs;
0729
0730
0731 ParticlePair _beams;
0732
0733
0734 bool _initialised;
0735
0736
0737 bool _checkBeams;
0738
0739
0740 bool _skipMultiWeights;
0741
0742
0743 std::string _matchWeightNames;
0744
0745
0746 std::string _unmatchWeightNames;
0747
0748
0749 std::string _nominalWeightName;
0750
0751
0752 double _weightCap;
0753
0754
0755
0756
0757 double _NLOSmearing;
0758
0759
0760 int _eventNumber;
0761
0762
0763 size_t _defaultWeightIdx;
0764
0765
0766 size_t _rivetDefaultWeightIdx;
0767
0768
0769 int _customDefaultWeightIdx;
0770
0771
0772 int _dumpPeriod;
0773
0774
0775 string _dumpFile;
0776
0777
0778 bool _dumping;
0779
0780
0781 ofstream _fbootstrap;
0782
0783
0784 std::string _bootstrapfilename;
0785
0786
0787 ProjectionHandler _projHandler;
0788
0789
0790
0791 };
0792
0793
0794 }
0795
0796 #endif