CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
BareRootProductGetter.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: FWLite
4 // Class : BareRootProductGetter
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Original Author: Chris Jones
10 // Created: Tue May 23 11:03:31 EDT 2006
11 //
12 
13 // user include files
24 
25 // system include files
26 
27 #include "TROOT.h"
28 #include "TBranch.h"
29 #include "TClass.h"
30 #include "TFile.h"
31 #include "TTree.h"
32 
33 //
34 // constants, enums and typedefs
35 //
36 
37 //
38 // static data member definitions
39 //
40 
41 //
42 // constructors and destructor
43 //
45 }
46 
47 // BareRootProductGetter::BareRootProductGetter(BareRootProductGetter const& rhs) {
48 // // do actual copying here;
49 // }
50 
52 }
53 
54 //
55 // assignment operators
56 //
57 // BareRootProductGetter const& BareRootProductGetter::operator=(BareRootProductGetter const& rhs) {
58 // //An exception safe implementation is
59 // BareRootProductGetter temp(rhs);
60 // swap(rhs);
61 //
62 // return *this;
63 // }
64 
65 //
66 // member functions
67 //
68 
69 //
70 // const member functions
71 //
72 edm::WrapperBase const*
74  // std::cout << "getIt called " << pid << std::endl;
75  TFile* currentFile = dynamic_cast<TFile*>(gROOT->GetListOfFiles()->Last());
76  if(0 == currentFile) {
77  throw cms::Exception("FileNotFound")
78  << "unable to find the TFile '" << gROOT->GetListOfFiles()->Last() << "'\n"
79  << "retrieved by calling 'gROOT->GetListOfFiles()->Last()'\n"
80  << "Please check the list of files.";
81  }
82  if(branchMap_.updateFile(currentFile)) {
83  idToBuffers_.clear();
84  }
85  TTree* eventTree = branchMap_.getEventTree();
86  // std::cout << "eventTree " << eventTree << std::endl;
87  if(0 == eventTree) {
88  throw cms::Exception("NoEventsTree")
89  << "unable to find the TTree '" << edm::poolNames::eventTreeName() << "' in the last open file, \n"
90  << "file: '" << branchMap_.getFile()->GetName()
91  << "'\n Please check that the file is a standard CMS ROOT format.\n"
92  << "If the above is not the file you expect then please open your data file after all other files.";
93  }
94  Long_t eventEntry = eventTree->GetReadEntry();
95  // std::cout << "eventEntry " << eventEntry << std::endl;
96  branchMap_.updateEvent(eventEntry);
97  if(eventEntry < 0) {
98  throw cms::Exception("GetEntryNotCalled")
99  << "please call GetEntry for the 'Events' TTree for each event in order to make edm::Ref's work."
100  << "\n Also be sure to call 'SetAddress' for all Branches after calling the GetEntry."
101  ;
102  }
103 
105 
106  return getIt(branchID, eventEntry);
107 }
108 
109 edm::WrapperBase const*
110 BareRootProductGetter::getIt(edm::BranchID const& branchID, Long_t eventEntry) const {
111 
112  Buffer* buffer = nullptr;
113  IdToBuffers::iterator itBuffer = idToBuffers_.find(branchID);
114 
115  // std::cout << "Buffers" << std::endl;
116  if(itBuffer == idToBuffers_.end()) {
117  buffer = createNewBuffer(branchID);
118  // std::cout << "buffer " << buffer << std::endl;
119  if(nullptr == buffer) {
120  return nullptr;
121  }
122  } else {
123  buffer = &(itBuffer->second);
124  }
125  if(nullptr == buffer) {
126  throw cms::Exception("NullBuffer")
127  << "Found a null buffer which is supposed to hold the data item."
128  << "\n Please contact developers since this message should not happen.";
129  }
130  if(nullptr == buffer->branch_) {
131  throw cms::Exception("NullBranch")
132  << "The TBranch which should hold the data item is null."
133  << "\n Please contact the developers since this message should not happen.";
134  }
135  if(buffer->eventEntry_ != eventEntry) {
136  //NOTE: Need to reset address because user could have set the address themselves
137  //std::cout << "new event" << std::endl;
138 
139  //ROOT WORKAROUND: Create new objects so any internal data cache will get cleared
140  void* address = buffer->class_->New();
141 
142  static TClass const* edproductTClass = TClass::GetClass(typeid(edm::WrapperBase));
143  edm::WrapperBase const* prod = static_cast<edm::WrapperBase const*>(buffer->class_->DynamicCast(edproductTClass,address,true));
144 
145  if(nullptr == prod) {
146  cms::Exception("FailedConversion")
147  << "failed to convert a '" << buffer->class_->GetName()
148  << "' to a edm::WrapperBase."
149  << "Please contact developers since something is very wrong.";
150  }
151  buffer->address_ = address;
152  buffer->product_ = std::shared_ptr<edm::WrapperBase const>(prod);
153  //END WORKAROUND
154 
155  address = &(buffer->address_);
156  buffer->branch_->SetAddress(address);
157 
158  buffer->branch_->GetEntry(eventEntry);
159  buffer->eventEntry_ = eventEntry;
160  }
161  if(!buffer->product_) {
162  throw cms::Exception("BranchGetEntryFailed")
163  << "Calling GetEntry with index " << eventEntry
164  << "for branch " << buffer->branch_->GetName() << " failed.";
165  }
166 
167  return buffer->product_.get();
168 }
169 
170 edm::WrapperBase const*
172 
173  Long_t eventEntry = branchMap_.getEventTree()->GetReadEntry();
175  if(!parent.isValid()) return nullptr;
176  edm::ThinnedAssociationsHelper const& thinnedAssociationsHelper = branchMap_.thinnedAssociationsHelper();
177 
178  // Loop over thinned containers which were made by selecting elements from the parent container
179  for(auto associatedBranches = thinnedAssociationsHelper.parentBegin(parent),
180  iEnd = thinnedAssociationsHelper.parentEnd(parent);
181  associatedBranches != iEnd; ++associatedBranches) {
182 
183  edm::ThinnedAssociation const* thinnedAssociation =
184  getThinnedAssociation(associatedBranches->association(), eventEntry);
185  if(thinnedAssociation == nullptr) continue;
186 
187  if(associatedBranches->parent() != branchMap_.productToBranchID(thinnedAssociation->parentCollectionID())) {
188  continue;
189  }
190 
191  unsigned int thinnedIndex = 0;
192  // Does this thinned container have the element referenced by key?
193  // If yes, thinnedIndex is set to point to it in the thinned container
194  if(!thinnedAssociation->hasParentIndex(key, thinnedIndex)) {
195  continue;
196  }
197  // Get the thinned container and return a pointer if we can find it
198  edm::ProductID const& thinnedCollectionPID = thinnedAssociation->thinnedCollectionID();
199  edm::WrapperBase const* thinnedCollection = getIt(thinnedCollectionPID);
200  if(thinnedCollection == nullptr) {
201  // Thinned container is not found, try looking recursively in thinned containers
202  // which were made by selecting elements from this thinned container.
203  edm::WrapperBase const* thinnedFromRecursiveCall = getThinnedProduct(thinnedCollectionPID, thinnedIndex);
204  if(thinnedFromRecursiveCall != nullptr) {
205  key = thinnedIndex;
206  return thinnedFromRecursiveCall;
207  } else {
208  continue;
209  }
210  }
211  key = thinnedIndex;
212  return thinnedCollection;
213  }
214  return nullptr;
215 }
216 
217 void
219  std::vector<edm::WrapperBase const*>& foundContainers,
220  std::vector<unsigned int>& keys) const {
221 
222  Long_t eventEntry = branchMap_.getEventTree()->GetReadEntry();
224  if(!parent.isValid()) return;
225  edm::ThinnedAssociationsHelper const& thinnedAssociationsHelper = branchMap_.thinnedAssociationsHelper();
226 
227  // Loop over thinned containers which were made by selecting elements from the parent container
228  for(auto associatedBranches = thinnedAssociationsHelper.parentBegin(parent),
229  iEnd = thinnedAssociationsHelper.parentEnd(parent);
230  associatedBranches != iEnd; ++associatedBranches) {
231 
232  edm::ThinnedAssociation const* thinnedAssociation =
233  getThinnedAssociation(associatedBranches->association(), eventEntry);
234  if(thinnedAssociation == nullptr) continue;
235 
236  if(associatedBranches->parent() != branchMap_.productToBranchID(thinnedAssociation->parentCollectionID())) {
237  continue;
238  }
239 
240  unsigned int nKeys = keys.size();
241  unsigned int doNotLookForThisIndex = std::numeric_limits<unsigned int>::max();
242  std::vector<unsigned int> thinnedIndexes(nKeys, doNotLookForThisIndex);
243  bool hasAny = false;
244  for(unsigned k = 0; k < nKeys; ++k) {
245  // Already found this one
246  if(foundContainers[k] != nullptr) continue;
247  // Already know this one is not in this thinned container
248  if(keys[k] == doNotLookForThisIndex) continue;
249  // Does the thinned container hold the entry of interest?
250  // Modifies thinnedIndexes[k] only if it returns true and
251  // sets it to the index in the thinned collection.
252  if(thinnedAssociation->hasParentIndex(keys[k], thinnedIndexes[k])) {
253  hasAny = true;
254  }
255  }
256  if(!hasAny) {
257  continue;
258  }
259  // Get the thinned container and set the pointers and indexes into
260  // it (if we can find it)
261  edm::ProductID thinnedCollectionPID = thinnedAssociation->thinnedCollectionID();
262  edm::WrapperBase const* thinnedCollection = getIt(thinnedCollectionPID);
263 
264  if(thinnedCollection == nullptr) {
265  // Thinned container is not found, try looking recursively in thinned containers
266  // which were made by selecting elements from this thinned container.
267  getThinnedProducts(thinnedCollectionPID, foundContainers, thinnedIndexes);
268  for(unsigned k = 0; k < nKeys; ++k) {
269  if(foundContainers[k] == nullptr) continue;
270  if(thinnedIndexes[k] == doNotLookForThisIndex) continue;
271  keys[k] = thinnedIndexes[k];
272  }
273  } else {
274  for(unsigned k = 0; k < nKeys; ++k) {
275  if(thinnedIndexes[k] == doNotLookForThisIndex) continue;
276  keys[k] = thinnedIndexes[k];
277  foundContainers[k] = thinnedCollection;
278  }
279  }
280  }
281 }
282 
285  //find the branch
286  edm::BranchDescription const& bdesc = branchMap_.branchIDToBranch(branchID);
287 
288  TBranch* branch= branchMap_.getEventTree()->GetBranch(bdesc.branchName().c_str());
289  if(nullptr == branch) {
290  //we do not thrown on missing branches since 'getIt' should not throw under that condition
291  return nullptr;
292  }
293  //find the class type
295  edm::TypeWithDict classType(edm::TypeWithDict::byName(fullName));
296  if(!bool(classType)) {
297  throw cms::Exception("MissingDictionary")
298  << "could not find dictionary for type '" << fullName << "'"
299  << "\n Please make sure all the necessary libraries are available.";
300  return nullptr;
301  }
302 
303  TClass* rootClassType = TClass::GetClass(classType.typeInfo());
304  if(nullptr == rootClassType) {
305  throw cms::Exception("MissingRootDictionary")
306  << "could not find a ROOT dictionary for type '" << fullName << "'"
307  << "\n Please make sure all the necessary libraries are available.";
308  return nullptr;
309  }
310  void* address = rootClassType->New();
311 
312  static TClass const* edproductTClass = TClass::GetClass(typeid(edm::WrapperBase));
313  edm::WrapperBase const* prod = static_cast<edm::WrapperBase const*>( rootClassType->DynamicCast(edproductTClass,address,true));
314  if(nullptr == prod) {
315  throw cms::Exception("FailedConversion")
316  << "failed to convert a '" << fullName
317  << "' to a edm::WrapperBase."
318  << "Please contact developers since something is very wrong.";
319  }
320 
321  //connect the instance to the branch
322  //void* address = wrapperObj.Address();
323  Buffer b(prod, branch, address, rootClassType);
324  idToBuffers_[branchID] = b;
325 
326  //As of 5.13 ROOT expects the memory address held by the pointer passed to
327  // SetAddress to be valid forever
328  address = &(idToBuffers_[branchID].address_);
329  branch->SetAddress(address);
330 
331  return &(idToBuffers_[branchID]);
332 }
333 
335 BareRootProductGetter::getThinnedAssociation(edm::BranchID const& branchID, Long_t eventEntry) const {
336 
337  edm::WrapperBase const* wrapperBase = getIt(branchID, eventEntry);
338  if(wrapperBase == nullptr) {
340  << "BareRootProductGetter::getThinnedAssociation, product ThinnedAssociation not found.\n";
341  }
342  if(!(typeid(edm::ThinnedAssociation) == wrapperBase->dynamicTypeInfo())) {
344  << "BareRootProductGetter::getThinnedAssociation, product has wrong type, not a ThinnedAssociation.\n";
345  }
347  static_cast<edm::Wrapper<edm::ThinnedAssociation> const*>(wrapperBase);
348 
349  edm::ThinnedAssociation const* thinnedAssociation = wrapper->product();
350  return thinnedAssociation;
351 }
std::string const & branchName() const
static TypeWithDict byName(std::string const &className)
list parent
Definition: dbtoconf.py:74
std::type_info const & dynamicTypeInfo() const
Definition: WrapperBase.h:37
virtual edm::WrapperBase const * getThinnedProduct(edm::ProductID const &, unsigned int &key) const override
virtual void getThinnedProducts(edm::ProductID const &, std::vector< edm::WrapperBase const * > &foundContainers, std::vector< unsigned int > &keys) const override
bool updateEvent(Long_t eventEntry)
bool updateFile(TFile *file)
TFile * getFile() const
bool isValid() const
Definition: BranchID.h:24
const edm::BranchDescription & branchIDToBranch(const edm::BranchID &bid) const
std::vector< ThinnedAssociationBranches >::const_iterator parentEnd(BranchID const &) const
virtual edm::WrapperBase const * getIt(edm::ProductID const &) const override
TTree * getEventTree() const
std::string const & className() const
edm::ThinnedAssociation const * getThinnedAssociation(edm::BranchID const &branchID, Long_t eventEntry) const
ProductID const & thinnedCollectionID() const
const edm::ThinnedAssociationsHelper & thinnedAssociationsHelper() const
string fullName
T const * product() const
Definition: Wrapper.h:38
std::string wrappedClassName(std::string const &iFullName)
tuple pid
Definition: sysUtil.py:22
double b
Definition: hdecay.h:120
string const
Definition: compareJSON.py:14
std::vector< ThinnedAssociationBranches >::const_iterator parentBegin(BranchID const &) const
Buffer * createNewBuffer(edm::BranchID const &) const
list key
Definition: combine.py:13
std::string const & eventTreeName()
Definition: BranchType.cc:260
fwlite::BranchMapReader branchMap_
ProductID const & parentCollectionID() const
bool hasParentIndex(unsigned int parentIndex, unsigned int &thinnedIndex) const
std::shared_ptr< edm::WrapperBase const > product_
edm::BranchID productToBranchID(const edm::ProductID &pid)
static HepMC::HEPEVT_Wrapper wrapper