CMS 3D CMS Logo

CachingVariable.h
Go to the documentation of this file.
1 #ifndef ConfigurableAnalysis_CachingVariable_H
2 #define ConfigurableAnalysis_CachingVariable_H
3 
12 
14 
15 namespace edm {
16  class EventSetup;
17 }
18 #include <vector>
19 #include "TString.h"
20 
21 class Description {
22 public:
24  Description(std::vector<std::string>& d) : d_(d) {}
25  std::string text() const {
27  for (unsigned int i = 0; i != d_.size(); ++i)
28  text += d_[i] + "\n";
29  return text;
30  }
31  const std::vector<std::string> lines() { return d_; }
32  void addLine(const std::string& l) { d_.push_back(l); }
33 
34 private:
35  std::vector<std::string> d_;
36 };
37 
38 class VariableComputer;
39 
41 public:
42  //every variable return double values
43  typedef double valueType;
44  typedef std::pair<bool, valueType> evalType;
45  typedef std::map<std::string, const CachingVariable*> vMap;
49  : n(N), m(M), iConfig(P) {}
53  };
54 
56  : cache_(std::make_pair(false, 0)), method_(m), name_(n), conf_(iConfig) {}
57 
58  virtual ~CachingVariable() {}
59 
60  //does the variable computes
61  bool compute(const edm::Event& iEvent) const { return baseEval(iEvent).first; }
62 
63  //accessor to the computed/cached value
64  valueType operator()(const edm::Event& iEvent) const { return baseEval(iEvent).second; }
65 
66  const std::string& name() const { return name_; }
67  const std::string& method() const { return method_; }
68  const Description& description() const { return d_; }
70  const std::string& holderName() const { return holderName_; }
71  void setHolder(std::string hn) const { holderName_ = hn; }
72 
73  void print() const { edm::LogVerbatim("CachingVariable") << name() << "\n" << description().text(); }
74 
75 protected:
76  mutable evalType cache_;
78 
82  void setCache(valueType& v) const {
83  cache_.first = true;
84  cache_.second = v;
85  }
86  void setNotCompute() const {
87  cache_.first = false;
88  cache_.second = 0;
89  }
92  LogDebug("CachingVariable") << name_ + ":" + holderName_ << " is checking once";
93  cache_ = eval(iEvent);
94  }
95  return cache_;
96  }
99  eventCacheID_ != iEvent.cacheIdentifier());
100  if (retValue) {
101  eventCacheID_ = iEvent.cacheIdentifier();
102  }
103  return retValue;
104  }
105 
106  //cannot be made purely virtual otherwise one cannot have purely CachingVariableObjects
107  virtual evalType eval(const edm::Event& iEvent) const { return std::make_pair(false, 0); };
108 
109  Description d_;
111  friend class VariableComputer;
112 };
113 
114 class ComputedVariable;
116 public:
118  virtual ~VariableComputer() {}
119 
120  virtual void compute(const edm::Event& iEvent) const = 0;
121  const std::string& name() const { return name_; }
123  void assign(std::string var, double& value) const;
124  void doesNotCompute() const;
125  void doesNotCompute(std::string var) const;
126 
129  eventCacheID_ != iEvent.cacheIdentifier());
130  if (retValue) {
131  eventCacheID_ = iEvent.cacheIdentifier();
132  }
133  return retValue;
134  }
135 
136 protected:
140  mutable std::map<std::string, const ComputedVariable*> iCompute_;
142 
144 };
145 
148 
155 
157 public:
161  : CachingVariable(M, N, P, iC), myComputer(c) {}
162  ~ComputedVariable() override {}
163 
164  evalType eval(const edm::Event& iEvent) const override {
165  if (myComputer->notSeenThisEventAlready(iEvent))
166  myComputer->compute(iEvent);
167  return cache_;
168  }
169 
170 private:
171  std::unique_ptr<const VariableComputer> myComputer;
172 };
173 
175 public:
177  ~VariableComputerTest() override {}
178 
179  void compute(const edm::Event& iEvent) const override;
180 };
181 
182 class Splitter : public CachingVariable {
183 public:
185  : CachingVariable(method, n, iConfig, iC) {}
186 
187  //purely virtual here
188  CachingVariable::evalType eval(const edm::Event& iEvent) const override = 0;
189 
190  unsigned int maxIndex() const { return maxSlots() - 1; }
191 
192  //maximum NUMBER of slots: counting over/under flows
193  virtual unsigned int maxSlots() const { return labels_.size(); }
194 
195  const std::string shortLabel(unsigned int i) const {
196  if (i >= short_labels_.size()) {
197  edm::LogError("Splitter") << "trying to access slots short_label at index: " << i
198  << "while of size: " << short_labels_.size() << "\n"
199  << conf_.dump();
200  return short_labels_.back();
201  } else
202  return short_labels_[i];
203  }
204 
205  const std::string& label(unsigned int i) const {
206  if (i >= labels_.size()) {
207  edm::LogError("Splitter") << "trying to access slots label at index: " << i << "while of size: " << labels_.size()
208  << "\n"
209  << conf_.dump();
210  return labels_.back();
211  } else
212  return labels_[i];
213  }
214 
215 protected:
216  std::vector<std::string> labels_;
217  std::vector<std::string> short_labels_;
218 };
219 
220 class VarSplitter : public Splitter {
221 public:
223  : Splitter("VarSplitter", arg.n, arg.iConfig, iC) {
224  var_ = arg.iConfig.getParameter<std::string>("var");
225  useUnderFlow_ = arg.iConfig.getParameter<bool>("useUnderFlow");
226  useOverFlow_ = arg.iConfig.getParameter<bool>("useOverFlow");
227  slots_ = arg.iConfig.getParameter<std::vector<double> >("slots");
228  if (useUnderFlow_) {
229  labels_.push_back("underflow");
230  short_labels_.push_back("_" + arg.n + "_underflow");
231  }
232  std::vector<std::string> confLabels;
233  if (arg.iConfig.exists("labels")) {
234  confLabels = arg.iConfig.getParameter<std::vector<std::string> >("labels");
235  } else {
236  std::string labelFormat = arg.iConfig.getParameter<std::string>("labelsFormat");
237  for (unsigned int is = 0; is != slots_.size() - 1; ++is) {
238  std::string l(Form(labelFormat.c_str(), slots_[is], slots_[is + 1]));
239  confLabels.push_back(l);
240  }
241  }
242  for (unsigned int i = 0; i != confLabels.size(); ++i) {
243  labels_.push_back(confLabels[i]);
244  std::stringstream ss;
245  ss << "_" << arg.n << "_" << i;
246  short_labels_.push_back(ss.str());
247  }
248  if (useOverFlow_) {
249  labels_.push_back("overFlow");
250  short_labels_.push_back("_" + arg.n + "_overFlow");
251  }
252 
253  //check consistency
254  if (labels_.size() != maxSlots())
255  edm::LogError("Splitter") << "splitter with name: " << name() << " has inconsistent configuration\n"
256  << conf_.dump();
257 
258  arg.m[arg.n] = this;
259  }
260 
261  CachingVariable::evalType eval(const edm::Event& iEvent) const override;
262 
263  //redefine the maximum number of slots
264  unsigned int maxSlots() const override {
265  unsigned int s = slots_.size() - 1;
266  if (useUnderFlow_)
267  s++;
268  if (useOverFlow_)
269  s++;
270  return s;
271  }
272 
273 protected:
277  std::vector<double> slots_;
278 };
279 
280 template <typename Object, const char* label>
282 public:
284  : CachingVariable(std::string(label) + "ExpressionVariable", arg.n, arg.iConfig, iC),
285  f_(nullptr),
286  forder_(nullptr) {
287  srcTag_ = edm::Service<InputTagDistributorService>()->retrieve("src", arg.iConfig);
289  //old style constructor
290  if (arg.iConfig.exists("expr") && arg.iConfig.exists("index")) {
291  std::string expr = arg.iConfig.getParameter<std::string>("expr");
292  index_ = arg.iConfig.getParameter<unsigned int>("index");
294  addDescriptionLine("calculating: " + expr);
295  std::stringstream ss;
296  ss << "on object at index: " << index_ << " of: " << srcTag_;
297 
298  if (arg.iConfig.exists("order")) {
299  std::string order = arg.iConfig.getParameter<std::string>("order");
301  ss << " after sorting according to: " << order;
302  } else
303  forder_ = nullptr;
304 
305  if (arg.iConfig.exists("selection")) {
306  std::string selection = arg.iConfig.getParameter<std::string>("selection");
308  ss << " and selecting only: " << selection;
309  } else
310  selector_ = nullptr;
311 
312  addDescriptionLine(ss.str());
313  ss.str("");
314  arg.m[arg.n] = this;
315  } else {
316  //multiple instance constructor
317  std::map<std::string, edm::Entry> indexEntry;
318  if (arg.n.find("_N") != std::string::npos) {
319  //will have to loop over indexes
320  std::vector<unsigned int> indexes = arg.iConfig.getParameter<std::vector<unsigned int> >("indexes");
321  for (unsigned int iI = 0; iI != indexes.size(); ++iI) {
322  edm::ParameterSet toUse = arg.iConfig;
323  edm::Entry e("unsigned int", indexes[iI], true);
324  std::stringstream ss;
325  //add +1 0->1, 1->2, ... in the variable label
326  ss << indexes[iI] + 1;
327  indexEntry.insert(std::make_pair(ss.str(), e));
328  }
329  } //contains "_N"
330 
331  std::map<std::string, edm::Entry> varEntry;
332  if (arg.n.find("_V") != std::string::npos) {
333  //do something fancy for multiple variable from one PSet
334  std::vector<std::string> vars = arg.iConfig.getParameter<std::vector<std::string> >("vars");
335  for (unsigned int v = 0; v != vars.size(); ++v) {
336  unsigned int sep = vars[v].find(':');
337  std::string name = vars[v].substr(0, sep);
338  std::string expr = vars[v].substr(sep + 1);
339 
340  edm::Entry e("string", expr, true);
341  varEntry.insert(std::make_pair(name, e));
342  }
343  } //contains "_V"
344 
345  std::string radical = arg.n;
346  //remove the "_V";
347  if (!varEntry.empty())
348  radical = radical.substr(0, radical.size() - 2);
349  //remove the "_N";
350  if (!indexEntry.empty())
351  radical = radical.substr(0, radical.size() - 2);
352 
353  if (varEntry.empty()) {
354  //loop only the indexes
355  for (std::map<std::string, edm::Entry>::iterator iIt = indexEntry.begin(); iIt != indexEntry.end(); ++iIt) {
356  edm::ParameterSet toUse = arg.iConfig;
357  toUse.insert(true, "index", iIt->second);
358  std::string newVname = radical + iIt->first;
359  // std::cout<<"in the loop, creating variable with name: "<<newVname<<std::endl;
360  // the constructor auto log the new variable in the map
362  }
363  } else {
364  for (std::map<std::string, edm::Entry>::iterator vIt = varEntry.begin(); vIt != varEntry.end(); ++vIt) {
365  if (indexEntry.empty()) {
366  edm::ParameterSet toUse = arg.iConfig;
367  toUse.insert(true, "expr", vIt->second);
368  std::string newVname = radical + vIt->first;
369  // std::cout<<"in the loop, creating variable with name: "<<newVname<<std::endl;
370  // the constructor auto log the new variable in the map
372  } else {
373  for (std::map<std::string, edm::Entry>::iterator iIt = indexEntry.begin(); iIt != indexEntry.end(); ++iIt) {
374  edm::ParameterSet toUse = arg.iConfig;
375  toUse.insert(true, "expr", vIt->second);
376  toUse.insert(true, "index", iIt->second);
377  std::string newVname = radical + iIt->first + vIt->first;
378  // std::cout<<"in the loop, creating variable with name: "<<newVname<<std::endl;
379  // the constructor auto log the new variable in the map
381  }
382  }
383  }
384  }
385  //there is a memory leak here, because the object we are in is not logged in the arg.m, the variable is not valid
386  // anyways, but reside in memory with no ways of de-allocating it.
387  // since the caching variables are actually "global" objects, it does not matter.
388  // we cannot add it to the map, otherwise, it would be considered for eventV ntupler
389  }
390  }
391  ~ExpressionVariable() override {
392  if (f_)
393  delete f_;
394  if (forder_)
395  delete forder_;
396  if (selector_)
397  delete selector_;
398  }
399 
401  if (!f_) {
402  edm::LogError(method()) << " no parser attached.";
403  return std::make_pair(false, 0);
404  }
406  iEvent.getByToken(src_, oH);
407  if (index_ >= oH->size()) {
408  LogDebug(method()) << "fail to get object at index: " << index_ << " in collection: " << srcTag_;
409  return std::make_pair(false, 0);
410  }
411 
412  //get the ordering right first. if required
413  if (selector_ || forder_) {
414  std::vector<const Object*> copyToSort(0);
415  copyToSort.reserve(oH->size());
416  for (unsigned int i = 0; i != oH->size(); ++i) {
417  if (selector_ && !((*selector_)((*oH)[i])))
418  continue;
419  copyToSort.push_back(&(*oH)[i]);
420  }
421  if (index_ >= copyToSort.size())
422  return std::make_pair(false, 0);
423  if (forder_)
424  std::sort(copyToSort.begin(), copyToSort.end(), sortByStringFunction<Object>(forder_));
425 
426  const Object* o = copyToSort[index_];
427  return std::make_pair(true, (*f_)(*o));
428  } else {
429  const Object& o = (*oH)[index_];
430  return std::make_pair(true, (*f_)(o));
431  }
432  }
433 
434 private:
437  unsigned int index_;
441 };
442 
443 template <typename LHS, const char* lLHS, typename RHS, const char* lRHS, typename Calculator>
445 public:
447  : CachingVariable(Calculator::calculationType() + std::string(lLHS) + std::string(lRHS), arg.n, arg.iConfig, iC),
448  srcLhsTag_(edm::Service<InputTagDistributorService>()->retrieve("srcLhs", arg.iConfig)),
449  srcLhs_(iC.consumes<std::vector<LHS> >(srcLhsTag_)),
450  indexLhs_(arg.iConfig.getParameter<unsigned int>("indexLhs")),
451  srcRhsTag_(edm::Service<InputTagDistributorService>()->retrieve("srcRhs", arg.iConfig)),
452  srcRhs_(iC.consumes<std::vector<RHS> >(srcRhsTag_)),
453  indexRhs_(arg.iConfig.getParameter<unsigned int>("indexRhs")) {
454  std::stringstream ss;
456  ss << "with Obj1 at index: " << indexLhs_ << " of: " << srcLhs_;
457  addDescriptionLine(ss.str());
458  ss.str("");
459  ss << "with Obj2 at index: " << indexRhs_ << " of: " << srcRhs_;
460  addDescriptionLine(ss.str());
461  ss.str("");
462  arg.m[arg.n] = this;
463  }
464 
465  class getObject {
466  public:
467  getObject() : test(false), lhs(0), rhs(0) {}
468  bool test;
469  const LHS* lhs;
470  const RHS* rhs;
471  };
475  iEvent.getByToken(srcLhs_, lhsH);
476  if (lhsH.failedToGet()) {
477  LogDebug("TwoObjectVariable") << name() << " could not get a collection with label: " << srcLhsTag_;
478  return failed;
479  }
480  if (indexLhs_ >= lhsH->size()) {
481  LogDebug("TwoObjectVariable") << name() << " tries to access index: " << indexLhs_ << " of: " << srcLhsTag_
482  << " with: " << lhsH->size() << " entries.";
483  return failed;
484  }
485  const LHS& lhs = (*lhsH)[indexLhs_];
486 
488  iEvent.getByToken(srcRhs_, rhsH);
489  if (rhsH.failedToGet()) {
490  LogDebug("TwoObjectVariable") << name() << " could not get a collection with label: " << srcLhsTag_;
491  return failed;
492  }
493 
494  if (indexRhs_ >= rhsH->size()) {
495  LogDebug("TwoObjectVariable") << name() << " tries to access index: " << indexRhs_ << " of: " << srcRhsTag_
496  << " with: " << rhsH->size() << " entries.";
497  return failed;
498  }
499  const RHS& rhs = (*rhsH)[indexRhs_];
500 
501  failed.test = true;
502  failed.lhs = &lhs;
503  failed.rhs = &rhs;
504  return failed;
505  }
506 
507  //to be overloaded by the user
509  Calculator calc;
510  return calc(*o.lhs, *o.rhs);
511  }
514  if (!o.test)
515  return std::make_pair(false, 0);
516  return std::make_pair(true, calculate(o));
517  }
518 
519 private:
522  unsigned int indexLhs_;
525  unsigned int indexRhs_;
526 };
527 
529 public:
531  : CachingVariable("Power", arg.n, arg.iConfig, iC) {
532  power_ = arg.iConfig.getParameter<double>("power");
533  var_ = arg.iConfig.getParameter<std::string>("var");
534  std::stringstream ss("Calculare X^Y, with X=");
535  ss << var_ << " and Y=" << power_;
536  addDescriptionLine(ss.str());
537  arg.m[arg.n] = this;
538  }
539  ~VariablePower() override {}
540 
541  //concrete calculation of the variable
542  CachingVariable::evalType eval(const edm::Event& iEvent) const override;
543 
544 private:
545  double power_;
547 };
548 
549 template <typename TYPE>
551 public:
553  : CachingVariable("SimpleValueVariable", arg.n, arg.iConfig, iC),
554  src_(iC.consumes<TYPE>(edm::Service<InputTagDistributorService>()->retrieve("src", arg.iConfig))) {
555  arg.m[arg.n] = this;
556  }
559  iEvent.getByToken(src_, value);
560  if (value.failedToGet() || !value.isValid())
561  return std::make_pair(false, 0);
562  else
563  return std::make_pair(true, *value);
564  }
565 
566 private:
568 };
569 
570 template <typename TYPE>
572 public:
574  : CachingVariable("SimpleValueVectorVariable", arg.n, arg.iConfig, iC),
575  src_(iC.consumes<TYPE>(edm::Service<InputTagDistributorService>()->retrieve("src", arg.iConfig))),
576  index_(arg.iConfig.getParameter<unsigned int>("index")) {
577  arg.m[arg.n] = this;
578  }
581  iEvent.getByToken(src_, values);
582  if (values.failedToGet() || !values.isValid())
583  return std::make_pair(false, 0);
584  else if (index_ >= values->size())
585  return std::make_pair(false, 0);
586  else
587  return std::make_pair(true, (*values)[index_]);
588  }
589 
590 private:
592  unsigned int index_;
593 };
594 
595 #endif
CachingVariable(std::string m, std::string n, const edm::ParameterSet &iConfig, edm::ConsumesCollector &iC)
void setNotCompute() const
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
Log< level::Info, true > LogVerbatim
unsigned long CacheIdentifier_t
Definition: Event.h:117
std::string separator_
std::string method_
CachingVariable::evalType eval(const edm::Event &iEvent) const override
unsigned int maxSlots() const override
const Description & description() const
~ExpressionVariable() override
const std::string shortLabel(unsigned int i) const
CachingVariable::evalType eval(const edm::Event &iEvent) const override
std::string holderName_
CachingVariable::evalType eval(const edm::Event &iEvent) const override
ComputedVariable(const CachingVariableFactoryArg &arg, edm::ConsumesCollector &iC)
edm::InputTag srcTag_
getObject objects(const edm::Event &iEvent) const
edm::EDGetTokenT< std::vector< LHS > > srcLhs_
vars
Definition: DeepTauIdBase.h:60
evalType eval(const edm::Event &iEvent) const override
selection
main part
Definition: corrVsCorr.py:100
VarSplitter(const CachingVariableFactoryArg &arg, edm::ConsumesCollector &iC)
StringCutObjectSelector< Object > * selector_
virtual evalType eval(const edm::Event &iEvent) const
VariableComputer(const CachingVariable::CachingVariableFactoryArg &arg, edm::ConsumesCollector &iC)
void insert(bool ok_to_replace, char const *, Entry const &)
std::vector< std::string > short_labels_
~ComputedVariable() override
CachingVariable::evalType eval(const edm::Event &iEvent) const override=0
unsigned int maxIndex() const
Log< level::Error, false > LogError
CachingVariable::evalType eval(const edm::Event &iEvent) const override
const std::string & holderName() const
A arg
Definition: Factorize.h:31
edm::Event::CacheIdentifier_t eventCacheID_
std::string text() const
void assign(std::string var, double &value) const
const CachingVariable::CachingVariableFactoryArg & arg_
VariablePower(const CachingVariableFactoryArg &arg, edm::ConsumesCollector &iC)
std::vector< double > slots_
bool notSeenThisEventAlready(const edm::Event &iEvent) const
virtual ~VariableComputer()
bool failedToGet() const
Definition: HandleBase.h:72
char const * label
int iEvent
Definition: GenABIO.cc:224
TwoObjectVariable(const CachingVariableFactoryArg &arg, edm::ConsumesCollector &iC)
const std::string & label(unsigned int i) const
void setHolder(std::string hn) const
edm::InputTag srcLhsTag_
std::map< std::string, const ComputedVariable * > iCompute_
void print() const
const std::string & name() const
~VariablePower() override
StringObjectFunction< Object > * f_
unsigned int indexLhs_
void compute(const edm::Event &iEvent) const override
virtual ~CachingVariable()
void addDescriptionLine(const std::string &s)
Description(std::vector< std::string > &d)
edm::EDGetTokenT< TYPE > src_
const std::string & method() const
VariableComputerTest(const CachingVariable::CachingVariableFactoryArg &arg, edm::ConsumesCollector &iC)
edm::InputTag srcRhsTag_
Definition: value.py:1
valueType operator()(const edm::Event &iEvent) const
d
Definition: ztail.py:151
void doesNotCompute() const
edm::EDGetTokenT< edm::View< Object > > src_
edm::Event::CacheIdentifier_t eventCacheID_
SimpleValueVariable(const CachingVariableFactoryArg &arg, edm::ConsumesCollector &iC)
CachingVariable::evalType eval(const edm::Event &iEvent) const override
SimpleValueVectorVariable(const CachingVariableFactoryArg &arg, edm::ConsumesCollector &iC)
StringObjectFunction< Object > * forder_
virtual CachingVariable::valueType calculate(getObject &o) const
#define N
Definition: blowfish.cc:9
std::vector< std::string > d_
std::unique_ptr< const VariableComputer > myComputer
Splitter(std::string method, std::string n, const edm::ParameterSet &iConfig, edm::ConsumesCollector &iC)
edm::ParameterSet conf_
std::pair< OmniClusterRef, TrackingParticleRef > P
unsigned int indexRhs_
std::vector< std::string > labels_
edm::EDGetTokenT< TYPE > src_
void setCache(valueType &v) const
const std::vector< std::string > lines()
std::string name_
ExpressionVariable(const CachingVariableFactoryArg &arg, edm::ConsumesCollector &iC)
void addLine(const std::string &l)
HLT enums.
virtual void compute(const edm::Event &iEvent) const =0
std::string var_
bool notSeenThisEventAlready(const edm::Event &iEvent) const
std::string dump(unsigned int indent=0) const
CachingVariable::evalType eval(const edm::Event &iEvent) const override
std::string method_
bool compute(const edm::Event &iEvent) const
const std::string & name() const
~VariableComputerTest() override
virtual unsigned int maxSlots() const
void declare(std::string var, edm::ConsumesCollector &iC)
CachingVariableFactoryArg(std::string &N, CachingVariable::vMap &M, edm::ParameterSet &P)
std::string var_
CachingVariableFactoryArg(const CachingVariableFactoryArg &copy)
edm::EDGetTokenT< std::vector< RHS > > srcRhs_
evalType & baseEval(const edm::Event &iEvent) const
ComputedVariable(const std::string &M, std::string &N, edm::ParameterSet &P, const VariableComputer *c, edm::ConsumesCollector &iC)
std::map< std::string, const CachingVariable * > vMap
std::pair< bool, valueType > evalType
#define LogDebug(id)