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