ATLAS Offline Software
iovset.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
2 
3 
4 from collections import defaultdict
5 from pickle import load, dump, loads
6 from sys import stdout
7 
8 from ..general import interleave
9 from ..utils import pprint_objects
10 
11 from .runlumi import RunLumi
12 from .iovtype import RANGEIOV_VAL, make_iov_type
13 
14 
15 def restore_iovset(cls, name, variables, elements):
16  """
17  Rebuild a pickled IOVSet
18  """
19  iov_type = make_iov_type(name, variables)
20  return cls(map(iov_type._make, elements))
21 
22 class IOVSet(list):
23  def __init__(self, *args, **kwargs):
24  self.iov_type = kwargs.pop("iov_type", None)
25  self.origin = kwargs.pop("origin", None)
26  self.parent = kwargs.pop("parent", None)
27  from sys import _getframe
28  f = _getframe(1)
29  self.constructed_at = "%s:%i" % (f.f_code.co_filename, f.f_lineno)
30  super(IOVSet, self).__init__(*args, **kwargs)
31  if self.iov_type is None and self:
32  self.iov_type = type(self.first)
33 
34  def logical_not(self):
35  from ..events import process_iovs
36  cls = type(self)
37  alliov = cls([RANGEIOV_VAL(RunLumi(0), RunLumi(0xFFFFFFFFFFFFFFFF))])
38  events = process_iovs(alliov, self)
39  return cls(RANGEIOV_VAL(since, until)
40  for since, until, (_, state) in events if not state)
41 
42  @classmethod
43  def logical_or(cls, *rhs_iovsets):
44  """
45  Gives the IOV ranges which are present in both this IOVSet and `rhs`
46  """
47  # Import goes here to prevent circular imports
48  from ..events import process_iovs
49  result = cls()
50  for since, until, iovsets in process_iovs(*rhs_iovsets):
51  if any(iovsets):
52  result.add(since, until)
53  return result.solidify(RANGEIOV_VAL)
54 
55  @classmethod
56  def logical_and(cls, *rhs_iovsets):
57  """
58  Gives the IOV ranges which are present in both this IOVSet and `rhs`
59  """
60  # Import goes here to prevent circular imports
61  from ..events import process_iovs
62  result = cls()
63  for since, until, iovsets in process_iovs(*rhs_iovsets):
64  if all(iovsets):
65  result.add(since, until)
66  return result.solidify(RANGEIOV_VAL)
67 
68  def __or__(self, rhs):
69  # Note: classmethod
70  return self.logical_or(self, rhs)
71 
72  def __and__(self, rhs):
73  # Note: classmethod
74  return self.logical_and(self, rhs)
75 
76  @classmethod
77  def from_iovsets(cls, iovsets):
78  """
79  Construct one IOVSet from many iovsets
80  """
81  iovsets = list(iovsets)
82  if not iovsets:
83  return cls()
84  types = set(iovset.iov_type for iovset in iovsets)
85  assert len(types) == 1
86  origins = [i.origin for i in iovsets]
87  parents = [i.parent for i in iovsets]
88  iov_gen = (iov for iovset in iovsets for iov in iovset)
89  return cls(iov_gen, iov_type=types.pop(), origin=origins, parent=parents)
90 
91  def connect_adjacent(self):
92  from ..iov_arrangement import connect_adjacent_iovs
93  return connect_adjacent_iovs(self)
94 
95  def pprint(self, where=stdout):
96  pprint_objects(self, where)
97 
98  @property
99  def ordered(self):
100  prev_until = None
101  for iov in self:
102  if iov.since > iov.until:
103  return False
104  if prev_until is not None and iov.since < prev_until:
105  return False
106  prev_until = iov.until
107  return True
108 
109  def to_file(self, filename):
110  with open(filename, "wb") as fd:
111  dump(self, fd)
112 
113  @classmethod
114  def from_file(cls, filename):
115  with open(filename, "rb") as fd:
116  if filename.endswith(".bz2"):
117  return loads(fd.read().decode("bz2"))
118  return load(fd)
119 
120  @classmethod
121  def from_grl_string(cls, data):
122  from ..grl import load_grl_string
123  return load_grl_string(data, IOVSet_class=cls)
124 
125  @classmethod
126  def from_grl(cls, filename):
127  with open(filename, "rb") as fd:
128  return cls.from_grl_string(fd.read())
129 
130  def to_grl_string(self, name="unknown", version="unknown"):
131  from ..grl import make_grl
132  return make_grl(self, name, version)
133 
134  def to_grl(self, filename, name="unknown", version="unknown"):
135  with open(filename, "w") as fd:
136  fd.write(self.to_grl_string(name, version))
137 
138  @classmethod
139  def from_runs(cls, runs):
140  return IOVSet(RANGEIOV_VAL(RunLumi(r, 0), RunLumi(r+1, 0)-1)
141  for r in sorted(runs))
142 
143  @property
144  def chans_iovsets(self):
145  """
146  Returns ([channel1, c2, c3, ...], [channel 1 iovs, c2iovs, c3iovs, ...])
147  """
148  if not self:
149  return [], []
150  return zip(*sorted(self.by_channel.items()))
151 
152  def empty(self, content=None):
153  """
154  Return an empty IOVSet, but keeping any metadata around. (Such as the
155  IOVType we were holding..)
156  """
157  return self.empty_maker()([] if content is None else content)
158 
159  def empty_maker(self):
160  """
161  Indirection is used here in order to create new empty instances on
162  demand without keeping a reference to the original object alive.
163  """
164  iov_type = self.iov_type
165  origin = self.origin
166  def empty(content=None):
167  return type(self)([] if content is None else content,
168  iov_type=iov_type, origin=origin, parent=self)
169  return empty
170 
171  def __reduce__(self):
172  """
173  Make an IOVSet pickleable (beware limitations)
174  """
175  types = set(type(x) for x in self)
176  if not types:
177  return IOVSet, ()
178 
179  assert len(types) == 1, (
180  "Can only pickle IOVSets with only one type (got types=%r)" % types)
181 
182  iov_type = type(self.first)
183  name = iov_type.__name__
184  variables = iov_type._fields[2:]
185 
186  return restore_iovset, (type(self), name, variables, map(tuple, self))
187 
188  def __hash__(self):
189  return hash(tuple(self))
190 
191  def __repr__(self):
192  if self.time_based:
193  args = (len(self), self.duration, len(self.channels),
194  ("%.2f" % (self.duration / len(self.channels)))
195  if self.channels else "N/A")
196  plurals = ["" if x == 1 else "s" for x in args]
197  args = tuple(interleave(args, plurals))
198  return ("<%i IoV%s %.2f hour%s %i channel%s (avg=%s hr%s/c)>"
199  % args)
200 
201  args = len(self), self.lb_counts, len(self.runs), len(self.channels)
202  plurals = ["" if x == 1 else "s" for x in args]
203  args = tuple(interleave(args, plurals))
204  return "<%i IoV%s %i lb%s %i run%s %i channel%s>" % args
205 
206  def add(self, since, until, *args):
207  args = list(args)
208  if self and self[-1][1] == since and self[-1][2:] == args:
209  # Last until == since and the rest of the thing matches
210  #self[-1] = self[-1]._replace(until=until)
211  self[-1][1] = until
212  else:
213  self.append([since, until] + args)
214 
215  def solidify(self, iov_type):
216  """
217  Because mutating lists is faster, once building an IOVSet is complete,
218  it should be 'solidified' into the desired IOV type
219  """
220  self.iov_type = type
221  return IOVSet(map(iov_type._make, self))
222 
223  @property
224  def trim_iovs(self):
225  """
226  Ensure all IoVs start on lumiblock 1.
227  """
228  return self.empty(iov.trimmed for iov in self)
229 
230  def add_old(self, iov):
231  """
232  Extends this result set by one iov. If it is adjacent (and equal)
233  to the previous IoV, then that IoV is extended instead.
234 
235  This was deprecated because it is too slow compared to add() and solidify().
236  """
237  if self and self.last.connected_to(iov):
238  self[-1] = self[-1].merge(iov)
239  else:
240  self.append(iov)
241 
242  @property
243  def time_based(self):
244  """
245  Looks at the first IoV to see if it is time based
246  """
247  if not self:
248  return False
249  try:
250  return self.first.is_time_based
251  except AttributeError:
252  return False
253 
254  @property
255  def lb_counts(self):
256  """
257  Sum of the LB counts
258  """
259  return sum(iov.length for iov in self)
260 
261  @property
262  def duration(self):
263  """
264  Duration of the sum of the time-based IoVs, in hours.
265  """
266  return self.lb_counts / 1e9 / 3600
267 
268  def __getslice__(self, *args):
269  """
270  Slicing an IOVSet should return an IOVSet
271  """
272  return self.__class__(super(IOVSet, self).__getslice__(*args))
273 
274  @property
275  def runs(self):
276  """
277  The set of runs present in this IOVSet
278  """
279  return set(iov.since.run for iov in self)
280 
281  @property
282  def by_run(self):
283  """
284  Return a dictionary representing {run : iovs in run}
285  """
286  result = defaultdict(IOVSet)
287  for iov in self:
288  result[iov.run].append(iov)
289  return dict(result)
290 
291  @property
292  def channels(self):
293  """
294  The set of channels this IOVSet represents
295  """
296  if not self or not hasattr(self[0], "channel"):
297  return set()
298  return set(iov.channel for iov in self)
299 
300  @property
301  def by_channel(self):
302  """
303  Return a dictionary representing {channels : iovs with channelid}
304  """
305  # Import here to prevent circular imports
306  from ..iov_arrangement import split_by_channel
307  return split_by_channel(self)
308 
309  @property
310  def first(self):
311  "The first IoV in the set"
312  assert self, (".first used in an empty IoV set. Is the range you are "
313  "trying to query valid?")
314  return self[0]
315 
316  @property
317  def last(self):
318  "The last IoV in the set"
319  assert self, (".last used in an empty IoV set. Is the range you are "
320  "trying to query valid?")
321  return self[-1]
322 
323  @property
324  def range_iov(self):
325  """
326  Returns an IoV object which represents the maximum range contained by
327  the IoVs.
328  """
329  since = min(i.since for i in self)
330  until = max(i.until for i in self)
331  return RANGEIOV_VAL(since, until)
332 
333  def intersect_range(self, iov_range):
334  """
335  Returns a new IOVSet intersected with `iov_range` (since, until)
336  """
337  since, until = iov_range
338  iov_range = RANGEIOV_VAL(RunLumi(since), RunLumi(until))
339 
340  intersected = (iov.intersect(iov_range) for iov in self)
341  return self.empty(iov for iov in intersected if iov)
342 
343  def select_runs(self, *selected):
344  """
345  Pick IoVs which are in the set of runs `selected`
346  """
347  selected = set(selected)
348  return self.empty(iov for iov in self
349  if any(run in selected for run in iov.runs))
350 
351  def select_channels(self, *selected):
352  """
353  Pick IoVs which are in the set of channels `selected`
354  """
355  selected = set(selected)
356  return self.empty(iov for iov in self if iov.channel in selected)
357 
358  def select(self, **what):
359  def selected(iov):
360  return all(getattr(iov, key) == value
361  for key, value in what.iteritems())
362 
363  return self.empty(iov for iov in self if selected(iov))
364 
365 
python.sugar.iovset.IOVSet.logical_not
def logical_not(self)
Definition: iovset.py:34
python.sugar.iovset.IOVSet.trim_iovs
def trim_iovs(self)
Definition: iovset.py:224
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename R::value_type > sorted(const R &r, PROJ proj={})
Helper function to create a sorted vector from an unsorted range.
python.sugar.iovset.IOVSet.select_runs
def select_runs(self, *selected)
Definition: iovset.py:343
AtlasMcWeight::decode
double decode(number_type binnedWeight)
Convert weight from unsigned to double.
Definition: AtlasMcWeight.cxx:32
python.sugar.iovset.IOVSet.intersect_range
def intersect_range(self, iov_range)
Definition: iovset.py:333
python.sugar.iovset.IOVSet.logical_or
def logical_or(cls, *rhs_iovsets)
Definition: iovset.py:43
python.sugar.iovset.IOVSet.__repr__
def __repr__(self)
Definition: iovset.py:191
python.sugar.iovset.IOVSet.__hash__
def __hash__(self)
Definition: iovset.py:188
python.sugar.iovset.IOVSet.solidify
def solidify(self, iov_type)
Definition: iovset.py:215
python.sugar.iovset.restore_iovset
def restore_iovset(cls, name, variables, elements)
Definition: iovset.py:15
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
python.sugar.iovset.IOVSet.from_runs
def from_runs(cls, runs)
Definition: iovset.py:139
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
python.sugar.iovtype.RANGEIOV_VAL
def RANGEIOV_VAL()
Definition: iovtype.py:152
python.sugar.iovset.IOVSet.from_file
def from_file(cls, filename)
Definition: iovset.py:114
python.grl.load_grl_string
def load_grl_string(data, IOVSet_class=IOVSet)
Definition: DQUtils/python/grl.py:42
python.sugar.iovset.IOVSet.from_iovsets
def from_iovsets(cls, iovsets)
Definition: iovset.py:77
python.sugar.iovset.IOVSet.constructed_at
constructed_at
Definition: iovset.py:29
CaloClusterListBadChannel.cls
cls
Definition: CaloClusterListBadChannel.py:8
python.sugar.iovset.IOVSet.empty
def empty(self, content=None)
Definition: iovset.py:152
python.sugar.iovset.IOVSet.to_file
def to_file(self, filename)
Definition: iovset.py:109
python.sugar.iovset.IOVSet.first
def first(self)
Definition: iovset.py:310
python.sugar.iovset.IOVSet.chans_iovsets
def chans_iovsets(self)
Definition: iovset.py:144
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
python.sugar.iovset.IOVSet.by_run
def by_run(self)
Definition: iovset.py:282
python.sugar.iovset.IOVSet.range_iov
def range_iov(self)
Definition: iovset.py:324
python.sugar.iovset.IOVSet.add_old
def add_old(self, iov)
Definition: iovset.py:230
python.sugar.iovset.IOVSet.__getslice__
def __getslice__(self, *args)
Definition: iovset.py:268
run_Egamma1_LArStrip_Fex.dump
dump
Definition: run_Egamma1_LArStrip_Fex.py:87
python.sugar.runlumi.RunLumi
RunLumi
Definition: runlumi.py:130
python.sugar.iovset.IOVSet.from_grl
def from_grl(cls, filename)
Definition: iovset.py:126
python.iov_arrangement.split_by_channel
def split_by_channel(iovs)
Definition: iov_arrangement.py:20
python.sugar.iovset.IOVSet.to_grl
def to_grl(self, filename, name="unknown", version="unknown")
Definition: iovset.py:134
python.sugar.iovset.IOVSet.to_grl_string
def to_grl_string(self, name="unknown", version="unknown")
Definition: iovset.py:130
convertTimingResiduals.sum
sum
Definition: convertTimingResiduals.py:55
python.sugar.iovset.IOVSet.add
def add(self, since, until, *args)
Definition: iovset.py:206
python.utils.pprint_objects
def pprint_objects(objects, where=stdout)
Definition: DataQuality/DQUtils/python/utils.py:128
python.general.interleave
def interleave(*args)
Definition: general.py:169
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
python.sugar.iovset.IOVSet.pprint
def pprint(self, where=stdout)
Definition: iovset.py:95
python.events.process_iovs
def process_iovs(*iovsets)
Definition: events.py:30
python.sugar.iovset.IOVSet.iov_type
iov_type
Definition: iovset.py:24
python.iov_arrangement.connect_adjacent_iovs
def connect_adjacent_iovs(generator)
Definition: iov_arrangement.py:66
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
python.sugar.iovset.IOVSet.time_based
def time_based(self)
Definition: iovset.py:243
python.sugar.iovset.IOVSet.channels
def channels(self)
Definition: iovset.py:292
python.sugar.iovset.IOVSet.__and__
def __and__(self, rhs)
Definition: iovset.py:72
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:71
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:67
python.sugar.iovset.IOVSet.by_channel
def by_channel(self)
Definition: iovset.py:301
python.sugar.iovset.IOVSet.select_channels
def select_channels(self, *selected)
Definition: iovset.py:351
Trk::open
@ open
Definition: BinningType.h:40
python.sugar.iovset.IOVSet.duration
def duration(self)
Definition: iovset.py:262
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:108
python.grl.make_grl
def make_grl(iovset, name="unknown", version="unknown")
Definition: DQUtils/python/grl.py:55
python.sugar.iovset.IOVSet.__or__
def __or__(self, rhs)
Definition: iovset.py:68
python.sugar.iovset.IOVSet.__init__
def __init__(self, *args, **kwargs)
Definition: iovset.py:23
python.sugar.iovtype.make_iov_type
def make_iov_type(name, variables, bases=(IOVType,), _memoized={})
Definition: iovtype.py:113
python.sugar.iovset.IOVSet.from_grl_string
def from_grl_string(cls, data)
Definition: iovset.py:121
python.sugar.iovset.IOVSet.parent
parent
Definition: iovset.py:26
python.sugar.iovset.IOVSet.empty_maker
def empty_maker(self)
Definition: iovset.py:159
python.sugar.iovset.IOVSet.origin
origin
Definition: iovset.py:25
python.sugar.iovset.IOVSet.select
def select(self, **what)
Definition: iovset.py:358
python.sugar.iovset.IOVSet.__reduce__
def __reduce__(self)
Definition: iovset.py:171
python.sugar.iovset.IOVSet
Definition: iovset.py:22
python.sugar.iovset.IOVSet.lb_counts
def lb_counts(self)
Definition: iovset.py:255
python.sugar.iovset.IOVSet.logical_and
def logical_and(cls, *rhs_iovsets)
Definition: iovset.py:56
python.root_pickle.load
def load(f, use_proxy=1, key=None)
Definition: root_pickle.py:430
python.sugar.iovset.IOVSet.runs
def runs(self)
Definition: iovset.py:275
python.sugar.iovset.IOVSet.last
def last(self)
Definition: iovset.py:317
python.sugar.iovset.IOVSet.ordered
def ordered(self)
Definition: iovset.py:99
merge
Definition: merge.py:1
python.sugar.iovset.IOVSet.connect_adjacent
def connect_adjacent(self)
Definition: iovset.py:91