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 were 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
104weightfiles = 'B2nunubarBGx1'
105
106# Flavor Tagging Function. Default Expert mode to use the official weight files.
107ft.flavorTagger(
108 particleLists=['B0:sig'],
109 weightFiles=weightfiles,
110 path=cp_val_path)
111
112# By default the flavorTagger trains and applies two methods, 'TMVA-FBDT' and 'FANN-MLP', for the combiner.
113# If you want to train or test the Flavor Tagger only for one of them you have to specify it like:
114#
115# combinerMethods=['TMVA-FBDT']
116#
117# All available categories are:
118# [
119# 'Electron',
120# 'IntermediateElectron',
121# 'Muon',
122# 'IntermediateMuon',
123# 'KinLepton',
124# 'IntermediateKinLepton',
125# 'Kaon',
126# 'SlowPion',
127# 'FastHadron',
128# 'Lambda',
129# 'FSC',
130# 'MaximumPstar',
131# 'KaonPion']
132#
133# If you want to train yourself, have a look at the scripts under analysis/release-validation/CPVTools/
134# in principle you need only to run CPVToolsValidatorInParalell.sh
135# If you train the event and combiner levels, you need two different samples of at least 500k events (one for each sampler).
136# The different samples are needed to avoid biases between levels.
137# We mean 500k of correctly corrected and MC matched neutral Bs. (isSignal > 0)
138# You can also train the event level for all categories and then train the combiner
139# for a specific combination (last two runs).
140# It is also possible to train different combiners consecutively using the same weightFiles name.
141# You just need always to specify the desired category combination while using the expert mode as:
142#
143# flavorTagger(particleLists=['B0:sig'], mode = 'Expert', weightFiles='B2JpsiKs_mu',
144# categories=['Electron', 'Muon', 'Kaon', ... etc.])
145#
146# Another possibility is to train a combiner for a specific category combination using the default weight files
147#
148# Attention: to train the flavor tagger you need MC samples generated without built-in CP violation!
149# The best sample for this is B0-> nu_tau anti-nu_tau .
150# You can apply cuts using the flavor Tagger: isNAN(qrOutput(FBDT)) < 1 rejects all events which do not
151# provide flavor information using the tag side
152ma.applyCuts(list_name='B0:sig',
153 cut='isNAN(qrOutput(FBDT)) < 1',
154 path=cp_val_path)
155
156# If you applied the cut on qrOutput(FBDT) > -2 before then you can rank by highest r- factor
157ma.rankByHighest(particleList='B0:sig',
158 variable='abs(qrOutput(FBDT))',
159 numBest=0,
160 outputVariable='Dilution_rank',
161 path=cp_val_path)
162
163# Fit vertex of the B0 on the signal side
164vx.kFit(list_name='B0:sig', conf_level=0.0, decay_string='B0:sig -> [J/psi:mumu -> ^mu+ ^mu-] K_S0',
165 constraint='', path=cp_val_path)
166
167
168# Fit Vertex of the B0 on the tag side
169vx.TagV(list_name='B0:sig', MCassociation='breco', path=cp_val_path)
170
171# Select variables that will be stored to ntuple
172fs_vars = vc.pid + vc.track + vc.track_hits + vc.mc_truth
173jpsiandk0s_vars = vc.mc_truth
174vertex_vars = vc.vertex + vc.mc_vertex + vc.kinematics + vc.mc_kinematics
175bvars = vc.reco_stats + \
176 vc.deltae_mbc + \
177 vc.mc_truth + \
178 vc.roe_multiplicities + \
179 vc.tag_vertex + \
180 vc.mc_tag_vertex + \
181 vertex_vars
182
183# Attention: the collection of flavor tagging variables is defined in the flavorTagger
184bvars += ft.flavor_tagging
185
186# Create aliases to save information for different particles
187bvars = bvars + \
188 vu.create_aliases_for_selected(list_of_variables=fs_vars,
189 decay_string='B0 -> [J/psi -> ^mu+ ^mu-] [K_S0 -> ^pi+ ^pi-]') + \
190 vu.create_aliases_for_selected(list_of_variables=jpsiandk0s_vars,
191 decay_string='B0 -> [^J/psi -> mu+ mu-] [^K_S0 -> pi+ pi-]') + \
192 vu.create_aliases_for_selected(list_of_variables=vertex_vars,
193 decay_string='B0 -> [^J/psi -> ^mu+ ^mu-] [^K_S0 -> ^pi+ ^pi-]')
194
195# Saving variables to ntuple
196output_file = 'B2A801-FlavorTagger.root'
197ma.variablesToNtuple(decayString='B0:sig',
198 variables=bvars,
199 filename=output_file,
200 treename='B0tree',
201 path=cp_val_path)
202
203# Summary of created Lists
204ma.summaryOfLists(particleLists=['J/psi:mumu', 'B0:sig'],
205 path=cp_val_path)
206
207# Process the events
208b2.process(cp_val_path)
209
210# print out the summary
211print(b2.statistics)
212
213# If you want to calculate the efficiency of the FlavorTagger on your own
214# File use the script analysis/release-validation/CPVTools/flavorTaggerEfficiency.py giving
215# your file and the treename as arguments:
216
217# basf2 flavorTaggerEfficiency.py 'YourFilesWithWildCards.root' 'B0tree'