Skip to content

Commit

Permalink
feat: Smearing digitization json config creator script (#1040)
Browse files Browse the repository at this point in the history
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
gagnonlg committed Nov 3, 2021
1 parent d575795 commit 20ca618
Show file tree
Hide file tree
Showing 5 changed files with 298 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,11 @@ jobs:
- name: Check
run: >
CI/check_boost_test_macro.sh
smearing_config:
runs-on: ubuntu-latest
container: python:alpine3.6
steps:
- uses: actions/checkout@v2
- name: Check
run: >
CI/check_smearing_config.py .
67 changes: 67 additions & 0 deletions CI/check_smearing_config.py
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 Examples/Algorithms/Digitization/scripts/smearing-config.py
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()
1 change: 1 addition & 0 deletions docs/examples/howto/howto.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ How-to guides
run_ckf_tracking
setup_and_run_vertexing
run_alignment
smearing_digitization_config.md
44 changes: 44 additions & 0 deletions docs/howto/smearing_digitization_config.md
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
```


0 comments on commit 20ca618

Please sign in to comment.