Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-19 09:06:56

0001 // -*- C++ -*-
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   // Forward declaration and smart pointer for Analysis
0020   class Analysis;
0021   using AnaHandle = std::shared_ptr<Analysis>;
0022 
0023 
0024   /// @brief The key class for coordination of Analysis objects and the event loop
0025   ///
0026   /// A class which handles a number of analysis objects to be applied to
0027   /// generated events. An {@link Analysis}' AnalysisHandler is also responsible
0028   /// for handling the final writing-out of histograms.
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     /// Preferred constructor, with optional run name.
0040     AnalysisHandler([[deprecated]]const string& runname="");
0041 
0042     /// The copy constructor is deleted, so it can never be called.
0043     AnalysisHandler(const AnalysisHandler&) = delete;
0044 
0045     /// The assignment operator is deleted, so it can never be called.
0046     AnalysisHandler& operator=(const AnalysisHandler&) = delete;
0047 
0048     /// The destructor is not virtual, as this class should not be inherited from.
0049     ~AnalysisHandler();
0050 
0051 
0052     /// @name Run properties
0053     /// @{
0054 
0055     /// Get the name of this run.
0056     string runName() const;
0057 
0058     /// Get the number of events seen. Should only really be used by external
0059     /// steering code or analyses in the finalize phase.
0060     ///
0061     /// N.B. This only reports the count for the last collapsed event group
0062     /// and hence ignores any additional sub-events seen so far.
0063     size_t numEvents() const {
0064       const double N = _eventCounter.get()->persistent(defaultWeightIndex())->numEntries();
0065       return  size_t(N + 0.5 - (N<0)); // round to nearest integer
0066     }
0067 
0068     /// Get the effective number of events seen. Should only really be used by external
0069     /// steering code or analyses in the finalize phase.
0070     ///
0071     /// N.B. This only reports the count for the last collapsed event group
0072     /// and hence ignores any additional sub-events seen so far.
0073     double effNumEvents() const {
0074       if ((bool)_eventCounter) { return _eventCounter->effNumEntries(); }
0075       return _eventCounter.get()->persistent(defaultWeightIndex())->effNumEntries();
0076     }
0077 
0078     /// @brief Access the sum of the event weights seen
0079     ///
0080     /// This is the weighted equivalent of the number of events. It should only
0081     /// be used by external steering code or analyses in the finalize phase.
0082     double sumW() const {
0083       if ((bool)_eventCounter) { return _eventCounter->sumW(); }
0084       return _eventCounter.get()->persistent(defaultWeightIndex())->sumW();
0085     }
0086     /// Access to the sum of squared-weights
0087     double sumW2() const {
0088       if ((bool)_eventCounter) { return _eventCounter->sumW2(); }
0089       return _eventCounter.get()->persistent(defaultWeightIndex())->sumW2();
0090     }
0091 
0092     /// @}
0093 
0094 
0095     /// @name Event weights
0096     /// @{
0097 
0098     /// Names of event weight categories
0099     const vector<string>& weightNames() const { return _weightNames; }
0100 
0101     /// Are any of the weights non-numeric?
0102     size_t numWeights() const { return _weightNames.size(); }
0103 
0104     /// Are any of the weights non-numeric?
0105     bool haveNamedWeights() const;
0106 
0107     /// Set the weight names from a GenEvent
0108     void setWeightNames(const GenEvent& ge);
0109 
0110     /// Set the weight names from a vector<string>
0111     void setWeightNames(const vector<string>& weightNames);
0112 
0113     /// Get the index of the nominal weight-stream
0114     size_t defaultWeightIndex() const { return _rivetDefaultWeightIdx; }
0115 
0116     /// @brief Access the array of sum of the event weights seen
0117     vector<double> weightSumWs() const;
0118 
0119     /// Set the weight cap
0120     void setWeightCap(const double maxWeight) { _weightCap = maxWeight; }
0121 
0122     /// Set the name of the nominal weight stream
0123     void setNominalWeightName(const std::string& name) { _nominalWeightName = name; }
0124 
0125     /// Ignore all weight streams other than the nominal
0126     void skipMultiWeights(bool skip=false) { _skipMultiWeights = skip; }
0127 
0128     /// Specify weight-name patterns to accept
0129     void matchWeightNames(const std::string& patterns) { _matchWeightNames = patterns; }
0130 
0131     /// Specify weight-name patterns to reject
0132     void unmatchWeightNames(const std::string& patterns) { _unmatchWeightNames = patterns; }
0133 
0134     /// Set the relative width of the NLO smearing window.
0135     void setNLOSmearing(double frac) { _NLOSmearing = frac; }
0136 
0137     /// @}
0138 
0139 
0140     /// @name Cross-sections
0141     /// @{
0142 
0143     /// Get the cross-section known to the handler
0144     Estimate0DPtr crossSection() const { return _xs; }
0145 
0146     /// Set all cross-sections for the process being generated specifically (preferred)
0147     void setCrossSection(const vector<pair<double,double>>& xsecs, bool isUserSupplied = false);
0148 
0149     /// Set all cross-sections for the process being generated, based on nominal weight
0150     void setCrossSection(const pair<double, double>& xsec, bool isUserSupplied=false);
0151 
0152     /// Set the cross-section for the process being generated (alternative signature)
0153     void setCrossSection(double xsec, double xsecerr, bool isUserSupplied=false) {
0154       setCrossSection({xsec, xsecerr}, isUserSupplied);
0155     }
0156 
0157     /// Update the internal cross-section average when running over multiple files
0158     ///
0159     /// @note This method should only be called when switching HepMC file mid-run.
0160     void updateCrossSection();
0161 
0162     /// Toggle to signal a change in HepMC input file
0163     void notifyEndOfFile() { _isEndOfFile = true; }
0164 
0165     /// Get the nominal cross-section
0166     double nominalCrossSection() const;
0167 
0168     /// Get the nominal cross-section
0169     double nominalCrossSectionError() const;
0170 
0171     /// @}
0172 
0173 
0174     /// @name Beams
0175     /// @{
0176 
0177     /// Set the beam particles for this run
0178     AnalysisHandler& setRunBeams(const ParticlePair& beams);
0179 
0180     /// Get the beam particles for this run, usually determined from the first event
0181     const ParticlePair& runBeams() const { return _beams; }
0182 
0183     /// Get beam IDs for this run, usually determined from the first event
0184     PdgIdPair runBeamIDs() const;
0185 
0186     /// Get beam IDs for this run, usually determined from the first event
0187     pair<double,double> runBeamEnergies() const;
0188 
0189     /// Get energy for this run, usually determined from the first event
0190     double runSqrtS() const;
0191 
0192     /// Option to disable analysis-compatibility checks
0193     void setCheckBeams(bool check=true) { _checkBeams = check; }
0194 
0195     /// Option to disable run-consistency checks
0196     // void setCheckConsistency(bool check=true) { _checkConsistency = check; }
0197     // Check event consistency with the run, usually determined from the first event
0198     // bool consistentWithRun(Event& event) {
0199 
0200     /// @}
0201 
0202 
0203     /// @name Run-based annotations
0204     /// @{
0205 
0206     // Get all the annotation names
0207     std::vector<std::string> annotations() const {
0208       return _beaminfo->annotations();
0209     }
0210 
0211     /// Check if an annotation is defined
0212     bool hasAnnotation(const std::string& name) const {
0213       return _beaminfo->hasAnnotation(name);
0214     }
0215 
0216     /// Get an annotation by name (as a string)
0217     const std::string& annotation(const std::string& name) const {
0218       return _beaminfo->annotation(name);
0219     }
0220 
0221     /// Get an annotation by name (as a string) with a default in case the annotation is not found
0222     const std::string& annotation(const std::string& name, const std::string& defaultreturn) const {
0223       return _beaminfo->annotation(name, defaultreturn);
0224     }
0225 
0226     /// @brief Get an annotation by name (copied to another type)
0227     ///
0228     /// @note Templated on return type
0229     template <typename T>
0230     const T annotation(const std::string& name) const {
0231       return _beaminfo->annotation<T>(name);
0232     }
0233 
0234     /// @brief Get an annotation by name (copied to another type) with a default in case the annotation is not found
0235     ///
0236     /// @note Templated on return type
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     /// @brief Add or set an annotation by name (templated for remaining types)
0243     ///
0244     /// @note Templated on arg type, but stored as a string.
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     /// Set all annotations at once
0252     void setAnnotations(const Annotations& anns) {
0253       _beaminfo->setAnnotations(anns);
0254     }
0255 
0256     /// Delete an annotation by name
0257     void rmAnnotation(const std::string& name) {
0258       _beaminfo->rmAnnotation(name);
0259     }
0260 
0261 
0262     /// Delete an annotation by name
0263     void clearAnnotations() {
0264       _beaminfo->clearAnnotations();
0265     }
0266 
0267     /// @}
0268 
0269 
0270     /// @name AO type handling
0271     /// @{
0272 
0273     /// Register an AO type handle into type map and YODA reader
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>(); // also let YODA know
0282     }
0283 
0284     /// If @a dst is the same subclass as @a src, copy the contents of
0285     /// @a src into @a dst and return true. Otherwise return false.
0286     bool copyAO(YODA::AnalysisObjectPtr src, YODA::AnalysisObjectPtr dst, const double scale=1.0);
0287 
0288     /// If @a dst is the same subclass as @a src, scale the contents of @a src with
0289     /// @a scale and add it to @a dst and return true. Otherwise return false.
0290     bool addAO(YODA::AnalysisObjectPtr src, YODA::AnalysisObjectPtr& dst, const double scale);
0291 
0292     /// @}
0293 
0294 
0295     /// @name Analysis handling
0296     /// @{
0297 
0298     /// Get a list of the currently registered analyses' names.
0299     std::vector<std::string> analysisNames() const;
0300 
0301     /// Get a list of the official analysis names for this release.
0302     std::vector<std::string> stdAnalysisNames() const;
0303 
0304     /// Get the collection of currently registered analyses.
0305     const std::map<std::string, AnaHandle>& analysesMap() const {
0306       return _analyses;
0307     }
0308 
0309     /// Get the collection of currently registered analyses.
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     /// Get a registered analysis by name.
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     /// Add an analysis to the run list by object
0329     AnalysisHandler& addAnalysis(Analysis* analysis);
0330 
0331     /// @brief Add an analysis to the run list using its name.
0332     ///
0333     /// The actual Analysis to be used will be obtained via
0334     /// AnalysisLoader::getAnalysis(string).  If no matching analysis is found,
0335     /// no analysis is added (i.e. the null pointer is checked and discarded.
0336     AnalysisHandler& addAnalysis(const std::string& analysisname);
0337 
0338     /// @brief Add an analysis with a map of analysis options.
0339     AnalysisHandler& addAnalysis(const std::string& analysisname, std::map<string, string> pars);
0340 
0341     /// @brief Add analyses to the run list using their names.
0342     ///
0343     /// The actual {@link Analysis}' to be used will be obtained via
0344     /// AnalysisHandler::addAnalysis(string), which in turn uses
0345     /// AnalysisLoader::getAnalysis(string). If no matching analysis is found
0346     /// for a given name, no analysis is added, but also no error is thrown.
0347     AnalysisHandler& addAnalyses(const std::vector<std::string>& analysisnames);
0348 
0349 
0350     /// Remove an analysis from the run list using its name.
0351     AnalysisHandler& removeAnalysis(const std::string& analysisname);
0352 
0353     /// Remove analyses from the run list using their names.
0354     AnalysisHandler& removeAnalyses(const std::vector<std::string>& analysisnames);
0355 
0356     /// @}
0357 
0358 
0359     /// @name Main init/execute/finalise
0360     /// @{
0361 
0362     /// Initialize a run, with the run beams taken from the example event
0363     void init(const GenEvent& event);
0364 
0365     /// @brief Analyze the given @a event by reference
0366     ///
0367     /// This function will call the AnalysisBase::analyze() function of all
0368     /// included analysis objects.
0369     ///
0370     /// @note Despite the event being passed as const, its units etc. may be changed, hence non-const.
0371     void analyze(GenEvent& event);
0372 
0373     /// @brief Analyze the given @a event by pointer
0374     ///
0375     /// This function will call the AnalysisBase::analyze() function of all
0376     /// included analysis objects, after checking the event pointer validity.
0377     void analyze(GenEvent* event);
0378 
0379     /// Finalize a run. This function calls the AnalysisBase::finalize()
0380     /// functions of all included analysis objects.
0381     void finalize();
0382 
0383     /// @}
0384 
0385 
0386     /// @name Histogram / data object access
0387     /// @{
0388 
0389     /// After all subevents in an event group have been processed, push
0390     /// all histo fills to the relevant histograms.
0391     void collapseEventGroup();
0392 
0393     /// @brief Read analysis plots into the histo collection from the given stream
0394     ///
0395     /// Use the @a fmt flag to specify the YODA output format (yoda, yoda.gz, yoda.h5, ...)
0396     void readData(std::istream& istr, const string& fmt, bool preload = true);
0397 
0398     /// Read analysis plots into the histo collection (via addData) from the named file.
0399     void readData(const std::string& filename, bool preload = true);
0400 
0401     /// Get all YODA analysis objects (across all weights, optionally including RAW)
0402     ///
0403     /// @note We'll live with the mixed-case "Yoda" here, since the consistent all-caps would be worse!
0404     vector<YODA::AnalysisObjectPtr> getYodaAOs(const bool includeraw=false, const bool mkinert=true) const;
0405 
0406     /// Get all raw YODA analysis objects (across all weights)
0407     vector<YODA::AnalysisObjectPtr> getRawAOs() const;
0408 
0409     /// Get all raw YODA analysis object paths (across all weights)
0410     vector<std::string> getRawAOPaths() const;
0411 
0412     /// Get a pointer to a preloaded yoda object with the given path,
0413     /// or null if path is not found.
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     /// @brief Write all analyses' plots (via getData) to the given stream.
0421     ///
0422     /// Use the @a fmt flag to specify the YODA output format (yoda, yoda.gz, yoda.h5, ...)
0423     void writeData(std::ostream& ostr, const string& fmt) const;
0424 
0425     /// Write all analyses' plots (via getData) to the named file.
0426     void writeData(const string& filename) const;
0427 
0428     /// @brief Configure the AnalysisObject dump rate and destination.
0429     ///
0430     /// Tell Rivet to dump intermediate result to a file named @a
0431     /// dumpfile every @a period'th event. If @a period is not positive,
0432     /// no periodic finalization will be done.
0433     void setFinalizePeriod(const string& dumpfile, int period) {
0434       _dumpPeriod = period;
0435       _dumpFile = dumpfile;
0436     }
0437     /// @brief Configure the AnalysisObject dump rate and destination.
0438     void setNoFinalizePeriod() {
0439       setFinalizePeriod("DUMMY", -1);
0440     }
0441 
0442     /// @brief Set filename of the bootstrap file
0443     void setBootstrapFilename(const string& filename) {
0444       _bootstrapfilename = filename;
0445     }
0446 
0447     /// Return a vector of (AO path, AO numBins) pairs to decode the fills layout
0448     vector<pair<string,size_t>> fillLayout() const;
0449 
0450     /// Return a vector of the binary fill outcome (was/wasn't filled) at each fill position
0451     vector<bool> fillOutcomes() const;
0452 
0453     /// Return a vector of the fill fraction at each fill position
0454     vector<double> fillFractions() const;
0455 
0456     /// @brief Merge the vector of YODA files, using the cross-section and weight information provided in each.
0457     ///
0458     /// Each file in @a aofiles is assumed to have been produced by Rivet. By
0459     /// default the files are assumed to contain different processes (or the
0460     /// same processs but mutually exclusive cuts), but if @a equiv if true, the
0461     /// files are assumed to contain output of completely equivalent (but
0462     /// statistically independent) Rivet runs. The corresponding analyses will
0463     /// be loaded and their analysis objects will be filled with the merged
0464     /// result. finalize() will be run on each relevant analysis. The resulting
0465     /// YODA file can then be written out by writeData().
0466     ///
0467     /// If @a delopts is non-empty, it is assumed to contain names of different
0468     /// options to be merged into the same analysis objects.
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     /// A method to merge another AnalysisHandler into the current one
0479     void merge(AnalysisHandler &other);
0480 
0481     /// @brief A method to prepare a re-entrant run for a given set
0482     /// of AO paths and serialized AO data
0483     ///
0484     /// The @a unscale parameter multiplies fillable objects with sumW/xsec to counteract
0485     /// the cross-section scaling in finalize() when merging different processes (non-equiv)
0486     void loadAOs(const vector<string>& aoPaths, const vector<double>& aoData);
0487 
0488     /// @}
0489 
0490     /// @name MPI (de-)serialisation
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       // Loop over raw AOs and work out the size of the content data
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       // Loop over raw AOs and retrieve the content data
0508       std::vector<double> data; // serialized data vector
0509       data.reserve(total); // pre-allocate enough memory
0510       // Add beam IDs
0511       data.push_back(_beaminfo->numBins());
0512       for (const string& beamID : _beaminfo->xEdges()) {
0513         data.push_back(_beamInfoLabelToID(beamID));
0514       }
0515       // Add raw YODA AO content
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()); // length of the AO
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       // get Rivet AOs for access to raw AO pointers
0533       vector<MultiplexAOPtr> raos = getRivetAOs();
0534 
0535 
0536       // beam info first
0537       size_t iAO = 0, iW = 0, nBeams = data[0], offset = 1;
0538       if (nprocs)  nBeams /= nprocs;
0539       const auto itr = data.cbegin();
0540       // set beam IDs
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       // set beam momenta
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       // then the multiweighted AOs
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; // move on to next AO
0568           raos[iAO].get()->setActiveWeightIdx(iW);
0569         }
0570 
0571         // obtain content length and set content iterators
0572         size_t aoLen = *(itr + offset); ++offset;
0573         if (nprocs)  aoLen /= nprocs;
0574         auto first = itr + offset;
0575         auto last = first + aoLen;
0576         // load data into AO
0577         raos[iAO].get()->activeAO()->deserializeContent(std::vector<double>{first, last});
0578 
0579         ++iW; offset += aoLen; // increment offset
0580       }
0581       raos[iAO].get()->unsetActiveWeight();
0582       // Reset cross-section bookkeeping
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     /// @name Processing stage
0598     /// @{
0599 
0600     /// Indicate which Rivet stage we're in.
0601     /// At the moment, only INIT is used to enable booking.
0602     enum class Stage { OTHER, INIT, FINALIZE };
0603 
0604     /// Return the current processing stage.
0605     Stage stage() const { return _stage; }
0606 
0607     /// @}
0608 
0609   private:
0610 
0611     /// @name Internal helper functions
0612     /// @{
0613 
0614     /// Get a logger object.
0615     Log& getLog() const;
0616 
0617     /// Get all multi-weight Rivet analysis object wrappers.
0618     vector<MultiplexAOPtr> getRivetAOs() const;
0619 
0620     /// Helper function to strip specific options from data object paths.
0621     void stripOptions(YODA::AnalysisObjectPtr ao, const vector<string>& delopts) const;
0622 
0623     /// @brief Merge the AO map @a newaos into @a allaos
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     /// @brief A method to prepare a re-entrant run for a given set of analysis objects
0637     ///
0638     /// The @a unscale parameter multiplies fillable objects with sumW/xsec to counteract
0639     /// the cross-section scaling in finalize() when merging different processes (non-equiv)
0640     void loadAOs(const map<string, YODA::AnalysisObjectPtr>& allAOs,
0641                  const bool unscale = false, const bool reentrantOnly = true);
0642 
0643     /// @brief A method to set the internal _beaminfo object from a pair of beams
0644     void _setRunBeamInfo(const ParticlePair& beams);
0645 
0646     /// @brief A method to set the internal _beaminfo object from an existing YODA AO
0647     void _setRunBeamInfo(YODA::AnalysisObjectPtr ao);
0648 
0649     /// Construct beaminfo label from ID
0650     string _mkBeamInfoLabel(size_t n, PdgId id) {
0651       return "BEAM"+std::to_string(n)+"("+std::to_string(id)+")";
0652     }
0653 
0654     /// Retrieve ID from beaminfo label
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     /// Current handler processing stage.
0668     Stage _stage = Stage::OTHER;
0669 
0670     /// The collection of Analysis objects to be used.
0671     std::map<std::string, AnaHandle> _analyses;
0672 
0673     /// A vector of pre-loaded object which do not have a valid Analysis plugged in.
0674     ///
0675     /// @todo Rename to _preloadedAOs for consistency
0676     map<string,YODA::AnalysisObjectPtr> _preloads;
0677 
0678     /// A vector containing copies of analysis objects after finalize() has been run.
0679     vector<YODA::AnalysisObjectPtr> _finalizedAOs;
0680 
0681     /// Loads a default set of YODA AO types into the TypeHandleMap
0682     template<typename... Args>
0683     void registerDefaultTypes();
0684 
0685     /// The TypeRegister of all registered types
0686     TypeRegister _register;
0687 
0688     /// A reference to the ReaderYODA singleton
0689     YODA::Reader& _reader = YODA::ReaderYODA::create();
0690 
0691 
0692     /// @name Run properties
0693     /// @{
0694 
0695     /// Weight names
0696     std::vector<std::string> _weightNames;
0697     std::vector<std::valarray<double> > _subEventWeights;
0698     //size_t _numWeightTypes; // always == WeightVector.size()
0699 
0700     /// Weight indices
0701     std::vector<size_t> _weightIndices;
0702 
0703     /// Run name
0704     std::string _runname;
0705 
0706     /// Event counter
0707     CounterPtr _eventCounter;
0708 
0709     /// Cross-section known to AH
0710     Estimate0DPtr _xs;
0711 
0712     /// Running average of the cross-section uncertainties
0713     CounterPtr _xserr;
0714 
0715     /// Beam info known to AH
0716     YODA::BinnedEstimatePtr<string> _beaminfo;
0717 
0718     /// Total number of trials
0719     double _ntrials;
0720 
0721     /// Total number of entries of the current HepMC file
0722     CounterPtr _fileCounter;
0723 
0724     /// Toggle for multi-file runs
0725     bool _isEndOfFile;
0726 
0727     /// Nominal cross-section
0728     std::pair<double,double> _userxs;
0729 
0730     /// Beams used by this run.
0731     ParticlePair _beams;
0732 
0733     /// Flag to check if init has been called
0734     bool _initialised;
0735 
0736     /// Flag whether input event beams should be ignored in compatibility check
0737     bool _checkBeams;
0738 
0739     /// Flag to check if multiweights should be ignored
0740     bool _skipMultiWeights;
0741 
0742     /// String of weight names (or regex) to select multiweights
0743     std::string _matchWeightNames;
0744 
0745     /// String of weight names (or regex) to veto multiweights
0746     std::string _unmatchWeightNames;
0747 
0748     /// String giving the nominal weight name
0749     std::string _nominalWeightName;
0750 
0751     /// weight cap value
0752     double _weightCap;
0753 
0754     /// The relative width of the NLO smearing window.
0755     ///
0756     /// @todo Improve & standardise name
0757     double _NLOSmearing;
0758 
0759     /// Current event number
0760     int _eventNumber;
0761 
0762     /// The index in the (original) weight vector for the nominal weight stream
0763     size_t _defaultWeightIdx;
0764 
0765     /// The index in the (possibly pruned) weight vector for the nominal weight stream
0766     size_t _rivetDefaultWeightIdx;
0767 
0768     /// The index of the (possibly user-specified) intended default stream
0769     int _customDefaultWeightIdx;
0770 
0771     /// How often Rivet runs finalize() and writes the result to a YODA file.
0772     int _dumpPeriod;
0773 
0774     /// The name of a YODA file to which Rivet periodically dumps results.
0775     string _dumpFile;
0776 
0777     /// Flag to indicate periodic AO dumping is in progress
0778     bool _dumping;
0779 
0780     /// Flag to indicate bootstrap dumping is in progress
0781     ofstream _fbootstrap;
0782 
0783     /// Name of the file that the bootstrap dumping should be written to
0784     std::string _bootstrapfilename;
0785 
0786     /// Projection Handler
0787     ProjectionHandler _projHandler;
0788 
0789     /// @}
0790 
0791   };
0792 
0793 
0794 }
0795 
0796 #endif