CMS 3D CMS Logo

MultiChainEvent.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: FWLite
4 // Class : MultiChainEvent
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Original Author: Salvatore Rappoccio
10 // Created: Thu Jul 9 22:05:56 CDT 2009
11 //
12 
13 // system include files
14 #include <iostream>
15 
16 // user include files
23 
24 #include <algorithm>
25 
26 namespace fwlite {
27 
28  namespace internal {
29 
31  public:
33 
34  edm::WrapperBase const* getIt(edm::ProductID const& iID) const override { return event_->getByProductID(iID); }
35 
36  std::optional<std::tuple<edm::WrapperBase const*, unsigned int>> getThinnedProduct(
37  edm::ProductID const& pid, unsigned int key) const override {
38  return event_->getThinnedProduct(pid, key);
39  }
40 
42  std::vector<edm::WrapperBase const*>& foundContainers,
43  std::vector<unsigned int>& keys) const override {
44  event_->getThinnedProducts(pid, foundContainers, keys);
45  }
46 
48  unsigned int key,
49  edm::ProductID const& thinned) const override {
50  return event_->getThinnedKeyFrom(parent, key, thinned);
51  }
52 
53  private:
54  unsigned int transitionIndex_() const override { return 0U; }
55 
57  };
58  } // namespace internal
59 
60  //
61  // constants, enums and typedefs
62  //
63 
64  //
65  // static data member definitions
66  //
67 
68  //
69  // constructors and destructor
70  //
71  MultiChainEvent::MultiChainEvent(std::vector<std::string> const& iFileNames1,
72  std::vector<std::string> const& iFileNames2,
73  bool useSecFileMapSorted) {
74  event1_ = std::make_shared<ChainEvent>(iFileNames1);
75  event2_ = std::make_shared<ChainEvent>(iFileNames2);
76 
77  getter_ = std::make_shared<internal::MultiProductGetter>(this);
78 
79  if (event1_->size() == 0) {
80  std::cout << "------------------------------------------------------------------------" << std::endl;
81  std::cout << "WARNING! MultiChainEvent: all primary files have zero events." << std::endl;
82  std::cout << "Trying to access the events may lead to a crash. " << std::endl;
83  std::cout << "------------------------------------------------------------------------" << std::endl;
84  } else {
85  event1_->setGetter(getter_);
86  event2_->setGetter(getter_);
87  }
88 
89  useSecFileMapSorted_ = useSecFileMapSorted;
90 
91  if (!useSecFileMapSorted_) {
92  std::cout << "------------------------------------------------------------------------" << std::endl;
93  std::cout << "WARNING! What you are about to do may be very slow." << std::endl;
94  std::cout << "The 2-file solution in FWLite works with very simple assumptions." << std::endl;
95  std::cout << "It will linearly search through the files in the secondary file list for Products." << std::endl;
96  std::cout << "There are speed improvements available to make this run faster." << std::endl;
97  std::cout << "***If your secondary files are sorted with a run-range within a file, (almost always the case) "
98  << std::endl;
99  std::cout << "***please use the option useSecFileMapSorted=true in this constructor. " << std::endl;
100  std::cout << " > usage: MultiChainEvent(primaryFiles, secondaryFiles, true);" << std::endl;
101  std::cout << "------------------------------------------------------------------------" << std::endl;
102  }
103 
104  if (useSecFileMapSorted_) {
105  std::cout << "------------------------------------------------------------------------" << std::endl;
106  std::cout << "This MultiChainEvent is now creating a (run_range)_2 ---> file_index_2 map" << std::endl;
107  std::cout << "for the 2-file solution. " << std::endl;
108  std::cout
109  << "This is assuming the files you are giving me are sorted by run,event pairs within each secondary file."
110  << std::endl;
111  std::cout << "If this is not true (rarely the case), set this option to false." << std::endl;
112  std::cout << " > usage: MultiChainEvent(primaryFiles, secondaryFiles, false);" << std::endl;
113  std::cout << "------------------------------------------------------------------------" << std::endl;
114  // speed up secondary file access with a (run,event)_1 ---> index_2 map
115 
116  // Loop over events, when a new file is encountered, store the first run number from this file,
117  // and the last run number from the last file.
118  TFile* lastFile = nullptr;
119  std::pair<event_id_range, Long64_t> eventRange;
120  bool firstFile = true;
121 
122  bool foundAny = false;
123 
124  for (event2_->toBegin(); !event2_->atEnd(); ++(*event2_)) {
125  // if we have a new file, cache the "first"
126  if (lastFile != event2_->getTFile()) {
127  // if this is not the first file, we have an entry.
128  // Add it to the list.
129  if (!firstFile) {
130  foundAny = true;
133  }
134  // always add the "first" event id to the cached event range
135  eventRange.first.first = event2_->event()->id();
136  lastFile = event2_->getTFile();
137  }
138  // otherwise, cache the "second" event id in the cached event range.
139  // Upon the discovery of a new file, this will be used as the
140  // "last" event id in the cached event range.
141  else {
142  eventRange.first.second = event2_->event()->id();
143  eventRange.second = event2_->eventIndex();
144  }
145  firstFile = false;
146  }
147  // due to the invailability of a "look ahead" operation, we have one additional "put" to make
148  // after the loop (which puts the "last" event, not "this" event.
149  if (foundAny) {
152  }
153  // std::cout << "Dumping run range to event id list:" << std::endl;
154  // for (sec_file_range_index_map::const_iterator mBegin = secFileMapSorted_.begin(),
155  // mEnd = secFileMapSorted_.end(),
156  // mit = mBegin;
157  // mit != mEnd; ++mit) {
158  // char buff[1000];
159  // event2_->to(mit->second);
160  // sprintf(buff, "[%10d,%10d - %10d,%10d] ---> %10d",
161  // mit->first.first.run(),
162  // mit->first.first.event(),
163  // mit->first.second.run(),
164  // mit->first.second.event(),
165  // mit->second);
166  // std::cout << buff << std::endl;
167  // }
168  }
169  }
170 
171  // MultiChainEvent::MultiChainEvent(const MultiChainEvent& rhs)
172  // {
173  // // do actual copying here;
174  // }
175 
177 
178  //
179  // assignment operators
180  //
181  // const MultiChainEvent& MultiChainEvent::operator=(const MultiChainEvent& rhs)
182  // {
183  // //An exception safe implementation is
184  // MultiChainEvent temp(rhs);
185  // swap(rhs);
186  //
187  // return *this;
188  // }
189 
190  //
191  // member functions
192  //
193 
195  event1_->operator++();
196  return *this;
197  }
198 
200  bool MultiChainEvent::to(Long64_t iIndex) { return event1_->to(iIndex); }
201 
203  bool MultiChainEvent::to(edm::EventID id) { return to(id.run(), id.luminosityBlock(), id.event()); }
204 
207  return event1_->to(run, lumi, event);
208  }
209 
212 
214  bool MultiChainEvent::toSec(Long64_t iIndex) { return event2_->to(iIndex); }
215 
216  // Go to event with event id "id"
218  // First try this file.
219  if (event2_->event_->to(id)) {
220  // Found it, return.
221  return true;
222  }
223  // Second, assume that the secondary files are each in run/event
224  // order. So, let's loop over all files and see if we can figure
225  // out where the event ought to be.
226  for (sec_file_range_index_map::const_iterator mBegin = secFileMapSorted_.begin(),
227  mEnd = secFileMapSorted_.end(),
228  mit = mBegin;
229  mit != mEnd;
230  ++mit) {
231  if (id < mit->first.first || id > mit->first.second) {
232  // We don't expect this event to be in this file, so don't
233  // bother checking it right now.
234  continue;
235  }
236  // If we're here, then we have a reasonable belief that this
237  // event is in this secondary file. This part is
238  // expensive. switchToFile does memory allocations and opens the
239  // files which becomes very time consuming. This should be done
240  // as infrequently as possible.
241  event2_->switchToFile(mit->second);
242  // Is it here?
243  if (event2_->to(id)) {
244  // Yes!
245  return true;
246  }
247  // if we assumed that the secondary files were not each in
248  // order, but were non-overlapping, we could break here. But at
249  // this point, we might as well keep going.
250  } // for loop over files
251 
252  // if we are still here, then we did not find the id in question,
253  // do it the old fashioned way. This will open up each secondary
254  // file and explicitly check to see if the event is there.
255  if (event2_->to(id)) {
256  return true;
257  }
258  // if we're still here, then there really is no matching event in
259  // the secondary files. Throw.
260  throw cms::Exception("ProductNotFound")
261  << "Cannot find id " << id.run() << ", " << id.event() << " in secondary list. Exiting." << std::endl;
262  // to make the compiler happy
263  return false;
264  }
265 
268  return toSec(edm::EventID(run, lumi, event));
269  }
270 
271  // Go to the very first Event
274  return toSec(edm::EventID(run, 0U, event));
275  }
276 
277  // Go to the very first Event
279  event1_->toBegin();
280  return *this;
281  }
282 
283  //
284  // const member functions
285  //
286  std::string const MultiChainEvent::getBranchNameFor(std::type_info const& iType,
287  char const* iModule,
288  char const* iInstance,
289  char const* iProcess) const {
290  return event1_->getBranchNameFor(iType, iModule, iInstance, iProcess);
291  }
292 
293  std::vector<edm::BranchDescription> const& MultiChainEvent::getBranchDescriptions() const {
294  return event1_->getBranchDescriptions();
295  }
296 
297  std::vector<std::string> const& MultiChainEvent::getProcessHistory() const { return event1_->getProcessHistory(); }
298 
299  edm::ProcessHistory const& MultiChainEvent::processHistory() const { return event1_->processHistory(); }
300 
301  edm::EventAuxiliary const& MultiChainEvent::eventAuxiliary() const { return event1_->eventAuxiliary(); }
302 
303  bool MultiChainEvent::getByLabel(std::type_info const& iType,
304  char const* iModule,
305  char const* iInstance,
306  char const* iProcess,
307  void* iValue) const {
308  bool ret1 = event1_->getByLabel(iType, iModule, iInstance, iProcess, iValue);
309  if (!ret1) {
310  (const_cast<MultiChainEvent*>(this))->toSec(event1_->id());
311  bool ret2 = event2_->getByLabel(iType, iModule, iInstance, iProcess, iValue);
312  if (!ret2)
313  return false;
314  }
315  return true;
316  }
317 
319  bool ret1 = event1_->getByTokenImp(iToken, iValue);
320  if (!ret1) {
321  (const_cast<MultiChainEvent*>(this))->toSec(event1_->id());
322  bool ret2 = event2_->getByTokenImp(iToken, iValue);
323  if (!ret2)
324  return false;
325  }
326  return true;
327  }
328 
330  // First try the first file
331  edm::WrapperBase const* edp = event1_->getByProductID(iID);
332  // Did not find the product, try secondary file
333  if (edp == nullptr) {
334  (const_cast<MultiChainEvent*>(this))->toSec(event1_->id());
335  edp = event2_->getByProductID(iID);
336  }
337  return edp;
338  }
339 
340  std::optional<std::tuple<edm::WrapperBase const*, unsigned int>> MultiChainEvent::getThinnedProduct(
341  edm::ProductID const& pid, unsigned int key) const {
342  // First try the first file
343  auto edp = event1_->getThinnedProduct(pid, key);
344  // Did not find the product, try secondary file
345  if (not edp.has_value()) {
346  (const_cast<MultiChainEvent*>(this))->toSec(event1_->id());
347  edp = event2_->getThinnedProduct(pid, key);
348  }
349  return edp;
350  }
351 
353  std::vector<edm::WrapperBase const*>& wrappers,
354  std::vector<unsigned int>& keys) const {
355  // First try the first file
356  event1_->getThinnedProducts(pid, wrappers, keys);
357  // Did not find all the products, try secondary file
358  if (std::find(wrappers.begin(), wrappers.end(), nullptr) != wrappers.end()) {
359  (const_cast<MultiChainEvent*>(this))->toSec(event1_->id());
360  event2_->getThinnedProducts(pid, wrappers, keys);
361  }
362  }
363 
365  unsigned int key,
366  edm::ProductID const& thinned) const {
367  // First try the first file
368  auto edp = event1_->getThinnedKeyFrom(parent, key, thinned);
369  // Did not find the product, try secondary file
370  if (std::holds_alternative<std::monostate>(edp)) {
371  (const_cast<MultiChainEvent*>(this))->toSec(event1_->id());
372  edp = event2_->getThinnedKeyFrom(parent, key, thinned);
373  }
374  return edp;
375  }
376 
377  bool MultiChainEvent::isValid() const { return event1_->isValid(); }
378  MultiChainEvent::operator bool() const { return *event1_; }
379 
380  bool MultiChainEvent::atEnd() const { return event1_->atEnd(); }
381 
382  Long64_t MultiChainEvent::size() const { return event1_->size(); }
383 
386  if (names != nullptr)
387  return *names;
388 
389  event1_->fillParameterSetRegistry();
391  if (names != nullptr)
392  return *names;
393 
394  // If we cannot find it in the primary file, this probably will
395  // not help but try anyway
396  event2_->to(event1_->id());
397  event2_->fillParameterSetRegistry();
399  if (names != nullptr)
400  return *names;
401 
402  throw cms::Exception("TriggerNamesNotFound") << "TriggerNames not found in ParameterSet registry";
403  return *names;
404  }
405 
408 
409  if (names == nullptr) {
410  event1_->fillParameterSetRegistry();
412  }
413 
414  if (names == nullptr) {
415  event2_->to(event1_->id());
416  event2_->fillParameterSetRegistry();
418  }
419 
421  }
422 
424  auto pset = event1_->parameterSet(psID);
425  if (nullptr == pset) {
426  pset = event2_->parameterSet(psID);
427  }
428  return pset;
429  }
430  //
431  // static member functions
432  //
433  void MultiChainEvent::throwProductNotFoundException(std::type_info const& iType,
434  char const* iModule,
435  char const* iInstance,
436  char const* iProcess) {
437  ChainEvent::throwProductNotFoundException(iType, iModule, iInstance, iProcess);
438  }
439 } // namespace fwlite
std::optional< std::tuple< edm::WrapperBase const *, unsigned int > > getThinnedProduct(edm::ProductID const &pid, unsigned int key) const
const MultiChainEvent & toBegin() override
edm::ParameterSet const * parameterSet(edm::ParameterSetID const &psID) const override
void getThinnedProducts(edm::ProductID const &pid, std::vector< edm::WrapperBase const *> &foundContainers, std::vector< unsigned int > &keys) const override
std::string const getBranchNameFor(std::type_info const &, char const *, char const *, char const *) const override
std::variant< unsigned int, detail::GetThinnedKeyFromExceptionFactory, std::monostate > OptionalThinnedKey
bool getByTokenImp(edm::EDGetToken, edm::WrapperBase const *&) const override
MultiProductGetter(MultiChainEvent const *iEvent)
edm::TriggerNames const & triggerNames(edm::TriggerResults const &triggerResults) const override
static TriggerNames const * triggerNames_(edm::TriggerResults const &triggerResults)
Definition: EventBase.cc:45
edm::WrapperBase const * getIt(edm::ProductID const &iID) const override
unsigned long long EventNumber_t
edm::EventAuxiliary const & eventAuxiliary() const override
edm::ProcessHistory const & processHistory() const override
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
unsigned int LuminosityBlockNumber_t
edm::LuminosityBlockNumber_t luminosityBlock() const
Definition: EventBase.h:65
const std::string names[nVars_]
static void throwProductNotFoundException(std::type_info const &, char const *, char const *, char const *)
Definition: ChainEvent.cc:276
bool to(Long64_t iIndex)
Go to the event at index iIndex.
int iEvent
Definition: GenABIO.cc:224
bool toSec(Long64_t iIndex)
Go to the event from secondary files at index iIndex.
edm::WrapperBase const * getByProductID(edm::ProductID const &) const override
edm::OptionalThinnedKey getThinnedKeyFrom(edm::ProductID const &parent, unsigned int key, edm::ProductID const &thinned) const
bool atEnd() const override
std::vector< edm::BranchDescription > const & getBranchDescriptions() const
void getThinnedProducts(edm::ProductID const &pid, std::vector< edm::WrapperBase const *> &foundContainers, std::vector< unsigned int > &keys) const
edm::OptionalThinnedKey getThinnedKeyFrom(edm::ProductID const &parent, unsigned int key, edm::ProductID const &thinned) const override
static void throwProductNotFoundException(std::type_info const &, char const *, char const *, char const *)
static std::string const triggerResults
Definition: EdmProvDump.cc:47
edm::TriggerResultsByName triggerResultsByName(edm::TriggerResults const &triggerResults) const override
sec_file_range_index_map secFileMapSorted_
std::shared_ptr< internal::MultiProductGetter const > getter_
bool getByLabel(std::type_info const &, char const *, char const *, char const *, void *) const override
MultiChainEvent(std::vector< std::string > const &iFileNames1, std::vector< std::string > const &iFileNames2, bool useSecFileMapSorted=false)
std::pair< edm::EventID, edm::EventID > event_id_range
std::vector< std::string > const & getProcessHistory() const
std::optional< std::tuple< edm::WrapperBase const *, unsigned int > > getThinnedProduct(edm::ProductID const &pid, unsigned int key) const override
std::shared_ptr< ChainEvent > event2_
unsigned int RunNumber_t
const MultiChainEvent & operator++() override
unsigned int transitionIndex_() const override
Definition: event.py:1
std::shared_ptr< ChainEvent > event1_