File indexing completed on 2023-03-17 10:50:53
0001 #ifndef DataFormats_EventHypothesis_interface_EventHypothesis_h
0002 #define DataFormats_EventHypothesis_interface_EventHypothesis_h
0003
0004 #include "DataFormats/Candidate/interface/CandidateFwd.h"
0005 #include "DataFormats/Candidate/interface/Candidate.h"
0006 #include <boost/regex.hpp>
0007
0008 #include <typeinfo>
0009 #include <iostream>
0010 #include <type_traits>
0011 #include <cxxabi.h>
0012
0013 namespace pat {
0014
0015 namespace eventhypothesis {
0016 template <typename T>
0017 class Looper;
0018 }
0019
0020 namespace eventhypothesis {
0021
0022 typedef reco::CandidatePtr CandRefType;
0023
0024 struct ParticleFilter {
0025 virtual ~ParticleFilter() {}
0026 bool operator()(const std::pair<std::string, CandRefType> &p) const { return operator()(p.second, p.first); }
0027 virtual bool operator()(const CandRefType &cand, const std::string &role) const = 0;
0028 };
0029
0030 typedef std::shared_ptr<const ParticleFilter> ParticleFilterPtr;
0031 }
0032
0033 class EventHypothesis {
0034 public:
0035 typedef eventhypothesis::CandRefType CandRefType;
0036 typedef std::pair<std::string, CandRefType> value_type;
0037 typedef std::vector<value_type> vector_type;
0038 typedef vector_type::const_iterator const_iterator;
0039 typedef vector_type::const_reverse_iterator const_reverse_iterator;
0040 typedef eventhypothesis::Looper<reco::Candidate> CandLooper;
0041
0042 void add(const CandRefType &ref, const std::string &role);
0043
0044 const_iterator begin() const { return particles_.begin(); }
0045 const_iterator end() const { return particles_.end(); }
0046 const_reverse_iterator rbegin() const { return particles_.rbegin(); }
0047 const_reverse_iterator rend() const { return particles_.rend(); }
0048
0049 class ByRole {
0050 public:
0051 ByRole(const std::string &role) : role_(role) {}
0052 bool operator()(const value_type &p) const { return p.first == role_; }
0053
0054 private:
0055 const std::string &role_;
0056 };
0057
0058 typedef eventhypothesis::ParticleFilter ParticleFilter;
0059 typedef eventhypothesis::ParticleFilterPtr ParticleFilterPtr;
0060
0061 const CandRefType &get(const std::string &role, int index = 0) const;
0062 const CandRefType &get(const ParticleFilter &filter, int index = 0) const;
0063 template <typename T>
0064 const T *getAs(const std::string &role, int index = 0) const;
0065 template <typename T>
0066 const T *getAs(const ParticleFilter &filter, int index = 0) const;
0067 const CandRefType &operator[](const std::string &role) const { return get(role, 0); }
0068 const CandRefType &operator[](const ParticleFilter &filter) const { return get(filter, 0); }
0069
0070
0071 std::vector<CandRefType> all(const std::string &roleRegexp) const;
0072
0073 std::vector<CandRefType> all(const ParticleFilter &filter) const;
0074
0075 size_t count() const { return particles_.size(); }
0076
0077 size_t count(const std::string &roleRegexp) const;
0078
0079 size_t count(const ParticleFilter &role) const;
0080
0081
0082 CandLooper loop() const;
0083
0084 CandLooper loop(const std::string &roleRegexp) const;
0085
0086
0087 CandLooper loop(const ParticleFilter &filter) const;
0088
0089
0090
0091 CandLooper loop(const ParticleFilter *filter) const;
0092
0093 CandLooper loop(const ParticleFilterPtr &filter) const;
0094
0095
0096 template <typename T>
0097 eventhypothesis::Looper<T> loopAs(const std::string &roleRegexp) const;
0098
0099
0100 template <typename T>
0101 eventhypothesis::Looper<T> loopAs(const ParticleFilter &filter) const;
0102
0103
0104
0105 template <typename T>
0106 eventhypothesis::Looper<T> loopAs(const ParticleFilter *filter) const;
0107
0108 template <typename T>
0109 eventhypothesis::Looper<T> loopAs(const ParticleFilterPtr &filter) const;
0110
0111 private:
0112 template <typename Iterator, typename Predicate>
0113 Iterator realGet(const Iterator &realBegin, const Iterator &realEnd, const Predicate &p, size_t idx) const;
0114 char *getDemangledSymbol(const char *mangledSymbol) const;
0115 template <typename T>
0116 std::string createExceptionMessage(const CandRefType &ref) const;
0117
0118 std::vector<value_type> particles_;
0119 };
0120
0121 namespace eventhypothesis {
0122 struct AcceptAllFilter : public ParticleFilter {
0123 AcceptAllFilter() {}
0124 static const AcceptAllFilter &get() { return s_dummyFilter; }
0125 bool operator()(const CandRefType &cand, const std::string &role) const override { return true; }
0126
0127 private:
0128 static const AcceptAllFilter s_dummyFilter;
0129 };
0130 class RoleRegexpFilter : public ParticleFilter {
0131 public:
0132 explicit RoleRegexpFilter(const std::string &roleRegexp) : re_(roleRegexp) {}
0133 bool operator()(const CandRefType &cand, const std::string &role) const override {
0134 return boost::regex_match(role, re_);
0135 }
0136
0137 private:
0138 boost::regex re_;
0139 };
0140 }
0141
0142 template <typename Iterator, typename Predicate>
0143 Iterator EventHypothesis::realGet(const Iterator &realBegin,
0144 const Iterator &realEnd,
0145 const Predicate &pred,
0146 size_t idx) const {
0147 Iterator it = realBegin;
0148 while (it != realEnd) {
0149 if (pred(*it)) {
0150 if (idx == 0)
0151 return it;
0152 idx--;
0153 }
0154 ++it;
0155 }
0156 return it;
0157 }
0158
0159 template <typename T>
0160 std::string EventHypothesis::createExceptionMessage(const CandRefType &ref) const {
0161 std::stringstream message;
0162 char *currentType = getDemangledSymbol(typeid(std::remove_reference<decltype(ref)>::type::value_type).name());
0163 char *targetType = getDemangledSymbol(typeid(T).name());
0164 if (currentType != nullptr && targetType != nullptr) {
0165 message << "You can't convert a '" << currentType << "' to a '" << targetType << "'" << std::endl;
0166 free(currentType);
0167 free(targetType);
0168 } else {
0169 message << "You can't convert a '" << typeid(ref).name() << "' to a '" << typeid(T).name() << "'" << std::endl;
0170 message << "Note: you can use 'c++filt -t' command to convert the above in human readable types." << std::endl;
0171 }
0172 return message.str();
0173 }
0174
0175 template <typename T>
0176 const T *EventHypothesis::getAs(const std::string &role, int index) const {
0177 CandRefType ref = get(role, index);
0178 const T *ret = dynamic_cast<const T *>(ref.get());
0179 if ((ret == nullptr) && (ref.get() != nullptr))
0180 throw cms::Exception("Type Checking") << createExceptionMessage<T>(ref);
0181 return ret;
0182 }
0183 template <typename T>
0184 const T *EventHypothesis::getAs(const ParticleFilter &filter, int index) const {
0185 CandRefType ref = get(filter, index);
0186 const T *ret = dynamic_cast<const T *>(ref.get());
0187 if ((ret == 0) && (ref.get() != nullptr))
0188 throw cms::Exception("Type Checking") << createExceptionMessage<T>(ref);
0189 return ret;
0190 }
0191 template <typename T>
0192 eventhypothesis::Looper<T> EventHypothesis::loopAs(const std::string &roleRegexp) const {
0193 return loopAs<T>(new pat::eventhypothesis::RoleRegexpFilter(roleRegexp));
0194 }
0195
0196 template <typename T>
0197 eventhypothesis::Looper<T> EventHypothesis::loopAs(const ParticleFilter &role) const {
0198 return pat::eventhypothesis::Looper<T>(*this, role);
0199 }
0200
0201 template <typename T>
0202 eventhypothesis::Looper<T> EventHypothesis::loopAs(const ParticleFilter *role) const {
0203 return pat::eventhypothesis::Looper<T>(*this, role);
0204 }
0205
0206 template <typename T>
0207 eventhypothesis::Looper<T> EventHypothesis::loopAs(const ParticleFilterPtr &role) const {
0208 return pat::eventhypothesis::Looper<T>(*this, role);
0209 }
0210 }
0211
0212 #endif