diff --git a/Snakefile b/Snakefile
index d645066a69052c7d36350c45d865c4c1ff718ea3..c001f8b08cc33e8b3306cdd1849a6263dcbed9f1 100644
--- a/Snakefile
+++ b/Snakefile
@@ -51,6 +51,7 @@ include: "benchmarks/insert_tau/Snakefile"
include: "benchmarks/femc_electron/Snakefile"
include: "benchmarks/femc_photon/Snakefile"
include: "benchmarks/femc_pi0/Snakefile"
+include: "benchmarks/beamline/Snakefile"
use_s3 = config["remote_provider"].lower() == "s3"
use_xrootd = config["remote_provider"].lower() == "xrootd"
diff --git a/benchmarks/beamline/Snakefile b/benchmarks/beamline/Snakefile
new file mode 100644
index 0000000000000000000000000000000000000000..70eaf753da4eacc3fc841c92c3b110404dba3408
--- /dev/null
+++ b/benchmarks/beamline/Snakefile
@@ -0,0 +1,25 @@
+rule beamline_sim:
+ input:
+ inputfile="/scratch/EIC/Events/el_beam_18.hepmc",
+ 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} \
+ --compactFile $DETECTOR_PATH/epic_ip6_extended.xml \
+ --outputFile {output}
+ """
+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
diff --git a/benchmarks/beamline/analysis.C b/benchmarks/beamline/analysis.C
new file mode 100644
index 0000000000000000000000000000000000000000..a0551139c667e2dc9d069dc300e0f21d5c755adb
--- /dev/null
+++ b/benchmarks/beamline/analysis.C
@@ -0,0 +1,50 @@
+// Script to plot the x and y positions and momentum of beamline particles as they pass through the magnets
+
+#include <iostream>
+#include "DD4hep/Detector.h"
+#include "DDRec/CellIDPositionConverter.h"
+#include "edm4hep/MCParticleCollection.h"
+#include "edm4hep/SimTrackerHit.h"
+#include "edm4hep/SimCalorimeterHit.h"
+#include "ROOT/RDataFrame.hxx"
+#include "ROOT/RDF/RInterface.hxx"
+#include "ROOT/RVec.hxx"
+#include "functors.h"
+
+using RVecS = ROOT::VecOps::RVec<string>;
+using RNode = ROOT::RDF::RNode;
+
+void analysis( std::string inFile = "/scratch/EIC/G4out/beamline/beamlineTest.edm4hep.root",
+ std::string compactName = "/home/simong/EIC/epic/install/share/epic/epic_ip6_extended.xml"){
+
+ //Set implicit multi-threading
+ ROOT::EnableImplicitMT();
+
+ //Load the detector config
+ dd4hep::Detector& detector = dd4hep::Detector::getInstance();
+ detector.fromCompact(compactName);
+
+ ROOT::RDataFrame d0("events",inFile, {"BackwardsBeamlineHits"});
+ RNode d1 = d0;
+ RVecS colNames = d1.GetColumnNames();
+
+ //Get the collection
+ std::string readoutName = "BackwardsBeamlineHits";
+
+ if(Any(colNames==readoutName)){
+
+ auto ids = detector.readout(readoutName).idSpec().fields();
+
+ 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;
+ }
+
+ d1.Snapshot("events","output.root");
+
+}
diff --git a/benchmarks/beamline/functors.h b/benchmarks/beamline/functors.h
new file mode 100644
index 0000000000000000000000000000000000000000..d81b456765f689e8be2a0c63117c1dbe3d2ca79a
--- /dev/null
+++ b/benchmarks/beamline/functors.h
@@ -0,0 +1,36 @@
+#include "DD4hep/Detector.h"
+#include "DDRec/CellIDPositionConverter.h"
+#include "edm4hep/MCParticleCollection.h"
+#include "edm4hep/SimTrackerHit.h"
+#include "edm4hep/SimCalorimeterHit.h"
+
+using RVecHits = ROOT::VecOps::RVec<edm4hep::SimTrackerHitData>;
+
+//-----------------------------------------------------------------------------------------
+// Grab Component functor
+//-----------------------------------------------------------------------------------------
+struct getSubID{
+ getSubID(std::string cname, dd4hep::Detector& det, std::string rname = "BackwardsBeamlineHits") : componentName(cname), detector(det), readoutName(rname){}
+
+ ROOT::VecOps::RVec<int> operator()(const RVecHits& evt) {
+ auto decoder = detector.readout(readoutName).idSpec().decoder();
+ auto indexID = decoder->index(componentName);
+ ROOT::VecOps::RVec<int> result;
+ for(const auto& h: evt) {
+ result.push_back(decoder->get(h.cellID,indexID));
+ }
+ return result;
+ };
+
+ void SetComponent(std::string cname){
+ componentName = cname;
+ }
+ void SetReadout(std::string rname){
+ readoutName = rname;
+ }
+
+ private:
+ std::string componentName;
+ dd4hep::Detector& detector;
+ std::string readoutName;
+};
\ No newline at end of file