Belle II Software  release-06-01-16
registry.py
1 # !/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 
11 
12 from importlib import import_module
13 import pandas as pd
14 
15 from basf2 import B2ERROR
16 
17 from tabulate import tabulate
18 
19 
20 _RegisteredSkims = [
21  # --- WG0: Systematics ---
22  ("10000000", "systematics", "Random"),
23  # ("10600100", "systematics", "Systematics"), renamed to SystematicsDstar.
24  ("10600300", "systematics", "SystematicsTracking"),
25  ("10600400", "systematics", "Resonance"),
26  ("10600500", "systematics", "SystematicsRadMuMu"),
27  ("10600600", "systematics", "SystematicsEELL"),
28  ("10600700", "systematics", "SystematicsRadEE"),
29  ("10620200", "systematics", "SystematicsLambda"),
30  ("11640100", "systematics", "SystematicsPhiGamma"),
31  ("10600800", "systematics", "SystematicsFourLeptonFromHLTFlag"),
32  ("10600900", "systematics", "SystematicsRadMuMuFromHLTFlag"),
33  ("10611000", "systematics", "SystematicsJpsi"),
34  ("10611100", "systematics", "SystematicsKshort"),
35  ("10601200", "systematics", "SystematicsBhabha"),
36  ("10601300", "systematics", "SystematicsCombinedHadronic"),
37  ("10601400", "systematics", "SystematicsCombinedLowMulti"),
38  ("10601500", "systematics", "SystematicsDstar"),
39 
40  # --- WG1: SL + missing energy ---
41  ("11110100", "semileptonic", "PRsemileptonicUntagged"),
42  ("11130300", "leptonic", "LeptonicUntagged"),
43  ("11130301", "leptonic", "dilepton"),
44  ("11160200", "semileptonic", "SLUntagged"),
45  ("11160201", "semileptonic", "B0toDstarl_Kpi_Kpipi0_Kpipipi"),
46  ("11180100", "fei", "feiHadronicB0"),
47  ("11180200", "fei", "feiHadronicBplus"),
48  ("11180300", "fei", "feiSLB0"),
49  ("11180301", "fei", "feiSLB0_RDstar"),
50  ("11180400", "fei", "feiSLBplus"),
51  ("11180500", "fei", "feiHadronic"),
52  ("11180501", "fei", "feiHadronic_DstEllNu"),
53  ("11180600", "fei", "feiSL"),
54 
55  # --- WG2: Electroweak penguins ---
56  ("12160100", "ewp", "BtoXgamma"),
57  ("12160200", "ewp", "BtoXll"),
58  ("12160300", "ewp", "BtoXll_LFV"),
59  ("12160400", "ewp", "inclusiveBplusToKplusNuNu"),
60 
61  # --- WG3: Time-dependent CP violation ---
62  ("13160200", "tdcpv", "TDCPV_ccs"),
63  ("13160300", "tdcpv", "TDCPV_qqs"),
64 
65  # --- WG4: Charmed B decays ---
66  ("14120300", "btocharm", "BtoD0h_Kspi0"),
67  ("14120400", "btocharm", "BtoD0h_Kspipipi0"),
68  # B0 -> D-(k+ ""- pi-)pi+ # ("14140500", "", "BtoD0h_Kspi0pi0"),
69  # Add when skim script is ready
70  ("14120600", "btocharm", "B0toDpi_Kpipi"),
71  ("14120601", "btocharm", "B0toDpi_Kspi"), # B0 -> D-(Ks pi-)pi+
72  # B0 -> D*-(anti-D0 pi-)pi+ With anti-D0 -> k+ pi-
73  ("14120700", "btocharm", "B0toDstarPi_D0pi_Kpi"),
74  # merge B0 -> D*-(anti-D0 pi-)pi+ with anti-D0 -> k- pi+ pi+ pi-
75  # and anti-D0 -> K- pi+ pi0
76  ("14120800", "btocharm", "B0toDstarPi_D0pi_Kpipipi_Kpipi0"),
77  ("14121100", "btocharm", "B0toDrho_Kpipi"),
78  ("14121101", "btocharm", "B0toDrho_Kspi"),
79  ("14121200", "btocharm", "B0toDstarRho_D0pi_Kpi"),
80  ("14121201", "btocharm", "B0toDstarRho_D0pi_Kpipipi_Kpipi0"),
81  ("14140100", "btocharm", "BtoD0h_hh"),
82  ("14140101", "btocharm", "BtoD0h_Kpi"),
83  # B+ -> anti-D0/anti-D0* (K- pi+ pi+ pi-, K- ""+ pi0) h+
84  ("14140102", "btocharm", "BtoD0h_Kpipipi_Kpipi0"),
85  ("14140200", "btocharm", "BtoD0h_Kshh"),
86  ("14141000", "btocharm", "BtoD0rho_Kpi"),
87  ("14141001", "btocharm", "BtoD0rho_Kpipipi_Kpipi0"),
88  ("14141002", "btocharm", "B0toDD_Kpipi_Kspi"),
89  ("14141003", "btocharm", "B0toDstarD"),
90  ("14121300", "btocharm", "B0toD0Kpipi0_pi0"),
91 
92 
93  # --- WG5: Quarkonium ---
94  ("15410300", "quarkonium", "InclusiveLambda"),
95  ("15420100", "quarkonium", "BottomoniumEtabExclusive"),
96  ("15440100", "quarkonium", "BottomoniumUpsilon"),
97  # ("16460100", "quarkonium", "ISRpipicc"), Subset of 16460200, deleted.
98  ("16460200", "quarkonium", "CharmoniumPsi"),
99 
100  # --- WG7: Charm physics ---
101  ("17230100", "charm", "XToD0_D0ToHpJm"), # D0 -> K pi/pi pi/K K
102  # D0 -> pi0 pi0/Ks pi0/Ks Ks # ("17230100", "", "D0ToHpJm"),
103  # D0 -> K pi/pi pi/K K
104  ("17230200", "charm", "XToD0_D0ToNeutrals"),
105  ("17230300", "charm", "DstToD0Pi_D0ToRare"), # D0 -> g g/e e/mu mu
106  ("17230400", "charm", "XToDp_DpToKsHp"), # D+ -> Ks h+
107  ("17230500", "charm", "XToDp_DpToHpHmJp"), # D+ -> h+ h- j+
108  ("17230600", "charm", "LambdacTopHpJm"), # Lambda_c+ -> proton h- j+
109  ("17240100", "charm", "DstToD0Pi_D0ToHpJm"), # D* -> D0 -> K pi/pi pi/K K
110  # D* -> D0 -> K- pi+ pi0 (""+WS)
111  ("17240200", "charm", "DstToD0Pi_D0ToHpJmPi0"),
112  ("17240300", "charm", "DstToD0Pi_D0ToHpHmPi0"), # D* -> D0 -> h h pi0
113  # D* -> D0 -> Ks omega / Ks eta -> Ks pi+ pi- pi0
114  ("17240400", "charm", "DstToD0Pi_D0ToKsOmega"),
115  # D* -> D0 -> K- pi+ eta (""+WS)
116  ("17240500", "charm", "DstToD0Pi_D0ToHpJmEta"),
117  # D* -> D0 -> pi0 pi0/Ks pi0/Ks Ks
118  ("17240600", "charm", "DstToD0Pi_D0ToNeutrals"),
119  ("17240700", "charm", "DstToD0Pi_D0ToHpJmKs"), # D* -> D0 -> h h Ks
120  # D* -> D0 -> K- pi+ pi0 (""+WS)
121  ("17240800", "charm", "EarlyData_DstToD0Pi_D0ToHpJmPi0"),
122  ("17240900", "charm", "EarlyData_DstToD0Pi_D0ToHpHmPi0"), # D* -> D0 -> h h pi0
123  ("17241000", "charm", "DstToDpPi0_DpToHpPi0"), # D*+ -> D+ pi0, D+ -> h+ pi0
124  ("17241100", "charm", "DstToD0Pi_D0ToHpHmHpJm"), # D* -> D0 -> h h h j
125  ("17241200", "charm", "DstToD0Pi_D0ToVGamma"), # D* -> D0 -> vgamma
126 
127  # --- WG8: Dark matter searches and tau physics ---
128  ("18020100", "dark", "SinglePhotonDark"),
129  ("18020200", "dark", "GammaGammaControlKLMDark"),
130  ("18020300", "dark", "ALP3Gamma"),
131  ("18020400", "dark", "EGammaControlDark"),
132  ("18000000", "dark", "InelasticDarkMatter"),
133  ("18000001", "dark", "RadBhabhaV0Control"),
134  ("18360100", "taupair", "TauLFV"),
135  ("18520100", "dark", "DimuonPlusMissingEnergy"),
136  ("18520200", "dark", "ElectronMuonPlusMissingEnergy"),
137  ("18520300", "dark", "DielectronPlusMissingEnergy"),
138  ("18520400", "dark", "LFVZpVisible"),
139  ("18130100", "dark", "BtoKplusLLP"),
140  ("18570600", "taupair", "TauGeneric"),
141  ("18570700", "taupair", "TauThrust"),
142  ("18530100", "lowMulti", "TwoTrackLeptonsForLuminosity"),
143  ("18520500", "lowMulti", "LowMassTwoTrack"),
144  ("18530200", "lowMulti", "SingleTagPseudoScalar"),
145  ("18020500", "dark", "InelasticDarkMatterWithDarkHiggs"),
146  ("18370100", "dark", "AA2uuuu"),
147 
148  # --- WG9: Charmless B decays ---
149  ("19120100", "btocharmless", "BtoPi0Pi0"),
150  ("19130201", "btocharmless", "BtoHadTracks"),
151  ("19130300", "btocharmless", "BtoHad1Pi0"),
152  ("19130310", "btocharmless", "BtoHad3Tracks1Pi0"),
153  ("19120400", "btocharmless", "BtoRhopRhom"),
154 ]
155 """
156 A list of all official registered skims and their skim code and parent module. Entries
157 must be of the form ``(code, module, name)``.
158 """
159 
160 
161 def _add_skim_registry_table(SkimRegistry):
162  """
163  Decorator to add a Sphinx table to the docstring of the skim registry.
164 
165  Inserts table wherever '<TABLE>' is in the docstring.
166  """
167 
168  df = pd.DataFrame(_RegisteredSkims, columns=["Skim code", "Module", "Skim name"])
169  df = df[["Module", "Skim name", "Skim code"]].sort_values(by=["Module", "Skim code"])
170  table = tabulate(df, showindex="never", tablefmt="grid", headers=df.columns)
171 
172  # Manual text manipulation (read: filthy hack) to make the table hierarchical
173  OriginalLines = table.split("\n")
174  header, OriginalLines, footer = OriginalLines[:2], OriginalLines[2:-1], OriginalLines[-1]
175  CurrentModule = ""
176  lines = []
177  lines.append("\n ".join(header))
178  for BorderLine, TextLine in zip(OriginalLines[::2], OriginalLines[1::2]):
179  segments = TextLine.split("|")
180  module = segments[1].lstrip().rstrip()
181  if CurrentModule == module:
182  segments[1] = " " * len(segments[1])
183  BorderLine = "|" + " " * len(segments[1]) + BorderLine.lstrip("+").lstrip("-")
184  else:
185  CurrentModule = module
186  lines.append(BorderLine)
187  lines.append("|".join(segments))
188  lines.append(footer)
189 
190  SkimRegistry.__doc__ = SkimRegistry.__doc__.replace("<TABLE>", "\n ".join(lines))
191 
192  return SkimRegistry
193 
194 
195 @_add_skim_registry_table
197  """
198  Class containing information on all official registered skims. This class also
199  contains helper functions for getting information from the registry. For
200  convenience, an instance of this class is provided: `skim.registry.Registry`.
201 
202  The table below lists all registered skims and their skim codes:
203 
204  <TABLE>
205  """
206  _registry = _RegisteredSkims
207 
208  def __init__(self):
209  self._codes_codes = [code for code, _, _ in self._registry_registry]
210  self._modules_modules = list({module for _, module, _ in self._registry_registry})
211  self._names_names = [names for _, _, names in self._registry_registry]
212 
213  @property
214  def names(self):
215  """A list of all registered skim names."""
216  return self._names_names
217 
218  @property
219  def codes(self):
220  """A list of all registered skim codes."""
221  return self._codes_codes
222 
223  @property
224  def modules(self):
225  """A list of all registered skim modules."""
226  return self._modules_modules
227 
228  def get_skim_module(self, SkimName):
229  """Retrieve the skim module name from the registry which contains the given
230  skim.
231 
232  Parameters:
233  SkimName (str): Name of the skim as it appears in the skim registry.
234 
235  Returns:
236  The name of the skim module which contains the skim.
237  """
238  lookup = {name: module for _, module, name in self._registry_registry}
239  try:
240  return lookup[SkimName]
241  except KeyError:
242  B2ERROR(
243  f"Unrecognised skim name {SkimName}. "
244  "Please add your skim to the list in `skim/scripts/skim/registry.py`."
245  )
246  raise LookupError(SkimName)
247 
248  def get_skims_in_module(self, SkimModule):
249  """Retrieve a list of the skims listed in the registry as existing in
250  the given skim module.
251 
252  Parameters:
253  SkimModule (str): The name of the module, *e.g.* ``btocharmless`` (not
254  ``skim.btocharmless`` or ``btocharmless.py``).
255 
256  Returns:
257  The skims listed in the registry as belonging to ``SkimModule``.
258  """
259  if SkimModule not in self.modulesmodules:
260  B2ERROR(f"Unrecognised skim module {SkimModule}.")
261  raise LookupError(SkimModule)
262 
263  ModuleLookup = {name: module for _, module, name in self._registry_registry}
264  NameLookup = {
265  module: [name for name in self.namesnames if ModuleLookup[name] == module]
266  for module in self.modulesmodules
267  }
268  return NameLookup[SkimModule]
269 
270  def get_skim_function(self, SkimName):
271  """Get the skim class constructor for the given skim.
272 
273  This is achieved by importing the module listed alongside the skim name in the
274  skim registry.
275 
276  Parameters:
277  SkimName (str): Name of the skim to be found.
278 
279  Returns:
280  The class constructor for the given skim.
281  """
282  ModuleName = self.get_skim_moduleget_skim_module(SkimName)
283  SkimModule = import_module(f"skim.WGs.{ModuleName}")
284  return getattr(SkimModule, SkimName)
285 
286  def encode_skim_name(self, SkimName):
287  """Find the 8 digit skim code assigned to the skim with the provided name.
288 
289  Parameters:
290  SkimName (str): Name of the corresponding skim as it appears in the skim registry.
291 
292  Returns:
293  8 digit skim code assigned to the given skim.
294  """
295  lookup = {name: code for code, _, name in self._registry_registry}
296  try:
297  return lookup[SkimName]
298  except KeyError:
299  B2ERROR(
300  f"Unrecognised skim name {SkimName}. "
301  "Please add your skim to the list in `skim/scripts/skim/registry.py`."
302  )
303  raise LookupError(SkimName)
304 
305  def decode_skim_code(self, SkimCode):
306  """Find the name of the skim which corresponds to the provided skim code.
307 
308  This is useful to determine the skim script used to produce a specific uDST
309  file, given the 8-digit code name of the file itself.
310 
311  Parameters:
312  SkimCode (str): 8 digit skim code assigned to some skim.
313 
314  Returns:
315  Name of the corresponding skim as it appears in the skim registry.
316  """
317  lookup = {code: name for code, _, name in self._registry_registry}
318  try:
319  return lookup[SkimCode]
320  except KeyError:
321  B2ERROR(
322  f"Unrecognised skim code {SkimCode}. "
323  "Please add your skim to the list in `skim/scripts/skim/registry.py`."
324  )
325  raise LookupError(SkimCode)
326 
327 
328 Registry = SkimRegistryClass()
329 """
330 An instance of `skim.registry.SkimRegistryClass`. Use this in your script to get
331 information from the registry.
332 
333  >>> from skim.registry import Registry
334  >>> Registry.encode_skim_name("SinglePhotonDark")
335  18020100
336 """
def decode_skim_code(self, SkimCode)
Definition: registry.py:305
def get_skims_in_module(self, SkimModule)
Definition: registry.py:248
def encode_skim_name(self, SkimName)
Definition: registry.py:286
def get_skim_module(self, SkimName)
Definition: registry.py:228
def get_skim_function(self, SkimName)
Definition: registry.py:270