CMS 3D CMS Logo

DataGetterHelper.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: DataFormats/FWLite
4 // Class : DataGetterHelper
5 //
6 // Implementation:
7 // [Notes on implementation]
8 //
9 // Original Author: Eric Vaandering
10 // Created: Fri Jan 29 11:58:01 CST 2010
11 //
12 
13 // system include files
14 #include <cassert>
15 #include <iostream>
16 
17 // user include files
19 #include "TFile.h"
20 #include "TTree.h"
21 #include "TTreeCache.h"
22 
27 
29 
36 
37 namespace fwlite {
38  //
39  // constants, enums and typedefs
40  //
41 
42  //
43  // static data member definitions
44  //
45  // empty object used to signal that the branch requested was not found
47  static char kEmptyString[1] = {0};
48 
49  //
50  // constructors and destructor
51  //
53  std::shared_ptr<HistoryGetterBase> historyGetter,
54  std::shared_ptr<BranchMapReader> branchMap,
55  std::shared_ptr<edm::EDProductGetter> getter,
56  bool useCache, std::function<void (TBranch const&)> baFunc):
57  branchMap_(branchMap),
58  historyGetter_(historyGetter),
59  getter_(getter),
60  tcTrained_(false),
61  tcUse_(useCache),
62  branchAccessFunc_(baFunc)
63  {
64  if(nullptr == tree) {
65  throw cms::Exception("NoTree")<<"The TTree pointer passed to the constructor was null";
66  }
67  tree_ = tree;
68  if (tcUse_) {
69  tree_->SetCacheSize();
70  }
71  }
72 
73  // DataGetterHelper::DataGetterHelper(const DataGetterHelper& rhs)
74  // {
75  // // do actual copying here;
76  // }
77 
79 
80  //
81  // assignment operators
82  //
83  // const DataGetterHelper& DataGetterHelper::operator=(const DataGetterHelper& rhs)
84  // {
85  // //An exception safe implementation is
86  // DataGetterHelper temp(rhs);
87  // swap(rhs);
88  //
89  // return *this;
90  // }
91 
92  //
93  // member functions
94  //
95 
96 
97 
98  //
99  // const member functions
100  //
101 
102  //
103  // static member functions
104  //
105 
106 
107  static
108  TBranch* findBranch(TTree* iTree, std::string const& iMainLabels, std::string const& iProcess) {
109  std::string branchName(iMainLabels);
110  branchName+=iProcess;
111  //branchName+=".obj";
112  branchName+=".";
113  return iTree->GetBranch(branchName.c_str());
114  }
115 
116  void
118  Long64_t eventEntry,
119  internal::Data& iData) const
120  {
121  GetterOperate op(iGetter);
122 
126  //edm::ObjectWithDict obj = iData.obj_;
127  //iData.obj_ = iData.obj_.construct();
128  //iData.pObj_ = iData.obj_.address();
129  //iData.branch_->SetAddress(&(iData.pObj_));
131  //if(nullptr != iData.pProd_) {
132  // iData.pProd_ = iData.obj_.address();
133  //}
134  //obj.destruct();
136 
137  if (tcUse_) {
138  TTreeCache* tcache = dynamic_cast<TTreeCache*> (branchMap_->getFile()->GetCacheRead());
139 
140  if (nullptr != tcache) {
141  if (!tcTrained_) {
142  tcache->SetLearnEntries(100);
143  tcache->SetEntryRange(0, tree_->GetEntries());
144  tcTrained_ = true;
145  }
146  tree_->LoadTree(eventEntry);
147  }
148  }
149  branchAccessFunc_(*iData.branch_);
150  iData.branch_->GetEntry(eventEntry);
151 
152  iData.lastProduct_=eventEntry;
153  }
154 
156  DataGetterHelper::getBranchDataFor(std::type_info const& iInfo,
157  char const* iModuleLabel,
158  char const* iProductInstanceLabel,
159  char const* iProcessLabel) const
160  {
161  edm::TypeID type(iInfo);
162  internal::DataKey key(type, iModuleLabel, iProductInstanceLabel, iProcessLabel);
163 
164  KeyToDataMap::iterator itFind = data_.find(key);
165  if(itFind == data_.end()) {
166  //see if such a branch actually exists
167  std::string const sep("_");
168  //CHANGE: If this fails, need to lookup the the friendly name which was used to write the file
170  name +=sep+std::string(key.module());
171  name +=sep+std::string(key.product())+sep;
172 
173  //if we have to lookup the process label, remember it and register the product again
174  std::string foundProcessLabel;
175  TBranch* branch = nullptr;
176  std::shared_ptr<internal::Data> theData;
177 
178  if (nullptr == iProcessLabel || iProcessLabel == key.kEmpty() ||
179  strlen(iProcessLabel)==0) {
180  std::string const* lastLabel = nullptr;
181  //have to search in reverse order since newest are on the bottom
183  for (edm::ProcessHistory::const_reverse_iterator iproc = h.rbegin(), eproc = h.rend();
184  iproc != eproc;
185  ++iproc) {
186 
187  lastLabel = &(iproc->processName());
188  branch=findBranch(tree_,name,iproc->processName());
189  if(nullptr != branch) {
190  break;
191  }
192  }
193  if(nullptr == branch) {
194  return branchNotFound;
195  }
196  //do we already have this one?
197  if(nullptr != lastLabel) {
198  internal::DataKey fullKey(type,iModuleLabel,iProductInstanceLabel,lastLabel->c_str());
199  itFind = data_.find(fullKey);
200  if(itFind != data_.end()) {
201  //remember the data we've found
202  theData = itFind->second;
203  } else {
204  //only set this if we don't already have it since it this string is not empty we re-register
205  foundProcessLabel = *lastLabel;
206  }
207  }
208  } else {
209  //we have all the pieces
210  branch = findBranch(tree_,name,key.process());
211  if(nullptr == branch){
212  return branchNotFound;
213  }
214  }
215 
216  //cache the info
217  size_t moduleLabelLen = strlen(iModuleLabel)+1;
218  char* newModule = new char[moduleLabelLen];
219  std::strncpy(newModule,iModuleLabel,moduleLabelLen);
220  labels_.push_back(newModule);
221 
222  char* newProduct = kEmptyString;
223  if(key.product()[0] != 0) {
224  size_t newProductLen = strlen(key.product())+1;
225  newProduct = new char[newProductLen];
226  std::strncpy(newProduct,key.product(),newProductLen);
227  labels_.push_back(newProduct);
228  }
229  char* newProcess = kEmptyString;
230  if(key.process()[0]!=0) {
231  size_t newProcessLen = strlen(key.process())+1;
232  newProcess = new char[newProcessLen];
233  std::strncpy(newProcess,key.process(),newProcessLen);
234  labels_.push_back(newProcess);
235  }
236  internal::DataKey newKey(edm::TypeID(iInfo),newModule,newProduct,newProcess);
237 
238  if(nullptr == theData.get()) {
239  //We do not already have this data as another key
240 
241  //create an instance of the object to be used as a buffer
242  edm::TypeWithDict type(iInfo);
243  if(!bool(type)) {
244  throw cms::Exception("UnknownType") << "No dictionary exists for type " << iInfo.name();
245  }
246 
248 
249  if(obj.address() == nullptr) {
250  throw cms::Exception("ConstructionFailed") << "failed to construct an instance of " << type.name();
251  }
252  auto newData = std::make_shared<internal::Data>();
253  newData->branch_ = branch;
254  newData->obj_ = obj;
255  newData->lastProduct_ = -1;
256  newData->pObj_ = obj.address();
257  newData->pProd_ = nullptr;
258  branch->SetAddress(&(newData->pObj_));
259  theData = newData;
260  }
261  itFind = data_.insert(std::make_pair(newKey, theData)).first;
262 
263  if(!foundProcessLabel.empty()) {
264  //also remember it with the process label
265  newProcess = new char[foundProcessLabel.size()+1];
266  std::strcpy(newProcess,foundProcessLabel.c_str());
267  labels_.push_back(newProcess);
268  internal::DataKey newKey(edm::TypeID(iInfo),newModule,newProduct,newProcess);
269 
270  data_.insert(std::make_pair(newKey,theData));
271  }
272  }
273  return *(itFind->second);
274  }
275 
276  std::string const
277  DataGetterHelper::getBranchNameFor(std::type_info const& iInfo,
278  char const* iModuleLabel,
279  char const* iProductInstanceLabel,
280  char const* iProcessLabel) const
281  {
282  internal::Data& theData =
283  DataGetterHelper::getBranchDataFor(iInfo, iModuleLabel, iProductInstanceLabel, iProcessLabel);
284 
285  if (nullptr != theData.branch_) {
286  return std::string(theData.branch_->GetName());
287  }
288  return std::string("");
289  }
290 
291  bool
292  DataGetterHelper::getByLabel(std::type_info const& iInfo,
293  char const* iModuleLabel,
294  char const* iProductInstanceLabel,
295  char const* iProcessLabel,
296  void* oData, Long_t eventEntry) const
297  {
298  // Maintain atEnd() check in parent classes
299  void** pOData = reinterpret_cast<void**>(oData);
300  *pOData = nullptr;
301 
302  internal::Data& theData =
303  DataGetterHelper::getBranchDataFor(iInfo, iModuleLabel, iProductInstanceLabel, iProcessLabel);
304 
305  if (nullptr != theData.branch_) {
306  if(eventEntry != theData.lastProduct_) {
307  //haven't gotten the data for this event
308  getBranchData(getter_.get(), eventEntry, theData);
309  }
310  *pOData = theData.obj_.address();
311  }
312 
313  if (nullptr == *pOData) return false;
314  else return true;
315  }
316 
317  bool
319  Long_t eventEntry,
320  KeyToDataMap::iterator& itData) const {
321  if (!bDesc.branchID().isValid()) {
322  return false;
323  }
324 
325  //Calculate the key from the branch description
327  edm::TypeID type(typeWD.typeInfo());
328  assert(bool(type));
329 
330  //Only the product instance label may be empty
331  char const* pIL = bDesc.productInstanceName().c_str();
332  if(pIL[0] == 0) {
333  pIL = nullptr;
334  }
336  bDesc.moduleLabel().c_str(),
337  pIL,
338  bDesc.processName().c_str());
339 
340  //has this already been gotten?
341  itData = data_.find(k);
342  if(data_.end() == itData) {
343  //ask for the data
344  edm::WrapperBase const* dummy = nullptr;
345  getByLabel(type.typeInfo(),
346  k.module(),
347  k.product(),
348  k.process(),
349  &dummy, eventEntry);
350  if(nullptr == dummy) {
351  return false;
352  }
353  itData = data_.find(k);
354  assert(itData != data_.end());
355  assert(dummy == itData->second->obj_.address());
356  }
357  return true;
358  }
359 
360  edm::WrapperBase const*
361  DataGetterHelper::getByProductID(edm::ProductID const& iID, Long_t eventEntry) const
362  {
363  typedef std::pair<edm::ProductID,edm::BranchListIndex> IDPair;
364  IDPair theID = std::make_pair(iID, branchMap_->branchListIndexes()[iID.processIndex()-1]);
365  std::map<IDPair,std::shared_ptr<internal::Data> >::const_iterator itFound = idToData_.find(theID);
366 
367  if(itFound == idToData_.end()) {
368  edm::BranchDescription const& bDesc = branchMap_->productToBranch(iID);
369  KeyToDataMap::iterator itData;
370 
371  if(!getByBranchDescription(bDesc, eventEntry, itData)) {
372  return nullptr;
373  }
374  itFound = idToData_.insert(std::make_pair(theID,itData->second)).first;
375  }
376  if(eventEntry != itFound->second->lastProduct_) {
377  //haven't gotten the data for this event
378  getBranchData(getter_.get(), eventEntry, *(itFound->second));
379  }
380  if(nullptr == itFound->second->pProd_) {
381  itFound->second->pProd_ = wrapperBasePtr(itFound->second->obj_);
382  if(nullptr == itFound->second->pProd_) {
383  return nullptr;
384  }
385  }
386  return itFound->second->pProd_;
387  }
388 
389  edm::WrapperBase const*
390  DataGetterHelper::getByBranchID(edm::BranchID const& bid, Long_t eventEntry) const
391  {
392  auto itFound = bidToData_.find(bid);
393 
394  if(itFound == bidToData_.end()) {
395  edm::BranchDescription const& bDesc = branchMap_->branchIDToBranch(bid);
396  KeyToDataMap::iterator itData;
397 
398  if(!getByBranchDescription(bDesc, eventEntry, itData)) {
399  return nullptr;
400  }
401  itFound = bidToData_.insert(std::make_pair(bid,itData->second)).first;
402  }
403  if(eventEntry != itFound->second->lastProduct_) {
404  //haven't gotten the data for this event
405  getBranchData(getter_.get(), eventEntry, *(itFound->second));
406  }
407  if(nullptr == itFound->second->pProd_) {
408  itFound->second->pProd_ = wrapperBasePtr(itFound->second->obj_);
409  if(nullptr == itFound->second->pProd_) {
410  return nullptr;
411  }
412  }
413  return itFound->second->pProd_;
414  }
415 
416  edm::WrapperBase const*
418  // This converts a void* that points at a Wrapper<T>* into a WrapperBase*
419  edm::TypeWithDict wrapperBaseTypeWithDict(typeid(edm::WrapperBase));
420  return static_cast<edm::WrapperBase const*>(wrapperBaseTypeWithDict.pointerToBaseType(objectWithDict.address(),
421  objectWithDict.typeOf()));
422  }
423 
424  edm::WrapperBase const*
425  DataGetterHelper::getThinnedProduct(edm::ProductID const& pid, unsigned int& key, Long_t eventEntry) const {
426 
427  edm::BranchID parent = branchMap_->productToBranchID(pid);
428  if(!parent.isValid()) return nullptr;
429  edm::ThinnedAssociationsHelper const& thinnedAssociationsHelper = branchMap_->thinnedAssociationsHelper();
430 
431  // Loop over thinned containers which were made by selecting elements from the parent container
432  for(auto associatedBranches = thinnedAssociationsHelper.parentBegin(parent),
433  iEnd = thinnedAssociationsHelper.parentEnd(parent);
434  associatedBranches != iEnd; ++associatedBranches) {
435 
436  edm::ThinnedAssociation const* thinnedAssociation =
437  getThinnedAssociation(associatedBranches->association(), eventEntry);
438  if(thinnedAssociation == nullptr) continue;
439 
440  if(associatedBranches->parent() != branchMap_->productToBranchID(thinnedAssociation->parentCollectionID())) {
441  continue;
442  }
443 
444  unsigned int thinnedIndex = 0;
445  // Does this thinned container have the element referenced by key?
446  // If yes, thinnedIndex is set to point to it in the thinned container
447  if(!thinnedAssociation->hasParentIndex(key, thinnedIndex)) {
448  continue;
449  }
450  // Get the thinned container and return a pointer if we can find it
451  edm::ProductID const& thinnedCollectionPID = thinnedAssociation->thinnedCollectionID();
452  edm::WrapperBase const* thinnedCollection = getByProductID(thinnedCollectionPID, eventEntry);
453 
454  if(thinnedCollection == nullptr) {
455  // Thinned container is not found, try looking recursively in thinned containers
456  // which were made by selecting elements from this thinned container.
457  edm::WrapperBase const* thinnedFromRecursiveCall = getThinnedProduct(thinnedCollectionPID, thinnedIndex, eventEntry);
458  if(thinnedFromRecursiveCall != nullptr) {
459  key = thinnedIndex;
460  return thinnedFromRecursiveCall;
461  } else {
462  continue;
463  }
464  }
465  key = thinnedIndex;
466  return thinnedCollection;
467  }
468  return nullptr;
469  }
470 
472  std::vector<edm::WrapperBase const*>& foundContainers,
473  std::vector<unsigned int>& keys,
474  Long_t eventEntry) const {
475 
476  edm::BranchID parent = branchMap_->productToBranchID(pid);
477  if(!parent.isValid()) return;
478  edm::ThinnedAssociationsHelper const& thinnedAssociationsHelper = branchMap_->thinnedAssociationsHelper();
479 
480  // Loop over thinned containers which were made by selecting elements from the parent container
481  for(auto associatedBranches = thinnedAssociationsHelper.parentBegin(parent),
482  iEnd = thinnedAssociationsHelper.parentEnd(parent);
483  associatedBranches != iEnd; ++associatedBranches) {
484 
485  edm::ThinnedAssociation const* thinnedAssociation =
486  getThinnedAssociation(associatedBranches->association(), eventEntry);
487  if(thinnedAssociation == nullptr) continue;
488 
489  if(associatedBranches->parent() != branchMap_->productToBranchID(thinnedAssociation->parentCollectionID())) {
490  continue;
491  }
492 
493  unsigned int nKeys = keys.size();
494  unsigned int doNotLookForThisIndex = std::numeric_limits<unsigned int>::max();
495  std::vector<unsigned int> thinnedIndexes(nKeys, doNotLookForThisIndex);
496  bool hasAny = false;
497  for(unsigned k = 0; k < nKeys; ++k) {
498  // Already found this one
499  if(foundContainers[k] != nullptr) continue;
500  // Already know this one is not in this thinned container
501  if(keys[k] == doNotLookForThisIndex ) continue;
502  // Does the thinned container hold the entry of interest?
503  // Modifies thinnedIndexes[k] only if it returns true and
504  // sets it to the index in the thinned collection.
505  if(thinnedAssociation->hasParentIndex(keys[k], thinnedIndexes[k])) {
506  hasAny = true;
507  }
508  }
509  if(!hasAny) {
510  continue;
511  }
512  // Get the thinned container and set the pointers and indexes into
513  // it (if we can find it)
514  edm::ProductID thinnedCollectionPID = thinnedAssociation->thinnedCollectionID();
515  edm::WrapperBase const* thinnedCollection = getByProductID(thinnedCollectionPID, eventEntry);
516 
517  if(thinnedCollection == nullptr) {
518  // Thinned container is not found, try looking recursively in thinned containers
519  // which were made by selecting elements from this thinned container.
520  getThinnedProducts(thinnedCollectionPID, foundContainers, thinnedIndexes, eventEntry);
521  for(unsigned k = 0; k < nKeys; ++k) {
522  if(foundContainers[k] == nullptr) continue;
523  if(thinnedIndexes[k] == doNotLookForThisIndex) continue;
524  keys[k] = thinnedIndexes[k];
525  }
526  } else {
527  for(unsigned k = 0; k < nKeys; ++k) {
528  if(thinnedIndexes[k] == doNotLookForThisIndex) continue;
529  keys[k] = thinnedIndexes[k];
530  foundContainers[k] = thinnedCollection;
531  }
532  }
533  }
534  }
535 
537  DataGetterHelper::getThinnedAssociation(edm::BranchID const& branchID, Long_t eventEntry) const {
538 
539  edm::WrapperBase const* wrapperBase = getByBranchID(branchID, eventEntry);
540  if(wrapperBase == nullptr) {
542  << "DataGetterHelper::getThinnedAssociation, product ThinnedAssociation not found.\n";
543  }
544  if(!(typeid(edm::ThinnedAssociation) == wrapperBase->dynamicTypeInfo())) {
546  << "DataGetterHelper::getThinnedAssociation, product has wrong type, not a ThinnedAssociation.\n";
547  }
549  static_cast<edm::Wrapper<edm::ThinnedAssociation> const*>(wrapperBase);
550 
551  edm::ThinnedAssociation const* thinnedAssociation = wrapper->product();
552  return thinnedAssociation;
553  }
554 
556  return historyGetter_->history();
557  }
558 
559 
560  //
561  // static member functions
562  //
563 }
const_reverse_iterator rbegin() const
static TBranch * findBranch(TTree *iTree, std::string const &iMainLabels, std::string const &iProcess)
type
Definition: HCALResponse.h:21
static ObjectWithDict byType(TypeWithDict const &)
edm::WrapperBase const * getByBranchID(edm::BranchID const &bid, Long_t eventEntry) const
edm::propagate_const< std::shared_ptr< fwlite::HistoryGetterBase > > historyGetter_
edm::ThinnedAssociation const * getThinnedAssociation(edm::BranchID const &branchID, Long_t eventEntry) const
edm::propagate_const< TBranch * > branch_
std::vector< char const * > labels_
std::map< edm::BranchID, std::shared_ptr< internal::Data > > bidToData_
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
std::type_info const & dynamicTypeInfo() const
Definition: WrapperBase.h:46
collection_type::const_reverse_iterator const_reverse_iterator
void * address() const
void const * pointerToBaseType(void const *ptr, TypeWithDict const &derivedType) const
virtual std::string const getBranchNameFor(std::type_info const &, char const *, char const *, char const *) const
std::map< std::pair< edm::ProductID, edm::BranchListIndex >, std::shared_ptr< internal::Data > > idToData_
edm::ObjectWithDict obj_
std::string const & processName() const
char const * product() const
bool isValid() const
Definition: BranchID.h:24
void getThinnedProducts(edm::ProductID const &pid, std::vector< edm::WrapperBase const * > &foundContainers, std::vector< unsigned int > &keys, Long_t eventEntry) const
bool getByBranchDescription(edm::BranchDescription const &, Long_t eventEntry, KeyToDataMap::iterator &) const
std::function< void(TBranch const &)> branchAccessFunc_
static TypeWithDict byName(std::string const &name)
Definition: TypeWithDict.cc:74
char const * kEmpty() const
TypeWithDict typeOf() const
std::vector< ThinnedAssociationBranches >::const_iterator parentEnd(BranchID const &) const
const bool tcUse_
Use internal TTreeCache.
char const * module() const
const edm::ProcessHistory & history() const
edm::WrapperBase const * getByProductID(edm::ProductID const &pid, Long_t eventEntry) const
std::string name() const
const_reverse_iterator rend() const
std::string const & moduleLabel() const
std::string const & productInstanceName() const
static internal::Data branchNotFound
static char kEmptyString[1]
BranchID const & branchID() const
ProductID const & thinnedCollectionID() const
void getBranchData(edm::EDProductGetter const *, Long64_t, internal::Data &) const
std::string const & fullClassName() const
int k[5][pyjets_maxn]
DataGetterHelper(TTree *tree, std::shared_ptr< HistoryGetterBase > historyGetter, std::shared_ptr< BranchMapReader > branchMap=std::shared_ptr< BranchMapReader >(), std::shared_ptr< edm::EDProductGetter > getter=std::shared_ptr< edm::EDProductGetter >(), bool useCache=false, std::function< void(TBranch const &)> baFunc=[](TBranch const &){})
std::shared_ptr< BranchMapReader > branchMap_
std::string wrappedClassName(std::string const &iFullName)
char const * process() const
std::vector< ThinnedAssociationBranches >::const_iterator parentBegin(BranchID const &) const
internal::Data & getBranchDataFor(std::type_info const &, char const *, char const *, char const *) const
virtual bool getByLabel(std::type_info const &, char const *, char const *, char const *, void *, Long_t) const
edm::WrapperBase const * getThinnedProduct(edm::ProductID const &pid, unsigned int &key, Long_t eventEntry) const
edm::WrapperBase const * wrapperBasePtr(edm::ObjectWithDict const &) const
Definition: tree.py:1
ProductID const & parentCollectionID() const
bool hasParentIndex(unsigned int parentIndex, unsigned int &thinnedIndex) const
std::shared_ptr< edm::EDProductGetter const > getter_
ProcessIndex processIndex() const
Definition: ProductID.h:36
static HepMC::HEPEVT_Wrapper wrapper
std::string friendlyClassName() const
Definition: TypeID.cc:62