diff --git a/benchmarks/beamline/Snakefile b/benchmarks/beamline/Snakefile index 70eaf753da4eacc3fc841c92c3b110404dba3408..94b5c1e779fd1396b07d76eb05f1375f3b49e43d 100644 --- a/benchmarks/beamline/Snakefile +++ b/benchmarks/beamline/Snakefile @@ -1,25 +1,30 @@ rule beamline_sim: input: - inputfile="/scratch/EIC/Events/el_beam_18.hepmc", + macro="beamGPS.mac", output: "/scratch/EIC/G4out/beamline/beamlineTest.edm4hep.root", log: "/scratch/EIC/G4out/beamline/beamlineTest.edm4hep.root.log", - params: - N_EVENTS=10000 shell: """ exec npsim \ - --runType batch \ - --inputFiles {input.inputfile} \ - --random.seed 1234 \ - --numberOfEvents {params.N_EVENTS} \ + --runType run \ + --enableG4GPS \ + --macroFile {input.macro} \ --compactFile $DETECTOR_PATH/epic_ip6_extended.xml \ - --outputFile {output} + --outputFile {output} \ """ -rule beamline_analysis + +rule beamline_analysis: input: "/scratch/EIC/G4out/beamline/beamlineTest.edm4hep.root", output: "/scratch/EIC/ReconOut/beamline/beamlineTestAnalysis.root" - log: \ No newline at end of file + log: + "/scratch/EIC/ReconOut/beamline/beamlineTestAnalysis.root.log" + params: + xml=os.getenv("DETECTOR_PATH")+"/epic_ip6_extended.xml", + shell: + """ + root -l -b -q 'analysis.C("{input}", "{output}", "{params.xml}")' + """ diff --git a/benchmarks/beamline/analysis.C b/benchmarks/beamline/analysis.C index a0551139c667e2dc9d069dc300e0f21d5c755adb..0c4c9465e9434d5e7f32974c928caccd35a6bbf7 100644 --- a/benchmarks/beamline/analysis.C +++ b/benchmarks/beamline/analysis.C @@ -4,22 +4,35 @@ #include "DD4hep/Detector.h" #include "DDRec/CellIDPositionConverter.h" #include "edm4hep/MCParticleCollection.h" -#include "edm4hep/SimTrackerHit.h" -#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/SimTrackerHitCollection.h" +#include "edm4hep/SimCalorimeterHitCollection.h" +#include "edm4hep/Vector3f.h" +#include "edm4hep/Vector3d.h" #include "ROOT/RDataFrame.hxx" #include "ROOT/RDF/RInterface.hxx" #include "ROOT/RVec.hxx" #include "functors.h" +#include "TCanvas.h" +#include "TStyle.h" using RVecS = ROOT::VecOps::RVec<string>; using RNode = ROOT::RDF::RNode; -void analysis( std::string inFile = "/scratch/EIC/G4out/beamline/beamlineTest.edm4hep.root", +void analysis( TString inFile = "/scratch/EIC/G4out/beamline/beamlineTest.edm4hep.root", + TString outFile = "output.root", std::string compactName = "/home/simong/EIC/epic/install/share/epic/epic_ip6_extended.xml"){ + //Set ROOT style + gStyle->SetPadLeftMargin(0.25); // Set left margin + gStyle->SetPadRightMargin(0.15); // Set right margin + gStyle->SetPadTopMargin(0.05); // Set top margin + gStyle->SetPadBottomMargin(0.15);// Set bottom margin + gStyle->SetTitleYOffset(2); // Adjust y-axis title offset + gStyle->SetOptStat(1110); + //Set implicit multi-threading ROOT::EnableImplicitMT(); - + //Load the detector config dd4hep::Detector& detector = dd4hep::Detector::getInstance(); detector.fromCompact(compactName); @@ -27,24 +40,105 @@ void analysis( std::string inFile = "/scratch/EIC/G4out/beamline/beamlineT ROOT::RDataFrame d0("events",inFile, {"BackwardsBeamlineHits"}); RNode d1 = d0; RVecS colNames = d1.GetColumnNames(); + + //Set number of entries to process + // d1 = d1.Range(0,1000); //Get the collection std::string readoutName = "BackwardsBeamlineHits"; + std::cout << "Running lazy RDataframe execution" << std::endl; + if(Any(colNames==readoutName)){ - auto ids = detector.readout(readoutName).idSpec().fields(); + d1 = d1.Define("pipeID",getSubID("pipe",detector),{readoutName}) + .Define("endID",getSubID("end",detector),{readoutName}); + + //global x,y,z position and momentum + d1 = d1.Define("xpos_global","BackwardsBeamlineHits.position.x") + .Define("ypos_global","BackwardsBeamlineHits.position.y") + .Define("zpos_global","BackwardsBeamlineHits.position.z") + .Define("px_global","BackwardsBeamlineHits.momentum.x") + .Define("py_global","BackwardsBeamlineHits.momentum.y") + .Define("pz_global","BackwardsBeamlineHits.momentum.z"); + + d1 = d1.Define("hitPosMom",globalToLocal(detector),{readoutName}) + .Define("xpos","hitPosMom[0]") + .Define("ypos","hitPosMom[1]") + .Define("zpos","hitPosMom[2]") + .Define("xmom","hitPosMom[3]") + .Define("ymom","hitPosMom[4]") + .Define("zmom","hitPosMom[5]"); - for(auto &[key,id]: ids){ - TString colName = key+"ID"; - d1 = d1.Define(colName,getSubID(key,detector),{readoutName}); - } } else{ std::cout << "Collection " << readoutName << " not found in file" << std::endl; return; + } + + std::cout << "Executing Analysis and creating histograms" << std::endl; + + //Create array of histogram results + std::map<TString,ROOT::RDF::RResultPtr<TH2D>> hHistsxpx; + std::map<TString,ROOT::RDF::RResultPtr<TH2D>> hHistsypy; + + + //Create histograms + for(int i=0; i<=7; i++){ + + std::string name = "pipeID"; + name += std::to_string(i); + auto filterDF = d1.Define("xposf","xpos["+std::to_string(i)+"]") + .Define("yposf","ypos["+std::to_string(i)+"]") + .Define("xmomf","xmom["+std::to_string(i)+"]") + .Define("ymomf","ymom["+std::to_string(i)+"]"); + + //Calculate Min and Max values + auto xmin = filterDF.Min("xposf").GetValue(); + auto xmax = filterDF.Max("xposf").GetValue(); + auto ymin = filterDF.Min("yposf").GetValue(); + auto ymax = filterDF.Max("yposf").GetValue(); + auto pxmin = filterDF.Min("xmomf").GetValue(); + auto pxmax = filterDF.Max("xmomf").GetValue(); + auto pymin = filterDF.Min("ymomf").GetValue(); + auto pymax = filterDF.Max("ymomf").GetValue(); + + TString xname = name+";x offset [mm]; x trajectory component"; + TString yname = name+";y offset [mm]; y trajectory component"; + hHistsxpx[name] = filterDF.Histo2D({xname,xname,100,xmin,xmax,100,pxmin,pxmax},"xposf","xmomf"); + hHistsypy[name] = filterDF.Histo2D({yname,yname,100,ymin,ymax,100,pymin,pymax},"yposf","ymomf"); + } - - d1.Snapshot("events","output.root"); + TCanvas *cX = new TCanvas("c1","c1",3000,1600); + cX->Divide(4,2); + + int i=1; + //Write histograms to file + for(auto& h : hHistsxpx){ + cX->cd(i++); + h.second->Draw("colz"); + } + + + TCanvas *cY = new TCanvas("c2","c2",3000,1600); + cY->Divide(4,2); + + i=1; + for(auto& h : hHistsypy){ + cY->cd(i++); + h.second->Draw("colz"); + } + + TFile *f = new TFile(outFile,"RECREATE"); + cX->Write(); + cY->Write(); + + f->Close(); + + std::cout << "Saving events to file" << std::endl; + + // ROOT::RDF::RSnapshotOptions opts; + // opts.fMode = "UPDATE"; + // d1.Snapshot("events",outFile,{"pipeID","endID","xpos","ypos","zpos","xmom","ymom","zmom","xpos_global","ypos_global","zpos_global","px_global","py_global","pz_global"},opts); } diff --git a/benchmarks/beamline/functors.h b/benchmarks/beamline/functors.h index d81b456765f689e8be2a0c63117c1dbe3d2ca79a..ee2414d08aa39c58919f7c4f795337a2c1f081bb 100644 --- a/benchmarks/beamline/functors.h +++ b/benchmarks/beamline/functors.h @@ -1,8 +1,10 @@ #include "DD4hep/Detector.h" #include "DDRec/CellIDPositionConverter.h" #include "edm4hep/MCParticleCollection.h" -#include "edm4hep/SimTrackerHit.h" -#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/SimTrackerHitCollection.h" +#include "edm4hep/SimCalorimeterHitCollection.h" +#include "DD4hep/VolumeManager.h" +#include "TFile.h" using RVecHits = ROOT::VecOps::RVec<edm4hep::SimTrackerHitData>; @@ -33,4 +35,69 @@ struct getSubID{ std::string componentName; dd4hep::Detector& detector; std::string readoutName; +}; + +//----------------------------------------------------------------------------------------- +// Transform global x,y,z position and momentum into local coordinates +//----------------------------------------------------------------------------------------- +struct globalToLocal{ + globalToLocal(dd4hep::Detector& det) : detector(det){ + volumeManager = dd4hep::VolumeManager::getVolumeManager(det); + } + + ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>> operator()(const RVecHits& evt) { + + ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>> result; + ROOT::VecOps::RVec<double> xvec; + ROOT::VecOps::RVec<double> yvec; + ROOT::VecOps::RVec<double> zvec; + ROOT::VecOps::RVec<double> pxvec; + ROOT::VecOps::RVec<double> pyvec; + ROOT::VecOps::RVec<double> pzvec; + + for(const auto& h: evt) { + auto cellID = h.cellID; + // dd4hep::DetElement detelement = volumeManager.lookupDetElement(cellID); + // auto detelement = volumeManager.lookupVolumePlacement(cellID); + auto detelement = volumeManager.lookupDetElement(cellID); + const TGeoMatrix& transform = detelement.nominal().worldTransformation(); + // transform.Print(); + //auto transform = volumeManager.worldTransformation(cellID); + //Convert position to local coordinates + auto pos = h.position; + Double_t globalPos[3] = {pos.x/10, pos.y/10, pos.z/10}; + Double_t localPos[3]; + transform.MasterToLocal(globalPos, localPos); + // std::cout << "Global: " << globalPos[0] << " " << globalPos[1] << " " << globalPos[2] << std::endl; + // std::cout << "Local: " << localPos[0] << " " << localPos[1] << " " << localPos[2] << std::endl; + //Transform global momentum to local coordinates + auto mom = h.momentum; + Double_t globalMom[3] = {mom.x, mom.y, mom.z}; + Double_t localMom[3]; + transform.MasterToLocalVect(globalMom, localMom); + // std::cout << "Global: " << globalMom[0] << " " << globalMom[1] << " " << globalMom[2] << std::endl; + // std::cout << "Local: " << localMom[0] << " " << localMom[1] << " " << localMom[2] << std::endl; + + xvec.push_back(localPos[0]); + yvec.push_back(localPos[1]); + zvec.push_back(localPos[2]); + pxvec.push_back(localMom[0]); + pyvec.push_back(localMom[1]); + pzvec.push_back(localMom[2]); + + } + + result.push_back(xvec); + result.push_back(yvec); + result.push_back(zvec); + result.push_back(pxvec); + result.push_back(pyvec); + result.push_back(pzvec); + + return result; + }; + + private: + dd4hep::Detector& detector; + dd4hep::VolumeManager volumeManager; }; \ No newline at end of file