Belle II Software  release-05-02-19
dark.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 """ Skim list building functions for the dark sector physics working group """
5 
6 __authors__ = [
7  "Sam Cunliffe",
8  "Michael De Nuccio",
9  "Ilya Komarov",
10  "Giacomo De Pietro",
11  "Miho Wakai",
12  "Savino Longo"
13 ]
14 
15 
16 import basf2 as b2
17 import modularAnalysis as ma
18 import pdg
19 from skimExpertFunctions import BaseSkim, fancy_skim_header, get_test_file
20 from stdCharged import stdE, stdMu, stdPi, stdK
21 from stdPhotons import stdPhotons
22 import vertex as vertex
23 
24 __liaison__ = "Sascha Dreyer <sascha.dreyer@desy.de>"
25 
26 
27 @fancy_skim_header
29  """
30  **Physics channel**: ee → A'γ; A' → invisible
31 
32  Skim list contains single photon candidates for the dark photon to invisible final
33  state analysis.
34  """
35  __authors__ = ["Sam Cunliffe", "Chris Hearty"]
36  __contact__ = __liaison__
37  __description__ = "Single photon skim list for the dark photon analysis."
38  __category__ = "physics, dark sector"
39  ApplyHLTHadronCut = False
40 
41  def load_standard_lists(self, path):
42  stdPhotons("all", path=path)
43 
44  def build_lists(self, path):
45 
46  # start with all photons with E* above 500 MeV in the tracking acceptance
47  in_tracking_acceptance = "0.296706 < theta < 2.61799" # rad = [17, 150] degrees
48  ma.cutAndCopyList(
49  "gamma:singlePhoton", "gamma:all",
50  f"useCMSFrame(E) > 0.5 and {in_tracking_acceptance}", path=path)
51 
52  # require a region-dependent minimum energy of the candidate, we have
53  # a new 0.5 GeV trigger in the inner barrel: [44.2, 94.8] degrees @ L1
54  region_dependent = " [clusterTheta < 1.65457213 and clusterTheta > 0.77143553] or "
55  region_dependent += "[clusterReg == 2 and useCMSFrame(E) > 1.0] or " # barrel
56  region_dependent += "[clusterReg == 1 and useCMSFrame(E) > 2.0] or " # fwd
57  region_dependent += "[clusterReg == 3 and useCMSFrame(E) > 2.0] or " # bwd
58  region_dependent += "[clusterReg == 11 and useCMSFrame(E) > 2.0] or " # between fwd and barrel
59  region_dependent += "[clusterReg == 13 and useCMSFrame(E) > 2.0]" # between bwd and barrel
60  ma.applyCuts("gamma:singlePhoton", region_dependent, path=path)
61 
62  # require only one single photon candidate and no good tracks in the event
63  good_tracks = 'abs(dz) < 2.0 and abs(dr) < 0.5 and pt > 0.15' # cm, cm, GeV/c
64  path = self.skim_event_cuts(
65  f"nParticlesInList(gamma:singlePhoton) == 1 and nCleanedTracks({good_tracks}) == 0",
66  path=path
67  )
68 
69  # check the second-most-energetic photon (above 550 MeV is unlikely to
70  # be beam-induced background) and veto if it's in time with our signal
71  # candidate -- do after the event cuts since it uses a ParticleCombiner
72  # and should not be done for all events (save event-processing time)
73  not_in_signal_list = "isInList(gamma:singlePhoton) < 1"
74  in_time = "maxWeightedDistanceFromAverageECLTime < 1"
75  ma.cutAndCopyList("gamma:to_veto", "gamma:all",
76  f"E > 0.55 and {not_in_signal_list}", path=path)
77  ma.rankByHighest("gamma:to_veto", "E", numBest=1, path=path)
78  ma.reconstructDecay("vpho:veto -> gamma:singlePhoton gamma:to_veto",
79  in_time, path=path)
80  veto_additional_in_time_cluster = 'nParticlesInList(vpho:veto) < 1'
81 
82  # final signal selection must pass the 'in-time' veto on the
83  # second-most-energetic cluster -- this is also an event cut, but apply
84  # to the list (which is anyway a maximum one candidate per event) since
85  # we can only call skim_event_cuts once
86  ma.applyCuts("gamma:singlePhoton", veto_additional_in_time_cluster, path=path)
87  self.SkimLists = ["gamma:singlePhoton"]
88 
89 
90 @fancy_skim_header
92  __authors__ = ["Michael De Nuccio"]
93  __description__ = (
94  "Neutral dark sector skim list for the ALP 3-photon analysis: "
95  ":math:`ee\\to a(\\to\\gamma\\gamma)\\gamma`"
96  )
97  __contact__ = __liaison__
98  __category__ = "physics, dark sector"
99  ApplyHLTHadronCut = False
100 
101  def addALPToPDG(self):
102  """Adds the ALP codes to the basf2 pdg instance """
103  pdg.add_particle('beam', 55, 999., 999., 0, 0)
104  pdg.add_particle('ALP', 9000006, 999., 999., 0, 0)
105 
106  def initialALP(self, path):
107  """
108  An list builder function for the ALP decays. Part of the `ALP3Gamma` skim.
109 
110  Parameters:
111  path (basf2.Path): the path to add the skim
112 
113  Returns:
114  list name of the ALP decays candidates
115  """
116  # no cuts applied on ALP
117  ALPcuts = ''
118 
119  # applying a lab frame energy cut to the daughter photons
120  ma.fillParticleList(
121  'gamma:cdcAndMinimumEnergy',
122  'E >= 0.1 and theta >= 0.297 and theta <= 2.618',
123  True, path=path
124  )
125 
126  # defining the decay string
127  ALPchannels = ['gamma:cdcAndMinimumEnergy gamma:cdcAndMinimumEnergy']
128  ALPList = []
129 
130  # creating an ALP from the daughter photons
131  for chID, channel in enumerate(ALPchannels):
132  mode = 'ALP:' + str(chID) + ' -> ' + channel
133  print(mode)
134  ma.reconstructDecay(mode, ALPcuts, chID, path=path)
135 
136  ALPList.append('ALP:' + str(chID))
137 
138  Lists = ALPList
139  return Lists
140 
141  def additional_setup(self, path):
142  self.addALPToPDG()
143 
144  def build_lists(self, path):
145  # applying invariant mass cut on the beam particle
146  beamcuts = "InvM >= formula(0.8 * Ecms) and InvM <= formula(1.05 * Ecms) and maxWeightedDistanceFromAverageECLTime <= 2"
147 
148  ALPList = self.initialALP(path=path)
149 
150  # applying a lab frame energy cut to the recoil photon
151  ma.fillParticleList("gamma:minimumEnergy", "E >= 0.1", True, path=path)
152  beamList = []
153 
154  # reconstructing decay using the reconstructed ALP
155  # from previous function and adding the recoil photon
156  for chID, channel in enumerate(ALPList):
157  mode = "beam:" + str(chID) + " -> gamma:minimumEnergy " + channel
158  print(mode)
159  ma.reconstructDecay(mode, beamcuts, chID, path=path)
160  beamList.append("beam:" + str(chID))
161  self.SkimLists = beamList
162 
163 
164 @fancy_skim_header
166  """
167  **Physics channel**: :math:`e^{+}e^{-} \\to \\mu^{+}\\mu^{-} \\, +` missing energy.
168  """
169  __authors__ = ["Giacomo De Pietro"]
170  __description__ = (
171  "Dimuon + missing energy skim, needed for :math:`e^{+}e^{-} \\to \\mu^{+}\\mu^{-}"
172  "Z^{\\prime}; \\, Z^{\\prime} \\to \\mathrm{invisible}` and other searches."
173  )
174  __contact__ = __liaison__
175  __category__ = "physics, dark sector"
176  ApplyHLTHadronCut = False
177 
178  def load_standard_lists(self, path):
179  stdMu("all", path=path)
180 
181  def build_lists(self, path):
182  dimuon_list = []
183  skim_label = "forDimuonMissingEnergySkim"
184  dimuon_name = "Z0:" + skim_label
185 
186  # Define some cuts
187  fromIP_cut = "[abs(dz) < 5.0] and [abs(dr) < 2.0]"
188  muonID_cut = "[muonID > 0.3]"
189  # We want exactly 2 tracks from IP
190  dimuon_cut = "[nCleanedTracks(" + fromIP_cut + ") < 4]"
191  # And the pair must have pt > 200 MeV in CMS frame
192  dimuon_cut += " and [useCMSFrame(pt) > 0.2]"
193 
194  # Reconstruct the dimuon candidate
195  ma.cutAndCopyList("mu+:" + skim_label, "mu+:all", fromIP_cut + " and " + muonID_cut, path=path)
196  ma.reconstructDecay(dimuon_name + " -> mu+:" + skim_label + " mu-:" + skim_label, dimuon_cut, path=path)
197 
198  # And return the dimuon list
199  dimuon_list.append(dimuon_name)
200  self.SkimLists = dimuon_list
201 
202 
203 @fancy_skim_header
205  __authors__ = ["Giacomo De Pietro"]
206  __description__ = (
207  "Electron-muon pair + missing energy skim, needed for :math:`e^{+}e^{-} \\to "
208  "e^{\\pm}\\mu^{\\mp} Z^{\\prime}; \\, Z^{\\prime} \\to \\mathrm{invisible}` and other "
209  "searches."
210  )
211  __contact__ = __liaison__
212  __category__ = "physics, dark sector"
213  ApplyHLTHadronCut = False
214 
215  def load_standard_lists(self, path):
216  stdE("all", path=path)
217  stdMu("all", path=path)
218 
219  def build_lists(self, path):
220  """
221  **Physics channel**: :math:`e^{+}e^{-} \\to e^{\\pm}\\mu^{\\mp} \\, +` missing energy
222  """
223  emu_list = []
224  skim_label = "forElectronMuonMissingEnergySkim"
225  emu_name = "Z0:" + skim_label
226 
227  # Define some basic cuts
228  fromIP_cut = "[abs(dz) < 5.0] and [abs(dr) < 2.0]"
229  electronID_cut = "[electronID > 0.3]"
230  muonID_cut = "[muonID > 0.3]"
231  # We require that the electron points to the barrel ECL + 10 degrees
232  theta_cut = "[0.387 < theta < 2.421]"
233  # We want exactly 2 tracks from IP
234  emu_cut = "[nCleanedTracks(" + fromIP_cut + ") < 4]"
235  # And the pair must have pt > 200 MeV in CMS frame
236  emu_cut += " and [useCMSFrame(pt) > 0.2]"
237 
238  # Reconstruct the dimuon candidate
239  ma.cutAndCopyList("e+:" + skim_label, "e+:all", fromIP_cut + " and " + electronID_cut + " and " + theta_cut, path=path)
240  ma.cutAndCopyList("mu+:" + skim_label, "mu+:all", fromIP_cut + " and " + muonID_cut, path=path)
241  ma.reconstructDecay(emu_name + " -> e+:" + skim_label + " mu-:" + skim_label, emu_cut, path=path)
242 
243  # And return the dimuon list
244  emu_list.append(emu_name)
245  self.SkimLists = emu_list
246 
247 
248 @fancy_skim_header
250  __authors__ = ["Ilya Komarov"]
251  __description__ = "Lepton flavour violating Z' skim, Z' to visible FS."
252  __contact__ = __liaison__
253  __category__ = "physics, dark sector"
254  ApplyHLTHadronCut = False
255 
256  def load_standard_lists(self, path):
257  stdE("all", path=path)
258  stdE("loose", path=path)
259 
260  def build_lists(self, path):
261  """
262  **Physics channel**: ee --> e mu Z'; Z' --> e mu
263  """
264  lfvzp_list = []
265 
266  # Here we just want four gpood tracks to be reconstructed
267  track_cuts = "abs(dz) < 2.0 and abs(dr) < 0.5"
268  Event_cuts_vis = "nCleanedTracks(abs(dz) < 2.0 and abs(dr) < 0.5) == 4"
269 
270  ma.cutAndCopyList("e+:lfvzp", "e+:all", track_cuts, path=path)
271 
272  # Z' to lfv: fully reconstructed
273  LFVZpVisChannel = "e+:lfvzp e+:lfvzp e-:lfvzp e-:lfvzp"
274 
275  ma.reconstructDecay("vpho:vislfvzp -> " + LFVZpVisChannel, Event_cuts_vis, path=path)
276 
277  lfvzp_list.append("vpho:vislfvzp")
278 
279  # Z' to lfv: part reco
280  LFVZpVisChannel = "e+:lfvzp e+:lfvzp e-:lfvzp"
281  Event_cuts_vis = "nCleanedTracks(abs(dz) < 2.0 and abs(dr) < 0.5) == 3"
282 
283  ma.reconstructDecay("vpho:3tr_vislfvzp -> " + LFVZpVisChannel, Event_cuts_vis, path=path, allowChargeViolation=True)
284 
285  lfvzp_list.append("vpho:3tr_vislfvzp")
286 
287  # Z' to lfv: two same-sign tracks
288  LFVZpVisChannel = "e+:lfvzp e+:lfvzp"
289  Event_cuts_vis = "nCleanedTracks(abs(dz) < 2.0 and abs(dr) < 0.5) == 2"
290  ma.reconstructDecay("vpho:2tr_vislfvzp -> " + LFVZpVisChannel, Event_cuts_vis, path=path, allowChargeViolation=True)
291 
292  lfvzp_list.append("vpho:2tr_vislfvzp")
293 
294  self.SkimLists = lfvzp_list
295 
296 
297 @fancy_skim_header
299  """
300  **Physics channel**: ee → eγ
301  """
302 
303  __authors__ = ["Sam Cunliffe", "Torben Ferber"]
304  __description__ = (
305  "Electron-gamma skim list for study of the ee backgrounds at high dark "
306  "photon mass, as part of the dark photon analysis"
307  )
308  __contact__ = __liaison__
309  __category__ = "physics, dark sector, control-channel"
310  ApplyHLTHadronCut = False
311 
312  def load_standard_lists(self, path):
313  stdPhotons("all", path=path)
314  stdE("all", path=path)
315 
316  def build_lists(self, path):
317 
318  # long-winded names for the particle lists to avoid clash
319  internal_skim_label = "forEGammaSkim"
320  skim_output_label = "EGammaControl"
321 
322  # want exactly 1 good quality track in the event
323  # (not one good electron, one good anything)
324  phys_perf_good_track = 'abs(dr) < 1 and abs(dz) < 3 and pt > 0.15' # cm, cm, GeV/c
325  one_good_track = f'[nCleanedTracks({phys_perf_good_track}) == 1]'
326 
327  # exactly 1 good photon in the event
328  photon_energy_cut = '0.45'
329  good_photon = 'theta > 0.296706 and theta < 2.61799' +\
330  f' and useCMSFrame(E) > {photon_energy_cut}'
331  ma.cutAndCopyList(f'gamma:{internal_skim_label}', 'gamma:all', good_photon, path=path)
332  one_good_photon = f'[eventCached(nParticlesInList(gamma:{internal_skim_label})) == 1]'
333 
334  # apply the event-level cuts
335  event_cuts = f'{one_good_photon} and {one_good_track}'
336  path = self.skim_event_cuts(event_cuts, path=path)
337 
338  # fill electron lists (tighter than previous selection)
339  good_track_w_hie_cluster_match = '%s and clusterE > 2.0' % phys_perf_good_track
340  ma.cutAndCopyList(f'e+:{internal_skim_label}', 'e+:all', good_track_w_hie_cluster_match, path=path)
341 
342  # reconstruct decay
343  ma.reconstructDecay(
344  f'vpho:{skim_output_label} -> e+:{internal_skim_label} gamma:{internal_skim_label}',
345  '', 1, allowChargeViolation=True, path=path)
346  self.SkimLists = [f"vpho:{skim_output_label}"]
347 
348 
349 @fancy_skim_header
351  """
352  **Physics channel**: ee → γγ
353 
354  .. Note::
355  This skim can retain a lot of γγ events.
356  In case this becomes unacceptable, we provide prescale parameters.
357  Prescales are given in standard trigger convention (reciprocal),
358  so prescale of 100 is 1% of events kept, etc.
359 
360  .. Tip::
361  To prescale the higher-energy probe photons by 10%:
362 
363  >>> from skim.dark import GammaGammaControlKLMDark
364  >>> Skim = GammaGammaControlKLMDark(prescale_high=10)
365  >>> Skim(path) # Add list-building function and uDST output module to path
366  >>> b2.process(path)
367  """
368 
369  __authors__ = ["Sam Cunliffe", "Miho Wakai"]
370  __description__ = (
371  "Gamma gamma skim list for study of the KLM efficiency as part of "
372  "the dark photon analysis"
373  )
374  __contact__ = __liaison__
375  __category__ = "physics, dark sector, control-channel"
376  ApplyHLTHadronCut = False
377 
378  def load_standard_lists(self, path):
379  stdPhotons("all", path=path)
380 
381  TestFiles = [get_test_file("MC13_ggBGx1")]
382 
383  def __init__(self, prescale_high=1, prescale_low=1, **kwargs):
384  """
385  Parameters:
386  prescale_high (int): the prescale for more energetic probe photon
387  prescale_low (int): the prescale for a less energetic probe photon
388  **kwargs: Passed to constructor of `BaseSkim`.
389  """
390  # Redefine __init__ to allow for additional optional arguments
391  super().__init__(**kwargs)
392  self.prescale_high = prescale_high
393  self.prescale_low = prescale_low
394 
395  def build_lists(self, path):
396  # unpack prescales and convert from trigger convention to a number we can
397  # compare with a float
398  prescale_high, prescale_low = self.prescale_high, self.prescale_low
399  if (prescale_high, prescale_low) is not (1, 1):
400  b2.B2INFO(
401  "GammaGammaControlKLMDarkList is prescaled. "
402  f"prescale_high={prescale_high}, prescale_low={prescale_low}"
403  )
404  prescale_high = str(float(1.0 / prescale_high))
405  prescale_low = str(float(1.0 / prescale_low))
406 
407  # no good (IP-originating) tracks in the event
408  good_tracks = "abs(dz) < 2.0 and abs(dr) < 0.5 and pt > 0.2" # cm, cm, GeV/c
409  no_good_tracks = f"nCleanedTracks({good_tracks}) < 1"
410 
411  # get two most energetic photons in the event (must be at least 100 MeV
412  # and not more than 7 GeV)
413  ma.cutAndCopyList(
414  "gamma:controlKLM", "gamma:all", "0.1 < useCMSFrame(clusterE) < 7", path=path)
415  ma.rankByHighest("gamma:controlKLM", "useCMSFrame(clusterE)", numBest=2, path=path)
416 
417  # will build pairwise candidates from the gamma:controlKLM list:
418  # vpho -> gamma gamma
419 
420  # the more energetic must be at least 4.5 GeV
421  tag_daughter = "daughterHighest(useCMSFrame(clusterE)) > 4.5"
422  # note that sometimes the probe will also fulfill this criteria, but the
423  # candidate list will *not* be double-counted: these extra candidates need
424  # to be added back offline
425 
426  # apply prescales to the less energetic daughter: compare to the eventwise random number
427  probe_high = f"[daughterLowest(useCMSFrame(clusterE)) > 4.5] and [eventRandom < {prescale_high}]"
428  probe_low = f"[daughterLowest(useCMSFrame(clusterE)) < 4.5] and [eventRandom < {prescale_low}]"
429  prescale = f"[ {probe_high} ] or [ {probe_low} ]"
430 
431  # ~back-to-back in phi in the CMS (3.1066... radians = 178 degrees)
432  delta_phi_cut = "abs(daughterDiffOfPhiCMS(0, 1)) > 3.1066860685499065"
433 
434  # sum theta in the cms 178 --> 182 degrees
435  sum_th = "daughterSumOf(useCMSFrame(theta))"
436  sum_th_cut = f"3.1066860685499065 < {sum_th} < 3.1764992386296798"
437 
438  # now build and return the candidates passing the AND of our cuts
439  cuts = [no_good_tracks, tag_daughter, prescale, delta_phi_cut, sum_th_cut]
440  cuts = " and ".join([f"[ {cut} ]" for cut in cuts])
441 
442  ma.reconstructDecay(
443  "vpho:singlePhotonControlKLM -> gamma:controlKLM gamma:controlKLM",
444  cuts, path=path)
445  self.SkimLists = ["vpho:singlePhotonControlKLM"]
446 
447 
448 @fancy_skim_header
450  """
451  **Physics channel**: :math:`e^{+}e^{-} \\to e^{+}e^{-}`
452 
453  Warning:
454  This skim is currently deactivated, since the retention rate is too high.
455  """
456 
457  __authors__ = "Giacomo De Pietro"
458  __description__ = (
459  "Dielectron skim, needed for :math:`e^{+}e^{-} \\to A^{\\prime} h^{\\prime};`"
460  ":math:`A^{\\prime} \\to e^{+}e^{-}; \\, h^{\\prime} \\to \\mathrm{invisible}` and other searches."
461  )
462  __contact__ = __liaison__
463  __category__ = "physics, dark sector"
464  ApplyHLTHadronCut = False
465 
466  def load_standard_lists(self, path):
467  stdE("all", path=path)
468 
469  TestFiles = [get_test_file("MC13_mumuBGx1")]
470 
471  def build_lists(self, path):
472  dielectron_list = []
473  skim_label = "forDielectronMissingEnergySkim"
474  dielectron_name = f"Z0:{skim_label}"
475 
476  # Define some basic cuts
477  fromIP_cut = "[abs(dz) < 5.0] and [abs(dr) < 2.0]"
478  electronID_cut = "[electronID > 0.2]"
479  # We require that the electron points to the barrel ECL + 10 degrees
480  theta_cut = "[0.387 < theta < 2.421]"
481  # We want exactly 2 tracks from IP
482  dielectron_cut = f"[nCleanedTracks({fromIP_cut}) == 2]"
483  # And the pair must have pt > 200 MeV in CMS frame
484  dielectron_cut += " and [useCMSFrame(pt) > 0.2]"
485 
486  # Reconstruct the dielectron candidate
487  electron_cuts = " and ".join([fromIP_cut, electronID_cut, theta_cut])
488  ma.cutAndCopyList(f"e+:{skim_label}", "e+:all", electron_cuts, path=path)
489  ma.reconstructDecay(f"{dielectron_name} -> e+:{skim_label} e-:{skim_label}", dielectron_cut, path=path)
490 
491  # And return the dielectron list
492  dielectron_list.append(dielectron_name)
493  self.SkimLists = dielectron_list
494 
495 
496 @fancy_skim_header
498 
499  """
500  Control sample: :math:`e^{+}e^{-} \\to e^{+}e^{-}V^{0};`"
501  """
502 
503  __authors__ = "Savino Longo"
504  __description__ = (
505  "iDM control sample skim. :math:`e^{+}e^{-} \\to e^{+}e^{-}V^{0};`"
506  )
507  __contact__ = __liaison__
508  __category__ = "physics, dark sector"
509  ApplyHLTHadronCut = False
510 
511  def load_standard_lists(self, path):
512  stdPhotons("all", path=path)
513  stdE("all", path=path)
514 
515  def build_lists(self, path):
516 
517  # require Bhabha tracks are high p and E/p is consitent with e+/e-
518  BhabhaTrackCuts = 'abs(dr)<0.5 and abs(dz)<2 and pt>0.2 and 0.8<clusterEoP<1.2 and p>1.0 and clusterReg==2 and nCDCHits>4'
519  BhabhaSystemCuts = '4<M<10 and 0.5<pRecoilTheta<2.25'
520  V0TrackCuts = 'nCDCHits>4 and p<3.0'
521  V0Cuts = 'dr>0.5'
522  PhotonVetoCuts = 'p>1.0' # event should have no high E photons
523 
524  ma.cutAndCopyList("gamma:HighEGammaVeto", "gamma:all", PhotonVetoCuts, path=path)
525  ma.cutAndCopyList("e+:BhabhaTrack", "e+:all", BhabhaTrackCuts, path=path)
526  ma.cutAndCopyList("e+:V0Track", "e+:all", V0TrackCuts, path=path)
527 
528  ma.reconstructDecay("vpho:BhabhaSysyem -> e+:BhabhaTrack e-:BhabhaTrack", BhabhaSystemCuts, path=path)
529 
530  ma.reconstructDecay("vpho:V0System -> e+:V0Track e-:V0Track", '', path=path)
531  vertex.treeFit('vpho:V0System', conf_level=0.0, path=path)
532  ma.applyCuts('vpho:V0System', V0Cuts, path=path)
533 
534  ma.reconstructDecay('vpho:Total -> vpho:BhabhaSysyem vpho:V0System', '', path=path)
535 
536  eventCuts = ('nParticlesInList(gamma:HighEGammaVeto)<1 and '
537  'nParticlesInList(vpho:Total)>0')
538 
539  path = self.skim_event_cuts(eventCuts, path=path)
540 
541  self.SkimLists = ["vpho:Total"]
542 
543 
544 @fancy_skim_header
546  """
547  Skim list contains events with no tracks from IP, no high E tracks and only one high E photon.
548  """
549  __authors__ = ["Savino Longo"]
550  __contact__ = __liaison__
551  __description__ = "iDM list for the iDM analysis."
552  __category__ = "physics, dark sector"
553  ApplyHLTHadronCut = False
554 
555  def load_standard_lists(self, path):
556  stdPhotons("all", path=path)
557  stdE("all", path=path)
558 
559  def build_lists(self, path):
560 
561  IPtrack = 'abs(dr) < 0.05' # cm
562  HighEtrack = 'useCMSFrame(p)>3.0' # GeV
563  ma.cutAndCopyList("e+:TrackFromIP", "e+:all", IPtrack, path=path)
564  ma.cutAndCopyList("e+:HighEnergyTrack", "e+:all", HighEtrack, path=path)
565 
566  signalPhoton = "[clusterReg==2 and useCMSFrame(E) > 1.0] or "
567  signalPhoton += "[clusterReg == 1 and useCMSFrame(E) > 2.0] or " # fwd
568  signalPhoton += "[clusterReg == 3 and useCMSFrame(E) > 2.0] or " # bwd
569  signalPhoton += "[clusterReg == 11 and useCMSFrame(E) > 2.0] or " # between fwd and barrel
570  signalPhoton += "[clusterReg == 13 and useCMSFrame(E) > 2.0] " # between bwd and barrel
571 
572  photonVetoHE1 = 'useCMSFrame(p) > 0.6'
573  photonVetoHE3 = 'p>0.5'
574 
575  ma.cutAndCopyList("gamma:ISR", "gamma:all", signalPhoton, path=path)
576  ma.cutAndCopyList("gamma:HighEnergyPhotons", "gamma:all", photonVetoHE1, path=path)
577  ma.cutAndCopyList("gamma:MediumEnergyPhotons", "gamma:all", photonVetoHE3, path=path)
578 
579  idmEventCuts = ('nParticlesInList(gamma:ISR)==1 and '
580  'nParticlesInList(e+:TrackFromIP)==0 and '
581  'nParticlesInList(e+:HighEnergyTrack) == 0 and '
582  'nParticlesInList(gamma:HighEnergyPhotons) == 1 and '
583  'nParticlesInList(gamma:MediumEnergyPhotons) < 4 and '
584  'HighLevelTrigger == 1')
585 
586  path = self.skim_event_cuts(idmEventCuts, path=path)
587 
588  self.SkimLists = ['gamma:ISR']
589 
590 
591 @fancy_skim_header
593  """
594  Skim to select B+ decays to a K+ from the IP and a LLP with a vertex displaced from the IR decaying to two charged tracks.
595  """
596  __authors__ = ["Sascha Dreyer"]
597  __contact__ = __liaison__
598  __description__ = (
599  "B+ to K+ LLP analysis skim :math:`e^{+}e^{-} \\to \\Upsilon(4s) \\to [B^{+} \\to K^{+} LLP]B^{-}`"
600  )
601  __category__ = "physics, dark sector"
602  ApplyHLTHadronCut = False
603 
604  def load_standard_lists(self, path):
605  stdPi("all", path=path)
606  stdK("all", path=path)
607  stdE("all", path=path)
608  stdMu("all", path=path)
609 
610  def build_lists(self, path):
611 
612  btoksLbl = '_btoks'
613 
614  minDisplacementCut = "[dr > 0.05]"
615 
616  ma.reconstructDecay("vpho:LLP_e" + btoksLbl + " -> e+:all e-:all", "", path=path)
617  ma.reconstructDecay("vpho:LLP_mu" + btoksLbl + " -> mu+:all mu-:all", "", path=path)
618  ma.reconstructDecay("vpho:LLP_pi" + btoksLbl + " -> pi+:all pi-:all", "", path=path)
619  ma.reconstructDecay("vpho:LLP_K" + btoksLbl + " -> K+:all K-:all", "", path=path)
620 
621  ma.copyLists(outputListName="vpho:LLP" + btoksLbl,
622  inputListNames=["vpho:LLP_e" + btoksLbl, "vpho:LLP_mu" + btoksLbl,
623  "vpho:LLP_pi" + btoksLbl, "vpho:LLP_K" + btoksLbl],
624  path=path)
625 
626  vertex.treeFit("vpho:LLP" + btoksLbl, conf_level=0, updateAllDaughters=True, path=path)
627 
628  ma.applyCuts("vpho:LLP" + btoksLbl, minDisplacementCut, path=path)
629 
630  ipKaon = "[pt > 0.1] and [abs(dr) < 0.5] and [abs(dz) < 2.0]"
631  ma.cutAndCopyList("K+:TrackFromIP" + btoksLbl, "K+:all", ipKaon, path=path)
632 
633  kinematicCuts = "[Mbc > 5.20] and [abs(deltaE) < 0.25]"
634  ma.reconstructDecay("B+:b" + btoksLbl + " -> K+:TrackFromIP" + btoksLbl + " vpho:LLP" + btoksLbl,
635  kinematicCuts, path=path)
636 
637  self.SkimLists = ["B+:b" + btoksLbl]
skim.dark.DielectronPlusMissingEnergy.load_standard_lists
def load_standard_lists(self, path)
Definition: dark.py:466
skim.dark.EGammaControlDark.SkimLists
SkimLists
Definition: dark.py:346
skimExpertFunctions.BaseSkim.skim_event_cuts
def skim_event_cuts(self, cut, *path)
Definition: skimExpertFunctions.py:716
skim.dark.SinglePhotonDark.load_standard_lists
def load_standard_lists(self, path)
Definition: dark.py:41
skim.dark.GammaGammaControlKLMDark.load_standard_lists
def load_standard_lists(self, path)
Definition: dark.py:378
skim.dark.SinglePhotonDark
Definition: dark.py:28
skim.dark.ALP3Gamma
Definition: dark.py:91
skim.dark.ElectronMuonPlusMissingEnergy.build_lists
def build_lists(self, path)
Definition: dark.py:219
skim.dark.ElectronMuonPlusMissingEnergy.load_standard_lists
def load_standard_lists(self, path)
Definition: dark.py:215
skim.dark.BtoKplusLLP
Definition: dark.py:592
skim.dark.InelasticDarkMatter.build_lists
def build_lists(self, path)
Definition: dark.py:559
skim.dark.ALP3Gamma.addALPToPDG
def addALPToPDG(self)
Definition: dark.py:101
pdg.add_particle
def add_particle(name, pdgCode, mass, width, charge, spin, max_width=None, lifetime=0, pythiaID=0)
Definition: pdg.py:121
skim.dark.DimuonPlusMissingEnergy.build_lists
def build_lists(self, path)
Definition: dark.py:181
skim.dark.BtoKplusLLP.build_lists
def build_lists(self, path)
Definition: dark.py:610
skim.dark.InelasticDarkMatter.load_standard_lists
def load_standard_lists(self, path)
Definition: dark.py:555
skim.dark.RadBhabhaV0Control.SkimLists
SkimLists
Definition: dark.py:541
skim.dark.GammaGammaControlKLMDark.prescale_low
prescale_low
Definition: dark.py:393
skim.dark.InelasticDarkMatter
Definition: dark.py:545
stdPhotons
Definition: stdPhotons.py:1
skim.dark.GammaGammaControlKLMDark.__init__
def __init__(self, prescale_high=1, prescale_low=1, **kwargs)
Definition: dark.py:383
skim.dark.ALP3Gamma.initialALP
def initialALP(self, path)
Definition: dark.py:106
skim.dark.ALP3Gamma.build_lists
def build_lists(self, path)
Definition: dark.py:144
skim.dark.ElectronMuonPlusMissingEnergy
Definition: dark.py:204
skim.dark.DimuonPlusMissingEnergy.load_standard_lists
def load_standard_lists(self, path)
Definition: dark.py:178
skim.dark.EGammaControlDark
Definition: dark.py:298
skim.dark.GammaGammaControlKLMDark.SkimLists
SkimLists
Definition: dark.py:445
skim.dark.LFVZpVisible.load_standard_lists
def load_standard_lists(self, path)
Definition: dark.py:256
skim.dark.RadBhabhaV0Control.load_standard_lists
def load_standard_lists(self, path)
Definition: dark.py:511
skim.dark.GammaGammaControlKLMDark.prescale_high
prescale_high
Definition: dark.py:392
skim.dark.GammaGammaControlKLMDark.build_lists
def build_lists(self, path)
Definition: dark.py:395
skimExpertFunctions.BaseSkim
Definition: skimExpertFunctions.py:504
skim.dark.BtoKplusLLP.load_standard_lists
def load_standard_lists(self, path)
Definition: dark.py:604
skim.dark.InelasticDarkMatter.SkimLists
SkimLists
Definition: dark.py:588
skim.dark.GammaGammaControlKLMDark
Definition: dark.py:350
skim.dark.LFVZpVisible.build_lists
def build_lists(self, path)
Definition: dark.py:260
skim.dark.RadBhabhaV0Control
Definition: dark.py:497
skim.dark.EGammaControlDark.build_lists
def build_lists(self, path)
Definition: dark.py:316
skim.dark.SinglePhotonDark.build_lists
def build_lists(self, path)
Definition: dark.py:44
skim.dark.SinglePhotonDark.SkimLists
SkimLists
Definition: dark.py:87
skim.dark.LFVZpVisible
Definition: dark.py:249
skim.dark.BtoKplusLLP.SkimLists
SkimLists
Definition: dark.py:637
skim.dark.EGammaControlDark.load_standard_lists
def load_standard_lists(self, path)
Definition: dark.py:312
vertex.treeFit
def treeFit(list_name, conf_level=0.001, massConstraint=[], ipConstraint=False, updateAllDaughters=False, customOriginConstraint=False, customOriginVertex=[0.001, 0, 0.0116], customOriginCovariance=[0.0048, 0, 0, 0, 0.003567, 0, 0, 0, 0.0400], path=None)
Definition: vertex.py:191
skim.dark.ALP3Gamma.additional_setup
def additional_setup(self, path)
Definition: dark.py:141
skim.dark.ElectronMuonPlusMissingEnergy.SkimLists
SkimLists
Definition: dark.py:245
skim.dark.DielectronPlusMissingEnergy.build_lists
def build_lists(self, path)
Definition: dark.py:471
skim.dark.ALP3Gamma.SkimLists
SkimLists
Definition: dark.py:161
skim.dark.DimuonPlusMissingEnergy
Definition: dark.py:165
skim.dark.RadBhabhaV0Control.build_lists
def build_lists(self, path)
Definition: dark.py:515
skim.dark.DielectronPlusMissingEnergy.SkimLists
SkimLists
Definition: dark.py:493
skim.dark.LFVZpVisible.SkimLists
SkimLists
Definition: dark.py:294
skim.dark.DielectronPlusMissingEnergy
Definition: dark.py:449
skim.dark.DimuonPlusMissingEnergy.SkimLists
SkimLists
Definition: dark.py:200