Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:54:18

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   // forward declaration
0015   namespace eventhypothesis {
0016     template <typename T>
0017     class Looper;
0018   }
0019   // real declarations
0020   namespace eventhypothesis {
0021     // typedef for the Ref
0022     typedef reco::CandidatePtr CandRefType;  // Ptr one day in the future
0023     // filter
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     // smart pointer to the filter
0030     typedef std::shared_ptr<const ParticleFilter> ParticleFilterPtr;
0031   }  // namespace eventhypothesis
0032   // the class
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     /// Return EDM references to all particles which have certaint roles.
0071     std::vector<CandRefType> all(const std::string &roleRegexp) const;
0072     /// Return EDM references to all particles which satisfy some condition.
0073     std::vector<CandRefType> all(const ParticleFilter &filter) const;
0074 
0075     size_t count() const { return particles_.size(); }
0076     /// Counts particles which have certaint roles.
0077     size_t count(const std::string &roleRegexp) const;
0078     /// Counts particles which satisfy some condition.
0079     size_t count(const ParticleFilter &role) const;
0080 
0081     /// Loops over all particles
0082     CandLooper loop() const;
0083     /// Loops over particles which have certaint roles.
0084     CandLooper loop(const std::string &roleRegexp) const;
0085     /// Loops over particles which satisfy some condition.
0086     /// The caller code owns the filter, and must take care it is not deleted while the looper is still being used
0087     CandLooper loop(const ParticleFilter &filter) const;
0088     /// Loops over particles which satisfy some condition.
0089     /// The looper owns the filter, which will be deleted when the looper is deleted.
0090     /// That is, you can call eventHypothesis.loop(new WhateverFilterYouLike(...))
0091     CandLooper loop(const ParticleFilter *filter) const;
0092     /// Loops over particles which satisfy some condition.
0093     CandLooper loop(const ParticleFilterPtr &filter) const;
0094 
0095     /// Loops over particles which have certaint roles.
0096     template <typename T>
0097     eventhypothesis::Looper<T> loopAs(const std::string &roleRegexp) const;
0098     /// Loops over particles which satisfy some condition.
0099     /// The caller code owns the filter, and must take care it is not deleted while the looper is still being used
0100     template <typename T>
0101     eventhypothesis::Looper<T> loopAs(const ParticleFilter &filter) const;
0102     /// Loops over particles which satisfy some condition.
0103     /// The looper owns the filter, which will be deleted when the looper is deleted.
0104     /// That is, you can call eventHypothesis.loopAs<...>(new WhateverFilterYouLike(...))
0105     template <typename T>
0106     eventhypothesis::Looper<T> loopAs(const ParticleFilter *filter) const;
0107     /// Loops over particles which satisfy some condition.
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   }  // namespace eventhypothesis
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 }  // namespace pat
0211 
0212 #endif