Belle II Software development
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
14using namespace Belle2;
15
16
17IntervalOfValidity::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
40int 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
54int 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
144namespace 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::ostream & operator<<(std::ostream &output, const IntervalOfValidity &iov)
std::istream & operator>>(std::istream &input, IntervalOfValidity &iov)
Abstract base class for different kinds of events.