CMS 3D CMS Logo

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