atlas-ftag-tools 0.0.4__tar.gz → 0.0.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.
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/PKG-INFO +3 -2
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/README.md +1 -0
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/atlas_ftag_tools.egg-info/PKG-INFO +3 -2
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/atlas_ftag_tools.egg-info/SOURCES.txt +1 -0
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/atlas_ftag_tools.egg-info/requires.txt +3 -3
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/ftag/__init__.py +3 -2
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/ftag/flavour.py +24 -1
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/ftag/hdf5/__init__.py +3 -7
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/ftag/hdf5/h5reader.py +48 -30
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/ftag/hdf5/h5utils.py +2 -56
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/ftag/hdf5/h5writer.py +5 -0
- atlas-ftag-tools-0.0.6/ftag/mock.py +105 -0
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/ftag/sample.py +2 -0
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/ftag/vds.py +2 -0
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/pyproject.toml +5 -4
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/MANIFEST.in +0 -0
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/atlas_ftag_tools.egg-info/dependency_links.txt +0 -0
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/atlas_ftag_tools.egg-info/top_level.txt +0 -0
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/ftag/cuts.py +0 -0
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/ftag/flavours.yaml +0 -0
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/ftag/region.py +0 -0
- {atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/setup.cfg +0 -0
@@ -1,17 +1,18 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: atlas-ftag-tools
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.6
|
4
4
|
Summary: ATLAS Flavour Tagging Tools
|
5
5
|
Author: Sam Van Stroud, Philipp Gadow
|
6
6
|
License: MIT
|
7
7
|
Project-URL: Homepage, https://github.com/umami-hep/atlas-ftag-tools/
|
8
|
-
Requires-Python: >=3.
|
8
|
+
Requires-Python: >=3.8
|
9
9
|
Description-Content-Type: text/markdown
|
10
10
|
Provides-Extra: dev
|
11
11
|
|
12
12
|
# ATLAS FTAG Python Tools
|
13
13
|
|
14
14
|
This is a collection of Python tools for working with files produced with the FTAG [ntuple dumper](https://gitlab.cern.ch/atlas-flavor-tagging-tools/training-dataset-dumper/).
|
15
|
+
The code is intended to be used a [library](https://iscinumpy.dev/post/app-vs-library/) for other projects.
|
15
16
|
Please see the [example notebook](ftag/example.ipynb) for usage.
|
16
17
|
|
17
18
|
## Installation
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# ATLAS FTAG Python Tools
|
2
2
|
|
3
3
|
This is a collection of Python tools for working with files produced with the FTAG [ntuple dumper](https://gitlab.cern.ch/atlas-flavor-tagging-tools/training-dataset-dumper/).
|
4
|
+
The code is intended to be used a [library](https://iscinumpy.dev/post/app-vs-library/) for other projects.
|
4
5
|
Please see the [example notebook](ftag/example.ipynb) for usage.
|
5
6
|
|
6
7
|
## Installation
|
@@ -1,17 +1,18 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: atlas-ftag-tools
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.6
|
4
4
|
Summary: ATLAS Flavour Tagging Tools
|
5
5
|
Author: Sam Van Stroud, Philipp Gadow
|
6
6
|
License: MIT
|
7
7
|
Project-URL: Homepage, https://github.com/umami-hep/atlas-ftag-tools/
|
8
|
-
Requires-Python: >=3.
|
8
|
+
Requires-Python: >=3.8
|
9
9
|
Description-Content-Type: text/markdown
|
10
10
|
Provides-Extra: dev
|
11
11
|
|
12
12
|
# ATLAS FTAG Python Tools
|
13
13
|
|
14
14
|
This is a collection of Python tools for working with files produced with the FTAG [ntuple dumper](https://gitlab.cern.ch/atlas-flavor-tagging-tools/training-dataset-dumper/).
|
15
|
+
The code is intended to be used a [library](https://iscinumpy.dev/post/app-vs-library/) for other projects.
|
15
16
|
Please see the [example notebook](ftag/example.ipynb) for usage.
|
16
17
|
|
17
18
|
## Installation
|
@@ -1,7 +1,7 @@
|
|
1
1
|
"""atlas-ftag-tools - Common tools for ATLAS flavour tagging software."""
|
2
2
|
|
3
3
|
|
4
|
-
__version__ = "v0.0.
|
4
|
+
__version__ = "v0.0.6"
|
5
5
|
|
6
6
|
from pathlib import Path
|
7
7
|
|
@@ -10,6 +10,7 @@ import yaml
|
|
10
10
|
import ftag.hdf5 as hdf5
|
11
11
|
from ftag.cuts import Cuts
|
12
12
|
from ftag.flavour import Flavour, FlavourContainer
|
13
|
+
from ftag.mock import get_mock_file
|
13
14
|
from ftag.sample import Sample
|
14
15
|
|
15
16
|
# load flavours
|
@@ -19,4 +20,4 @@ flavours_dict = {f["name"]: Flavour(cuts=Cuts.from_list(f.pop("cuts")), **f) for
|
|
19
20
|
assert len(flavours_dict) == len(flavours_yaml), "Duplicate flavour names detected"
|
20
21
|
Flavours = FlavourContainer(flavours_dict)
|
21
22
|
|
22
|
-
__all__ = ["Cuts", "Flavours", "Sample", "hdf5", "__version__"]
|
23
|
+
__all__ = ["Cuts", "Flavours", "Sample", "hdf5", "get_mock_file", "__version__"]
|
@@ -16,7 +16,17 @@ class Flavour:
|
|
16
16
|
|
17
17
|
@property
|
18
18
|
def px(self) -> str:
|
19
|
-
|
19
|
+
if self.name.endswith("jets"):
|
20
|
+
return f"p{self.name[: -len('jets')]}"
|
21
|
+
return f"p{self.name}"
|
22
|
+
|
23
|
+
@property
|
24
|
+
def eff_str(self) -> str:
|
25
|
+
return self.label.replace("jets", "jet") + " efficiency"
|
26
|
+
|
27
|
+
@property
|
28
|
+
def rej_str(self) -> str:
|
29
|
+
return self.label.replace("jets", "jet") + " rejection"
|
20
30
|
|
21
31
|
def __str__(self) -> str:
|
22
32
|
return self.name
|
@@ -38,6 +48,11 @@ class FlavourContainer:
|
|
38
48
|
def __getattr__(self, name) -> Flavour:
|
39
49
|
return self[name]
|
40
50
|
|
51
|
+
def __contains__(self, flavour: str | Flavour) -> bool:
|
52
|
+
if isinstance(flavour, Flavour):
|
53
|
+
flavour = flavour.name
|
54
|
+
return flavour in self.flavours
|
55
|
+
|
41
56
|
def __repr__(self) -> str:
|
42
57
|
return f"{self.__class__.__name__}({', '.join(list(f.name for f in self))})"
|
43
58
|
|
@@ -47,3 +62,11 @@ class FlavourContainer:
|
|
47
62
|
|
48
63
|
def by_category(self, category: str) -> FlavourContainer:
|
49
64
|
return FlavourContainer({k: v for k, v in self.flavours.items() if v.category == category})
|
65
|
+
|
66
|
+
def from_cuts(self, cuts: list | Cuts) -> Flavour:
|
67
|
+
if isinstance(cuts, list):
|
68
|
+
cuts = Cuts.from_list(cuts)
|
69
|
+
for flavour in self:
|
70
|
+
if flavour.cuts == cuts:
|
71
|
+
return flavour
|
72
|
+
raise KeyError(f"Flavour with {cuts} not found")
|
@@ -1,17 +1,13 @@
|
|
1
1
|
from ftag.hdf5.h5reader import H5Reader
|
2
|
-
from ftag.hdf5.h5utils import
|
3
|
-
cast_dtype,
|
4
|
-
get_dtype,
|
5
|
-
get_dummy_file,
|
6
|
-
join_structured_arrays,
|
7
|
-
)
|
2
|
+
from ftag.hdf5.h5utils import cast_dtype, get_dtype, join_structured_arrays
|
8
3
|
from ftag.hdf5.h5writer import H5Writer
|
4
|
+
from ftag.mock import get_mock_file
|
9
5
|
|
10
6
|
__all__ = [
|
11
7
|
"H5Reader",
|
12
8
|
"H5Writer",
|
13
|
-
"get_dummy_file",
|
14
9
|
"get_dtype",
|
15
10
|
"cast_dtype",
|
16
11
|
"join_structured_arrays",
|
12
|
+
"get_mock_file",
|
17
13
|
]
|
@@ -1,3 +1,5 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
import logging as log
|
2
4
|
import math
|
3
5
|
from collections.abc import Generator
|
@@ -58,43 +60,28 @@ class H5SingleReader:
|
|
58
60
|
)
|
59
61
|
return {name: array[keep_idx] for name, array in data.items()}
|
60
62
|
|
61
|
-
def stream(
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
variables : dict
|
67
|
-
Dictionary of variables to for each group.
|
68
|
-
num_jets : int
|
69
|
-
Total number of selected jets to generate.
|
70
|
-
cuts : Cuts | None, optional
|
71
|
-
Cuts to apply, by default None
|
72
|
-
|
73
|
-
Yields
|
74
|
-
------
|
75
|
-
Generator
|
76
|
-
Generator of batches of selected jets.
|
77
|
-
|
78
|
-
Raises
|
79
|
-
------
|
80
|
-
ValueError
|
81
|
-
If more jets are requested than available.
|
82
|
-
"""
|
63
|
+
def stream(
|
64
|
+
self, variables: dict | None = None, num_jets: int | None = None, cuts: Cuts | None = None
|
65
|
+
) -> Generator:
|
66
|
+
if num_jets is None:
|
67
|
+
num_jets = self.num_jets
|
83
68
|
if num_jets > self.num_jets:
|
84
69
|
raise ValueError(
|
85
70
|
f"{num_jets:,} jets requested but only {self.num_jets:,} available in {self.fname}"
|
86
71
|
)
|
87
72
|
|
88
|
-
|
89
|
-
|
73
|
+
if variables is None:
|
74
|
+
variables = {self.jets_name: None}
|
75
|
+
|
90
76
|
total = 0
|
77
|
+
rng = np.random.default_rng(42)
|
91
78
|
with h5py.File(self.fname) as f:
|
92
79
|
data = {name: self.empty(f[name], var) for name, var in variables.items()}
|
93
80
|
|
94
81
|
# get indices
|
95
82
|
indices = list(range(0, self.num_jets, self.batch_size))
|
96
83
|
if self.shuffle:
|
97
|
-
|
84
|
+
rng.shuffle(indices)
|
98
85
|
|
99
86
|
# loop over batches and read file
|
100
87
|
for low in indices:
|
@@ -130,7 +117,7 @@ class H5Reader:
|
|
130
117
|
weights: list[float] | None = None
|
131
118
|
|
132
119
|
def __post_init__(self) -> None:
|
133
|
-
if isinstance(self.fname, str
|
120
|
+
if isinstance(self.fname, (str, Path)):
|
134
121
|
self.fname = [self.fname]
|
135
122
|
|
136
123
|
# calculate batch sizes
|
@@ -141,7 +128,7 @@ class H5Reader:
|
|
141
128
|
# create readers
|
142
129
|
self.readers = [
|
143
130
|
H5SingleReader(fname, batch_size, self.jets_name, self.precision, self.shuffle)
|
144
|
-
for fname, batch_size in zip(self.fname, self.batch_sizes
|
131
|
+
for fname, batch_size in zip(self.fname, self.batch_sizes)
|
145
132
|
]
|
146
133
|
|
147
134
|
@property
|
@@ -158,7 +145,33 @@ class H5Reader:
|
|
158
145
|
with h5py.File(self.readers[0].fname) as f:
|
159
146
|
return f[name].dtype
|
160
147
|
|
161
|
-
def stream(
|
148
|
+
def stream(
|
149
|
+
self, variables: dict | None = None, num_jets: int | None = None, cuts: Cuts | None = None
|
150
|
+
) -> Generator:
|
151
|
+
"""Generate batches of selected jets.
|
152
|
+
|
153
|
+
Parameters
|
154
|
+
----------
|
155
|
+
variables : dict | None, optional
|
156
|
+
Dictionary of variables to for each group, by default use all jet variables.
|
157
|
+
num_jets : int | None, optional
|
158
|
+
Total number of selected jets to generate, by default all.
|
159
|
+
cuts : Cuts | None, optional
|
160
|
+
Selection cuts to apply, by default None
|
161
|
+
|
162
|
+
Yields
|
163
|
+
------
|
164
|
+
Generator
|
165
|
+
Generator of batches of selected jets.
|
166
|
+
"""
|
167
|
+
if num_jets is None:
|
168
|
+
num_jets = self.num_jets
|
169
|
+
if variables is None:
|
170
|
+
variables = {self.jets_name: None}
|
171
|
+
if self.jets_name not in variables or variables[self.jets_name] is not None:
|
172
|
+
jet_vars = variables.get(self.jets_name, [])
|
173
|
+
variables[self.jets_name] = list(jet_vars) + (cuts.variables if cuts else [])
|
174
|
+
|
162
175
|
# get streams for selected jets from each reader
|
163
176
|
streams = [
|
164
177
|
r.stream(variables, int(r.num_jets / self.num_jets * num_jets), cuts)
|
@@ -184,11 +197,16 @@ class H5Reader:
|
|
184
197
|
# select
|
185
198
|
yield data
|
186
199
|
|
187
|
-
def load(
|
200
|
+
def load(
|
201
|
+
self, variables: dict | None = None, num_jets: int | None = None, cuts: Cuts | None = None
|
202
|
+
) -> dict:
|
203
|
+
if variables is None:
|
204
|
+
variables = {self.jets_name: None}
|
188
205
|
data: dict[str, list] = {name: [] for name in variables}
|
189
206
|
for sample in self.stream(variables, num_jets, cuts):
|
190
207
|
for name, array in sample.items():
|
191
|
-
data
|
208
|
+
if name in data:
|
209
|
+
data[name].append(array)
|
192
210
|
return {name: np.concatenate(array) for name, array in data.items()}
|
193
211
|
|
194
212
|
def estimate_available_jets(self, cuts: Cuts, num: int = 1_000_000) -> int:
|
@@ -1,10 +1,8 @@
|
|
1
|
-
from
|
1
|
+
from __future__ import annotations
|
2
2
|
|
3
|
-
import h5py
|
4
3
|
import numpy as np
|
5
|
-
from numpy.lib.recfunctions import unstructured_to_structured as u2s
|
6
4
|
|
7
|
-
__all__ = ["
|
5
|
+
__all__ = ["join_structured_arrays"]
|
8
6
|
|
9
7
|
|
10
8
|
def get_dtype(ds, variables: list[str] | None = None, precision: str | None = None) -> np.dtype:
|
@@ -74,58 +72,6 @@ def cast_dtype(typestr: str, precision: str) -> np.dtype:
|
|
74
72
|
raise ValueError(f"Invalid precision {precision}")
|
75
73
|
|
76
74
|
|
77
|
-
def get_dummy_file():
|
78
|
-
jet_vars = [
|
79
|
-
"pt",
|
80
|
-
"eta",
|
81
|
-
"abs_eta",
|
82
|
-
"mass",
|
83
|
-
"HadronConeExclTruthLabelID",
|
84
|
-
"n_tracks",
|
85
|
-
"n_truth_promptLepton",
|
86
|
-
]
|
87
|
-
|
88
|
-
track_vars = ["pt", "deta", "dphi", "dr"]
|
89
|
-
|
90
|
-
# settings
|
91
|
-
n_jets = 1000
|
92
|
-
n_tracks_per_jet = 40
|
93
|
-
|
94
|
-
# setup jets
|
95
|
-
shapes_jets = {
|
96
|
-
"inputs": [n_jets, len(jet_vars)],
|
97
|
-
}
|
98
|
-
|
99
|
-
# setup tracks
|
100
|
-
shapes_tracks = {
|
101
|
-
"inputs": [n_jets, n_tracks_per_jet, len(track_vars)],
|
102
|
-
"valid": [n_jets, n_tracks_per_jet],
|
103
|
-
}
|
104
|
-
|
105
|
-
# setup jets
|
106
|
-
rng = np.random.default_rng()
|
107
|
-
jets_dtype = np.dtype([(n, "f4") for n in jet_vars])
|
108
|
-
jets = u2s(rng.random(shapes_jets["inputs"]), jets_dtype)
|
109
|
-
jets["HadronConeExclTruthLabelID"] = np.random.choice([0, 4, 5], size=n_jets)
|
110
|
-
jets["pt"] *= 400e3
|
111
|
-
jets["eta"] = (jets["eta"] - 0.5) * 6.0
|
112
|
-
jets["abs_eta"] = np.abs(jets["eta"])
|
113
|
-
|
114
|
-
# setup tracks
|
115
|
-
tracks_dtype = np.dtype([(n, "f4") for n in track_vars])
|
116
|
-
tracks = u2s(rng.random(shapes_tracks["inputs"]), tracks_dtype)
|
117
|
-
valid = rng.random(shapes_tracks["valid"])
|
118
|
-
valid = valid.astype(bool).view(dtype=np.dtype([("valid", bool)]))
|
119
|
-
tracks = join_structured_arrays([tracks, valid])
|
120
|
-
|
121
|
-
fname = NamedTemporaryFile(suffix=".h5", dir=mkdtemp()).name
|
122
|
-
f = h5py.File(fname, "w")
|
123
|
-
f.create_dataset("jets", data=jets)
|
124
|
-
f.create_dataset("tracks", data=tracks)
|
125
|
-
f.create_dataset("flow", data=tracks)
|
126
|
-
return fname, f
|
127
|
-
|
128
|
-
|
129
75
|
def join_structured_arrays(arrays: list):
|
130
76
|
"""Join a list of structured numpy arrays.
|
131
77
|
|
@@ -1,5 +1,8 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
from dataclasses import dataclass
|
2
4
|
from pathlib import Path
|
5
|
+
from subprocess import check_output
|
3
6
|
|
4
7
|
import h5py
|
5
8
|
import numpy as np
|
@@ -27,6 +30,8 @@ class H5Writer:
|
|
27
30
|
self.dst.parent.mkdir(parents=True, exist_ok=True)
|
28
31
|
self.file = h5py.File(self.dst, "w")
|
29
32
|
self.add_attr("srcfile", str(self.src))
|
33
|
+
self.git_hash = check_output(["git", "rev-parse", "HEAD"]).decode("ascii").strip()
|
34
|
+
self.add_attr("git_hash", self.git_hash)
|
30
35
|
for name, var in self.variables.items():
|
31
36
|
self.create_ds(name, var)
|
32
37
|
|
@@ -0,0 +1,105 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from tempfile import NamedTemporaryFile, mkdtemp
|
4
|
+
|
5
|
+
import h5py
|
6
|
+
import numpy as np
|
7
|
+
from numpy.lib.recfunctions import unstructured_to_structured as u2s
|
8
|
+
|
9
|
+
from ftag.hdf5 import join_structured_arrays
|
10
|
+
|
11
|
+
__all__ = ["get_mock_file"]
|
12
|
+
|
13
|
+
JET_VARS = [
|
14
|
+
("pt", "f4"),
|
15
|
+
("eta", "f4"),
|
16
|
+
("abs_eta", "f4"),
|
17
|
+
("mass", "f4"),
|
18
|
+
("pt_btagJes", "f4"),
|
19
|
+
("eta_btagJes", "f4"),
|
20
|
+
("n_tracks", "i4"),
|
21
|
+
("HadronConeExclTruthLabelID", "i4"),
|
22
|
+
("HadronConeExclTruthLabelPt", "f4"),
|
23
|
+
("n_truth_promptLepton", "i4"),
|
24
|
+
("flavour_label", "i4"),
|
25
|
+
]
|
26
|
+
|
27
|
+
TRACK_VARS = [
|
28
|
+
("d0", "f4"),
|
29
|
+
("z0SinTheta", "f4"),
|
30
|
+
("dphi", "f4"),
|
31
|
+
("deta", "f4"),
|
32
|
+
("qOverP", "f4"),
|
33
|
+
("IP3D_signed_d0_significance", "f4"),
|
34
|
+
("IP3D_signed_z0_significance", "f4"),
|
35
|
+
("phiUncertainty", "f4"),
|
36
|
+
("thetaUncertainty", "f4"),
|
37
|
+
("qOverPUncertainty", "f4"),
|
38
|
+
("numberOfPixelHits", "i4"),
|
39
|
+
("numberOfSCTHits", "i4"),
|
40
|
+
("numberOfInnermostPixelLayerHits", "i4"),
|
41
|
+
("numberOfNextToInnermostPixelLayerHits", "i4"),
|
42
|
+
("numberOfInnermostPixelLayerSharedHits", "i4"),
|
43
|
+
("numberOfInnermostPixelLayerSplitHits", "i4"),
|
44
|
+
("numberOfPixelSharedHits", "i4"),
|
45
|
+
("numberOfPixelSplitHits", "i4"),
|
46
|
+
("numberOfSCTSharedHits", "i4"),
|
47
|
+
("numberOfPixelHoles", "i4"),
|
48
|
+
("numberOfSCTHoles", "i4"),
|
49
|
+
]
|
50
|
+
|
51
|
+
|
52
|
+
def softmax(x, axis=None):
|
53
|
+
"""Compute softmax values for each sets of scores in x."""
|
54
|
+
e_x = np.exp(x - np.max(x, axis=axis, keepdims=True))
|
55
|
+
return e_x / e_x.sum(axis=axis, keepdims=True)
|
56
|
+
|
57
|
+
|
58
|
+
def get_mock_scores(labels: np.ndarray):
|
59
|
+
rng = np.random.default_rng(42)
|
60
|
+
scores = np.zeros((len(labels), 3))
|
61
|
+
for label, count in zip(*np.unique(labels, return_counts=True)):
|
62
|
+
if label == 0:
|
63
|
+
scores[labels == label] = rng.normal(loc=[2, 0, 0], scale=1, size=(count, 3))
|
64
|
+
elif label == 4:
|
65
|
+
scores[labels == label] = rng.normal(loc=[0, 1, 0], scale=2.5, size=(count, 3))
|
66
|
+
elif label == 5:
|
67
|
+
scores[labels == label] = rng.normal(loc=[0, 0, 3.5], scale=5, size=(count, 3))
|
68
|
+
scores = softmax(scores, axis=1)
|
69
|
+
cols = [f"MockTagger_p{x}" for x in ["u", "c", "b"]]
|
70
|
+
scores = u2s(scores, dtype=np.dtype([(name, "f4") for name in cols]))
|
71
|
+
return scores
|
72
|
+
|
73
|
+
|
74
|
+
def get_mock_file(num_jets=1000, tracks_name: str = "tracks", num_tracks: int = 40):
|
75
|
+
# setup jets
|
76
|
+
rng = np.random.default_rng(42)
|
77
|
+
jets_dtype = np.dtype(JET_VARS)
|
78
|
+
jets = u2s(rng.random((num_jets, len(JET_VARS))), jets_dtype)
|
79
|
+
jets["HadronConeExclTruthLabelID"] = rng.choice([0, 4, 5], size=num_jets)
|
80
|
+
jets["flavour_label"] = rng.choice([0, 4, 5], size=num_jets)
|
81
|
+
jets["pt"] *= 400e3
|
82
|
+
jets["mass"] *= 50e3
|
83
|
+
jets["eta"] = (jets["eta"] - 0.5) * 6.0
|
84
|
+
jets["abs_eta"] = np.abs(jets["eta"])
|
85
|
+
jets["n_truth_promptLepton"] = 0
|
86
|
+
|
87
|
+
# add tagger scores
|
88
|
+
scores = get_mock_scores(jets["HadronConeExclTruthLabelID"])
|
89
|
+
jets = join_structured_arrays([jets, scores])
|
90
|
+
|
91
|
+
# create a tempfile in a new folder
|
92
|
+
fname = NamedTemporaryFile(suffix=".h5", dir=mkdtemp()).name
|
93
|
+
f = h5py.File(fname, "w")
|
94
|
+
f.create_dataset("jets", data=jets)
|
95
|
+
|
96
|
+
# setup tracks
|
97
|
+
if tracks_name:
|
98
|
+
tracks_dtype = np.dtype(TRACK_VARS)
|
99
|
+
tracks = u2s(rng.random((num_jets, num_tracks, len(TRACK_VARS))), tracks_dtype)
|
100
|
+
valid = rng.choice([True, False], size=(num_jets, num_tracks))
|
101
|
+
valid = valid.astype(bool).view(dtype=np.dtype([("valid", bool)]))
|
102
|
+
tracks = join_structured_arrays([tracks, valid])
|
103
|
+
f.create_dataset(tracks_name, data=tracks)
|
104
|
+
|
105
|
+
return fname, f
|
@@ -5,11 +5,11 @@ authors = [{name="Sam Van Stroud"}, {name="Philipp Gadow"}]
|
|
5
5
|
dynamic = ["version"]
|
6
6
|
license = {text = "MIT"}
|
7
7
|
readme = "README.md"
|
8
|
-
requires-python = ">=3.
|
8
|
+
requires-python = ">=3.8"
|
9
9
|
dependencies = [
|
10
|
-
"h5py
|
11
|
-
"numpy
|
12
|
-
"PyYAML
|
10
|
+
"h5py>=3.0", # requires numpy
|
11
|
+
"numpy",
|
12
|
+
"PyYAML>=5.1"
|
13
13
|
]
|
14
14
|
|
15
15
|
[project.urls]
|
@@ -42,6 +42,7 @@ line-length = 100
|
|
42
42
|
preview = "True"
|
43
43
|
|
44
44
|
[tool.ruff]
|
45
|
+
target-version = "py38"
|
45
46
|
select = ["I", "E", "W", "F", "B", "UP", "ARG", "SIM", "TID", "RUF", "D2", "D3", "D4"]
|
46
47
|
ignore = ["D211", "D213", "RUF005"]
|
47
48
|
line-length = 100
|
File without changes
|
{atlas-ftag-tools-0.0.4 → atlas-ftag-tools-0.0.6}/atlas_ftag_tools.egg-info/dependency_links.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|