Belle II Software development
IntervalOfValidity Class Reference

Public Member Functions

def __init__ (self, *iov)
 
def first (self)
 
def first_exp (self)
 
def first_run (self)
 
def final (self)
 
def final_exp (self)
 
def final_run (self)
 
def __repr__ (self)
 
def __eq__ (self, other)
 
def __lt__ (self, other)
 
def __and__ (self, other)
 
def __or__ (self, other)
 
def __sub__ (self, other)
 
def __hash__ (self)
 
def subtract (self, other)
 
def intersect (self, other)
 
def union (self, other, allow_startone=False)
 
def contains (self, exp, run)
 
def is_open (self)
 
def tuple (self)
 

Static Public Member Functions

def always ()
 

Public Attributes

 final
 Doxygen complains without this string.
 

Private Attributes

 __first
 tuple with the first valid exp, run
 
 __final
 tuple with the final valid exp, run
 

Detailed Description

Interval of validity class to support set operations like union and
intersection.

An interval of validity is a set of runs for which something is valid. An
IntervalOfValidity consists of a `first` valid run and a `final` valid run.

Warning:
    The `final` run is inclusive so the the validity is including the final run.

Each run is identified by a experiment number and a run number. Accessing
`first` or `final` will return a tuple ``(experiment, run)`` but the
elements can also be accessed separately with `first_exp`, `first_exp`,
`final_exp` and `final_run`.

For `final` there's a special case where either the run or both, the run and
the experiment number are infinite. This means the validity extends to all
values. If only the run number is infinite then it's valid for all further
runs in this experiment. If both are infinite the validity extends to everything.

For simplicity ``-1`` can be passed in instead of infinity when creating objects.

Definition at line 24 of file iov.py.

Constructor & Destructor Documentation

◆ __init__()

def __init__ (   self,
iov 
)
Create a new object.

It can be either instantiated by providing four values or one tuple/list
with four values for first_exp, first_run, final_exp, final_run

Definition at line 48 of file iov.py.

48 def __init__(self, *iov):
49 """Create a new object.
50
51 It can be either instantiated by providing four values or one tuple/list
52 with four values for first_exp, first_run, final_exp, final_run
53 """
54 if len(iov) == 1 and isinstance(iov[0], (list, tuple)):
55 iov = iov[0]
56 if len(iov) != 4:
57 raise ValueError("A iov should have four values")
58
59 self.__first = tuple(iov[:2])
60
61 self.__final = tuple(math.inf if x == -1 else x for x in iov[2:])
62 if math.isinf(self.__final[0]) and not math.isinf(self.__final[1]):
63 raise ValueError(f"Unlimited final experiment but not unlimited run: {self}")
64 if self.__first[0] > self.__final[0]:
65 raise ValueError(f"First exp larger than final exp: {self}")
66 if self.__first[0] == self.__final[0] and self.__first[1] > self.__final[1]:
67 raise ValueError(f"First run larger than final run: {self}")
68 if self.__first[0] < 0 or self.__first[1] < 0:
69 raise ValueError(f"Negative first exp or run: {self}")
70

Member Function Documentation

◆ __and__()

def __and__ (   self,
  other 
)
Intersection between iovs. Will return None if the payloads don't overlap

Definition at line 126 of file iov.py.

126 def __and__(self, other):
127 """Intersection between iovs. Will return None if the payloads don't overlap"""
128 if not isinstance(other, IntervalOfValidity):
129 return NotImplemented
130 return self.intersect(other)
131

◆ __eq__()

def __eq__ (   self,
  other 
)
Check for equality

Definition at line 114 of file iov.py.

114 def __eq__(self, other):
115 """Check for equality"""
116 if not isinstance(other, IntervalOfValidity):
117 return NotImplemented
118 return (self.__first, self.__final) == (other.__first, other.__final)
119

◆ __hash__()

def __hash__ (   self)
Make object hashable

Definition at line 145 of file iov.py.

145 def __hash__(self):
146 """Make object hashable"""
147 return hash((self.__first, self.__final))
148

◆ __lt__()

def __lt__ (   self,
  other 
)
Sort by run values

Definition at line 120 of file iov.py.

120 def __lt__(self, other):
121 """Sort by run values"""
122 if not isinstance(other, IntervalOfValidity):
123 return NotImplemented
124 return (self.__first, self.__final) < (other.__first, other.__final)
125

◆ __or__()

def __or__ (   self,
  other 
)
Union between iovs. Will return None if the iovs don't overlap or
connect to each other

Definition at line 132 of file iov.py.

132 def __or__(self, other):
133 """Union between iovs. Will return None if the iovs don't overlap or
134 connect to each other"""
135 if not isinstance(other, IntervalOfValidity):
136 return NotImplemented
137 return self.union(other, False)
138

◆ __repr__()

def __repr__ (   self)
Return a printable representation

Definition at line 110 of file iov.py.

110 def __repr__(self):
111 """Return a printable representation"""
112 return str(self.__first + self.__final)
113

◆ __sub__()

def __sub__ (   self,
  other 
)
Difference between iovs. Will return None if nothing is left over

Definition at line 139 of file iov.py.

