diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3b7997b011f59e5abc0f49f2b9ec48f498daaa8f..5319f8ebf0f5ac9da5c219ba4cf046821c11001d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -121,6 +121,9 @@ get_data:
     - mkdir "${DETECTOR_CONFIG}"
     - ln -s "${LOCAL_DATA_PATH}/sim_output" "${DETECTOR_CONFIG}/sim_output"
     - ln -s "../results" "${DETECTOR_CONFIG}/results"
+    # cache downloaded artifacts
+    - if [ -d /scratch ]; then mkdir -p /scratch/EPIC; ln -sf /scratch/EPIC ./EPIC; fi
+    - du -hs /scratch/EPIC
     - ls -lrtha
   retry:
     max: 2
diff --git a/benchmarks/tracking_performances/README.md b/benchmarks/tracking_performances/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..acf8844c3d92e6e9fcab53d7c13d3c5850b2a031
--- /dev/null
+++ b/benchmarks/tracking_performances/README.md
@@ -0,0 +1,19 @@
+Shyam Kumar; INFN Bari, Italy; shyam055119@gmail.com
+Method to produce the tracking performances with ePIC tracker
+The scripts can be used to create the debug plots for the momentum resolutions.
+
+To run a full simulation-reconstruction-analysis chain do:
+```
+snakemake -c2 results/tracking_performances/local
+```
+or, referencing it by the rule name:
+```
+snakemake --cores 1 tracking_performance_local
+```
+
+To process an individual campaign do:
+```
+snakemake -c2 results/tracking_performances/24.04.0
+```
+
+It will produce the results with truth/realistic seeding.
diff --git a/benchmarks/tracking_performances/Snakefile b/benchmarks/tracking_performances/Snakefile
index b3ff53738dd1487cac2e0862c877f99c18457c85..f9f04237ec4c980bceff293dca6ace43791b1754 100644
--- a/benchmarks/tracking_performances/Snakefile
+++ b/benchmarks/tracking_performances/Snakefile
@@ -48,17 +48,26 @@ rule tracking_performance_at_momentum:
     input:
         script="benchmarks/tracking_performances/Tracking_Performances.C",
         # TODO pass as a file list?
-        sim=lambda wildcards: expand(
-            "sim_output/tracking_performance/{DETECTOR_CONFIG}/{{PARTICLE}}/{ENERGY}/{PHASE_SPACE}/{{PARTICLE}}_{ENERGY}_{PHASE_SPACE}.{INDEX:04d}.eicrecon.tree.edm4eic.root",
-            DETECTOR_CONFIG="epic_craterlake_tracking_only",
-            ENERGY=f"{float(wildcards.MOMENTUM):.0f}GeV" if float(wildcards.MOMENTUM) >= 1 else f"{float(wildcards.MOMENTUM) * 1000:.0f}MeV",
-            PHASE_SPACE=["3to50deg", "45to135deg", "130to177deg"],
-            INDEX=range(1),
-        ),
+        sim=lambda wildcards:
+          expand(
+              "sim_output/tracking_performance/{DETECTOR_CONFIG}/{{PARTICLE}}/{ENERGY}/{PHASE_SPACE}/{{PARTICLE}}_{ENERGY}_{PHASE_SPACE}.{INDEX:04d}.eicrecon.tree.edm4eic.root",
+              DETECTOR_CONFIG="epic_craterlake_tracking_only",
+              ENERGY=f"{float(wildcards.MOMENTUM):.0f}GeV" if float(wildcards.MOMENTUM) >= 1 else f"{float(wildcards.MOMENTUM) * 1000:.0f}MeV",
+              PHASE_SPACE=["3to50deg", "45to135deg", "130to177deg"],
+              INDEX=range(1),
+          )
+          if wildcards.CAMPAIGN == "local" else
+          expand(
+              "EPIC/RECO/{{CAMPAIGN}}/epic_craterlake/SINGLE/{{PARTICLE}}/{ENERGY}/{PHASE_SPACE}/{{PARTICLE}}_{ENERGY}_{PHASE_SPACE}.{INDEX:04d}.eicrecon.tree.edm4eic.root",
+              DETECTOR_CONFIG="epic_craterlake",
+              ENERGY=f"{float(wildcards.MOMENTUM):.0f}GeV" if float(wildcards.MOMENTUM) >= 1 else f"{float(wildcards.MOMENTUM) * 1000:.0f}MeV",
+              PHASE_SPACE=["3to50deg", "45to135deg", "130to177deg"],
+              INDEX=range(1),
+          ),
     output:
