diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 31456e7e..9eb90aea 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -124,64 +124,71 @@ get_data: - runner_system_failure include: - - local: 'benchmarks/backgrounds/config.yml' - - local: 'benchmarks/backwards_ecal/config.yml' - - local: 'benchmarks/beamline/config.yml' - - local: 'benchmarks/calo_pid/config.yml' - - local: 'benchmarks/ecal_gaps/config.yml' - - local: 'benchmarks/tracking_detectors/config.yml' - - local: 'benchmarks/tracking_performances/config.yml' - - local: 'benchmarks/tracking_performances_dis/config.yml' - - local: 'benchmarks/barrel_ecal/config.yml' - - local: 'benchmarks/barrel_hcal/config.yml' - - local: 'benchmarks/lfhcal/config.yml' - - local: 'benchmarks/zdc/config.yml' - - local: 'benchmarks/zdc_lyso/config.yml' - - local: 'benchmarks/zdc_neutron/config.yml' - - local: 'benchmarks/zdc_photon/config.yml' - - local: 'benchmarks/zdc_pi0/config.yml' - - local: 'benchmarks/material_scan/config.yml' - - local: 'benchmarks/pid/config.yml' - - local: 'benchmarks/timing/config.yml' - - local: 'benchmarks/b0_tracker/config.yml' - - local: 'benchmarks/insert_muon/config.yml' - - local: 'benchmarks/insert_tau/config.yml' - - local: 'benchmarks/zdc_sigma/config.yml' - - local: 'benchmarks/zdc_lambda/config.yml' - - local: 'benchmarks/insert_neutron/config.yml' - - local: 'benchmarks/femc_electron/config.yml' - - local: 'benchmarks/femc_photon/config.yml' - - local: 'benchmarks/femc_pi0/config.yml' + # - local: 'benchmarks/backgrounds/config.yml' + # - local: 'benchmarks/backwards_ecal/config.yml' + # - local: 'benchmarks/beamline/config.yml' + # - local: 'benchmarks/calo_pid/config.yml' + # - local: 'benchmarks/ecal_gaps/config.yml' + # - local: 'benchmarks/tracking_detectors/config.yml' + # - local: 'benchmarks/tracking_performances/config.yml' + # - local: 'benchmarks/tracking_performances_dis/config.yml' + # - local: 'benchmarks/barrel_ecal/config.yml' + # - local: 'benchmarks/barrel_hcal/config.yml' + # - local: 'benchmarks/lfhcal/config.yml' + # - local: 'benchmarks/zdc/config.yml' + # - local: 'benchmarks/zdc_lyso/config.yml' + # - local: 'benchmarks/zdc_neutron/config.yml' + # - local: 'benchmarks/zdc_photon/config.yml' + # - local: 'benchmarks/zdc_pi0/config.yml' + # - local: 'benchmarks/material_scan/config.yml' + # - local: 'benchmarks/pid/config.yml' + # - local: 'benchmarks/timing/config.yml' + # - local: 'benchmarks/b0_tracker/config.yml' + # - local: 'benchmarks/insert_muon/config.yml' + # - local: 'benchmarks/insert_tau/config.yml' + # - local: 'benchmarks/zdc_sigma/config.yml' + # - local: 'benchmarks/zdc_lambda/config.yml' + # - local: 'benchmarks/insert_neutron/config.yml' + # - local: 'benchmarks/femc_electron/config.yml' + # - local: 'benchmarks/femc_photon/config.yml' + # - local: 'benchmarks/femc_pi0/config.yml' + # - local: 'benchmarks/nhcal_acceptance/config.yml' + # - local: 'benchmarks/nhcal_basic_distribution/config.yml' + - local: 'benchmarks/nhcal_sampling_fraction/config.yml' + deploy_results: allow_failure: true stage: deploy needs: - - "collect_results:backgrounds" - - "collect_results:backwards_ecal" - - "collect_results:barrel_ecal" - - "collect_results:barrel_hcal" - - "collect_results:beamline" - - "collect_results:calo_pid" - - "collect_results:ecal_gaps" - - "collect_results:lfhcal" - - "collect_results:material_scan" - - "collect_results:pid" - - "collect_results:tracking_performance" - - "collect_results:tracking_performance_campaigns" - - "collect_results:zdc_sigma" - - "collect_results:zdc_lambda" - - "collect_results:insert_neutron" - - "collect_results:tracking_performances_dis" - - "collect_results:zdc" - - "collect_results:zdc_lyso" - - "collect_results:zdc_neutron" - - "collect_results:insert_muon" - - "collect_results:insert_tau" - - "collect_results:zdc_photon" - - "collect_results:zdc_pi0" - - "collect_results:femc_electron" - - "collect_results:femc_photon" - - "collect_results:femc_pi0" + # - "collect_results:backgrounds" + # - "collect_results:backwards_ecal" + # - "collect_results:barrel_ecal" + # - "collect_results:barrel_hcal" + # - "collect_results:beamline" + # - "collect_results:calo_pid" + # - "collect_results:ecal_gaps" + # - "collect_results:lfhcal" + # - "collect_results:material_scan" + # - "collect_results:pid" + # - "collect_results:tracking_performance" + # - "collect_results:tracking_performance_campaigns" + # - "collect_results:zdc_sigma" + # - "collect_results:zdc_lambda" + # - "collect_results:insert_neutron" + # - "collect_results:tracking_performances_dis" + # - "collect_results:zdc" + # - "collect_results:zdc_lyso" + # - "collect_results:zdc_neutron" + # - "collect_results:insert_muon" + # - "collect_results:insert_tau" + # - "collect_results:zdc_photon" + # - "collect_results:zdc_pi0" + # - "collect_results:femc_electron" + # - "collect_results:femc_photon" + # - "collect_results:femc_pi0" + # - "collect_results:nhcal_acceptance" + # - "collect_results:nhcal_basic_distribution" + - "collect_results:nhcal_sampling_fraction" script: - snakemake $SNAKEMAKE_FLAGS --cores 1 results/metadata.json - find results -print | sort | tee summary.txt diff --git a/Snakefile b/Snakefile index 2277a081..5aced1f5 100644 --- a/Snakefile +++ b/Snakefile @@ -30,28 +30,31 @@ def find_epic_libraries(): return libs -include: "benchmarks/backgrounds/Snakefile" -include: "benchmarks/backwards_ecal/Snakefile" -include: "benchmarks/barrel_ecal/Snakefile" -include: "benchmarks/beamline/Snakefile" -include: "benchmarks/calo_pid/Snakefile" -include: "benchmarks/ecal_gaps/Snakefile" -include: "benchmarks/material_scan/Snakefile" -include: "benchmarks/tracking_performances/Snakefile" -include: "benchmarks/tracking_performances_dis/Snakefile" -include: "benchmarks/lfhcal/Snakefile" -include: "benchmarks/zdc_lyso/Snakefile" -include: "benchmarks/zdc_neutron/Snakefile" -include: "benchmarks/insert_muon/Snakefile" -include: "benchmarks/zdc_lambda/Snakefile" -include: "benchmarks/zdc_photon/Snakefile" -include: "benchmarks/zdc_pi0/Snakefile" -include: "benchmarks/zdc_sigma/Snakefile" -include: "benchmarks/insert_neutron/Snakefile" -include: "benchmarks/insert_tau/Snakefile" -include: "benchmarks/femc_electron/Snakefile" -include: "benchmarks/femc_photon/Snakefile" -include: "benchmarks/femc_pi0/Snakefile" +# include: "benchmarks/backgrounds/Snakefile" +# include: "benchmarks/backwards_ecal/Snakefile" +# include: "benchmarks/barrel_ecal/Snakefile" +# include: "benchmarks/beamline/Snakefile" +# include: "benchmarks/calo_pid/Snakefile" +# include: "benchmarks/ecal_gaps/Snakefile" +# include: "benchmarks/material_scan/Snakefile" +# include: "benchmarks/tracking_performances/Snakefile" +# include: "benchmarks/tracking_performances_dis/Snakefile" +# include: "benchmarks/lfhcal/Snakefile" +# include: "benchmarks/zdc_lyso/Snakefile" +# include: "benchmarks/zdc_neutron/Snakefile" +# include: "benchmarks/insert_muon/Snakefile" +# include: "benchmarks/zdc_lambda/Snakefile" +# include: "benchmarks/zdc_photon/Snakefile" +# include: "benchmarks/zdc_pi0/Snakefile" +# include: "benchmarks/zdc_sigma/Snakefile" +# include: "benchmarks/insert_neutron/Snakefile" +# include: "benchmarks/insert_tau/Snakefile" +# include: "benchmarks/femc_electron/Snakefile" +# include: "benchmarks/femc_photon/Snakefile" +# include: "benchmarks/femc_pi0/Snakefile" +# include: "benchmarks/nhcal_acceptance/Snakefile" +# include: "benchmarks/nhcal_basic_distribution/Snakefile" +include: "benchmarks/nhcal_sampling_fraction/Snakefile" use_s3 = config["remote_provider"].lower() == "s3" use_xrootd = config["remote_provider"].lower() == "xrootd" diff --git a/benchmarks/nhcal_acceptance/Snakefile b/benchmarks/nhcal_acceptance/Snakefile new file mode 100644 index 00000000..ebb469a3 --- /dev/null +++ b/benchmarks/nhcal_acceptance/Snakefile @@ -0,0 +1,57 @@ +import os + +DETECTOR_PATH = os.environ["DETECTOR_PATH"] + +rule nhcal_acceptance_simulate: + output: + "sim_output/nhcal_acceptance/E{ENERGY}GeV/sim_{DETECTOR_CONFIG}.{INDEX}.edm4hep.root", + params: + N_EVENTS=10000, + shell: + """ +set -m +mkdir -p sim_output/nhcal_acceptance/E{wildcards.ENERGY}GeV +exec ddsim \ + --compactFile {DETECTOR_PATH}/{wildcards.DETECTOR_CONFIG}.xml \ + --numberOfEvents {params.N_EVENTS} \ + --random.seed $RANDOM \ + --enableGun \ + -v WARNING \ + --gun.particle pi- \ + --gun.thetaMin 120*degree \ + --gun.thetaMax 180*degree \ + --gun.distribution uniform \ + --gun.energy "{wildcards.ENERGY}*GeV" \ + --outputFile {output} +""" + + +rule nhcal_acceptance_combine: + input: + lambda wildcards: expand( + "sim_output/nhcal_acceptance/E{ENERGY}GeV/sim_{DETECTOR_CONFIG}.{INDEX:02d}.edm4hep.root", + DETECTOR_CONFIG=wildcards.DETECTOR_CONFIG, + ENERGY=wildcards.ENERGY, + INDEX=range(int(wildcards.N)), + ), + wildcard_constraints: + N=r"\d+", + ENERGY=r"\d+" + output: + f"sim_output/nhcal_acceptance/sim_{{DETECTOR_CONFIG}}_E{{ENERGY}}GeV_combined_{{N}}files.edm4hep.root", + shell: + """ +hadd -f {output} {input} +""" + +rule nhcal_acceptance_analysis: + input: + combined="sim_output/nhcal_acceptance/sim_{DETECTOR_CONFIG}_E{ENERGY}GeV_combined_{N}files.edm4hep.root", + script="benchmarks/nhcal_acceptance/scripts/acceptance_analysis.cxx", + output: + png=f"results/nhcal_acceptance/analysis_{{DETECTOR_CONFIG}}_E{{ENERGY}}GeV_combined_{{N}}files.png", + pdf=f"results/nhcal_acceptance/analysis_{{DETECTOR_CONFIG}}_E{{ENERGY}}GeV_combined_{{N}}files.pdf", + shell: + """ + root -l -b -q '{input.script}("{input.combined}","{output.pdf}","{output.png}")' +""" \ No newline at end of file diff --git a/benchmarks/nhcal_acceptance/config.yml b/benchmarks/nhcal_acceptance/config.yml new file mode 100644 index 00000000..5eea45bd --- /dev/null +++ b/benchmarks/nhcal_acceptance/config.yml @@ -0,0 +1,34 @@ +sim:nhcal_acceptance: + extends: .det_benchmark + stage: simulate + parallel: + matrix: + - ENERGY: ["1GeV", "5GeV", "10GeV"] + INDEX: ["00","01","02","03","04","05","06","07","08","09"] + script: + - snakemake --cores 5 sim_output/nhcal_acceptance/E${ENERGY}/sim_epic_backward_hcal_only.${INDEX}.edm4hep.root + +bench:nhcal_acceptance_analysis: + extends: .det_benchmark + stage: benchmarks + needs: + - "sim:nhcal_acceptance" + parallel: + matrix: + - ENERGY: ["1GeV", "5GeV", "10GeV"] + script: + - snakemake --cores 1 results/nhcal_acceptance/analysis_epic_backward_hcal_only_E${ENERGY}_combined_10files.pdf + +collect_results:nhcal_acceptance: + extends: .det_benchmark + stage: collect + needs: + - "bench:nhcal_acceptance_analysis" + parallel: + matrix: + - ENERGY: ["1GeV", "5GeV", "10GeV"] + script: + - ls -lrht + - mv results{,_save}/ + - snakemake $SNAKEMAKE_FLAGS --cores 1 --delete-all-output results/nhcal_acceptance/analysis_epic_backward_hcal_only_E${ENERGY}_combined_10files.pdf + - mv results{_save,}/ \ No newline at end of file diff --git a/benchmarks/nhcal_acceptance/scripts/acceptance_analysis.cxx b/benchmarks/nhcal_acceptance/scripts/acceptance_analysis.cxx new file mode 100644 index 00000000..d8248894 --- /dev/null +++ b/benchmarks/nhcal_acceptance/scripts/acceptance_analysis.cxx @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +int acceptance_analysis(TString filename, string outname_pdf, string outname_png) +{ + TChain *chain = new TChain("events"); + chain->Add(filename); + + TTreeReader reader(chain); + + TTreeReaderArray mc_pdg(reader, "MCParticles.PDG"); + TTreeReaderArray mc_genStatus(reader, "MCParticles.generatorStatus"); + TTreeReaderArray mc_px(reader, "MCParticles.momentum.x"); + TTreeReaderArray mc_py(reader, "MCParticles.momentum.y"); + TTreeReaderArray mc_pz(reader, "MCParticles.momentum.z"); + + TTreeReaderArray contrib_particle_idx(reader, "_HcalEndcapNHitsContributions_particle.index"); + TTreeReaderArray contrib_particle_cid(reader, "_HcalEndcapNHitsContributions_particle.collectionID"); + + int nEtaBins = 100; + int nPhiBins = 100; + double etaMin = -5, etaMax = 0; + + TH2D* hEtaPhiAll = new TH2D("hEtaPhiAll", "All #pi- (status==1); #eta[1]; #phi[rad]", + nEtaBins, etaMin, etaMax, nPhiBins, -TMath::Pi(), TMath::Pi()); + + TH2D* hEtaPhiDetected = new TH2D("hEtaPhiDetected", "#pi- detected in nHCal; #eta[1]; #phi[rad]", + nEtaBins, etaMin, etaMax, nPhiBins, -TMath::Pi(), TMath::Pi()); + + while (reader.Next()) + { + map> pi_minus_eta_phi; + set detected; + for (size_t i = 0; i < mc_pdg.GetSize(); ++i) + { + if (mc_pdg[i] == -211 && mc_genStatus[i] == 1) + { + float px = mc_px[i]; + float py = mc_py[i]; + float pz = mc_pz[i]; + + float p = sqrt(px * px + py * py + pz * pz); + float eta = 0.5 * log((p + pz) / (p - pz + 1e-8)); + float phi = atan2(py, px); + + hEtaPhiAll->Fill(eta, phi); + pi_minus_eta_phi[i] = make_pair(eta, phi); + } + } + + for (size_t i = 0; i < contrib_particle_idx.GetSize(); i++) { + int idx = contrib_particle_idx[i]; + if (pi_minus_eta_phi.count(idx)) { + detected.insert(idx); + } + } + + for (auto idx : detected) { + auto [eta, phi] = pi_minus_eta_phi[idx]; + hEtaPhiDetected->Fill(eta, phi); + } + } + + TH2D* hAcceptance = (TH2D*)hEtaPhiAll->Clone("hAcceptance"); + hAcceptance->Divide(hEtaPhiDetected); + hAcceptance->SetTitle("#pi- detected/All"); + hAcceptance->SetMinimum(0); + hAcceptance->SetMaximum(1); + + TCanvas *canvas = new TCanvas("canvas", "pi- All", 1600, 600); + canvas->Divide(3,1); + canvas->cd(1); + hEtaPhiAll->Draw("COLZ"); + canvas->cd(2); + hEtaPhiDetected->Draw("COLZ"); + canvas->cd(3); + hAcceptance->Draw("COLZ"); + + canvas->SaveAs(outname_pdf.c_str()); + canvas->SaveAs(outname_png.c_str()); + + return 0; +} + + diff --git a/benchmarks/nhcal_basic_distribution/Snakefile b/benchmarks/nhcal_basic_distribution/Snakefile new file mode 100644 index 00000000..6c823e43 --- /dev/null +++ b/benchmarks/nhcal_basic_distribution/Snakefile @@ -0,0 +1,57 @@ +import os + +DETECTOR_PATH = os.environ["DETECTOR_PATH"] + +rule nhcal_basic_distribution_simulate: + output: + "sim_output/nhcal_basic_distribution/E{ENERGY}GeV/sim_{DETECTOR_CONFIG}.{INDEX}.edm4hep.root", + params: + N_EVENTS=10000, + shell: + """ +set -m +mkdir -p sim_output/nhcal_basic_distribution/E{wildcards.ENERGY}GeV +exec ddsim \ + --compactFile {DETECTOR_PATH}/{wildcards.DETECTOR_CONFIG}.xml \ + --numberOfEvents {params.N_EVENTS} \ + --random.seed $RANDOM \ + --enableGun \ + -v WARNING \ + --gun.particle neutron \ + --gun.thetaMin 120*degree \ + --gun.thetaMax 180*degree \ + --gun.distribution uniform \ + --gun.energy "{wildcards.ENERGY}*GeV" \ + --outputFile {output} +""" + + +rule nhcal_basic_distribution_combine: + input: + lambda wildcards: expand( + "sim_output/nhcal_basic_distribution/E{ENERGY:.1f}GeV/sim_{DETECTOR_CONFIG}.{INDEX:02d}.edm4hep.root", + DETECTOR_CONFIG=wildcards.DETECTOR_CONFIG, + ENERGY=float(wildcards.ENERGY), + INDEX=range(int(wildcards.N)), + ), + wildcard_constraints: + N=r"\d+", + ENERGY=r"\d+(\.\d+)?" + output: + f"sim_output/nhcal_basic_distribution/sim_{{DETECTOR_CONFIG}}_E{{ENERGY}}GeV_combined_{{N}}files.edm4hep.root", + shell: + """ +hadd -f {output} {input} +""" + +rule nhcal_basic_distribution_analysis: + input: + combined="sim_output/nhcal_basic_distribution/sim_{DETECTOR_CONFIG}_E{ENERGY}GeV_combined_{N}files.edm4hep.root", + script="benchmarks/nhcal_basic_distribution/scripts/basic_distribution_analysis.cxx", + output: + pdf=f"results/nhcal_basic_distribution/analysis_{{DETECTOR_CONFIG}}_E{{ENERGY}}GeV_combined_{{N}}files.pdf", + png=f"results/nhcal_basic_distribution/analysis_{{DETECTOR_CONFIG}}_E{{ENERGY}}GeV_combined_{{N}}files.png", + shell: + """ + root -l -b -q '{input.script}("{input.combined}","{output.pdf}","{output.png}")' +""" \ No newline at end of file diff --git a/benchmarks/nhcal_basic_distribution/config.yml b/benchmarks/nhcal_basic_distribution/config.yml new file mode 100644 index 00000000..5acd773c --- /dev/null +++ b/benchmarks/nhcal_basic_distribution/config.yml @@ -0,0 +1,59 @@ +sim:nhcal_basic_distribution: + extends: .det_benchmark + stage: simulate + parallel: + matrix: + - ENERGY: ["0.5GeV", "0.7GeV", "1.0GeV", "2.0GeV", "5.0GeV"] + INDEX: ["00","01","02","03","04","05","06","07","08","09"] + script: + - snakemake --cores 5 sim_output/nhcal_basic_distribution/E${ENERGY}/sim_epic_backward_hcal_only.${INDEX}.edm4hep.root + +sim:nhcal_basic_distribution_full: + extends: .det_benchmark + stage: simulate + parallel: + matrix: + - ENERGY: ["0.5GeV", "0.7GeV", "1.0GeV", "2.0GeV", "5.0GeV"] + INDEX: ["00","01","02","03","04","05","06","07","08","09"] + script: + - snakemake --cores 5 sim_output/nhcal_basic_distribution/E${ENERGY}/sim_epic_full.${INDEX}.edm4hep.root + +bench:nhcal_basic_distribution_analysis: + extends: .det_benchmark + stage: benchmarks + needs: + - "sim:nhcal_basic_distribution" + parallel: + matrix: + - ENERGY: ["0.5GeV", "0.7GeV", "1.0GeV", "2.0GeV", "5.0GeV"] + script: + - snakemake --cores 1 results/nhcal_basic_distribution/analysis_epic_backward_hcal_only_E${ENERGY}_combined_10files.pdf + +bench:nhcal_basic_distribution_analysis_full: + extends: .det_benchmark + stage: benchmarks + needs: + - "sim:nhcal_basic_distribution_full" + parallel: + matrix: + - ENERGY: ["0.5GeV", "0.7GeV", "1.0GeV", "2.0GeV", "5.0GeV"] + script: + - snakemake --cores 1 results/nhcal_basic_distribution/analysis_epic_full_E${ENERGY}_combined_10files.pdf + + +collect_results:nhcal_basic_distribution: + extends: .det_benchmark + stage: collect + needs: + - "bench:nhcal_basic_distribution_analysis" + - "bench:nhcal_basic_distribution_analysis_full" + parallel: + matrix: + - ENERGY: ["0.5GeV", "0.7GeV", "1.0GeV", "2.0GeV", "5.0GeV"] + DETECTOR_CONFIG: ["epic_backward_hcal_only", "epic_full"] + script: + - ls -lrht + - mv results{,_save}/ + - snakemake $SNAKEMAKE_FLAGS --cores 1 --delete-all-output results/nhcal_basic_distribution/analysis_${DETECTOR_CONFIG}_E${ENERGY}_combined_10files.pdf + - mv results{_save,}/ + \ No newline at end of file diff --git a/benchmarks/nhcal_basic_distribution/scripts/basic_distribution_analysis.cxx b/benchmarks/nhcal_basic_distribution/scripts/basic_distribution_analysis.cxx new file mode 100644 index 00000000..c29d5191 --- /dev/null +++ b/benchmarks/nhcal_basic_distribution/scripts/basic_distribution_analysis.cxx @@ -0,0 +1,231 @@ +#include +#include +#include +#include +#include + +#include "ROOT/RDataFrame.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TROOT.h" +#include "TRandom.h" +#include "TH3.h" + + +#include "DD4hep/Detector.h" +#include "DDRec/CellIDPositionConverter.h" + +#include +#include +#include "podio/ROOTReader.h" +//#include +#include "podio/CollectionIDTable.h" +#include "podio/ObjectID.h" + +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/MCParticleCollectionData.h" +#include "edm4hep/MCParticle.h" +#include "edm4hep/MCParticleData.h" + +#include "edm4hep/SimCalorimeterHitCollectionData.h" +#include "edm4hep/SimCalorimeterHitCollection.h" +#include "edm4hep/SimCalorimeterHitData.h" +#include "edm4hep/SimCalorimeterHit.h" + +#include "edm4hep/CalorimeterHit.h" +#include "edm4hep/CalorimeterHitCollectionData.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/CalorimeterHitData.h" +#include "edm4hep/CalorimeterHit.h" +#include "edm4hep/CalorimeterHitObj.h" + +#include "edm4eic/ClusterCollection.h" +#include "edm4eic/Cluster.h" +#include "edm4eic/ClusterData.h" + +#include "edm4eic/CalorimeterHit.h" +#include "edm4eic/CalorimeterHitCollectionData.h" +#include "edm4eic/CalorimeterHitCollection.h" +#include "edm4eic/CalorimeterHitData.h" +#include "edm4eic/CalorimeterHit.h" +#include "edm4eic/CalorimeterHitObj.h" + + +#include +#include + +// #include "FileList.h" +// #include "EICutil.h" +// #include "BasicUtil.h" + +// #pragma link C++ class vector+; +// #pragma link C++ class vector+; +// #pragma link C++ class vector+; + +using namespace std; +using namespace ROOT; +using namespace TMath; +using namespace edm4hep; + +int basic_distribution_analysis(const string &filename, string outname_pdf, string outname_png) +{ + podio::ROOTReader *reader = new podio::ROOTReader(); + reader->openFile(filename); + unsigned nEvents = reader->getEntries("events"); + cout << "Number of events: " << nEvents << endl; + + vector xPosition; + vector yPosition; + vector zPosition; + vector rPosition; + vector energy; + vector totalEventEnergy; + vector totalEventHits; + vector zLayerValues; + vector nHitsPerLayer; + vector nEnergyPerLayer; + + for (unsigned ev = 0; ev < nEvents; ev++) + { + auto frameData = reader->readNextEntry(podio::Category::Event); + if (!frameData) + { + cerr << "Invalid FrameData at event " << ev << endl; + continue; + } + + podio::Frame frame(std::move(frameData)); + + auto& hits = frame.get("HcalEndcapNHits"); + if (!hits.isValid()) + { + cerr << "HcalEndcapNHits collection is not valid!" << endl; + } + + map> layerData; + double totalEnergy = 0; + int totalHits = 0; + + for (const auto& hit : hits) + { + totalHits++; + energy.push_back(hit.getEnergy()); + totalEnergy += hit.getEnergy(); + + auto pos = hit.getPosition(); + xPosition.push_back(pos.x); + yPosition.push_back(pos.y); + zPosition.push_back(pos.z); + rPosition.push_back(sqrt(pos.x * pos.x + pos.y * pos.y)); + + double zBin = round(pos.z); + layerData[zBin].first++; + layerData[zBin].second += hit.getEnergy(); + } + + totalEventEnergy.push_back(totalEnergy); + totalEventHits.push_back(totalHits); + + for (const auto& [zValue, stats] : layerData) + { + zLayerValues.push_back(zValue); + nHitsPerLayer.push_back(stats.first); + nEnergyPerLayer.push_back(stats.second); + } + + } + + auto minmax_xPosition = minmax_element(xPosition.begin(), xPosition.end()); + auto minmax_yPosition = minmax_element(yPosition.begin(), yPosition.end()); + auto minmax_zPosition = minmax_element(zPosition.begin(), zPosition.end()); + auto minmax_rPosition = minmax_element(rPosition.begin(), rPosition.end()); + auto minmax_totalEventEnergy = minmax_element(totalEventEnergy.begin(), totalEventEnergy.end()); + auto minmax_totalEventHits = minmax_element(totalEventHits.begin(), totalEventHits.end()); + auto minmax_energy = minmax_element(energy.begin(), energy.end()); + auto minmax_zLayerValues = minmax_element(zLayerValues.begin(), zLayerValues.end()); + auto minmax_nHitsPerLayer = minmax_element(nHitsPerLayer.begin(), nHitsPerLayer.end()); + auto minmax_nEnergyPerLayer = minmax_element(nEnergyPerLayer.begin(), nEnergyPerLayer.end()); + + int nbins = nEvents/1000; + + TH1D *h_energyTotal = new TH1D("h_energyTotal", "Total Energy per Event; Energy per Event", + nbins/2, *minmax_totalEventEnergy.first, *minmax_totalEventEnergy.second); + TH2D *h_layerEnergy = new TH2D("h_layerEnergy", "Energy in Layers (Z); Z; Energy", + nbins/5, *minmax_zLayerValues.first, *minmax_zLayerValues.second, + nbins/4, *minmax_nEnergyPerLayer.first, *minmax_nEnergyPerLayer.second); + TProfile *p_layerEnergy = new TProfile("p_layerEnergy", "Energy in Layers (Z); Z; Mean Energy", + nbins/5, *minmax_zLayerValues.first, *minmax_zLayerValues.second); + TH1D *h_hitCount = new TH1D("h_hitCount", "Number of Hits per Event; Hits per Event", + nbins/2, *minmax_totalEventHits.first, *minmax_totalEventHits.second); + TH2D *h_layerHits = new TH2D("h_layerHits", "Number of Hits in Layers (Z); Layer(Z); Hits", + nbins/5, *minmax_zLayerValues.first, *minmax_zLayerValues.second, + *minmax_nHitsPerLayer.second, *minmax_nHitsPerLayer.first, *minmax_nHitsPerLayer.second); + TProfile *p_layerHits = new TProfile("p_layerHits", "Number of Hits in Layers (Z); Z; Mean Hits", + nbins/5, *minmax_zLayerValues.first, *minmax_zLayerValues.second); + TH2D *h_XYPos = new TH2D("h_XYPos", "Hits position X,Y;X [mm];Y [mm]", + nbins, *minmax_xPosition.first, *minmax_xPosition.second, + nbins, *minmax_yPosition.first, *minmax_yPosition.second); + TH2D *h_ZRPos = new TH2D("h_ZRPos", "Hits position Z,R;Z [mm];R [mm]", + nbins/5, *minmax_zPosition.first, *minmax_zPosition.second, + nbins, *minmax_rPosition.first, *minmax_rPosition.second); + TH2D *h_XYEnergy = new TH2D("h_XYEnergy", "Hits energy X,Y;X [mm];Y [mm]", + nbins, *minmax_xPosition.first, *minmax_xPosition.second, + nbins, *minmax_yPosition.first, *minmax_yPosition.second); + + for(int i = 0; i < xPosition.size(); i++) + { + + h_XYPos->Fill(xPosition[i], yPosition[i]); + h_ZRPos->Fill(zPosition[i], rPosition[i]); + h_XYEnergy->Fill(xPosition[i], yPosition[i], energy[i]); + } + + for (int i = 0; i < zLayerValues.size(); i++) + { + h_layerHits->Fill(zLayerValues[i], nHitsPerLayer[i]); + p_layerHits->Fill(zLayerValues[i], nHitsPerLayer[i]); + + h_layerEnergy->Fill(zLayerValues[i], nEnergyPerLayer[i]); + p_layerEnergy->Fill(zLayerValues[i], nEnergyPerLayer[i]); + } + + for(int i = 0; i < nEvents; i++) + { + h_energyTotal->Fill(totalEventEnergy[i]); + h_hitCount->Fill(totalEventHits[i]); + } + + gStyle->SetPadLeftMargin(0.13); + + TCanvas *canvas = new TCanvas("canvas", "canvas", 1600, 800); + canvas->Divide(4,2); + canvas->cd(1); + h_energyTotal->Draw(); + canvas->cd(2); + h_layerEnergy->Draw("COLZ"); + p_layerEnergy->Draw("SAME"); + canvas->cd(3); + h_hitCount->Draw(); + canvas->cd(4); + h_layerHits->Draw("COLZ"); + p_layerHits->Draw("SAME"); + canvas->cd(5); + h_XYPos->Draw("COLZ"); + canvas->cd(6); + h_ZRPos->Draw("COLZ"); + canvas->cd(7); + h_XYEnergy->Draw("COLZ"); + + canvas->SaveAs(outname_pdf.c_str()); + canvas->SaveAs(outname_png.c_str()); + + return 0; +} diff --git a/benchmarks/nhcal_sampling_fraction/Snakefile b/benchmarks/nhcal_sampling_fraction/Snakefile new file mode 100644 index 00000000..955b099f --- /dev/null +++ b/benchmarks/nhcal_sampling_fraction/Snakefile @@ -0,0 +1,56 @@ +import os + +DETECTOR_PATH = os.environ["DETECTOR_PATH"] +DETECTOR_CONFIG = "epic_backward_hcal_only.xml" + +rule nhcal_sampling_fraction_simulate: + output: + "sim_output/nhcal_sampling_fraction/{PARTICLE}/E{ENERGY}GeV/sim.edm4hep.root", + params: + N_EVENTS=1000, + shell: + """ +set -m +mkdir -p sim_output/nhcal_sampling_fraction/{wildcards.PARTICLE}/E{wildcards.ENERGY}GeV +exec ddsim \ + --compactFile {DETECTOR_PATH}/{DETECTOR_CONFIG} \ + --numberOfEvents {params.N_EVENTS} \ + --random.seed $RANDOM \ + --enableGun \ + -v WARNING \ + --gun.particle {wildcards.PARTICLE} \ + --gun.thetaMin 120*degree \ + --gun.thetaMax 180*degree \ + --gun.distribution uniform \ + --gun.energy "{wildcards.ENERGY}*GeV" \ + --outputFile {output} +""" + + +rule nhcal_sampling_fraction_combine: + input: + lambda wildcards: expand( + "sim_output/nhcal_sampling_fraction/{PARTICLE}/E{ENERGY}GeV/sim.edm4hep.root", + ENERGY=["1", "2", "5", "10"], + PARTICLE=["pi-", "neutron", "e-"], + ), + wildcard_constraints: + ENERGY=r"\d+" + output: + f"sim_output/nhcal_sampling_fraction/sim_combined.edm4hep.root", + shell: + """ +hadd -f {output} {input} +""" + +rule nhcal_sampling_fraction_analysis: + input: + combined="sim_output/nhcal_sampling_fraction/sim_combined.edm4hep.root", + script="benchmarks/nhcal_sampling_fraction/scripts/sampling_fraction_analysis.cxx", + output: + pdf=f"results/nhcal_sampling_fraction/analysis.pdf", + png=f"results/nhcal_sampling_fraction/analysis.png", + shell: + """ + root -l -b -q '{input.script}("{input.combined}","{output.pdf}","{output.png}","{DETECTOR_PATH}/{DETECTOR_CONFIG}")' +""" \ No newline at end of file diff --git a/benchmarks/nhcal_sampling_fraction/config.yml b/benchmarks/nhcal_sampling_fraction/config.yml new file mode 100644 index 00000000..8c1e4614 --- /dev/null +++ b/benchmarks/nhcal_sampling_fraction/config.yml @@ -0,0 +1,29 @@ +sim:nhcal_sampling_fraction: + extends: .det_benchmark + stage: simulate + parallel: + matrix: + - ENERGY: ["1GeV", "2GeV", "5GeV", "10GeV"] + PARTICLE: ["pi-", "neutron", "e-"] + script: + - snakemake --cores 5 sim_output/nhcal_sampling_fraction/${PARTICLE}/E${ENERGY}/sim.edm4hep.root + +bench:nhcal_sampling_fraction: + extends: .det_benchmark + stage: benchmarks + needs: + - "sim:nhcal_sampling_fraction" + script: + - snakemake --cores 1 results/nhcal_sampling_fraction/analysis.pdf + +collect_results:nhcal_sampling_fraction: + extends: .det_benchmark + stage: collect + needs: + - "bench:nhcal_sampling_fraction" + script: + - ls -lrht + - mv results{,_save}/ + - snakemake $SNAKEMAKE_FLAGS --cores 1 --delete-all-output results/nhcal_sampling_fraction/analysis.pdf + - mv results{_save,}/ + \ No newline at end of file diff --git a/benchmarks/nhcal_sampling_fraction/scripts/sampling_fraction_analysis.cxx b/benchmarks/nhcal_sampling_fraction/scripts/sampling_fraction_analysis.cxx new file mode 100644 index 00000000..a194a214 --- /dev/null +++ b/benchmarks/nhcal_sampling_fraction/scripts/sampling_fraction_analysis.cxx @@ -0,0 +1,189 @@ +#include +#include +#include +#include +#include + +#include "ROOT/RDataFrame.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TROOT.h" +#include "TRandom.h" +#include "TH3.h" + + +#include "DD4hep/Detector.h" +#include "DDRec/CellIDPositionConverter.h" + +#include +#include +#include "podio/ROOTReader.h" +//#include +#include "podio/CollectionIDTable.h" +#include "podio/ObjectID.h" + +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/MCParticleCollectionData.h" +#include "edm4hep/MCParticle.h" +#include "edm4hep/MCParticleData.h" + +#include "edm4hep/SimCalorimeterHitCollectionData.h" +#include "edm4hep/SimCalorimeterHitCollection.h" +#include "edm4hep/SimCalorimeterHitData.h" +#include "edm4hep/SimCalorimeterHit.h" + +#include "edm4hep/CalorimeterHit.h" +#include "edm4hep/CalorimeterHitCollectionData.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/CalorimeterHitData.h" +#include "edm4hep/CalorimeterHit.h" +#include "edm4hep/CalorimeterHitObj.h" + +#include "edm4eic/ClusterCollection.h" +#include "edm4eic/Cluster.h" +#include "edm4eic/ClusterData.h" + +#include "edm4eic/CalorimeterHit.h" +#include "edm4eic/CalorimeterHitCollectionData.h" +#include "edm4eic/CalorimeterHitCollection.h" +#include "edm4eic/CalorimeterHitData.h" +#include "edm4eic/CalorimeterHit.h" +#include "edm4eic/CalorimeterHitObj.h" + +#include +#include + +using namespace std; +using namespace ROOT; +using namespace TMath; +using namespace edm4hep; + +dd4hep::Detector* det = NULL; + +int sampling_fraction_analysis(const string &filename, string outname_pdf, string outname_png, TString compact_file) +{ + + podio::ROOTReader *reader = new podio::ROOTReader(); + reader->openFile(filename); + unsigned nEvents = reader->getEntries("events"); + cout << "Number of events: " << nEvents << endl; + + det = &(dd4hep::Detector::getInstance()); + det->fromCompact(compact_file.Data()); + det->volumeManager(); + det->apply("DD4hepVolumeManager", 0, 0); + + dd4hep::rec::CellIDPositionConverter cellid_converter(*det); + auto idSpec = det->readout("HcalEndcapNHits").idSpec(); + auto decoder = idSpec.decoder(); + const int slice_index = decoder->index("slice"); + if (slice_index < 0) { + cerr << "ERROR: 'slice' field not found in cell ID spec!" << endl; + return 1; + } + + TH2D *h_sampF_e = new TH2D("h_sampF_e", "nHCal sampling fraction vs. energy (e-); E [GeV]; sampling fraction; counts", + 50, 0.0, 12.0, 50, 0.0, 1.0); + TProfile *p_sampF_e = new TProfile("p_sampF_e", "nHCal sampling fraction vs. energy (e-); E [GeV]; sampling fraction", + 50, 0.0, 12.0, 0.0, 1.0); + + TH2D *h_sampF_n = new TH2D("h_sampF_n", "nHCal sampling fraction vs. energy (neutron); E [GeV]; sampling fraction; counts", + 50, 0.0, 12.0, 50, 0.0, 1.0); + TProfile *p_sampF_n = new TProfile("p_sampF_n", "nHCal sampling fraction vs. energy (neutron); E [GeV]; sampling fraction", + 50, 0.0, 12.0, 0.0, 1.0); + + TH2D *h_sampF_pi = new TH2D("h_sampF_pi", "nHCal sampling fraction vs. energy (#pi-); E [GeV]; sampling fraction; counts", + 50, 0.0, 12.0, 50, 0.0, 1.0); + TProfile *p_sampF_pi = new TProfile("p_sampF_pi", "nHCal sampling fraction vs. energy (#pi-); E [GeV]; sampling fraction", + 50, 0.0, 12.0, 0.0, 1.0); + + + + for (unsigned ev = 0; ev < nEvents; ev++) + { + double hit_Esum = 0; + double hit_scint_Esum = 0; + double singlePart_Ekin = 0; + + auto frameData = reader->readNextEntry(podio::Category::Event); + if (!frameData) + { + cerr << "Invalid FrameData at event " << ev << endl; + continue; + } + + podio::Frame frame(std::move(frameData)); + + auto& MCParticles_coll = frame.get("MCParticles"); + auto& SimCalorimeterHit_coll = frame.get("HcalEndcapNHits"); + + if (!SimCalorimeterHit_coll.isValid()) + { + cerr << "HcalEndcapNHits collection is not valid!" << endl; + } + if (!MCParticles_coll.isValid()) + { + cerr << "MCParticles collection is not valid!" << endl; + } + + edm4hep::MCParticle mcpart = MCParticles_coll.at(0); + singlePart_Ekin = mcpart.getEnergy(); //-mcpart.getMass(); + int pdg = mcpart.getPDG(); + + for (const auto& hit : SimCalorimeterHit_coll) + { + const int hit_slice = decoder->get(hit.getCellID(), slice_index); + hit_Esum += hit.getEnergy(); + if(hit_slice == 3) hit_scint_Esum += hit.getEnergy(); + } + + if (pdg == 11) // e- + { + h_sampF_e->Fill(singlePart_Ekin, hit_scint_Esum/hit_Esum); + p_sampF_e->Fill(singlePart_Ekin, hit_scint_Esum/hit_Esum); + } + else if (pdg == -211) // pi- + { + h_sampF_pi->Fill(singlePart_Ekin, hit_scint_Esum/hit_Esum); + p_sampF_pi->Fill(singlePart_Ekin, hit_scint_Esum/hit_Esum); + } + else if (pdg == 2112) // neutron + { + h_sampF_n->Fill(singlePart_Ekin, hit_scint_Esum/hit_Esum); + p_sampF_n->Fill(singlePart_Ekin, hit_scint_Esum/hit_Esum); + } + } + + delete reader; + + TProfile *p_e_over_pi = (TProfile*) p_sampF_e->Clone("p_e_over_pi"); + p_e_over_pi->SetTitle("e/h ratio;E [GeV];e/h"); + p_e_over_pi->Divide(p_sampF_pi); + + TCanvas *canvas = new TCanvas("canvas", "canvas", 1600, 800); + canvas->Divide(2,2); + canvas->cd(1); + h_sampF_e->Draw("COLZ"); + p_sampF_e->Draw("SAME"); + canvas->cd(2); + h_sampF_pi->Draw("COLZ"); + p_sampF_pi->Draw("SAME"); + canvas->cd(3); + h_sampF_n->Draw("COLZ"); + p_sampF_n->Draw("SAME"); + canvas->cd(4); + p_e_over_pi->Draw("HIST"); + + canvas->SaveAs(outname_pdf.c_str()); + canvas->SaveAs(outname_png.c_str()); + + return 0; +}