Belle II Software development
B2A801-FlavorTagger.py
1#!/usr/bin/env python3
2
3
10
11
30
31import basf2 as b2
32import modularAnalysis as ma
33import flavorTagger as ft
34import vertex as vx
35import variables.collections as vc
36import variables.utils as vu
37
38
39# create path
40cp_val_path = b2.Path()
41
42# Environment of the MC or data sample
43environmentType = "default"
44
45# For Belle data/MC use
46# from b2biiConversion import convertBelleMdstToBelleIIMdst
47# import os
48
49# os.environ['PGUSER'] = 'g0db'
50# os.environ['USE_GRAND_REPROCESS_DATA'] = '1'
51
52# environmentType = "Belle"
53
54# # You can use Belle MC/data as input calling this script as basf2 -i 'YourConvertedBelleData*.root' B2A801-FlavorTagger.py
55# ma.inputMdstList(environmentType=environmentType, filelist=[], path=cp_val_path)
56
57
58# load input ROOT file
59ma.inputMdst(environmentType=environmentType,
60 filename=b2.find_file('analysis/mdst11_BGx1_b2jpsiks.root', 'validation', False),
61 path=cp_val_path)
62
63
64# Creates Muon particle list
65ma.fillParticleList(decayString='mu+:all', cut='', path=cp_val_path)
66
67# reconstruct J/psi -> mu+ mu- decay
68# keep only candidates with dM<0.11
69ma.reconstructDecay(decayString='J/psi:mumu -> mu+:all mu-:all', cut='dM<0.11', path=cp_val_path)
70
71
72# For Belle data/MC use
73# # use the existent K_S0:mdst list to reconstruct B0 -> J/psi Ks decay
74# ma.reconstructDecay(decayString='B0:sig -> J/psi:mumu K_S0:mdst', cut='Mbc > 5.2 and abs(deltaE)<0.15', path=cp_val_path)
75
76
77# reconstruct Ks from standard pi+ particle list
78ma.fillParticleList(decayString='pi+:all', cut='', path=cp_val_path)
79ma.reconstructDecay(decayString='K_S0:pipi -> pi+:all pi-:all', cut='dM<0.25', path=cp_val_path)
80
81# reconstruct B0 -> J/psi Ks decay
82ma.reconstructDecay(decayString='B0:sig -> J/psi:mumu K_S0:pipi', cut='Mbc > 5.2 and abs(deltaE)<0.15', path=cp_val_path)
83
84# Does the matching between reconstructed and MC particles
85ma.matchMCTruth(list_name='B0:sig', path=cp_val_path)
86
87# build the rest of the event associated to the B0
88ma.buildRestOfEvent(target_list_name='B0:sig', fillWithMostLikely=True,
89 path=cp_val_path)
90
91b2.conditions.append_globaltag(ma.getAnalysisGlobaltag())
92
93# The default working directory is '.'
94# Note that if you also train by yourself the weights of the trained Methods are saved therein.
95# To save CPU time the weight files should be saved in the same server where you run.
96#
97# NEVER set uploadToDatabaseAfterTraining to True if you are not a librarian!!!
98#
99# BGx1 stays for MC generated with machine Background.
100# The official weight files are trained using B0-> nu_tau anti-nu_tau as signal channel (no CP violation)
101# to avoid that the flavor tagger learns asymmetries on the tag side.
102# Only this kind of weight files are supported since release-03-01-00.
103
104# Flavor Tagging Function. Default Expert mode to use the official weight files.
105ft.flavorTagger(
106 particleLists=['B0:sig'],
107 useGNN=False,
108 path=cp_val_path)
109
110# All available categories are:
111# [
112# 'Electron',
113# 'IntermediateElectron',
114# 'Muon',
115# 'IntermediateMuon',
116# 'KinLepton',
117# 'IntermediateKinLepton',
118# 'Kaon',
119# 'SlowPion',
120# 'FastHadron',
121# 'Lambda',
122# 'FSC',
123# 'MaximumPstar',
124# 'KaonPion']
125#
126# If you want to train yourself, have a look at the scripts at
127# https://gitlab.desy.de/belle2/performance/releasevalidation/-/tree/main/CPVTools
128# In principle, you only need to run CPVToolsValidatorInParalell.sh
129# If you train the event and combiner levels, you need two different samples of at least 500k events (one for each sampler).
130# The different samples are needed to avoid biases between levels.
131# We mean 500k of correctly corrected and MC matched neutral Bs. (isSignal > 0)
132# You can also train the event level for all categories and then train the combiner
133# for a specific combination (last two runs).
134# It is also possible to train different combiners consecutively using the same weightFiles name.
135# You just need always to specify the desired category combination while using the expert mode as:
136#
137# flavorTagger(particleLists=['B0:sig'], mode = 'Expert', weightFiles='B2JpsiKs_mu',
138# categories=['Electron', 'Muon', 'Kaon', ... etc.])
139#
140# Another possibility is to train a combiner for a specific category combination using the default weight files
141#
142# Attention: to train the flavor tagger you need MC samples generated without built-in CP violation!
143# The best sample for this is B0-> nu_tau anti-nu_tau .
144# You can apply cuts using the flavor Tagger: isNAN(qrOutput(FBDT)) < 1 rejects all events which do not
145# provide flavor information using the tag side
146ma.applyCuts(list_name='B0:sig',
147 cut='isNAN(qrOutput(FBDT)) < 1',
148 path=cp_val_path)
149
150# If you applied the cut on qrOutput(FBDT) > -2 before then you can rank by highest r- factor
151ma.rankByHighest(particleList='B0:sig',
152 variable='abs(qrOutput(FBDT))',
153 numBest=0,
154 outputVariable='Dilution_rank',
155 path=cp_val_path)
156
157# Fit vertex of the B0 on the signal side
158vx.kFit(list_name='B0:sig', conf_level=0.0, decay_string='B0:sig -> [J/psi:mumu -> ^mu+ ^mu-] K_S0',
159 constraint='', path=cp_val_path)
160
161
162# Fit Vertex of the B0 on the tag side
163vx.TagV(list_name='B0:sig', MCassociation='breco', path=cp_val_path)
164
165# Select variables that will be stored to ntuple
166fs_vars = vc.pid + vc.track + vc.track_hits + vc.mc_truth
167jpsiandk0s_vars = vc.mc_truth
168vertex_vars = vc.vertex + vc.mc_vertex + vc.kinematics + vc.mc_kinematics
169bvars = vc.reco_stats + \
170 vc.deltae_mbc + \
171 vc.mc_truth + \
172 vc.roe_multiplicities + \
173 vc.tag_vertex + \
174 vc.mc_tag_vertex + \
175 vertex_vars
176
177# Attention: the collection of flavor tagging variables is defined in the flavorTagger
178bvars += ft.flavor_tagging
179
180# Create aliases to save information for different particles
181bvars = bvars + \
182 vu.create_aliases_for_selected(list_of_variables=fs_vars,
183 decay_string='B0 -> [J/psi -> ^mu+ ^mu-] [K_S0 -> ^pi+ ^pi-]') + \
184 vu.create_aliases_for_selected(list_of_variables=jpsiandk0s_vars,
185 decay_string='B0 -> [^J/psi -> mu+ mu-] [^K_S0 -> pi+ pi-]') + \
186 vu.create_aliases_for_selected(list_of_variables=vertex_vars,
187 decay_string='B0 -> [^J/psi -> ^mu+ ^mu-] [^K_S0 -> ^pi+ ^pi-]')
188
189# Saving variables to ntuple
190output_file = 'B2A801-FlavorTagger.root'
191ma.variablesToNtuple(decayString='B0:sig',
192 variables=bvars,
193 filename=output_file,
194 treename='B0tree',
195 path=cp_val_path)
196
197# Summary of created Lists
198ma.summaryOfLists(particleLists=['J/psi:mumu', 'B0:sig'],
199 path=cp_val_path)
200
201# Process the events
202b2.process(cp_val_path)
203
204# print out the summary
205print(b2.statistics)