-        "{SEEDING}/pi-/mom/Performances_mom_{MOMENTUM}_mom_resol_{SEEDING_IGNORE}_{PARTICLE}.root",
-        "{SEEDING}/pi-/dca/Performances_dca_{MOMENTUM}_dca_resol_{SEEDING_IGNORE}_{PARTICLE}.root",
-        combined_root=temp("sim_{SEEDING}_{MOMENTUM}_{SEEDING_IGNORE}_{PARTICLE}.root"),
+        "{CAMPAIGN}/{SEEDING}/pi-/mom/Performances_mom_{MOMENTUM}_mom_resol_{SEEDING_IGNORE}_{PARTICLE}.root",
+        "{CAMPAIGN}/{SEEDING}/pi-/dca/Performances_dca_{MOMENTUM}_dca_resol_{SEEDING_IGNORE}_{PARTICLE}.root",
+        combined_root=temp("{CAMPAIGN}/sim_{SEEDING}_{MOMENTUM}_{SEEDING_IGNORE}_{PARTICLE}.root"),
     shell:
         """
 if [[ "{wildcards.SEEDING}" == "truthseed" ]]; then
@@ -67,7 +76,8 @@ elif [[ "{wildcards.SEEDING}" == "realseed" ]]; then
         SEEDING="Seeded"
 fi
 hadd {output.combined_root} {input.sim}
-root -l -b -q {input.script}'("{output.combined_root}", "{wildcards.PARTICLE}", {wildcards.MOMENTUM}, 0.15, "'$SEEDING'")'
+cd {wildcards.CAMPAIGN}
+root -l -b -q ../{input.script}'("../{output.combined_root}", "{wildcards.PARTICLE}", {wildcards.MOMENTUM}, 0.15, "'$SEEDING'")'
 """
 
 
@@ -75,31 +85,40 @@ rule tracking_performance_summary_at_eta:
     input:
         expand(
             [
-                "truthseed/pi-/mom/Performances_mom_{MOMENTUM:.1f}_mom_resol_truth_pi-.root",
-                "truthseed/pi-/dca/Performances_dca_{MOMENTUM:.1f}_dca_resol_truth_pi-.root",
-                "realseed/pi-/mom/Performances_mom_{MOMENTUM:.1f}_mom_resol_realseed_pi-.root",
-                "realseed/pi-/dca/Performances_dca_{MOMENTUM:.1f}_dca_resol_realseed_pi-.root",
+                "{{CAMPAIGN}}/truthseed/pi-/mom/Performances_mom_{MOMENTUM:.1f}_mom_resol_truth_pi-.root",
+                "{{CAMPAIGN}}/truthseed/pi-/dca/Performances_dca_{MOMENTUM:.1f}_dca_resol_truth_pi-.root",
+                "{{CAMPAIGN}}/realseed/pi-/mom/Performances_mom_{MOMENTUM:.1f}_mom_resol_realseed_pi-.root",
+                "{{CAMPAIGN}}/realseed/pi-/dca/Performances_dca_{MOMENTUM:.1f}_dca_resol_realseed_pi-.root",
             ],
-            MOMENTUM=[0.5, 1.0, 2.0, 5.0, 10.0, 15.0],
+            MOMENTUM=[0.5, 1.0, 2.0, 5.0, 10.0, 20.0],
         ),
         script="benchmarks/tracking_performances/doCompare_truth_real_widebins_mom.C",
     output:
         expand(
-            "Debug_Plots/{SEEDING}/pi-/mom/{SEEDING}_mom_resol_mom{MOMENTUM:.1f}_{{ETA_MIN}}_eta_{{ETA_MAX}}.png",
+            "{{CAMPAIGN}}/Debug_Plots/{SEEDING}/pi-/mom/{SEEDING}_mom_resol_mom{MOMENTUM:.1f}_{{ETA_MIN}}_eta_{{ETA_MAX}}.png",
             SEEDING=["real", "truth"],
-            MOMENTUM=[0.5, 1.0, 2.0, 5.0, 10.0, 15.0],
+            MOMENTUM=[0.5, 1.0, 2.0, 5.0, 10.0, 20.0],
         ),
