Belle II Software  release-06-01-15
quarkonium.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 
11 
12 """ Skim list building functions for quarkonium analyses: bottomonium, charmonium, resonance """
13 
14 import modularAnalysis as ma
15 from skim import BaseSkim, fancy_skim_header
16 from stdPhotons import stdPhotons
17 from stdV0s import stdLambdas
18 from variables import variables as v
19 
20 __liaison__ = "Sen Jia <jiasen@buaa.edu.cn>"
21 _VALIDATION_SAMPLE = "mdst14.root"
22 
23 
24 @fancy_skim_header
26  """
27  Reconstructed decay modes:
28 
29  * ``eta_b -> gamma gamma``
30 
31  Selection criteria:
32 
33  * ``2 std photon with E > 3.5 GeV``
34  * ``7 < M(eta_b) < 10 GeV/c^2``
35  * ``foxWolframR2 < 0.995``
36  """
37 
38  __authors__ = ["Stefano Spataro", "Sen Jia"]
39  __description__ = ""
40  __contact__ = __liaison__
41  __category__ = "physics, quarkonium"
42 
43  def load_standard_lists(self, path):
44  stdPhotons("loose", path=path, loadPhotonBeamBackgroundMVA=False)
45 
46  def build_lists(self, path):
47  # create and fill hard photon
48  ma.fillParticleList(decayString="pi+:BottomoniumEtab_eventshape", cut="pt > 0.1", path=path)
49  ma.fillParticleList(decayString="gamma:BottomoniumEtab_eventshape", cut="E > 0.1", path=path,
50  loadPhotonBeamBackgroundMVA=False)
51 
52  ma.buildEventShape(inputListNames=["pi+:BottomoniumEtab_eventshape", "gamma:BottomoniumEtab_eventshape"],
53  allMoments=False,
54  foxWolfram=True,
55  harmonicMoments=False,
56  cleoCones=False,
57  thrust=False,
58  collisionAxis=False,
59  jets=False,
60  sphericity=False,
61  checkForDuplicates=False,
62  path=path)
63 
64  ma.cutAndCopyList("gamma:hard", "gamma:loose", "E>3.5", path=path)
65  ma.applyCuts("gamma:hard", "foxWolframR2 < 0.995", path=path)
66 
67  # the requirement of 7 < M(eta_b) < 10 GeV/c2
68  Etabcuts = "M > 7 and M < 10"
69 
70  # eta_b candidates are reconstructed
71  Etab_Channels = ["gamma:hard gamma:hard"]
72 
73  # define the eta_b decay list
74  EtabList = []
75 
76  # reconstruct the decay eta_b -> gamma gamma
77  for chID, channel in enumerate(Etab_Channels):
78  ma.reconstructDecay("eta_b:all" + str(chID) + " -> " + channel, Etabcuts, chID, path=path)
79  EtabList.append("eta_b:all" + str(chID))
80 
81  return EtabList
82 
83 
84 @fancy_skim_header
86  """
87  Reconstructed decay modes:
88 
89  * Y(1S,2S) -> l^+ l^{-} (l = e or mu)
90 
91  Selection criteria:
92 
93  * 2 tracks with momentum ranging between ``3.5 < p < 15``
94  * At least 1 track ``p < 1.5`` or 1 std photon with ``E > 150 MeV``
95  * ``M(Y(1S,2S)) > 8 GeV/c^2``
96  * ``foxWolframR2 < 0.995``
97  """
98  __authors__ = ["Stefano Spataro", "Sen Jia"]
99  __description__ = ""
100  __contact__ = __liaison__
101  __category__ = "physics, quarkonium"
102 
103  def load_standard_lists(self, path):
104  stdPhotons("loose", path=path, loadPhotonBeamBackgroundMVA=False)
105 
106  def build_lists(self, path):
107  Ycuts = ""
108  # create and fill e/mu/pi/photon ParticleLists
109  ma.fillParticleList("mu+:BottomoniumUpsilon", "p<15 and p>3.5", path=path)
110  ma.fillParticleList("e+:BottomoniumUpsilon", "p<15 and p>3.5", path=path)
111  ma.fillParticleList("pi+:BottomoniumUpsilon", "p<1.5 and pt>0.05", path=path)
112  ma.cutAndCopyList("gamma:soft", "gamma:loose", "E>0.15", path=path)
113 
114  # Y(1S,2S) are reconstructed with e^+ e^- or mu^+ mu^-
115  ma.reconstructDecay("Upsilon:ee -> e+:BottomoniumUpsilon e-:BottomoniumUpsilon", "M > 8", path=path)
116  ma.reconstructDecay("Upsilon:mumu -> mu+:BottomoniumUpsilon mu-:BottomoniumUpsilon", "M > 8", path=path)
117  ma.copyLists("Upsilon:all", ["Upsilon:ee", "Upsilon:mumu"], path=path)
118 
119  # require foxWolframR2 < 0.995
120  ma.fillParticleList(decayString="pi+:BottomoniumUpsilon_eventshape", cut="pt > 0.1", path=path)
121  ma.fillParticleList(decayString="gamma:BottomoniumUpsilon_eventshape", cut="E > 0.1", path=path,
122  loadPhotonBeamBackgroundMVA=False)
123 
124  ma.buildEventShape(inputListNames=["pi+:BottomoniumUpsilon_eventshape", "gamma:BottomoniumUpsilon_eventshape"],
125  allMoments=False,
126  foxWolfram=True,
127  harmonicMoments=False,
128  cleoCones=False,
129  thrust=False,
130  collisionAxis=False,
131  jets=False,
132  sphericity=False,
133  checkForDuplicates=False,
134  path=path)
135 
136  ma.applyCuts("Upsilon:all", "foxWolframR2 < 0.995", path=path)
137 
138  # Y(1S,2S) with pi+ or photon are reconstructed
139  Upsilon_Channels = ["Upsilon:all pi+:BottomoniumUpsilon",
140  "Upsilon:all gamma:soft"]
141 
142  # define the Y(1S,2S) decay channel list
143  UpsilonList = []
144 
145  # reconstruct the decay channel
146  for chID, channel in enumerate(Upsilon_Channels):
147  ma.reconstructDecay("junction:all" + str(chID) + " -> " + channel, Ycuts, chID, path=path, allowChargeViolation=True)
148  UpsilonList.append("junction:all" + str(chID))
149 
150  # return the list
151  return UpsilonList
152 
153  # *two* sets of validation scripts defined.
154 
155 
156 @fancy_skim_header
158  """
159  Reconstructed decay modes:
160 
161  * J/psi -> l^+ l^- (l = e or mu)
162  * psi(2S) -> l^+ l^- (l = e or mu)
163 
164  Selection criteria:
165 
166  * 2 tracks with electronID > 0.1 or muonID > 0.1 and 2.7 < M < 4.
167  Track-quality requirements are not applied.
168  """
169  __authors__ = ["Kirill Chilikin"]
170  __description__ = "Selection of J/psi and psi(2S) via leptonic decays."
171  __contact__ = __liaison__
172  __category__ = "physics, quarkonium"
173 
174  validation_sample = _VALIDATION_SAMPLE
175 
176  def load_standard_lists(self, path):
177  stdPhotons("all", path=path, loadPhotonBeamBackgroundMVA=False)
178 
179  def build_lists(self, path):
180 
181  # Definition of the variables.
182  from variables import variables
183  variables.addAlias('electronID_noSVD_noTOP',
184  'pidProbabilityExpert(11, CDC, ARICH, ECL, KLM)')
185 
186  # Lepton lists. Exclude SVD and TOP for electrons, and SVD for muons.
187  ma.fillParticleList('e+:loosepid_noSVD_noTOP',
188  'electronID_noSVD_noTOP > 0.1', path=path)
189  ma.fillParticleList('mu+:loosepid_noSVD',
190  'muonID_noSVD > 0.1', path=path)
191 
192  # Mass cuts.
193  jpsi_mass_cut = '2.85 < M < 3.3'
194  psi2s_mass_cut = '3.45 < M < 3.9'
195 
196  # Electrons with bremsstrahlung correction.
197  # Use both correction algorithms as well as uncorrected electrons
198  # to allow for algorithm comparison in analysis.
199  # The recommended list for further reconstruction is J/psi:eebrems.
200  # The estimated ratio of efficiencies in B decays in release 5.1.5 is
201  # 1.00 (J/psi:eebrems) : 0.95 (J/psi:eebrems2) : 0.82 (J/psi:ee).
202  ma.correctBremsBelle('e+:brems', 'e+:loosepid_noSVD_noTOP', 'gamma:all',
203  angleThreshold=0.05,
204  path=path)
205  ma.correctBrems('e+:brems2', 'e+:loosepid_noSVD_noTOP', 'gamma:all',
206  path=path)
207 
208  # Reconstruct J/psi or psi(2S).
209  ma.reconstructDecay(
210  'J/psi:ee -> e+:loosepid_noSVD_noTOP e-:loosepid_noSVD_noTOP',
211  jpsi_mass_cut, path=path)
212  ma.reconstructDecay(
213  'psi(2S):ee -> e+:loosepid_noSVD_noTOP e-:loosepid_noSVD_noTOP',
214  psi2s_mass_cut, path=path)
215 
216  ma.reconstructDecay('J/psi:eebrems -> e+:brems e-:brems',
217  jpsi_mass_cut, path=path)
218  ma.reconstructDecay('psi(2S):eebrems -> e+:brems e-:brems',
219  psi2s_mass_cut, path=path)
220 
221  ma.reconstructDecay('J/psi:eebrems2 -> e+:brems2 e-:brems2',
222  jpsi_mass_cut, path=path)
223  ma.reconstructDecay('psi(2S):eebrems2 -> e+:brems2 e-:brems2',
224  psi2s_mass_cut, path=path)
225 
226  ma.reconstructDecay(
227  'J/psi:mumu -> mu+:loosepid_noSVD mu-:loosepid_noSVD',
228  jpsi_mass_cut, path=path)
229  ma.reconstructDecay(
230  'psi(2S):mumu -> mu+:loosepid_noSVD mu-:loosepid_noSVD',
231  psi2s_mass_cut, path=path)
232 
233  # Return the lists.
234  return ['J/psi:ee', 'psi(2S):ee',
235  'J/psi:eebrems', 'psi(2S):eebrems',
236  'J/psi:eebrems2', 'psi(2S):eebrems2',
237  'J/psi:mumu', 'psi(2S):mumu']
238 
239  def validation_histograms(self, path):
240  # NOTE: the validation package is not part of the light releases, so this import
241  # must be made here rather than at the top of the file.
242  from validation_tools.metadata import create_validation_histograms
243 
244  # [Y(3S) -> pi+pi- [Y(1S,2S) -> mu+mu-]] decay
245  ma.reconstructDecay(
246  'J/psi:mumu_test -> mu+:loosepid_noSVD mu-:loosepid_noSVD',
247  '', path=path)
248  ma.reconstructDecay(
249  'J/psi:ee_test -> e+:loosepid_noSVD_noTOP e-:loosepid_noSVD_noTOP',
250  '', path=path)
251  ma.copyList('J/psi:ll', 'J/psi:mumu_test', path=path)
252  ma.copyList('J/psi:ll', 'J/psi:ee_test', path=path)
253 
254  # Print histograms.
255  create_validation_histograms(
256  rootfile=f'{self}_Validation.root',
257  particlelist='J/psi:ll',
258  variables_1d=[(
259  'InvM', 65, 2.7, 4.0,
260  'J/#psi mass',
261  __liaison__,
262  'J/psi mass',
263  'J/psi peak is seen.',
264  'M [GeV/c^{2}]', 'Events / (20 MeV/c^{2})',
265  'shifter'
266  )],
267  path=path
268  )
269 
270 
271 @fancy_skim_header
273  """
274  Reconstructed decay
275  * :math:`\\Lambda \\to p \\pi^-` (and charge conjugate)
276 
277  Selection criteria:
278  * proton
279  ``protonID > 0.1``
280  * Lambda:
281  ``cosAngleBetweenMomentumAndVertexVector > 0.99``
282  ``flightDistance/flightDistanceErr > 3.``
283  * ``0.6 < p,proton/p,Lambda < 1.0 GeV/c``
284 
285  """
286  __authors__ = ["Bianca Scavino"]
287  __description__ = "Inclusive Lambda skim"
288  __contact__ = __liaison__
289  __category__ = "physics, quarkonium"
290 
291  def load_standard_lists(self, path):
292  stdLambdas(path=path)
293 
294  def build_lists(self, path):
295 
296  # Add useful alias
297  v.addAlias("protonID_proton", "daughter(0, protonID)")
298  v.addAlias("momRatio_protonLambda", "formula(daughter(0, p)/p)")
299  v.addAlias('flightSignificance', 'formula(flightDistance/flightDistanceErr)')
300 
301  # Apply selection to Lambdas
302  ma.applyCuts("Lambda0:merged", "cosAngleBetweenMomentumAndVertexVector > 0.99", path=path)
303  ma.applyCuts("Lambda0:merged", "0.6 < momRatio_protonLambda < 1.", path=path)
304  ma.applyCuts("Lambda0:merged", "flightSignificance > 3.", path=path)
305  ma.applyCuts("Lambda0:merged", "protonID_proton > 0.1", path=path)
306 
307  # Return the lists.
308  return ["Lambda0:merged"]
def build_lists(self, path)
Definition: quarkonium.py:106
def load_standard_lists(self, path)
Definition: quarkonium.py:103
def build_lists(self, path)
Definition: quarkonium.py:179
def validation_histograms(self, path)
Definition: quarkonium.py:239
def load_standard_lists(self, path)
Definition: quarkonium.py:176
def build_lists(self, path)
Definition: quarkonium.py:294
def load_standard_lists(self, path)
Definition: quarkonium.py:291