Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // -*- C++ -*-
0002 #ifndef RIVET_Event_HH
0003 #define RIVET_Event_HH
0004 
0005 #include "Rivet/Config/RivetCommon.hh"
0006 #include "Rivet/Particle.hh"
0007 #include "Rivet/Projection.hh"
0008 
0009 namespace Rivet {
0010 
0011 
0012   /// @brief Representation of a HepMC event, and enabler of Projection caching
0013   ///
0014   /// Event is a concrete class representing an generated event in Rivet. It is
0015   /// constructed given a HepMC::GenEvent, a pointer to which is kept by the
0016   /// Event object throughout its lifetime. The user must therefore make sure
0017   /// that the corresponding HepMC::GenEvent will persist at least as long as
0018   /// the Event object.
0019   ///
0020   /// In addition to the HepMC::GenEvent object the Event also keeps track of
0021   /// all Projection objects which have been applied to the Event so far.
0022   class Event {
0023   public:
0024 
0025     /// @name Constructors and destructors.
0026     /// @{
0027 
0028     /// Constructor from a HepMC GenEvent pointer
0029     ///
0030     /// @note Although Rivet is an analysis system and should not modify the
0031     /// *physics* of provided events, it needs to ensure that the events are
0032     /// "sane" for analysis purposes, including fixing units and potentially
0033     /// orientations and unphysical graph structures. The passed event pointer
0034     /// is hence not const.
0035     Event(GenEvent* ge, const vector<size_t>& weightindices={}) //, bool strip=false)
0036       : _weightIndices(weightindices), _genevent(*ge)
0037     {
0038       if (!ge) throw UserError("User provided a null GenEvent pointer for analysis");
0039       // if (strip) _strip(_genevent);
0040       _fixGenEvent();
0041     }
0042 
0043     /// Constructor from a HepMC GenEvent reference
0044     ///
0045     /// @note See the pointer-based constructor for discussion of the
0046     /// non-constness of the passed GenEvent.
0047     ///
0048     /// @deprecated HepMC uses pointers, so we should talk to HepMC via pointers: no need to duplicate.
0049     Event(GenEvent& ge, const vector<size_t>& weightindices={}) //, bool strip=false)
0050       : _weightIndices(weightindices), _genevent(ge)
0051     {
0052       // if (strip) _strip(_genevent);
0053       _fixGenEvent();
0054     }
0055 
0056     /// Copy constructor
0057     Event(const Event& e)
0058       : _weightIndices(e._weightIndices),
0059         _genevent(e._genevent) {  }
0060 
0061     /// @}
0062 
0063 
0064     /// @name Major event properties
0065     /// @{
0066 
0067     /// The generated HepMC event obtained from an external event generator
0068     const GenEvent& hepmcEvent() const { return _genevent; }
0069     // /// @brief The generated HepMC event obtained from an external event generator
0070     // ///
0071     // /// Convenience alias for hepmcEventPtr()
0072     // const GenEvent& hepmc() const { return _genevent; }
0073 
0074     /// The generated HepMC event pointer obtained from an external event generator
0075     const GenEvent* hepmcEventPtr() const { return &_genevent; }
0076     /// @brief The generated HepMC event pointer obtained from an external event generator
0077     ///
0078     /// Backward-compatibility alias for hepmcEventPtr()
0079     const GenEvent* genEvent() const { return &_genevent; }
0080 
0081     /// Get the beam particles
0082     ParticlePair beams() const;
0083 
0084     /// Get the beam centre-of-mass energy
0085     double sqrtS() const;
0086 
0087     /// Get the beam centre-of-mass energy per nucleon
0088     double asqrtS() const;
0089 
0090     /// @}
0091 
0092 
0093     /// @name Access to event particles
0094     /// @{
0095 
0096     /// All the raw GenEvent particles, wrapped in Rivet::Particle objects
0097     const Particles& allParticles() const;
0098 
0099     /// @brief All the raw GenEvent particles, wrapped in Rivet::Particle objects, but with a Cut applied
0100     ///
0101     /// @note Due to the cut, this returns by value, i.e. involves an expensive copy
0102     inline Particles allParticles(const Cut& c) const {
0103       return select(allParticles(), c);
0104     }
0105 
0106     /// @brief All the raw GenEvent particles, wrapped in Rivet::Particle objects, but with a selection function applied
0107     ///
0108     /// @note Due to the cut, this returns by value, i.e. involves an expensive copy
0109     template <typename FN>
0110     inline Particles allParticles(const FN& f) const {
0111       return select(allParticles(), f);
0112     }
0113 
0114     /// @brief The generation weights associated with the event
0115     std::valarray<double> weights() const;
0116 
0117     /// @brief The generation cross-sections associated with the event
0118     std::vector<std::pair<double, double>> crossSections() const;
0119 
0120     /// @}
0121 
0122     /// @name Projection running
0123     /// @{
0124 
0125     /// @brief Add a projection @a p to this Event.
0126     ///
0127     /// If an equivalent Projection has been applied before, the
0128     /// Projection::project(const Event&) of @a p is not called and a reference
0129     /// to the previous equivalent projection is returned. If no previous
0130     /// Projection was found, the Projection::project(const Event&) of @a p is
0131     /// called and a reference to @a p is returned.
0132     ///
0133     /// @todo Can make this non-templated, since only cares about ptr to Projection base class
0134     ///
0135     /// @note Comparisons here are by direct pointer comparison, because
0136     /// equivalence is guaranteed if pointers are equal, and inequivalence
0137     /// guaranteed if they aren't, thanks to the ProjectionHandler registry
0138     template <typename PROJ>
0139     const PROJ& applyProjection(PROJ& p) const {
0140       static bool docaching = getEnvParam("RIVET_CACHE_PROJECTIONS", true);
0141       if (docaching) {
0142         MSG_TRACE("Applying projection " << &p << " (" << p.name() << ") -> comparing to projections " << _projections);
0143         // First search for this projection *or an equivalent* in the already-executed list
0144         const Projection* cpp(&p);
0145         /// @note Currently using reint cast to integer type to bypass operator==(Proj*, Proj*)
0146         // std::set<const Projection*>::const_iterator old = _projections.find(cpp);
0147         std::set<const Projection*>::const_iterator old = std::begin(_projections);
0148         std::uintptr_t recpp = reinterpret_cast<std::uintptr_t>(cpp);
0149         for (; old != _projections.end(); ++old)
0150           if (reinterpret_cast<std::uintptr_t>(*old) == recpp) break;
0151         if (old != _projections.end()) {
0152           MSG_TRACE("Equivalent projection found -> returning already-run projection " << *old);
0153           const Projection& pRef = **old;
0154           return pcast<PROJ>(pRef);
0155         }
0156         MSG_TRACE("No equivalent projection in the already-run list -> projecting now");
0157       } else {
0158         MSG_TRACE("Applying projection " << &p << " (" << p.name() << ") WITHOUT projection caching & comparison");
0159       }
0160       // If this one hasn't been run yet on this event, run it and add to the list
0161       Projection* pp = const_cast<Projection*>(&p);
0162       pp->_isValid = true;
0163       pp->project(*this);
0164       if (docaching) _projections.insert(pp);
0165       return p;
0166     }
0167 
0168 
0169     /// @brief Add a projection @a p to this Event by pointer.
0170     template <typename PROJ>
0171     const PROJ& applyProjection(PROJ* pp) const {
0172       if (!pp) throw Error("Event::applyProjection(PROJ*): Projection pointer is null.");
0173       return applyProjection(*pp);
0174     }
0175 
0176     /// @}
0177 
0178 
0179   private:
0180 
0181     /// Tweak the GenEvent to Rivet's expected standards if necessary
0182     void _fixGenEvent();
0183 
0184     /// Get a Log object for Event
0185     Log& getLog() const;
0186 
0187 
0188     // /// @brief Remove uninteresting or unphysical particles in the
0189     // /// GenEvent to speed up searches
0190     // ///
0191     // /// @todo Remove!
0192     // void _strip(GenEvent& ge);
0193 
0194     // /// @brief Convert the GenEvent to use conventional alignment
0195     // ///
0196     // /// For example, FHerwig only produces DIS events in the unconventional
0197     // /// hadron-lepton orientation and has to be corrected for DIS analysis
0198     // /// portability.
0199     // void _geNormAlignment();
0200 
0201     /// @brief The indices of the selected weights, as instructed to the AnalysisHandler.
0202     ///
0203     /// The user can (de-)select weights and the AnalysisHandler knows about the subset
0204     /// that match the specifications.
0205     const std::vector<size_t> _weightIndices;
0206 
0207     /// The GenEvent used by Rivet analysis projections etc.
0208     const GenEvent& _genevent;
0209 
0210     /// All the GenEvent particles, wrapped as Rivet::Particles
0211     ///
0212     /// @note To be populated lazily, hence mutability
0213     mutable Particles _particles;
0214 
0215     /// The set of Projection objects applied so far
0216     mutable std::set<ConstProjectionPtr> _projections;
0217 
0218     /// A cached set of event weights (a single unit weight if the original weight vector was empty)
0219     mutable std::valarray<double> _weights;
0220 
0221     /// A cached set of event cross-section & errors (a pair of zeros if the original weight vector was empty)
0222     mutable std::vector<std::pair<double,double>> _xsecs;
0223   };
0224 
0225 
0226 }
0227 
0228 #endif