atlas-ftag-tools 0.2.4__tar.gz → 0.2.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/PKG-INFO +1 -1
  2. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/atlas_ftag_tools.egg-info/PKG-INFO +1 -1
  3. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/__init__.py +3 -1
  4. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/flavour.py +2 -1
  5. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/flavours.yaml +29 -0
  6. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/hdf5/h5writer.py +1 -1
  7. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/labeller.py +5 -2
  8. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/mock.py +16 -11
  9. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/track_selector.py +3 -1
  10. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/wps/discriminant.py +11 -2
  11. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/wps/working_points.py +1 -1
  12. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/MANIFEST.in +0 -0
  13. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/README.md +0 -0
  14. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/atlas_ftag_tools.egg-info/SOURCES.txt +0 -0
  15. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/atlas_ftag_tools.egg-info/dependency_links.txt +0 -0
  16. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/atlas_ftag_tools.egg-info/entry_points.txt +0 -0
  17. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/atlas_ftag_tools.egg-info/requires.txt +0 -0
  18. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/atlas_ftag_tools.egg-info/top_level.txt +0 -0
  19. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/cli_utils.py +0 -0
  20. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/cuts.py +0 -0
  21. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/git_check.py +0 -0
  22. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/hdf5/__init__.py +0 -0
  23. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/hdf5/h5move.py +0 -0
  24. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/hdf5/h5reader.py +0 -0
  25. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/hdf5/h5split.py +0 -0
  26. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/hdf5/h5utils.py +0 -0
  27. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/region.py +0 -0
  28. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/sample.py +0 -0
  29. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/test_cli_utils.py +0 -0
  30. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/transform.py +0 -0
  31. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/vds.py +0 -0
  32. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/ftag/wps/__init__.py +0 -0
  33. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/pyproject.toml +0 -0
  34. {atlas_ftag_tools-0.2.4 → atlas_ftag_tools-0.2.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atlas-ftag-tools
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: ATLAS Flavour Tagging Tools
5
5
  Author: Sam Van Stroud, Philipp Gadow
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atlas-ftag-tools
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: ATLAS Flavour Tagging Tools
5
5
  Author: Sam Van Stroud, Philipp Gadow
6
6
  License: MIT
@@ -2,12 +2,13 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = "v0.2.4"
5
+ __version__ = "v0.2.6"
6
6
 
7
7
 
8
8
  from ftag import hdf5
9
9
  from ftag.cuts import Cuts
10
10
  from ftag.flavour import Flavour, Flavours
11
+ from ftag.labeller import Labeller
11
12
  from ftag.mock import get_mock_file
12
13
  from ftag.sample import Sample
13
14
  from ftag.transform import Transform
@@ -18,6 +19,7 @@ __all__ = [
18
19
  "Cuts",
19
20
  "Flavour",
20
21
  "Flavours",
22
+ "Labeller",
21
23
  "Sample",
22
24
  "Transform",
23
25
  "__version__",
@@ -22,10 +22,11 @@ class Flavour:
22
22
  cuts: Cuts
23
23
  colour: str
24
24
  category: str
25
+ _px: str | None = None
25
26
 
26
27
  @property
27
28
  def px(self) -> str:
28
- return f"p{remove_suffix(self.name, 'jets')}"
29
+ return self._px or f"p{remove_suffix(self.name, 'jets')}"
29
30
 
30
31
  @property
31
32
  def eff_str(self) -> str:
@@ -53,21 +53,25 @@
53
53
  cuts: ["HadronGhostTruthLabelID == 5"]
54
54
  colour: tab:blue
55
55
  category: single-btag-ghost
56
+ _px: pb
56
57
  - name: ghostcjets
57
58
  label: $c$-jets
58
59
  cuts: ["HadronGhostTruthLabelID == 4"]
59
60
  colour: tab:orange
60
61
  category: single-btag-ghost
62
+ _px: pc
61
63
  - name: ghostujets
62
64
  label: Light-jets
63
65
  cuts: ["HadronGhostTruthLabelID == 0"]
64
66
  colour: tab:green
65
67
  category: single-btag-ghost
68
+ _px: pu
66
69
  - name: ghosttaujets
67
70
  label: $\tau$-jets
68
71
  cuts: ["HadronGhostTruthLabelID == 15"]
69
72
  colour: tab:purple
70
73
  category: single-btag-ghost
74
+ _px: ptau
71
75
 
72
76
  # Xbb tagging
73
77
  - name: hbb
@@ -90,6 +94,31 @@
90
94
  cuts: ["R10TruthLabel_R22v1 == 10"]
91
95
  colour: "#38761D"
92
96
  category: xbb
97
+ - name: qcdbb
98
+ label: QCD->bb
99
+ cuts: ["R10TruthLabel_R22v1 == 10", "GhostBHadronsFinalCount == 2"]
100
+ colour: "red"
101
+ category: xbb
102
+ - name: qcdnonbb
103
+ label: QCD
104
+ cuts: ["R10TruthLabel_R22v1 == 10", "GhostBHadronsFinalCount != 2"]
105
+ colour: "silver"
106
+ category: xbb
107
+ - name: qcdbx
108
+ label: QCD
109
+ cuts: ["R10TruthLabel_R22v1 == 10", "GhostBHadronsFinalCount == 1"]
110
+ colour: "gold"
111
+ category: xbb
112
+ - name: qcdcx
113
+ label: QCD
114
+ cuts: ["R10TruthLabel_R22v1 == 10", "GhostCHadronsFinalCount >= 1", "GhostBHadronsFinalCount == 0"]
115
+ colour: "pink"
116
+ category: xbb
117
+ - name: qcdll
118
+ label: QCD
119
+ cuts: ["R10TruthLabel_R22v1 == 10", "GhostBHadronsFinalCount == 0", "GhostCHadronsFinalCount == 0"]
120
+ colour: "green"
121
+ category: xbb
93
122
 
94
123
  # extended Xbb tagging
95
124
  - name: tqqb
@@ -81,7 +81,7 @@ class H5Writer:
81
81
  return cls(dtypes=dtypes, shapes=shapes, **kwargs)
82
82
 
83
83
  def create_ds(self, name: str, dtype: np.dtype) -> None:
84
- if name == self.jets_name and self.add_flavour_label:
84
+ if name == self.jets_name and self.add_flavour_label and "flavour_label" not in dtype.names:
85
85
  dtype = np.dtype([*dtype.descr, ("flavour_label", "i4")])
86
86
 
87
87
  # adjust dtype based on specified precision
@@ -4,8 +4,7 @@ from dataclasses import dataclass
4
4
 
5
5
  import numpy as np
6
6
 
7
- from ftag import Flavours
8
- from ftag.flavour import Flavour, FlavourContainer
7
+ from ftag.flavour import Flavour, FlavourContainer, Flavours
9
8
  from ftag.hdf5 import join_structured_arrays, structured_from_dict
10
9
 
11
10
 
@@ -27,6 +26,10 @@ class Labeller:
27
26
  labels: FlavourContainer | list[str | Flavour]
28
27
  require_labels: bool = True
29
28
 
29
+ @property
30
+ def variables(self):
31
+ return sum((label.cuts.variables for label in self.labels), [])
32
+
30
33
  def __post_init__(self) -> None:
31
34
  if isinstance(self.labels, FlavourContainer):
32
35
  self.labels = list(self.labels)
@@ -22,6 +22,8 @@ JET_VARS = [
22
22
  ("HadronConeExclTruthLabelID", "i4"),
23
23
  ("HadronConeExclTruthLabelPt", "f4"),
24
24
  ("R10TruthLabel_R22v1", "i4"),
25
+ ("GhostBHadronsFinalCount", "i4"),
26
+ ("GhostCHadronsFinalCount", "i4"),
25
27
  ("n_truth_promptLepton", "i4"),
26
28
  ("flavour_label", "i4"),
27
29
  ]
@@ -37,17 +39,18 @@ TRACK_VARS = [
37
39
  ("phiUncertainty", "f4"),
38
40
  ("thetaUncertainty", "f4"),
39
41
  ("qOverPUncertainty", "f4"),
40
- ("numberOfPixelHits", "i4"),
41
- ("numberOfSCTHits", "i4"),
42
- ("numberOfInnermostPixelLayerHits", "i4"),
43
- ("numberOfNextToInnermostPixelLayerHits", "i4"),
44
- ("numberOfInnermostPixelLayerSharedHits", "i4"),
45
- ("numberOfInnermostPixelLayerSplitHits", "i4"),
46
- ("numberOfPixelSharedHits", "i4"),
47
- ("numberOfPixelSplitHits", "i4"),
48
- ("numberOfSCTSharedHits", "i4"),
49
- ("numberOfPixelHoles", "i4"),
50
- ("numberOfSCTHoles", "i4"),
42
+ ("numberOfPixelHits", "u1"),
43
+ ("numberOfSCTHits", "u1"),
44
+ ("numberOfInnermostPixelLayerHits", "u1"),
45
+ ("numberOfNextToInnermostPixelLayerHits", "u1"),
46
+ ("numberOfInnermostPixelLayerSharedHits", "u1"),
47
+ ("numberOfInnermostPixelLayerSplitHits", "u1"),
48
+ ("numberOfPixelSharedHits", "u1"),
49
+ ("numberOfPixelSplitHits", "u1"),
50
+ ("numberOfSCTSharedHits", "u1"),
51
+ ("numberOfPixelHoles", "u1"),
52
+ ("numberOfSCTHoles", "u1"),
53
+ ("leptonID", "i1"),
51
54
  ]
52
55
 
53
56
 
@@ -98,6 +101,8 @@ def mock_jets(num_jets=1000) -> np.ndarray:
98
101
 
99
102
  # add tagger scores
100
103
  jets["HadronConeExclTruthLabelID"] = rng.choice([0, 4, 5, 15], size=num_jets)
104
+ jets["GhostBHadronsFinalCount"] = rng.choice([0, 1, 2], size=num_jets)
105
+ jets["GhostCHadronsFinalCount"] = rng.choice([0, 1, 2], size=num_jets)
101
106
  jets["R10TruthLabel_R22v1"] = rng.choice([1, 10, 11, 12], size=num_jets)
102
107
  scores = get_mock_scores(jets["HadronConeExclTruthLabelID"])
103
108
  xbb_scores = get_mock_scores(jets["R10TruthLabel_R22v1"], is_xbb=True)
@@ -41,8 +41,10 @@ class TrackSelector:
41
41
  for var in tracks.dtype.names:
42
42
  if issubclass(tracks[var].dtype.type, np.floating):
43
43
  tracks[var][rm_idx] = np.nan
44
- elif issubclass(tracks[var].dtype.type, np.integer):
44
+ elif issubclass(tracks[var].dtype.type, np.signedinteger):
45
45
  tracks[var][rm_idx] = -1
46
+ elif issubclass(tracks[var].dtype.type, np.unsignedinteger):
47
+ tracks[var][rm_idx] = 0
46
48
  elif issubclass(tracks[var].dtype.type, np.bool_):
47
49
  tracks[var][rm_idx] = False
48
50
  else:
@@ -4,7 +4,7 @@ from typing import Callable
4
4
 
5
5
  import numpy as np
6
6
 
7
- from ftag.flavour import Flavour, Flavours
7
+ from ftag.flavour import Flavour, Flavours, remove_suffix
8
8
 
9
9
 
10
10
  def discriminant(
@@ -50,7 +50,10 @@ def discriminant(
50
50
  if fx > 0 and name not in jets.dtype.names:
51
51
  raise ValueError(f"Nonzero fx for {d}, but '{name}' not found in input array.")
52
52
  denominator += jets[name] * fx if name in jets.dtype.names else 0
53
- return np.log((jets[f"{tagger}_{signal.px}"] + epsilon) / (denominator + epsilon))
53
+ signal_field = f"{tagger}_{signal.px}"
54
+ if signal_field not in jets.dtype.names:
55
+ signal_field = f"{tagger}_p{remove_suffix(signal.name, 'jets')}"
56
+ return np.log((jets[signal_field] + epsilon) / (denominator + epsilon))
54
57
 
55
58
 
56
59
  def tautag_dicriminant(jets, tagger, fb, fc, epsilon=1e-10):
@@ -63,6 +66,11 @@ def btag_discriminant(jets, tagger, fc, ftau=0, epsilon=1e-10):
63
66
  return discriminant(jets, tagger, Flavours.bjets, fxs, epsilon=epsilon)
64
67
 
65
68
 
69
+ def ghostbtag_discriminant(jets, tagger, fc, ftau=0, epsilon=1e-10):
70
+ fxs = {"pghostc": fc, "pghosttau": ftau, "pghostu": 1 - fc - ftau}
71
+ return discriminant(jets, tagger, Flavours.ghostbjets, fxs, epsilon=epsilon)
72
+
73
+
66
74
  def ctag_discriminant(jets, tagger, fb, ftau=0, epsilon=1e-10):
67
75
  fxs = {"pb": fb, "ptau": ftau, "pu": 1 - fb - ftau}
68
76
  return discriminant(jets, tagger, Flavours.cjets, fxs, epsilon=epsilon)
@@ -112,6 +120,7 @@ def get_discriminant(
112
120
  "taujets": tautag_dicriminant,
113
121
  "hbb": hbb_discriminant,
114
122
  "hcc": hcc_discriminant,
123
+ "ghostbjets": ghostbtag_discriminant,
115
124
  }
116
125
 
117
126
  if str(signal) not in tagger_funcs:
@@ -218,7 +218,7 @@ def setup_common_parts(args):
218
218
  zprime_cuts = Cuts.from_list(args.zprime_cuts) + default_cuts
219
219
 
220
220
  # prepare to load jets
221
- all_vars = next(iter(flavs)).cuts.variables
221
+ all_vars = list(set(sum((flav.cuts.variables for flav in flavs), [])))
222
222
  reader = H5Reader(args.ttbar)
223
223
  jet_vars = reader.dtypes()["jets"].names
224
224
  for tagger in args.tagger: