10 Airflow script to perform eCMS calibration (combination of the had-B and mumu method).
13 from prompt
import CalibrationSettings, INPUT_DATA_FILTERS
14 from prompt.calibrations.caf_boostvector
import settings
as boostvector
15 from reconstruction
import add_pid_module, add_ecl_modules, prepare_cdst_analysis
17 from basf2
import create_path, register_module, get_file_metadata, B2INFO, B2WARNING
18 import modularAnalysis
as ma
26 settings = CalibrationSettings(
27 name=
"Ecms Calibrations",
28 expert_username=
"zlebcr",
30 input_data_formats=[
"cdst"],
31 input_data_names=[
"hadron4S",
"mumu4S",
"mumuOff"],
34 INPUT_DATA_FILTERS[
"Data Tag"][
"btocharm_calib"],
35 INPUT_DATA_FILTERS[
"Run Type"][
"physics"],
36 INPUT_DATA_FILTERS[
"Beam Energy"][
"4S"],
37 INPUT_DATA_FILTERS[
"Data Quality Tag"][
"Good Or Recoverable"],
38 INPUT_DATA_FILTERS[
"Magnet"][
"On"]],
40 INPUT_DATA_FILTERS[
"Data Tag"][
"mumu_tight_or_highm_calib"],
41 INPUT_DATA_FILTERS[
"Run Type"][
"physics"],
42 INPUT_DATA_FILTERS[
"Beam Energy"][
"4S"],
43 INPUT_DATA_FILTERS[
"Data Quality Tag"][
"Good Or Recoverable"],
44 INPUT_DATA_FILTERS[
"Magnet"][
"On"]],
46 INPUT_DATA_FILTERS[
"Data Tag"][
"mumu_tight_or_highm_calib"],
47 INPUT_DATA_FILTERS[
"Run Type"][
"physics"],
48 INPUT_DATA_FILTERS[
"Beam Energy"][
"Continuum"],
49 INPUT_DATA_FILTERS[
'Beam Energy'][
'Scan'],
50 INPUT_DATA_FILTERS[
"Data Quality Tag"][
"Good Or Recoverable"],
51 INPUT_DATA_FILTERS[
"Magnet"][
"On"]]
54 "outerLoss":
"pow(0.000010e0*rawTime, 2) + 1./nEv",
55 "innerLoss":
"pow(0.000120e0*rawTime, 2) + 1./nEv",
57 "eCMSmumuSpread": 5.2e-3,
58 "eCMSmumuShift": 10e-3},
59 depends_on=[boostvector])
64 def get_hadB_path(isCDST):
65 """ Selects the hadronic B decays, function returns corresponding path """
68 rec_path_1 = create_path()
70 prepare_cdst_analysis(path=rec_path_1, components=[
'CDC',
'ECL',
'KLM'])
72 add_pid_module(rec_path_1)
73 add_ecl_modules(rec_path_1)
79 ma.cutAndCopyList(
"pi+:my",
"pi+:loose",
"[abs(dz)<2.0] and [abs(dr)<0.5]", path=rec_path_1)
80 ma.cutAndCopyList(
"K+:my",
"K+:good",
"[abs(dz)<2.0] and [abs(dr)<0.5]", path=rec_path_1)
82 ma.cutAndCopyList(
"pi0:my",
"pi0:eff40_May2020",
"", path=rec_path_1)
88 DcutLoose =
'1.7 < M < 2.1'
89 Dcut =
'1.830 < M < 1.894'
91 ma.reconstructDecay(decayString=
'D0:Kpi -> K-:my pi+:my', cut=DcutLoose, dmID=1, path=rec_path_1)
92 ma.reconstructDecay(decayString=
'D0:Kpipi0 -> K-:my pi+:my pi0:my',
93 cut=DcutLoose, dmID=2, path=rec_path_1)
94 ma.reconstructDecay(decayString=
'D0:Kpipipi -> K-:my pi+:my pi-:my pi+:my',
95 cut=DcutLoose, dmID=3, path=rec_path_1)
98 vertex.kFit(list_name=
'D0:Kpi', conf_level=0.0, fit_type=
'mass', path=rec_path_1)
100 vertex.kFit(list_name=
'D0:Kpipipi', conf_level=0.0, fit_type=
'mass', path=rec_path_1)
102 ma.applyCuts(
"D0:Kpi", Dcut, path=rec_path_1)
103 ma.applyCuts(
"D0:Kpipi0", Dcut, path=rec_path_1)
104 ma.applyCuts(
"D0:Kpipipi", Dcut, path=rec_path_1)
106 DStarcutLoose =
'massDifference(0) < 0.16'
109 ma.reconstructDecay(decayString=
'D*+:D0pi_Kpi -> D0:Kpi pi+:my', cut=DStarcutLoose, dmID=1, path=rec_path_1)
110 ma.reconstructDecay(decayString=
'D*+:D0pi_Kpipi0 -> D0:Kpipi0 pi+:my',
111 cut=DStarcutLoose, dmID=2, path=rec_path_1)
112 ma.reconstructDecay(decayString=
'D*+:D0pi_Kpipipi -> D0:Kpipipi pi+:my',
113 cut=DStarcutLoose, dmID=3, path=rec_path_1)
115 BcutLoose =
'[ useCMSFrame(p) < 1.6 ] and [abs(dM) < 0.25]'
116 Bcut =
'[ useCMSFrame(p) < 1.2 ] and [abs(dM) < 0.05]'
119 ma.reconstructDecay(decayString=
'B0:Dstpi_D0pi_Kpi -> D*-:D0pi_Kpi pi+:my',
121 dmID=1, path=rec_path_1)
122 ma.reconstructDecay(decayString=
'B0:Dstpi_D0pi_Kpipi0 -> D*-:D0pi_Kpipi0 pi+:my',
124 dmID=2, path=rec_path_1)
125 ma.reconstructDecay(decayString=
'B0:Dstpi_D0pi_Kpipipi -> D*-:D0pi_Kpipipi pi+:my',
127 dmID=3, path=rec_path_1)
129 vertex.treeFit(
'B0:Dstpi_D0pi_Kpi', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
130 vertex.treeFit(
'B0:Dstpi_D0pi_Kpipi0', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
131 vertex.treeFit(
'B0:Dstpi_D0pi_Kpipipi', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
138 ma.reconstructDecay(decayString=
'D-:Kpipi -> K+:my pi-:my pi-:my',
139 cut=DcutLoose, dmID=4, path=rec_path_1)
141 vertex.kFit(list_name=
'D-:Kpipi', conf_level=0.0, fit_type=
'mass', path=rec_path_1)
142 ma.applyCuts(
"D-:Kpipi",
'1.844 < M < 1.894', path=rec_path_1)
145 ma.reconstructDecay(decayString=
'B0:Dpi_Kpipi -> D-:Kpipi pi+:my',
146 cut=BcutLoose, dmID=4, path=rec_path_1)
153 ma.reconstructDecay(decayString=
'B-:D0pi_Kpi -> D0:Kpi pi-:my',
155 dmID=5, path=rec_path_1)
156 ma.reconstructDecay(decayString=
'B-:D0pi_Kpipi0 -> D0:Kpipi0 pi-:my',
158 dmID=6, path=rec_path_1)
159 ma.reconstructDecay(decayString=
'B-:D0pi_Kpipipi -> D0:Kpipipi pi-:my',
161 dmID=7, path=rec_path_1)
163 vertex.treeFit(
'B-:D0pi_Kpi', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
164 vertex.treeFit(
'B-:D0pi_Kpipi0', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
165 vertex.treeFit(
'B-:D0pi_Kpipipi', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
168 outputListName=
'B0:merged',
171 'B0:Dstpi_D0pi_Kpipi0',
172 'B0:Dstpi_D0pi_Kpipipi',
178 outputListName=
'B-:merged',
187 ma.buildRestOfEvent(target_list_name=
'B0:merged', path=rec_path_1)
190 cleanMask = (
'cleanMask',
'nCDCHits > 0 and useCMSFrame(p)<=3.2',
'p >= 0.05 and useCMSFrame(p)<=3.2')
191 ma.appendROEMasks(list_name=
'B0:merged', mask_tuples=[cleanMask], path=rec_path_1)
192 ma.buildContinuumSuppression(list_name=
'B0:merged', roe_mask=
'cleanMask', path=rec_path_1)
195 ma.buildRestOfEvent(target_list_name=
'B-:merged', path=rec_path_1)
198 cleanMask = (
'cleanMask',
'nCDCHits > 0 and useCMSFrame(p)<=3.2',
'p >= 0.05 and useCMSFrame(p)<=3.2')
199 ma.appendROEMasks(list_name=
'B-:merged', mask_tuples=[cleanMask], path=rec_path_1)
200 ma.buildContinuumSuppression(list_name=
'B-:merged', roe_mask=
'cleanMask', path=rec_path_1)
202 ma.applyCuts(
"B0:merged",
"[R2 < 0.3] and " + Bcut, path=rec_path_1)
203 ma.applyCuts(
"B-:merged",
"[R2 < 0.3] and " + Bcut, path=rec_path_1)
208 def get_mumu_path(isCDST):
209 """ Selects the ee -> mumu events, function returns corresponding path """
212 rec_path_1 = create_path()
214 prepare_cdst_analysis(path=rec_path_1, components=[
'CDC',
'ECL',
'KLM'])
216 muSelection =
'[p>1.0]'
217 muSelection +=
' and abs(dz)<2.0 and abs(dr)<0.5'
218 muSelection +=
' and nPXDHits >=1 and nSVDHits >= 8 and nCDCHits >= 20'
220 ma.fillParticleList(
'mu+:BV', muSelection, path=rec_path_1)
221 ma.reconstructDecay(
'Upsilon(4S):BV -> mu+:BV mu-:BV',
'9.5<M<11.5', path=rec_path_1)
222 vertex.treeFit(
'Upsilon(4S):BV', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
227 def get_data_info(inData, kwargs):
228 """ Filter the input data and returns the IOVs """
232 file_to_iov_physics = inData
237 max_files_per_run = 1000000
243 reduced_file_to_iov_physics = filter_by_max_files_per_run(file_to_iov_physics, max_files_per_run)
244 input_files_physics = list(reduced_file_to_iov_physics.keys())
245 B2INFO(f
"Total number of files actually used as input = {len(input_files_physics)}")
249 requested_iov = kwargs.get(
"requested_iov",
None)
251 from caf.utils
import IoV
253 output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, -1, -1)
255 return input_files_physics, output_iov
258 def is_cDST_file(fName):
259 """ Check if the file is cDST based on the metadata """
261 metaData = get_file_metadata(fName)
262 description = metaData.getDataDescription()
265 if 'dataLevel' not in description:
266 B2WARNING(
'The cdst/mdst info is not stored in file metadata')
267 return (
'cdst' in os.path.basename(fName))
269 return (description[
'dataLevel'] ==
'cdst')
272 def get_calibrations(input_data, **kwargs):
274 Required function used by b2caf-prompt-run tool.
275 This function return a list of Calibration objects we assign to the CAF process.
278 input_data (dict): Should contain every name from the 'input_data_names' variable as a key.
279 Each value is a dictionary with {"/path/to/file_e1_r5.root": IoV(1,5,1,5), ...}. Useful for
280 assigning to calibration.files_to_iov
282 **kwargs: Configuration options to be sent in. Since this may change we use kwargs as a way to help prevent
283 backwards compatibility problems. But you could use the correct arguments in b2caf-prompt-run for this
284 release explicitly if you want to.
286 Currently only kwargs["output_iov"] is used. This is the output IoV range that your payloads should
287 correspond to. Generally your highest ExpRun payload should be open ended e.g. IoV(3,4,-1,-1)
290 list(caf.framework.Calibration): All of the calibration objects we want to assign to the CAF process
293 from caf.framework
import Calibration
294 from caf.strategies
import SingleIOV
296 from ROOT.Belle2
import InvariantMassAlgorithm
297 from caf.framework
import Collection
299 input_files_Had, output_iov_Had = get_data_info(input_data[
"hadron4S"], kwargs)
300 input_files_MuMu4S, output_iov_MuMu4S = get_data_info(input_data[
"mumu4S"], kwargs)
301 input_files_MuMuOff, output_iov_MuMuOff = get_data_info(input_data[
"mumuOff"], kwargs)
304 isCDST_had = is_cDST_file(input_files_Had[0])
if len(input_files_Had) > 0
else True
305 isCDST_mumu = is_cDST_file((input_files_MuMu4S + input_files_MuMuOff)[0])
307 rec_path_HadB = get_hadB_path(isCDST_had)
308 rec_path_MuMu = get_mumu_path(isCDST_mumu)
310 collector_HadB = register_module(
'EcmsCollector')
311 collector_MuMu = register_module(
'BoostVectorCollector', Y4SPListName=
'Upsilon(4S):BV')
313 algorithm_ecms = InvariantMassAlgorithm()
314 algorithm_ecms.setOuterLoss(kwargs[
'expert_config'][
'outerLoss'])
315 algorithm_ecms.setInnerLoss(kwargs[
'expert_config'][
'innerLoss'])
317 algorithm_ecms.includeHadBcalib(kwargs[
'expert_config'][
'runHadB'])
318 algorithm_ecms.setMuMuEcmsSpread(kwargs[
'expert_config'][
'eCMSmumuSpread'])
319 algorithm_ecms.setMuMuEcmsOffset(kwargs[
'expert_config'][
'eCMSmumuShift'])
322 algorithms=algorithm_ecms)
324 collection_HadB =
Collection(collector=collector_HadB,
325 input_files=input_files_Had,
326 pre_collector_path=rec_path_HadB)
327 collection_MuMu4S =
Collection(collector=collector_MuMu,
328 input_files=input_files_MuMu4S,
329 pre_collector_path=rec_path_MuMu)
330 collection_MuMuOff =
Collection(collector=collector_MuMu,
331 input_files=input_files_MuMuOff,
332 pre_collector_path=rec_path_MuMu)
334 calibration_ecms.add_collection(name=
'dimuon_4S', collection=collection_MuMu4S)
335 calibration_ecms.add_collection(name=
'dimuon_Off', collection=collection_MuMuOff)
336 calibration_ecms.add_collection(name=
'hadB_4S', collection=collection_HadB)
338 calibration_ecms.strategies = SingleIOV
343 for algorithm
in calibration_ecms.algorithms:
344 algorithm.params = {
"iov_coverage": output_iov_Had}
350 return [calibration_ecms]
def stdK(listtype=_defaultlist, path=None, writeOut=True)
def stdPi(listtype=_defaultlist, path=None, writeOut=True)
def stdPi0s(listtype="eff60_May2020", path=None, beamBackgroundMVAWeight="", fakePhotonMVAWeight="", biasCorrectionTable="")
def kFit(list_name, conf_level, fit_type='vertex', constraint='', daughtersUpdate=False, decay_string='', massConstraint=[], recoilMass=0, smearing=0, path=None)
def treeFit(list_name, conf_level=0.001, massConstraint=[], ipConstraint=False, updateAllDaughters=False, customOriginConstraint=False, customOriginVertex=[0.001, 0, 0.0116], customOriginCovariance=[0.0048, 0, 0, 0, 0.003567, 0, 0, 0, 0.0400], originDimension=3, treatAsInvisible='', ignoreFromVertexFit='', path=None)