Belle II Software  release-05-01-25
B2A711-DeepContinuumSuppression_Input.py
1 #!/usr/bin/env python3
2 
3 
20 
21 import basf2
22 import modularAnalysis as ma
23 from vertex import TagV
24 import glob
25 import os
26 import sys
27 import numpy as np
28 import variables as v
29 from root_pandas import read_root, to_root
30 import pandas
31 
32 basf2.set_log_level(basf2.LogLevel.ERROR)
33 
34 # --I/O----------------------------------------------------------------------------------------
35 if (len(sys.argv) < 2 or sys.argv[1] not in ['train', 'test', 'apply_signal', 'apply_qqbar']):
36  sys.exit("usage:\n\tbasf2 B2A701-ContinuumSuppression_Input.py <train,test,apply_signal,apply_qqbar>")
37 
38 step = str(sys.argv[1])
39 
40 path = '/group/belle2/tutorial/release_01-00-00/DCS_Bd_KsPi0'
41 train_inputfiles = glob.glob(path + '/*/*/*8.root.mdst')
42 val_inputfiles = glob.glob(path + '/*/*/*2.root.mdst')
43 signal_inputfiles = glob.glob(path + '/*/*/*1.root.mdst')
44 qqbar_inputfiles = glob.glob(path + '/*/*/*7.root.mdst')
45 
46 # shuffle file names
47 np.random.shuffle(train_inputfiles)
48 np.random.shuffle(val_inputfiles)
49 np.random.shuffle(signal_inputfiles)
50 np.random.shuffle(qqbar_inputfiles)
51 
52 if step == 'train':
53  input = train_inputfiles
54 elif step == 'test':
55  input = val_inputfiles
56 elif step == 'apply_signal':
57  input = signal_inputfiles
58 elif step == 'apply_qqbar':
59  input = qqbar_inputfiles
60 else:
61  sys.exit('Step does not match any of the available samples: `train`, `test`, `apply_signal`or `apply_qqbar`')
62 
63 outfile = step + '.root'
64 # ---------------------------------------------------------------------------------------------
65 
66 # Perform analysis.
67 firstpath = basf2.Path()
68 
69 ma.inputMdstList('default', input, path=firstpath)
70 
71 firstpath.add_module('ProgressBar')
72 
73 # Build B candidate like in B2A701-ContinuumSuppression_Input.py
74 ma.fillParticleList('gamma', 'goodGamma == 1', path=firstpath)
75 
76 ma.fillParticleList('pi+:good', 'chiProb > 0.001 and pionID > 0.5', path=firstpath)
77 
78 ma.reconstructDecay('K_S0 -> pi+:good pi-:good', '0.480<=M<=0.516', path=firstpath)
79 ma.reconstructDecay('pi0 -> gamma gamma', '0.115<=M<=0.152', path=firstpath)
80 ma.reconstructDecay('B0 -> K_S0 pi0', '5.2 < Mbc < 5.3 and -0.3 < deltaE < 0.2', path=firstpath)
81 
82 ma.matchMCTruth('B0', path=firstpath)
83 ma.buildRestOfEvent('B0', path=firstpath)
84 
85 cleanMask = ('cleanMask', 'nCDCHits > 0 and useCMSFrame(p)<=3.2', 'p >= 0.05 and useCMSFrame(p)<=3.2')
86 ma.appendROEMasks('B0', [cleanMask], path=firstpath)
87 
88 ma.buildContinuumSuppression('B0', 'cleanMask', path=firstpath)
89 
90 # Accept only correctly reconstructed B candidates as signal
91 ma.applyCuts('B0', 'isSignal or isContinuumEvent', path=firstpath)
92 
93 # Tag B candidate for Vertex information
94 TagV('B0', path=firstpath)
95 
96 # Loop over each possible ROE (1 for every B candidate) in every event
97 roe_path = basf2.create_path()
98 
99 deadEndPath = basf2.create_path()
100 
101 ma.signalSideParticleFilter('B0', '', roe_path, deadEndPath)
102 
103 # Build particle lists for low level variables
104 ma.fillParticleList('gamma:roe', 'isInRestOfEvent == 1 and goodGamma == 1', path=roe_path)
105 ma.fillParticleList('gamma:signal', 'isInRestOfEvent == 0 and goodGamma == 1', path=roe_path)
106 ma.fillParticleList('pi+:chargedProe', 'isInRestOfEvent == 1', path=roe_path)
107 ma.fillParticleList('pi+:chargedPsignal', 'isInRestOfEvent == 0', path=roe_path)
108 ma.fillParticleList('pi-:chargedMroe', 'isInRestOfEvent == 1', path=roe_path)
109 ma.fillParticleList('pi-:chargedMsignal', 'isInRestOfEvent == 0', path=roe_path)
110 
111 v.variables.addAlias('cmsp', 'useCMSFrame(p)')
112 
113 ma.rankByHighest('gamma:roe', 'cmsp', path=roe_path)
114 ma.rankByHighest('gamma:signal', 'cmsp', path=roe_path)
115 ma.rankByHighest('pi+:chargedProe', 'cmsp', path=roe_path)
116 ma.rankByHighest('pi+:chargedPsignal', 'cmsp', path=roe_path)
117 ma.rankByHighest('pi-:chargedMroe', 'cmsp', path=roe_path)
118 ma.rankByHighest('pi-:chargedMsignal', 'cmsp', path=roe_path)
119 
120 # Define traditional Continuum Suppression Variables
121 contVars = [
122  'R2',
123  'thrustBm',
124  'thrustOm',
125  'cosTBTO',
126  'cosTBz',
127  'KSFWVariables(et)',
128  'KSFWVariables(mm2)',
129  'KSFWVariables(hso00)',
130  'KSFWVariables(hso02)',
131  'KSFWVariables(hso04)',
132  'KSFWVariables(hso10)',
133  'KSFWVariables(hso12)',
134  'KSFWVariables(hso14)',
135  'KSFWVariables(hso20)',
136  'KSFWVariables(hso22)',
137  'KSFWVariables(hso24)',
138  'KSFWVariables(hoo0)',
139  'KSFWVariables(hoo1)',
140  'KSFWVariables(hoo2)',
141  'KSFWVariables(hoo3)',
142  'KSFWVariables(hoo4)',
143  'CleoCone(1)',
144  'CleoCone(2)',
145  'CleoCone(3)',
146  'CleoCone(4)',
147  'CleoCone(5)',
148  'CleoCone(6)',
149  'CleoCone(7)',
150  'CleoCone(8)',
151  'CleoCone(9)'
152 ]
153 
154 # Define additional low level variables
155 basic_variables = ['p', 'phi', 'cosTheta', 'pErr', 'phiErr', 'cosThetaErr']
156 vertex_variables = ['distance', 'dphi', 'dcosTheta']
157 cluster_specific_variables = ['clusterNHits', 'clusterTiming', 'clusterE9E25', 'clusterReg', 'isInRestOfEvent']
158 track_specific_variables = ['kaonID', 'electronID', 'muonID', 'protonID', 'pValue', 'nCDCHits', 'isInRestOfEvent', 'charge']
159 
160 # Aliases from normal coordinates to thrustframe coordinates
161 for variablename in basic_variables + vertex_variables:
162  v.variables.addAlias('thrustsig' + variablename, 'useBThrustFrame(' + variablename + ',Signal)')
163 
164 cluster_variables = cluster_specific_variables[:]
165 for variablename in basic_variables:
166  cluster_variables.append('thrustsig' + variablename)
167 
168 track_variables = track_specific_variables
169 for variablename in basic_variables + vertex_variables:
170  track_variables.append('thrustsig' + variablename)
171 
172 # General variables and training targets, which are nice to have in the Ntuple
173 variables = ['isContinuumEvent', 'isNotContinuumEvent', 'isSignal', 'M', 'p', 'Mbc', 'DeltaZ',
174  'deltaE', 'daughter(0, M)', 'daughter(0, p)', 'daughter(1, M)', 'daughter(1, p)']
175 
176 # Aliases for variable ranks created by rankByHighest function
177 for rank in range(10):
178  for shortcut, particlelist in [('Croe', 'gamma:roe'), ('Csig', 'gamma:signal')]:
179  for variable in cluster_variables:
180  v.variables.addAlias(
181  '{}_{}{}'.format(
182  variable, shortcut, rank), 'getVariableByRank({}, cmsp, {}, {})'.format(
183  particlelist, variable, rank + 1))
184  variables.append('{}_{}{}'.format(variable, shortcut, rank))
185 
186 for rank in range(5):
187  for shortcut, particlelist in [('TProe', 'pi+:chargedProe'), ('TPsig', 'pi+:chargedPsignal'),
188  ('TMroe', 'pi+:chargedMroe'), ('TMsig', 'pi+:chargedMsignal')]:
189  for variable in track_variables:
190  v.variables.addAlias(
191  '{}_{}{}'.format(
192  variable, shortcut, rank), 'getVariableByRank({}, cmsp, {}, {})'.format(
193  particlelist, variable, rank + 1))
194  variables.append('{}_{}{}'.format(variable, shortcut, rank))
195 
196 # Create output file.
197 ma.variablesToNtuple('B0', variables + contVars, treename='tree', filename=outfile, path=roe_path)
198 
199 # Loop over each possible ROE (1 for every B candidate) in every event
200 firstpath.for_each('RestOfEvent', 'RestOfEvents', roe_path)
201 
202 basf2.process(firstpath)
203 print(basf2.statistics)
204 
205 # Shuffle Data. Use only if enough Ram is available
206 df = read_root(outfile)
207 df = df.sample(frac=1)
208 df.to_root(outfile, key='tree')
basf2.process
def process(path, max_event=0)
Definition: __init__.py:25