139 def __sub__(self, other):
140 """Difference between iovs. Will return None if nothing is left over"""
141 if not isinstance(other, IntervalOfValidity):
142 return NotImplemented
143 return self.subtract(other)
144

◆ always()

def always ( )
static
Return an iov that is valid everywhere

>>> IntervalOfValidity.always()
(0, 0, inf, inf)

Definition at line 72 of file iov.py.

72 def always():
73 """Return an iov that is valid everywhere
74
75 >>> IntervalOfValidity.always()
76 (0, 0, inf, inf)
77 """
78 return IntervalOfValidity(0, 0, -1, -1)
79

◆ contains()

def contains (   self,
  exp,
  run 
)
Check if a run is part of the validity

Definition at line 253 of file iov.py.

253 def contains(self, exp, run):
254 """Check if a run is part of the validity"""
255 return self.first <= (exp, run) <= self.final
256

◆ final()

def final (   self)
Return the final valid experiment,run

Definition at line 96 of file iov.py.

96 def final(self):
97 """Return the final valid experiment,run"""
98 return self.__final
99

◆ final_exp()

def final_exp (   self)
Return the final valid experiment

Definition at line 101 of file iov.py.

101 def final_exp(self):
102 """Return the final valid experiment"""
103 return self.__final[0]
104

◆ final_run()

def final_run (   self)
Return the final valid run

Definition at line 106 of file iov.py.

106 def final_run(self):
107 """Return the final valid run"""
108 return self.__final[1]
109

◆ first()

def first (   self)
Return the first valid experiment,run

Definition at line 81 of file iov.py.

81 def first(self):
82 """Return the first valid experiment,run"""
83 return self.__first
84

◆ first_exp()

def first_exp (   self)
Return the first valid experiment

Definition at line 86 of file iov.py.

86 def first_exp(self):
87 """Return the first valid experiment"""
88 return self.__first[0]
89

◆ first_run()

def first_run (   self)
Return the first valid run

Definition at line 91 of file iov.py.

91 def first_run(self):
92 """Return the first valid run"""
93 return self.__first[1]
94

◆ intersect()

def intersect (   self,
  other 
)
Intersection with another iov.

Will return None if the payloads don't overlap

    >>> iov1 = IntervalOfValidity(1,0,2,5)
    >>> iov2 = IntervalOfValidity(2,0,2,-1)
    >>> iov3 = IntervalOfValidity(2,10,5,-1)
    >>> iov1.intersect(iov2)
    (2, 0, 2, 5)
    >>> iov2.intersect(iov3)
    (2, 10, 2, inf)
    >>> iov3.intersect(iov1) is None
    True

Definition at line 187 of file iov.py.

187 def intersect(self, other):
188 """Intersection with another iov.
189
190 Will return None if the payloads don't overlap
191
192 >>> iov1 = IntervalOfValidity(1,0,2,5)
193 >>> iov2 = IntervalOfValidity(2,0,2,-1)
194 >>> iov3 = IntervalOfValidity(2,10,5,-1)
195 >>> iov1.intersect(iov2)
196 (2, 0, 2, 5)
197 >>> iov2.intersect(iov3)
198 (2, 10, 2, inf)
199 >>> iov3.intersect(iov1) is None
200 True
201
202 """
203 if other.first <= self.final and other.final >= self.first:
204 return IntervalOfValidity(*(max(self.first, other.first) + min(self.final, other.final)))
205 return None
206

◆ is_open()

def is_open (   self)
Check whether the iov is valid until infinity

Definition at line 258 of file iov.py.

258 def is_open(self):
259 """Check whether the iov is valid until infinity"""
260
261 return self.final == (math.inf, math.inf)
262

◆ subtract()

def subtract (   self,
  other 
)
Return a new iov with the validity of the other removed.
Will return None if everything is removed.

Warning:
    If the other iov is in the middle of the validity we will return a
    tuple of two new iovs

        >>> iov1 = IntervalOfValidity(0,0,10,-1)
        >>> iov2 = IntervalOfValidity(5,0,5,-1)
        >>> iov1 - iov2
        ((0, 0, 4, inf), (6, 0, 10, inf))

Definition at line 149 of file iov.py.

149 def subtract(self, other):
150 """Return a new iov with the validity of the other removed.
151 Will return None if everything is removed.
152
153 Warning:
154 If the other iov is in the middle of the validity we will return a
155 tuple of two new iovs
156
157 >>> iov1 = IntervalOfValidity(0,0,10,-1)
158 >>> iov2 = IntervalOfValidity(5,0,5,-1)
159 >>> iov1 - iov2
160 ((0, 0, 4, inf), (6, 0, 10, inf))
161 """
162 if other.first <= self.first and other.final >= self.final:
163 # full overlap
164 return None
165 if other.first > self.first and other.final < self.final:
166 # the one we want to remove is in the middle, return a pair of iovs
167 # by subtracting two extended once
168 iov1 = self.subtract(IntervalOfValidity(other.first + (-1, -1)))
169 iov2 = self.subtract(IntervalOfValidity((0, 0) + other.final))
170 return (iov1, iov2)
171 if other.first <= self.final and other.final >= self.first:
172 # one sided overlap, figure out which side and calculate the remainder
173 if self.first < other.first:
174 end_run = other.first_run - 1
175 end_exp = other.first_exp if end_run >= 0 else other.first_exp - 1
176 return IntervalOfValidity(self.first + (end_exp, end_run))
177 else:
178 start_run = other.final_run + 1
179 start_exp = other.final_exp
180 if math.isinf(other.final_run):
181 start_exp += 1
182 start_run = 0
183 return IntervalOfValidity((start_exp, start_run) + self.final)
184 # no overlap so return unchanged
185 return self
186

