diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 164594d57926e8e4124046455457f139a4d8db64..c24f9813acec6ca8a70a2e44a66c9ac5685ac079 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -62,6 +62,7 @@ include: - local: 'benchmarks/dis/config.yml' #- local: 'benchmarks/dvmp/config.yml' - local: 'benchmarks/dvcs/config.yml' + - local: 'benchmarks/u_omega/config.yml' summary: stage: finish diff --git a/benchmarks/u_omega/config.yml b/benchmarks/u_omega/config.yml new file mode 100644 index 0000000000000000000000000000000000000000..9e4925b6d431097afec2363d590e7c2aeb26480a --- /dev/null +++ b/benchmarks/u_omega/config.yml @@ -0,0 +1,14 @@ +u_omega:process: + stage: process + extends: .phy_benchmark + tags: + - s3 + needs: ["common:detector"] + script: + - bash benchmarks/u_omega/u_omega.sh --all + +u_omega:results: + stage: collect + needs: ["u_omega:process"] + script: + - ls -lrth diff --git a/benchmarks/u_omega/scripts/demo.cxx b/benchmarks/u_omega/scripts/demo.cxx new file mode 100644 index 0000000000000000000000000000000000000000..599b63d16332de170970a9756e856186d332bdb1 --- /dev/null +++ b/benchmarks/u_omega/scripts/demo.cxx @@ -0,0 +1,145 @@ +#include <cmath> +#include <iostream> +#include <string> +#include <vector> + +#include "ROOT/RDataFrame.hxx" + +#include <nlohmann/json.hpp> +using json = nlohmann::json; + +R__LOAD_LIBRARY(libfmt.so) +#include "fmt/core.h" +#include "fmt/color.h" + +R__LOAD_LIBRARY(libeicd.so) +R__LOAD_LIBRARY(libDD4pod.so) + +#include "dd4pod/Geant4ParticleCollection.h" +#include "eicd/TrackParametersCollection.h" +#include "eicd/ClusterCollection.h" +#include "eicd/ReconstructedParticleCollection.h" +#include "eicd/BasicParticleCollection.h" + +using ROOT::RDataFrame; +using namespace ROOT::VecOps; + +auto p_track = [](std::vector<eic::TrackParametersData> const& in) { + std::vector<double> result; + for (size_t i = 0; i < in.size(); ++i) { + result.push_back(std::abs(1.0/(in[i].qOverP))); + } + return result; +}; + + +auto pt = [](std::vector<dd4pod::Geant4ParticleData> const& in){ + std::vector<float> result; + for (size_t i = 0; i < in.size(); ++i) { + result.push_back(std::sqrt(in[i].ps.x * in[i].ps.x + in[i].ps.y * in[i].ps.y)); + } + return result; +}; + +auto momentum = [](std::vector<ROOT::Math::PxPyPzMVector> const& in) { + std::vector<double> result; + for (size_t i = 0; i < in.size(); ++i) { + result.push_back(in[i].E()); + } + return result; +}; +auto theta = [](std::vector<ROOT::Math::PxPyPzMVector> const& in) { + std::vector<double> result; + for (size_t i = 0; i < in.size(); ++i) { + result.push_back(in[i].Theta()*180/M_PI); + } + return result; +}; +auto fourvec = [](ROOT::VecOps::RVec<dd4pod::Geant4ParticleData> const& in) { + std::vector<ROOT::Math::PxPyPzMVector> result; + ROOT::Math::PxPyPzMVector lv; + for (size_t i = 0; i < in.size(); ++i) { + lv.SetCoordinates(in[i].ps.x, in[i].ps.y, in[i].ps.z, in[i].mass); + result.push_back(lv); + } + return result; +}; +auto recfourvec = [](ROOT::VecOps::RVec<eic::ReconstructedParticleData> const& in) { + std::vector<ROOT::Math::PxPyPzMVector> result; + ROOT::Math::PxPyPzMVector lv; + for (size_t i = 0; i < in.size(); ++i) { + lv.SetCoordinates(in[i].p.x, in[i].p.y, in[i].p.z, in[i].mass); + result.push_back(lv); + } + return result; +}; + +auto delta_p = [](const std::vector<double>& tracks, const std::vector<double>& thrown) { + std::vector<double> res; + for (const auto& p1 : thrown) { + for (const auto& p2 : tracks) { + res.push_back(p1 - p2); + } + } + return res; +}; + + +void demo(const char* fname = "rec_dvcs.root"){ + + fmt::print(fmt::emphasis::bold | fg(fmt::color::forest_green), "Running u_omega analysis...\n"); + + // Run this in multi-threaded mode if desired + ROOT::EnableImplicitMT(); + ROOT::RDataFrame df("events", fname); + + using ROOT::Math::PxPyPzMVector; + PxPyPzMVector p_ebeam = {0,0,-10, 0.000511}; + PxPyPzMVector p_pbeam = {0,0,275, 0.938 }; + + auto eprime = [](ROOT::VecOps::RVec<dd4pod::Geant4ParticleData> const& in) { + for(const auto& p : in){ + if(p.pdgID == 11 ) { + return PxPyPzMVector(p.ps.x,p.ps.y,p.ps.z,p.mass); + } + } + return PxPyPzMVector(0,0,0,0); + }; + auto q_vec = [=](PxPyPzMVector const& p) { + return p_ebeam - p; + }; + + auto df0 = df.Define("isThrown", "mcparticles2.genStatus == 1") + .Define("thrownParticles", "mcparticles2[isThrown]") + .Define("thrownP", fourvec, {"thrownParticles"}) + .Define("recP", recfourvec, {"ReconstructedParticles"}) + .Define("NPart", "recP.size()") + .Define("p_thrown", momentum, {"thrownP"}) + .Define("nTracks", "outputTrackParameters.size()") + .Define("p_track", p_track, {"outputTrackParameters"}) + .Define("delta_p",delta_p, {"p_track", "p_thrown"}) + .Define("eprime", eprime, {"thrownParticles"}) + .Define("q", q_vec, {"eprime"}) + .Define("Q2", "-1.0*(q.Dot(q))"); + + auto h_n_dummy = df0.Histo1D({"h_n_part", "; h_n_part n", 10, 0, 10}, "NPart"); + auto h_Q2 = df0.Histo1D({"h_Q2", "; Q^{2} [GeV^{2}/c^{2}]", 100, 0, 30}, "Q2"); + auto n_Q2 = df0.Filter("Q2>1").Count(); + auto n_tracks = df0.Mean("nTracks"); + + // --------------------------- + // Do evaluation + + auto c = new TCanvas(); + h_Q2->DrawCopy(); + c->SaveAs("results/u_omega/Q2.png"); + c->SaveAs("results/u_omega/Q2.pdf"); + fmt::print("{} u_omega events\n",*n_Q2); + fmt::print("{} tracks per event\n",*n_tracks); + + c = new TCanvas(); + h_n_dummy->DrawCopy(); + c->SaveAs("results/u_omega/n_dummy.png"); + //c->SaveAs("results/u_omega/n_dummy.pdf"); + +} diff --git a/benchmarks/u_omega/u_omega.sh b/benchmarks/u_omega/u_omega.sh new file mode 100644 index 0000000000000000000000000000000000000000..fa0f69bb5dd8afd754615101de6d3bf9a41f55dc --- /dev/null +++ b/benchmarks/u_omega/u_omega.sh @@ -0,0 +1,150 @@ +#!/bin/bash + +function print_the_help { + echo "USAGE: ${0} [--rec] [--sim] [--analysis] [--all] " + echo " The default options are to run all steps (sim,rec,analysis) " + echo "OPTIONS: " + echo " --data-init download the input event data" + echo " --sim,-s Runs the Geant4 simulation" + echo " --rec,-r Run the juggler reconstruction" + echo " --analysis,-a Run the analysis scripts" + echo " --all (default) Do all steps. Argument is included so usage can convey intent." + exit +} + +DO_ALL=1 +DATA_INIT= +DO_SIM= +DO_REC= +DO_ANALYSIS= + +POSITIONAL=() +while [[ $# -gt 0 ]] +do + key="$1" + + case $key in + -h|--help) + shift # past argument + print_the_help + ;; + --all) + DO_ALL=2 + if [[ ! "${DO_REC}${DO_SIM}${DO_ANALYSIS}" -eq "" ]] ; then + echo "Error: cannot use --all with other arguments." 1>&2 + print_the_help + exit 1 + fi + shift # past value + ;; + -s|--sim) + DO_SIM=1 + DO_ALL= + shift # past value + ;; + --data-init) + DATA_INIT=1 + DO_ALL= + shift # past value + ;; + -r|--rec) + DO_REC=1 + DO_ALL= + shift # past value + ;; + -a|--analysis) + DO_ANALYSIS=1 + DO_ALL= + shift # past value + ;; + *) # unknown option + #POSITIONAL+=("$1") # save it in an array for later + echo "unknown option $1" + print_the_help + shift # past argument + ;; + esac +done +set -- "${POSITIONAL[@]}" # restore positional parameters + +# assuming something like .local/bin/env.sh has already been sourced. +print_env.sh + +FILE_NAME_TAG="u_omega" +DATA_URL="S3/eictest/ATHENA/EVGEN/EXCLUSIVE/omega/u_omegaNeutralDecay_5x41GeV_5k_Q2_1_5.hepmc" + +export JUGGLER_MC_FILE="${LOCAL_DATA_PATH}/mc_${FILE_NAME_TAG}.hepmc" +export JUGGLER_SIM_FILE="${LOCAL_DATA_PATH}/sim_${FILE_NAME_TAG}.root" +export JUGGLER_REC_FILE="${LOCAL_DATA_PATH}/rec_${FILE_NAME_TAG}.root" + +echo "FILE_NAME_TAG = ${FILE_NAME_TAG}" +echo "JUGGLER_N_EVENTS = ${JUGGLER_N_EVENTS}" +echo "JUGGLER_DETECTOR = ${JUGGLER_DETECTOR}" + +## 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 + +## Step 1. Get the data +if [[ -n "${DATA_INIT}" || -n "${DO_ALL}" ]] ; then + mc -C . config host add S3 https://dtn01.sdcc.bnl.gov:9000 $S3_ACCESS_KEY $S3_SECRET_KEY + mc -C . cat --insecure ${DATA_URL} | head -n 1004 > "${JUGGLER_MC_FILE}" + if [[ "$?" -ne "0" ]] ; then + echo "Failed to download hepmc file" + exit 1 + fi +fi + +### Step 2. Run the simulation (geant4) +if [[ -n "${DO_SIM}" || -n "${DO_ALL}" ]] ; then + ## run geant4 simulations + npsim --runType batch \ + --part.minimalKineticEnergy 1000*GeV \ + -v ERROR \ + --numberOfEvents ${JUGGLER_N_EVENTS} \ + --compactFile ${DETECTOR_PATH}/${JUGGLER_DETECTOR}.xml \ + --inputFiles "${JUGGLER_MC_FILE}" \ + --outputFile ${JUGGLER_SIM_FILE} + if [[ "$?" -ne "0" ]] ; then + echo "ERROR running npsim" + exit 1 + fi +fi + +### Step 3. Run the reconstruction (juggler) +if [[ -n "${DO_REC}" || -n "${DO_ALL}" ]] ; then + xenv -x ${JUGGLER_INSTALL_PREFIX}/Juggler.xenv \ + gaudirun.py options/reconstruction.py + if [[ "$?" -ne "0" ]] ; then + echo "ERROR running juggler" + exit 1 + fi + + root_filesize=$(stat --format=%s "${JUGGLER_REC_FILE}") + if [[ "${JUGGLER_N_EVENTS}" -lt "500" ]] ; then + # file must be less than 10 MB to upload + if [[ "${root_filesize}" -lt "10000000" ]] ; then + cp ${JUGGLER_REC_FILE} results/. + fi + fi +fi + +### Step 4. Run the analysis code +if [[ -n "${DO_ANALYSIS}" || -n "${DO_ALL}" ]] ; then + echo "Running analysis scripts" + rootls -t ${JUGGLER_REC_FILE} + + # Store all plots here (preferribly png and pdf files) + mkdir -p "results/${FILE_NAME_TAG}" + + # here you can add as many scripts as you want. + root -b -q "benchmarks/${FILE_NAME_TAG}/scripts/demo.cxx(\"${JUGGLER_REC_FILE}\")" + if [[ "$?" -ne "0" ]] ; then + echo "ERROR running root script" + exit 1 + fi +fi + + +