LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
FileIndex.cc
Go to the documentation of this file.
2 
3 #include "cetlib/container_algorithms.h"
5 
6 #include <algorithm>
7 #include <iomanip>
8 #include <ostream>
9 
10 using namespace cet;
11 using namespace std;
12 
13 namespace {
14  bool
15  subRunUnspecified(art::EventID const& eID)
16  {
17  // This is nasty, principally because we don't want to be
18  // encouraging too many people to do this. Basically, we're
19  // checking whether the only reason an EventID is invalid is
20  // because its subRun number is invalid.
21  return (!eID.isValid()) && eID.runID().isValid() &&
22  art::EventID(art::SubRunID::firstSubRun(), eID.event()).isValid();
23  }
24 }
25 
26 namespace art {
27 
28  void
29  FileIndex::addEntry(EventID const& eID, EntryNumber_t const entry)
30  {
31  entries_.emplace_back(eID, entry);
32  resultCached() = false;
33  sortState() = kNotSorted;
34  }
35 
36  void
37  FileIndex::addEntryOnLoad(EventID const& eID, EntryNumber_t const entry)
38  {
39  entries_.emplace_back(eID, entry);
40  resultCached() = false;
41  }
42 
43  void
44  FileIndex::sortBy_Run_SubRun_Event()
45  {
46  stable_sort_all(entries_);
47  resultCached() = false;
48  sortState() = kSorted_Run_SubRun_Event;
49  }
50 
51  void
52  FileIndex::sortBy_Run_SubRun_EventEntry()
53  {
54  stable_sort_all(entries_, Compare_Run_SubRun_EventEntry());
55  resultCached() = false;
56  sortState() = kSorted_Run_SubRun_EventEntry;
57  }
58 
59  bool
60  FileIndex::allEventsInEntryOrder() const
61  {
62  if (!resultCached()) {
63  resultCached() = true;
64  EntryNumber_t maxEntry{Element::invalidEntry};
65  for (auto const& e : entries_) {
66  if (e.getEntryType() == kEvent) {
67  if (e.entry_ < maxEntry) {
68  allInEntryOrder() = false;
69  return false;
70  }
71  maxEntry = e.entry_;
72  }
73  }
74  allInEntryOrder() = true;
75  return true;
76  }
77  return allInEntryOrder();
78  }
79 
80  bool
81  FileIndex::eventsUniqueAndOrdered() const
82  {
83 
84  auto it = cbegin();
85  auto itEnd = cend();
86 
87  // Set up the iterators to point to first two events
88  // (In the trivial case where there is zero or one event,
89  // the set is unique and ordered by construction).
90 
91  if (it == itEnd)
92  return true;
93 
94  // Step to first event
95  while (it->getEntryType() != kEvent) {
96  ++it;
97  if (it == itEnd)
98  return true;
99  }
100  auto itPrevious = it;
101 
102  // Step to second event
103  ++it;
104  if (it == itEnd)
105  return true;
106  while (it->getEntryType() != kEvent) {
107  ++it;
108  if (it == itEnd)
109  return true;
110  }
111 
112  for (; it != itEnd; ++it) {
113  if (it->getEntryType() == kEvent) {
114  if (it->eventID_ <= itPrevious->eventID_)
115  return false;
116  itPrevious = it;
117  }
118  }
119  return true; // finished and found no duplicates
120  }
121 
123  FileIndex::findPosition(EventID const& eID) const
124  {
125 
126  assert(sortState() == kSorted_Run_SubRun_Event);
127 
128  Element el{eID};
129  return lower_bound_all(entries_, el);
130  }
131 
132  template <>
134  FileIndex::findPosition(EventID const& eID, bool exact) const
135  {
136 
137  assert(sortState() == kSorted_Run_SubRun_Event);
138 
139  if (subRunUnspecified(eID)) {
140  return findEventForUnspecifiedSubRun(eID, exact);
141  }
142 
143  const_iterator it = findPosition(eID);
144  const_iterator itEnd = entries_.end();
145  while (it != itEnd && it->getEntryType() != FileIndex::kEvent) {
146  ++it;
147  }
148  if (it == itEnd)
149  return itEnd;
150  if (exact && (*it != eID))
151  return itEnd;
152  return it;
153  }
154 
155  template <>
157  FileIndex::findPosition(SubRunID const& srID, bool exact) const
158  {
159  assert(sortState() != kNotSorted);
160  const_iterator it;
161  auto const invID = EventID::invalidEvent(srID);
162  if (sortState() == kSorted_Run_SubRun_EventEntry) {
163  Element const el{invID};
164  it = lower_bound_all(entries_, el, Compare_Run_SubRun_EventEntry());
165  } else {
166  it = findPosition(invID);
167  }
168  auto const itEnd = entries_.cend();
169  while (it != itEnd && it->getEntryType() != FileIndex::kSubRun) {
170  ++it;
171  }
172  if (it == itEnd)
173  return itEnd;
174  if (exact && (it->eventID_.subRunID() != srID))
175  return itEnd;
176  return it;
177  }
178 
179  template <>
181  FileIndex::findPosition(RunID const& rID, bool exact) const
182  {
183  assert(sortState() != kNotSorted);
184  const_iterator it;
185  auto const invID = EventID::invalidEvent(rID);
186  if (sortState() == kSorted_Run_SubRun_EventEntry) {
187  Element const el{invID};
188  it = lower_bound_all(entries_, el, Compare_Run_SubRun_EventEntry());
189  } else {
190  it = findPosition(invID);
191  }
192  auto const itEnd = entries_.cend();
193  while (it != itEnd && it->getEntryType() != FileIndex::kRun) {
194  ++it;
195  }
196  if (it == itEnd)
197  return itEnd;
198  if (exact && (it->eventID_.runID() != rID))
199  return itEnd;
200  return it;
201  }
202 
204  FileIndex::findSubRunOrRunPosition(SubRunID const& srID) const
205  {
206  assert(sortState() != kNotSorted);
207  const_iterator it;
208  if (sortState() == kSorted_Run_SubRun_EventEntry) {
209  Element el{EventID::invalidEvent(srID)};
210  it = lower_bound_all(entries_, el, Compare_Run_SubRun_EventEntry());
211  } else {
212  it = findPosition(EventID::invalidEvent(srID));
213  }
214  auto const itEnd = entries_.cend();
215  while (it != itEnd && it->getEntryType() != FileIndex::kSubRun &&
216  it->getEntryType() != FileIndex::kRun) {
217  ++it;
218  }
219  return it;
220  }
221 
222  bool
224  {
225  bool const result = lh.eventID_ < rh.eventID_;
226  return result;
227  }
228 
229  bool
230  Compare_Run_SubRun_EventEntry::operator()(FileIndex::Element const& lh,
231  FileIndex::Element const& rh)
232  {
233  if (lh.eventID_.subRunID() == rh.eventID_.subRunID()) {
234  if ((!lh.eventID_.isValid()) && (!rh.eventID_.isValid())) {
235  return false;
236  } else if (!lh.eventID_.isValid()) {
237  return true;
238  } else if (!rh.eventID_.isValid()) {
239  return false;
240  } else {
241  return lh.entry_ < rh.entry_;
242  }
243  } else {
244  return lh.eventID_.subRunID() < rh.eventID_.subRunID();
245  }
246  }
247 
248  ostream&
249  operator<<(ostream& os, FileIndex::Element const& el)
250  {
251  os << el.eventID_ << ": entry# " << el.entry_;
252  return os;
253  }
254 
255  void
256  FileIndex::print_event_list(ostream& os) const
257  {
258  os << "\nPrinting the list of Runs, SubRuns, and Events stored in the root "
259  "file.\n\n";
260  os << setw(15) << "Run" << setw(15) << "SubRun" << setw(15) << "Event"
261  << "\n";
262  for (auto const& e : entries_) {
263  if (e.getEntryType() == FileIndex::kEvent) {
264  os << setw(15) << e.eventID_.run() << setw(15) << e.eventID_.subRun()
265  << setw(15) << e.eventID_.event() << "\n";
266  } else if (e.getEntryType() == FileIndex::kSubRun) {
267  os << setw(15) << e.eventID_.run() << setw(15) << e.eventID_.subRun()
268  << setw(15) << " "
269  << "\n";
270  } else if (e.getEntryType() == FileIndex::kRun) {
271  os << setw(15) << e.eventID_.run() << setw(15) << " " << setw(15) << " "
272  << "\n";
273  }
274  }
275  }
276 
277  ostream&
278  operator<<(ostream& os, FileIndex const& fileIndex)
279  {
280 
281  os << "\nPrinting FileIndex contents. This includes a list of all Runs, "
282  "SubRuns\n"
283  << "and Events stored in the root file.\n\n";
284  os << setw(15) << "Run" << setw(15) << "SubRun" << setw(15) << "Event"
285  << setw(15) << "TTree Entry"
286  << "\n";
287  for (auto const& e : fileIndex) {
288  if (e.getEntryType() == FileIndex::kEvent) {
289  os << setw(15) << e.eventID_.run() << setw(15) << e.eventID_.subRun()
290  << setw(15) << e.eventID_.event() << setw(15) << e.entry_ << "\n";
291  } else if (e.getEntryType() == FileIndex::kSubRun) {
292  os << setw(15) << e.eventID_.run() << setw(15) << e.eventID_.subRun()
293  << setw(15) << " " << setw(15) << e.entry_ << " (SubRun)"
294  << "\n";
295  } else if (e.getEntryType() == FileIndex::kRun) {
296  os << setw(15) << e.eventID_.run() << setw(15) << " " << setw(15) << " "
297  << setw(15) << e.entry_ << " (Run)"
298  << "\n";
299  }
300  }
301  return os;
302  }
303 
305  FileIndex::findEventForUnspecifiedSubRun(EventID const& eID, bool exact) const
306  {
307 
308  RunID const& runID = eID.runID();
309  EventNumber_t event = eID.event();
310  SubRunID last_subRunID;
311 
312  // Try to find the event.
313  auto const firstEvent =
314  findPosition(EventID::firstEvent(SubRunID::firstSubRun(runID)), false);
315  const_iterator it = firstEvent;
316  const_iterator const itEnd = entries_.end();
317  if (it == itEnd)
318  return it;
319 
320  // Starting with it, jump to the first event of each subrun until
321  // we find either:
322  //
323  // 1. The next run.
324  // 2. An event number higher than we want.
325  // 3. The end of the file index.
326  while ((it != itEnd) && (it->eventID_.runID() == runID) &&
327  (it->eventID_.event() < event)) {
328  last_subRunID = it->eventID_.subRunID();
329  // Get the first event in the next subrun.
330  it = findPosition(EventID::firstEvent(it->eventID_.subRunID().next()),
331  false);
332  }
333 
334  const_iterator result = itEnd;
335  if ((it != itEnd) && (it->eventID_.runID() == runID) &&
336  (it->eventID_.event() == event)) {
337  // We started on the correct event.
338  result = it;
339  } else if (last_subRunID.isValid()) {
340  // Find the event in the last subrun.
341  result = findPosition(EventID(last_subRunID, event), exact);
342  }
343  if (result == itEnd) {
344  // Did not find anything.
345  mf::LogWarning("FileIndex")
346  << "Could not find incompletely specified event " << eID
347  << " with smart algorithm:\n"
348  << "Assuming pathological file structure (event selection?) and\n"
349  << "trying again (inefficient).\n"
350  << "NOTE: this will find only the event with matching event number "
351  << "and the\n"
352  << " lowest subrun number: any others are inaccessible via this "
353  << "method.";
354  SubRunID trySubRun{SubRunID::firstSubRun(runID)};
355  // Try to find the highest subrun number in this run.
356  const_iterator findIt(firstEvent);
357  SubRunID lastSubRunInRun{trySubRun};
358  for (; findIt != itEnd && findIt->eventID_.runID() == runID;
359  findIt =
360  findPosition(EventID::firstEvent(lastSubRunInRun.next()), false)) {
361  lastSubRunInRun = findIt->eventID_.subRunID();
362  }
363  // Now loop through each subrun looking for an exact match to our event.
364  while ((findIt = findPosition(EventID(trySubRun, event), true)) ==
365  itEnd &&
366  trySubRun < lastSubRunInRun) {
367  trySubRun = trySubRun.next();
368  }
369  result = findIt;
370  }
371  return result;
372  }
373 }
bool isValid() const
Definition: EventID.h:123
RunID const & runID() const
Definition: EventID.h:93
SubRunID const & subRunID() const
Definition: EventID.h:105
STL namespace.
long long EntryNumber_t
Definition: FileIndex.h:43
bool isValid() const
Definition: SubRunID.h:96
SubRunID next() const
Definition: SubRunID.h:110
int print_event_list(InfoDumperInputFile const &file, ostream &output)
static SubRunID firstSubRun()
Definition: SubRunID.h:152
ostream & operator<<(ostream &os, FileIndex const &fileIndex)
Definition: FileIndex.cc:278
std::vector< Element >::const_iterator const_iterator
Definition: FileIndex.h:72
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
IDNumber_t< Level::Event > EventNumber_t
Definition: IDNumber.h:117
bool isValid() const
Definition: RunID.h:69
HLT enums.
EventNumber_t event() const
Definition: EventID.h:117
EntryNumber_t entry_
Definition: FileIndex.h:69
Float_t e
Definition: plot.C:34
bool operator<(FileIndex::Element const &lh, FileIndex::Element const &rh)
Definition: FileIndex.cc:223
Event finding and building.