ATLAS Offline Software
Loading...
Searching...
No Matches
iov_truncator.py
Go to the documentation of this file.
1#! /usr/bin/env python
2
3# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
4
5from collections import namedtuple
6
7from .sugar import RunLumi
8from .events import iov_yielder
9
10try:
11 from .db import fetch_iovs
12except ImportError:
13 def rlumi(run, lumi):
14 return run << 32 | lumi
15
16 def un_rlumi(x):
17 return x >> 32, x & 0xFFFFFFFF
18
19 def fetch_iovs(*args, **kwargs):
20 """
21 A dummy fetch_iovs for testing. Returns two runs, one 100 LBs long
22 and the other 50 long.
23 """
24 T = namedtuple("EOR_VAL", "since, until RunNumber")
25
26 return map(T._make, [(rlumi( 1, 0), rlumi(1, 100), 1),
27 (rlumi( 2, 0), rlumi(2, 50), 2),
28 (rlumi(100, 0), rlumi(100, 10), 100),
29 (rlumi(101, 0), rlumi(101, 0xFFFFFFFF), 101)])
30
31def fix_iov_lengths(iovs, run_lengths):
32 """
33 Truncate input iovs so that their length does not exceed the length
34 of the run.
35
36 Also clean up records which go from (run, 0) to (run+1, 0)
37
38 `run_lengths` should be a dictionary {run_number: lumiblock count}
39 """
40 def fix_iov(iov):
41 """
42 Given an iov, correct its since and until if necessary
43 """
44 run = iov.since.run
45
46 if iov.since.run == iov.until.run-1 and iov.until.lumi == 0:
47 iov = iov._replace(until=RunLumi(run, 0xFFFFFFFF))
48
49 if run in run_lengths:
50 run_length = run_lengths[run]
51 if iov.until.lumi > run_length:
52 iov = iov._replace(until=RunLumi(run, run_length))
53
54 if iov.since >= iov.until:
55 return None
56
57 return iov
58
59 return [_ for _ in map(fix_iov, iovs) if _ is not None]
60
61def make_run_iovs(iovs):
62 # Find the minimum and maximum extent for this set of iovs
63 since = min(min(o.since for o in objects) for objects in iovs)
64 until = max(max(o.until for o in objects) for objects in iovs)
65
66 run_iovs = fetch_iovs("EOR", since, until,
67 with_channel=False, what=[])
68
69 from .oracle import atlas_runs_set
70 atlas_runs = atlas_runs_set()
71
72 run_iovs = (iov for iov in run_iovs if iov.since.run in atlas_runs)
73 return run_iovs
74
76 """
77 Given a set of iovs
78 """
79
80 run_iovs = make_run_iovs(iovs)
81 return truncate_to_run_iovs(run_iovs, *iovs)
82
83def truncate_to_run_iovs(run_iovs, *iovs):
84 result_iovs = [[] for i in iovs]
85 active_states, ended_states = [set() for i in iovs], [set() for i in iovs]
86
87 def bind_to_run(run_iov, active_states):
88 """
89 Given a run_iov and a set of active iovs, emit iovs which are bound
90 to this run.
91 """
92 for active_state in sorted(active_states):
93 iov = active_state._replace(
94 since=max(run_iov.since+1, active_state.since),
95 until=min(run_iov.until, active_state.until))
96
97 if iov.since != iov.until:
98 # Prevent zero-length iovs from being emitted
99 yield iov
100
101 for position, index, beginning, iov in iov_yielder(run_iovs, *iovs):
102 if index == 0:
103 # Run events
104 if beginning:
105 # Run start
106 # * Invalidate ended iovs
107 # * Clear sets of ended iovs
108 for active, ended in zip(active_states, ended_states):
109 active.difference_update(ended)
110 ended.clear()
111 else:
112 # Run end - Intersect active iovs for each channel with this run
113 # - Results are stored
114 for i, chan_active_states in enumerate(active_states):
115 result_iovs[i].extend(bind_to_run(iov, chan_active_states))
116 else:
117 # IOV events
118 index -= 1
119 # Add current iov to active states if it has just started, otherwise
120 # ended states.
121 action = active_states[index] if beginning else ended_states[index]
122 action.add(iov)
123
124 return result_iovs
125
127
128 IOV = namedtuple("IOV", "since until channel state")
129 GOOD = True
130 BAD = False
131 A, B = 1, 2
132
133 def __repr__(self):
134 """
135 A pretty convertor for (since, until)
136 """
137 args = un_rlumi(self.since) + un_rlumi(self.until) + (
138 self.channel, self.state)
139
140 return "IOV(since=(%i, %i), until=(%i, %i), channel=%i, state=%s)" % args
141 IOV.__repr__ = __repr__
142
143 iovs = [
144 IOV(0, 1, A, GOOD),
145 IOV(rlumi( 0, 0), rlumi(2**31, 0), A, GOOD),
146 IOV(rlumi( 0, 0), rlumi(100, 0), B, GOOD),
147 IOV(rlumi(100, 0), rlumi(2**31, 0), B, BAD),
148 IOV(rlumi(101, 0), rlumi(101, 100), A, GOOD),
149 IOV(rlumi(101, 0), rlumi(101, 0), B, BAD),
150 ]
151
152 result = truncate_to_run_iovs(iovs)
153
154 print(len(result))
155
156 from pprint import pprint
157
158 pprint(result)
159
160if __name__ == "__main__":
161
void print(char *figname, TCanvas *c1)
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
STL class.
STL class.
fetch_iovs(*args, **kwargs)
truncate_to_run_iovs(run_iovs, *iovs)
fix_iov_lengths(iovs, run_lengths)