Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:12:57

0001 #ifndef EDM4HEP_UTILS_PARTICLEIDUTILS_H
0002 #define EDM4HEP_UTILS_PARTICLEIDUTILS_H
0003 
0004 #include <edm4hep/ParticleIDCollection.h>
0005 #include <edm4hep/ReconstructedParticle.h>
0006 
0007 #include <podio/Frame.h>
0008 
0009 #include <map>
0010 #include <optional>
0011 #include <string>
0012 #include <vector>
0013 
0014 namespace edm4hep::utils {
0015 
0016 /// A simple struct bundling relevant metadata for a ParticleID collection
0017 ///
0018 /// This is the recommended class to use for storing ParticleID related
0019 /// metadata. Most importantly it contains the name of an algorithm as well as
0020 /// the names of the parameters (if any). Additionally, it can also
0021 /// automatically determine an algorithm type (to be used in
0022 /// edm4hep::PartilceID::setAlgorithmType) given a name. This is a 32 bit hash
0023 /// of the algorithm name.
0024 ///
0025 /// @note Given that this structure and the actual contents of the corresponding
0026 /// ParticleIDCollection are disjoint it is your responsibility to set the
0027 /// information accordingly. We offer some utility functionality to ensure
0028 /// consistent setting, but the tools can in principle also be used without
0029 /// that.
0030 struct ParticleIDMeta {
0031   /// Constructor for I/O purposes or with a pre-defined algorithm type
0032   ///
0033   /// @note We generally recommend not using pre-defined algorithm types, but
0034   /// rather to use the automatically determined ones from the
0035   ///
0036   /// @param algName  The name of the PID algorithm
0037   /// @param algType  The (encoded) algorithm type (stored in the ParticleID
0038   ///                 algorithmType) field
0039   /// @param parNames The (optional) parameter names for this PID algorithms.
0040   ///                 There should be a parameter name for each parameter that
0041   ///                 is stored in the ParticleID parameters field
0042   ParticleIDMeta(const std::string& algName, int32_t algType, const std::vector<std::string>& parNames = {});
0043 
0044   /// Main constructor for creating a ParticleIDMeta object without parameters
0045   ///
0046   /// @param algName  The name of the PID algorithm
0047   ParticleIDMeta(const std::string& algName);
0048 
0049   /// Main constructor for creating a ParticleIDMeta object with parameters
0050   ///
0051   /// @param algName  The name of the PID algorithm
0052   /// @param parNames The (optional) parameter names for this PID algorithms.
0053   ///                 There should be a parameter name for each parameter that
0054   ///                 is stored in the ParticleID parameters field
0055   ParticleIDMeta(const std::string& algName, const std::vector<std::string>& parNames);
0056 
0057   ~ParticleIDMeta() = default;
0058   /// Default constructor
0059   ///
0060   /// @note It is not possible to change the algorithm type when this
0061   /// constructor is used
0062   ParticleIDMeta() = default;
0063   ParticleIDMeta(const ParticleIDMeta&) = default;
0064   ParticleIDMeta& operator=(const ParticleIDMeta&) = default;
0065   ParticleIDMeta(ParticleIDMeta&&) = default;
0066   ParticleIDMeta& operator=(ParticleIDMeta&&) = default;
0067 
0068   std::string algoName{};                ///< The name of the algorithm
0069   std::vector<std::string> paramNames{}; ///< The names of the parameters
0070 
0071   /// Get the encoded algorithm type for the PID algorithm that is described by
0072   /// this meta object
0073   ///
0074   /// @returns the algorithm type (usually a 32 bit hash of the algorithm name)
0075   int32_t algoType() const { return m_algoType; }
0076 
0077 private:
0078   int32_t m_algoType{0}; ///< The (potentially user defined) algorithm type
0079 };
0080 
0081 /// Get the index of a parameter for a given PID algorithm
0082 ///
0083 /// @param pidMetaInfo A metadata object describig a ParticleID algorithm
0084 /// @param param       The name of the parameter
0085 ///
0086 /// @returns The index of the parameter which can be used to index into the
0087 ///          ParticleID::getParameters() values or an empty optional in case the
0088 ///          parameter name could not be found in the metadata that were passed.
0089 std::optional<int> getParamIndex(const ParticleIDMeta& pidMetaInfo, const std::string& param);
0090 
0091 /// Utility class to invert the ParticleID to ReconstructedParticle relation
0092 ///
0093 /// This is the main utility class to use when trying to obtain ParticleID
0094 /// objects related to ReconstructedParticles. Basic functionality (i.e.
0095 /// retrieving the related ParticleIDs) can be done without any additional
0096 /// metadata. The full functionality is enabled by also passing in metadata (in
0097 /// the form of ParticleIDMeta) or alternatively adding it after the initial
0098 /// construction.
0099 ///
0100 /// This uses an internal map that is updated whenever a new
0101 /// ParticleIDCollection is added. Hence, lookup of related ParticleID objects
0102 /// for a given ReconstructedParticle avoids looping over all collections.
0103 ///
0104 /// @note there are no checks in place that ensure that the metadata that has
0105 /// been added to a given PIDHandler actually correspond to any of the stored
0106 /// ParticleIDs. It is in fact even possible to use the PIDHandler without any
0107 /// PartileID objects to simply query meta information about ParticleID
0108 /// algorithms.
0109 ///
0110 /// See [this page](@ref md_doc_2_p_i_d_handler) for example usage and more information.
0111 class PIDHandler {
0112 
0113   using RecoPidMapT = std::multimap<edm4hep::ReconstructedParticle, edm4hep::ParticleID>;
0114 
0115   RecoPidMapT m_recoPidMap{}; ///< The internal map from recos to pids
0116 
0117   std::map<std::string, int> m_algoTypes{}; ///< Maps algo names to algo types
0118 
0119   /// Maps algo types to the full particle id meta information
0120   std::map<int, edm4hep::utils::ParticleIDMeta> m_algoPidMeta{};
0121 
0122 public:
0123   PIDHandler() = default;
0124   ~PIDHandler() = default;
0125   // Copies are not allowed to avoid copying the internal maps
0126   PIDHandler(const PIDHandler&) = delete;
0127   PIDHandler& operator=(const PIDHandler&) = delete;
0128   PIDHandler(PIDHandler&&) = default;
0129   PIDHandler& operator=(PIDHandler&&) = default;
0130 
0131   /// Construct a PIDHandler from an arbitrary number of ParticleIDCollections
0132   ///
0133   /// This constructor does not retrieve any metadata and on its own will only
0134   /// enable the basic functionality. For the full functionality add the
0135   /// necessary metadata in a follow up call to @ref addMetaInfos or @ref
0136   /// addMetaInfo
0137   ///
0138   /// @tparam PIDColls A variadic template that we use to enable passing
0139   ///                  arbitrary numbers of collections
0140   ///
0141   /// @param coll A ParticleIDCollection for constructing a PIDHandler
0142   /// @param pidColls An arbitrary number of additional ParticleIDCollections
0143   ///                 that will also be added to the internal map
0144   ///
0145   /// @returns A PIDHandler that is able to handle relations between
0146   ///          ReconstructedParticles and all ParticleID objects that are part
0147   ///          of the passed collection
0148   template <typename... PIDColls>
0149   static PIDHandler from(const ParticleIDCollection& coll, const PIDColls&... pidColls) {
0150     static_assert((std::is_same_v<PIDColls, edm4hep::ParticleIDCollection> && ...),
0151                   "PIDHandler can only be constructed from ParticleIDCollections");
0152     PIDHandler handler{};
0153     handler.addColl(coll);
0154     (handler.addColl(pidColls), ...);
0155     return handler;
0156   }
0157 
0158   /// Create a PIDHandler from a Frame potentially also populating some metadata information.
0159   ///
0160   /// Create a PIDHandler using all ParticleIDCollections that can be found. If
0161   /// metadata is passed automatically also load all related metadata (if
0162   /// available).
0163   ///
0164   /// @note This constructor does not guarantee that **all**
0165   /// ParticleIDCollections will have valid metadata loaded. Only if such
0166   /// metadata is actually present and found will it be ingested, otherwise only
0167   /// the ParticleID objects will be added to the internal map.
0168   ///
0169   /// @param event    The event Frame from which all ParticleIDCollections will be
0170   ///                 retrieved
0171   /// @param metadata An (optional) metadata Frame from which ParticleIDMeta will
0172   ///                 be automatically retrieved for all ParticleIDCollections
0173   ///                 for which it is actually available.
0174   ///
0175   /// @returns A PIDHandler that is able to handle relations between
0176   ///          ReconstructedParticles and all ParticleID objects that were found
0177   ///          in the event Frame. If metadata is found on top of that, also
0178   ///          that has been ingested and can now be queried through this handler.
0179   static PIDHandler from(const podio::Frame& event, const podio::Frame& metadata = {});
0180 
0181   /// Add the information from one ParticleIDCollection to the handler
0182   ///
0183   /// @note This will only add the collection to enable basic functionality. In
0184   /// order to enable the full functionality it is also necessary to add the
0185   /// necessary ParticleIDMeta information that corresponds to the added
0186   /// collection.
0187   ///
0188   /// This is the main function for adding new collections. All other methods
0189   /// that add ParticleID collections will eventually call this in one way or
0190   /// another.
0191   ///
0192   /// @param coll A ParticleIDCollection that should be added to the internal map
0193   void addColl(const edm4hep::ParticleIDCollection& coll);
0194 
0195   /// Add the information from one ParticleIDCollection to the handler together
0196   /// with its meta data
0197   ///
0198   /// @note This method does no check in any form whether the passed collection
0199   /// and metadata are actually related in any form.
0200   ///
0201   /// @param coll    A ParticleIDCollection that should be added to the internal
0202   ///                map
0203   /// @param pidInfo The metadata describing the algorithm that has been used to
0204   ///                determine the ParticleIDs of the coll
0205   void addColl(const edm4hep::ParticleIDCollection& coll, const edm4hep::utils::ParticleIDMeta& pidInfo);
0206 
0207   /// Add (arbitrary) metadata describing a PID algorithm.
0208   ///
0209   /// This is the main function for ingesting metadata. All other methods that
0210   /// add ParticleID algorithm metadata will eventually call this in one way or
0211   /// another.
0212   ///
0213   /// @param pidInfo The metadata describing an algorithm that has been used to
0214   ///                determine ParticleID objects
0215   void addMetaInfo(const edm4hep::utils::ParticleIDMeta& pidInfo);
0216 
0217   /// Add several (arbitrary) meta informations simultaneously
0218   ///
0219   /// @tparam PIDMetas A variadic template that we use to enable calling this
0220   ///                  with an arbitrary number of ParticleIDMeta objects
0221   ///
0222   /// @param pidMetas An arbitrary number of metadata objects describing
0223   ///                 algorithms that have been used to determine ParticleID
0224   ///                 objects
0225   template <typename... PIDMetas>
0226   void addMetaInfos(const PIDMetas&... pidMetas) {
0227     static_assert((std::is_same_v<PIDMetas, edm4hep::utils::ParticleIDMeta> && ...),
0228                   "Only ParticleIDMeta can be used to add metadata to a PIDHandler");
0229     (addMetaInfo(pidMetas), ...);
0230   }
0231 
0232   /// Retrieve all ParticleIDs that are related to the passed
0233   /// ReconstructedParticle
0234   ///
0235   /// @param reco The ReconstructedParticle for which ParticleIDs should be
0236   ///             looked up
0237   ///
0238   /// @returns All ParticleID objects (that this PIDHandler knows about) that
0239   ///          point to the passed ReconstructedParticle
0240   std::vector<edm4hep::ParticleID> getPIDs(const edm4hep::ReconstructedParticle& reco) const;
0241 
0242   /// Retrieve the ParticleID for a given PID algorithm
0243   ///
0244   /// @param reco The ReconstructedParticle for which a ParticleID should be
0245   ///                 looked up
0246   /// @param algoType The (encoded) algorithm type that corresponds to the
0247   ///                 desired algorithm. See also @ref getAlgoType
0248   ///
0249   /// @returns The ParticleID object for this PID algorithm that points to the
0250   ///          passed ReconstrucedParticle if found or an empty optional
0251   ///          otherwise
0252   std::optional<edm4hep::ParticleID> getPID(const edm4hep::ReconstructedParticle& reco, int algoType) const;
0253 
0254   /// Retrieve the index in the parameters for a given parameter name and
0255   /// algoType
0256   ///
0257   /// @param algoType  The (encoded) algorithm type that corresponds to the
0258   ///                  desired algorithm. See also @ref getAlgoType
0259   /// @param paramName The name of the parameter
0260   ///
0261   /// @returns The index of the parameter which can be used to index into the
0262   ///          ParticleID::getParameters() values or an empty optional in case the
0263   ///          parameter name could not be found for the passed algorithm type
0264   ///
0265   /// See also @ref edm4hep::utils::getParamIndex
0266   std::optional<int> getParamIndex(int32_t algoType, const std::string& paramName) const;
0267 
0268   /// Retrieve the algoType for a given algorithm name
0269   ///
0270   /// @param algoName
0271   ///
0272   /// @returns The (encoded) algorithm type for the desired algorithm if known
0273   ///          to the PIDHandler otherwise an empty optional.
0274   std::optional<int32_t> getAlgoType(const std::string& algoName) const;
0275 
0276   /// Set the metadata information for the passed collection in the metadata Frame.
0277   ///
0278   /// This also sets the algorithmType of all elements in the collection to the
0279   /// one that is found in the meta information.
0280   ///
0281   /// @param metadata The metadata Frame into which the information should be
0282   ///                 stored
0283   /// @param pidcoll  A ParticleIDCollection for which the corresponding
0284   ///                 algorithm type will be set (consistent with what is found
0285   ///                 in the @p pidMetaInfo)
0286   /// @param pidMetaInfo The metadata object that corresponds to the ParticleID
0287   ///                    algorithm that has been used for creating the @p
0288   ///                    pidcoll
0289   static void setAlgoInfo(podio::Frame& metadata, edm4hep::ParticleIDCollection& pidcoll, const std::string& collname,
0290                           const edm4hep::utils::ParticleIDMeta& pidMetaInfo);
0291 
0292   /// Set the metadata information for a given collection name in the metadata Frame.
0293   ///
0294   /// @note It is user responsibility to ensure that the meta information that
0295   /// is passed here and the one that is present in the collection with the
0296   /// given name is consistent
0297   ///
0298   /// @param metadata The metadata Frame into which the information should be
0299   ///                 stored
0300   /// @param collname The name of the (ParticleID) collection for which this
0301   ///                 meta information should be stored
0302   /// @param pidMetaInfo The metadata object that corresponds to the ParticleID
0303   ///                    algorithm that has been used for creating the
0304   ///                    ParticleID objects stored in the collection with the @p
0305   ///                    collname
0306   static void setAlgoInfo(podio::Frame& metadata, const std::string& collname,
0307                           const edm4hep::utils::ParticleIDMeta& pidMetaInfo);
0308 
0309   /// Get the ParticleID meta information for a given collection name from the metadata Frame.
0310   ///
0311   /// @param metadata The metadata frame in which to search for ParticleID
0312   ///                 related metadata
0313   /// @param collName The (ParticleID) collection name for which to obtain metadata
0314   ///
0315   /// @returns The metadata related to the PID algorithm that has been used to
0316   ///          create the @p collName collection if available, otherwise an
0317   ///          empty optional.
0318   static std::optional<edm4hep::utils::ParticleIDMeta> getAlgoInfo(const podio::Frame& metadata,
0319                                                                    const std::string& collName);
0320 };
0321 } // namespace edm4hep::utils
0322 
0323 #endif // EDM4HEP_UTILS_PARTICLEIDUTILS_H