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