File indexing completed on 2025-01-18 09:12:06
0001
0002
0003
0004 import sys
0005 import os
0006 import re
0007 import getopt
0008 import json
0009 import subprocess
0010 from collections import OrderedDict
0011
0012
0013 def usage():
0014 print(
0015 prog,
0016 """- convert TGeo response file options to ACTS v13.0.0 JSON format
0017
0018 USAGE:
0019 """
0020 + prog
0021 + """ [OPTIONS] tgeo.response
0022
0023 ACTS v13.0.0 (PR #884) changed the way the TGeo detector configuration is specified.
0024 A JSON file is now used, instead of the previous method using Boost options,
0025 which were often collected together in a response file (--response-file).
0026 This script converts an old response file to the new JSON file.
0027
0028 To include all the required settings, this script needs to know the defaults for
0029 any options not specified in the response file. These defaults can be obtained
0030 by running a TGeo example with the --geo-tgeo-dump-jsonconfig=def.json option.
0031 This script includes a hardcoded copy of these defaults (produced with ACTS v13.0.0).
0032 These are used by default, but the latest defaults can be regenerated and used by
0033 specifying the -d (or -c) option.
0034
0035 The JSON file is written to stdout.
0036
0037 OPTIONS:
0038 -h display this help and exit
0039 -v verbose running
0040 -d use ActsExampleGeometryTGeo --geo-tgeo-dump-jsonconfig to get list of default options
0041 -c CMD run CMD --geo-tgeo-dump-jsonconfig instead
0042 -f JSON read list of default options from JSON file
0043 -n don't add any defaults
0044
0045 If none of -dcfn options is specified, then use hardcoded default options.
0046
0047 AUTHOR: Tim Adye <tim.adye@cern.ch>""",
0048 )
0049
0050
0051 prog = os.path.basename(sys.argv[0])
0052
0053
0054 def main():
0055 args = getopts()
0056 for filename in args:
0057 try:
0058 with open(filename) as f:
0059 process(f)
0060 except IOError as e:
0061 print(prog + ":", e, file=sys.stderr)
0062
0063
0064 def getopts():
0065 global opt, verbose
0066 try:
0067 optlist, args = getopt.getopt(sys.argv[1:], "hvdc:f:n")
0068 except getopt.GetoptError as e:
0069 print(prog + ":", e, file=sys.stderr)
0070 exit(1)
0071 opt = dict(optlist)
0072 if "-h" in opt or len(sys.argv) <= 1:
0073 usage()
0074 sys.exit(0)
0075 verbose = "-v" in opt
0076 return args
0077
0078
0079 def process(f):
0080 vols = []
0081 cfg = OrderedDict()
0082 vol = None
0083 iline = 0
0084 for line in f:
0085 iline += 1
0086 if verbose:
0087 print(str(iline) + ":" + line, end="", file=sys.stderr)
0088 line = re.sub(r"#.*", "", line).strip()
0089 if not line:
0090 continue
0091
0092 if re.match(r"--geo-[\w-]+-loglevel\s\d+$", line):
0093 continue
0094
0095 m = re.match(r"--(geo-tgeo-[\w-]+)\s+(.*)$", line)
0096 if not m:
0097 print(
0098 "%s:%d: unrecognised type of option: %s" % (f.name, iline, line),
0099 file=sys.stderr,
0100 )
0101 continue
0102 o, v = m.groups()
0103
0104 if o == "geo-tgeo-filename" or o == "geo-tgeo-worldvolume":
0105
0106 continue
0107
0108 if o == "geo-tgeo-unit-scalor":
0109 cfg[o] = float(v)
0110 continue
0111
0112 if o == "geo-tgeo-beampipe-parameters":
0113 cfg["geo-tgeo-build-beampipe"] = True
0114 cfg[o] = [float(x) for x in v.split(":")]
0115 continue
0116
0117 if o == "geo-tgeo-volume":
0118 if vol is None:
0119 cfg["Volumes"] = vols
0120 vol = OrderedDict()
0121 vol["geo-tgeo-volume-name"] = v
0122 vols.append(vol)
0123 continue
0124
0125 if vol is None:
0126 print(
0127 "%s:%d: unrecognised global option: %s" % (f.name, iline, line),
0128 file=sys.stderr,
0129 )
0130 continue
0131
0132 if re.match("geo-tgeo-sfbin-(r|z|phi)-tolerance$", o):
0133 vv = [float(x) for x in v.split(":")]
0134 vol[o] = OrderedDict([("lower", vv[0]), ("upper", vv[1])])
0135 continue
0136
0137 m = re.match("geo-tgeo-([ncp])(.*)$", o)
0138 if not m:
0139 print(
0140 "%s:%d: unrecognised option: %s" % (f.name, iline, line),
0141 file=sys.stderr,
0142 )
0143 continue
0144
0145 side, oo = m.groups()
0146 side = {"n": "negative", "c": "central", "p": "positive"}[side]
0147 oo = "geo-tgeo-" + oo
0148 vv = v
0149
0150 if oo == "geo-tgeo-layers":
0151 oo = "geo-tgeo-volume-layers"
0152 vv = bool(int(vv))
0153
0154 elif oo == "geo-tgeo-volume-name":
0155 oo = "geo-tgeo-subvolume-names"
0156
0157 elif oo == "geo-tgeo-module-name":
0158 oo = "geo-tgeo-sensitive-names"
0159 vv = vv.split("|")
0160
0161 elif oo == "geo-tgeo-module-axes":
0162 oo = "geo-tgeo-sensitive-axes"
0163
0164 elif re.match("geo-tgeo-layer-[rz]-split$", oo):
0165 vv = float(vv)
0166
0167 elif re.match("geo-tgeo-layer-[rz]-range$", oo):
0168 oo += "s"
0169 vv = [float(x) for x in vv.split(":")]
0170 vv = OrderedDict([("lower", vv[0]), ("upper", vv[1])])
0171
0172 else:
0173 print(
0174 "%s:%d: unrecognised option: %s" % (f.name, iline, line),
0175 file=sys.stderr,
0176 )
0177 continue
0178
0179 if oo not in vol:
0180 vol[oo] = OrderedDict()
0181 vol[oo][side] = vv
0182
0183 if "-n" not in opt:
0184 if "-d" in opt:
0185 empty = generate_empty_config("ActsExampleGeometryTGeo")
0186 elif "-c" in opt:
0187 empty = generate_empty_config(opt["-c"])
0188 elif "-f" in opt:
0189 with open(opt["-f"]) as ef:
0190 ecfg = ef.read()
0191 empty = json.loads(ecfg, object_pairs_hook=OrderedDict)
0192 else:
0193 empty = None
0194
0195 if not empty:
0196 empty = empty_config()
0197
0198 for o, v in empty.items():
0199 if o not in cfg:
0200 cfg[o] = v
0201 if len(empty.get("Volumes", [])):
0202 for vol in vols:
0203 for o, v in empty["Volumes"][0].items():
0204 if o not in vol:
0205 vol[o] = v
0206
0207 print(json.dumps(cfg, indent=2))
0208
0209
0210 def generate_empty_config(cmd):
0211 cmd += " --geo-tgeo-dump-jsonconfig=/dev/stdout"
0212 if verbose:
0213 print("+", cmd, file=sys.stderr)
0214 cfg = subprocess.check_output(cmd, shell=True)
0215 if not cfg:
0216 print(prog + ": command failed: " + cmd, file=sys.stderr)
0217 return None
0218 if verbose:
0219 print(cfg, file=sys.stderr)
0220 return json.loads(cfg, object_pairs_hook=OrderedDict)
0221
0222
0223 def empty_config():
0224 return json.loads(
0225 """
0226 {
0227 "geo-tgeo-unit-scalor": 1.0,
0228 "geo-tgeo-build-beampipe": false,
0229 "geo-tgeo-beampipe-parameters": [
0230 0.0,
0231 0.0,
0232 0.0
0233 ],
0234 "Volumes": [
0235 {
0236 "geo-tgeo-volume-name": "",
0237 "geo-tgeo-sfbin-r-tolerance": {
0238 "lower": 0.0,
0239 "upper": 0.0
0240 },
0241 "geo-tgeo-sfbin-z-tolerance": {
0242 "lower": 0.0,
0243 "upper": 0.0
0244 },
0245 "geo-tgeo-sfbin-phi-tolerance": {
0246 "lower": 0.0,
0247 "upper": 0.0
0248 },
0249 "geo-tgeo-volume-layers": {
0250 "negative": false,
0251 "central": false,
0252 "positive": false
0253 },
0254 "geo-tgeo-subvolume-names": {
0255 "negative": "",
0256 "central": "",
0257 "positive": ""
0258 },
0259 "geo-tgeo-sensitive-names": {
0260 "negative": [],
0261 "central": [],
0262 "positive": []
0263 },
0264 "geo-tgeo-sensitive-axes": {
0265 "negative": "",
0266 "central": "",
0267 "positive": ""
0268 },
0269 "geo-tgeo-layer-r-ranges": {
0270 "negative": {
0271 "lower": 0.0,
0272 "upper": 0.0
0273 },
0274 "central": {
0275 "lower": 0.0,
0276 "upper": 0.0
0277 },
0278 "positive": {
0279 "lower": 0.0,
0280 "upper": 0.0
0281 }
0282 },
0283 "geo-tgeo-layer-z-ranges": {
0284 "negative": {
0285 "lower": 0.0,
0286 "upper": 0.0
0287 },
0288 "central": {
0289 "lower": 0.0,
0290 "upper": 0.0
0291 },
0292 "positive": {
0293 "lower": 0.0,
0294 "upper": 0.0
0295 }
0296 },
0297 "geo-tgeo-layer-r-split": {
0298 "negative": 0.0,
0299 "central": 0.0,
0300 "positive": 0.0
0301 },
0302 "geo-tgeo-layer-z-split": {
0303 "negative": 0.0,
0304 "central": 0.0,
0305 "positive": 0.0
0306 },
0307 "geo-tgeo-cyl-disc-split": false,
0308 "Splitters": {
0309 "CylinderDisk": {
0310 "geo-tgeo-cyl-nphi-segs": 0,
0311 "geo-tgeo-cyl-nz-segs": 0,
0312 "geo-tgeo-disc-nphi-segs": 0,
0313 "geo-tgeo-disc-nr-segs": 0
0314 }
0315 }
0316 }
0317 ]
0318 }
0319 """,
0320 object_pairs_hook=OrderedDict,
0321 )
0322
0323
0324 if __name__ == "__main__":
0325 sys.exit(main())