12 Airflow script to perform eCMS calibration (combination of the had-B and mumu method).
15 from prompt
import CalibrationSettings, INPUT_DATA_FILTERS
16 from prompt.calibrations.caf_boostvector
import settings
as boostvector
17 from reconstruction
import add_pid_module, add_ecl_modules, prepare_cdst_analysis
19 from basf2
import create_path, register_module, B2INFO
20 import modularAnalysis
as ma
27 settings = CalibrationSettings(
28 name=
"Ecms Calibrations",
29 expert_username=
"zlebcr",
31 input_data_formats=[
"cdst"],
32 input_data_names=[
"hadron4S",
"mumu4S",
"mumuOff"],
35 INPUT_DATA_FILTERS[
"Data Tag"][
"btocharm_calib"],
36 INPUT_DATA_FILTERS[
"Run Type"][
"physics"],
37 INPUT_DATA_FILTERS[
"Beam Energy"][
"4S"],
38 INPUT_DATA_FILTERS[
"Data Quality Tag"][
"Good Or Recoverable"],
39 INPUT_DATA_FILTERS[
"Magnet"][
"On"]],
41 INPUT_DATA_FILTERS[
"Data Tag"][
"mumu_tight_or_highm_calib"],
42 INPUT_DATA_FILTERS[
"Run Type"][
"physics"],
43 INPUT_DATA_FILTERS[
"Beam Energy"][
"4S"],
44 INPUT_DATA_FILTERS[
"Data Quality Tag"][
"Good Or Recoverable"],
45 INPUT_DATA_FILTERS[
"Magnet"][
"On"]],
47 INPUT_DATA_FILTERS[
"Data Tag"][
"mumu_tight_or_highm_calib"],
48 INPUT_DATA_FILTERS[
"Run Type"][
"physics"],
49 INPUT_DATA_FILTERS[
"Beam Energy"][
"Continuum"],
50 INPUT_DATA_FILTERS[
'Beam Energy'][
'Scan'],
51 INPUT_DATA_FILTERS[
"Data Quality Tag"][
"Good Or Recoverable"],
52 INPUT_DATA_FILTERS[
"Magnet"][
"On"]]
55 "outerLoss":
"pow(0.000010e0*rawTime, 2) + 1./nEv",
56 "innerLoss":
"pow(0.000120e0*rawTime, 2) + 1./nEv",
58 "eCMSmumuSpread": 5.2e-3,
59 "eCMSmumuShift": 10e-3},
60 depends_on=[boostvector])
65 def get_hadB_path(isCDST):
66 """ Selects the hadronic B decays, function returns corresponding path """
69 rec_path_1 = create_path()
71 prepare_cdst_analysis(path=rec_path_1, components=[
'CDC',
'ECL',
'KLM'])
73 add_pid_module(rec_path_1)
74 add_ecl_modules(rec_path_1)
80 ma.cutAndCopyList(
"pi+:my",
"pi+:loose",
"[abs(dz)<2.0] and [abs(dr)<0.5]", path=rec_path_1)
81 ma.cutAndCopyList(
"K+:my",
"K+:good",
"[abs(dz)<2.0] and [abs(dr)<0.5]", path=rec_path_1)
83 ma.cutAndCopyList(
"pi0:my",
"pi0:eff40_May2020",
"", path=rec_path_1)
89 DcutLoose =
'1.7 < M < 2.1'
90 Dcut =
'1.830 < M < 1.894'
92 ma.reconstructDecay(decayString=
'D0:Kpi -> K-:my pi+:my', cut=DcutLoose, dmID=1, path=rec_path_1)
93 ma.reconstructDecay(decayString=
'D0:Kpipi0 -> K-:my pi+:my pi0:my',
94 cut=DcutLoose, dmID=2, path=rec_path_1)
95 ma.reconstructDecay(decayString=
'D0:Kpipipi -> K-:my pi+:my pi-:my pi+:my',
96 cut=DcutLoose, dmID=3, path=rec_path_1)
99 vertex.kFit(list_name=
'D0:Kpi', conf_level=0.0, fit_type=
'mass', path=rec_path_1)
101 vertex.kFit(list_name=
'D0:Kpipipi', conf_level=0.0, fit_type=
'mass', path=rec_path_1)
103 ma.applyCuts(
"D0:Kpi", Dcut, path=rec_path_1)
104 ma.applyCuts(
"D0:Kpipi0", Dcut, path=rec_path_1)
105 ma.applyCuts(
"D0:Kpipipi", Dcut, path=rec_path_1)
107 DStarcutLoose =
'massDifference(0) < 0.16'
110 ma.reconstructDecay(decayString=
'D*+:D0pi_Kpi -> D0:Kpi pi+:my', cut=DStarcutLoose, dmID=1, path=rec_path_1)
111 ma.reconstructDecay(decayString=
'D*+:D0pi_Kpipi0 -> D0:Kpipi0 pi+:my',
112 cut=DStarcutLoose, dmID=2, path=rec_path_1)
113 ma.reconstructDecay(decayString=
'D*+:D0pi_Kpipipi -> D0:Kpipipi pi+:my',
114 cut=DStarcutLoose, dmID=3, path=rec_path_1)
116 BcutLoose =
'[ useCMSFrame(p) < 1.6 ] and [abs(dM) < 0.25]'
117 Bcut =
'[ useCMSFrame(p) < 1.2 ] and [abs(dM) < 0.05]'
120 ma.reconstructDecay(decayString=
'B0:Dstpi_D0pi_Kpi -> D*-:D0pi_Kpi pi+:my',
122 dmID=1, path=rec_path_1)
123 ma.reconstructDecay(decayString=
'B0:Dstpi_D0pi_Kpipi0 -> D*-:D0pi_Kpipi0 pi+:my',
125 dmID=2, path=rec_path_1)
126 ma.reconstructDecay(decayString=
'B0:Dstpi_D0pi_Kpipipi -> D*-:D0pi_Kpipipi pi+:my',
128 dmID=3, path=rec_path_1)
130 vertex.treeFit(
'B0:Dstpi_D0pi_Kpi', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
131 vertex.treeFit(
'B0:Dstpi_D0pi_Kpipi0', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
132 vertex.treeFit(
'B0:Dstpi_D0pi_Kpipipi', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
139 ma.reconstructDecay(decayString=
'D-:Kpipi -> K+:my pi-:my pi-:my',
140 cut=DcutLoose, dmID=4, path=rec_path_1)
142 vertex.kFit(list_name=
'D-:Kpipi', conf_level=0.0, fit_type=
'mass', path=rec_path_1)
143 ma.applyCuts(
"D-:Kpipi",
'1.844 < M < 1.894', path=rec_path_1)
146 ma.reconstructDecay(decayString=
'B0:Dpi_Kpipi -> D-:Kpipi pi+:my',
147 cut=BcutLoose, dmID=4, path=rec_path_1)
154 ma.reconstructDecay(decayString=
'B-:D0pi_Kpi -> D0:Kpi pi-:my',
156 dmID=5, path=rec_path_1)
157 ma.reconstructDecay(decayString=
'B-:D0pi_Kpipi0 -> D0:Kpipi0 pi-:my',
159 dmID=6, path=rec_path_1)
160 ma.reconstructDecay(decayString=
'B-:D0pi_Kpipipi -> D0:Kpipipi pi-:my',
162 dmID=7, path=rec_path_1)
164 vertex.treeFit(
'B-:D0pi_Kpi', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
165 vertex.treeFit(
'B-:D0pi_Kpipi0', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
166 vertex.treeFit(
'B-:D0pi_Kpipipi', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
169 outputListName=
'B0:merged',
172 'B0:Dstpi_D0pi_Kpipi0',
173 'B0:Dstpi_D0pi_Kpipipi',
179 outputListName=
'B-:merged',
188 ma.buildRestOfEvent(target_list_name=
'B0:merged', path=rec_path_1)
191 cleanMask = (
'cleanMask',
'nCDCHits > 0 and useCMSFrame(p)<=3.2',
'p >= 0.05 and useCMSFrame(p)<=3.2')
192 ma.appendROEMasks(list_name=
'B0:merged', mask_tuples=[cleanMask], path=rec_path_1)
193 ma.buildContinuumSuppression(list_name=
'B0:merged', roe_mask=
'cleanMask', path=rec_path_1)
196 ma.buildRestOfEvent(target_list_name=
'B-:merged', path=rec_path_1)
199 cleanMask = (
'cleanMask',
'nCDCHits > 0 and useCMSFrame(p)<=3.2',
'p >= 0.05 and useCMSFrame(p)<=3.2')
200 ma.appendROEMasks(list_name=
'B-:merged', mask_tuples=[cleanMask], path=rec_path_1)
201 ma.buildContinuumSuppression(list_name=
'B-:merged', roe_mask=
'cleanMask', path=rec_path_1)
203 ma.applyCuts(
"B0:merged",
"[R2 < 0.3] and " + Bcut, path=rec_path_1)
204 ma.applyCuts(
"B-:merged",
"[R2 < 0.3] and " + Bcut, path=rec_path_1)
209 def get_mumu_path(isCDST):
210 """ Selects the ee -> mumu events, function returns corresponding path """
213 rec_path_1 = create_path()
215 prepare_cdst_analysis(path=rec_path_1, components=[
'CDC',
'ECL',
'KLM'])
217 muSelection =
'[p>1.0]'
218 muSelection +=
' and abs(dz)<2.0 and abs(dr)<0.5'
219 muSelection +=
' and nPXDHits >=1 and nSVDHits >= 8 and nCDCHits >= 20'
221 ma.fillParticleList(
'mu+:BV', muSelection, path=rec_path_1)
222 ma.reconstructDecay(
'Upsilon(4S):BV -> mu+:BV mu-:BV',
'9.5<M<11.5', path=rec_path_1)
223 vertex.treeFit(
'Upsilon(4S):BV', updateAllDaughters=
True, ipConstraint=
True, path=rec_path_1)
228 def get_data_info(inData, kwargs):
229 """ Filter the input data and returns the IOVs """
233 file_to_iov_physics = inData
238 max_files_per_run = 1000000
244 reduced_file_to_iov_physics = filter_by_max_files_per_run(file_to_iov_physics, max_files_per_run)
245 input_files_physics = list(reduced_file_to_iov_physics.keys())
246 B2INFO(f
"Total number of files actually used as input = {len(input_files_physics)}")
250 requested_iov = kwargs.get(
"requested_iov",
None)
252 from caf.utils
import IoV
254 output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, -1, -1)
256 return input_files_physics, output_iov
259 def get_calibrations(input_data, **kwargs):
261 Required function used by b2caf-prompt-run tool.
262 This function return a list of Calibration objects we assign to the CAF process.
265 input_data (dict): Should contain every name from the 'input_data_names' variable as a key.
266 Each value is a dictionary with {"/path/to/file_e1_r5.root": IoV(1,5,1,5), ...}. Useful for
267 assigning to calibration.files_to_iov
269 **kwargs: Configuration options to be sent in. Since this may change we use kwargs as a way to help prevent
270 backwards compatibility problems. But you could use the correct arguments in b2caf-prompt-run for this
271 release explicitly if you want to.
273 Currently only kwargs["output_iov"] is used. This is the output IoV range that your payloads should
274 correspond to. Generally your highest ExpRun payload should be open ended e.g. IoV(3,4,-1,-1)
277 list(caf.framework.Calibration): All of the calibration objects we want to assign to the CAF process
280 from caf.framework
import Calibration
281 from caf.strategies
import SingleIOV
283 from ROOT.Belle2
import InvariantMassAlgorithm
284 from caf.framework
import Collection
286 input_files_Had, output_iov_Had = get_data_info(input_data[
"hadron4S"], kwargs)
287 input_files_MuMu4S, output_iov_MuMu4S = get_data_info(input_data[
"mumu4S"], kwargs)
288 input_files_MuMuOff, output_iov_MuMuOff = get_data_info(input_data[
"mumuOff"], kwargs)
290 isCDST =
'mdst' not in (input_files_MuMu4S + input_files_MuMuOff)[0]
292 rec_path_HadB = get_hadB_path(isCDST)
293 rec_path_MuMu = get_mumu_path(isCDST)
295 collector_HadB = register_module(
'EcmsCollector')
296 collector_MuMu = register_module(
'BoostVectorCollector', Y4SPListName=
'Upsilon(4S):BV')
298 algorithm_ecms = InvariantMassAlgorithm()
299 algorithm_ecms.setOuterLoss(kwargs[
'expert_config'][
'outerLoss'])
300 algorithm_ecms.setInnerLoss(kwargs[
'expert_config'][
'innerLoss'])
302 algorithm_ecms.includeHadBcalib(kwargs[
'expert_config'][
'runHadB'])
303 algorithm_ecms.setMuMuEcmsSpread(kwargs[
'expert_config'][
'eCMSmumuSpread'])
304 algorithm_ecms.setMuMuEcmsOffset(kwargs[
'expert_config'][
'eCMSmumuShift'])
307 algorithms=algorithm_ecms)
309 collection_HadB =
Collection(collector=collector_HadB,
310 input_files=input_files_Had,
311 pre_collector_path=rec_path_HadB)
312 collection_MuMu4S =
Collection(collector=collector_MuMu,
313 input_files=input_files_MuMu4S,
314 pre_collector_path=rec_path_MuMu)
315 collection_MuMuOff =
Collection(collector=collector_MuMu,
316 input_files=input_files_MuMuOff,
317 pre_collector_path=rec_path_MuMu)
319 calibration_ecms.add_collection(name=
'dimuon_4S', collection=collection_MuMu4S)
320 calibration_ecms.add_collection(name=
'dimuon_Off', collection=collection_MuMuOff)
321 calibration_ecms.add_collection(name=
'hadB_4S', collection=collection_HadB)
323 calibration_ecms.strategies = SingleIOV
328 for algorithm
in calibration_ecms.algorithms:
329 algorithm.params = {
"iov_coverage": output_iov_Had}
335 return [calibration_ecms]
def stdPi(listtype=_defaultlist, path=None)
def stdK(listtype=_defaultlist, path=None)
def stdPi0s(listtype="eff60_May2020", path=None, loadPhotonBeamBackgroundMVA=False)
def kFit(list_name, conf_level, fit_type='vertex', constraint='', daughtersUpdate=False, decay_string='', massConstraint=[], 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], path=None)