10Airflow script to perform eCMS calibration (combination of the had-B and mumu method).
13from prompt
import CalibrationSettings, INPUT_DATA_FILTERS
14from prompt.calibrations.caf_boostvector
import settings
as boostvector
15from reconstruction
import add_pid_module, add_ecl_modules, prepare_cdst_analysis
17from basf2
import create_path, register_module, get_file_metadata, B2INFO, B2WARNING
18import modularAnalysis
as ma
26settings = 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])
64def 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)
208def 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)
227def 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
258def 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')
272def 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
import Belle2
297 from ROOT.Belle2
import InvariantMassAlgorithm
298 from caf.framework
import Collection
300 input_files_Had, output_iov_Had = get_data_info(input_data[
"hadron4S"], kwargs)
301 input_files_MuMu4S, output_iov_MuMu4S = get_data_info(input_data[
"mumu4S"], kwargs)
302 input_files_MuMuOff, output_iov_MuMuOff = get_data_info(input_data[
"mumuOff"], kwargs)
305 isCDST_had = is_cDST_file(input_files_Had[0])
if len(input_files_Had) > 0
else True
306 isCDST_mumu = is_cDST_file((input_files_MuMu4S + input_files_MuMuOff)[0])
308 rec_path_HadB = get_hadB_path(isCDST_had)
309 rec_path_MuMu = get_mumu_path(isCDST_mumu)
311 collector_HadB = register_module(
'EcmsCollector')
312 collector_MuMu = register_module(
'BoostVectorCollector', Y4SPListName=
'Upsilon(4S):BV')
314 algorithm_ecms = InvariantMassAlgorithm()
315 algorithm_ecms.setOuterLoss(kwargs[
'expert_config'][
'outerLoss'])
316 algorithm_ecms.setInnerLoss(kwargs[
'expert_config'][
'innerLoss'])
318 algorithm_ecms.includeHadBcalib(kwargs[
'expert_config'][
'runHadB'])
319 algorithm_ecms.setMuMuEcmsSpread(kwargs[
'expert_config'][
'eCMSmumuSpread'])
320 algorithm_ecms.setMuMuEcmsOffset(kwargs[
'expert_config'][
'eCMSmumuShift'])
323 algorithms=algorithm_ecms)
325 collection_HadB =
Collection(collector=collector_HadB,
326 input_files=input_files_Had,
327 pre_collector_path=rec_path_HadB)
328 collection_MuMu4S =
Collection(collector=collector_MuMu,
329 input_files=input_files_MuMu4S,
330 pre_collector_path=rec_path_MuMu)
331 collection_MuMuOff =
Collection(collector=collector_MuMu,
332 input_files=input_files_MuMuOff,
333 pre_collector_path=rec_path_MuMu)
335 calibration_ecms.add_collection(name=
'dimuon_4S', collection=collection_MuMu4S)
336 calibration_ecms.add_collection(name=
'dimuon_Off', collection=collection_MuMuOff)
337 calibration_ecms.add_collection(name=
'hadB_4S', collection=collection_HadB)
339 calibration_ecms.strategies = SingleIOV
344 for algorithm
in calibration_ecms.algorithms:
345 algorithm.params = {
"iov_coverage": output_iov_Had}
351 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 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)
def kFit(list_name, conf_level, fit_type='vertex', constraint='', daughtersUpdate=False, decay_string='', massConstraint=[], recoilMass=0, smearing=0, path=None)