ATLAS Offline Software
lumi.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 from DQUtils import fetch_iovs, process_iovs, IOVSet
4 
5 class UnknownTrigger(RuntimeError):
6  "Raised when an unknown trigger is requested for a time interval"
7 
8 LVL1_MENU = "COOLONL_TRIGGER::/TRIGGER/LVL1/Menu"
9 
10 def get_trigger_channel(trigger, iovrange):
11  """
12  Returns the set of iovs for which the trigger is valid
13  """
14 
15  raise NotImplementedError("Implementation incomplete")
16 
17  # First check just the first run.
18  iovs = fetch_iovs(LVL1_MENU, runs=iovrange.since.run, what=["ItemName"])
19 
20  result = [i for i in iovs if i.ItemName == trigger]
21  if not result:
22  raise UnknownTrigger()
23 
24  assert len(result) == 1, "This should not happen."
25 
26  channel = result[0].channel
27 
28  iovs = fetch_iovs(LVL1_MENU, *iovrange, channels=[channel], what=["ItemName"])
29 
30  return iovs.select(ItemName = trigger)
31 
32 def compute_lumi(lbs, lumis, iovs, exclude_iovsets=[], good_runs=None):
33  """
34  Compute luminosity for an IOVSet iovs using lbs, lumis from fetch_lumi_inputs.
35 
36  exclude_iovsets is a list of IOVSets for channels to be excluded from the
37  calculation such as not_ready, busy, etc.
38 
39  good_runs is an optional set of runs to consider, such as the set of runs
40  which are OK for physics.
41  """
42  # This is the old simple approach, which doesn't have a lot of features
43  #inputs = process_iovs(lbs, lumis, iovs)
44  #return sum((lb.EndTime - lb.StartTime)/1e9 * lumi.LBAvInstLumi
45  # #for since, until, (lb, lumi, good) in inputs
46  # #if lb and lumi and good)
47 
48  inputs = process_iovs(lbs, lumis, iovs, *exclude_iovsets)
49  total_lumi = 0
50  for since, until, states in inputs:
51  lb, lumi, good, excludes = states[0], states[1], states[2], states[3:]
52 
53  # Skip this iov if requested info not available
54  # or if any excluded channels are present
55  if not lb or not lumi or not good or any(excludes):
56  continue
57 
58  # Optional set of runs to consider. Reject if not in set
59  if good_runs and since.run not in good_runs:
60  continue
61 
62  total_lumi += (lb.EndTime - lb.StartTime)/1e9 * lumi.LBAvInstLumi
63 
64  return total_lumi
65 
66 def compute_lumi_many_channels(lbs, lumis, iovs, exclude_iovsets=[], good_runs=None):
67  """
68  Compute luminosity per channel for an IOVSet iovs using
69  lbs, lumis from fetch_lumi_inputs.
70 
71  exclude_iovsets is a list of IOVSets for channels to be excluded from the
72  calculation such as not_ready, busy, etc.
73 
74  good_runs is an optional set of runs to consider, such as the set of runs
75  which are OK for physics.
76 
77  Return type is a dictionary of {channel name: lumi}
78  """
79  # Split the IOVSet by channel
80  chans, iovsets = iovs.chans_iovsets
81  result = {}
82 
83  # Old method, keeping it here for now
84  #inputs = process_iovs(lbs, lumis, *iovsets)
85  #for since, until, states in inputs:
86  # #(lb, lumi), defects = states[:2], states[2:]
87  # #if not (lb and lumi and lumi.LBAvInstLumi):
88  # #continue
89  # #lumi = (lb.EndTime - lb.StartTime)/1e9 * lumi.LBAvInstLumi
90  # #for name, defect_iov in zip(chans, defects):
91  # #if defect_iov:
92  # #result[name] = result.get(name, 0) + lumi
93 
94  # New approach, adding new functionality
95  num_exclude = len(exclude_iovsets)
96  full_iovsets = exclude_iovsets
97  full_iovsets.extend(iovsets)
98  inputs = process_iovs(lbs, lumis, *full_iovsets)
99  for since, until, states in inputs:
100  # I find the below version conceptually cleaner
101  #(lb, lumi), excludes, defects = (states[:2], states[2:2+num_exclude],
102  # #states[2+num_exclude:])
103  (lb, lumi), defectstates = states[:2], states[2:]
104  excludes, defects = defectstates[:num_exclude], defectstates[num_exclude:]
105 
106  # Skip this iov if requested info not available
107  # or if any excluded channels are present
108  #if not (lb and lumi and lumi.LBAvInstLumi):
109  if not lb or not lumi or any(excludes):
110  continue
111 
112  # Optional set of runs to consider. Reject if not in set
113  if good_runs and since.run not in good_runs:
114  continue
115 
116  # Lumi for this lb
117  lumi = (lb.EndTime - lb.StartTime)/1e9 * lumi.LBAvInstLumi
118  # Loop over channels present, add lumi
119  for name, defect_iov in zip(chans, defects):
120  if defect_iov:
121  result[name] = result.get(name, 0) + lumi
122 
123  return result
124 
125 def fetch_lumi_inputs(range_iov, tag="OflLumi-7TeV-002"):
126  """
127  Retrieve information required to calculate the luminosity from the database
128  """
129  lbs = fetch_iovs("LBLB", *range_iov, with_channel=False)
130 
131  if tag == "ONLINE":
132  lumis = fetch_iovs("COOLONL_TRIGGER::/TRIGGER/LUMI/OnlPrefLumi",
133  *range_iov,
134  channels=[0])
135 
136  # Select valid
137  lumis = IOVSet(l for l in lumis if (l.Valid & 0xFFFF) % 10 == 0)
138  else:
139  # Apparently this string changes from time to time...
140  lumi_folder = "COOLOFL_TRIGGER::/TRIGGER/OFLLUMI/OflPrefLumi" # Run-2
141  #lumi_folder = "COOLOFL_TRIGGER::/TRIGGER/OFLLUMI/LBLESTOFL" # Run-1
142  lumis = fetch_iovs(lumi_folder,
143  *range_iov,
144  tag=tag,
145  channels=[0])
146 
147 
148  return lbs, lumis
python.lumi.compute_lumi_many_channels
def compute_lumi_many_channels(lbs, lumis, iovs, exclude_iovsets=[], good_runs=None)
Definition: lumi.py:66
python.db.fetch_iovs
def fetch_iovs(folder_name, since=None, until=None, channels=None, tag="", what="all", max_records=-1, with_channel=True, loud=False, database=None, convert_time=False, named_channels=False, selection=None, runs=None, with_time=False, unicode_strings=False)
Definition: DQUtils/python/db.py:67
python.lumi.fetch_lumi_inputs
def fetch_lumi_inputs(range_iov, tag="OflLumi-7TeV-002")
Definition: lumi.py:125
python.lumi.get_trigger_channel
def get_trigger_channel(trigger, iovrange)
Definition: lumi.py:10
python.lumi.UnknownTrigger
Definition: lumi.py:5
python.events.process_iovs
def process_iovs(*iovsets)
Definition: events.py:30
python.lumi.compute_lumi
def compute_lumi(lbs, lumis, iovs, exclude_iovsets=[], good_runs=None)
Definition: lumi.py:32