Belle II Software  release-08-01-10
IntervalOfValidity.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <framework/database/IntervalOfValidity.h>
10 #include <framework/dataobjects/EventMetaData.h>
11 #include <framework/logging/Logger.h>
12 #include <utility>
13 
14 using namespace Belle2;
15 
16 
17 IntervalOfValidity::IntervalOfValidity(int experimentLow, int runLow, int experimentHigh,
18  int runHigh) : m_experimentLow(experimentLow), m_runLow(runLow), m_experimentHigh(experimentHigh), m_runHigh(runHigh)
19 {
20  // consistency checks
21  if ((experimentLow < 0) && (runLow >= 0)) {
22  B2ERROR("A run number of " << runLow << " is given for an undefined low experiment number. Setting run to undefined, too.");
23  m_runLow = -1;
24  }
25  if ((experimentHigh < 0) && (runHigh >= 0)) {
26  B2ERROR("A run number of " << runHigh << " is given for an undefined high experiment number. Setting run to undefined, too.");
27  m_runHigh = -1;
28  }
29  if ((experimentLow >= 0) && (experimentHigh >= 0)) {
30  if ((experimentLow > experimentHigh) || ((experimentLow == experimentHigh) && (runHigh >= 0) && (runLow > runHigh))) {
31  B2ERROR("The given lower and higher experiment/run numbers of " << experimentLow << "/" << runLow << " and " << experimentHigh <<
32  "/" << runHigh << ", respectively, are in the wrong order, Swapping them.");
34  std::swap(m_runLow, m_runHigh);
35  }
36  }
37 }
38 
39 
40 int IntervalOfValidity::checkLowerBound(int experiment, int run) const
41 {
42  // check for empty interval
43  if (empty()) return false;
44 
45  if ((m_experimentLow == experiment) && (m_runLow == run)) return 0;
46  if (m_experimentLow < 0) return 1;
47  if (experiment < m_experimentLow) return -1;
48  if (experiment == m_experimentLow) {
49  if (run < m_runLow) return -1;
50  }
51  return 1;
52 }
53 
54 int IntervalOfValidity::checkUpperBound(int experiment, int run) const
55 {
56  // check for empty interval
57  if (empty()) return false;
58 
59  if ((m_experimentHigh == experiment) && (m_runHigh == run)) return 0;
60  if (m_experimentHigh < 0) return -1;
61  if ((experiment < 0) || (experiment > m_experimentHigh)) return 1;
62  if (experiment == m_experimentHigh) {
63  if ((m_runHigh >= 0) && ((run > m_runHigh) || (run < 0))) return 1;
64  }
65  return -1;
66 }
67 
69 {
70  if (m_experimentLow < 0) m_runLow = -1;
71  if (m_experimentHigh < 0) m_runHigh = -1;
72  if ((m_experimentLow >= 0) && (m_experimentHigh >= 0)) {
75  }
76  }
77 }
78 
79 
81 {
82  auto experiment = (int) event.getExperiment();
83  auto run = (int) event.getRun();
84 
85  // check for empty interval
86  if (empty()) return false;
87 
88  // check lower bound
89  if (checkLowerBound(experiment, run) < 0) return false;
90  if (checkUpperBound(experiment, run) > 0) return false;
91  return true;
92 }
93 
95 {
96  if (empty() || iov.empty()) return IntervalOfValidity();
97 
98  IntervalOfValidity result(*this);
99  if (checkLowerBound(iov.m_experimentLow, iov.m_runLow) > 0) {
100  result.m_experimentLow = iov.m_experimentLow;
101  result.m_runLow = iov.m_runLow;
102  }
103  if (checkUpperBound(iov.m_experimentHigh, iov.m_runHigh) < 0) {
104  result.m_experimentHigh = iov.m_experimentHigh;
105  result.m_runHigh = iov.m_runHigh;
106  }
107 
108  result.makeValid();
109  return result;
110 }
111 
113 {
114  if (!overlaps(iov)) return true;
115 
116  bool thisOlder = checkLowerBound(iov.m_experimentLow, iov.m_runLow) >= 0;
117  IntervalOfValidity& older = (thisOlder) ? *this : iov;
118  IntervalOfValidity& younger = (thisOlder) ? iov : *this;
119 
120  if (trimOlder) {
121  // check for the case where trimming is not possible because the interval would be split
122  if (older.checkUpperBound(younger.m_experimentHigh, younger.m_runHigh) < 0) return false;
123 
124  older.m_experimentHigh = younger.m_experimentLow;
125  older.m_runHigh = younger.m_runLow - 1;
126  if (older.m_runHigh < 0) {
127  older.m_experimentHigh--;
128  older.m_runHigh = -1;
129  }
130  older.makeValid();
131  } else {
132  younger.m_experimentLow = older.m_experimentHigh;
133  younger.m_runLow = older.m_runHigh + 1;
134  if (younger.m_runLow == 0) {
135  younger.m_experimentLow++;
136  }
137  younger.makeValid();
138  }
139 
140  return true;
141 }
142 
143 
144 namespace Belle2 {
150  std::istream& operator>> (std::istream& input, IntervalOfValidity& iov)
151  {
152  iov = IntervalOfValidity();
153  if (!input.good()) {
154  throw std::runtime_error("cannot read from stream");
155  }
156 
157  std::string str[4];
158  int index = 0;
159  while (input.good()) {
160  auto c = input.peek();
161  if (c == EOF) break;
162  if (((c == ' ') || (c == '\n') || (c == '\t'))) {
163  //ignore whitespace in the beginning
164  if (index == 0 && str[0].empty()) {
165  input.get();
166  continue;
167  }
168  //and stop parsing otherwise
169  break;
170  }
171  if (c == ',') {
172  index++;
173  if (index == 4) break;
174  } else {
175  str[index] += c;
176  }
177  input.get();
178  }
179  if (index != 3) {
180  throw std::invalid_argument("IoV needs to be four values (firstExp,firstRun,finalExp,finalRun)");
181  }
182  try {
183  iov.m_experimentLow = stoi(str[0]);
184  iov.m_runLow = stoi(str[1]);
185  iov.m_experimentHigh = stoi(str[2]);
186  iov.m_runHigh = stoi(str[3]);
187  } catch (std::invalid_argument& e) {
188  throw std::invalid_argument("experiment and run numbers must be integers");
189  }
190 
191  return input;
192  }
193 
194  std::ostream& operator<< (std::ostream& output, const IntervalOfValidity& iov)
195  {
196  output << iov.m_experimentLow << "," << iov.m_runLow << "," << iov.m_experimentHigh << "," << iov.m_runHigh;
197 
198  return output;
199  }
200 
202 }
Store event, run, and experiment numbers.
Definition: EventMetaData.h:33
A class that describes the interval of experiments/runs for which an object in the database is valid.
bool trimOverlap(IntervalOfValidity &iov, bool trimOlder=true)
Remove the overlap between two intervals of validity by shortening one of them.
int checkUpperBound(int experiment, int run) const
Helper function to check whether a given experiment/run number is above or below the upper bound of t...
bool empty() const
Function that checks whether the validity interval is empty.
void makeValid()
Helper function to set the interval to empty if the upper bound is below the lower one.
int m_runLow
Lowest run number.
bool contains(const EventMetaData &event) const
Function that checks whether the event is inside the validity interval.
int checkLowerBound(int experiment, int run) const
Helper function to check whether a given experiment/run number is above or below the lower bound of t...
bool overlaps(const IntervalOfValidity &iov) const
Function that checks the validity interval overlaps with another interval of validity.
int m_experimentLow
Lowest experiment number.
IntervalOfValidity overlap(const IntervalOfValidity &iov) const
Function that determines the overlap of the validity interval with another interval of validity.
int m_experimentHigh
Highest experiment number.
IntervalOfValidity()
Default constructor which will create an empty iov.
int m_runHigh
Highest run number.
std::istream & operator>>(std::istream &input, IntervalOfValidity &iov)
std::ostream & operator<<(std::ostream &output, const IntervalOfValidity &iov)
Abstract base class for different kinds of events.