Belle II Software  release-08-01-10
caf_hotpixel_sequential.py
1 #!/usr/bin/env python3
2 
3 
10 
11 # This steering file computes PXD hotpixel and deadpixel masks from root formatted raw data
12 # running the CAF
13 #
14 # Before running, you have to put a file to IoV mapping called 'file_iov_map.pkl' in your
15 # working directory. You can create such a map file by using the tool b2caf-filemap.
16 # See also the option --help.
17 #
18 # b2caf-filemap -m raw -p "/hsm/belle2/bdata/Data/Raw/e0003/r*/**/*.root"
19 #
20 # This will try to compute hot pixel masks, dead pixel masks and occupancy maps for each run
21 # in the given IoV range.
22 #
23 # The results will be collected in a folder 'pxd_calibration_results_range_XY'. In order to complete the
24 # process, the check and uploads the outputdbs to a global tag (GT).
25 #
26 # b2conditionsdb upload Calibration_Offline_Development ./database.txt
27 #
28 # The option --help provides extensive help for the b2conditionsdb tool.
29 
30 import argparse
31 from caf.strategies import SequentialRunByRun
32 from caf.utils import ExpRun, IoV
33 from caf import backends
34 from caf.framework import Calibration, CAF
35 from ROOT.Belle2 import PXDHotPixelMaskCalibrationAlgorithm
36 import pickle
37 import basf2 as b2
38 b2.set_log_level(b2.LogLevel.INFO)
39 
40 
41 parser = argparse.ArgumentParser(
42  description="Compute hot pixel masks for PXD from rawhit occupancy")
43 parser.add_argument(
44  '--runLow',
45  default=0,
46  type=int,
47  help='Compute mask for specific IoV')
48 parser.add_argument('--runHigh', default=-1, type=int,
49  help='Compute mask for specific IoV')
50 parser.add_argument(
51  '--expNo',
52  default=3,
53  type=int,
54  help='Compute mask for specific IoV')
55 parser.add_argument('--maxSubRuns', default=20, type=int,
56  help='Maximum number of subruns to use')
57 args = parser.parse_args()
58 
59 
60 # Ignoring runs
61 pxd_ignore_run_list = [ExpRun(3, 484), ExpRun(3, 485), ExpRun(3, 486), ExpRun(3, 524)]
62 
63 # Set the IoV range for this calibration
64 iov_to_calibrate = IoV(
65  exp_low=args.expNo,
66  run_low=args.runLow,
67  exp_high=args.expNo,
68  run_high=args.runHigh)
69 
70 map_file_path = "file_iov_map.pkl"
71 with open(map_file_path, 'br') as map_file:
72  files_to_iovs = pickle.load(map_file)
73 
74 
75 input_file_iov_set = set(files_to_iovs.values())
76 print(f'Number of distinct iovs {len(input_file_iov_set)}')
77 
78 
79 input_files = []
80 
81 for file_iov in input_file_iov_set:
82  if iov_to_calibrate.contains(file_iov):
83  subruns = [k for k, v in files_to_iovs.items() if v == file_iov]
84  input_files.extend(subruns[:args.maxSubRuns])
85 
86 
87 print(f'Number selected input files: {len(input_files)}')
88 
89 # Create and configure the collector and its pre collector path
90 hotpixelcollector = b2.register_module("PXDRawHotPixelMaskCollector")
91 hotpixelcollector.param("granularity", "run")
92 
93 # The pre collector path must contain geometry and unpacker
94 gearbox = b2.register_module('Gearbox')
95 gearbox.param('fileName', 'geometry/Beast2_phase2.xml')
96 geometry = b2.register_module('Geometry')
97 geometry.param('components', ['PXD'])
98 pre_collector_path = b2.create_path()
99 pre_collector_path.add_module(gearbox)
100 pre_collector_path.add_module(geometry)
101 pre_collector_path.add_module('PXDUnpacker')
102 
103 
104 # Create and configure the calibration algorithm
105 # Getting a calibration algorithm instance
106 hotpixelkiller = PXDHotPixelMaskCalibrationAlgorithm()
107 # We can play around with hotpixelkiller parameters
108 # Continue masking even when few/no events were collected
109 hotpixelkiller.forceContinueMasking = False
110 # Minimum number of collected events for masking
111 hotpixelkiller.minEvents = 30000
112 # Only consider dead pixel masking when median number of hits per pixel is
113 # higher
114 hotpixelkiller.minHits = 15
115 # Occupancy threshold is median occupancy x multiplier
116 hotpixelkiller.pixelMultiplier = 7
117 # Set True to allow masking of hot drain lines
118 hotpixelkiller.maskDrains = True
119 # Occupancy threshold is median occupancy x multiplier
120 hotpixelkiller.drainMultiplier = 7
121 # Set True to allow masking of hot rows
122 hotpixelkiller.maskRows = True
123 # Occupancy threshold is median occupancy x multiplier
124 hotpixelkiller.rowMultiplier = 7
125 # We want to use a specific collector collecting from raw hits
126 hotpixelkiller.setPrefix("PXDRawHotPixelMaskCollector")
127 
128 # Create a calibration
129 cal = Calibration(
130  name="PXDHotPixelMaskCalibrationAlgorithm",
131  collector=hotpixelcollector,
132  algorithms=hotpixelkiller,
133  input_files=input_files)
134 cal.pre_collector_path = pre_collector_path
135 
136 # Apply the map to this calibration, now the CAF doesn't have to do it
137 cal.files_to_iovs = files_to_iovs
138 
139 # The SequentialRunByRun strategy executes your algorithm over runs
140 # individually to give you payloads for each one (if successful)
141 cal.strategies = SequentialRunByRun
142 
143 cal.ignored_runs = pxd_ignore_run_list
144 cal.algorithms[0].params["iov_coverage"] = iov_to_calibrate
145 
146 cal.max_files_per_collector_job = 1
147 
148 # Create a CAF instance and add the calibration to it.
149 cal_fw = CAF()
150 cal_fw.add_calibration(cal)
151 # cal_fw.backend = backends.LSF()
152 cal_fw.backend = backends.Local(max_processes=20)
153 # Time between polling checks to the CAF to see if a step (algorithm,
154 # collector jobs) is complete
155 cal_fw.heartbeat = 30
156 # Can change where your calibration runs
157 cal_fw.output_dir = f'calibration_results_range_{args.runLow}_{args.runHigh}'
158 cal_fw.run(iov=iov_to_calibrate)
159 # Should have created a directory called 'calibration_results'