CMS 3D CMS Logo

VersionedSelector.h
Go to the documentation of this file.
1 #ifndef PhysicsTools_SelectorUtils_VersionedSelector_h
2 #define PhysicsTools_SelectorUtils_VersionedSelector_h
3 
14 #if ( !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__REFLEX__) && !defined(__CLING__) )
15 
16 #define REGULAR_CPLUSPLUS 1
17 #define CINT_GUARD(CODE) CODE
19 #include <memory>
20 #define SHARED_PTR(T) std::shared_ptr<T>
21 
22 #else
23 
24 #define CINT_GUARD(CODE)
25 #include <boost/shared_ptr.hpp>
26 #define SHARED_PTR(T) boost::shared_ptr<T>
27 
28 #endif
29 
35 
36 // because we need to be able to validate the ID
37 #include <openssl/md5.h>
38 
39 namespace candf = candidate_functions;
40 
41 namespace vid {
42  class CutFlowResult;
43 }
44 
45 template<class T>
46 class VersionedSelector : public Selector<T> {
47  public:
48  VersionedSelector() : Selector<T>(), initialized_(false) {}
49 
51  Selector<T>(),
52  initialized_(false) {
53 
54  validateParamsAreTracked(conf);
55 
56  name_ = conf.getParameter<std::string>("idName");
57 
58  // now setup the md5 and cute accessor functions
59  constexpr unsigned length = MD5_DIGEST_LENGTH;
60  std::string tracked(conf.trackedPart().dump());
61  memset(id_md5_,0,length*sizeof(unsigned char));
62  MD5((unsigned char*)tracked.c_str(), tracked.size(), id_md5_);
63  char buf[32];
64  for( unsigned i=0; i<MD5_DIGEST_LENGTH; ++i ){
65  sprintf(buf, "%02x", id_md5_[i]);
66  md5_string_.append( buf );
67  }
68  initialize(conf);
69  this->retInternal_ = this->getBitTemplate();
70  }
71 
72  bool operator()( const T& ref, pat::strbitset& ret ) CINT_GUARD(final) {
73  howfar_ = 0;
74  bitmap_ = 0;
75  values_.clear();
76  bool failed = false;
77  if( !initialized_ ) {
78  throw cms::Exception("CutNotInitialized")
79  << "VersionedGsfElectronSelector not initialized!" << std::endl;
80  }
81  for( unsigned i = 0; i < cuts_.size(); ++i ) {
83  const bool result = (*cuts_[i])(temp);
84  values_.push_back(cuts_[i]->value(temp));
85  if( result || this->ignoreCut(cut_indices_[i]) ) {
86  this->passCut(ret,cut_indices_[i]);
87  bitmap_ |= 1<<i;
88  if( !failed ) ++howfar_;
89  } else {
90  failed = true;
91  }
92  }
93  this->setIgnored(ret);
94  return (bool)ret;
95  }
96 
97  bool operator()(const T& ref, edm::EventBase const& e, pat::strbitset& ret) CINT_GUARD(final) {
98  // setup isolation needs
99  for( size_t i = 0, cutssize = cuts_.size(); i < cutssize; ++i ) {
100  if( needs_event_content_[i] ) {
101  CutApplicatorWithEventContentBase* needsEvent =
102  static_cast<CutApplicatorWithEventContentBase*>(cuts_[i].get());
103  needsEvent->getEventContent(e);
104  }
105  }
106  return this->operator()(ref, ret);
107  }
108 
109  //repeat the other operator() we left out here
110  //in the base class here so they are exposed to ROOT
111 
112  /* VID BY VALUE */
113  bool operator()( typename T::value_type const & t ) {
114  const T temp(&t,0); // assuming T is edm::Ptr
115  return this->operator()(temp);
116  }
117 
118  bool operator()( typename T::value_type const & t, edm::EventBase const & e) {
119  const T temp(&t,0);
120  return this->operator()(temp,e);
121  }
122 
123  bool operator()( T const & t ) CINT_GUARD(final) {
124  this->retInternal_.set(false);
125  this->operator()(t, this->retInternal_);
126  this->setIgnored(this->retInternal_);
127  return (bool)this->retInternal_;
128  }
129 
130  bool operator()( T const & t, edm::EventBase const & e) CINT_GUARD(final) {
131  this->retInternal_.set(false);
132  this->operator()(t, e, this->retInternal_);
133  this->setIgnored(this->retInternal_);
134  return (bool)this->retInternal_;
135  }
136 
137  const unsigned char* md55Raw() const { return id_md5_; }
138  bool operator==(const VersionedSelector& other) const {
139  constexpr unsigned length = MD5_DIGEST_LENGTH;
140  return ( 0 == memcmp(id_md5_,other.id_md5_,length*sizeof(unsigned char)) );
141  }
142  const std::string& md5String() const { return md5_string_; }
143 
144  const std::string& name() const { return name_; }
145 
146  const unsigned howFarInCutFlow() const { return howfar_; }
147 
148  const unsigned bitMap() const { return bitmap_; }
149 
150  const size_t cutFlowSize() const { return cuts_.size(); }
151 
152  vid::CutFlowResult cutFlowResult() const;
153 
154  void initialize(const edm::ParameterSet&);
155 
156  CINT_GUARD(void setConsumes(edm::ConsumesCollector));
157 
158  private:
159  //here we check that the parameters of the VID cuts are tracked
160  //we allow exactly one parameter to be untracked "isPOGApproved"
161  //as if its tracked, its a pain for the md5Sums
162  //due to the mechanics of PSets, it was demined easier just to
163  //create a new config which doesnt have an untracked isPOGApproved
164  //if isPOGApproved is tracked (if we decide to do that in the future), it keeps it
165  //see https://github.com/cms-sw/cmssw/issues/19799 for the discussion
166  static void validateParamsAreTracked(const edm::ParameterSet& conf){
167  edm::ParameterSet trackedPart = conf.trackedPart();
168  edm::ParameterSet confWithoutIsPOGApproved;
169  for(auto& paraName : conf.getParameterNames()){
170  if(paraName != "isPOGApproved") confWithoutIsPOGApproved.copyFrom(conf,paraName);
171  else if(conf.existsAs<bool>(paraName,true)) confWithoutIsPOGApproved.copyFrom(conf,paraName); //adding isPOGApproved if its a tracked bool
172  }
173  std::string tracked(conf.trackedPart().dump()), untracked(confWithoutIsPOGApproved.dump());
174  if ( tracked != untracked ) {
175  throw cms::Exception("InvalidConfiguration")
176  << "VersionedSelector does not allow untracked parameters"
177  << " in the cutflow ParameterSet!";
178  }
179  }
180 
181 
182  protected:
184  std::vector<SHARED_PTR(candf::CandidateCut) > cuts_;
185  std::vector<bool> needs_event_content_;
186  std::vector<typename Selector<T>::index_type> cut_indices_;
187  unsigned howfar_, bitmap_;
188  std::vector<double> values_;
189 
190  private:
191  unsigned char id_md5_[MD5_DIGEST_LENGTH];
192  std::string md5_string_,name_;
193 };
194 
195 template<class T>
198  if(initialized_) {
199  edm::LogWarning("VersionedPatElectronSelector")
200  << "ID was already initialized!";
201  return;
202  }
203  const std::vector<edm::ParameterSet>& cutflow =
204  conf.getParameterSetVector("cutFlow");
205  if( cutflow.empty() ) {
206  throw cms::Exception("InvalidCutFlow")
207  << "You have supplied a null/empty cutflow to VersionedIDSelector,"
208  << " please add content to the cuflow and try again.";
209  }
210 
211  // this lets us keep track of cuts without knowing what they are :D
212  std::vector<edm::ParameterSet>::const_iterator cbegin(cutflow.begin()),
213  cend(cutflow.end());
214  std::vector<edm::ParameterSet>::const_iterator icut = cbegin;
215  std::map<std::string,unsigned> cut_counter;
216  std::vector<std::string> ignored_cuts;
217  for( ; icut != cend; ++icut ) {
218  std::stringstream realname;
219  const std::string& name = icut->getParameter<std::string>("cutName");
220  if( !cut_counter.count(name) ) cut_counter[name] = 0;
221  realname << name << "_" << cut_counter[name];
222  const bool needsContent =
223  icut->getParameter<bool>("needsAdditionalProducts");
224  const bool ignored = icut->getParameter<bool>("isIgnored");
225  CINT_GUARD(cuts_.emplace_back(CutApplicatorFactory::get()->create(name,*icut)));
226  needs_event_content_.push_back(needsContent);
227  const std::string therealname = realname.str();
228  this->push_back(therealname);
229  this->set(therealname);
230  if(ignored) ignored_cuts.push_back(therealname);
231  cut_counter[name]++;
232  }
233  this->setIgnoredCuts(ignored_cuts);
234 
235  //have to loop again to set cut indices after all are filled
236  icut = cbegin;
237  cut_counter.clear();
238  for( ; icut != cend; ++icut ) {
239  std::stringstream realname;
240  const std::string& name = cuts_[std::distance(cbegin,icut)]->name();
241  if( !cut_counter.count(name) ) cut_counter[name] = 0;
242  realname << name << "_" << cut_counter[name];
243  cut_indices_.push_back(typename Selector<T>::index_type(&(this->bits_),realname.str()));
244  cut_counter[name]++;
245  }
246 
247  initialized_ = true;
248 }
249 
250 
251 
252 #ifdef REGULAR_CPLUSPLUS
254 template<class T>
256  std::map<std::string,unsigned> names_to_index;
257  std::map<std::string,unsigned> cut_counter;
258  for( unsigned idx = 0; idx < cuts_.size(); ++idx ) {
259  const std::string& name = cuts_[idx]->name();
260  if( !cut_counter.count(name) ) cut_counter[name] = 0;
261  std::stringstream realname;
262  realname << name << "_" << cut_counter[name];
263  names_to_index.emplace(realname.str(),idx);
264  cut_counter[name]++;
265  }
266  return vid::CutFlowResult(name_,md5_string_,names_to_index,values_,bitmap_);
267 }
268 
270 template<class T>
272  for( size_t i = 0, cutssize = cuts_.size(); i < cutssize; ++i ) {
273  if( needs_event_content_[i] ) {
274  CutApplicatorWithEventContentBase* needsEvent =
275  dynamic_cast<CutApplicatorWithEventContentBase*>(cuts_[i].get());
276  if( nullptr != needsEvent ) {
277  needsEvent->setConsumes(cc);
278  } else {
279  throw cms::Exception("InvalidCutConfiguration")
280  << "Cut: " << ((CutApplicatorBase*)cuts_[i].get())->name()
281  << " configured to consume event products but does not "
282  << " inherit from CutApplicatorWithEventContenBase "
283  << " please correct either your python or C++!";
284  }
285  }
286  }
287 }
288 #endif
289 
290 #endif
T getParameter(std::string const &) const
static AlgebraicMatrix initialize()
bool operator()(T const &t) final
This provides an alternative signature without the second ret.
VParameterSet const & getParameterSetVector(std::string const &name) const
const unsigned char * md55Raw() const
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:161
bool operator()(typename T::value_type const &t)
bool operator()(typename T::value_type const &t, edm::EventBase const &e)
std::vector< double > values_
vid::CutFlowResult cutFlowResult() const
std::string dump(unsigned int indent=0) const
const size_t cutFlowSize() const
std::vector< std::shared_ptr< candf::CandidateCut > > cuts_
VersionedSelector(const edm::ParameterSet &conf)
ParameterSet trackedPart() const
std::vector< bool > needs_event_content_
const std::string & name() const
void copyFrom(ParameterSet const &from, std::string const &name)
void initialize(const edm::ParameterSet &)
virtual void getEventContent(const edm::EventBase &)=0
const unsigned bitMap() const
std::vector< std::string > getParameterNames() const
Functor that operates on <T>
Definition: Selector.h:23
bool operator()(const T &ref, edm::EventBase const &e, pat::strbitset &ret) final
bool operator()(T const &t, edm::EventBase const &e) final
This provides an alternative signature that includes extra information.
const unsigned howFarInCutFlow() const
const std::string & md5String() const
void setConsumes(edm::ConsumesCollector)
unsigned char id_md5_[MD5_DIGEST_LENGTH]
#define CINT_GUARD(CODE)
static void validateParamsAreTracked(const edm::ParameterSet &conf)
long double T
std::vector< typename Selector< T >::index_type > cut_indices_
cut-flow versioning info in the event provenance
bool operator==(const VersionedSelector &other) const
virtual void setConsumes(edm::ConsumesCollector &)=0
T get(const Candidate &c)
Definition: component.h:55
#define constexpr
bool operator()(const T &ref, pat::strbitset &ret) final