29import modularAnalysis
as ma
31from b2pandas_utils
import VariablesToTable
32from variables
import variables
as vm
34parser = argparse.ArgumentParser()
35parser.add_argument(
'--input', nargs=
'+', default=
None,
36 help=
'Input ROOT file(s) with FEI B meson candidates')
37parser.add_argument(
'--output', default=
'modeSelector_output',
38 help=
'Output parquet filename or stem (default: modeSelector_output)')
39parser.add_argument(
'--cat-model', default=
None,
40 help=
'Path to category MVA ONNX weightfile (omit to use payloads)')
41parser.add_argument(
'--main-model', default=
None,
42 help=
'Path to main MVA ONNX weightfile (omit to use payloads)')
43parser.add_argument(
'--cat-payload-name', default=
None,
44 help=
'Conditions DB payload name for the category model (default: derived from the contract version)')
45parser.add_argument(
'--main-payload-name', default=
None,
46 help=
'Conditions DB payload name for the main model (default: derived from the contract version)')
47parser.add_argument(
'--globaltag', default=
None,
48 help=
'Additional globaltag holding the ModeSelector payloads, prepended to the analysis globaltag')
49parser.add_argument(
'--data', action=
'store_true',
50 help=
'Run in data mode: keep 10% of events with eventRandom and drop MC-only output variables')
51args = parser.parse_args()
55 args.input = [b2.find_file(
'udst16_feiHadronic.root',
'validation')]
57output_root, output_suffix = os.path.splitext(args.output)
58if output_suffix.lower()
in [
'.pq',
'.parquet']:
59 final_output = args.output
60elif output_suffix !=
'':
61 final_output = output_root +
'.pq'
63 final_output = args.output +
'.pq'
66b2.set_random_seed(1337)
69my_path = b2.create_path()
77b2.conditions.prepend_globaltag(ma.getAnalysisGlobaltag())
83 b2.conditions.prepend_globaltag(args.globaltag)
86fei_identifier =
'feiHadronic'
89particle_lists = [f
'B+:{fei_identifier}', f
'B0:{fei_identifier}']
92 ma.applyEventCuts(
'eventRandom < 0.1', path=my_path)
95 for plist
in particle_lists:
96 ma.matchMCTruth(plist, path=my_path)
99 ma.applyEventCuts(
'eventRandom > 0.95', path=my_path)
102track_mask =
"[[dr < 2] and [abs(dz) < 4] and [pt > 0.2] and [thetaInCDCAcceptance==1]]"
103ecl_mask = (
"[[[[clusterReg==1] and [E>0.080]] or [[clusterReg==2] and [E > 0.03]] "
104 "or [[clusterReg==3] and [E > 0.06]]] and [clusterNHits > 1.5] "
105 "and [abs(clusterTiming) < 200] and [thetaInCDCAcceptance==1]]")
106cleanMask = (
"cleanMask", track_mask, ecl_mask)
109for b
in [
'B+',
'B0']:
110 ma.applyCuts(f
'{b}:{fei_identifier}',
'[Mbc > 5.23] and [-0.15 < deltaE < 0.1]', path=my_path)
113 ma.buildRestOfEvent(f
'{b}:{fei_identifier}', path=my_path)
114 ma.appendROEMasks(f
'{b}:{fei_identifier}', [cleanMask], path=my_path)
117 ma.buildContinuumSuppression(f
'{b}:{fei_identifier}',
'cleanMask', path=my_path)
120 ma.applyCuts(f
'{b}:{fei_identifier}',
'cosTBTO < 0.9', path=my_path)
123 ma.rankByHighest(f
'{b}:{fei_identifier}',
'sigProb', outputVariable=
'sigProb_rank', path=my_path)
131 harmonicMoments=
True,
140 bp_list=f
'B+:{fei_identifier}',
141 b0_list=f
'B0:{fei_identifier}',
142 cat_model_path=args.cat_model,
143 main_model_path=args.main_model,
144 payload_cat_model=args.cat_payload_name,
145 payload_main_model=args.main_payload_name,
146 output_variable=
'BplusScore',
147 store_fei_calib_weight=
not args.data,
160for b
in [
'B+',
'B0']:
161 ma.applyCuts(f
'{b}:{fei_identifier}',
'[sigProb_rank == 1] or [modeSelector_rank == 1]', path=my_path)
164 modeSelector.addGeneratedDecayWeights(
165 bp_list=f
'B+:{fei_identifier}',
166 b0_list=f
'B0:{fei_identifier}',
171ma.fillParticleList(decayString=
"pi+:test", cut=
'', path=my_path)
174vm.addAlias(
'sigProbRank_global', f
'sigProbRank(B+:{fei_identifier}, B0:{fei_identifier})')
176vm.addAlias(
'isBestCandidate_sigProb',
'conditionalVariableSelector(sigProbRank_global == 1, 1, 0)')
179vm.addAlias(
'sigProb',
'extraInfo(SignalProbability)')
180vm.addAlias(
'dmID',
'extraInfo(decayModeID)')
182candidate_variables = [
185 'modeSelector_eqSigProb',
186 'Dstp_deltaMassDiff',
188 'Dst0_deltaMassDiff',
193vu.create_aliases(candidate_variables, wrapper=
'extraInfo({variable})')
195event_output_variables = [
197 'modeSelector_catB0',
198 'modeSelector_catBp',
199 'modeSelector_catCont',
201vu.create_aliases(event_output_variables, wrapper=
'eventExtraInfo({variable})')
206 'Mbc',
'deltaE',
'M',
213 'modeSelector_eqSigProb',
216 'modeSelector_catB0',
217 'modeSelector_catBp',
218 'modeSelector_catCont',
221 'Dstp_deltaMassDiff',
223 'Dst0_deltaMassDiff',
228 'sigProbRank_global',
229 'isBestCandidate_sigProb',
234 vm.addAlias(
'modeSelector_feiCalibWeight',
'eventExtraInfo(modeSelector_feiCalibWeight)')
235 output_variables.extend([
240 'mostcommonBTagDeltaP',
242 'modeSelector_feiCalibWeight',
246for b, b_str
in zip([
'B+',
'B0'], [
'Bp',
'B0']):
248 f
'Upsilon(4S):{b_str} -> {b}:{fei_identifier}',
250 allowChargeViolation=
True,
255 outputListName=
'Upsilon(4S):all',
256 inputListNames=[
'Upsilon(4S):Bp',
'Upsilon(4S):B0'],
261merged_output_variables = vu.create_daughter_aliases(
265 include_indices=
False
268v2t = VariablesToTable(
270 variables=merged_output_variables,
271 filename=final_output,
272 event_buffer_size=500_000,
274my_path.add_module(v2t)
modeSelector(bp_list, b0_list, payload_cat_model=None, payload_main_model=None, output_variable='BplusScore', cat_model_path=None, main_model_path=None, addDstarVetoReco=True, training_mode=False, skip_nn_evaluation=False, store_fei_calib_weight=False, debug=False, debug_max_events=10, path=None)