Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: material map generation and validation scripts and pipeline job #677

Merged
merged 10 commits into from
Apr 5, 2024
31 changes: 31 additions & 0 deletions .github/workflows/linux-eic-shell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,37 @@ jobs:
root -b -q "scripts/test_ACTS.cxx+(\"${DETECTOR_PATH}/${DETECTOR_CONFIG}.xml\")" | tee check_tracking_geometry.out
bin/acts_geo_check check_tracking_geometry.out
validate-material-map:
runs-on: ubuntu-latest
needs:
- build
- check-tracking-geometry
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: build-gcc-full-eic-shell
path: install/
- uses: cvmfs-contrib/github-action-cvmfs@v4
- uses: eic/run-cvmfs-osg-eic-shell@main
with:
platform-release: "jug_xl:nightly"
setup: install/setup.sh
run: |
pushd scripts/material_map
wdconinc marked this conversation as resolved.
Show resolved Hide resolved
export DETECTOR_CONFIG=epic_craterlake_material_map
./run_material_map_validation.sh
popd
- uses: actions/upload-artifact@v4
with:
name: material_map
path: |
"scripts/material_map/*.json"
"scripts/material_map/*.root"
scripts/material_map/Surfaces/
scripts/material_map/Validation/
if-no-files-found: error

convert-to-gdml:
runs-on: ubuntu-latest
needs:
Expand Down
5 changes: 5 additions & 0 deletions scripts/material_map/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Examples/
Surfaces/
Validation/
calibrations/
*.json
49 changes: 49 additions & 0 deletions scripts/material_map/epic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2024 Shujie Li

## Stand alone function to build ePIC geometry with ACTS python bindings
## for material mapping
## Shujie Li, 03, 2024

from pathlib import Path

import acts
import acts.examples.dd4hep

from acts import (
Vector4,
MaterialMapJsonConverter
)

import json

def getDetector(
xmlFile,
jsonFile="",
logLevel=acts.logging.WARNING,
):
customLogLevel = acts.examples.defaultLogging(logLevel=logLevel)
logger = acts.logging.getLogger("epic.getDetector")

matDeco = None
if len(jsonFile)>0:
file = Path(jsonFile)
logger.info("Adding material from %s", file.absolute())
matDeco = acts.IMaterialDecorator.fromFile(
file,
level=customLogLevel(maxLevel=acts.logging.INFO),
)

dd4hepConfig = acts.examples.dd4hep.DD4hepGeometryService.Config(
xmlFileNames=[xmlFile],
logLevel=logLevel,
dd4hepLogLevel=customLogLevel(),
)
detector = acts.examples.dd4hep.DD4hepDetector()

config = acts.MaterialMapJsonConverter.Config()

trackingGeometry, deco = detector.finalize(dd4hepConfig, matDeco)

return detector, trackingGeometry, deco
39 changes: 39 additions & 0 deletions scripts/material_map/geometry_epic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2024 Shujie Li

import os
import argparse

import acts

import epic
from geometry import runGeometry

if "__main__" == __name__:
p = argparse.ArgumentParser(
description="Script to generate geometry-map.json for ePIC geometry"
)
p.add_argument(
"-i",
"--xmlFile",
default=(
os.environ.get("DETECTOR_PATH", "")
"/" + os.environ.get("DETECTOR_CONFIG", "")
wdconinc marked this conversation as resolved.
Show resolved Hide resolved
+ ".xml"
),
help="Input xml file containing ePIC geometry",
)
args = p.parse_args()

detector, trackingGeometry, decorators = epic.getDetector(args.xmlFile)

runGeometry(
trackingGeometry,
decorators,
outputDir=os.getcwd(),
outputObj=False,
outputCsv=False,
outputJson=True,
outputRoot=True,
)
51 changes: 51 additions & 0 deletions scripts/material_map/material_mapping_epic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2024 Shujie Li

import os
import argparse

import acts
from acts.examples import JsonFormat

import epic
from material_mapping import runMaterialMapping

if "__main__" == __name__:

p = argparse.ArgumentParser(
description="Script to generate material map for ePIC geometry"
)
p.add_argument(
"--xmlFile",
default=os.environ.get("DETECTOR_PATH", "")+"epic_craterlake.xml",
help="input xml file containing ePIC geometry",
)
p.add_argument(
"--geoFile",
type=str,
default="geometry-map.json",
help="input json file to define volumes and layers used in material mapping",
)
p.add_argument(
"--matFile",
type=str,
default="material-map.json",
help="output filename for the generated material map, can be json and cbor formats",
wdconinc marked this conversation as resolved.
Show resolved Hide resolved
)
args = p.parse_args()

mapName = args.matFile.split('.')[0]

detector, trackingGeometry, decorators = epic.getDetector(
args.xmlFile, args.geoFile)

runMaterialMapping(
trackingGeometry,
decorators,
outputDir = os.getcwd(),
inputDir = os.getcwd(),
readCachedSurfaceInformation=False,
mapVolume= False,
mapName = mapName,
).run()
77 changes: 77 additions & 0 deletions scripts/material_map/material_recording_epic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2024 Shujie Li

import os
import warnings
from pathlib import Path
import argparse

import acts
from acts.examples import (
GaussianVertexGenerator,
ParametricParticleGenerator,
FixedMultiplicityGenerator,
EventGenerator,
RandomNumbers,
)

import acts.examples.dd4hep
import acts.examples.geant4
import acts.examples.geant4.dd4hep

import epic
from material_recording import runMaterialRecording

u = acts.UnitConstants

_material_recording_executed = False


def main():

p = argparse.ArgumentParser()
p.add_argument(
"-n", "--events", type=int, default=1000, help="Number of events to generate"
)
p.add_argument(
"-t", "--tracks", type=int, default=100, help="Particle tracks per event"
)
p.add_argument(
"-i", "--xmlFile", type=str, default=os.environ.get("DETECTOR_PATH", "") + os.environ.get("DETECTOR_CONFIG", "") + ".xml", help="DD4hep input file"
)
p.add_argument(
"-o", "--outputName", type=str, default="geant4_material_tracks.root", help="Name of the output rootfile"
)
p.add_argument(
"--eta_min",
type=float,
default=-8.0,
help="eta min (optional)",
)
p.add_argument(
"--eta_max",
type=float,
default=8.0,
help="eta max (optional)",
)
args = p.parse_args()

detector, trackingGeometry, decorators = epic.getDetector(
args.xmlFile)

detectorConstructionFactory = (
acts.examples.geant4.dd4hep.DDG4DetectorConstructionFactory(detector)
)

runMaterialRecording(
detectorConstructionFactory=detectorConstructionFactory,
tracksPerEvent=args.tracks,
outputDir=os.getcwd(),
etaRange=(args.eta_min, args.eta_max),
s=acts.examples.Sequencer(events=args.events, numThreads=1),
).run()


if "__main__" == __name__:
main()
54 changes: 54 additions & 0 deletions scripts/material_map/material_validation_epic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2024 Shujie Li

import os
import argparse

import acts
import acts.examples.dd4hep
from acts.examples import Sequencer

import epic
from material_validation import runMaterialValidation


if "__main__" == __name__:

p = argparse.ArgumentParser(
description="Script to produce propogation validation for ePIC material mapping."
)
p.add_argument(
"--xmlFile",
default=os.environ.get("DETECTOR_PATH", "") + os.environ.get("DETECTOR_CONFIG", "") + ".xml",
help="input xml file containing ePIC geometry",
)
p.add_argument(
"--matFile",
type=str,
default="material-map.json",
help="input material map file, can be either Json or Cbor",
)
p.add_argument(
"--outputName",
type=str,
default="propagation-material.root",
help="customized name of the output rootfile",
)
p.add_argument(
"-n","--nevents",
type=int,
default=100,
help="number of events to run",
)
args = p.parse_args()

detector, trackingGeometry, decorators = epic.getDetector(args.xmlFile, args.matFile)

field = acts.ConstantBField(acts.Vector3(0, 0, 0))

runMaterialValidation(
trackingGeometry, decorators, field,
outputDir=os.getcwd(), outputName=args.outputName,
s=Sequencer(events=args.nevents, numThreads=-1)
).run()
70 changes: 70 additions & 0 deletions scripts/material_map/materialmap_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2024 Shujie Li

## Generate ePIC material map for ACTS
## read config-map.json and turn on mapping for approach 1 and 2 of each sensitive surface.
import pandas as pd
import numpy as np
import json
import os
import argparse

if "__main__" == __name__:
p = argparse.ArgumentParser(
description="Script to turn on all approach 1 and 2, and also the beampipe surface in config json file for matieral mapping"
)
p.add_argument(
"-i","--inputFile",
type=str,
default="config-map.json",
help=" input json file to be modified",
)
p.add_argument(
"-o","--outputFile",
type=str,
default="config-map_new.json",
help=" output json file",
)

args = p.parse_args()
print(args)
fname = args.inputFile
out_name = args.outputFile


## load json file
f = open(fname)
dd = json.load(f)

ee=dd['Volumes']['entries']

## print volume name and ID
print ("Volume ID Name Approaches")
for vv in np.arange(len(ee)):
nn = ee[vv]['value']['NAME']

if "|" not in nn and "Gap" not in nn:
print(ee[vv]['volume'], nn,"1, 2")#print(ee[vv]['value'])#['NAME'])
if "acts_beampipe_central::Barrel" in nn:
v_beampipe = vv+1
print(v_beampipe, nn, "X")

## find apporach 1 and 2 to turn on mapping
for vv in np.arange(1,1+len(dd['Surfaces'])):
for ii,tt in enumerate(dd['Surfaces'][str(vv)]):
if 'approach' in tt:
dd['Surfaces'][str(vv)][ii]['value']['material']['mapMaterial']=True
## turn on beampipe surface and defind binning
elif vv==v_beampipe:
if tt['value']['bounds']['type']=='CylinderBounds':
# print (dd['Surfaces'][str(vv)][ii])
dd['Surfaces'][str(vv)][ii]['value']['material']['mapMaterial']=True
dd['Surfaces'][str(vv)][ii]['value']['material']['binUtility']['binningdata'][0]['bins']=36
dd['Surfaces'][str(vv)][ii]['value']['material']['binUtility']['binningdata'][1]['bins']=200


with open(out_name, "w") as outfile:
json.dump(dd, outfile, indent=4)

print("Done! Updated config file at "+out_name)
Loading
Loading