/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
DataFormats/PatCandidates/interface/PATObject.h
1 038 строк
53 KB
Christopher Jones
Remove include of MessageLogger.h from DataFormats headers
08 фев 2021, 20:54
08 фев 2021, 20:54
5039d3a
Код
Авторство
О чём код?
// // #ifndef DataFormats_PatCandidates_PATObject_h #define DataFormats_PatCandidates_PATObject_h /** \class pat::PATObject PATObject.h "DataFormats/PatCandidates/interface/PATObject.h" \brief Templated PAT object container PATObject is the templated base PAT object that wraps around reco objects. Please post comments and questions to the Physics Tools hypernews: https://hypernews.cern.ch/HyperNews/CMS/get/physTools.html \author Steven Lowette, Giovanni Petrucciani, Frederic Ronga, Volker Adler, Sal Rappoccio */ #include "DataFormats/Common/interface/Ptr.h" #include "DataFormats/Candidate/interface/CandidateFwd.h" #include "DataFormats/Candidate/interface/Candidate.h" #include <vector> #include <string> #include <iosfwd> #include "DataFormats/PatCandidates/interface/TriggerObjectStandAlone.h" #include "DataFormats/PatCandidates/interface/LookupTableRecord.h" #include "DataFormats/HepMCCandidate/interface/GenParticle.h" #include "DataFormats/PatCandidates/interface/UserData.h" #include "DataFormats/Common/interface/OwnVector.h" #include "DataFormats/PatCandidates/interface/CandKinResolution.h" #include "DataFormats/PatCandidates/interface/throwMissingLabel.h" namespace pat { const reco::CandidatePtrVector &get_empty_cpv(); const std::string &get_empty_str(); template <class ObjectType> class PATObject : public ObjectType { public: typedef ObjectType base_type; /// default constructor PATObject(); /// constructor from a base object (leaves invalid reference to original object!) PATObject(const ObjectType &obj); /// constructor from reference PATObject(const edm::RefToBase<ObjectType> &ref); /// constructor from reference PATObject(const edm::Ptr<ObjectType> &ref); /// destructor ~PATObject() override {} // returns a clone // NO: ObjectType can be an abstract type like reco::Candidate // virtual PATObject<ObjectType> * clone() const ; // for which the clone() can't be defined /// access to the original object; returns zero for null Ref and throws for unavailable collection const reco::Candidate *originalObject() const; /// reference to original object. Returns a null reference if not available const edm::Ptr<reco::Candidate> &originalObjectRef() const; /// access to embedded trigger matches: /// duplicated functions using 'char*' instead of 'std::string' are needed in order to work properly in CINT command lines; /// duplicated functions using 'unsigned' instead of 'bool' are needed in order to work properly in the cut string parser; /// get all matched trigger objects const TriggerObjectStandAloneCollection &triggerObjectMatches() const { return triggerObjectMatchesEmbedded_; }; /// get one matched trigger object by index const TriggerObjectStandAlone *triggerObjectMatch(const size_t idx = 0) const; /// get all matched trigger objects of a certain type; /// trigger object types are defined in 'enum trigger::TriggerObjectType' (DataFormats/HLTReco/interface/TriggerTypeDefs.h) const TriggerObjectStandAloneCollection triggerObjectMatchesByType( const trigger::TriggerObjectType triggerObjectType) const; const TriggerObjectStandAloneCollection triggerObjectMatchesByType(const unsigned triggerObjectType) const { return triggerObjectMatchesByType(trigger::TriggerObjectType(triggerObjectType)); }; // for backward compatibility const TriggerObjectStandAloneCollection triggerObjectMatchesByFilterID(const unsigned triggerObjectType) const { return triggerObjectMatchesByType(trigger::TriggerObjectType(triggerObjectType)); }; /// get one matched trigger object of a certain type by index const TriggerObjectStandAlone *triggerObjectMatchByType(const trigger::TriggerObjectType triggerObjectType, const size_t idx = 0) const; const TriggerObjectStandAlone *triggerObjectMatchByType(const unsigned triggerObjectType, const size_t idx = 0) const { return triggerObjectMatchByType(trigger::TriggerObjectType(triggerObjectType), idx); }; // for backward compatibility const TriggerObjectStandAlone *triggerObjectMatchByFilterID(const unsigned triggerObjectType, const size_t idx = 0) const { return triggerObjectMatchByType(trigger::TriggerObjectType(triggerObjectType), idx); }; /// get all matched trigger objects from a certain collection const TriggerObjectStandAloneCollection triggerObjectMatchesByCollection(const std::string &coll) const; // for RooT command line const TriggerObjectStandAloneCollection triggerObjectMatchesByCollection(const char *coll) const { return triggerObjectMatchesByCollection(std::string(coll)); }; /// get one matched trigger object from a certain collection by index const TriggerObjectStandAlone *triggerObjectMatchByCollection(const std::string &coll, const size_t idx = 0) const; // for RooT command line const TriggerObjectStandAlone *triggerObjectMatchByCollection(const char *coll, const size_t idx = 0) const { return triggerObjectMatchByCollection(std::string(coll), idx); }; /// get all matched L1 objects used in a succeeding object combination of a certain L1 condition const TriggerObjectStandAloneCollection triggerObjectMatchesByCondition(const std::string &nameCondition) const; // for RooT command line const TriggerObjectStandAloneCollection triggerObjectMatchesByCondition(const char *nameCondition) const { return triggerObjectMatchesByCondition(std::string(nameCondition)); }; /// get one matched L1 object used in a succeeding object combination of a certain L1 condition by index const TriggerObjectStandAlone *triggerObjectMatchByCondition(const std::string &nameCondition, const size_t idx = 0) const; // for RooT command line const TriggerObjectStandAlone *triggerObjectMatchByCondition(const char *nameCondition, const size_t idx = 0) const { return triggerObjectMatchByCondition(std::string(nameCondition), idx); }; /// get all matched L1 objects used in a succeeding object combination of a condition in a certain L1 (physics) algorithm; /// if 'algoCondAccepted' is set to 'true' (default), only objects used in succeeding conditions of succeeding algorithms are considered /// ("firing" objects) const TriggerObjectStandAloneCollection triggerObjectMatchesByAlgorithm(const std::string &nameAlgorithm, const bool algoCondAccepted = true) const; // for RooT command line const TriggerObjectStandAloneCollection triggerObjectMatchesByAlgorithm(const char *nameAlgorithm, const bool algoCondAccepted = true) const { return triggerObjectMatchesByAlgorithm(std::string(nameAlgorithm), algoCondAccepted); }; // for the cut string parser const TriggerObjectStandAloneCollection triggerObjectMatchesByAlgorithm(const std::string &nameAlgorithm, const unsigned algoCondAccepted) const { return triggerObjectMatchesByAlgorithm(nameAlgorithm, bool(algoCondAccepted)); }; // for RooT command line and the cut string parser const TriggerObjectStandAloneCollection triggerObjectMatchesByAlgorithm(const char *nameAlgorithm, const unsigned algoCondAccepted) const { return triggerObjectMatchesByAlgorithm(std::string(nameAlgorithm), bool(algoCondAccepted)); }; /// get one matched L1 object used in a succeeding object combination of a condition in a certain L1 (physics) algorithm by index; /// if 'algoCondAccepted' is set to 'true' (default), only objects used in succeeding conditions of succeeding algorithms are considered /// ("firing" objects) const TriggerObjectStandAlone *triggerObjectMatchByAlgorithm(const std::string &nameAlgorithm, const bool algoCondAccepted = true, const size_t idx = 0) const; // for RooT command line const TriggerObjectStandAlone *triggerObjectMatchByAlgorithm(const char *nameAlgorithm, const bool algoCondAccepted = true, const size_t idx = 0) const { return triggerObjectMatchByAlgorithm(std::string(nameAlgorithm), algoCondAccepted, idx); }; // for the cut string parser const TriggerObjectStandAlone *triggerObjectMatchByAlgorithm(const std::string &nameAlgorithm, const unsigned algoCondAccepted, const size_t idx = 0) const { return triggerObjectMatchByAlgorithm(nameAlgorithm, bool(algoCondAccepted), idx); }; // for RooT command line and the cut string parser const TriggerObjectStandAlone *triggerObjectMatchByAlgorithm(const char *nameAlgorithm, const unsigned algoCondAccepted, const size_t idx = 0) const { return triggerObjectMatchByAlgorithm(std::string(nameAlgorithm), bool(algoCondAccepted), idx); }; /// get all matched HLT objects used in a certain HLT filter const TriggerObjectStandAloneCollection triggerObjectMatchesByFilter(const std::string &labelFilter) const; // for RooT command line const TriggerObjectStandAloneCollection triggerObjectMatchesByFilter(const char *labelFilter) const { return triggerObjectMatchesByFilter(std::string(labelFilter)); }; /// get one matched HLT object used in a certain HLT filter by index const TriggerObjectStandAlone *triggerObjectMatchByFilter(const std::string &labelFilter, const size_t idx = 0) const; // for RooT command line const TriggerObjectStandAlone *triggerObjectMatchByFilter(const char *labelFilter, const size_t idx = 0) const { return triggerObjectMatchByFilter(std::string(labelFilter), idx); }; /// get all matched HLT objects used in a certain HLT path; /// if 'pathLastFilterAccepted' is set to 'true' (default), only objects used in the final filter of a succeeding path are considered /// ("firing" objects old style only valid for single object triggers); /// if 'pathL3FilterAccepted' is set to 'true' (default), only objects used in L3 filters (identified by the "saveTags" parameter being 'true') /// of a succeeding path are considered ("firing" objects old style only valid for single object triggers) const TriggerObjectStandAloneCollection triggerObjectMatchesByPath(const std::string &namePath, const bool pathLastFilterAccepted = false, const bool pathL3FilterAccepted = true) const; // for RooT command line const TriggerObjectStandAloneCollection triggerObjectMatchesByPath(const char *namePath, const bool pathLastFilterAccepted = false, const bool pathL3FilterAccepted = true) const { return triggerObjectMatchesByPath(std::string(namePath), pathLastFilterAccepted, pathL3FilterAccepted); }; // for the cut string parser const TriggerObjectStandAloneCollection triggerObjectMatchesByPath(const std::string &namePath, const unsigned pathLastFilterAccepted, const unsigned pathL3FilterAccepted = 1) const { return triggerObjectMatchesByPath(namePath, bool(pathLastFilterAccepted), bool(pathL3FilterAccepted)); }; // for RooT command line and the cut string parser const TriggerObjectStandAloneCollection triggerObjectMatchesByPath(const char *namePath, const unsigned pathLastFilterAccepted, const unsigned pathL3FilterAccepted = 1) const { return triggerObjectMatchesByPath( std::string(namePath), bool(pathLastFilterAccepted), bool(pathL3FilterAccepted)); }; /// get one matched HLT object used in a certain HLT path by index; /// if 'pathLastFilterAccepted' is set to 'true' (default), only objects used in the final filter of a succeeding path are considered /// ("firing" objects, old style only valid for single object triggers); /// if 'pathL3FilterAccepted' is set to 'true' (default), only objects used in L3 filters (identified by the "saveTags" parameter being 'true') /// of a succeeding path are considered ("firing" objects also valid for x-triggers) const TriggerObjectStandAlone *triggerObjectMatchByPath(const std::string &namePath, const bool pathLastFilterAccepted = false, const bool pathL3FilterAccepted = true, const size_t idx = 0) const; // for RooT command line const TriggerObjectStandAlone *triggerObjectMatchByPath(const char *namePath, const bool pathLastFilterAccepted = false, const bool pathL3FilterAccepted = true, const size_t idx = 0) const { return triggerObjectMatchByPath(std::string(namePath), pathLastFilterAccepted, pathL3FilterAccepted, idx); }; // for the cut string parser const TriggerObjectStandAlone *triggerObjectMatchByPath(const std::string &namePath, const unsigned pathLastFilterAccepted, const unsigned pathL3FilterAccepted = 1, const size_t idx = 0) const { return triggerObjectMatchByPath(namePath, bool(pathLastFilterAccepted), bool(pathL3FilterAccepted), idx); }; // for RooT command line and the cut string parser const TriggerObjectStandAlone *triggerObjectMatchByPath(const char *namePath, const unsigned pathLastFilterAccepted, const unsigned pathL3FilterAccepted = 1, const size_t idx = 0) const { return triggerObjectMatchByPath( std::string(namePath), bool(pathLastFilterAccepted), bool(pathL3FilterAccepted), idx); }; /// add a trigger match void addTriggerObjectMatch(const TriggerObjectStandAlone &trigObj) { triggerObjectMatchesEmbedded_.push_back(trigObj); }; /// unpack path names of matched trigger objects (if they were packed before embedding, which is not normally the case) void unpackTriggerObjectPathNames(const edm::TriggerNames &names) { for (std::vector<TriggerObjectStandAlone>::iterator it = triggerObjectMatchesEmbedded_.begin(), ed = triggerObjectMatchesEmbedded_.end(); it != ed; ++it) it->unpackPathNames(names); } /// Returns an efficiency given its name const pat::LookupTableRecord &efficiency(const std::string &name) const; /// Returns the efficiencies as <name,value> pairs (by value) std::vector<std::pair<std::string, pat::LookupTableRecord> > efficiencies() const; /// Returns the list of the names of the stored efficiencies const std::vector<std::string> &efficiencyNames() const { return efficiencyNames_; } /// Returns the list of the values of the stored efficiencies (the ordering is the same as in efficiencyNames()) const std::vector<pat::LookupTableRecord> &efficiencyValues() const { return efficiencyValues_; } /// Store one efficiency in this item, in addition to the existing ones /// If an efficiency with the same name exists, the old value is replaced by this one /// Calling this method many times with names not sorted alphabetically will be slow void setEfficiency(const std::string &name, const pat::LookupTableRecord &value); /// Get generator level particle reference (might be a transient ref if the genParticle was embedded) /// If you stored multiple GenParticles, you can specify which one you want. reco::GenParticleRef genParticleRef(size_t idx = 0) const { if (idx >= genParticlesSize()) return reco::GenParticleRef(); return genParticleEmbedded_.empty() ? genParticleRef_[idx] : reco::GenParticleRef(&genParticleEmbedded_, idx); } /// Get a generator level particle reference with a given pdg id and status /// If there is no MC match with that pdgId and status, it will return a null ref /// Note: this might be a transient ref if the genParticle was embedded /// If status == 0, only the pdgId will be checked; likewise, if pdgId == 0, only the status will be checked. /// When autoCharge is set to true, and a charged reco particle is matched to a charged gen particle, /// positive pdgId means 'same charge', negative pdgId means 'opposite charge'; /// for example, electron.genParticleById(11,0,true) will get an e^+ matched to e^+ or e^- matched to e^-, /// while genParticleById(-15,0,true) will get e^+ matched to e^- or vice versa. /// If a neutral reco particle is matched to a charged gen particle, the sign of the pdgId passed to getParticleById must match that of the gen particle; /// for example photon.getParticleById(11) will match gamma to e^-, while genParticleById(-11) will match gamma to e^+ (pdgId=-11) // implementation note: uint8_t instead of bool, because the string parser doesn't allow bool currently reco::GenParticleRef genParticleById(int pdgId, int status, uint8_t autoCharge = 0) const; /// Get generator level particle, as C++ pointer (might be 0 if the ref was null) /// If you stored multiple GenParticles, you can specify which one you want. const reco::GenParticle *genParticle(size_t idx = 0) const { reco::GenParticleRef ref = genParticleRef(idx); return ref.isNonnull() ? ref.get() : nullptr; } /// Number of generator level particles stored as ref or embedded size_t genParticlesSize() const { return genParticleEmbedded_.empty() ? genParticleRef_.size() : genParticleEmbedded_.size(); } /// Return the list of generator level particles. /// Note that the refs can be transient refs to embedded GenParticles std::vector<reco::GenParticleRef> genParticleRefs() const; /// Set the generator level particle reference void setGenParticleRef(const reco::GenParticleRef &ref, bool embed = false); /// Add a generator level particle reference /// If there is already an embedded particle, this ref will be embedded too void addGenParticleRef(const reco::GenParticleRef &ref); /// Set the generator level particle from a particle not in the Event (embedding it, of course) void setGenParticle(const reco::GenParticle &particle); /// Embed the generator level particle(s) in this PATObject /// Note that generator level particles can only be all embedded or all not embedded. void embedGenParticle(); /// Returns true if there was at least one overlap for this test label bool hasOverlaps(const std::string &label) const; /// Return the list of overlaps for one label (can be empty) /// The original ordering of items is kept (usually it's by increasing deltaR from this item) const reco::CandidatePtrVector &overlaps(const std::string &label) const; /// Returns the labels of the overlap tests that found at least one overlap const std::vector<std::string> &overlapLabels() const { return overlapLabels_; } /// Sets the list of overlapping items for one label /// Note that adding an empty PtrVector has no effect at all /// Items within the list should already be sorted appropriately (this method won't sort them) void setOverlaps(const std::string &label, const reco::CandidatePtrVector &overlaps); /// Returns user-defined data. Returns NULL if the data is not present, or not of type T. template <typename T> const T *userData(const std::string &key) const { const pat::UserData *data = userDataObject_(key); return (data != nullptr ? data->template get<T>() : nullptr); } /// Check if user data with a specific type is present bool hasUserData(const std::string &key) const { return (userDataObject_(key) != nullptr); } /// Get human-readable type of user data object, for debugging const std::string &userDataObjectType(const std::string &key) const { const pat::UserData *data = userDataObject_(key); return (data != nullptr ? data->typeName() : get_empty_str()); }; /// Get list of user data object names const std::vector<std::string> &userDataNames() const { return userDataLabels_; } /// Get the data as a void *, for CINT usage. /// COMPLETELY UNSUPPORTED, USE ONLY FOR DEBUGGING const void *userDataBare(const std::string &key) const { const pat::UserData *data = userDataObject_(key); return (data != nullptr ? data->bareData() : nullptr); } /// Set user-defined data /// Needs dictionaries for T and for pat::UserHolder<T>, /// and it will throw exception if they're missing, /// unless transientOnly is set to true template <typename T> void addUserData(const std::string &label, const T &data, bool transientOnly = false, bool overwrite = false) { std::unique_ptr<pat::UserData> made(pat::UserData::make<T>(data, transientOnly)); addUserDataObject_(label, std::move(made), overwrite); } /// Set user-defined data. To be used only to fill from ValueMap<Ptr<UserData>> /// Do not use unless you know what you are doing. void addUserDataFromPtr(const std::string &label, const edm::Ptr<pat::UserData> &data, bool overwrite = false) { std::unique_ptr<pat::UserData> cloned(data->clone()); addUserDataObject_(label, std::move(cloned), overwrite); } /// Get user-defined float /// Note: throws if the key is not found; you can check if the key exists with 'hasUserFloat' method. float userFloat(const std::string &key) const; /// return a range of values corresponding to key std::vector<float> userFloatRange(const std::string &key) const; /// a CINT-friendly interface float userFloat(const char *key) const { return userFloat(std::string(key)); } /// Set user-defined float void addUserFloat(const std::string &label, float data, const bool overwrite = false); /// Get list of user-defined float names const std::vector<std::string> &userFloatNames() const { return userFloatLabels_; } /// Return true if there is a user-defined float with a given name bool hasUserFloat(const std::string &key) const { auto it = std::lower_bound(userFloatLabels_.cbegin(), userFloatLabels_.cend(), key); return (it != userFloatLabels_.cend() && *it == key); } /// a CINT-friendly interface bool hasUserFloat(const char *key) const { return hasUserFloat(std::string(key)); } /// Get user-defined int /// Note: throws if the key is not found; you can check if the key exists with 'hasUserInt' method. int32_t userInt(const std::string &key) const; /// returns a range of values corresponding to key std::vector<int> userIntRange(const std::string &key) const; /// Set user-defined int void addUserInt(const std::string &label, int32_t data, const bool overwrite = false); /// Get list of user-defined int names const std::vector<std::string> &userIntNames() const { return userIntLabels_; } /// Return true if there is a user-defined int with a given name bool hasUserInt(const std::string &key) const { auto it = std::lower_bound(userIntLabels_.cbegin(), userIntLabels_.cend(), key); return (it != userIntLabels_.cend() && *it == key); } /// Get user-defined candidate ptr /// Note: it will a null pointer if the key is not found; you can check if the key exists with 'hasUserInt' method. reco::CandidatePtr userCand(const std::string &key) const; /// Set user-defined int void addUserCand(const std::string &label, const reco::CandidatePtr &data, const bool overwrite = false); /// Get list of user-defined cand names const std::vector<std::string> &userCandNames() const { return userCandLabels_; } /// Return true if there is a user-defined int with a given name bool hasUserCand(const std::string &key) const { auto it = std::lower_bound(userCandLabels_.cbegin(), userCandLabels_.cend(), key); return (it != userCandLabels_.cend() && *it == key); } // === New Kinematic Resolutions /// Return the kinematic resolutions associated to this object, possibly specifying a label for it. /// If not present, it will throw an exception. const pat::CandKinResolution &getKinResolution(const std::string &label = "") const; /// Check if the kinematic resolutions are stored into this object (possibly specifying a label for them) bool hasKinResolution(const std::string &label = "") const; /// Add a kinematic resolution to this object (possibly with a label) void setKinResolution(const pat::CandKinResolution &resol, const std::string &label = ""); /// Resolution on eta, possibly with a label to specify which resolution to use double resolEta(const std::string &label = "") const { return getKinResolution(label).resolEta(this->p4()); } /// Resolution on theta, possibly with a label to specify which resolution to use double resolTheta(const std::string &label = "") const { return getKinResolution(label).resolTheta(this->p4()); } /// Resolution on phi, possibly with a label to specify which resolution to use double resolPhi(const std::string &label = "") const { return getKinResolution(label).resolPhi(this->p4()); } /// Resolution on energy, possibly with a label to specify which resolution to use double resolE(const std::string &label = "") const { return getKinResolution(label).resolE(this->p4()); } /// Resolution on et, possibly with a label to specify which resolution to use double resolEt(const std::string &label = "") const { return getKinResolution(label).resolEt(this->p4()); } /// Resolution on p, possibly with a label to specify which resolution to use double resolP(const std::string &label = "") const { return getKinResolution(label).resolP(this->p4()); } /// Resolution on pt, possibly with a label to specify which resolution to use double resolPt(const std::string &label = "") const { return getKinResolution(label).resolPt(this->p4()); } /// Resolution on 1/p, possibly with a label to specify which resolution to use double resolPInv(const std::string &label = "") const { return getKinResolution(label).resolPInv(this->p4()); } /// Resolution on px, possibly with a label to specify which resolution to use double resolPx(const std::string &label = "") const { return getKinResolution(label).resolPx(this->p4()); } /// Resolution on py, possibly with a label to specify which resolution to use double resolPy(const std::string &label = "") const { return getKinResolution(label).resolPy(this->p4()); } /// Resolution on pz, possibly with a label to specify which resolution to use double resolPz(const std::string &label = "") const { return getKinResolution(label).resolPz(this->p4()); } /// Resolution on mass, possibly with a label to specify which resolution to use /// Note: this will be zero if a mass-constrained parametrization is used for this object double resolM(const std::string &label = "") const { return getKinResolution(label).resolM(this->p4()); } protected: // reference back to the original object edm::Ptr<reco::Candidate> refToOrig_; /// vector of trigger matches TriggerObjectStandAloneCollection triggerObjectMatchesEmbedded_; /// vector of the efficiencies (values) std::vector<pat::LookupTableRecord> efficiencyValues_; /// vector of the efficiencies (names) std::vector<std::string> efficiencyNames_; /// Reference to a generator level particle std::vector<reco::GenParticleRef> genParticleRef_; /// vector to hold an embedded generator level particle std::vector<reco::GenParticle> genParticleEmbedded_; /// Overlapping test labels (only if there are any overlaps) std::vector<std::string> overlapLabels_; /// Overlapping items (sorted by distance) std::vector<reco::CandidatePtrVector> overlapItems_; /// User data object std::vector<std::string> userDataLabels_; pat::UserDataCollection userDataObjects_; // User float values std::vector<std::string> userFloatLabels_; std::vector<float> userFloats_; // User int values std::vector<std::string> userIntLabels_; std::vector<int32_t> userInts_; // User candidate matches std::vector<std::string> userCandLabels_; std::vector<reco::CandidatePtr> userCands_; /// Kinematic resolutions. std::vector<pat::CandKinResolution> kinResolutions_; /// Labels for the kinematic resolutions. /// if (kinResolutions_.size() == kinResolutionLabels_.size()+1), then the first resolution has no label. std::vector<std::string> kinResolutionLabels_; void addUserDataObject_(const std::string &label, std::unique_ptr<pat::UserData> value, bool overwrite = false); private: const pat::UserData *userDataObject_(const std::string &key) const; }; template <class ObjectType> PATObject<ObjectType>::PATObject() {} template <class ObjectType> PATObject<ObjectType>::PATObject(const ObjectType &obj) : ObjectType(obj), refToOrig_() {} template <class ObjectType> PATObject<ObjectType>::PATObject(const edm::RefToBase<ObjectType> &ref) : ObjectType(*ref), refToOrig_(ref.id(), ref.get(), ref.key()) // correct way to convert RefToBase=>Ptr, if ref is guaranteed to be available // which happens to be true, otherwise the line before this throws ex. already {} template <class ObjectType> PATObject<ObjectType>::PATObject(const edm::Ptr<ObjectType> &ref) : ObjectType(*ref), refToOrig_(ref) {} template <class ObjectType> const reco::Candidate *PATObject<ObjectType>::originalObject() const { if (refToOrig_.isNull()) { // this object was not produced from a reference, so no link to the // original object exists -> return a 0-pointer return nullptr; } else if (!refToOrig_.isAvailable()) { throw edm::Exception(edm::errors::ProductNotFound) << "The original collection from which this PAT object was made is not present any more in the event, hence " "you cannot access the originating object anymore."; } else { return refToOrig_.get(); } } template <class ObjectType> const edm::Ptr<reco::Candidate> &PATObject<ObjectType>::originalObjectRef() const { return refToOrig_; } template <class ObjectType> const TriggerObjectStandAlone *PATObject<ObjectType>::triggerObjectMatch(const size_t idx) const { if (idx >= triggerObjectMatches().size()) return nullptr; TriggerObjectStandAloneRef ref(&triggerObjectMatchesEmbedded_, idx); return ref.isNonnull() ? ref.get() : nullptr; } template <class ObjectType> const TriggerObjectStandAloneCollection PATObject<ObjectType>::triggerObjectMatchesByType( const trigger::TriggerObjectType triggerObjectType) const { TriggerObjectStandAloneCollection matches; for (size_t i = 0; i < triggerObjectMatches().size(); ++i) { if (triggerObjectMatch(i) != 0 && triggerObjectMatch(i)->hasTriggerObjectType(triggerObjectType)) matches.push_back(*(triggerObjectMatch(i))); } return matches; } template <class ObjectType> const TriggerObjectStandAlone *PATObject<ObjectType>::triggerObjectMatchByType( const trigger::TriggerObjectType triggerObjectType, const size_t idx) const { std::vector<size_t> refs; for (size_t i = 0; i < triggerObjectMatches().size(); ++i) { if (triggerObjectMatch(i) != nullptr && triggerObjectMatch(i)->hasTriggerObjectType(triggerObjectType)) refs.push_back(i); } if (idx >= refs.size()) return nullptr; TriggerObjectStandAloneRef ref(&triggerObjectMatchesEmbedded_, refs.at(idx)); return ref.isNonnull() ? ref.get() : nullptr; } template <class ObjectType> const TriggerObjectStandAloneCollection PATObject<ObjectType>::triggerObjectMatchesByCollection( const std::string &coll) const { TriggerObjectStandAloneCollection matches; for (size_t i = 0; i < triggerObjectMatches().size(); ++i) { if (triggerObjectMatch(i) != 0 && triggerObjectMatch(i)->hasCollection(coll)) matches.push_back(*(triggerObjectMatch(i))); } return matches; } template <class ObjectType> const TriggerObjectStandAlone *PATObject<ObjectType>::triggerObjectMatchByCollection(const std::string &coll, const size_t idx) const { std::vector<size_t> refs; for (size_t i = 0; i < triggerObjectMatches().size(); ++i) { if (triggerObjectMatch(i) != 0 && triggerObjectMatch(i)->hasCollection(coll)) { refs.push_back(i); } } if (idx >= refs.size()) return nullptr; TriggerObjectStandAloneRef ref(&triggerObjectMatchesEmbedded_, refs.at(idx)); return ref.isNonnull() ? ref.get() : nullptr; } template <class ObjectType> const TriggerObjectStandAloneCollection PATObject<ObjectType>::triggerObjectMatchesByCondition( const std::string &nameCondition) const { TriggerObjectStandAloneCollection matches; for (size_t i = 0; i < triggerObjectMatches().size(); ++i) { if (triggerObjectMatch(i) != 0 && triggerObjectMatch(i)->hasConditionName(nameCondition)) matches.push_back(*(triggerObjectMatch(i))); } return matches; } template <class ObjectType> const TriggerObjectStandAlone *PATObject<ObjectType>::triggerObjectMatchByCondition(const std::string &nameCondition, const size_t idx) const { std::vector<size_t> refs; for (size_t i = 0; i < triggerObjectMatches().size(); ++i) { if (triggerObjectMatch(i) != 0 && triggerObjectMatch(i)->hasConditionName(nameCondition)) refs.push_back(i); } if (idx >= refs.size()) return nullptr; TriggerObjectStandAloneRef ref(&triggerObjectMatchesEmbedded_, refs.at(idx)); return ref.isNonnull() ? ref.get() : nullptr; } template <class ObjectType> const TriggerObjectStandAloneCollection PATObject<ObjectType>::triggerObjectMatchesByAlgorithm( const std::string &nameAlgorithm, const bool algoCondAccepted) const { TriggerObjectStandAloneCollection matches; for (size_t i = 0; i < triggerObjectMatches().size(); ++i) { if (triggerObjectMatch(i) != 0 && triggerObjectMatch(i)->hasAlgorithmName(nameAlgorithm, algoCondAccepted)) matches.push_back(*(triggerObjectMatch(i))); } return matches; } template <class ObjectType> const TriggerObjectStandAlone *PATObject<ObjectType>::triggerObjectMatchByAlgorithm(const std::string &nameAlgorithm, const bool algoCondAccepted, const size_t idx) const { std::vector<size_t> refs; for (size_t i = 0; i < triggerObjectMatches().size(); ++i) { if (triggerObjectMatch(i) != 0 && triggerObjectMatch(i)->hasAlgorithmName(nameAlgorithm, algoCondAccepted)) refs.push_back(i); } if (idx >= refs.size()) return nullptr; TriggerObjectStandAloneRef ref(&triggerObjectMatchesEmbedded_, refs.at(idx)); return ref.isNonnull() ? ref.get() : nullptr; } template <class ObjectType> const TriggerObjectStandAloneCollection PATObject<ObjectType>::triggerObjectMatchesByFilter( const std::string &labelFilter) const { TriggerObjectStandAloneCollection matches; for (size_t i = 0; i < triggerObjectMatches().size(); ++i) { if (triggerObjectMatch(i) != 0 && triggerObjectMatch(i)->hasFilterLabel(labelFilter)) matches.push_back(*(triggerObjectMatch(i))); } return matches; } template <class ObjectType> const TriggerObjectStandAlone *PATObject<ObjectType>::triggerObjectMatchByFilter(const std::string &labelFilter, const size_t idx) const { std::vector<size_t> refs; for (size_t i = 0; i < triggerObjectMatches().size(); ++i) { if (triggerObjectMatch(i) != 0 && triggerObjectMatch(i)->hasFilterLabel(labelFilter)) refs.push_back(i); } if (idx >= refs.size()) return nullptr; TriggerObjectStandAloneRef ref(&triggerObjectMatchesEmbedded_, refs.at(idx)); return ref.isNonnull() ? ref.get() : nullptr; } template <class ObjectType> const TriggerObjectStandAloneCollection PATObject<ObjectType>::triggerObjectMatchesByPath( const std::string &namePath, const bool pathLastFilterAccepted, const bool pathL3FilterAccepted) const { TriggerObjectStandAloneCollection matches; for (size_t i = 0; i < triggerObjectMatches().size(); ++i) { if (triggerObjectMatch(i) != nullptr && triggerObjectMatch(i)->hasPathName(namePath, pathLastFilterAccepted, pathL3FilterAccepted)) matches.push_back(*(triggerObjectMatch(i))); } return matches; } template <class ObjectType> const TriggerObjectStandAlone *PATObject<ObjectType>::triggerObjectMatchByPath(const std::string &namePath, const bool pathLastFilterAccepted, const bool pathL3FilterAccepted, const size_t idx) const { std::vector<size_t> refs; for (size_t i = 0; i < triggerObjectMatches().size(); ++i) { if (triggerObjectMatch(i) != nullptr && triggerObjectMatch(i)->hasPathName(namePath, pathLastFilterAccepted, pathL3FilterAccepted)) refs.push_back(i); } if (idx >= refs.size()) return nullptr; TriggerObjectStandAloneRef ref(&triggerObjectMatchesEmbedded_, refs.at(idx)); return ref.isNonnull() ? ref.get() : nullptr; } template <class ObjectType> const pat::LookupTableRecord &PATObject<ObjectType>::efficiency(const std::string &name) const { // find the name in the (sorted) list of names auto it = std::lower_bound(efficiencyNames_.cbegin(), efficiencyNames_.cend(), name); if ((it == efficiencyNames_.end()) || (*it != name)) { throw cms::Exception("Invalid Label") << "There is no efficiency with name '" << name << "' in this PAT Object\n"; } return efficiencyValues_[std::distance(efficiencyNames_.cbegin(), it)]; } template <class ObjectType> std::vector<std::pair<std::string, pat::LookupTableRecord> > PATObject<ObjectType>::efficiencies() const { std::vector<std::pair<std::string, pat::LookupTableRecord> > ret; std::vector<std::string>::const_iterator itn = efficiencyNames_.begin(), edn = efficiencyNames_.end(); std::vector<pat::LookupTableRecord>::const_iterator itv = efficiencyValues_.begin(); for (; itn != edn; ++itn, ++itv) { ret.emplace_back(*itn, *itv); } return ret; } template <class ObjectType> void PATObject<ObjectType>::setEfficiency(const std::string &name, const pat::LookupTableRecord &value) { // look for the name, or to the place where we can insert it without violating the alphabetic order auto it = std::lower_bound(efficiencyNames_.begin(), efficiencyNames_.end(), name); const auto dist = std::distance(efficiencyNames_.begin(), it); if (it == efficiencyNames_.end()) { // insert at the end efficiencyNames_.push_back(name); efficiencyValues_.push_back(value); } else if (*it == name) { // replace existing efficiencyValues_[dist] = value; } else { // insert in the middle :-( efficiencyNames_.insert(it, name); efficiencyValues_.insert(efficiencyValues_.begin() + dist, value); } } template <class ObjectType> void PATObject<ObjectType>::setGenParticleRef(const reco::GenParticleRef &ref, bool embed) { genParticleRef_ = std::vector<reco::GenParticleRef>(1, ref); genParticleEmbedded_.clear(); if (embed) embedGenParticle(); } template <class ObjectType> void PATObject<ObjectType>::addGenParticleRef(const reco::GenParticleRef &ref) { if (!genParticleEmbedded_.empty()) { // we're embedding if (ref.isNonnull()) genParticleEmbedded_.push_back(*ref); } else { genParticleRef_.push_back(ref); } } template <class ObjectType> void PATObject<ObjectType>::setGenParticle(const reco::GenParticle &particle) { genParticleEmbedded_.clear(); genParticleEmbedded_.push_back(particle); genParticleRef_.clear(); } template <class ObjectType> void PATObject<ObjectType>::embedGenParticle() { genParticleEmbedded_.clear(); for (std::vector<reco::GenParticleRef>::const_iterator it = genParticleRef_.begin(); it != genParticleRef_.end(); ++it) { if (it->isNonnull()) genParticleEmbedded_.push_back(**it); } genParticleRef_.clear(); } template <class ObjectType> std::vector<reco::GenParticleRef> PATObject<ObjectType>::genParticleRefs() const { if (genParticleEmbedded_.empty()) return genParticleRef_; std::vector<reco::GenParticleRef> ret(genParticleEmbedded_.size()); for (size_t i = 0, n = ret.size(); i < n; ++i) { ret[i] = reco::GenParticleRef(&genParticleEmbedded_, i); } return ret; } template <class ObjectType> reco::GenParticleRef PATObject<ObjectType>::genParticleById(int pdgId, int status, uint8_t autoCharge) const { // get a vector, avoiding an unneeded copy if there is no embedding const std::vector<reco::GenParticleRef> &vec = (genParticleEmbedded_.empty() ? genParticleRef_ : genParticleRefs()); for (std::vector<reco::GenParticleRef>::const_iterator ref = vec.begin(), end = vec.end(); ref != end; ++ref) { if (ref->isNonnull()) { const reco::GenParticle &g = **ref; if ((status != 0) && (g.status() != status)) continue; if (pdgId == 0) { return *ref; } else if (!autoCharge) { if (pdgId == g.pdgId()) return *ref; } else if (abs(pdgId) == abs(g.pdgId())) { // I want pdgId > 0 to match "correct charge" (for charged particles) if (g.charge() == 0) return *ref; else if ((this->charge() == 0) && (pdgId == g.pdgId())) return *ref; else if (g.charge() * this->charge() * pdgId > 0) return *ref; } } } return reco::GenParticleRef(); } template <class ObjectType> bool PATObject<ObjectType>::hasOverlaps(const std::string &label) const { auto match = std::lower_bound(overlapLabels_.cbegin(), overlapLabels_.cend(), label); return (match != overlapLabels_.end() && *match == label); } template <class ObjectType> const reco::CandidatePtrVector &PATObject<ObjectType>::overlaps(const std::string &label) const { auto match = std::lower_bound(overlapLabels_.cbegin(), overlapLabels_.cend(), label); if (match == overlapLabels_.cend() || *match != label) return get_empty_cpv(); return overlapItems_[std::distance(overlapLabels_.begin(), match)]; } template <class ObjectType> void PATObject<ObjectType>::setOverlaps(const std::string &label, const reco::CandidatePtrVector &overlaps) { auto match = std::lower_bound(overlapLabels_.begin(), overlapLabels_.end(), label); const auto dist = std::distance(overlapLabels_.begin(), match); if (match == overlapLabels_.end() || *match != label) { overlapLabels_.insert(match, label); overlapItems_.insert(overlapItems_.begin() + dist, overlaps); } else { overlapItems_[dist] = overlaps; } } template <class ObjectType> const pat::UserData *PATObject<ObjectType>::userDataObject_(const std::string &key) const { auto it = std::lower_bound(userDataLabels_.cbegin(), userDataLabels_.cend(), key); if (it != userDataLabels_.cend() && *it == key) { return &userDataObjects_[std::distance(userDataLabels_.cbegin(), it)]; } return nullptr; } template <class ObjectType> void PATObject<ObjectType>::addUserDataObject_(const std::string &label, std::unique_ptr<pat::UserData> data, bool overwrite) { auto it = std::lower_bound(userDataLabels_.begin(), userDataLabels_.end(), label); const auto dist = std::distance(userDataLabels_.begin(), it); if (it == userDataLabels_.end() || *it != label) { userDataLabels_.insert(it, label); userDataObjects_.insert(userDataObjects_.begin() + dist, std::move(data)); } else if (overwrite) { userDataObjects_.set(dist, std::move(data)); } else { //create a range by adding behind the first entry userDataLabels_.insert(it + 1, label); userDataObjects_.insert(userDataObjects_.begin() + dist + 1, std::move(data)); } } template <class ObjectType> float PATObject<ObjectType>::userFloat(const std::string &key) const { auto it = std::lower_bound(userFloatLabels_.cbegin(), userFloatLabels_.cend(), key); if (it != userFloatLabels_.cend() && *it == key) { return userFloats_[std::distance(userFloatLabels_.cbegin(), it)]; } throwMissingLabel("UserFloat", key, userFloatLabels_); return std::numeric_limits<float>::quiet_NaN(); } template <class ObjectType> std::vector<float> PATObject<ObjectType>::userFloatRange(const std::string &key) const { auto range = std::equal_range(userFloatLabels_.cbegin(), userFloatLabels_.cend(), key); std::vector<float> result; result.reserve(std::distance(range.first, range.second)); for (auto it = range.first; it != range.second; ++it) { result.push_back(userFloats_[std::distance(userFloatLabels_.cbegin(), it)]); } return result; } template <class ObjectType> void PATObject<ObjectType>::addUserFloat(const std::string &label, float data, const bool overwrite) { auto it = std::lower_bound(userFloatLabels_.begin(), userFloatLabels_.end(), label); const auto dist = std::distance(userFloatLabels_.begin(), it); if (it == userFloatLabels_.end() || *it != label) { userFloatLabels_.insert(it, label); userFloats_.insert(userFloats_.begin() + dist, data); } else if (overwrite) { userFloats_[dist] = data; } else { //create a range by adding behind the first entry userFloatLabels_.insert(it + 1, label); userFloats_.insert(userFloats_.begin() + dist + 1, data); } } template <class ObjectType> int PATObject<ObjectType>::userInt(const std::string &key) const { auto it = std::lower_bound(userIntLabels_.cbegin(), userIntLabels_.cend(), key); if (it != userIntLabels_.cend() && *it == key) { return userInts_[std::distance(userIntLabels_.cbegin(), it)]; } throwMissingLabel("UserInt", key, userIntLabels_); return std::numeric_limits<int>::max(); } template <class ObjectType> std::vector<int> PATObject<ObjectType>::userIntRange(const std::string &key) const { auto range = std::equal_range(userIntLabels_.cbegin(), userIntLabels_.cend(), key); std::vector<int> result; result.reserve(std::distance(range.first, range.second)); for (auto it = range.first; it != range.second; ++it) { result.push_back(userInts_[std::distance(userIntLabels_.cbegin(), it)]); } return result; } template <class ObjectType> void PATObject<ObjectType>::addUserInt(const std::string &label, int data, bool overwrite) { auto it = std::lower_bound(userIntLabels_.begin(), userIntLabels_.end(), label); const auto dist = std::distance(userIntLabels_.begin(), it); if (it == userIntLabels_.end() || *it != label) { userIntLabels_.insert(it, label); userInts_.insert(userInts_.begin() + dist, data); } else if (overwrite) { userInts_[dist] = data; } else { //create a range by adding behind the first entry userIntLabels_.insert(it + 1, label); userInts_.insert(userInts_.begin() + dist + 1, data); } } template <class ObjectType> reco::CandidatePtr PATObject<ObjectType>::userCand(const std::string &key) const { auto it = std::lower_bound(userCandLabels_.cbegin(), userCandLabels_.cend(), key); if (it != userCandLabels_.cend()) { return userCands_[std::distance(userCandLabels_.begin(), it)]; } return reco::CandidatePtr(); } template <class ObjectType> void PATObject<ObjectType>::addUserCand(const std::string &label, const reco::CandidatePtr &data, const bool overwrite) { auto it = std::lower_bound(userCandLabels_.begin(), userCandLabels_.end(), label); const auto dist = std::distance(userCandLabels_.begin(), it); if (it == userCandLabels_.end() || *it != label) { userCandLabels_.insert(it, label); userCands_.insert(userCands_.begin() + dist, data); } else if (overwrite) { userCands_[dist] = data; } else { userCandLabels_.insert(it + 1, label); userCands_.insert(userCands_.begin() + dist + 1, data); } } template <class ObjectType> const pat::CandKinResolution &PATObject<ObjectType>::getKinResolution(const std::string &label) const { const bool has_unlabelled = (kinResolutionLabels_.size() + 1 == kinResolutions_.size()); if (label.empty()) { if (has_unlabelled) { return kinResolutions_[0]; } else { throw cms::Exception("Missing Data", "This object does not contain an un-labelled kinematic resolution"); } } else { auto match = std::lower_bound(kinResolutionLabels_.cbegin(), kinResolutionLabels_.cend(), label); const auto dist = std::distance(kinResolutionLabels_.begin(), match); const size_t increment = (has_unlabelled ? 1 : 0); if (match == kinResolutionLabels_.end() || *match != label) { cms::Exception ex("Missing Data"); ex << "This object does not contain a kinematic resolution with name '" << label << "'.\n"; ex << "The known labels are: "; for (std::vector<std::string>::const_iterator it = kinResolutionLabels_.cbegin(); it != kinResolutionLabels_.cend(); ++it) { ex << "'" << *it << "' "; } ex << "\n"; throw ex; } else { return kinResolutions_[dist + increment]; } } } template <class ObjectType> bool PATObject<ObjectType>::hasKinResolution(const std::string &label) const { if (label.empty()) { return (kinResolutionLabels_.size() + 1 == kinResolutions_.size()); } else { auto match = std::lower_bound(kinResolutionLabels_.cbegin(), kinResolutionLabels_.cend(), label); return (match != kinResolutionLabels_.cend() && *match == label); } } template <class ObjectType> void PATObject<ObjectType>::setKinResolution(const pat::CandKinResolution &resol, const std::string &label) { const bool has_unlabelled = (kinResolutionLabels_.size() + 1 == kinResolutions_.size()); if (label.empty()) { if (has_unlabelled) { // There is already an un-labelled object. Replace it kinResolutions_[0] = resol; } else { // Insert. Note that the un-labelled is always the first, so we need to insert before begin() // (for an empty vector, this should not cost more than push_back) kinResolutions_.insert(kinResolutions_.begin(), resol); } } else { auto match = std::lower_bound(kinResolutionLabels_.begin(), kinResolutionLabels_.end(), label); const auto dist = std::distance(kinResolutionLabels_.begin(), match); const size_t increment = (has_unlabelled ? 1 : 0); if (match != kinResolutionLabels_.end() && *match == label) { // Existing object: replace kinResolutions_[dist + increment] = resol; } else { kinResolutionLabels_.insert(match, label); kinResolutions_.insert(kinResolutions_.begin() + dist + increment, resol); } } } } // namespace pat #endif