Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:04:53

0001 #ifndef DataFormats_EventHypothesis_interface_EventHypothesisLooper_h
0002 #define DataFormats_EventHypothesis_interface_EventHypothesisLooper_h
0003 
0004 #include "DataFormats/Candidate/interface/Candidate.h"
0005 #include "DataFormats/PatCandidates/interface/EventHypothesis.h"
0006 #include <algorithm>
0007 
0008 namespace pat {
0009   namespace eventhypothesis {
0010     template <typename T>
0011     class DynCastCandPtr {
0012     public:
0013       const T *get(const reco::Candidate *ptr);
0014       void clearCache() { isPtrCached_ = false; }
0015       bool typeOk(const reco::Candidate *ptr) {
0016         doPtr(ptr);
0017         return cachePtr_ != 0;
0018       }
0019 
0020     private:
0021       void doPtr(const reco::Candidate *ptr);
0022       bool isPtrCached_;
0023       const T *cachePtr_;
0024     };
0025     template <typename T>
0026     void DynCastCandPtr<T>::doPtr(const reco::Candidate *ptr) {
0027       if (!isPtrCached_) {
0028         cachePtr_ = dynamic_cast<const T *>(ptr);
0029         isPtrCached_ = true;
0030       }
0031     }
0032     template <typename T>
0033     const T *DynCastCandPtr<T>::get(const reco::Candidate *ptr) {
0034       doPtr(ptr);
0035       if ((ptr != nullptr) && (cachePtr_ == nullptr))
0036         throw cms::Exception("Type Checking")
0037             << "You can't convert a " << typeid(*ptr).name() << " to a " << typeid(T).name() << "\n"
0038             << "note: you can use c++filt command to convert the above in human readable types.\n";
0039       return cachePtr_;
0040     }
0041 
0042     template <>
0043     struct DynCastCandPtr<reco::Candidate> {
0044       const reco::Candidate *get(const reco::Candidate *ptr) { return ptr; }
0045       void clearCache() {}
0046       bool typeOk(const reco::Candidate *ptr) { return true; }
0047     };
0048 
0049     template <typename T>
0050     class Looper {
0051     public:
0052       /// Looper from EventHypothesis and an external, not owned, ParticleFilter.
0053       /// That is: MyFilter flt; Looper(eh, flt);
0054       Looper(const EventHypothesis &eh, const ParticleFilter &filter);
0055 
0056       /// Looper from EventHypothesis and an internal, owned, ParticleFilter
0057       /// That is: Looper(eh, new MyFilter());
0058       Looper(const EventHypothesis &eh, const ParticleFilter *filter);
0059       /// Looper from EventHypothesis and a shared ParticleFilter
0060       /// That is: Looper(eh, ParticleFilterPtr(new MyFilter()));
0061       Looper(const EventHypothesis &eh, const ParticleFilterPtr &filter);
0062       ~Looper() {}
0063 
0064       /// Accessor as if it was a const_iterator on a list of T
0065       const T &operator*() const { return ptr_.get(iter_->second.get()); }
0066       /// Accessor as if it was a const_iterator on a list of T
0067       const T *operator->() const { return ptr_.get(iter_->second.get()); }
0068       /// Accessor as if it was a smart pointer to const T *
0069       const T *get() const { return ptr_.get(iter_->second.get()); }
0070 
0071       /// test if the type is correct
0072       bool isTypeOk() const { return ptr_.typeOk(iter_->second.get()); }
0073 
0074       /// Role of pointed item
0075       const std::string &role() const { return iter_->first; }
0076       /// EDM Ref to pointed particle
0077       const CandRefType &ref() const { return iter_->second; }
0078       /// C++ reference to pointed particle
0079       const reco::Candidate &cand() const { return *iter_->second; }
0080 
0081       /// Index of this item in the full EventHypothesis
0082       size_t globalIndex() { return iter_ - eh_.begin(); }
0083       /// Index of this item among those in the loop
0084       size_t index() const { return num_; }
0085       /// Number of particles in the loop
0086       size_t size() const {
0087         if (total_ < 0)
0088           realSize();
0089         return total_;
0090       }
0091 
0092       /// iteration
0093       Looper &operator++();
0094       /// iteration
0095       Looper &operator--();
0096       /// skip (might be slow)
0097       Looper &skip(int delta);
0098       /// Reset to the start or to any other specific item; negatives count from the end.
0099       /// might be slow, especially with negative items
0100       Looper &reset(int item = 0);
0101 
0102       /// Returns true if you have not run out of the boundaries.
0103       /// It does NOT check if typeOk()
0104       operator bool() const;
0105 
0106       /// returns true if loopers point to the same record
0107       template <typename T2>
0108       bool operator==(const Looper<T2> &other) const {
0109         return iter_ == other.iter_;
0110       }
0111       template <typename T2>
0112       bool operator!=(const Looper<T2> &other) const {
0113         return iter_ != other.iter_;
0114       }
0115       template <typename T2>
0116       bool operator<=(const Looper<T2> &other) const {
0117         return iter_ <= other.iter_;
0118       }
0119       template <typename T2>
0120       bool operator>=(const Looper<T2> &other) const {
0121         return iter_ >= other.iter_;
0122       }
0123       template <typename T2>
0124       bool operator<(const Looper<T2> &other) const {
0125         return iter_ < other.iter_;
0126       }
0127       template <typename T2>
0128       bool operator>(const Looper<T2> &other) const {
0129         return iter_ > other.iter_;
0130       }
0131 
0132     private:
0133       struct null_deleter {
0134         void operator()(void const *) const {}
0135       };
0136       typedef typename EventHypothesis::const_iterator const_iterator;
0137 
0138       void first();
0139       void realSize() const;
0140       bool assertOk() const;
0141 
0142       const EventHypothesis &eh_;
0143       const ParticleFilterPtr filter_;
0144       const_iterator iter_;
0145       int num_;
0146       mutable int total_;  // mutable as it is not computed unless needed
0147       mutable DynCastCandPtr<T> ptr_;
0148     };
0149     typedef Looper<reco::Candidate> CandLooper;
0150 
0151     template <typename T>
0152     Looper<T>::Looper(const EventHypothesis &eh, const ParticleFilter &filter)
0153         : eh_(eh), filter_(ParticleFilterPtr(&filter, typename Looper<T>::null_deleter())), total_(-1) {
0154       first();
0155     }
0156 
0157     template <typename T>
0158     Looper<T>::Looper(const EventHypothesis &eh, const ParticleFilter *filter) : eh_(eh), filter_(filter), total_(-1) {
0159       first();
0160     }
0161 
0162     template <typename T>
0163     Looper<T>::Looper(const EventHypothesis &eh, const ParticleFilterPtr &filter)
0164         : eh_(eh), filter_(filter), total_(-1) {
0165       first();
0166     }
0167 
0168     template <typename T>
0169     bool Looper<T>::assertOk() const {
0170       assert(iter_ <= eh_.end());
0171       assert((iter_ + 1) >= eh_.begin());
0172       assert((iter_ < eh_.begin()) || (iter_ == eh_.end()) || ((*filter_)(*iter_)));
0173       return true;
0174     }
0175 
0176     template <typename T>
0177     Looper<T> &Looper<T>::operator++() {
0178       ptr_.clearCache();
0179       assert(assertOk());
0180       if (iter_ == eh_.end())
0181         return *this;
0182       do {
0183         ++iter_;
0184         if (iter_ == eh_.end())
0185           break;
0186         if ((*filter_)(*iter_)) {
0187           assert(assertOk());
0188           ++num_;
0189           return *this;
0190         }
0191       } while (true);
0192       assert(assertOk());
0193       return *this;
0194     }
0195     template <typename T>
0196     Looper<T> &Looper<T>::operator--() {
0197       ptr_.clearCache();
0198       assert(assertOk());
0199       if (num_ < 0)
0200         return *this;
0201       do {
0202         --iter_;
0203         if (iter_ < eh_.begin()) {
0204           num_ = -1;
0205           break;
0206         }
0207         if ((*filter_)(*iter_)) {
0208           assert(assertOk());
0209           --num_;
0210           return *this;
0211         }
0212       } while (true);
0213       assert(assertOk());
0214       return *this;
0215     }
0216 
0217     template <typename T>
0218     Looper<T> &Looper<T>::skip(int delta) {
0219       assert(assertOk());
0220       std::advance(this, delta);
0221       assert(assertOk());
0222       return *this;
0223     }
0224 
0225     template <typename T>
0226     Looper<T> &Looper<T>::reset(int item) {
0227       assert(assertOk());
0228       if (item >= 0) {
0229         first();
0230         std::advance(this, item);
0231       } else {
0232         num_ = item + 1;
0233         iter_ = eh_.end();
0234         std::advance(this, item);
0235       }
0236       assert(assertOk());
0237       return *this;
0238     }
0239 
0240     template <typename T>
0241     void Looper<T>::first() {
0242       num_ = 0;
0243       iter_ = eh_.begin();
0244       ptr_.clearCache();
0245       for (; iter_ != eh_.end(); ++iter_) {
0246         if ((*filter_)(*iter_))
0247           break;
0248       }
0249       assert(assertOk());
0250     }
0251 
0252     template <typename T>
0253     Looper<T>::operator bool() const {
0254       return (iter_ < eh_.end()) && (iter_ >= eh_.begin());
0255     }
0256 
0257     template <typename T>
0258     void Looper<T>::realSize() const {
0259       EventHypothesis::const_iterator it = iter_;
0260       if (it < eh_.begin()) {
0261         it = eh_.begin();
0262         total_ = 0;
0263       } else {
0264         total_ = num_;
0265       }
0266       for (; it != eh_.end(); ++it) {
0267         if ((*filter_)(*it))
0268           ++total_;
0269       }
0270     }
0271   }  // namespace eventhypothesis
0272 }  // namespace pat
0273 
0274 #endif