◆ tuple()

def tuple (   self)
Return the iov as a tuple with experiment/run numbers replaced with -1

This is mostly helpful where infinity is not supported and is how the
intervals are represented in the database.

    >>> a = IntervalOfValidity.always()
    >>> a
    (0, 0, inf, inf)
    >>> a.tuple
    (0, 0, -1, -1)

Definition at line 264 of file iov.py.

264 def tuple(self):
265 """Return the iov as a tuple with experiment/run numbers replaced with -1
266
267 This is mostly helpful where infinity is not supported and is how the
268 intervals are represented in the database.
269
270 >>> a = IntervalOfValidity.always()
271 >>> a
272 (0, 0, inf, inf)
273 >>> a.tuple
274 (0, 0, -1, -1)
275 """
276 return self.__first + tuple(-1 if math.isinf(x) else x for x in self.__final)
277
278

◆ union()

def union (   self,
  other,
  allow_startone = False 
)
Return the union with another iov.

    >>> iov1 = IntervalOfValidity(1,0,1,-1)
    >>> iov2 = IntervalOfValidity(2,0,2,-1)
    >>> iov3 = IntervalOfValidity(2,10,5,-1)
    >>> iov1.union(iov2)
    (1, 0, 2, inf)
    >>> iov2.union(iov3)
    (2, 0, 5, inf)
    >>> iov3.union(iov1) is None
    True

Warning:
   This method will return None if the iovs don't overlap or connect to
   each other as no union can be formed.

Parameters:
    other (IntervalOfValidity): IoV to calculate the union with
    allow_startone (bool): If True we will consider run 0 and run 1 the
        first run in an experiment. This means that if one of the iovs has
        un unlimited final run it can be joined with the other iov if the
        experiment number increases and the iov starts at run 0 and 1. If
        this is False just run 0 is considered the next run.

            >>> iov1 = IntervalOfValidity(0,0,0,-1)
            >>> iov2 = IntervalOfValidity(1,1,1,-1)
            >>> iov1.union(iov2, False) is None
            True
            >>> iov1.union(iov2, True)
            (0, 0, 1, inf)

Definition at line 207 of file iov.py.

207 def union(self, other, allow_startone=False):
208 """
209 Return the union with another iov.
210
211 >>> iov1 = IntervalOfValidity(1,0,1,-1)
212 >>> iov2 = IntervalOfValidity(2,0,2,-1)
213 >>> iov3 = IntervalOfValidity(2,10,5,-1)
214 >>> iov1.union(iov2)
215 (1, 0, 2, inf)
216 >>> iov2.union(iov3)
217 (2, 0, 5, inf)
218 >>> iov3.union(iov1) is None
219 True
220
221 Warning:
222 This method will return None if the iovs don't overlap or connect to
223 each other as no union can be formed.
224
225 Parameters:
226 other (IntervalOfValidity): IoV to calculate the union with
227 allow_startone (bool): If True we will consider run 0 and run 1 the
228 first run in an experiment. This means that if one of the iovs has
229 un unlimited final run it can be joined with the other iov if the
230 experiment number increases and the iov starts at run 0 and 1. If
231 this is False just run 0 is considered the next run.
232
233 >>> iov1 = IntervalOfValidity(0,0,0,-1)
234 >>> iov2 = IntervalOfValidity(1,1,1,-1)
235 >>> iov1.union(iov2, False) is None
236 True
237 >>> iov1.union(iov2, True)
238 (0, 0, 1, inf)
239
240 """
241 # check the trivial case of overlapping
242 if other.first <= self.final and other.final >= self.first:
243 return IntervalOfValidity(min(self.first, other.first) + max(self.final, other.final))
244 # ok, let's do the less simple case where they don't overlap but join directly
245 for i1, i2 in (self, other), (other, self):
246 if (i1.first == (i2.final_exp, i2.final_run + 1) or
247 (math.isinf(i2.final_run) and (i1.first_exp == i2.final_exp + 1) and
248 (i1.first_run == 0 or allow_startone and i1.first_run == 1))):
249 return IntervalOfValidity(i2.first + i1.final)
250 # no union possible: not directly connected and not overlapping
251 return None
252

Member Data Documentation

◆ __final

__final
private

tuple with the final valid exp, run

Definition at line 61 of file iov.py.

◆ __first

__first
private

tuple with the first valid exp, run

Definition at line 59 of file iov.py.

◆ final

final

Doxygen complains without this string.

Definition at line 261 of file iov.py.


The documentation for this class was generated from the following file: