CMS 3D CMS Logo

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