-
Notifications
You must be signed in to change notification settings - Fork 157
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Smearing digitization json config creator script (#1040)
Draft version of a python script that uses the old smearing cli configuration switches to bootstrap a .json config file usable with the current digitization algorithm.
- Loading branch information
Showing
5 changed files
with
298 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# This file is part of the Acts project. | ||
# | ||
# Copyright (C) 2021 CERN for the benefit of the Acts project | ||
# | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this | ||
# file, You can obtain one at http:#mozilla.org/MPL/2.0/. | ||
|
||
# Configuration taken from: https://arxiv.org/pdf/1904.06778.pdf | ||
# See also https://github.com/acts-project/acts/issues/946 | ||
|
||
import argparse | ||
import math | ||
import subprocess | ||
|
||
args = argparse.ArgumentParser() | ||
args.add_argument("sourcedir") | ||
args = args.parse_args() | ||
|
||
volumes = [7, 8, 9, 12, 13, 14, 16, 17, 18] | ||
|
||
|
||
base_cli = [ | ||
"python", | ||
args.sourcedir + "/Examples/Algorithms/Digitization/scripts/smearing-config.py", | ||
] | ||
|
||
for vid in volumes: | ||
# 50μm×50μmand further out two different strip detectors withshort80μm×1200μmand long strips0.12 mm×10.8 mmare placed. | ||
if vid in [7, 8, 9]: # Pixel | ||
resx, resy = 0.05, 0.05 | ||
elif vid in [12, 13, 14]: # Short strip | ||
resx, resy = 0.08, 1.2 | ||
elif vid in [16, 17, 18]: # Long strip | ||
resx, resy = 0.12, 10.8 | ||
else: | ||
raise RuntimeError("Invalid volume id") | ||
|
||
resx /= math.sqrt(12) | ||
resy /= math.sqrt(12) | ||
|
||
base_cli += [ | ||
"--digi-smear-volume={}".format(vid), | ||
"--digi-smear-indices=0:1", | ||
"--digi-smear-types=0:0", | ||
"--digi-smear-parameters={}:{}".format(resx, resy), | ||
] | ||
|
||
output = subprocess.check_output(base_cli).decode("utf-8") | ||
|
||
ref_path = ( | ||
args.sourcedir | ||
+ "/Examples/Algorithms/Digitization/share/default-smearing-config-generic.json" | ||
) | ||
|
||
with open(ref_path, "r") as ifile: | ||
ref = ifile.read() | ||
|
||
for i, (line_ref, line_gen) in enumerate(zip(ref.split("\n"), output.split("\n"))): | ||
|
||
lhs = line_ref.strip() | ||
rhs = line_gen.strip() | ||
|
||
if lhs != rhs: | ||
raise RuntimeError(f"Mismatched line #{i}: Ref=<{lhs}>, Gen=<{rhs}>") |
178 changes: 178 additions & 0 deletions
178
Examples/Algorithms/Digitization/scripts/smearing-config.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
# This file is part of the Acts project. | ||
# | ||
# Copyright (C) 2021 CERN for the benefit of the Acts project | ||
# | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this | ||
# file, You can obtain one at http:#mozilla.org/MPL/2.0/. | ||
|
||
|
||
# each volume configuration is one logical block | ||
# | ||
# --digi-smear-volume=8 | ||
# --digi-smear-indices=0:1:5 # loc0, loc1, and time | ||
# --digi-smear-types=0:0:3 # loc{0,1} uses gaussian, time uses uniform | ||
# # parameter 0: loc0 gaussian width | ||
# # parameter 1: loc1 gaussian width | ||
# # parameter 2-4: time pitch,min,max | ||
# --digi-smear-parameters=10:20:2.5:-25:25 | ||
# | ||
# which can be repeated as often as needed | ||
# | ||
# --digi-smear-volume=11 | ||
# --digi-smear-indices=1 # loc1 | ||
# --digi-smear-types=0 # loc1 uses gaussian | ||
# --digi-smear-parameters=12.5 # loc1 gaussian width | ||
# | ||
|
||
|
||
import argparse | ||
import json | ||
import sys | ||
|
||
|
||
def add_switch(i, argv, current): | ||
|
||
fields = argv[i].split("=") | ||
|
||
if len(fields) == 1: | ||
# --foo bar | ||
current.append(argv[i]) | ||
current.append(argv[i + 1]) | ||
i += 2 | ||
|
||
elif len(fields) == 2: | ||
# --foo=bar | ||
current.append(argv[i]) | ||
i += 1 | ||
|
||
else: | ||
raise RuntimeError(f"Invalid argument: {argv[i]}") | ||
|
||
return i | ||
|
||
|
||
def get_args_blocks(): | ||
argv = sys.argv[1:] | ||
blocks = [] | ||
current = [] | ||
|
||
i = 0 | ||
while i < len(argv): | ||
if argv[i].startswith("--digi-smear-volume"): | ||
if current: | ||
blocks.append(current) | ||
current = [] | ||
i = add_switch(i, argv, current) | ||
if current: | ||
blocks.append(current) | ||
current = [] | ||
|
||
return blocks | ||
|
||
|
||
def arg_parser(): | ||
argp = argparse.ArgumentParser() | ||
argp.add_argument( | ||
"--digi-smear-volume", help="Sensitive volume identifiers", required=True | ||
) | ||
argp.add_argument( | ||
"--digi-smear-indices", | ||
help="Smear parameter indices for this volume", | ||
required=True, | ||
) | ||
argp.add_argument( | ||
"--digi-smear-types", | ||
help="Smear function types as 0 (gauss), 1 (truncated gauss), 2 (clipped gauss), 3 (uniform), 4 (digital)", | ||
required=True, | ||
) | ||
argp.add_argument( | ||
"--digi-smear-parameters", | ||
help="Smear parameters depending on the smearing type, 1 parameter for simple gauss, 3 for all others (1 parameter, 2 range values)", | ||
required=True, | ||
) | ||
return argp | ||
|
||
|
||
def get_args(): | ||
return [arg_parser().parse_args(block) for block in get_args_blocks()] | ||
|
||
|
||
def get_n_params(type_id): | ||
if type_id == 0: | ||
return 1 | ||
return 3 | ||
|
||
|
||
def get_param_blocks(types_ids, params): | ||
blocks = [] | ||
icur = 0 | ||
for x in types_ids: | ||
n = get_n_params(x) | ||
blocks.append(params[icur : icur + n]) | ||
icur += n | ||
return blocks | ||
|
||
|
||
def block_to_json(args): | ||
top_data = {"volume": int(args.digi_smear_volume), "value": {"smearing": []}} | ||
|
||
indices = [int(x) for x in args.digi_smear_indices.split(":")] | ||
types = [int(x) for x in args.digi_smear_types.split(":")] | ||
params = [float(x) for x in args.digi_smear_parameters.split(":")] | ||
param_blocks = get_param_blocks(types, params) | ||
|
||
for i, t, ps in zip(indices, types, param_blocks): | ||
data = {"index": i} | ||
if t == 0: | ||
data["mean"] = 0.0 | ||
data["stddev"] = ps[0] | ||
data["type"] = "Gauss" | ||
elif t == 1: | ||
data["mean"] = 0.0 | ||
data["stddev"] = ps[0] | ||
data["range"] = ps[1:] | ||
data["type"] = "GaussTrunc" | ||
elif t == 2: | ||
data["mean"] = 0.0 | ||
data["stddev"] = ps[0] | ||
data["range"] = ps[1:] | ||
data["type"] = "GaussClipped" | ||
elif t in [3, 4]: | ||
data["type"] = "Uniform" if t == 3 else "Digitial" | ||
|
||
pitch = ps[0] | ||
low = ps[1] | ||
high = ps[2] | ||
|
||
data["bindata"] = [ | ||
0, # Acts::Open, | ||
0, # Acts::binX, | ||
(high - low) / pitch, | ||
low, | ||
high, | ||
] | ||
else: | ||
raise RuntimeError(f"Unrecognized type: {t}") | ||
|
||
top_data["value"]["smearing"].append(data) | ||
|
||
return top_data | ||
|
||
|
||
def get_json_data(): | ||
return { | ||
"acts-geometry-hierarchy-map": { | ||
"format-version": 0, | ||
"value-identifier": "digitization-configuration", | ||
}, | ||
"entries": [block_to_json(x) for x in get_args()], | ||
} | ||
|
||
|
||
def main(): | ||
print(json.dumps(get_json_data(), indent=4)) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,3 +12,4 @@ How-to guides | |
run_ckf_tracking | ||
setup_and_run_vertexing | ||
run_alignment | ||
smearing_digitization_config.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Generate a configuration file for the smearing digitizer | ||
|
||
As a convenience, a simple helper script is provided to help producing JSON configuration files for smearing digitization. | ||
The script is located in the source tree at `Examples/Algorithms/Digitization/scripts/smearing-config.py`. | ||
|
||
Each volume configuration is one logical block consiting of the following options: | ||
|
||
* `--digi-smear-volume=X`: Specifies the numeric identifier of the | ||
volume configured in the present block. This option also acts as a | ||
delimiter for different blocks. | ||
* `--digi-smear-indices=X[:Y...]`: Specifies the dimensions to be configured in a comma-delimited list | ||
* `--digi-smear-types=X[:Y...]`: Specifies the smearer type for each dimension. The following values are allowed: | ||
* 0: Gaussian | ||
* 1: Truncated gaussian | ||
* 2: Clipped gaussian | ||
* 3: Uniform | ||
* 4: Digital | ||
* `--digi-smear-parameters=X[:Y...]`: Configuration parameters, 1 for Gaussian, 3 for all others (1 parameter, 2 range values) | ||
|
||
Such blocks may be repeated as often as needed to configure many volumes, but each block has to begin with `--digi-smear-volume` and must contain all of the above arguments. | ||
|
||
## Example | ||
|
||
The following snippet will print a JSON string containing the | ||
configuration for two different volumes. The first volume applies | ||
gaussian smearing to the first two spatial dimensions and uniform | ||
smearing to the time dimension. Correspondingly, the parameter list | ||
for this volume has five entries: two for the simple gaussians and | ||
three for the uniform smearer. After this, another volume gets only | ||
one spatial dimension smeared by a simple gaussian. | ||
|
||
```bash | ||
Examples/Algorithms/Digitization/scripts/smearing-config.py \ | ||
--digi-smear-volume=8 \ | ||
--digi-smear-indices=0:1:5 \ | ||
--digi-smear-types=0:0:3 \ | ||
--digi-smear-parameters=10:20:2.5:-25:25 \ | ||
--digi-smear-volume=11 \ | ||
--digi-smear-indices=1 \ | ||
--digi-smear-types=0 \ | ||
--digi-smear-parameters=12.5 | ||
``` | ||
|
||
|