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
0053
0054 Looper(const EventHypothesis &eh, const ParticleFilter &filter);
0055
0056
0057
0058 Looper(const EventHypothesis &eh, const ParticleFilter *filter);
0059
0060
0061 Looper(const EventHypothesis &eh, const ParticleFilterPtr &filter);
0062 ~Looper() {}
0063
0064
0065 const T &operator*() const { return ptr_.get(iter_->second.get()); }
0066
0067 const T *operator->() const { return ptr_.get(iter_->second.get()); }
0068
0069 const T *get() const { return ptr_.get(iter_->second.get()); }
0070
0071
0072 bool isTypeOk() const { return ptr_.typeOk(iter_->second.get()); }
0073
0074
0075 const std::string &role() const { return iter_->first; }
0076
0077 const CandRefType &ref() const { return iter_->second; }
0078
0079 const reco::Candidate &cand() const { return *iter_->second; }
0080
0081
0082 size_t globalIndex() { return iter_ - eh_.begin(); }
0083
0084 size_t index() const { return num_; }
0085
0086 size_t size() const {
0087 if (total_ < 0)
0088 realSize();
0089 return total_;
0090 }
0091
0092
0093 Looper &operator++();
0094
0095 Looper &operator--();
0096
0097 Looper &skip(int delta);
0098
0099
0100 Looper &reset(int item = 0);
0101
0102
0103
0104 operator bool() const;
0105
0106
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_;
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 }
0272 }
0273
0274 #endif