atlas-ftag-tools 0.1.14__py3-none-any.whl → 0.1.16__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.
- {atlas_ftag_tools-0.1.14.dist-info → atlas_ftag_tools-0.1.16.dist-info}/METADATA +14 -1
- {atlas_ftag_tools-0.1.14.dist-info → atlas_ftag_tools-0.1.16.dist-info}/RECORD +10 -10
- ftag/__init__.py +1 -1
- ftag/hdf5/h5reader.py +5 -0
- ftag/vds.py +15 -1
- ftag/wps/discriminant.py +2 -0
- ftag/wps/working_points.py +75 -5
- {atlas_ftag_tools-0.1.14.dist-info → atlas_ftag_tools-0.1.16.dist-info}/WHEEL +0 -0
- {atlas_ftag_tools-0.1.14.dist-info → atlas_ftag_tools-0.1.16.dist-info}/entry_points.txt +0 -0
- {atlas_ftag_tools-0.1.14.dist-info → atlas_ftag_tools-0.1.16.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: atlas-ftag-tools
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.16
|
4
4
|
Summary: ATLAS Flavour Tagging Tools
|
5
5
|
Author: Sam Van Stroud, Philipp Gadow
|
6
6
|
License: MIT
|
@@ -102,6 +102,19 @@ By default the working points are printed to the terminal, but you can save the
|
|
102
102
|
|
103
103
|
See `wps --help` for more options and information.
|
104
104
|
|
105
|
+
## Calculate efficiency at discriminant cut
|
106
|
+
|
107
|
+
The same script can be used to calculate the efficiency and rejection values at a given discriminant cut value.
|
108
|
+
The script `working_points.py` can be run after intalling this package as follows
|
109
|
+
|
110
|
+
```
|
111
|
+
wps \
|
112
|
+
--ttbar "path/to/ttbar/*.h5" \
|
113
|
+
--tagger GN120220509 \
|
114
|
+
--fx 0.1
|
115
|
+
--disc_cuts 1.0 1.5
|
116
|
+
```
|
117
|
+
The `--tagger`, `--fx`, and `--outfile` follow the same procedure as in the 'Calculate WPs' script as described above.
|
105
118
|
|
106
119
|
## H5 Utils
|
107
120
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
ftag/__init__.py,sha256=
|
1
|
+
ftag/__init__.py,sha256=PN9ZbZHVfxreetH3HnhEbZf1G-J4Up-5si-dQ4rrezg,629
|
2
2
|
ftag/cuts.py,sha256=RYAfK3MkEhYhlKQFWQTKu72ZrUwlExFeT8IWLSIgeTU,2798
|
3
3
|
ftag/flavour.py,sha256=BLifDbJCoszPzgrU5X3Txff9fTMuVGEjUeU0OtOfllc,2701
|
4
4
|
ftag/flavours.yaml,sha256=9ifKyz1_VoHlOaWuf3JEqMLSYyLFedYJf9x1D6dCTnM,5335
|
@@ -7,17 +7,17 @@ ftag/mock.py,sha256=T2YGeuCkgDEzKPVYwU7Vnq5TNIDrx9eIDVrAQt8s0Mw,4865
|
|
7
7
|
ftag/region.py,sha256=-WxdC0Gy9zz3zEJ2pN779RcxXPG-QEROuMwMoP-Qs0g,353
|
8
8
|
ftag/sample.py,sha256=cd-rNHsEY2aWSZdy3V4bOKi3aDMtHTCpjXS8Hl9zwUY,2597
|
9
9
|
ftag/transform.py,sha256=uEGGJSnqoKOzLYQv650XdK_kDNw4Aw-5dc60z9Dp_y0,3963
|
10
|
-
ftag/vds.py,sha256=
|
10
|
+
ftag/vds.py,sha256=PG-NCJdpmK5X2l8i8YWBHx6CY8vosShfqp36facKaYM,3383
|
11
11
|
ftag/hdf5/__init__.py,sha256=pZva2TI8nvpBwoawcm_ucVZbGsQJW_u8GGoJgt5mKEw,354
|
12
12
|
ftag/hdf5/h5move.py,sha256=1XxiJZ96DYSp8JF0ry3lbRSQaFX72DjUV5vBA6hYw-0,873
|
13
|
-
ftag/hdf5/h5reader.py,sha256=
|
13
|
+
ftag/hdf5/h5reader.py,sha256=et-_LXt942xegqc14bPapUgIO7MUfC2m04uJslLkXxI,13579
|
14
14
|
ftag/hdf5/h5split.py,sha256=BlhpsUlqBSDCjVRWuyEq1OImyzwp7VyVkDrCz7pvQKc,2508
|
15
15
|
ftag/hdf5/h5utils.py,sha256=wjbAmFY5GoFkWW_AvEKTPbwYMFroHKKFuIcehd91dhM,3222
|
16
16
|
ftag/hdf5/h5writer.py,sha256=5jm3vSk4m77lFSUyWm-i_y_USzQRVoKpLL8F_cii65Q,4826
|
17
|
-
ftag/wps/discriminant.py,sha256=
|
18
|
-
ftag/wps/working_points.py,sha256=
|
19
|
-
atlas_ftag_tools-0.1.
|
20
|
-
atlas_ftag_tools-0.1.
|
21
|
-
atlas_ftag_tools-0.1.
|
22
|
-
atlas_ftag_tools-0.1.
|
23
|
-
atlas_ftag_tools-0.1.
|
17
|
+
ftag/wps/discriminant.py,sha256=0YmI3-ieSWReO_uY4-3Sc_85hLVpoCHQ7LfuU1SC_Sg,2318
|
18
|
+
ftag/wps/working_points.py,sha256=pLoe8RaVmbtiGM9TxMtWocMohBWrY6JcMCLE_e3XtVY,8033
|
19
|
+
atlas_ftag_tools-0.1.16.dist-info/METADATA,sha256=H547FpfWZ6plg5PXm7E9SJhppKGWM8iKM_EpFJaUNJs,5064
|
20
|
+
atlas_ftag_tools-0.1.16.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
21
|
+
atlas_ftag_tools-0.1.16.dist-info/entry_points.txt,sha256=LfVLsZHQolqbPnwPgtmc5IQTh527BKkN2v-IpXWTNHw,137
|
22
|
+
atlas_ftag_tools-0.1.16.dist-info/top_level.txt,sha256=qiYQuKcAvMim-31FwkT3MTQu7WQm0s58tPAia5KKWqs,5
|
23
|
+
atlas_ftag_tools-0.1.16.dist-info/RECORD,,
|
ftag/__init__.py
CHANGED
ftag/hdf5/h5reader.py
CHANGED
@@ -354,6 +354,11 @@ class H5Reader:
|
|
354
354
|
int
|
355
355
|
Estimated number of jets available after selection cuts, rounded down.
|
356
356
|
"""
|
357
|
+
# reset rngs to ensure same jets are used for each sample
|
358
|
+
self.rng = np.random.default_rng(42)
|
359
|
+
for r in self.readers:
|
360
|
+
r.rng = np.random.default_rng(42)
|
361
|
+
|
357
362
|
# if equal jets is True, available jets is based on the smallest sample
|
358
363
|
if self.equal_jets:
|
359
364
|
num_jets = []
|
ftag/vds.py
CHANGED
@@ -62,10 +62,24 @@ def create_virtual_file(
|
|
62
62
|
if not overwrite and out_fname.is_file():
|
63
63
|
return out_fname
|
64
64
|
|
65
|
+
# identify common groups across all files
|
66
|
+
common_groups: set[str] = set()
|
67
|
+
for fname in fnames:
|
68
|
+
with h5py.File(fname) as f:
|
69
|
+
groups = set(f.keys())
|
70
|
+
common_groups = groups if not common_groups else common_groups.intersection(groups)
|
71
|
+
|
72
|
+
if not common_groups:
|
73
|
+
raise ValueError("No common groups found across files")
|
74
|
+
|
75
|
+
print("Common groups found:")
|
76
|
+
for group in common_groups:
|
77
|
+
print(f" {group}")
|
78
|
+
|
65
79
|
# create virtual file
|
66
80
|
out_fname.parent.mkdir(exist_ok=True)
|
67
81
|
with h5py.File(out_fname, "w") as f:
|
68
|
-
for group in
|
82
|
+
for group in common_groups:
|
69
83
|
layout = get_virtual_layout(fnames, group)
|
70
84
|
f.create_virtual_dataset(group, layout)
|
71
85
|
attrs_dict: dict = {}
|
ftag/wps/discriminant.py
CHANGED
ftag/wps/working_points.py
CHANGED
@@ -36,7 +36,6 @@ def parse_args(args):
|
|
36
36
|
nargs="+",
|
37
37
|
type=float,
|
38
38
|
help="efficiency working point(s). If -r is specified, values should be 1/efficiency",
|
39
|
-
default=[60, 70, 77, 85],
|
40
39
|
)
|
41
40
|
parser.add_argument(
|
42
41
|
"-t",
|
@@ -69,6 +68,13 @@ def parse_args(args):
|
|
69
68
|
choices=["ujets", "cjets", "bjets", "hbb", "hcc", "top", "qcd"],
|
70
69
|
help="use rejection of specified background class to determine working points",
|
71
70
|
)
|
71
|
+
parser.add_argument(
|
72
|
+
"-d",
|
73
|
+
"--disc_cuts",
|
74
|
+
nargs="+",
|
75
|
+
type=float,
|
76
|
+
help="D_x value(s) to calculate efficiency at",
|
77
|
+
)
|
72
78
|
parser.add_argument(
|
73
79
|
"-n",
|
74
80
|
"--num_jets",
|
@@ -116,8 +122,6 @@ def get_eff_rej(jets, disc, wp, flavs):
|
|
116
122
|
|
117
123
|
|
118
124
|
def get_working_points(args=None):
|
119
|
-
args = parse_args(args)
|
120
|
-
|
121
125
|
if args.xbb:
|
122
126
|
if len(args.fx) != 2 * len(args.tagger):
|
123
127
|
raise ValueError("For Xbb tagging, each tagger must have two fx values")
|
@@ -180,10 +184,76 @@ def get_working_points(args=None):
|
|
180
184
|
return out
|
181
185
|
|
182
186
|
|
183
|
-
def
|
184
|
-
|
187
|
+
def get_rej_eff_at_disc(jets, tagger, signal, fx, disc_cuts):
|
188
|
+
disc = get_discriminant(jets, tagger, signal, fx)
|
189
|
+
d = {}
|
190
|
+
flavs = Flavours.by_category("single-btag")
|
191
|
+
for dcut in disc_cuts:
|
192
|
+
d[str(dcut)] = {"eff": {}, "rej": {}}
|
193
|
+
for f in flavs:
|
194
|
+
e_discs = disc[f.cuts(jets).idx]
|
195
|
+
eff = sum(e_discs > dcut) / len(e_discs)
|
196
|
+
d[str(dcut)]["eff"][str(f)] = float(f"{eff:.3g}")
|
197
|
+
d[str(dcut)]["rej"][str(f)] = 1 / float(f"{eff:.3g}")
|
198
|
+
return d
|
199
|
+
|
200
|
+
|
201
|
+
def get_efficiencies(args=None):
|
202
|
+
if len(args.tagger) != len(args.fx):
|
203
|
+
raise ValueError("Must provide fb/fc for each tagger")
|
204
|
+
|
205
|
+
fx_values = [(fx,) for fx in args.fx]
|
206
|
+
# setup cuts and variables
|
207
|
+
flavs = Flavours.by_category("single-btag")
|
208
|
+
default_cuts = Cuts.from_list(["eta > -2.5", "eta < 2.5"])
|
209
|
+
ttbar_cuts = Cuts.from_list(args.ttbar_cuts) + default_cuts
|
210
|
+
zprime_cuts = Cuts.from_list(args.zprime_cuts) + default_cuts
|
211
|
+
all_vars = next(iter(flavs)).cuts.variables
|
212
|
+
for tagger in args.tagger:
|
213
|
+
all_vars += [f"{tagger}_{f.px}" for f in flavs if "tau" not in f.px]
|
214
|
+
|
215
|
+
# load jets
|
216
|
+
reader = H5Reader(args.ttbar)
|
217
|
+
jets = reader.load({"jets": all_vars}, args.num_jets, cuts=ttbar_cuts)["jets"]
|
218
|
+
if args.zprime:
|
219
|
+
zp_reader = H5Reader(args.zprime)
|
220
|
+
zp_jets = zp_reader.load({"jets": all_vars}, args.num_jets, cuts=zprime_cuts)["jets"]
|
221
|
+
|
222
|
+
# loop over taggers
|
223
|
+
out = {}
|
224
|
+
for tagger, fx in zip(args.tagger, fx_values):
|
225
|
+
out[tagger] = {"signal": args.signal, "fx": fx}
|
226
|
+
|
227
|
+
out[tagger]["ttbar"] = get_rej_eff_at_disc(jets, tagger, args.signal, fx, args.disc_cuts)
|
228
|
+
if args.zprime:
|
229
|
+
out[tagger]["zprime"] = get_rej_eff_at_disc(
|
230
|
+
zp_jets, tagger, args.signal, fx, args.disc_cuts
|
231
|
+
)
|
232
|
+
|
233
|
+
if args.outfile:
|
234
|
+
with open(args.outfile, "w") as f:
|
235
|
+
yaml.dump(out, f, sort_keys=False)
|
236
|
+
return None
|
237
|
+
else:
|
238
|
+
return out
|
239
|
+
|
240
|
+
|
241
|
+
def main(args=None):
|
242
|
+
args = parse_args(args)
|
243
|
+
|
244
|
+
if args.effs and args.disc_cuts:
|
245
|
+
raise ValueError("Cannot specify both --effs and --disc_cuts")
|
246
|
+
|
247
|
+
if args.effs:
|
248
|
+
out = get_working_points(args)
|
249
|
+
elif args.disc_cuts:
|
250
|
+
out = get_efficiencies(args)
|
251
|
+
else:
|
252
|
+
raise ValueError("Must specify either --effs or --disc_cuts")
|
185
253
|
if out:
|
186
254
|
print(yaml.dump(out, sort_keys=False))
|
255
|
+
return out
|
256
|
+
return None
|
187
257
|
|
188
258
|
|
189
259
|
if __name__ == "__main__":
|
File without changes
|
File without changes
|
File without changes
|