-        "Final_Results/pi-/mom/mom_resol_{ETA_MIN}_eta_{ETA_MAX}.png",
-        "Final_Results/pi-/mom/mom_resol_{ETA_MIN}_eta_{ETA_MAX}.root",
+        "{CAMPAIGN}/Final_Results/pi-/mom/mom_resol_{ETA_MIN}_eta_{ETA_MAX}.png",
+        "{CAMPAIGN}/Final_Results/pi-/mom/mom_resol_{ETA_MIN}_eta_{ETA_MAX}.root",
     shell:
         """
-set +e
-EPIC_VERSION="$(echo $DETECTOR_PATH | sed -n -e 's/.*epic-\([^-]\+\).*/\\1/p')"
-EICRECON_VERSION="$(eicrecon -v | sed -n -e 's/.*\(v[0-9.]\+\).*/\\1/p')"
-set -e
-echo "ePIC version: $EPIC_VERSION"
-echo "EICrecon version: $EICRECON_VERSION"
-root -l -b -q {input.script}'("pi-", {wildcards.ETA_MIN}, {wildcards.ETA_MAX}, 1., true, "'$EPIC_VERSION'", "'$EICRECON_VERSION'")'
+if [[ "{wildcards.CAMPAIGN}" == "local" ]]; then
+	set +e
+	EPIC_VERSION="${{DETECTOR_VERSION:-}}"
+	EICRECON_VERSION="$(eicrecon -v | sed -n -e 's/.*\(v[0-9\.]\+\).*/\\1/p')"
+	# Legacy detection
+	: ${{EPIC_VERSION:="$(echo $DETECTOR_PATH | sed -n -e 's/.*epic-\([^-/]\+\).*/\\1/p')"}}
+	set -e
+
+	echo "ePIC version: $EPIC_VERSION"
+	echo "EICrecon version: $EICRECON_VERSION"
+	EXTRA_LEGEND="ePIC $EPIC_VERSION / EICrecon $EICRECON_VERSION"
+else
+	EXTRA_LEGEND="ePIC Simulation {wildcards.CAMPAIGN}"
+fi
+cd {wildcards.CAMPAIGN}
+root -l -b -q ../{input.script}'("pi-", {wildcards.ETA_MIN}, {wildcards.ETA_MAX}, 1., true, "'"$EXTRA_LEGEND"'")'
 """
 
 
@@ -109,15 +128,34 @@ rule tracking_performance:
     input:
         expand(
             [
-                "Final_Results/pi-/mom/mom_resol_{ETA_BIN}.png",
-                "Final_Results/pi-/mom/mom_resol_{ETA_BIN}.root",
+                "{{CAMPAIGN}}/Final_Results/pi-/mom/mom_resol_{ETA_BIN}.png",
+                "{{CAMPAIGN}}/Final_Results/pi-/mom/mom_resol_{ETA_BIN}.root",
             ],
             ETA_BIN=[f"{eta_min:.1f}_eta_{eta_max:.1f}" for eta_min, eta_max in zip(TRACKING_PERFORMANCE_ETA_BINS[:-1], TRACKING_PERFORMANCE_ETA_BINS[1:])],
         ),
     output:
-        directory("results/tracking_performances")
+        directory("results/tracking_performances/{CAMPAIGN}/")
     shell:
         """
 mkdir {output}
 cp {input} {output}
 """
