CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
StringBasedNTupler.h
Go to the documentation of this file.
1 #ifndef StringBasedNTupler_NTupler_H
2 #define StringBasedNTupler_NTupler_H
3 
4 //#include "PhysicsTools/UtilAlgos/interface/UpdaterService.h"
5 
11 
12 //#include "PhysicsTools/UtilAlgos/interface/TFileService.h"
14 #include "TTree.h"
15 #include "TBranch.h"
16 #include "TFile.h"
17 
19 
26 
29 
32 
33 //#define StringBasedNTuplerPrecision float;
34 
35 #include <memory>
36 #include <string>
37 #include <sstream>
38 
44 
45 // LHE Event
47 
48 
49 class TreeBranch {
50  public:
53  class_(C),src_(S),expr_(E),order_(O), selection_(SE),maxIndexName_(Mi),branchAlias_(Ba){
54  branchTitle_= E+" calculated on "+C+" object from "+S.encode();
55  if (O!="") branchTitle_+=" ordered according to "+O;
56  if (SE!="") branchTitle_+=" selecting on "+SE;
57  edm::LogInfo("TreeBranch")<<"the branch with alias: "<<branchAlias_<<" corresponds to: "<<branchTitle_;
58  }
59 
60  const std::string & className() const { return class_;}
61  const edm::InputTag & src() const { return src_;}
62  const std::string & expr() const { return expr_;}
63  const std::string & order() const { return order_;}
64  const std::string & selection() const { return selection_;}
65  const std::string & maxIndexName() const { return maxIndexName_;}
66  const std::string branchName()const{
68  std::replace(name.begin(), name.end(), '_','0');
69  return std::string(name.c_str());}
70  const std::string & branchAlias()const{ return branchAlias_;}
71  const std::string & branchTitle()const{ return branchTitle_;}
72  typedef std::auto_ptr<std::vector<float> > value;
73  value branch(const edm::Event& iEvent);
74 
75  std::vector<float>** dataHolderPtrAdress() { return &dataHolderPtr_;}
76  std::vector<float>* dataHolderPtr() { return dataHolderPtr_;}
77  void assignDataHolderPtr(std::vector<float> * data) { dataHolderPtr_=data;}
78  private:
87 
88  std::vector<float> * dataHolderPtr_;
89 };
90 
91 
92 template <typename Object>
94  public:
96  value operator()() { return value_;}
97 
99  {
100  const float defaultValue = 0.;
101  // grab the object
103  iEvent.getByLabel(B.src(), oH);
104  //empty vector if product not found
105  if (oH.failedToGet()){
106  edm::LogError("StringBranchHelper")<<"cannot open: "<<B.src();
107  value_.reset(new std::vector<float>(0));
108  }
109  else{
110  //parser for the object expression
112  //allocate enough memory for the data holder
113  value_.reset(new std::vector<float>(1));
114  try{
115  (*value_)[0]=(expr)(*oH);
116  }catch(...){
117  LogDebug("StringLeaveHelper")<<"could not evaluate expression: "<<B.expr()<<" on class: "<<B.className();
118  (*value_)[0]=defaultValue;
119  }
120  }
121  }
122  private:
124 };
125 
126 template <typename Object, typename Collection=std::vector<Object> >
128 public:
130  value operator()() { return value_;}
131 
133  {
134  const float defaultValue = 0.;
135 
136  // grab the collection
138  iEvent.getByLabel(B.src(), oH);
139 
140 
141  //empty vector if product not found
142  if (oH.failedToGet()){
143  if(!(iEvent.isRealData() && B.className()=="reco::GenParticle") ) { //don't output genparticle error in data
144  edm::LogError("StringBranchHelper")<<"cannot open: "<<B.src()<<" "<<B.className();
145  }
146  value_.reset(new std::vector<float>());
147  }
148  else{
149  //parser for the object expression
151  //allocate enough memory for the data holder
152  value_.reset(new std::vector<float>());
153  value_->reserve(oH->size());
154 
156  if (B.selection()!=""){
157  //std::cout<<"trying to get to a selection"<<std::endl;
158  selection = new StringCutObjectSelector<Object>(B.selection());
159  //std::cout<<"got the objet"<<std::endl;
160  }
161  uint i_end=oH->size();
162  //sort things first if requested
163  if (B.order()!=""){
165  // allocate a vector of pointers (we are using view) to be sorted
166  std::vector<const Object*> copyToSort(oH->size());
167  for (uint i=0;i!=i_end;++i) copyToSort[i]= &(*oH)[i];
168  std::sort(copyToSort.begin(), copyToSort.end(), sortByStringFunction<Object>(&order));
169  //then loop and fill
170  for (uint i=0;i!=i_end;++i) {
171  //try and catch is necessary because ...
172  try{
173  if (selection && !((*selection)(*(copyToSort)[i]))) continue;
174  value_->push_back((expr)(*(copyToSort)[i]));
175  }catch(...){
176  LogDebug("StringBranchHelper")<<"with sorting. could not evaluate expression: "<<B.expr()<<" on class: "<<B.className();
177  value_->push_back(defaultValue);//push a default value to not change the indexing
178  }
179  }
180  }
181  else{
182  //actually fill the vector of values
183  for (uint i=0;i!=i_end;++i){
184  //try and catch is necessary because ...
185  try {
186  if (selection && !((*selection)((*oH)[i]))) continue;
187  value_->push_back((expr)((*oH)[i]));
188  }catch(...){
189  LogDebug("StringBranchHelper")<<"could not evaluate expression: "<<B.expr()<<" on class: "<<B.className();
190  value_->push_back(defaultValue);//push a default value to not change the indexing
191  }
192  }
193  }
194  if (selection) delete selection;
195  }
196  }
197  private:
199 };
200 
201 
202 
203 class StringBasedNTupler : public NTupler {
204 
205 
206  public:
208 
209 
210 
211  edm::ParameterSet branchesPSet = iConfig.getParameter<edm::ParameterSet>("branchesPSet");
212  std::vector<std::string> branches;
213  branchesPSet.getParameterSetNames(branches);
214  const std::string separator = branchesPSet.getUntrackedParameter<std::string>("separator",":");
215  for (uint b=0;b!=branches.size();++b){
216  edm::ParameterSet bPSet = branchesPSet.getParameter<edm::ParameterSet>(branches[b]);
218  if (bPSet.exists("class"))
219  className=bPSet.getParameter<std::string>("class");
220  else
221  className=bPSet.getParameter<std::string>("Class");
223  edm::ParameterSet leavesPSet=bPSet.getParameter<edm::ParameterSet>("leaves");
224  std::string order = "";
225  if (bPSet.exists("order")) order = bPSet.getParameter<std::string>("order");
226  std::string selection = "";
227  if (bPSet.exists("selection")) selection = bPSet.getParameter<std::string>("selection");
228  // do it one by one with configuration [string x = "x"]
229  std::vector<std::string> leaves=leavesPSet.getParameterNamesForType<std::string>();
230  std::string maxName="N"+branches[b];
231  for (uint l=0;l!=leaves.size();++l){
232  std::string leave_expr=leavesPSet.getParameter<std::string>(leaves[l]);
233  std::string branchAlias=branches[b]+"_"+leaves[l];
234 
235  //add a branch manager for this expression on this collection
236  branches_[maxName].push_back(TreeBranch(className, src, leave_expr, order, selection, maxName, branchAlias));
237  }//loop the provided leaves
238 
239  //do it once with configuration [vstring vars = { "x:x" ,... } ] where ":"=separator
240  if (leavesPSet.exists("vars")){
241  std::vector<std::string> leavesS = leavesPSet.getParameter<std::vector<std::string> >("vars");
242  for (uint l=0;l!=leavesS.size();++l){
243  uint sep=leavesS[l].find(separator);
244  std::string name=leavesS[l].substr(0,sep);
245  //removes spaces from the variable name
246  /*uint*/int space = name.find(" ");
247  while (space!=-1/*std::string::npos*/){
248  std::string first = name.substr(0,space);
249  std::string second = name.substr(space+1);
250  name = first+second;
251  space = name.find(" ");
252  }
253  std::string expr=leavesS[l].substr(sep+1);
254  std::string branchAlias=branches[b]+"_"+name;
255 
256  //add a branch manager for this expression on this collection
257  branches_[maxName].push_back(TreeBranch(className, src, expr, order, selection, maxName, branchAlias));
258  }
259  }
260 
261  }//loop the provided branches
262 
263 
264 
265 
266  ev_ = new uint;
267  run_ = new uint;
268  lumiblock_ = new uint;
269  experimentType_ = new uint;
270  bunchCrossing_ = new uint;
271  orbitNumber_ = new uint;
272  weight_ = new float;
274 
275 
276  if (branchesPSet.exists("useTFileService"))
277  useTFileService_=branchesPSet.getParameter<bool>("useTFileService");
278  else
279  useTFileService_=iConfig.getParameter<bool>("useTFileService");
280 
281  if (useTFileService_){
282  if (branchesPSet.exists("treeName")){
283  treeName_=branchesPSet.getParameter<std::string>("treeName");
284  ownTheTree_=true;
285  }
286  else{
287  treeName_=iConfig.getParameter<std::string>("treeName");
288  ownTheTree_=false;
289  }
290  }
291  }
292 
293 
294 
296  uint nLeaves=0;
297 
298  if (useTFileService_){
300  if (ownTheTree_){
301  ownTheTree_=true;
302  tree_=fs->make<TTree>(treeName_.c_str(),"StringBasedNTupler tree");
303  }else{
304  TObject * object = fs->file().Get(treeName_.c_str());
305  if (!object){
306  ownTheTree_=true;
307  tree_=fs->make<TTree>(treeName_.c_str(),"StringBasedNTupler tree");
308  }
309  else{
310  tree_=dynamic_cast<TTree*>(object);
311  if (!tree_){
312  ownTheTree_=true;
313  tree_=fs->make<TTree>(treeName_.c_str(),"StringBasedNTupler tree");
314  }
315  else ownTheTree_=false;
316  }
317  }
318 
319  //reserve memory for the indexes
320  indexDataHolder_ = new uint[branches_.size()];
321  // loop the automated leafer
322  Branches::iterator iB=branches_.begin();
323  Branches::iterator iB_end=branches_.end();
324  uint indexOfIndexInDataHolder=0;
325  for(;iB!=iB_end;++iB,++indexOfIndexInDataHolder){
326  //create a branch for the index: an integer
327  tree_->Branch(iB->first.c_str(), &(indexDataHolder_[indexOfIndexInDataHolder]),(iB->first+"/i").c_str());
328  //loop on the "leaves"
329  std::vector<TreeBranch>::iterator iL=iB->second.begin();
330  std::vector<TreeBranch>::iterator iL_end=iB->second.end();
331  for(;iL!=iL_end;++iL){
332  TreeBranch & b=*iL;
333  //create a branch for the leaves: vector of floats
334  TBranch * br = tree_->Branch(b.branchAlias().c_str(),"std::vector<float>",iL->dataHolderPtrAdress());
335  br->SetTitle(b.branchTitle().c_str());
336  nLeaves++;
337  }
338  }
339 
340  //extra leaves for event info.
341  tree_->Branch("run",run_,"run/i");
342  tree_->Branch("event",ev_,"event/i");
343  tree_->Branch("lumiblock",lumiblock_,"lumiblock/i");
344  tree_->Branch("experimentType",experimentType_,"experimentType/i");
345  tree_->Branch("bunchCrossing",bunchCrossing_,"bunchCrossing/i");
346  tree_->Branch("orbitNumber",orbitNumber_,"orbitNumber/i");
347  tree_->Branch("weight",weight_,"weight/f");
348  tree_->Branch("model_params",&model_params_);
349 
350  }
351  else{
352  // loop the automated leafer
353  Branches::iterator iB=branches_.begin();
354  Branches::iterator iB_end=branches_.end();
355  for(;iB!=iB_end;++iB){
356  //the index. should produce it only once
357  // a simple uint for the index
358  producer->produces<uint>(iB->first).setBranchAlias(iB->first);
359  std::vector<TreeBranch>::iterator iL=iB->second.begin();
360  std::vector<TreeBranch>::iterator iL_end=iB->second.end();
361  for(;iL!=iL_end;++iL){
362  TreeBranch & b=*iL;
363  //a vector of float for each leave
364  producer->produces<std::vector<float> >(b.branchName()).setBranchAlias(b.branchAlias());
365  nLeaves++;
366  }
367  }
368  }
369  return nLeaves;
370  }
371 
373  // if (!edm::Service<UpdaterService>()->checkOnce("StringBasedNTupler::fill")) return;
374  //well if you do that, you cannot have two ntupler of the same type in the same job...
375 
376  if (useTFileService_){
377  // loop the automated leafer
378  Branches::iterator iB=branches_.begin();
379  Branches::iterator iB_end=branches_.end();
380  uint indexOfIndexInDataHolder=0;
381  for(;iB!=iB_end;++iB,++indexOfIndexInDataHolder){
382  std::vector<TreeBranch>::iterator iL=iB->second.begin();
383  std::vector<TreeBranch>::iterator iL_end=iB->second.end();
384  uint maxS=0;
385  for(;iL!=iL_end;++iL){
386  TreeBranch & b=*iL;
387  // grab the vector of values from the interpretation of expression for the associated collection
388  std::auto_ptr<std::vector<float> > branch(b.branch(iEvent));
389  // calculate the maximum index size.
390  if (branch->size()>maxS) maxS=branch->size();
391  // transfer of (no copy) pointer to the vector of float from the auto_ptr to the tree data pointer
392  b.assignDataHolderPtr(branch.release());
393  // for memory tracing, object b is holding the data (not auto_ptr) and should delete it for each event (that's not completely optimum)
394  }
395  //assigne the maximum vector size for this collection
396  indexDataHolder_[indexOfIndexInDataHolder]=maxS;
397  }
398 
399  //fill event info.
400  *run_ = iEvent.id().run();
401  *ev_ = iEvent.id().event();
402  // *lumiblock_ = iEvent.id().luminosityBlock();
403  *lumiblock_ = iEvent.luminosityBlock();
404  *experimentType_ = iEvent.experimentType();
405  *bunchCrossing_ = iEvent.bunchCrossing();
406  *orbitNumber_ = iEvent.orbitNumber();
407 
408  *weight_ = 1;
409  if(!iEvent.isRealData()) {
410  edm::Handle<GenEventInfoProduct> wgeneventinfo;
411  iEvent.getByLabel("generator", wgeneventinfo);
412  *weight_ = wgeneventinfo->weight();
413  }
414 
415  typedef std::vector<std::string>::const_iterator comments_const_iterator;
416 // using namespace edm;
417 
419  *model_params_ = "NULL";
420  if(iEvent.getByLabel("source", product)) {
421  comments_const_iterator c_begin = product->comments_begin();
422  comments_const_iterator c_end = product->comments_end();
423 
424  for( comments_const_iterator cit=c_begin; cit!=c_end; ++cit) {
425  size_t found = (*cit).find("model");
426  if( found != std::string::npos) {
427  //std::cout << *cit << std::endl;
428  *model_params_ = *cit;
429  }
430  }
431  }
432 
433 
434  if (ownTheTree_){ tree_->Fill(); }
435  }else{
436  // loop the automated leafer
437  Branches::iterator iB=branches_.begin();
438  Branches::iterator iB_end=branches_.end();
439  for(;iB!=iB_end;++iB){
440  std::vector<TreeBranch>::iterator iL=iB->second.begin();
441  std::vector<TreeBranch>::iterator iL_end=iB->second.end();
442  uint maxS=0;
443  for(;iL!=iL_end;++iL){
444  TreeBranch & b=*iL;
445  std::auto_ptr<std::vector<float> > branch(b.branch(iEvent));
446  if (branch->size()>maxS) maxS=branch->size();
447  iEvent.put(branch, b.branchName());
448  }
449  //index should be put only once per branch. doe not really mattter for edm root files
450  std::auto_ptr<uint> maxN(new uint(maxS));
451  iEvent.put(maxN, iB->first);
452  }
453  }
454  }
455 
456  void callBack()
457  {
458  if (useTFileService_){
459  Branches::iterator iB=branches_.begin();
460  Branches::iterator iB_end=branches_.end();
461  //de-allocate memory now: allocated in branch(...) and released to the pointer.
462  for(;iB!=iB_end;++iB){
463  std::vector<TreeBranch>::iterator iL=iB->second.begin();
464  std::vector<TreeBranch>::iterator iL_end=iB->second.end();
465  for(;iL!=iL_end;++iL){
466  TreeBranch & b=*iL;
467  delete b.dataHolderPtr();
468  }
469  }
470  }
471  }
472 
474  delete indexDataHolder_;
475  delete ev_;
476  delete run_;
477  delete lumiblock_;
478  delete experimentType_;
479  delete bunchCrossing_;
480  delete orbitNumber_;
481  delete weight_;
482  delete model_params_;
483  }
484 
485  protected:
486  typedef std::map<std::string, std::vector<TreeBranch> > Branches;
488 
492 
493  //event info
494  uint * ev_;
495  uint * run_;
496  uint * lumiblock_;
499  uint * orbitNumber_;
500  float * weight_;
502 
503 };
504 
505 
506 #endif
const std::string & branchTitle() const
#define LogDebug(id)
RunNumber_t run() const
Definition: EventID.h:39
T getParameter(std::string const &) const
EventNumber_t event() const
Definition: EventID.h:41
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
TTree * tree_
Definition: NTupler.h:30
const std::string & branchAlias() const
std::vector< float > * dataHolderPtr()
const std::string branchName() const
std::auto_ptr< std::vector< float > > value
value branch(const edm::Event &iEvent)
std::string order_
selection
main part
Definition: corrVsCorr.py:98
bool exists(std::string const &parameterName) const
checks if a parameter exists
int bunchCrossing() const
Definition: EventBase.h:62
edm::LuminosityBlockNumber_t luminosityBlock() const
Definition: EventBase.h:59
T * make(const Args &...args) const
make new ROOT object
Definition: TFileService.h:64
std::string branchTitle_
std::string maxIndexName_
TreeBranch::value value
StringLeaveHelper(const TreeBranch &B, const edm::Event &iEvent)
const std::string & selection() const
bool isRealData() const
Definition: EventBase.h:60
std::string encode() const
Definition: InputTag.cc:164
std::vector< float > * dataHolderPtr_
const std::string & order() const
std::vector< std::string > getParameterNamesForType(bool trackiness=true) const
Definition: ParameterSet.h:192
std::string * model_params_
U second(std::pair< T, U > const &p)
uint registerleaves(edm::ProducerBase *producer)
int iEvent
Definition: GenABIO.cc:230
const edm::InputTag & src() const
OrphanHandle< PROD > put(std::auto_ptr< PROD > product)
Put a new product.
Definition: Event.h:113
TypeLabelItem const & produces()
declare what type of product will make and with which optional label
std::map< std::string, std::vector< TreeBranch > > Branches
TreeBranch(std::string C, edm::InputTag S, std::string E, std::string O, std::string SE, std::string Mi, std::string Ba)
void fill(edm::Event &iEvent)
std::string branchAlias_
int orbitNumber() const
Definition: EventBase.h:63
bool first
Definition: L1TdeRCT.cc:75
std::string expr_
bool getByLabel(InputTag const &tag, Handle< PROD > &result) const
Definition: Event.h:402
TreeBranch::value value
edm::InputTag src_
void assignDataHolderPtr(std::vector< float > *data)
bool failedToGet() const
Definition: HandleBase.h:80
TFile & file() const
return opened TFile
Definition: TFileService.h:37
double b
Definition: hdecay.h:120
list object
Definition: dbtoconf.py:77
std::string selection_
const std::string & className() const
edm::EventID id() const
Definition: EventBase.h:56
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
edm::EventAuxiliary::ExperimentType experimentType() const
Definition: EventBase.h:61
const std::string & maxIndexName() const
std::string class_
bool useTFileService_
Definition: NTupler.h:29
size_t getParameterSetNames(std::vector< std::string > &output, bool trackiness=true) const
const std::string & expr() const
StringBranchHelper(const TreeBranch &B, const edm::Event &iEvent)
std::string className(const T &t)
Definition: ClassName.h:30
StringBasedNTupler(const edm::ParameterSet &iConfig)
std::vector< float > ** dataHolderPtrAdress()