-
Notifications
You must be signed in to change notification settings - Fork 0
/
make_signalpatch.py
121 lines (108 loc) · 3.42 KB
/
make_signalpatch.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env python
#
# see https://github.com/scikit-hep/pyhf/issues/886
#
import pyhf
import click
import json
import parse
import sys
import pathlib
import jsonpatch
@parse.with_pattern(r"\d+[p\.]?\d+")
def parse_number(text):
return float(text.replace("p", "."))
@click.command()
@click.argument("signals", nargs=-1, type=click.File("r"))
@click.option(
"-b",
"--bkg-only",
help="Background-only JSON file",
required=True,
type=click.File("r"),
)
@click.option(
"-p",
"--pattern",
help="Pattern of signal filenames to extract information from",
default="{x:number}_{y:number}",
)
@click.option("--hepdata", help="hepdata record id, e.g. ins1234567", required=True)
@click.option(
"-a",
"--algorithm",
"algorithms",
default=["sha256"],
help="Digest algorithms to use",
multiple=True,
)
@click.option(
"-d",
"--description",
default="signal patchset",
help="Description of patchset file",
)
@click.option(
"--output-file",
help="The location of the output json file. If not specified, prints to screen.",
default=None,
)
def main(signals, bkg_only, pattern, algorithms, description, hepdata, output_file):
patchset = {
"metadata": {
"description": description,
},
"patches": [],
}
# add in analysis id if specified
patchset["metadata"]["references"] = {"hepdata": hepdata}
# add in the digest for background-only
bkg_only_workspace = json.load(bkg_only)
patchset["metadata"]["digests"] = {
algorithm: pyhf.utils.digest(bkg_only_workspace, algorithm=algorithm)
for algorithm in algorithms
}
click.echo("Background-only digests:")
click.echo(
"\t"
+ json.dumps(patchset["metadata"]["digests"], indent=4, sort_keys=True).replace(
"\n", "\n\t"
)
)
p = parse.compile(pattern, dict(number=parse_number))
labels = p._named_fields
if len(labels) == 0:
click.echo("You didn't specify any named labels...")
sys.exit(1)
click.echo(f"You specified {len(labels)} labels: {labels}.")
patchset["metadata"]["labels"] = labels
patchset["metadata"]["references"] = {"hepdata": "ins1234567"}
patchset["version"] = "1.0.0"
click.echo(f"Making patches for {len(signals)} signals.")
for signal in signals:
signal_name = pathlib.Path(signal.name).stem
r = p.search(signal_name)
if r is None:
click.echo(f"Filename parse failure for: {signal.name}")
sys.exit(1)
values = [r.named[label] for label in labels]
patch = jsonpatch.make_patch(bkg_only_workspace, json.load(signal))
if not patch.patch:
click.echo(f"Patch failure for: {signal.name}")
sys.exit(1)
patchset["patches"].append(
{"metadata": {"name": signal_name, "values": values}, "patch": patch.patch}
)
click.echo("Done. Validating patchset structure against schema.")
pyhf.utils.validate(patchset, "patchset.json")
click.echo(
f"Validated. {'Writing to file' if output_file else 'Printing to screen'}."
)
if output_file is None:
click.echo(json.dumps(patchset, indent=4, sort_keys=True))
else:
with open(output_file, "w+") as out_file:
json.dump(patchset, out_file, indent=4, sort_keys=True)
click.echo("Written to {0:s}".format(output_file))
if __name__ == "__main__":
main()