+
+
+rule tracking_performance_local:
+    input:
+        "results/tracking_performances/local",
+
+
+rule tracking_performance_campaigns:
+    input:
+        expand(
+            "results/tracking_performances/{CAMPAIGN}",
+            CAMPAIGN=[
+                "23.10.0",
+                "23.11.0",
+                "23.12.0",
+                "24.03.1",
+                "24.04.0",
+            ],
+        )
diff --git a/benchmarks/tracking_performances/Tracking_Performances.C b/benchmarks/tracking_performances/Tracking_Performances.C
index 6d1b213cc98d2a3d1315830dbd424bd78c133ce7..77fc0202b85dfa8b33fc1f2ce9a57f8a9a6986b7 100644
--- a/benchmarks/tracking_performances/Tracking_Performances.C
+++ b/benchmarks/tracking_performances/Tracking_Performances.C
@@ -34,11 +34,11 @@ void Tracking_Performances(TString filename="tracking_output",TString particle="
    int theta_val[nbins_eta+1] ={3,50,45,135,130,177};
    int nfiles = 100; 
    double eta[nbins_eta+1]={-3.5,-2.5,-1.0,1.0,2.5,3.5};
-   double pt[nbins_eta+1]={0.1,0.5,1.0,2.0,5.0,10.0};
+   double pt[nbins_eta+1]={0.5,1.0,2.0,5.0,10.0,20.1};
    TH1D *histp[nbins_eta]; 
    
-    TH3D *h_d0xy_3d= new TH3D("h_d0xy_3d","Transverse Pointing Resolution",500,-0.1,0.1,70,-3.5,3.5,200,0.,20.);
-    TH3D *h_d0z_3d= new TH3D("h_d0z_3d","Longitudinal Pointing Resolution",500,-0.1,0.1,70,-3.5,3.5,200,0.,20.);
+    TH3D *h_d0xy_3d= new TH3D("h_d0xy_3d","Transverse Pointing Resolution",500,-0.1,0.1,70,-3.5,3.5,201,0.,20.1);
+    TH3D *h_d0z_3d= new TH3D("h_d0z_3d","Longitudinal Pointing Resolution",500,-0.1,0.1,70,-3.5,3.5,201,0.,20.1);
    
    for (int i=0; i<nbins_eta; i++){
    histp[i] = new TH1D(Form("hist_etabin%d",i),Form("hist_etabin%d",i),600,-0.3,0.3);
@@ -82,7 +82,7 @@ void Tracking_Performances(TString filename="tracking_output",TString particle="
       
       if (fabs(ptmc) < pTcut) continue;
 
-      Double_t pmc = charge[j]*sqrt(px_mc[j]*px_mc[j]+py_mc[j]*py_mc[j]+pz_mc[j]*pz_mc[j]); 
+      Double_t pmc = (1./charge[j])*sqrt(px_mc[j]*px_mc[j]+py_mc[j]*py_mc[j]+pz_mc[j]*pz_mc[j]); // 1./(q/p); similar to prec
       Double_t prec = 1./qoverp[j]; 
 
       Double_t pzrec = prec*TMath::Cos(theta[j]);  Double_t pt_rec = sqrt(prec*prec-pzrec*pzrec);  
diff --git a/benchmarks/tracking_performances/config.yml b/benchmarks/tracking_performances/config.yml
index 22290396ba550ecf7aabe9ccce815decd09b08e3..fadeec02e625bb5de03e53ebcbff6e47c3440072 100644
--- a/benchmarks/tracking_performances/config.yml
+++ b/benchmarks/tracking_performances/config.yml
@@ -18,7 +18,7 @@ bench:tracking_performance:
   needs:
     - ["sim:tracking_performance"]
   script:
-    - snakemake --cores 1 tracking_performance
+    - snakemake --cores 1 tracking_performance_local
 
 collect_results:tracking_performance:
   extends: .det_benchmark
@@ -27,3 +27,18 @@ collect_results:tracking_performance:
     - "bench:tracking_performance"
   script:
     - ls -lrht
+
+bench:tracking_performance_campaigns:
+  extends: .det_benchmark
+  stage: benchmarks
+  #when: manual
+  script:
+    - snakemake --cores 1 tracking_performance_campaigns
+
+collect_results:tracking_performance_campaigns:
+  extends: .det_benchmark
+  stage: collect
+  needs:
+    - "bench:tracking_performance_campaigns"
+  script:
+    - ls -lrht
diff --git a/benchmarks/tracking_performances/doCompare_truth_real_widebins_mom.C b/benchmarks/tracking_performances/doCompare_truth_real_widebins_mom.C
index 7b8e799b8acd536293ca9da87307c880e315c18c..153f536016853d891255bab9bec0c2ae5730f3ec 100644
--- a/benchmarks/tracking_performances/doCompare_truth_real_widebins_mom.C
+++ b/benchmarks/tracking_performances/doCompare_truth_real_widebins_mom.C
@@ -10,7 +10,7 @@
 #define mpi 0.139  // 1.864 GeV/c^2
 
 void draw_req_Mom(double etamin, double etamax, double xmin=0., double xmax=0.);
-void doCompare_truth_real_widebins_mom(TString particle = "pi-",double etamin=-1.0, double etamax=1.0, double range =0.3, Bool_t drawreq=1, TString epic ="", TString eicrecon = "") // name = p, pt for getting p or pt dependence fitted results
+void doCompare_truth_real_widebins_mom(TString particle = "pi-",double etamin=-1.0, double etamax=1.0, double range =0.3, Bool_t drawreq=1, TString extra_legend = "") // name = p, pt for getting p or pt dependence fitted results
 {
 
 //=== style of the plot=========
@@ -24,7 +24,7 @@ void doCompare_truth_real_widebins_mom(TString particle = "pi-",double etamin=-1
    gStyle->SetOptStat(1);
   
    const Int_t nfiles = 6;
-   double mom[nfiles] ={0.5,1.0,2.0,5.0,10.0,15.0};
+   double mom[nfiles] ={0.5,1.0,2.0,5.0,10.0,20.0};
    std::vector<double> momV_truth, momV_real, momresolV_truth, err_momresolV_truth, momresolV_real, err_momresolV_real;
    momV_truth.clear(); momV_real.clear(); momresolV_truth.clear(); err_momresolV_truth.clear(); momresolV_real.clear(); err_momresolV_real.clear();
    TString symbolname = "";
@@ -52,7 +52,8 @@ void doCompare_truth_real_widebins_mom(TString particle = "pi-",double etamin=-1
   lmom = new TLegend(0.65,0.80,0.90,0.93);
   lmom->SetTextSize(0.03);
   lmom->SetBorderSize(0);
-  lmom->SetHeader(Form("%s ePIC(%s/%s): %1.1f < #eta < %1.1f",symbolname.Data(),epic.Data(),eicrecon.Data(),etamin,etamax),"C");
+  lmom->SetHeader(extra_legend.Data(), "C");
+  lmom->AddEntry((TObject*)0, Form("%s, %1.1f < #eta < %1.1f", symbolname.Data(), etamin, etamax), "C");
   
   TF1 *func_truth = new TF1("func_truth","gaus",-0.5,0.5);
   TF1 *func_real = new TF1("func_real","gaus",-0.5,0.5);
@@ -155,8 +156,8 @@ void doCompare_truth_real_widebins_mom(TString particle = "pi-",double etamin=-1
 	mgMom->Add(gr1);
 	mgMom->Add(gr2);
 	c_mom->cd();
-	mgMom->GetXaxis()->SetRangeUser(0.40,15.2);
-	mgMom->GetYaxis()->SetRangeUser(0.,10.0);
+	mgMom->GetXaxis()->SetRangeUser(0.40,20.2);
+	mgMom->GetYaxis()->SetRangeUser(0.0,1.50*TMath::MaxElement(gr2->GetN(),gr2->GetY())); // 50% more of the maximum value on yaxis
 	mgMom->Draw("AP");
 	lmom->AddEntry(gr1,"Truth Seeding");
 	lmom->AddEntry(gr2,"Realistic Seeding");
@@ -165,7 +166,7 @@ void doCompare_truth_real_widebins_mom(TString particle = "pi-",double etamin=-1
 	c_mom->SaveAs(Form("Final_Results/%s/mom/mom_resol_%1.1f_eta_%1.1f.png",particle.Data(),etamin,etamax));
 	
 	// Write the numbers in output file for comparisons
-	outfile<<"ePIC"<<setw(20)<<epic.Data()<<setw(20)<<"EICrecon"<<setw(20)<<eicrecon.Data()<<endl;
+	outfile << extra_legend << endl;
   outfile<<"Etamin"<<setw(20)<<"Etamax"<<setw(20)<<"p (GeV/c) \t"<<setw(20)<<"Resol  #mum (Truth)"<<setw(20)<<"Resol #mum (Real)"<<endl;
   for (Int_t i = 0; i<gr1->GetN(); ++i){
   double x,ytrue, yreal;
diff --git a/benchmarks/tracking_performances/readme.txt b/benchmarks/tracking_performances/readme.txt
deleted file mode 100644
index 4d9badac3c6ec0796f51a56ad6fbaa24836f62e6..0000000000000000000000000000000000000000
--- a/benchmarks/tracking_performances/readme.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Shyam Kumar; INFN Bari, Italy; shyam055119@gmail.com
-Method to produce the tracking performances with ePIC tracker
-The scripts can be used to create the debug plots for the momentum resolutions.
-In the first step enter inside eic-shell and create a directory (your preferred name) there and put all the script inside that.
-Simply run the command source Script_widebin.sh
-It will produce the results with truth/realistic seeding.