Belle II Software development
studyLaserLight.py
1#!/usr/bin/env python3
2
3
10
11# ------------------------------------------------------------------------
12# Module to produce the laser time histograms that serve as input to the laser
13# resolution fitter
14#
15# usage: basf2 studyLaserResolution.py dbaddress (path|none) type (local|pocket|root)
16# output_name.root path_to_sroot run1 run2 ... runN
17# The run number accepts wildcards
18# ------------------------------------------------------------------------
19
20
21import basf2 as b2
22import sys
23import glob
24from ROOT import Belle2
25from ROOT import TFile, TH2F
26from laserResolutionTools import fitLaserResolution, plotLaserResolution
27
28
30
31 ''' Module to study resolution and performance of the top laser calibration.'''
32
33
34 h_LaserTimingVSChannel = TH2F(
35 'LaserTimingVSChannel',
36 'Laser timing in as function of the channel number',
37 512 * 16,
38 0,
39 512 * 16,
40 10000,
41 0.,
42 100) # 10 ps binning
43
44 h_LaserTimingVSChannelOneSlot = TH2F(
45 'LaserTimingVSChannelOneSlot',
46 'Laser timing in as function of the channel number',
47 512,
48 0,
49 512,
50 10000,
51 0.,
52 100) # 10 ps binning
53
54
55 h_crossOccupancy = [[TH2F(
56 'crossOccupancy_' + str(slotA) + '_' + str(slotB),
57 ' ',
58 200,
59 0,
60 200,
61 200,
62 0.,
63 200) for slotA in range(16)] for slotB in range(16)]
64
65
66 outname = 'outStudyLaserResolution.root'
67
68
69 m_ignoreNotCalibrated = True
70
71 m_runOnData = True
72
73
74 m_maxWidth = 3.
75
76 m_minWidth = 0.5
77
78 m_maxAmp = 700.
79
80 m_minAmp = 250.
81
82 m_mcCorrectionsFile = '/group/belle2/group/detector/TOP/calibration/MCreferences/t0MC.root'
83
84 m_MCPeaks = [[]]
85
86 def setOutputName(self, outputname):
87 ''' Sets the output file name '''
88
89 self.outnameoutname = outputname
90
91 def setMaxWidth(self, maxWidth):
92 ''' Sets the maximum calpulse width '''
93
94 self.m_maxWidthm_maxWidth = maxWidth
95
96 def setMinWidth(self, minWidth):
97 ''' Sets the minimum calpulse width '''
98
99 self.m_minWidthm_minWidth = minWidth
100
101 def setMaxAmp(self, maxAmp):
102 ''' Sets the maximum calpulse amplitude '''
103
104 self.m_maxAmpm_maxAmp = maxAmp
105
106 def setMinAmp(self, minAmp):
107 ''' Sets the minimum calpulse amplitude '''
108
109 self.m_minAmpm_minAmp = minAmp
110
111 def setMCCorrectionsFile(self, MCfile):
112 ''' Sets the file containing the MC correction'''
113
115
116 def ignoreNotCalibrated(self, ignoreNotCal):
117 ''' Sets the flag to ingore the hits without calibration '''
118
120
121 def event(self):
122 ''' Event processor: fill histograms '''
123
124 digits = Belle2.PyStoreArray('TOPDigits')
125 nhits = [0 for i in range(16)]
126 for digit in digits:
127 if(not self.ignoreNotCalibrated and not digit.isTimeBaseCalibrated()):
128 continue
129 if (digit.getHitQuality() == 1 and
130 digit.getPulseWidth() > self.m_minWidthm_minWidth and digit.getPulseWidth() < self.m_maxWidthm_maxWidth and
131 digit.getPulseHeight() > self.m_minAmpm_minAmp and digit.getPulseHeight() < self.m_maxAmpm_maxAmp):
132 slotID = digit.getModuleID()
133 hwchan = digit.getChannel()
134 self.h_LaserTimingVSChannel.Fill(512 * (slotID - 1) + hwchan, digit.getTime())
135 simhits = digit.getRelationsWith('TOPSimHits')
136 nhits[slotID - 1] = nhits[slotID - 1] + 1
137 for simhit in simhits:
138 self.h_LaserTimingVSChannelOneSlot.Fill(hwchan, simhit.getTime())
139 for slotA in range(16):
140 for slotB in range(16):
141 self.h_crossOccupancy[slotA][slotB].Fill(nhits[slotA], nhits[slotB])
142
143 def terminate(self):
144 ''' Write histograms to file, fills and fits the resolution plots'''
145 tfile = TFile(self.outnameoutname, 'recreate')
146 self.h_LaserTimingVSChannel.Write()
148 for slotA in range(16):
149 for slotB in range(16):
150 self.h_crossOccupancy[slotA][slotB].Write()
151 tfile.Close()
152
153
154argvs = sys.argv
155print('usage: basf2', argvs[0], 'runNumber outfileName')
156
157lookBack = argvs[1] # lookbackWindows setting
158dbaddress = argvs[2] # path to the calibration DB (absolute path or 'none')
159datatype = argvs[3] # data type ('pocket' or 'local' or 'root', if root files have to be analyzed)
160outfile = argvs[4] # output name
161folder = argvs[5] # folder containing the sroot files
162runnumbers = sys.argv[6:] # run numbers
163
164files = []
165for runnumber in runnumbers:
166 if datatype == 'root':
167 files += [f for f in glob.glob(str(folder) + '/*' + str(runnumber) + '*.root')]
168 else:
169 # print('running on sroot files in folder ' + glob.glob(str(folder))
170 files += [f for f in glob.glob(str(folder) + '/*' + str(runnumber) + '*.sroot')]
171for fname in files:
172 print("file: " + fname)
173
174if dbaddress != 'none':
175 print("using local DB " + dbaddress)
176 b2.conditions.append_testing_payloads(dbaddress + "/localDB.txt")
177else:
178 print("database not set. Continuing without calibrations")
179
180# Suppress messages and warnings during processing
181b2.set_log_level(b2.LogLevel.ERROR)
182
183# Define a global tag (note: the one given bellow can be out-dated!)
184b2.conditions.append_globaltag('data_reprocessing_proc8')
185
186# Create path
187main = b2.create_path()
188
189# input
190if datatype == 'root':
191 roinput = b2.register_module('RootInput')
192 roinput.param('inputFileNames', files)
193 main.add_module(roinput)
194else:
195 roinput = b2.register_module('SeqRootInput')
196 roinput.param('inputFileNames', files)
197 main.add_module(roinput)
198
199# conversion from RawCOPPER or RawDataBlock to RawDetector objects
200if datatype == 'pocket':
201 print('pocket DAQ data assumed')
202 converter = b2.register_module('Convert2RawDet')
203 main.add_module(converter)
204
205# Initialize TOP geometry parameters (creation of Geant geometry is not needed)
206main.add_module('TOPGeometryParInitializer')
207
208if datatype != 'root':
209 # Unpacking (format auto detection works now)
210 unpack = b2.register_module('TOPUnpacker')
211 main.add_module(unpack)
212
213 # Add multiple hits by running feature extraction offline
214 featureExtractor = b2.register_module('TOPWaveformFeatureExtractor')
215 main.add_module(featureExtractor)
216
217 # Convert to TOPDigits
218 converter = b2.register_module('TOPRawDigitConverter')
219 if dbaddress == 'none':
220 print("Not using Calibrations")
221 converter.param('useSampleTimeCalibration', False)
222 converter.param('useAsicShiftCalibration', False)
223 converter.param('useChannelT0Calibration', False)
224 converter.param('useModuleT0Calibration', False)
225 else:
226 print("Using Calibrations")
227 converter.param('useSampleTimeCalibration', True)
228 converter.param('useAsicShiftCalibration', True)
229 converter.param('useChannelT0Calibration', True)
230 converter.param('useModuleT0Calibration', True)
231 converter.param('useCommonT0Calibration', False)
232 converter.param('calibrationChannel', -1) # do not specify the calpulse channel
233 converter.param('lookBackWindows', int(lookBack)) # in number of windows
234 main.add_module(converter)
235
236# resolution plotter
237resolutionModule = TOPLaserHistogrammerModule()
238resolutionModule.setOutputName(outfile)
239resolutionModule.setMinWidth(0.1) # good TOPDigit selection
240resolutionModule.setMaxWidth(999) # good TOPDigit selection
241resolutionModule.setMinAmp(100) # good TOPDigit selection
242resolutionModule.setMaxAmp(999) # good TOPDigit selection
243if dbaddress == 'none':
244 resolutionModule.ignoreNotCalibrated(True)
245else:
246 resolutionModule.ignoreNotCalibrated(False)
247main.add_module(resolutionModule)
248
249# Show progress of processing
250progress = b2.register_module('Progress')
251main.add_module(progress)
252
253# Process events
254b2.process(main)
255
256# Print call statistics
257print(b2.statistics)
258print(b2.statistics(b2.statistics.TERM))
259
260
261fitLaserResolution(dataFile=outfile, outputFile='laserResolutionResults.root', pdfType='cb', saveFits=True)
262plotLaserResolution()
A (simplified) python wrapper for StoreArray.
Definition: PyStoreArray.h:72
int m_maxWidth
maximum width to accept a TOPDigit
bool m_ignoreNotCalibrated
ignores the hits wthout calibration
str m_mcCorrectionsFile
root file with the MC distribution of the laser light, to get the light path corrections
int m_minAmp
minimum amplitude to accept a TOPDigit
TH2F h_LaserTimingVSChannelOneSlot
Laser timing in as function of the channel number.
int m_maxAmp
minimum amplitude to accept a TOPDigit
TH2F h_LaserTimingVSChannel
Width as function of the sample number in each channel.
float m_minWidth
minimum width to accept a TOPDigit