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*
35  getIt(edm::ProductID const& iID) const override {
36  return event_->getByProductID(iID);
37  }
38 
39  edm::WrapperBase const*
40  getThinnedProduct(edm::ProductID const& pid, unsigned int& key) const override {
41  return event_->getThinnedProduct(pid, key);
42  }
43 
45  std::vector<edm::WrapperBase const*>& foundContainers,
46  std::vector<unsigned int>& keys) const override {
47  event_->getThinnedProducts(pid, foundContainers, keys);
48  }
49 
50 private:
51  unsigned int transitionIndex_() const override {
52  return 0U;
53  }
54 
56 
57  };
58  }
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 {
75  event1_ = std::make_shared<ChainEvent>(iFileNames1);
76  event2_ = std::make_shared<ChainEvent>(iFileNames2);
77 
78  getter_ = std::make_shared<internal::MultiProductGetter>(this);
79 
80  if (event1_->size() == 0) {
81  std::cout << "------------------------------------------------------------------------" << std::endl;
82  std::cout << "WARNING! MultiChainEvent: all primary files have zero events." << std::endl;
83  std::cout << "Trying to access the events may lead to a crash. " << std::endl;
84  std::cout << "------------------------------------------------------------------------" << std::endl;
85  } else {
86  event1_->setGetter(getter_);
87  event2_->setGetter(getter_);
88  }
89 
90  useSecFileMapSorted_ = useSecFileMapSorted;
91 
92  if (!useSecFileMapSorted_) {
93  std::cout << "------------------------------------------------------------------------" << std::endl;
94  std::cout << "WARNING! What you are about to do may be very slow." << std::endl;
95  std::cout << "The 2-file solution in FWLite works with very simple assumptions." << std::endl;
96  std::cout << "It will linearly search through the files in the secondary file list for Products." << std::endl;
97  std::cout << "There are speed improvements available to make this run faster." << std::endl;
98  std::cout << "***If your secondary files are sorted with a run-range within a file, (almost always the case) " << 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 
105  if (useSecFileMapSorted_) {
106 
107  std::cout << "------------------------------------------------------------------------" << std::endl;
108  std::cout << "This MultiChainEvent is now creating a (run_range)_2 ---> file_index_2 map" << std::endl;
109  std::cout << "for the 2-file solution. " << std::endl;
110  std::cout << "This is assuming the files you are giving me are sorted by run,event pairs within each secondary file." << 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 
117  // Loop over events, when a new file is encountered, store the first run number from this file,
118  // and the last run number from the last file.
119  TFile * lastFile = nullptr;
120  std::pair<event_id_range,Long64_t> eventRange;
121  bool firstFile = true;
122 
123  bool foundAny = false;
124 
125  for(event2_->toBegin();
126  ! event2_->atEnd();
127  ++(*event2_)) {
128  // if we have a new file, cache the "first"
129  if (lastFile != event2_->getTFile()) {
130 
131  // if this is not the first file, we have an entry.
132  // Add it to the list.
133  if (!firstFile) {
134  foundAny = true;
135  event_id_range toAdd = eventRange.first;
136  secFileMapSorted_[ toAdd ] = eventRange.second;
137  }
138  // always add the "first" event id to the cached event range
139  eventRange.first.first = event2_->event()->id();
140  lastFile = event2_->getTFile();
141  }
142  // otherwise, cache the "second" event id in the cached event range.
143  // Upon the discovery of a new file, this will be used as the
144  // "last" event id in the cached event range.
145  else {
146  eventRange.first.second = event2_->event()->id();
147  eventRange.second = event2_->eventIndex();
148  }
149  firstFile = false;
150  }
151  // due to the invailability of a "look ahead" operation, we have one additional "put" to make
152  // after the loop (which puts the "last" event, not "this" event.
153  if (foundAny) {
154  event_id_range toAdd = eventRange.first;
155  secFileMapSorted_[ toAdd ] = eventRange.second;
156  }
157 // std::cout << "Dumping run range to event id list:" << std::endl;
158 // for (sec_file_range_index_map::const_iterator mBegin = secFileMapSorted_.begin(),
159 // mEnd = secFileMapSorted_.end(),
160 // mit = mBegin;
161 // mit != mEnd; ++mit) {
162 // char buff[1000];
163 // event2_->to(mit->second);
164 // sprintf(buff, "[%10d,%10d - %10d,%10d] ---> %10d",
165 // mit->first.first.run(),
166 // mit->first.first.event(),
167 // mit->first.second.run(),
168 // mit->first.second.event(),
169 // mit->second);
170 // std::cout << buff << std::endl;
171 // }
172  }
173 
174 }
175 
176 // MultiChainEvent::MultiChainEvent(const MultiChainEvent& rhs)
177 // {
178 // // do actual copying here;
179 // }
180 
182 {
183 }
184 
185 //
186 // assignment operators
187 //
188 // const MultiChainEvent& MultiChainEvent::operator=(const MultiChainEvent& rhs)
189 // {
190 // //An exception safe implementation is
191 // MultiChainEvent temp(rhs);
192 // swap(rhs);
193 //
194 // return *this;
195 // }
196 
197 //
198 // member functions
199 //
200 
201 const MultiChainEvent&
203 {
204  event1_->operator++();
205  return *this;
206 }
207 
209 bool
210 MultiChainEvent::to(Long64_t iIndex)
211 {
212  return event1_->to(iIndex);
213 }
214 
215 
217 bool
219 {
220  return to(id.run(), id.luminosityBlock(), id.event());
221 }
222 
224 bool
226 {
227  return event1_->to(run, lumi, event);
228 }
229 
231 bool
233 {
234  return to(run, 0U, event);
235 }
236 
237 
239 bool
240 MultiChainEvent::toSec(Long64_t iIndex)
241 {
242  return event2_->to(iIndex);
243 }
244 
245 // Go to event with event id "id"
246 bool
248 {
249  // First try this file.
250  if (event2_->event_->to(id))
251  {
252  // Found it, return.
253  return true;
254  }
255  // Second, assume that the secondary files are each in run/event
256  // order. So, let's loop over all files and see if we can figure
257  // out where the event ought to be.
258  for (sec_file_range_index_map::const_iterator mBegin =
259  secFileMapSorted_.begin(),
260  mEnd = secFileMapSorted_.end(),
261  mit = mBegin;
262  mit != mEnd;
263  ++mit)
264  {
265  if (id < mit->first.first || id > mit->first.second)
266  {
267  // We don't expect this event to be in this file, so don't
268  // bother checking it right now.
269  continue;
270  }
271  // If we're here, then we have a reasonable belief that this
272  // event is in this secondary file. This part is
273  // expensive. switchToFile does memory allocations and opens the
274  // files which becomes very time consuming. This should be done
275  // as infrequently as possible.
276  event2_->switchToFile(mit->second);
277  // Is it here?
278  if (event2_->to(id))
279  {
280  // Yes!
281  return true;
282  }
283  // if we assumed that the secondary files were not each in
284  // order, but were non-overlapping, we could break here. But at
285  // this point, we might as well keep going.
286  } // for loop over files
287 
288  // if we are still here, then we did not find the id in question,
289  // do it the old fashioned way. This will open up each secondary
290  // file and explicitly check to see if the event is there.
291  if (event2_->to(id))
292  {
293  return true;
294  }
295  // if we're still here, then there really is no matching event in
296  // the secondary files. Throw.
297  throw cms::Exception("ProductNotFound") << "Cannot find id "
298  << id.run() << ", "
299  << id.event()
300  << " in secondary list. Exiting."
301  << std::endl;
302  // to make the compiler happy
303  return false;
304 }
305 
307 bool
309 {
310  return toSec(edm::EventID(run, lumi, event));
311 }
312 
313 // Go to the very first Event
315 bool
317 {
318  return toSec(edm::EventID(run, 0U, event));
319 }
320 
321 // Go to the very first Event
322 const MultiChainEvent&
324 {
325  event1_->toBegin();
326  return *this;
327 }
328 
329 //
330 // const member functions
331 //
332 std::string const
333 MultiChainEvent::getBranchNameFor(std::type_info const& iType,
334  char const* iModule,
335  char const* iInstance,
336  char const* iProcess) const
337 {
338  return event1_->getBranchNameFor(iType,iModule,iInstance,iProcess);
339 }
340 
341 std::vector<edm::BranchDescription> const&
343 {
344  return event1_->getBranchDescriptions();
345 }
346 
347 std::vector<std::string> const&
349 {
350  return event1_->getProcessHistory();
351 }
352 
353 edm::ProcessHistory const&
355 {
356  return event1_->processHistory();
357 }
358 
359 edm::EventAuxiliary const&
361 {
362  return event1_->eventAuxiliary();
363 }
364 
365 bool
367  std::type_info const& iType,
368  char const* iModule,
369  char const* iInstance,
370  char const* iProcess,
371  void* iValue) const
372 {
373  bool ret1 = event1_->getByLabel(iType, iModule, iInstance, iProcess, iValue);
374  if (!ret1) {
375  (const_cast<MultiChainEvent*>(this))->toSec(event1_->id());
376  bool ret2 = event2_->getByLabel(iType,iModule,iInstance,iProcess,iValue);
377  if (!ret2) return false;
378  }
379  return true;
380 }
381 
383 {
384  // First try the first file
385  edm::WrapperBase const* edp = event1_->getByProductID(iID);
386  // Did not find the product, try secondary file
387  if (edp == nullptr) {
388  (const_cast<MultiChainEvent*>(this))->toSec(event1_->id());
389  edp = event2_->getByProductID(iID);
390  }
391  return edp;
392 }
393 
395  // First try the first file
396  edm::WrapperBase const* edp = event1_->getThinnedProduct(pid, key);
397  // Did not find the product, try secondary file
398  if (edp == nullptr) {
399  (const_cast<MultiChainEvent*>(this))->toSec(event1_->id());
400  edp = event2_->getThinnedProduct(pid, key);
401  }
402  return edp;
403 }
404 
406  std::vector<edm::WrapperBase const*>& wrappers,
407  std::vector<unsigned int>& keys) const {
408  // First try the first file
409  event1_->getThinnedProducts(pid, wrappers, keys);
410  // Did not find all the products, try secondary file
411  if(std::find(wrappers.begin(), wrappers.end(), nullptr) != wrappers.end()) {
412  (const_cast<MultiChainEvent*>(this))->toSec(event1_->id());
413  event2_->getThinnedProducts(pid, wrappers, keys);
414  }
415 }
416 
417 bool
419 {
420  return event1_->isValid();
421 }
423 {
424  return *event1_;
425 }
426 
427 bool
429 {
430  return event1_->atEnd();
431 }
432 
433 Long64_t
435 {
436  return event1_->size();
437 }
438 
439 edm::TriggerNames const&
441 {
442  edm::TriggerNames const* names = triggerNames_(triggerResults);
443  if (names != nullptr) return *names;
444 
445  event1_->fillParameterSetRegistry();
446  names = triggerNames_(triggerResults);
447  if (names != nullptr) return *names;
448 
449  // If we cannot find it in the primary file, this probably will
450  // not help but try anyway
451  event2_->to(event1_->id());
452  event2_->fillParameterSetRegistry();
453  names = triggerNames_(triggerResults);
454  if (names != nullptr) return *names;
455 
456  throw cms::Exception("TriggerNamesNotFound")
457  << "TriggerNames not found in ParameterSet registry";
458  return *names;
459 }
460 
463 
464  edm::TriggerNames const* names = triggerNames_(triggerResults);
465 
466  if (names == nullptr) {
467  event1_->fillParameterSetRegistry();
468  names = triggerNames_(triggerResults);
469  }
470 
471  if (names == nullptr) {
472  event2_->to(event1_->id());
473  event2_->fillParameterSetRegistry();
474  names = triggerNames_(triggerResults);
475  }
476 
477  return edm::TriggerResultsByName(&triggerResults, names);
478 }
479 
480 edm::ParameterSet const*
482  auto pset = event1_->parameterSet(psID);
483  if(nullptr ==pset) {
484  pset = event2_->parameterSet(psID);
485  }
486  return pset;
487 }
488 //
489 // static member functions
490 //
491 void
493  char const* iModule,
494  char const* iInstance,
495  char const* iProcess) {
496  ChainEvent::throwProductNotFoundException(iType,iModule,iInstance,iProcess);
497 }
498 }
const MultiChainEvent & toBegin() override
edm::EventAuxiliary const & eventAuxiliary() const override
std::vector< edm::BranchDescription > const & getBranchDescriptions() const
MultiProductGetter(MultiChainEvent const *iEvent)
unsigned long long EventNumber_t
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
unsigned int LuminosityBlockNumber_t
const std::string names[nVars_]
static void throwProductNotFoundException(std::type_info const &, char const *, char const *, char const *)
Definition: ChainEvent.cc:342
bool to(Long64_t iIndex)
Go to the event at index iIndex.
Long64_t size() const
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::WrapperBase const * getThinnedProduct(edm::ProductID const &pid, unsigned int &key) const
std::vector< std::string > const & getProcessHistory() const
std::string const getBranchNameFor(std::type_info const &, char const *, char const *, char const *) const override
static void throwProductNotFoundException(std::type_info const &, char const *, char const *, char const *)
static std::string const triggerResults
Definition: EdmProvDump.cc:45
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
edm::TriggerResultsByName triggerResultsByName(edm::TriggerResults const &triggerResults) const override
void getThinnedProducts(edm::ProductID const &pid, std::vector< edm::WrapperBase const * > &foundContainers, std::vector< unsigned int > &keys) const override
void getThinnedProducts(edm::ProductID const &pid, std::vector< edm::WrapperBase const * > &foundContainers, std::vector< unsigned int > &keys) const
bool atEnd() const override
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
unsigned int RunNumber_t
const MultiChainEvent & operator++() override
edm::TriggerNames const & triggerNames(edm::TriggerResults const &triggerResults) const override
edm::WrapperBase const * getIt(edm::ProductID const &iID) const override
edm::ParameterSet const * parameterSet(edm::ParameterSetID const &psID) const override
unsigned int transitionIndex_() const override
Definition: event.py:1
edm::WrapperBase const * getThinnedProduct(edm::ProductID const &pid, unsigned int &key) const override
edm::ProcessHistory const & processHistory() const override