atlas-ftag-tools 0.2.4__py3-none-any.whl → 0.2.6__py3-none-any.whl

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.
@@ -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,15 +1,15 @@
1
- ftag/__init__.py,sha256=Mx2Emsw4TM1YL0wTQMHK36EaQE_ImeV6ukiz1X5BZAU,629
1
+ ftag/__init__.py,sha256=edvBW3ySbO10OzSeqTQd9HPuXqiosdWibAhi3ZJFT4g,680
2
2
  ftag/cli_utils.py,sha256=w3TtQmUHSyAKChS3ewvOtcSDAUJAZGIIomaNi8f446U,298
3
3
  ftag/cuts.py,sha256=9_ooLZHaO3SnIQBNxwbaPZn-qptGdKnB27FdKQGTiTY,2933
4
- ftag/flavour.py,sha256=EMZZLyl6lSdvkfrYxHhMcSn3aqP_FU7OpCFkvZpTksU,3761
5
- ftag/flavours.yaml,sha256=lFnVwjh_DwLhOc3mr5n6bSIWyHgxQvAXas4lEmEDncU,7520
4
+ ftag/flavour.py,sha256=MUij7lknepnkidErDsyNsJDbAPotAEwS-uMaTSYCet4,3800
5
+ ftag/flavours.yaml,sha256=E_vpn38qJ3-Tygg2aHlH4wkn_rR1On_lMeaG8OemHCQ,8285
6
6
  ftag/git_check.py,sha256=Y-XqM80CVXZ5ZKrDdZcYOJt3X64uU6W3OP6Z0D7AZU0,1663
7
- ftag/labeller.py,sha256=uDygOhVGSNn96DWw8aErHpTtFsFX0RnxYYpy4g1FRog,2457
8
- ftag/mock.py,sha256=_oy-r3eLllFy33NAoZaKfAx-Rp2vrCdrGj3UsTMks94,4740
7
+ ftag/labeller.py,sha256=iyDjRkOaly48jTaaFimA5eZ5YySp1lrLVEt3GyDZW-8,2553
8
+ ftag/mock.py,sha256=Eyj3tkkaSSnqvS3G6NS7fq8sB__Nx8YE9-OM2_lpdoQ,4992
9
9
  ftag/region.py,sha256=ANv0dGI2W6NJqD9fp7EfqAUReH4FOjc1gwl_Qn8llcM,360
10
10
  ftag/sample.py,sha256=TFXMhDkbPmjkms9-b-bINJ32T3bO86JcU70C0nY7wa8,2500
11
11
  ftag/test_cli_utils.py,sha256=xa08vf6SEOow58SSFagYdAselb-dkNOVvWsWheMnW-g,1001
12
- ftag/track_selector.py,sha256=piSYAN_IkOsrXxKXjXbJpMSseUig5P2BJW5mCwsMUDM,2535
12
+ ftag/track_selector.py,sha256=fJNk_kIBQriBqV4CPT_3ReJbOUnavDDzO-u3EQlRuyk,2654
13
13
  ftag/transform.py,sha256=uEGGJSnqoKOzLYQv650XdK_kDNw4Aw-5dc60z9Dp_y0,3963
14
14
  ftag/vds.py,sha256=nRViQZQIORB95nC7NZsW3KsSoGkLzEdOsuCViH5h8-U,3296
15
15
  ftag/hdf5/__init__.py,sha256=LFDNxVOCp58SvLHwQhdT68Q-KBMS_i6jBrbXoRpHzbM,354
@@ -17,12 +17,12 @@ ftag/hdf5/h5move.py,sha256=oYpRu0IDCIJIQ2ML52HBAdoyDxmKkHTeM9JdbPEgKfI,947
17
17
  ftag/hdf5/h5reader.py,sha256=i31pDAqmOSaxdeRhc4iSBlld8xJ0pmp4rNd7CugNzw0,13706
18
18
  ftag/hdf5/h5split.py,sha256=4Wy6Xc3J58MdD9aBaSZHf5ZcVFnJSkWsm42R5Pgo-R4,2448
19
19
  ftag/hdf5/h5utils.py,sha256=-4zKTMtNCrDZr_9Ww7uzfsB7M7muBKpmm_1IkKJnHOI,3222
20
- ftag/hdf5/h5writer.py,sha256=j3Fy8snkiVVfimiUz3rrZOhSV8OF27978Y9pk0QcTGM,5277
20
+ ftag/hdf5/h5writer.py,sha256=9FkClV__UbBqmFsq_h2jwiZnbWVm8QFRL_4mDZZBbTs,5316
21
21
  ftag/wps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- ftag/wps/discriminant.py,sha256=kJFekUTPNIvCabJCon6OqOAQEzz5hj3XrWFFRLOgGOs,3836
23
- ftag/wps/working_points.py,sha256=VTU6OD40ULAJQD0MlD1EZd33q8ociUvFX1YrhgJFvXc,9722
24
- atlas_ftag_tools-0.2.4.dist-info/METADATA,sha256=f4aCu6JmItUBp5EmTzbrqhC5-Wsy7uiOiBO9yufyacQ,5169
25
- atlas_ftag_tools-0.2.4.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
26
- atlas_ftag_tools-0.2.4.dist-info/entry_points.txt,sha256=LfVLsZHQolqbPnwPgtmc5IQTh527BKkN2v-IpXWTNHw,137
27
- atlas_ftag_tools-0.2.4.dist-info/top_level.txt,sha256=qiYQuKcAvMim-31FwkT3MTQu7WQm0s58tPAia5KKWqs,5
28
- atlas_ftag_tools-0.2.4.dist-info/RECORD,,
22
+ ftag/wps/discriminant.py,sha256=rTASnt9s6xEHK5hLKHgvc9c7TiyyX6Upbp4LeTh6TB0,4270
23
+ ftag/wps/working_points.py,sha256=fPfSZoTp-2qxL3YB7HdPxIB-7aSR_HozEtWWIA0BUtg,9749
24
+ atlas_ftag_tools-0.2.6.dist-info/METADATA,sha256=gmEDL518a_xrRBsPsRYCFt-C06BD3K9bH6HCStV6mAU,5169
25
+ atlas_ftag_tools-0.2.6.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
26
+ atlas_ftag_tools-0.2.6.dist-info/entry_points.txt,sha256=LfVLsZHQolqbPnwPgtmc5IQTh527BKkN2v-IpXWTNHw,137
27
+ atlas_ftag_tools-0.2.6.dist-info/top_level.txt,sha256=qiYQuKcAvMim-31FwkT3MTQu7WQm0s58tPAia5KKWqs,5
28
+ atlas_ftag_tools-0.2.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.1.0)
2
+ Generator: setuptools (75.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
ftag/__init__.py CHANGED
@@ -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__",
ftag/flavour.py CHANGED
@@ -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:
ftag/flavours.yaml CHANGED
@@ -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
ftag/hdf5/h5writer.py CHANGED
@@ -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
ftag/labeller.py CHANGED
@@ -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)
ftag/mock.py CHANGED
@@ -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)
ftag/track_selector.py CHANGED
@@ -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:
ftag/wps/discriminant.py CHANGED
@@ -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: