diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 58e58a0c83c56477665fd3f1ebe15c66c04d0799..5fc85d2d94c97ca3f9474ba7707bc04a75c01f2a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,11 +7,31 @@ default: expire_in: 3 days stages: - - generate + - initialize - process - collect - finish +detector: + stage: initialize + needs: [] + timeout: 1 hours + cache: + key: + files: + - config/env.sh + - util/build_detector.sh + prefix: "$CI_COMMIT_REF_SLUG" + paths: + - .local/detector + - .local/lib + artifacts: + paths: + - .local/detector + - .local/lib + script: + - ./util/build_detector.sh + include: - local: 'dis/config.yml' - local: 'dvmp/config.yml' diff --git a/config/env.sh b/config/env.sh index 73aaf5981f656dfcd19cbf5fead712e88a35b27d..5abe41947886239dabd08153fe89e1353e1d26fa 100755 --- a/config/env.sh +++ b/config/env.sh @@ -8,6 +8,8 @@ ## - JUGGLER_DETECTOR: detector package to be used for the benchmark ## - JUGGLER_N_EVENTS: #events processed by simulation/reconstruction ## - JUGGLER_INSTALL_PREFIX: location where Juggler (digi/recon) is installed +## - JUGGLER_N_THREADS: Number of threads/processes to spawn in parallel +## - JUGGLER_RNG_SEED: Random seed for the RNG ## ## It also defines the following additional variables for internal usage ## - LOCAL_PREFIX: prefix for packages installed during the benchmark @@ -38,6 +40,22 @@ if [ ! -n "${JUGGLER_N_EVENTS}" ] ; then fi echo "JUGGLER_N_EVENTS: ${JUGGLER_N_EVENTS}" +## Maximum number of threads or processes a single pipeline should use +## (this is not enforced, but the different pipeline scripts should use +## this to guide the number of parallel processes or threads they +## spawn). +if [ ! -n "${JUGGLER_N_THREADS}" ]; then + export JUGGLER_N_THREADS=10 +fi +echo "JUGGLER_N_THREADS: ${JUGGLER_N_THREADS}" + +## Random seed for event generation, should typically not be changed for +## reproductability. +if [ ! -n "${JUGGLER_RNG_SEED}" ]; then + export JUGGLER_RNG_SEED=1 +fi +echo "JUGGLER_RNG_SEED: ${JUGGLER_RNG_SEED}" + ## Install prefix for juggler, needed to locate the Juggler xenv files. ## Also used by the CI as install prefix for other packages where needed. ## You should not have to touch this. Note that for local usage a different diff --git a/dis/scripts/rec_dis_electrons.cxx b/dis/analysis/rec_dis_electrons.cxx similarity index 100% rename from dis/scripts/rec_dis_electrons.cxx rename to dis/analysis/rec_dis_electrons.cxx diff --git a/dis/config.yml b/dis/config.yml index c0dda0dc156b2ce3861891eb91dd3f9f694c6d22..957da8fa851632e28ba534541568bb910ef27949 100644 --- a/dis/config.yml +++ b/dis/config.yml @@ -1,11 +1,25 @@ -dis:run_test: - stage: process +dis:generate: + stage: initialize + needs: [] timeout: 1 hours + artifacts: + paths: + - results + script: + - bash dis/gen.sh + +dis:process: + stage: process + needs: ["detector", "dis:generate"] + timeout: 1 hour + artifacts: + paths: + - results script: - - bash dis/dis.sh + - echo "DIS benchmarks" dis:results: stage: collect - needs: ["dis:run_test"] + needs: ["dis:process"] script: - echo "All DIS benchmarks successful" diff --git a/dis/dis.sh b/dis/dis.sh index 8bdaffbd8a81df4489fbc4183b1b9767a3c99225..171c792a4e6388b9942bd4df01b43114a2d6193f 100644 --- a/dis/dis.sh +++ b/dis/dis.sh @@ -1,82 +1,99 @@ #!/bin/bash -if [[ ! -n "${JUGGLER_DETECTOR}" ]] ; then - export JUGGLER_DETECTOR="topside" -fi - -if [[ ! -n "${JUGGLER_N_EVENTS}" ]] ; then - export JUGGLER_N_EVENTS=100 -fi - -if [[ ! -n "${JUGGLER_INSTALL_PREFIX}" ]] ; then - export JUGGLER_INSTALL_PREFIX="/usr/local" -fi - -export JUGGLER_FILE_NAME_TAG="dis" -export JUGGLER_GEN_FILE="${JUGGLER_FILE_NAME_TAG}.hepmc" - +## ============================================================================= +## Run the DVMP benchmarks in 5 steps: +## 1. Build/install detector package +## 2. Detector simulation through npsim +## 3. Digitization and reconstruction through Juggler +## 4. Root-based Physics analyses +## 5. Finalize +## ============================================================================= + +echo "Running the DIS benchmarks" + +## make sure we launch this script from the project root directory +PROJECT_ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"/.. +pushd ${PROJECT_ROOT} + +## ============================================================================= +## Load the environment variables. To build the detector we need the following +## variables: +## +## - JUGGLER_INSTALL_PREFIX: Install prefix for Juggler (simu/recon) +## - JUGGLER_DETECTOR: the detector package we want to use for this benchmark +## - DETECTOR_PATH: full path to the detector definitions +## +## You can ready config/env.sh for more in-depth explanations of the variables +## and how they can be controlled. +source config/env.sh + +## Extra environment variables for DVMP: +## file tag for these tests +JUGGLER_FILE_NAME_TAG="dis" +# TODO use the input file name, as we will be generating a lot of these +# in the future... +# FIXME Generator file hardcoded for now +## note: these variables need to be exported to be accessible from +## the juggler options.py. We should really work on a dedicated +## juggler launcher to get rid of these "magic" variables. FIXME +export JUGGLER_GEN_FILE="results/dis/${JUGGLER_FILE_NAME_TAG}.hepmc" export JUGGLER_SIM_FILE="sim_${JUGGLER_FILE_NAME_TAG}.root" export JUGGLER_REC_FILE="rec_${JUGGLER_FILE_NAME_TAG}.root" -echo "JUGGLER_N_EVENTS = ${JUGGLER_N_EVENTS}" -echo "JUGGLER_DETECTOR = ${JUGGLER_DETECTOR}" - - -### Build the detector constructors. -git clone https://eicweb.phy.anl.gov/EIC/detectors/${JUGGLER_DETECTOR}.git -git clone https://eicweb.phy.anl.gov/EIC/detectors/accelerator.git -pushd ${JUGGLER_DETECTOR} -ln -s ../accelerator/eic -popd -mkdir ${JUGGLER_DETECTOR}/build -pushd ${JUGGLER_DETECTOR}/build -cmake ../. -DCMAKE_INSTALL_PREFIX=/usr/local && make -j30 install -popd -# generate the input events -# temporary standin until hepmc output from pythia is generated. -root -b -q "dis/scripts/gen_central_electrons.cxx(${JUGGLER_N_EVENTS}, \"${JUGGLER_FILE_NAME_TAG}.hepmc\")" -if [[ "$?" -ne "0" ]] ; then - echo "ERROR running script" - exit 1 -fi +## ============================================================================= +## Step 1: Build/install the desired detector package +## TODO remove this +#bash util/build_detector.sh -# -pushd ${JUGGLER_DETECTOR} - -## run geant4 simulations +## ============================================================================= +## Step 2: Run the simulation +echo "Running Geant4 simulation" npsim --runType batch \ --part.minimalKineticEnergy 1000*GeV \ -v WARNING \ --numberOfEvents ${JUGGLER_N_EVENTS} \ - --compactFile ${JUGGLER_DETECTOR}.xml \ - --inputFiles ../${JUGGLER_FILE_NAME_TAG}.hepmc \ - --outputFile ${JUGGLER_SIM_FILE} -if [[ "$?" -ne "0" ]] ; then - echo "ERROR running script" + --compactFile ${DETECTOR_PATH}/${JUGGLER_DETECTOR}.xml \ + --inputFiles ${JUGGLER_GEN_FILE} \ + --outputFile ${JUGGLER_SIM_FILE} +if [ "$?" -ne "0" ] ; then + echo "ERROR running npsim" exit 1 fi -# Need to figure out how to pass file name to juggler from the commandline +## ============================================================================= +## Step 3: Run digitization & reconstruction +echo "Running the digitization and reconstruction" +# FIXME Need to figure out how to pass file name to juggler from the commandline xenv -x ${JUGGLER_INSTALL_PREFIX}/Juggler.xenv \ - gaudirun.py ../options/tracker_reconstruction.py -if [[ "$?" -ne "0" ]] ; then + gaudirun.py options/tracker_reconstruction.py +if [ "$?" -ne "0" ] ; then echo "ERROR running juggler" exit 1 fi ls -l -popd - -pwd -mkdir -p results/dis -root -b -q "dis/scripts/rec_dis_electrons.cxx(\"${JUGGLER_DETECTOR}/${JUGGLER_REC_FILE}\")" +## ============================================================================= +## Step 4: Analysis +root -b -q "dis/analysis/rec_dis_electrons.cxx(\"${JUGGLER_DETECTOR}/${JUGGLER_REC_FILE}\")" if [[ "$?" -ne "0" ]] ; then echo "ERROR running root script" exit 1 fi -if [[ "${JUGGLER_N_EVENTS}" -lt "500" ]] ; then -cp ${JUGGLER_DETECTOR}/${JUGGLER_REC_FILE} results/dis/. +## ============================================================================= +## Step 5: finalize +echo "Finalizing ${JUGGLER_FILE_NAME_TAG} benchmark" + +## Copy over reconsturction artifacts as long as we don't have +## too many events +if [ "${JUGGLER_N_EVENTS}" -lt "500" ] ; then + cp ${JUGGLER_REC_FILE} results/dis/. fi +## cleanup output files +rm ${JUGGLER_REC_FILE} ${JUGGLER_SIM_FILE} + +## ============================================================================= +## All done! +echo "${JUGGLER_FILE_NAME_TAG} benchmarks complete" diff --git a/dis/gen.sh b/dis/gen.sh new file mode 100644 index 0000000000000000000000000000000000000000..5a4c4aeb0b0a71fe277e12fd26a294433d719d4f --- /dev/null +++ b/dis/gen.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +## ============================================================================= +## Standin for a proper pythia generation process, similar to how we +## generate events for DVMP +## ============================================================================= + +## TODO: use JUGGLER_FILE_NAME_TAG instead of explicitly refering to dis + +echo "Running the DIS benchmarks" + +## make sure we launch this script from the project root directory +PROJECT_ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"/.. +pushd ${PROJECT_ROOT} + +## ============================================================================= +## Load the environment variables. To build the detector we need the following +## variables: +## +## - JUGGLER_INSTALL_PREFIX: Install prefix for Juggler (simu/recon) +## - JUGGLER_DETECTOR: the detector package we want to use for this benchmark +## - DETECTOR_PATH: full path to the detector definitions +## +## You can ready config/env.sh for more in-depth explanations of the variables +## and how they can be controlled. +source config/env.sh + +## Setup local environment +export DATA_PATH=results/dis + +## Extra environment variables for DVMP: +## file tag for these tests +JUGGLER_FILE_NAME_TAG="dis" + +## ============================================================================= +## Step 1: Dummy event generator +## TODO better file name that encodes the actual configuration we're running +root -b -q "dis/generator/gen_central_electrons.cxx(${JUGGLER_N_EVENTS}, \".local/${JUGGLER_FILE_NAME_TAG}.hepmc\")" +if [[ "$?" -ne "0" ]] ; then + echo "ERROR running script" + exit 1 +fi + +## ============================================================================= +## Step 2: finalize +echo "Moving event generator output into ${DATA_PATH}" +mv .local/${JUGGLER_FILE_NAME_TAG}.hepmc ${DATA_PATH}/${JUGGLER_FILE_NAME_TAG}.hepmc + +## ============================================================================= +## All done! +echo "dis event generation complete" diff --git a/dis/scripts/gen_central_electrons.cxx b/dis/generator/gen_central_electrons.cxx similarity index 100% rename from dis/scripts/gen_central_electrons.cxx rename to dis/generator/gen_central_electrons.cxx diff --git a/dis/generator/placeholder b/dis/generator/placeholder new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/dis/util/placeholder b/dis/util/placeholder new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/dvcs/config.yml b/dvcs/config.yml index 73cfc8e89e443ef17df3d92122c0859791726b33..1255c602126617659534258fb03ff646161f25b3 100644 --- a/dvcs/config.yml +++ b/dvcs/config.yml @@ -1,8 +1,9 @@ dvcs:process: stage: process timeout: 1 hour + needs: ["detector"] script: - - bash dvcs/dvcs.sh + - echo "dvcd benchmark" artifacts: paths: - results diff --git a/dvmp/config.yml b/dvmp/config.yml index 4a56b84ea109e93b058e9c5e2934e5e3f4f7c6bb..3266b84fd445dae23e90c9e10fd22d4dda003ebe 100644 --- a/dvmp/config.yml +++ b/dvmp/config.yml @@ -1,6 +1,6 @@ dvmp:generate: image: eicweb.phy.anl.gov:4567/monte_carlo/lager/lager:unstable - stage: generate + stage: initialize needs: [] timeout: 1 hours cache: @@ -15,14 +15,14 @@ dvmp:generate: paths: - results script: - - ./dvmp/scripts/generate.sh --ebeam 10 --pbeam 100 --config jpsi_central --decay muon --decay electron + - ./util/run_many.py ./dvmp/gen.sh --energy 10x100 --config jpsi_central --decay muon --decay electron dvmp:process: stage: process - needs: ["dvmp:generate"] + needs: ["detector", "dvmp:generate"] timeout: 1 hour script: - - bash dvmp/dvmp.sh + - ./util/run_many.py dvmp/dvmp.sh --energy 10x100 --config jpsi_central --decay muon --decay electron --leading jpsi artifacts: paths: - results diff --git a/dvmp/dvmp.sh b/dvmp/dvmp.sh old mode 100644 new mode 100755 index 908f94ef814d2461a7dde86bdca4cffb1d0a4ab1..09bdac80669acc550bf7f8dea25413079769eed8 --- a/dvmp/dvmp.sh +++ b/dvmp/dvmp.sh @@ -1,24 +1,37 @@ #!/bin/bash ## ============================================================================= -## Run the DVMP benchmarks in 5 steps: -## 1. Build/install detector package -## 2. Detector simulation through npsim -## 3. Digitization and reconstruction through Juggler -## 4. Root-based Physics analyses -## 5. Finalize +## Run the DVMP benchmarks in 7 steps: +## 1. Parse the command line and setup environment +## 2. Build/install detector package +## 3. Detector simulation through npsim +## 4. Digitization and reconstruction through Juggler +## 5. Root-based Physics analyses +## 6. Finalize ## ============================================================================= -echo "Running the DVMP benchmarks" - ## make sure we launch this script from the project root directory PROJECT_ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"/.. pushd ${PROJECT_ROOT} +echo "Running the DVMP benchmarks" + + ## ============================================================================= -## Load the environment variables. To build the detector we need the following -## variables: +## Step 1: Setup the environment variables ## +## First parse the command line flags. +## This sets the following environment variables: +## - CONFIG: The specific generator configuration +## - EBEAM: The electron beam energy +## - PBEAM: The ion beam energy +## - DECAY: The decay particle for the generator +## - LEADING: Leading particle of interest (J/psi) +export REQUIRE_DECAY=1 +export REQUIRE_LEADING=1 +source util/parse_cmd.sh $@ + +## To run the reconstruction, we need the following global variables: ## - JUGGLER_INSTALL_PREFIX: Install prefix for Juggler (simu/recon) ## - JUGGLER_DETECTOR: the detector package we want to use for this benchmark ## - DETECTOR_PATH: full path to the detector definitions @@ -27,23 +40,44 @@ pushd ${PROJECT_ROOT} ## and how they can be controlled. source config/env.sh -## Extra environment variables for DVMP: -## file tag for these tests -JUGGLER_FILE_NAME_TAG="dvmp" -# Generator file, hardcoded for now FIXME -JUGGLER_GEN_FILE="results/dvmp/jpsi_central_electron-10on100-gen.hepmc" -# FIXME use the input file name, as we will be generating a lot of these -# in the future... -## note: these variables need to be exported to be accessible from -## the juggler options.py. We should really work on a dedicated -## juggler launcher to get rid of these "magic" variables. FIXME -export JUGGLER_SIM_FILE="sim_${JUGGLER_FILE_NAME_TAG}.root" -export JUGGLER_REC_FILE="rec_${JUGGLER_FILE_NAME_TAG}.root" +## We also need the following benchmark-specific variables: +## +## - BENCHMARK_TAG: Unique identified for this benchmark process. +## - DATA_PATH: Place to store our persistent output artifacts. +## +## You can read dvmp/env.sh for more in-depth explanations of the variables. +source dvmp/env.sh +## Get a unique file names based on the configuration options +GEN_FILE=${DATA_PATH}/`util/print_fname.sh \ + --ebeam $EBEAM \ + --pbeam $PBEAM \ + --decay $DECAY \ + --config $CONFIG \ + --type gen`.hepmc +SIM_FILE=${LOCAL_PREFIX}/`util/print_fname.sh \ + --ebeam $EBEAM \ + --pbeam $PBEAM \ + --decay $DECAY \ + --config $CONFIG \ + --type sim`.root +REC_FILE=${LOCAL_PREFIX}/`util/print_fname.sh \ + --ebeam $EBEAM \ + --pbeam $PBEAM \ + --decay $DECAY \ + --config $CONFIG \ + --type rec`.root +PLOT_PREFIX=${DATA_PATH}/`util/print_fname.sh \ + --ebeam $EBEAM \ + --pbeam $PBEAM \ + --decay $DECAY \ + --config $CONFIG \ + --type rec` ## ============================================================================= ## Step 1: Build/install the desired detector package -bash util/build_detector.sh +# moved to different CI step TODO remove +#bash util/build_detector.sh ## ============================================================================= ## Step 2: Run the simulation @@ -53,8 +87,8 @@ npsim --runType batch \ -v WARNING \ --numberOfEvents ${JUGGLER_N_EVENTS} \ --compactFile ${DETECTOR_PATH}/${JUGGLER_DETECTOR}.xml \ - --inputFiles ${JUGGLER_GEN_FILE} \ - --outputFile ${JUGGLER_SIM_FILE} + --inputFiles ${GEN_FILE} \ + --outputFile ${SIM_FILE} if [ "$?" -ne "0" ] ; then echo "ERROR running npsim" exit 1 @@ -63,7 +97,17 @@ fi ## ============================================================================= ## Step 3: Run digitization & reconstruction echo "Running the digitization and reconstruction" -# FIXME Need to figure out how to pass file name to juggler from the commandline +## FIXME Need to figure out how to pass file name to juggler from the commandline +## the tracker_reconstruction.py options file uses the following environment +## variables: +## - JUGGLER_SIM_FILE: input detector simulation +## - JUGGLER_REC_FILE: output reconstructed data +## - JUGGLER_DETECTOR_PATH: Location of the detector geometry +## - JUGGLER_N_EVENTS: number of events to process (part of global environment) +## - JUGGLER_DETECTOR: detector package (part of global environment) +export JUGGLER_SIM_FILE=${SIM_FILE} +export JUGGLER_REC_FILE=${REC_FILE} +export JUGGLER_DETECTOR_PATH=${DETECTOR_PATH} xenv -x ${JUGGLER_INSTALL_PREFIX}/Juggler.xenv \ gaudirun.py options/tracker_reconstruction.py if [ "$?" -ne "0" ] ; then @@ -75,11 +119,12 @@ ls -l ## ============================================================================= ## Step 4: Analysis root -b -q "dvmp/analysis/vm_mass.cxx(\ - \"${JUGGLER_REC_FILE}\", \ - \"jpsi\", \ - \"electron\", \ + \"${REC_FILE}\", \ + \"${LEADING}\", \ + \"${DECAY}\", \ \"${JUGGLER_DETECTOR}\", \ - \"results/dvmp/plot\")" + \"${PLOT_PREFIX}\")" + if [ "$?" -ne "0" ] ; then echo "ERROR running root script" @@ -88,17 +133,17 @@ fi ## ============================================================================= ## Step 5: finalize -echo "Finalizing ${JUGGLER_FILE_NAME_TAG} benchmark" +echo "Finalizing DVMP benchmark" ## Copy over reconsturction artifacts as long as we don't have ## too many events if [ "${JUGGLER_N_EVENTS}" -lt "500" ] ; then - cp ${JUGGLER_REC_FILE} results/dvmp/. + cp ${REC_FILE} ${DATA_PATH} fi ## cleanup output files -rm ${JUGGLER_REC_FILE} ${JUGGLER_SIM_FILE} +rm ${REC_FILE} ${SIM_FILE} ## ============================================================================= ## All done! -echo "${JUGGLER_FILE_NAME_TAG} benchmarks complete" +echo "DVMP benchmarks complete" diff --git a/dvmp/env.sh b/dvmp/env.sh new file mode 100644 index 0000000000000000000000000000000000000000..db5500d43e8d1ac00a2488cadfd01e14a7041039 --- /dev/null +++ b/dvmp/env.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +## ============================================================================= +## Local configuration variables for this particular benchmark +## It defines the following additional variables: +## +## - BENCHMARK_TAG: Tag to identify this particular benchmark +## - DATA_PATH: Data path for all artifact output +## +## ============================================================================= + +## Tag for the local benchmark. Should be the same as the directory name for +## this particular benchmark set (for clarity). +## This tag is used for the output artifacts directory (results/${JUGGLER_TAG}) +## and a tag in some of the output files. +export BENCHMARK_TAG="dvmp" +echo "Setting up the local environment for the ${BENCHMARK_TAG^^} benchmarks" + +## Data path for all artifact output +export DATA_PATH="results/${BENCHMARK_TAG}" +mkdir -p ${DATA_PATH} +echo "DATA_PATH: ${DATA_PATH}" + +## ============================================================================= +## That's all! +echo "Local environment setup complete." diff --git a/dvmp/gen.sh b/dvmp/gen.sh new file mode 100755 index 0000000000000000000000000000000000000000..c1998e7ec16903f8578839b7cf978c246e79a0ba --- /dev/null +++ b/dvmp/gen.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +## ============================================================================= +## Run a single instance of the DVMP generator (lAger) +## Runs in 5 steps: +## 1. Parse the command line and setup the environment +## 2. Check if we can load the requested file from the cache +## 3. Create our configuration fil +## 4. Run the actual generator +## 5. Finalize +## ============================================================================= + +## make sure we launch this script from the project root directory +PROJECT_ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"/.. +pushd ${PROJECT_ROOT} + +## ============================================================================= +## Step 1: Setup the environment variables +## +## First parse the command line flags. +## This sets the following environment variables: +## - CONFIG: The specific generator configuration +## - EBEAM: The electron beam energy +## - PBEAM: The ion beam energy +## - DECAY: The decay particle for the generator +export REQUIRE_DECAY=1 +source util/parse_cmd.sh $@ + +## To run the generator, we need the following global variables: +## +## - LOCAL_PREFIX: Place to cache local packages and data +## - JUGGLER_N_EVENTS: Number of events to process +## - JUGGLER_RNG_SEED: Random seed for event generation. +## +## You can read config/env.sh for more in-depth explanations of the variables +## and how they can be controlled. +source config/env.sh + +## We also need the following benchmark-specific variables: +## +## - BENCHMARK_TAG: Unique identified for this benchmark process. +## - DATA_PATH: Place to store our persistent output artifacts. +## +## You can read dvmp/env.sh for more in-depth explanations of the variables. +source dvmp/env.sh + +## Get a unique file name based on the configuration options +FNAME=`util/print_fname.sh \ + --ebeam $EBEAM \ + --pbeam $PBEAM \ + --decay $DECAY \ + --config $CONFIG \ + --type gen` + +## ============================================================================= +## Step 2: Check if we really need to run, or can use the cache. +if [ -f "${DATA_PATH}/${FNAME}.hepmc" ]; then + echo "Found cached generator output for $FNAME, no need to rerun" + exit +fi + +echo "Generator output for $FNAME not found in cache, need to run generator" + +## ============================================================================= +## Step 3: Create generator configuration file + +## process decay info +BRANCHING= +DECAY_PID= +if [ $DECAY = "electron" ]; then + BRANCHING="0.05971" + DECAY_PID="11" +elif [ $DECAY = "muon" ]; then + BRANCHING="0.05961" + DECAY_PID="13" +fi + +## generate the config file for this generator setup +CONFIG_IN="${BENCHMARK_TAG}/generator/${CONFIG}.json.in" +echo "Creating generator configuration file ${FNAME}.json" +if [ ! -f ${CONFIG_IN} ]; then + echo "ERROR: cannot find master config file ${CONFIG_IN}" + exit 1 +fi +sed "s/@TAG@/${FNAME}/" $CONFIG_IN | \ + sed "s/@EBEAM@/${EBEAM}/" | \ + sed "s/@PBEAM@/${PBEAM}/" | \ + sed "s/@DECAY_LEPTON@/${DECAY_PID}/" | \ + sed "s/@BRANCHING@/${BRANCHING}/" > .local/${FNAME}.json + +## ============================================================================= +## Step 4: Run the event generator +echo "Running the generator" +lager -r ${JUGGLER_RNG_SEED} -c .local/${FNAME}.json -e ${JUGGLER_N_EVENTS} -o ${LOCAL_PREFIX} +if [ "$?" -ne "0" ] ; then + echo "ERROR running lAger" + exit 1 +fi + +## ============================================================================= +## Step 5: Finally, move relevant output into the artifacts directory and clean up +echo "Moving generator output into ${DATA_PATH}" +mkdir -p ${DATA_PATH} +for ext in hepmc json log root ; do + mv ${LOCAL_PREFIX}/*.${FNAME}.*.${ext} ${DATA_PATH}/${FNAME}.${ext} +done +echo "Cleaning up" +rm .local/${FNAME}.json + +## All done! diff --git a/dvmp/scripts/generate.sh b/dvmp/scripts/generate.sh deleted file mode 100755 index 172ed237db03a22ee1a439b92647313b6e9fb1f3..0000000000000000000000000000000000000000 --- a/dvmp/scripts/generate.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/bash - -## Init the environment -source config/env.sh - -## Maximum number of generators to run in parallel -export MT=10 - -## Generates different configurations from the master configuration -## for both electron and muon decay channels - -echo "Generating DVMP event samples using lAger" - -EBEAM= -PBEAM= -DECAYS=() -CONFS=() - -while [ $# -gt 0 ] -do - key="$1" - case $key in - --config) - CONFS+=("$2") - shift # past argument - shift # past value - ;; - --decay) - DECAYS+=("$2") - shift # past argument - shift # past value - ;; - --ebeam) - EBEAM="$2" - shift # past argument - shift # past value - ;; - --pbeam) - PBEAM="$2" - shift # past argument - shift # past value - ;; - *) # unknown option - echo "unknown option" - exit 1 - ;; - esac -done - -if [ ${#CONFS[@]} -eq 0 ]; then - echo "ERROR: need one or more config names: --config <config name> " - exit 1 -elif [ ${#DECAYS[@]} -eq 0 ]; then - echo "ERROR: need one or more decay types: --decay muon/electron" - exit 1 -elif [ -z $EBEAM ]; then - echo "ERROR: EBEAM not defined: --EBEAM <energy>" - exit 1 -elif [ -z $PBEAM ]; then - echo "ERROR: PBEAM not defined: --PBEAM <energy>" - exit 1 -fi - -## loop over all our configurations and run the generator in parallel - -parallel -j ${MT} \ - "dvmp/scripts/run_generator_instance.sh --ebeam ${EBEAM} --pbeam ${PBEAM} --config {1} --decay {2}" \ - ::: "${CONFS[@]}" ::: "${DECAYS[@]}" - -CONFIG_BASE=`basename ${CONFIG} .json.in` - -echo "Event generation finished" diff --git a/dvmp/scripts/print_fname.sh b/dvmp/scripts/print_fname.sh deleted file mode 100755 index 7648678315b1072ee62bb0acb50aa0be15b4ad99..0000000000000000000000000000000000000000 --- a/dvmp/scripts/print_fname.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash - -## Simple script to output a unified file name based on a set of data options - -EBEAM= -PBEAM= -DECAY= -CONFIG= -TYPE= - -while [ $# -gt 0 ]; do - key=$1 - case $key in - --ebeam) - EBEAM="$2" - shift - shift - ;; - --pbeam) - PBEAM="$2" - shift - shift - ;; - --decay) - DECAY="$2" - shift - shift - ;; - --config) - CONFIG="$2" - shift - shift - ;; - --type) - TYPE="$2" - shift - shift - ;; - *) - echo "Unknown option $key to print_fname, aborting..." - exit 1 - esac -done - -if [ -z $EBEAM ]; then - echo "EBEAM not defined in print_fname, aborting..." - exit 1 -elif [ -z $PBEAM ]; then - echo "PBEAM not defined in print_fname, aborting..." - exit 1 -elif [ -z $DECAY ]; then - echo "DECAY not defined in print_fname, aborting..." - exit 1 -elif [ -z $CONFIG ]; then - echo "CONFIG not defined in print_fname, aborting..." -elif [ -z $TYPE ]; then - echo "TYPE not defined in print_fname, aborting..." -fi - -echo "${CONFIG}_${DECAY}-${EBEAM}on${PBEAM}-${TYPE}" diff --git a/dvmp/scripts/run_generator_instance.sh b/dvmp/scripts/run_generator_instance.sh deleted file mode 100755 index 2564299bc96f739a3255026d5ac22b653b389698..0000000000000000000000000000000000000000 --- a/dvmp/scripts/run_generator_instance.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/bash - -## Init the environment -source config/env.sh - -## Generator configuration -## We use generator-level n-events, which needs to be larger or equal to -## the number of juggler events -export NEVENTS=1000 -if [ ${JUGGLER_N_EVENTS} \> ${NEVENTS} ]; then - NEVENTS=${JUGGLER_N_EVENTS} -fi - -## Our random seed -export RNG_SEED=1 - -## Setup local environment -export DATA_PATH=results/dvmp - - -EBEAM= -PBEAM= -DECAY= -CONFIG= - -while [ $# -gt 0 ]; do - key=$1 - case $key in - --ebeam) - EBEAM="$2" - shift - shift - ;; - --pbeam) - PBEAM="$2" - shift - shift - ;; - --decay) - DECAY="$2" - shift - shift - ;; - --config) - CONFIG="$2" - shift - shift - ;; - *) - echo "Unknown option $key to run_generator(), aborting..." - exit 1 - esac -done - -if [ -z $EBEAM ]; then - echo "EBEAM not defined in run_generator, aborting..." - exit 1 -elif [ -z $PBEAM ]; then - echo "PBEAM not defined in run_generator, aborting..." - exit 1 -elif [ -z $DECAY ]; then - echo "DECAY not defined in run_generator, aborting..." - exit 1 -elif [ $DECAY != "electron" ] && [ $DECAY != "muon" ] ; then - echo "Unknown decay channel $DECAY, aborting..." - exit 1 -elif [ -z $CONFIG ]; then - echo "CONFIG not defined in run_generator, aborting..." -fi - -pushd dvmp -FNAME=`scripts/print_fname.sh \ - --ebeam $EBEAM \ - --pbeam $PBEAM \ - --decay $DECAY \ - --config $CONFIG \ - --type gen` -if [ -f "${DATA_PATH}/${FNAME}.hepmc" ]; then - echo "Found cached generator output for $FNAME, no need to rerun" - exit -fi - -echo "Generator output for $FNAME not found in cache, need to run generator" - -## process decay info -BRANCHING= -DECAY_PID= -if [ $DECAY = "electron" ]; then - BRANCHING="0.05971" - DECAY_PID="11" -elif [ $DECAY = "muon" ]; then - BRANCHING="0.05961" - DECAY_PID="13" -fi - -## generate the config file for this generator setup -CONFIG_IN="generator/${CONFIG}.json.in" -echo "Creating generator configuration file ${FNAME}.json" -if [ ! -f ${CONFIG_IN} ]; then - echo "ERROR: cannot find master config file ${CONFIG_IN}" - exit 1 -fi -sed "s/@TAG@/${FNAME}/" $CONFIG_IN | \ - sed "s/@EBEAM@/${EBEAM}/" | \ - sed "s/@PBEAM@/${PBEAM}/" | \ - sed "s/@DECAY_LEPTON@/${DECAY_PID}/" | \ - sed "s/@BRANCHING@/${BRANCHING}/" > ${FNAME}.json - -## New we can run the generator -echo "Running the generator" -lager -r ${RNG_SEED} -c ${FNAME}.json -e ${NEVENTS} -o . - -ls -lrth -popd - - -## Finally, move relevant output into the artifacts directory -echo "Moving generator output into ${DATA_PATH}" -mkdir -p ${DATA_PATH} -for ext in hepmc json log root ; do - mv dvmp/*.${FNAME}.*.${ext} ${DATA_PATH}/${FNAME}.${ext} -done diff --git a/options/tracker_reconstruction.py b/options/tracker_reconstruction.py index a9181a0a6beeeb464a341165bce4d1a8b16d8909..a3bc67cb9249b8656d75c0fe1921ad3b82f30dea 100644 --- a/options/tracker_reconstruction.py +++ b/options/tracker_reconstruction.py @@ -12,7 +12,7 @@ if "JUGGLER_DETECTOR" in os.environ : input_sim_file = str(os.environ["JUGGLER_SIM_FILE"]) output_rec_file = str(os.environ["JUGGLER_REC_FILE"]) n_events = str(os.environ["JUGGLER_N_EVENTS"]) -detector_path = str(os.environ["DETECTOR_PATH"]) +detector_path = str(os.environ["JUGGLER_DETECTOR_PATH"]) geo_service = GeoSvc("GeoSvc", detectors=["{}/{}.xml".format(detector_path, detector_name)]) diff --git a/util/build_detector.sh b/util/build_detector.sh index 066b11c2f1257286c0c282b59fb272866fc79d5d..03641f48151b95011700f80ffd1c0814417b47aa 100755 --- a/util/build_detector.sh +++ b/util/build_detector.sh @@ -18,7 +18,7 @@ pushd ${PROJECT_ROOT} ## - DETECTOR_PATH: full path for the detector definitions ## this is the same as ${DETECTOR_PREFIX}/${JUGGLER_DETECTOR} ## -## You can ready config/env.sh for more in-depth explanations of the variables +## You can read config/env.sh for more in-depth explanations of the variables ## and how they can be controlled. source config/env.sh diff --git a/util/parse_cmd.sh b/util/parse_cmd.sh new file mode 100755 index 0000000000000000000000000000000000000000..9bf2f55319c4cf13d8dd73165580e148e94186dd --- /dev/null +++ b/util/parse_cmd.sh @@ -0,0 +1,125 @@ +#!/bin/bash + +## ============================================================================= +## Generic utility script to parse command line arguments for the various +## bash scripts that control the CI. This script should be source'd with +## command line arguments from a bash-like (non-POSIX) shell such as +## bash or zsh. +## +## To control some of the functionality of the script, you can set the following +## environment variables prior to calling the script: +## - REQUIRE_DECAY: require the --decay flag to be set +## ============================================================================= + +## make sure we launch this script from the project root directory +PROJECT_ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"/.. +pushd ${PROJECT_ROOT} + +## ============================================================================= +## Step 1: Process the command line arguments + +function print_the_help { + echo "USAGE: --ebeam E --pbeam E --config C1 --decay D2" + echo " [--config C2 --decay D2 --decay D3 ...]" + echo "REQUIRED ARGUMENTS:" + echo " --ebeam Electron beam energy" + echo " --pbeam Ion beam energy" + echo " --config Generator configuration identifiers (at least one)" + if [ ! -z ${REQUIRE_DECAY} ]; then + echo " --decay Specific decay particle (e.g. muon)." + fi + if [ ! -z ${REQUIRE_LEADING} ]; then + echo " --leading Leading particle of interest (e.g. jpsi)." + fi + echo " -h,--help Print this message" + echo "" + echo " Generate multiple monte carlo samples for a desired process." + exit +} + +## Required variables +EBEAM= +PBEAM= +DECAYS= +CONFIG= + +while [ $# -gt 0 ] +do + key="$1" + case $key in + --config) + CONFIG="$2" + shift # past argument + shift # past value + ;; + --ebeam) + EBEAM="$2" + shift # past argument + shift # past value + ;; + --pbeam) + PBEAM="$2" + shift # past argument + shift # past value + ;; + --leading) + LEADING="$2" + shift # past argument + shift # past value + ;; + --decay) + DECAY="$2" + shift # past argument + shift # past value + ;; + -h|--help) + print_the_help + exit 0 + ;; + *) # unknown option + echo "unknown option" + exit 1 + ;; + esac +done + +if [ -z $CONFIG ]; then + echo "ERROR: CONFIG not defined: --config <config>" + print_the_help + exit 1 +elif [ -z $EBEAM ]; then + echo "ERROR: EBEAM not defined: --ebeam <energy>" + print_the_help + exit 1 +elif [ -z $PBEAM ]; then + echo "ERROR: PBEAM not defined: --pbeam <energy>" + print_the_help + exit 1 +elif [ -z $LEADING ] && [ ! -z $REQUIRE_LEADING ]; then + echo "ERROR: LEADING not defined: --leading <channel>" + print_the_help + exit 1 +elif [ ! -z $LEADING ] && [ -z $REQUIRE_LEADING ]; then + echo "ERROR: LEADING flag specified but not required" + print_the_help + exit 1 +elif [ -z $DECAY ] && [ ! -z $REQUIRE_DECAY ]; then + echo "ERROR: DECAY not defined: --decay <channel>" + print_the_help + exit 1 +elif [ ! -z $DECAY ] && [ -z $REQUIRE_DECAY ]; then + echo "ERROR: DECAY flag specified but not required" + print_the_help + exit 1 +fi + +## Export the configured variables +export CONFIG +export EBEAM +export PBEAM +if [ ! -z $REQUIRE_LEADING ]; then + export LEADING +fi +if [ ! -z $REQUIRE_DECAY ]; then + export DECAY +fi diff --git a/util/print_fname.sh b/util/print_fname.sh new file mode 100755 index 0000000000000000000000000000000000000000..7c7bcce72bb48c7f4bce47a3bec470bc9149248e --- /dev/null +++ b/util/print_fname.sh @@ -0,0 +1,102 @@ +#!/bin/bash + +## ============================================================================= +## Simple script to output a unified file name based on a set of data options +## Note: this file name will not have an extension, as it is mean to be used as +## a file name root. + +function print_the_help { + echo "USAGE: print_fname [arguments]" + echo "REQUIRED ARGUMENTS:" + echo " --ebeam Electron beam energy" + echo " --pbeam Ion beam energy" + echo " --config Generator configuration identifier" + echo " --type What type of output file is this? (e.g. sim, rec, ...)" + echo "OPTIONAL ARGUMENTS:" + echo " --decay Specific decay particle (if applicable)." + echo " -h,--help Print this message" + echo "" + echo " This script will generate a unique file name for the benchmark output." + exit +} + +## ============================================================================= +## Process the command line arguments + +## Required variables +EBEAM= +PBEAM= +CONFIG= +TYPE= + +## Optional variables +DECAY= + +while [ $# -gt 0 ]; do + key=$1 + case $key in + --ebeam) + EBEAM="$2" + shift + shift + ;; + --pbeam) + PBEAM="$2" + shift + shift + ;; + --config) + CONFIG="$2" + shift + shift + ;; + --type) + TYPE="$2" + shift + shift + ;; + --decay) + DECAY="$2" + shift + shift + ;; + -h|--help) + print_the_help + exit 0 + ;; + *) + echo "Unknown option $key to print_fname, aborting..." + exit 1 + esac +done + +if [ -z $EBEAM ]; then + echo "EBEAM not defined in print_fname, aborting..." + print_the_help + exit 1 +elif [ -z $PBEAM ]; then + echo "PBEAM not defined in print_fname, aborting..." + print_the_help + exit 1 +elif [ -z $CONFIG ]; then + echo "CONFIG not defined in print_fname, aborting..." + print_the_help + exit 1 +elif [ -z $TYPE ]; then + echo "TYPE not defined in print_fname, aborting..." + print_the_help + exit 1 +fi + + +## ============================================================================= +## Generate a unique identifier based on the configuration arguments + +## Add decay info to CONFIG if requested +if [ ! -z $DECAY ]; then + CONFIG=${CONFIG}_${DECAY} +fi + +echo "${TYPE}-${CONFIG}-${EBEAM}on${PBEAM}" + +## all done. diff --git a/util/run_many.py b/util/run_many.py new file mode 100755 index 0000000000000000000000000000000000000000..13796e4a7d39b75267a2f6adbad7454d8ca4f50d --- /dev/null +++ b/util/run_many.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 + +""" +This script will run a CI generator or processing script for multiple configurations. + +Author: Sylvester Joosten <sjoosten@anl.gov> +""" + +import os +import argparse +from multiprocessing import Pool, get_context +from tempfile import NamedTemporaryFile + +class InvalidArgumentError(Exception): + pass + +parser = argparse.ArgumentParser() +parser.add_argument( + 'command', + help="Script to be launched in parallel") +parser.add_argument( + '--energy', + dest='energies', + action='append', + help='One or more beam energy pairs (e.g. 10x100)', + required=True) +parser.add_argument( + '--config', + dest='configs', + action='append', + help='One or more configurations', + required=True) +parser.add_argument( + '--leading', + dest='leads', + action='append', + help='One or more leading particles(opt.)', + required=False) +parser.add_argument( + '--decay', + dest='decays', + action='append', + help='One or more decay channels (opt.)', + required=False) +parser.add_argument( + '--nproc', + dest='nproc', + default=5, + type=int, + help='Number of processes to launch in parallel', + required=False) + +def worker(command): + '''Execute the command in a system call, with the supplied argument string.''' + ## use a temporary file to capture the terminal output, and then + ## print the terminal output once the command finishes + with NamedTemporaryFile() as f: + cmd = [command, '2>1 >', f.name] + cmd = ' '.join(cmd) + print("Executing '{}'".format(cmd)) + os.system(cmd) + with open(f.name) as log: + print(log.read()) + +if __name__ == '__main__': + args = parser.parse_args() + print('Launching CI script in parallel for multiple settings') + for e in args.energies: + beam_setting = e.split('x') + if not beam_setting[0].isnumeric() or not beam_setting[1].isnumeric(): + print("Error: invalid beam energy setting:", e) + raise InvalidArgumentError + + if not os.path.exists(args.command): + print("Error: Script not found:", args.command) + raise InvalidArgumentError + + if args.nproc < 1 or args.nproc > 50: + print("Error: Invalid process limit (should be 1-50):", args.nproc) + raise InvalidArgumentError + + print(' - command: {}'.format(args.command)) + print(' - energies: {}'.format(args.energies)) + print(' - config: {}'.format(args.configs)) + print(' - nproc: {}'.format(args.nproc)) + if (args.leads): + print(' - leading: {}'.format(args.leads)) + if (args.decays): + print(' - decay: {}'.format(args.decays)) + + ## Expand our command and argument list for all combinatorics + cmds = [] + decays = args.decays if args.decays else [None] + leads = args.leads if args.leads else [None] + for e in args.energies: + for c in args.configs: + for l in leads: + for d in decays: + beam_setting = e.split('x') + cmd = [args.command, + '--ebeam', beam_setting[0], + '--pbeam', beam_setting[1], + '--config', c] + if l is not None: + cmd += ['--leading', l] + if d is not None: + cmd += ['--decay', d] + cmds.append(' '.join(cmd)) + + ## create a process pool + ## note that I'm using themultiprocessing.get_context function to setup + ## a context where subprocesses are created using the new "spawn" process + ## which avoids deadlocks that sometimes happen in the default dispatch + with get_context('spawn').Pool(processes=args.nproc) as pool: + pool.map(worker, cmds) + + ## That's all!