Belle II Software development
caf_svd_hotstrips.py
1
8'''
9Script to perform the svd hot-strips calibration.
10It identifies the hot strips using the criteria in defined in SVDHotStripsCalibrationsAlgorithm.
11This calibration is run manually on pedestal runs (runs without beams and detector on PEAK).
12
13b2caf-prompt-run Local config.json inputs.json --permissive
14
15The location of the steering file caf_svd_hotstrips.py must be specified in
16the json configuration file, config.json, e.g.
17
18{"caf_script": "/home/belle2/lgcorona/basf2_2/svd/scripts/caf/caf_svd_hotstrips.py", ...}
19'''
20
21import basf2 as b2
22
23import sys
24import datetime
25
26from ROOT.Belle2 import SVDHotStripsCalibrationsAlgorithm
27
28from caf.framework import Calibration
29from caf import strategies
30from caf.utils import IoV
31from prompt import CalibrationSettings
32
33import rawdata as raw
34
35b2.set_log_level(b2.LogLevel.INFO)
36
37now = datetime.datetime.now()
38
39input_branches = ['RawSVDs']
40
41settings = CalibrationSettings(name="caf_svd_hotstrips",
42 expert_username="lgcorona",
43 description=__doc__,
44 input_data_formats=["raw"],
45 input_data_names=["beam"],
46 expert_config={
47 "snrThreshold": 5,
48 "computeAverageOccupancyPerChip": False,
49 "relativeOccupancyThreshold": 5.0,
50 "absoluteOccupancyThreshold": 0.2,
51 "skipHLTRejectedEvents": False
52 })
53
54
55def create_collector(name="SVDOccupancyCalibrationsCollector",
56 svdShaperDigits="SVDShaperDigits",
57 skipHLTRejectedEvents=False):
58 """
59 Simply creates a SVDOccupancyCalibrationsCollector module with some options.
60
61 Parameters:
62 name: name of the collector to run
63 svdShaperDigits: name of the SVDShaperDigits store object to use as input
64
65 Returns:
66 pybasf2.Module
67 """
68
69 collector = b2.register_module('SVDOccupancyCalibrationsCollector')
70 collector.param("SVDShaperDigitsName", svdShaperDigits)
71 collector.param("skipHLTRejectedEvents", skipHLTRejectedEvents)
72
73 return collector
74
75
76def create_algorithm(unique_id,
77 computeAvgOccupancyPerChip=False,
78 relativeOccupancyThreshold=5.,
79 absoluteOccupancyThreshold=0.2):
80 """
81 Simply creates a SVDHotStripsCalibrationsAlgorithm class.
82
83 Parameters:
84 unique_id: name of the uniqueID written in the payload to identify it
85 computeAvgOccupancyPerChip: true, compute the average occupancy per chip;
86 false, compute the average occupancy per sensor/side
87 relativeOccupancyThreshold: relative occupancy threshold wrt the average sensor/side
88 or chip occupancy to define a strip as hot
89 absoluteOccupancyThreshold: absolute occupancy threshold to define a strip as hot
90
91 Returns:
92 ROOT.Belle2.SVDHotStripsCalibrationAlgorithm
93 """
94
95 algorithm = SVDHotStripsCalibrationsAlgorithm(unique_id)
96 algorithm.computeAverageOccupancyPerChip(computeAvgOccupancyPerChip)
97 algorithm.setRelativeOccupancyThreshold(relativeOccupancyThreshold)
98 algorithm.setAbsoluteOccupancyThreshold(absoluteOccupancyThreshold)
99
100 return algorithm
101
102
103def crate_svd_zerosuppression(svdShaperDigits="SVDShaperDigits",
104 svdShaperDigitsOutput="SVDShaperDigitsZS",
105 snrThreshold=5,
106 fadcMode=True):
107 """
108 Simply creates a SVDZeroSuppressionEmulator module with some options.
109
110 Parameters:
111 svdShaperDigits: name of the input SVDShaperDigits store object
112 svdShaperDigitsOutput: name of the output SVDShaperDigits store object.
113 Kept shaper digits are selected with snrThreshold
114 snrThreshold: signal-to-noise ratio treshold to select strips
115 fadcMode: if true, the approximation to integer for the minimum signal-to-noise
116 ratio (int(snrThreshold*strip_noise + 0.5)) is done. This is the same algorithm
117 applied on the FADC
118
119 Returns:
120 pybasf2.Module
121 """
122
123 svdZSemulator = b2.register_module("SVDZeroSuppressionEmulator")
124 svdZSemulator.param("SNthreshold", snrThreshold)
125 svdZSemulator.param("ShaperDigits", svdShaperDigits)
126 svdZSemulator.param("ShaperDigitsIN", svdShaperDigitsOutput)
127 svdZSemulator.param("FADCmode", fadcMode)
128
129 return svdZSemulator
130
131
132def create_pre_collector_path(svdShaperDigits="SVDShaperDigits",
133 svdShaperDigitsOutput="SVDShaperDigitsZS",
134 snrThreshold=5,
135 fadcMode=True):
136 """
137 Create a basf2 path that runs the unpacker and zero suppression emulator.
138
139 Returns:
140 pybasf2.Path
141 """
142
143 # Set-up re-processing path
144 path = b2.create_path()
145 path.add_module('Progress')
146
147 # Remove all non-raw data to run the full reco again
148 path.add_module('RootInput', branchNames=input_branches)
149
150 path.add_module("Gearbox")
151 path.add_module("Geometry", useDB=True)
152 raw.add_unpackers(path, components=['SVD'])
153 svdZSemulator = crate_svd_zerosuppression(svdShaperDigits=svdShaperDigits,
154 svdShaperDigitsOutput=svdShaperDigitsOutput,
155 snrThreshold=snrThreshold,
156 fadcMode=fadcMode)
157 path.add_module(svdZSemulator)
158
159 return path
160
161
162def get_calibrations(input_data, **kwargs):
163 """
164 Simply creates the calibrations to be run in the caf, and returns a list of calibrations.
165
166 Parameters:
167 input_data: input_data defined in the json file
168
169 Returns:
170 pybasf2.list
171 """
172
173 file_to_iov = input_data["beam"]
174 input_files = list(file_to_iov.keys())
175
176 expert_config = kwargs.get("expert_config")
177 snrThreshold = expert_config["snrThreshold"]
178 computeAverageOccupancyPerChip = expert_config["computeAverageOccupancyPerChip"]
179 relativeOccupancyThreshold = expert_config["relativeOccupancyThreshold"]
180 absoluteOccupancyThreshold = expert_config["absoluteOccupancyThreshold"]
181 skipHLTRejectedEvents = expert_config["skipHLTRejectedEvents"]
182
183 avgOcc = "avgOccPerSensor"
184 if (computeAverageOccupancyPerChip):
185 avgOcc = "avgOccPerChip"
186
187 exps = [i.exp_low for i in file_to_iov.values()]
188 runs = sorted([i.run_low for i in file_to_iov.values()])
189
190 firstRun = runs[0]
191 lastRun = runs[-1]
192 expNum = exps[0]
193
194 if not len(input_files):
195 print("No good input files found! Check that the input files have entries != 0!")
196 sys.exit(1)
197
198 uniqueID = f"SVDHotStripsCalibrations_{now.isoformat()}_INFO:"\
199 f"_ZS{snrThreshold}_{avgOcc}_relOccThr={relativeOccupancyThreshold}"\
200 f"_absOccThr={absoluteOccupancyThreshold}_Exp{expNum}_runsFrom{firstRun}to{lastRun}"
201 print(f"\nUniqueID:\n{uniqueID}")
202
203 requested_iov = kwargs.get("requested_iov", None)
204 output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, requested_iov.exp_high, -1)
205
206 pre_collector_path = create_pre_collector_path(snrThreshold=snrThreshold)
207
208 coll = create_collector(name="SVDOccupancyCalibrationsCollector",
209 svdShaperDigits="SVDShaperDigitsZS",
210 skipHLTRejectedEvents=skipHLTRejectedEvents)
211
212 algo = create_algorithm(uniqueID,
213 computeAverageOccupancyPerChip,
214 relativeOccupancyThreshold,
215 absoluteOccupancyThreshold)
216
217 calibration = Calibration("SVDHotStripsCalibrations",
218 collector=coll,
219 algorithms=[algo],
220 input_files=input_files,
221 pre_collector_path=pre_collector_path)
222
223 calibration.strategies = strategies.SequentialRunByRun
224
225 for algorithm in calibration.algorithms:
226 algorithm.params = {"iov_coverage": output_iov}
227
228 return [calibration]