22 parser = argparse.ArgumentParser(description=
"analyze gain and efficiency for laser run data")
23 parser.add_argument(
"inputFile", nargs=
'*', default=[
"NoInputFile"],
24 help=
"Input sroot files. Mulitple files can be given.")
25 parser.add_argument(
"--interimRootFile", default=
"NoInterimRootFile",
26 help=
"Interim root file name to store timing-height 2D histograms.")
27 parser.add_argument(
"--outputRootFile", default=
"NoOutputRootFile",
28 help=
"Output root file name to save TTree containing fit results.")
29 parser.add_argument(
"--outputPDFFile", default=
"NoOutputPDFFile",
30 help=
"Output PDF file name to save fitting results for each channel.")
31 parser.add_argument(
"--interimFW", action=
"store_true", default=
False,
32 help=
"use when analyzing interimFW data")
33 parser.add_argument(
"--slotID", type=int, default=0,
34 help=
"slot number [1-16]")
35 parser.add_argument(
"--PMTID", type=int, default=0,
36 help=
"slot number [1-32]")
37 parser.add_argument(
"--calChannel", type=int, default=0,
38 help=
"asic channel number where calibration signals are injected [0-7]")
39 parser.add_argument(
"--threshold", type=float, default=100.,
40 help=
"threshold in pulse height fitting")
41 parser.add_argument(
"--globalDAQ", action=
"store_true", default=
False,
42 help=
"Force to assume global DAQ data.")
43 parser.add_argument(
"--pocketDAQ", action=
"store_true", default=
False,
44 help=
"Force to assume global DAQ data.")
45 parser.add_argument(
"--noOfflineFE", action=
"store_true", default=
False,
46 help=
"Use only online FE hits, and do not use waveform data.")
47 parser.add_argument(
"--useSingleCalPulse", action=
"store_true", default=
False,
48 help=
"Do not require double calibration pulses, but require only the first one.")
49 parser.add_argument(
"--windowSelection", type=int, default=0,
50 help=
"Select window number (All=0,Odd=2,Even=1)")
51 parser.add_argument(
"--includePrimaryChargeShare", action=
"store_true", default=
False,
52 help=
"don't want to use primary charge share cut,type true.")
53 parser.add_argument(
"--includeAllChargeShare", action=
"store_true", default=
False,
54 help=
"don't want to use all charge share cut,type true.")
55 parser.add_argument(
"--sumChargeShare", action=
"store_true", default=
False,
56 help=
"When you want to use summation of charge share for gain distribution,type true.")
57 parser.add_argument(
"--fitoption", action=
"store", default=
'L',
58 help=
"fitting with chisquare=R, loglikelihood=L")
59 parser.add_argument(
"--timeCut", type=float, default=1,
60 help=
"cut of hittiming for chargeshare")
61 parser.add_argument(
"--HVHigherSetting", type=int, default=0,
62 help=
"HV positive difference from nominal value")
63 parser.add_argument(
"--HVLowerSetting", type=int, default=0,
64 help=
"HV negative difference from nominal value")
65 args = parser.parse_args()
67 if (args.inputFile[0] ==
"NoInputFile")
and (args.interimRootFile ==
"NoInterimRootFile"):
68 print(
"Steering file to study gain/efficiency analysis from laser data.")
69 print(
"In the first step, 2D histograms (hit time vs pulse height) were created for all the available channels, "
70 "and saved in an interim root file.")
71 print(
"Then, in the second process, 1D pulse height distribution is extracted "
72 "from the 2D histogram and fitted to evaluate gain and efficiency for each channel.")
73 print(
"The second process is done only for one give PMT as it takes time.")
75 print(
"basf2 analyzeGainEff.py [input_filename1.sroot, input_filename2.sroot, ...]")
76 print(
" [--arg --interimRootFile interim_histo_output.root]")
77 print(
" [--arg --outputRootFile summary_tree_output.root]")
78 print(
" [--arg --outputPDFFile summary_plot.pdf]")
79 print(
" [--arg --slotID slotNum(1-16)] [--arg --PMTID PMTID(1-32)]")
80 print(
" [--arg --calChannel asicCh(0-7)] [--arg --threshold threshold]")
81 print(
" [--arg --globalDAQ] [--arg --pocketDAQ]")
82 print(
" [--arg --noOfflineFE] [--arg --useSingleCalPulse]")
83 print(
" [--arg --timeCut] [--arg --fitoption]")
84 print(
" [--arg --windowSelection] [--arg --sumChargeShare]")
85 print(
" [--arg --includePrimaryChargeShare] [--arg --includeAllChargeShare]")
86 print(
" [--arg --HVHigherSetting] [--arg --HVLowerSetting]")
87 print(
"*When input sroot files are missing but interim root file is given,"
88 " skip the first process to create 2D histogram and start fitting.")
89 print(
"*Both the slot and PMT numbers are mandatory to proceed to the second processes.")
90 print(
"*default calibration asic channel is " + str(args.calChannel))
91 print(
"*default threshold is " + str(args.threshold))
95 inputFiles = args.inputFile
96 interimRoot = args.interimRootFile
97 outputRoot = args.outputRootFile
98 outputPDF = args.outputPDFFile
99 isInterimFW = args.interimFW
102 calChannel = args.calChannel
103 threshold = args.threshold
105 isGlobalDAQForced = args.globalDAQ
106 isPocketDAQForced = args.pocketDAQ
107 isOfflineFEDisabled = args.noOfflineFE
108 windowSelect = args.windowSelection
109 includePrimaryChargeShare = args.includePrimaryChargeShare
110 includeAllChargeShare = args.includeAllChargeShare
111 sumChargeShare = args.sumChargeShare
112 HVHigherSetting = args.HVHigherSetting
113 HVLowerSetting = args.HVLowerSetting
114 fitOption = args.fitoption
115 timeCut = args.timeCut
117 useSingleCalPulse = (
True if isOfflineFEDisabled
else args.useSingleCalPulse)
118 skipFirst = ((inputFiles[0] ==
"NoInputFile")
and (interimRoot !=
"NoInterimRootFile"))
119 skipSecond = ((slotId < 1)
or (slotId > 16)
or (pmtId < 1)
or (pmtId > 32))
120 pmtStr =
"s" + (
'%02d' % slotId) +
"_PMT" + (
'%02d' % pmtId)
121 if isGlobalDAQForced
and isPocketDAQForced:
122 print(
"ERROR : both of --GlobalDAQ or --PocketDAQ can not be given.")
124 if skipFirst
and skipSecond:
125 print(
"ERROR : unable to run either of the first and second process:"
126 "no input sroot file and no valid slot ID or PMT ID")
128 if (calChannel < 0)
or (calChannel > 7):
129 print(
"ERROR : invalid asic channel with calibration pulses : " + str(calChannel))
132 if includePrimaryChargeShare
and includeAllChargeShare:
133 print(
"ERROR : both of --includePrimaryChargeShare and --includeAllChargeShare can not be given.")
136 if sumChargeShare
and includeAllChargeShare:
137 print(
"ERROR : both of --sumChargeShare and --includeAllChargeShare can not be given."
138 "While both of --sumChargeShare and --includePrimaryChargeShare can be given.")
141 if HVHigherSetting
and HVLowerSetting:
142 print(
"ERROR : both of --HVHigherSetting and --HVLowerSetting can not be given.")
147 path_to_db =
"/group/belle2/group/detector/TOP/calibration/combined/Combined_TBCrun417x_LocaT0run4855_AfterRelease01/localDB/"
148 b2.use_local_database(path_to_db +
'/localDB.txt', path_to_db)
150 inputBase = inputFiles[0]
if not skipFirst
else interimRoot
151 dotPos = inputBase.rfind(
'.')
152 outputBase = inputBase[0:dotPos]
if (dotPos > 0)
else inputBase
154 if re.search(
r"run[0-9]+_slot[0-1][0-9]", inputFiles[0]):
155 outputBase = re.search(
r"run[0-9]+_slot[0-1][0-9]", inputFiles[0]).group()
156 elif re.search(
r"(top|cosmic|cdc|ecl|klm|test|debug|beam)\.[0-9]+\.[0-9]+", inputFiles[0]):
158 outputBase = re.search(
r"(top|cosmic|cdc|ecl|klm|test|debug|beam)\.[0-9]+\.[0-9]+", inputFiles[0]).group()
160 if interimRoot ==
"NoInterimRootFile":
161 interimRoot = outputBase +
"_gain_histo.root"
162 if outputRoot ==
"NoOutputRootFile":
163 outputRoot = outputBase +
"_gain_" + pmtStr +
".root"
164 if outputPDF ==
"NoOutputPDFFile":
165 outputPDF = outputBase +
"_" + pmtStr
167 if isGlobalDAQForced
and (
not isPocketDAQForced):
169 elif (
not isGlobalDAQForced)
and isPocketDAQForced:
173 print(
"*first process : " + str(inputFiles) +
" --> " + interimRoot)
175 print(
"*first process is skipped...")
177 print(
"*second process : " + interimRoot +
" --> " + outputRoot +
", " + outputPDF)
179 print(
"*second process is skipped")
180 print(
"*Is global DAQ? : " + str(isGlobalDAQ))
181 print(
"*Offline FE : " + (
"enabled" if not isOfflineFEDisabled
else "disabled"))
182 print(
"*use double pulse : " + str(
not useSingleCalPulse))
183 print(
"*cal. asic channel: " + str(calChannel))
184 print(
"*threshold : " + str(threshold))
186 print(
"start process...")
191 b2.use_central_database(
'data_reprocessing_proc8')
194 first = b2.create_path()
196 srootInput = b2.register_module(
'SeqRootInput')
197 srootInput.param(
'inputFileNames', inputFiles)
198 first.add_module(srootInput)
201 histoman = b2.register_module(
'HistoManager')
202 histoman.param(
'histoFileName', interimRoot)
203 first.add_module(histoman)
207 converter = b2.register_module(
'Convert2RawDet')
208 first.add_module(converter)
211 gearbox = b2.register_module(
'Gearbox')
212 first.add_module(gearbox)
215 geometry = b2.register_module(
'Geometry')
216 first.add_module(geometry)
219 unpack = b2.register_module(
'TOPUnpacker')
221 unpack.param(
'swapBytes',
True)
222 unpack.param(
'dataFormat', 0x0301)
223 first.add_module(unpack)
226 if not isOfflineFEDisabled:
227 featureExtractor = b2.register_module(
'TOPWaveformFeatureExtractor')
228 first.add_module(featureExtractor)
231 converter = b2.register_module(
'TOPRawDigitConverter')
232 converter.param(
'useSampleTimeCalibration',
False)
233 converter.param(
'useChannelT0Calibration',
False)
234 converter.param(
'useModuleT0Calibration',
False)
235 converter.param(
'useCommonT0Calibration',
False)
236 converter.param(
'calibrationChannel', calChannel)
237 converter.param(
'calpulseHeightMin', 100)
238 converter.param(
'calpulseHeightMax', 650)
239 converter.param(
'calpulseWidthMin', 0.8)
240 converter.param(
'calpulseWidthMax', 2.4)
241 first.add_module(converter)
243 flagSetter = b2.register_module(
'TOPXTalkChargeShareSetter')
244 flagSetter.param(
'sumChargeShare', sumChargeShare)
245 flagSetter.param(
'timeCut', timeCut)
246 first.add_module(flagSetter)
248 laserHitSelector = b2.register_module(
'TOPLaserHitSelector')
249 laserHitSelector.param(
'useDoublePulse', (
not useSingleCalPulse))
250 laserHitSelector.param(
'minHeightFirstCalPulse', 300)
251 laserHitSelector.param(
'minHeightSecondCalPulse', 100)
252 laserHitSelector.param(
'nominalDeltaT', 25.5)
253 laserHitSelector.param(
'nominalDeltaTRange', 2)
254 laserHitSelector.param(
'windowSelect', windowSelect)
255 laserHitSelector.param(
'includePrimaryChargeShare', includePrimaryChargeShare)
256 laserHitSelector.param(
'includeAllChargeShare', includeAllChargeShare)
258 first.add_module(laserHitSelector)
261 progress = b2.register_module(
'Progress')
262 first.add_module(progress)
269 print(
"start the second process...")
270 second = b2.create_path()
272 eventinfosetter = b2.register_module(
'EventInfoSetter')
273 eventinfosetter.param(
'evtNumList', [1])
274 second.add_module(eventinfosetter)
277 histoman2 = b2.register_module(
'HistoManager')
278 histoman2.param(
'histoFileName', outputRoot)
279 second.add_module(histoman2)
281 analysis = b2.register_module(
'TOPGainEfficiencyCalculator')
282 analysis.param(
'inputFile', interimRoot)
283 analysis.param(
'outputPDFFile', outputPDF)
284 analysis.param(
'targetSlotId', slotId)
285 analysis.param(
'targetPmtId', pmtId)
286 analysis.param(
'hvDiff', HVHigherSetting - HVLowerSetting)
287 analysis.param(
'threshold', threshold)
288 analysis.param(
'fitoption', fitOption)
289 second.add_module(analysis)