Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:24:10

0001 #ifndef PhysicsTools_SelectorUtils_Selector_h
0002 #define PhysicsTools_SelectorUtils_Selector_h
0003 
0004 /**
0005   \class    Selector Selector.h "CommonTools/Utils/interface/Selector.h"
0006   \brief    Implements a string-indexed bit_vector
0007 
0008   class template that implements an interface to Selector utilities. This
0009   allows the user to access individual cuts based on a string index.
0010   The user can then turn individual cuts on and off at will.
0011 
0012   \author Salvatore Rappoccio
0013 */
0014 
0015 #include "PhysicsTools/SelectorUtils/interface/strbitset.h"
0016 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0017 #include "FWCore/Common/interface/EventBase.h"
0018 #include <fstream>
0019 
0020 /// Functor that operates on <T>
0021 template <class T>
0022 class Selector {
0023 public:
0024   typedef T data_type;
0025   typedef pat::strbitset::index_type index_type;
0026   typedef std::pair<index_type, size_t> cut_flow_item;
0027   typedef std::vector<cut_flow_item> cut_flow_map;
0028   typedef std::map<index_type, int> int_map;
0029   typedef std::map<index_type, double> double_map;
0030 
0031   /// Constructor clears the bits
0032   Selector() {
0033     bits_.clear();
0034     intCuts_.clear();
0035     doubleCuts_.clear();
0036     cutFlow_.clear();
0037     retInternal_ = getBitTemplate();
0038   }
0039   virtual ~Selector() {}
0040 
0041   /// This is the registration of an individual cut string
0042   virtual void push_back(std::string const &s) {
0043     bits_.push_back(s);
0044     index_type i(&bits_, s);
0045     // don't need to check to see if the key is already there,
0046     // bits_ does that.
0047     cutFlow_.push_back(cut_flow_item(i, 0));
0048   }
0049 
0050   /// This is the registration of an individual cut string, with an int cut value
0051   virtual void push_back(std::string const &s, int cut) {
0052     bits_.push_back(s);
0053     index_type i(&bits_, s);
0054     intCuts_[i] = cut;
0055     // don't need to check to see if the key is already there,
0056     // bits_ does that.
0057     cutFlow_.push_back(cut_flow_item(i, 0));
0058   }
0059 
0060   /// This is the registration of an individual cut string, with a double cut value
0061   virtual void push_back(std::string const &s, double cut) {
0062     bits_.push_back(s);
0063     index_type i(&bits_, s);
0064     doubleCuts_[i] = cut;
0065     // don't need to check to see if the key is already there,
0066     // bits_ does that.
0067     cutFlow_.push_back(cut_flow_item(i, 0));
0068   }
0069 
0070   /// This provides the interface for base classes to select objects
0071   virtual bool operator()(T const &t, pat::strbitset &ret) = 0;
0072 
0073   /// This provides an alternative signature without the second ret
0074   virtual bool operator()(T const &t) {
0075     retInternal_.set(false);
0076     operator()(t, retInternal_);
0077     setIgnored(retInternal_);
0078     return (bool)retInternal_;
0079   }
0080 
0081   /// This provides an alternative signature that includes extra information
0082   virtual bool operator()(T const &t, edm::EventBase const &e, pat::strbitset &ret) { return operator()(t, ret); }
0083 
0084   /// This provides an alternative signature that includes extra information
0085   virtual bool operator()(T const &t, edm::EventBase const &e) {
0086     retInternal_.set(false);
0087     operator()(t, e, retInternal_);
0088     setIgnored(retInternal_);
0089     return (bool)retInternal_;
0090   }
0091 
0092   /// Set a given selection cut, on or off
0093   void set(std::string const &s, bool val = true) { set(index_type(&bits_, s), val); }
0094   void set(index_type const &i, bool val = true) { bits_[i] = val; }
0095 
0096   /// Set a given selection cut, on or off, and reset int cut value
0097   void set(std::string const &s, int cut, bool val = true) { set(index_type(&bits_, s), cut); }
0098   void set(index_type const &i, int cut, bool val = true) {
0099     bits_[i] = val;
0100     intCuts_[i] = cut;
0101   }
0102 
0103   /// Set a given selection cut, on or off, and reset int cut value
0104   void set(std::string const &s, double cut, bool val = true) { set(index_type(&bits_, s), cut); }
0105   void set(index_type const &i, double cut, bool val = true) {
0106     bits_[i] = val;
0107     doubleCuts_[i] = cut;
0108   }
0109 
0110   /// Turn off a given selection cut.
0111   void clear(std::string const &s) { clear(index_type(&bits_, s)); }
0112 
0113   void clear(index_type const &i) { bits_[i] = false; }
0114 
0115   /// Access the selector cut at index "s".
0116   /// "true" means to consider the cut.
0117   /// "false" means to ignore the cut.
0118   bool operator[](std::string const &s) const { return bits_[s]; }
0119 
0120   bool operator[](index_type const &i) const { return bits_[i]; }
0121 
0122   /// consider the cut at index "s"
0123   bool considerCut(std::string const &s) const { return bits_[s] == true; }
0124   bool considerCut(index_type const &i) const { return bits_[i] == true; }
0125 
0126   /// ignore the cut at index "s"
0127   bool ignoreCut(std::string const &s) const { return bits_[s] == false; }
0128   bool ignoreCut(index_type const &i) const { return bits_[i] == false; }
0129 
0130   /// set the bits to ignore from a vector
0131   void setIgnoredCuts(std::vector<std::string> const &bitsToIgnore) {
0132     for (std::vector<std::string>::const_iterator ignoreBegin = bitsToIgnore.begin(),
0133                                                   ignoreEnd = bitsToIgnore.end(),
0134                                                   ibit = ignoreBegin;
0135          ibit != ignoreEnd;
0136          ++ibit) {
0137       set(*ibit, false);
0138     }
0139   }
0140 
0141   /// Passing cuts
0142   void passCut(pat::strbitset &ret, std::string const &s) { passCut(ret, index_type(&bits_, s)); }
0143 
0144   void passCut(pat::strbitset &ret, index_type const &i) {
0145     ret[i] = true;
0146     cut_flow_map::iterator found = cutFlow_.end();
0147     for (cut_flow_map::iterator cutsBegin = cutFlow_.begin(), cutsEnd = cutFlow_.end(), icut = cutsBegin;
0148          icut != cutsEnd && found == cutsEnd;
0149          ++icut) {
0150       if (icut->first == i) {
0151         found = icut;
0152       }
0153     }
0154     ++(found->second);
0155   }
0156 
0157   /// Access the int cut values at index "s"
0158   int cut(index_type const &i, int val) const { return intCuts_.find(i)->second; };
0159   /// Access the double cut values at index "s"
0160   double cut(index_type const &i, double val) const { return doubleCuts_.find(i)->second; };
0161 
0162   /// Access the int cut values at index "s"
0163   int cut(std::string s, int val) const { return cut(index_type(&bits_, s), val); };
0164   /// Access the double cut values at index "s"
0165   double cut(std::string s, double val) const { return cut(index_type(&bits_, s), val); };
0166 
0167   /// Get an empty bitset with the proper names
0168   pat::strbitset getBitTemplate() const {
0169     pat::strbitset ret = bits_;
0170     ret.set(false);
0171     for (cut_flow_map::const_iterator cutsBegin = cutFlow_.begin(), cutsEnd = cutFlow_.end(), icut = cutsBegin;
0172          icut != cutsEnd;
0173          ++icut) {
0174       if (ignoreCut(icut->first))
0175         ret[icut->first] = true;
0176     }
0177     return ret;
0178   }
0179 
0180   /// set ignored bits
0181   void setIgnored(pat::strbitset &ret) {
0182     for (cut_flow_map::const_iterator cutsBegin = cutFlow_.begin(), cutsEnd = cutFlow_.end(), icut = cutsBegin;
0183          icut != cutsEnd;
0184          ++icut) {
0185       if (ignoreCut(icut->first))
0186         ret[icut->first] = true;
0187     }
0188   }
0189 
0190   /// Print the cut flow
0191   void print(std::ostream &out) const {
0192     for (cut_flow_map::const_iterator cutsBegin = cutFlow_.begin(), cutsEnd = cutFlow_.end(), icut = cutsBegin;
0193          icut != cutsEnd;
0194          ++icut) {
0195       char buff[1000];
0196       if (considerCut(icut->first)) {
0197         sprintf(buff,
0198                 "%6lu : %20s %10lu",
0199                 static_cast<unsigned long>(icut - cutsBegin),
0200                 icut->first.str().c_str(),
0201                 static_cast<unsigned long>(icut->second));
0202       } else {
0203         sprintf(
0204             buff, "%6lu : %20s %10s", static_cast<unsigned long>(icut - cutsBegin), icut->first.str().c_str(), "off");
0205       }
0206       out << buff << std::endl;
0207     }
0208   }
0209 
0210   /// Print the cuts being considered
0211   void printActiveCuts(std::ostream &out) const {
0212     bool already_printed_one = false;
0213     for (cut_flow_map::const_iterator cutsBegin = cutFlow_.begin(), cutsEnd = cutFlow_.end(), icut = cutsBegin;
0214          icut != cutsEnd;
0215          ++icut) {
0216       if (considerCut(icut->first)) {
0217         if (already_printed_one)
0218           out << ", ";
0219         out << icut->first;
0220         already_printed_one = true;
0221       }
0222     }
0223     out << std::endl;
0224   }
0225 
0226   /// Return the number of passing cases
0227   double getPasses(std::string const &s) const { return getPasses(index_type(&bits_, s)); }
0228   double getPasses(index_type const &i) const {
0229     cut_flow_map::const_iterator found = cutFlow_.end();
0230     for (cut_flow_map::const_iterator cutsBegin = cutFlow_.begin(), cutsEnd = cutFlow_.end(), icut = cutsBegin;
0231          icut != cutsEnd && found == cutsEnd;
0232          ++icut) {
0233       if (icut->first == i) {
0234         found = icut;
0235       }
0236     }
0237     return found->second;
0238   }
0239 
0240 protected:
0241   pat::strbitset bits_;         //!< the bitset indexed by strings
0242   pat::strbitset retInternal_;  //!< internal ret if users don't care about return bits
0243   int_map intCuts_;             //!< the int-value cut map
0244   double_map doubleCuts_;       //!< the double-value cut map
0245   cut_flow_map cutFlow_;        //!< map of cut flows in "human" order
0246 };
0247 
0248 #endif