Belle II Software development
commondqm.py
1#!/usr/bin/env python3
2
3
10
11import basf2 as b2
12from svd import add_svd_create_recodigits
13from svd.dqm_utils import add_svd_dqm_dose
14from geometry import check_components
15from analysisDQM import add_analysis_dqm, add_mirabelle_dqm
16import neurotrigger
17
18
19def add_common_dqm(path, components=None, dqm_environment="expressreco", dqm_mode="dont_care", create_hlt_unit_histograms=False):
20 """
21 This function adds DQMs which are common for Cosmic runs and Collion runs
22
23 @param components: A list of the detector components which are available in this
24 run of basf2
25 @param dqm_environment: The environment the DQM modules are running in
26 "expressreco" (default) if running on the ExpressReco system
27 "hlt" if running on the HLT online reconstructon nodes
28 If running on the hlt, you may want to output less or other DQM plots
29 due to the limited bandwidth of the HLT nodes.
30 @param dqm_mode: How to split up the path for online/HLT.
31 For dqm_mode == "dont_care" all the DQM modules should be added.
32 For dqm_mode == "all_events" only the DQM modules which should run on all events
33 (filtered and dismissed) should be added
34 For dqm_mode == "before_reco" only the DQM modules which should run before
35 all reconstruction
36 For dqm_mode == "filtered" only the DQM modules which should run on filtered
37 events should be added
38 @param create_hlt_unit_histograms: Parameter for SoftwareTiggerHLTDQMModule.
39 Should be True only when running on the HLT servers
40 """
41 assert dqm_mode in ["dont_care", "all_events", "filtered", "before_filter"]
42 # Check components.
43 check_components(components)
44
45 if dqm_mode in ["dont_care", "filtered"]:
46 # TTD trigger and bunch injection monitoring
47 path.add_module('TTDDQM')
48
49 if dqm_environment == "expressreco" and (dqm_mode in ["dont_care"]):
50 # PXD (not useful on HLT)
51 if components is None or 'PXD' in components:
52 path.add_module('PXDDAQDQM', histogramDirectoryName='PXDDAQ')
53 path.add_module('PXDROIDQM', histogramDirectoryName='PXDROI')
54 path.add_module('PXDDQMExpressReco', histogramDirectoryName='PXDER')
55 path.add_module('SetupGenfitExtrapolation')
56 path.add_module('PXDROIFinder',
57 recoTrackListName='RecoTracks',
58 PXDInterceptListName='PXDIntercepts')
59 # moved to cosmics/collision as we need different cuts
60 # path.add_module('PXDDQMEfficiency', histogramDirectoryName='PXDEFF')
61 path.add_module('PXDTrackClusterDQM', histogramDirectoryName='PXDER')
62 path.add_module('PXDInjectionDQM', histogramDirectoryName='PXDINJ', eachModule=True)
63 # SVD
64 if components is None or 'SVD' in components:
65 # reconstruct SVDRecoDigits first of all
66 add_svd_create_recodigits(path)
67
68 # SVD DATA FORMAT
69 svdunpackerdqm = b2.register_module('SVDUnpackerDQM')
70 path.add_module(svdunpackerdqm)
71 # offline ZS emulator
72 path.add_module(
73 'SVDZeroSuppressionEmulator',
74 SNthreshold=5,
75 ShaperDigits='SVDShaperDigits',
76 ShaperDigitsIN='SVDShaperDigitsZS5',
77 FADCmode=True)
78 # SVD Occupancy after Injection
79 path.add_module('SVDDQMInjection', ShaperDigits='SVDShaperDigitsZS5')
80 # SVDDQMExpressReco General
81 path.add_module('SVDDQMExpressReco',
82 offlineZSShaperDigits='SVDShaperDigitsZS5')
83 # SVD HIT TIME
84 path.add_module('SVDDQMHitTime')
85 # SVD EFFICIENCY
86 path.add_module('SetupGenfitExtrapolation')
87 path.add_module('SVDROIFinder',
88 recoTrackListName='RecoTracks',
89 SVDInterceptListName='SVDIntercepts')
90 path.add_module('SVDDQMEfficiency')
91 # SVD CLUSTERS ON TRACK
92 path.add_module('SVDDQMClustersOnTrack')
93 # SVD DOSE
94 add_svd_dqm_dose(path, 'SVDShaperDigitsZS5')
95
96 # Event time measuring detectors
97 if components is None or 'CDC' in components or 'ECL' in components or 'TOP' in components:
98 eventT0DQMmodule = b2.register_module('EventT0DQM')
99 path.add_module(eventT0DQMmodule)
100
101 if dqm_environment == "hlt" and (dqm_mode in ["dont_care", "before_filter"]):
102 path.add_module(
103 "SoftwareTriggerHLTDQM",
104 createHLTUnitHistograms=create_hlt_unit_histograms,
105 createTotalResultHistograms=False,
106 createExpRunEventHistograms=False,
107 createErrorFlagHistograms=True,
108 cutResultIdentifiers={},
109 histogramDirectoryName="softwaretrigger_before_filter",
110 pathLocation="before filter",
111 ).set_name("SoftwareTriggerHLTDQM_before_filter")
112
113 path.add_module(
114 "TrackingAbortDQM",
115 histogramDirectoryName="TrackingAbort_before_filter",
116 ).set_name("TrackingAbortDQM_before_filter")
117
118 path.add_module("DetectorOccupanciesDQM", histogramDirectoryName="DetectorOccupancies_before_filter").set_name(
119 "DetectorOccupanciesDQM_before_filter")
120
121 path.add_module("StatisticsTimingHLTDQM",
122 createHLTUnitHistograms=create_hlt_unit_histograms,
123 )
124
125 if dqm_environment == "hlt" and (dqm_mode in ["dont_care", "filtered"]):
126 # HLT
127 hlt_trigger_lines_in_plot = []
128 hlt_skim_lines_in_plot = []
129
130 hlt_trigger_lines_per_unit_in_plot = [
131 "ge3_loose_tracks_inc_1_tight_not_ee2leg",
132 "Elab_gt_0.5_plus_2_others_with_Elab_gt_0.18_plus_no_clust_with_Ecms_gt_2.0",
133 "selectee",
134 "Estargt2_GeV_cluster",
135 ]
136 cutResultIdentifiers = {}
137
138 from softwaretrigger import filter_categories, skim_categories
139
140 filter_cat = [method for method in dir(filter_categories) if method.startswith('__') is False if method != 'RESULTS']
141 skim_cat = [method for method in dir(skim_categories) if method.startswith('__') is False]
142
143 def read_lines(category):
144 return [i.split(" ", 1)[1].replace(" ", "_") for i in category]
145
146 for i in filter_cat:
147 cutResultIdentifiers[i] = {"filter": read_lines(getattr(filter_categories, i))}
148 hlt_trigger_lines_in_plot += read_lines(getattr(filter_categories, i))
149
150 for i in skim_cat:
151 cutResultIdentifiers[i] = {"skim": read_lines(getattr(skim_categories, i))}
152 hlt_skim_lines_in_plot += read_lines(getattr(skim_categories, i))
153
154 cutResultIdentifiers["skim"] = {"skim": hlt_skim_lines_in_plot}
155 cutResultIdentifiers["filter"] = {"filter": hlt_trigger_lines_in_plot}
156
157 additionalL1Identifiers = [
158 'ffy',
159 'fyo',
160 'c4',
161 'hie',
162 'mu_b2b',
163 'mu_eb2b',
164 'beklm',
165 'eklm2',
166 'cdcklm1',
167 'seklm1',
168 'ieklm1',
169 'ecleklm1',
170 'fso',
171 'fioiecl1',
172 'ff30',
173 'stt',
174 'ioiecl1',
175 'ioiecl2',
176 'lml1',
177 'lml2',
178 'lml3',
179 'lml4',
180 'lml5',
181 'lml6',
182 'lml7',
183 'lml8',
184 'lml9',
185 'lml10',
186 'lml12',
187 'lml13',
188 'bhapur']
189
190 # Default plot
191 path.add_module(
192 "SoftwareTriggerHLTDQM",
193 cutResultIdentifiers=cutResultIdentifiers,
194 l1Identifiers=["fff", "ffo", "lml0", "ffb", "fp"],
195 additionalL1Identifiers=additionalL1Identifiers,
196 createHLTUnitHistograms=create_hlt_unit_histograms,
197 cutResultIdentifiersPerUnit=hlt_trigger_lines_per_unit_in_plot,
198 pathLocation="after filter",
199 )
200
201 path.add_module("TrackingAbortDQM")
202
203 path.add_module("DetectorOccupanciesDQM")
204
205 # Skim plots where bhabha contamination is removed
206 path.add_module(
207 "SoftwareTriggerHLTDQM",
208 cutResultIdentifiers={
209 "skim": {"skim": hlt_skim_lines_in_plot},
210 },
211 cutResultIdentifiersIgnored={
212 "skim": [
213 "accept_bhabha_all",
214 ]
215 },
216 createTotalResultHistograms=False,
217 createExpRunEventHistograms=False,
218 histogramDirectoryName="softwaretrigger_skim_nobhabha",
219 ).set_name("SoftwareTriggerHLTDQM_skim_nobhabha")
220
221 if dqm_environment == "hlt" and (dqm_mode in ["dont_care", "filtered"]):
222 # SVD DATA FORMAT
223 if components is None or 'SVD' in components:
224 svdunpackerdqm = b2.register_module('SVDUnpackerDQM')
225 path.add_module(svdunpackerdqm)
226
227 # CDC
228 if (components is None or 'CDC' in components) and (dqm_mode in ["dont_care", "filtered"]):
229 cdcdqm = b2.register_module('cdcDQM7')
230 path.add_module(cdcdqm)
231
232 module_names = [m.name() for m in path.modules()]
233 if ('SoftwareTrigger' in module_names):
234 cdcdedxdqm = b2.register_module('CDCDedxDQM')
235 path.add_module(cdcdedxdqm)
236
237 if dqm_environment == "expressreco":
238 path.add_module('CDCDQM')
239
240 # ECL
241 if (components is None or 'ECL' in components) and (dqm_mode in ["dont_care", "filtered"]):
242 ecldqm = b2.register_module('ECLDQM')
243 path.add_module(ecldqm)
244 ecldqmext = b2.register_module('ECLDQMEXTENDED')
245 path.add_module(ecldqmext)
246 path.add_module('ECLDQMOutOfTimeDigits')
247 path.add_module('ECLDQMConnectedRegions')
248 # we dont want to create large histograms on HLT, thus ERECO only
249 if dqm_environment == "expressreco":
250 path.add_module('ECLDQMInjection', histogramDirectoryName='ECLINJ')
251
252 # TOP
253 if (components is None or 'TOP' in components) and (dqm_mode in ["dont_care", "filtered"]):
254 topdqm = b2.register_module('TOPDQM')
255 path.add_module(topdqm)
256
257 # KLM
258 if (components is None or 'KLM' in components) and (dqm_mode in ["dont_care", "filtered"]):
259 klmdqm = b2.register_module("KLMDQM")
260 path.add_module(klmdqm)
261
262 # TRG before all reconstruction runs (so on all events with all unpacked information)
263 if (components is None or 'TRG' in components) and (dqm_mode in ["dont_care", "before_filter"]):
264 # TRGECL
265 trgecldqm = b2.register_module('TRGECLDQM')
266 path.add_module(trgecldqm)
267 trgecltimingdqm = b2.register_module('TRGECLEventTimingDQM')
268 path.add_module(trgecltimingdqm)
269 # TRGGDL
270 trggdldqm = b2.register_module('TRGGDLDQM')
271 trggdldqm.param('skim', 0)
272 path.add_module(trggdldqm)
273 # TRGTOP
274 trgtopdqm = b2.register_module('TRGTOPDQM')
275 trgtopdqm.param('skim', 0)
276 path.add_module(trgtopdqm)
277 # TRGGRL
278 trggrldqm = b2.register_module('TRGGRLDQM')
279 path.add_module(trggrldqm)
280 # TRGCDCTSF
281 nmod_tsf = [0, 1, 2, 3, 4, 5, 6]
282 for mod_tsf in nmod_tsf:
283 path.add_module('TRGCDCTSFDQM', TSFMOD=mod_tsf)
284 # TRGCDC2D
285 trgcdct2ddqm = b2.register_module('TRGCDCT2DDQM')
286 path.add_module(trgcdct2ddqm)
287 # TRGCDC3D
288 nmod_t3d = [0, 1, 2, 3]
289 for mod_t3d in nmod_t3d:
290 path.add_module('TRGCDCT3DConverter',
291 hitCollectionName='FirmCDCTriggerSegmentHits' + str(mod_t3d),
292 addTSToDatastore=True,
293 EventTimeName='FirmBinnedEventT0' + str(mod_t3d),
294 addEventTimeToDatastore=True,
295 inputCollectionName='FirmTRGCDC2DFinderTracks' + str(mod_t3d),
296 add2DFinderToDatastore=True,
297 outputCollectionName='FirmTRGCDC3DFitterTracks' + str(mod_t3d),
298 add3DToDatastore=True,
299 fit3DWithTSIM=0,
300 firmwareResultCollectionName='TRGCDCT3DUnpackerStore' + str(mod_t3d),
301 isVerbose=0)
302 path.add_module('TRGCDCT3DDQM', T3DMOD=mod_t3d)
303 # CDCTriggerNeuro
304 if dqm_environment != "expressreco":
306 path.add_module('CDCTriggerNeuroDQMOnline', histogramDirectoryName="TRGCDCTNN2", useRecoTracks=False)
307 path.add_module('CDCTriggerNeuroDQM')
308
309 # TRG for expressreco:
310 if dqm_environment == "expressreco" and (components is None or 'TRG' in components) and (dqm_mode in ["dont_care"]):
311 # TRGCDCTNN
313 path.add_module('CDCTriggerRecoMatcher', TrgTrackCollectionName=neurotrigger.hwneurotracks,
314 hitCollectionName=neurotrigger.hwneuroinputsegmenthits, axialOnly=True)
315 path.add_module('CDCTriggerRecoMatcher', TrgTrackCollectionName=neurotrigger.hwsimneurotracks,
316 hitCollectionName=neurotrigger.hwneuroinputsegmenthits, axialOnly=True)
317 path.add_module('CDCTriggerRecoMatcher', TrgTrackCollectionName=neurotrigger.hwneuroinput2dfindertracks,
318 hitCollectionName=neurotrigger.hwneuroinputsegmenthits, axialOnly=True)
319 path.add_module('CDCTriggerNeuroDQMOnline', histogramDirectoryName="TRGCDCTNN2", useRecoTracks=True)
320
321 # TRG after skim
322 if (components is None or 'TRG' in components) and (dqm_mode in ["dont_care", "filtered"]):
323 # TRGGDL
324 trggdldqm_skim = b2.register_module('TRGGDLDQM')
325 trggdldqm_skim.param('skim', 1)
326 path.add_module(trggdldqm_skim)
327 # TRGTOP
328 trgtopdqm_skim = b2.register_module('TRGTOPDQM')
329 trgtopdqm_skim.param('skim', 1)
330 path.add_module(trgtopdqm_skim)
331
332 # TrackDQM, needs at least one VXD components to be present or will crash otherwise
333 if (components is None or 'SVD' in components or 'PXD' in components) and (dqm_mode in ["dont_care", "filtered"]):
334 if (dqm_environment == "hlt"):
335 path.add_module('TrackingHLTDQM')
336 else:
337 path.add_module('ParallelTrackFilter', min_d0=-0.5, max_d0=0.5, min_z0=-1, max_z0=1,
338 inputArrayName="", outputINArrayName="TracksFromIP", outputOUTArrayName="TracksNotFromIP")
339 path.add_module('TrackingExpressRecoDQM', histogramDirectoryName="TrackingERDQM_FromIP",
340 tracksStoreArrayName="TracksFromIP", histogramTitleSuffix=" - Tracks from IP") \
341 .set_name("TrackingExpressRecoDQM_FromIP")
342 path.add_module('TrackingExpressRecoDQM', histogramDirectoryName="TrackingERDQM_NotFromIP",
343 tracksStoreArrayName="TracksNotFromIP", histogramTitleSuffix=" - Tracks not from IP") \
344 .set_name("TrackingExpressRecoDQM_NotFromIP")
345
346 # ARICH
347 if (components is None or 'ARICH' in components) and (dqm_mode in ["dont_care", "filtered"]):
348 path.add_module('ARICHDQM')
349
350 if dqm_mode in ["dont_care", "filtered"]:
351 # PhysicsObjectsDQM
352 add_analysis_dqm(path)
353 if dqm_environment == "expressreco" and (dqm_mode in ["dont_care"]):
354 add_mirabelle_dqm(path)
355
356 # KLM2 (requires mu+ particle list from add_analysis_dqm)
357 if (components is None or ('KLM' in components and 'CDC' in components)) and (dqm_mode in ["dont_care", "filtered"]):
358 path.add_module("KLMDQM2", MuonListName='mu+:KLMDQM',
359 MinimalMatchingDigits=12,
360 MinimalMatchingDigitsOuterLayers=0,
361 MinimalMomentumNoOuterLayers=4.0,
362 SoftwareTriggerName="")
363
364 # We want to see the datasize of all events after removing the raw data
365 if dqm_mode in ["dont_care", "all_events"]:
366 # DAQ Monitor
367 path.add_module('DAQMonitor')
def add_neurotrigger_hw(path, nntweightfile=None, debug_level=4, debugout=False, **kwargs)