diff --git a/benchmarks/dvmp/analysis/dvmp.h b/benchmarks/dvmp/analysis/dvmp.h
index 3baf03ad4d9d8213d52ada928b34ed74631fa0e4..20e6b9537a5a7c4478993f1bc74c1a3fb92b042e 100644
--- a/benchmarks/dvmp/analysis/dvmp.h
+++ b/benchmarks/dvmp/analysis/dvmp.h
@@ -17,13 +17,6 @@
 // promoted to the top-level util library
 namespace util {
 
-  // Calculate the 4-vector sum of a given pair of particles
-  inline ROOT::Math::PxPyPzMVector
-  get_sum(const std::pair<ROOT::Math::PxPyPzMVector, ROOT::Math::PxPyPzMVector>& particle_pair)
-  {
-    return (particle_pair.first + particle_pair.second);
-  }
-
   //========================================================================================================
   // for structure functions
 
@@ -36,26 +29,29 @@ namespace util {
   {
     ROOT::Math::PxPyPzMVector q(parts[0] - parts[2]);
     ROOT::Math::PxPyPzMVector P(parts[3]);
-    ROOT::Math::PxPyPzMVector Delta(parts[6] - parts[3]);
+    //ROOT::Math::PxPyPzMVector Delta(parts[6] - parts[3]);//exact jpsi
+    ROOT::Math::PxPyPzMVector Delta(parts[0] - parts[2] - parts[7] - parts[8]);//jpsi->l l' gamma, ignore gamma
 
     double    nu         = q.Dot(P) / P.mass();
     double    Q2         = -q.Dot(q);
     double t = Delta.Dot(Delta);
-    inv_quant quantities = {nu, Q2, Q2 / 2. / P.mass() / nu, t};
+    inv_quant quantities = {nu, Q2, Q2/2./P.mass()/nu, t};
     return quantities;
   }
   
-  //for tracking
-  inline inv_quant calc_inv_quant_rec(const std::vector<ROOT::Math::PxPyPzMVector>& parts, const double pdg_mass){
+ //for Dummy rc
+  inline inv_quant calc_inv_quant_rec(const std::vector<ROOT::Math::PxPyPzMVector>& parts, const double pdg_mass, const double daughter_mass){
     int first = -1;
     int second = -1;
     double best_mass = -1;
-
+    
     // go through all particle combinatorics, calculate the invariant mass
     // for each combination, and remember which combination is the closest
     // to the desired pdg_mass
     for (int i = 0; i < parts.size(); ++i) {
+      if( fabs(parts[i].mass() - daughter_mass)/daughter_mass > 0.01) continue;
       for (int j = i + 1; j < parts.size(); ++j) {
+        if( fabs(parts[j].mass() - daughter_mass)/daughter_mass > 0.01) continue;
         const double new_mass{(parts[i] + parts[j]).mass()};
         if (fabs(new_mass - pdg_mass) < fabs(best_mass - pdg_mass)) {
           first = i;
@@ -64,30 +60,39 @@ namespace util {
         }
       }
     }
-    if (first < 0 || parts.size() < 3 ){
-      inv_quant quantities = {-999., -999., -999., -999.};
+    
+    
+    if (first < 0 || parts.size() < 3 ){      //fewer than 3 candidates 
+      inv_quant quantities = {-99999., -99999., -99999., -99999.};
       return quantities;
     }
+    
+    //construct the beam kinematics
     ROOT::Math::PxPyPzMVector pair_4p(parts[first] + parts[second]);
     ROOT::Math::PxPyPzMVector e1, P;
-    double e1_Energy = sqrt(10.*10. + get_pdg_mass("electron")*get_pdg_mass("electron"));
-    double P_Energy = sqrt(100.*100. + get_pdg_mass("proton")*get_pdg_mass("proton"));
-    e1.SetPxPyPzE(0., 0., -10., e1_Energy);
-    P.SetPxPyPzE(0., 0., 100., P_Energy);
+    //double e1_Energy = sqrt(10.*10. + get_pdg_mass("electron")*get_pdg_mass("electron"));
+    //double P_Energy = sqrt(100.*100. + get_pdg_mass("proton")*get_pdg_mass("proton"));
+    double e1_Energy = sqrt((1.305e-8 - 10.)*(1.305e-8 - 10.) + (0.0005109+9.888e-8)*(0.0005109+9.888e-8));
+    double P_Energy = sqrt((99.995598 + 1.313e-7)*(99.995598 + 1.313e-7) + (0.938272-1.23e-12)*(0.938272-1.23e-12));
+    e1.SetPxPyPzE(0., 0., 1.305e-8 - 10., e1_Energy);
+    P.SetPxPyPzE(0., 0., 99.995598 + 1.313e-7, P_Energy);
     int scatteredIdx = -1;
-    float dp = 10.;
+    
+    //float dp = 10.;
     for(int i = 0 ; i < parts.size(); i++){
-      if(i==first || i==second) continue;
-      ROOT::Math::PxPyPzMVector k_prime(parts[i]);
-      float ptmp = sqrt(parts[i].px()*parts[i].px() + parts[i].py()*parts[i].py() + parts[i].pz()*parts[i].pz());
-      if( (k_prime.px()) * (pair_4p.px()) + (k_prime.py()) * (pair_4p.py()) + (k_prime.pz()) * (pair_4p.pz()) > 0. || ptmp >= 10.) continue; //angle between jpsi and scattered electron < pi/2, 3-momentum mag < 10.
-      if(dp > 10.- ptmp){     //if there are more than one candidate of scattered electron, choose the one with highest 3-momentum mag
+      if(i==first || i==second) continue;   //skip the paired leptons
+      //if( fabs(parts[i].mass() - get_pdg_mass("electron"))/get_pdg_mass("electron") > 0.01) continue;
+      if( fabs(parts[i].mass() - 0.0005109 - 9.888e-8)/(0.0005109 + 9.888e-8) > 0.01) continue;
+      //ROOT::Math::PxPyPzMVector k_prime(parts[i]);  //scattered
+      //float ptmp = sqrt(parts[i].px()*parts[i].px() + parts[i].py()*parts[i].py() + parts[i].pz()*parts[i].pz());
+      //if( (k_prime.px()) * (pair_4p.px()) + (k_prime.py()) * (pair_4p.py()) + (k_prime.pz()) * (pair_4p.pz()) > 0. || ptmp >= 10.) continue; //angle between jpsi and scattered electron < pi/2, 3-momentum mag < 10. 
+      //if(dp > 10.- ptmp){     //if there are more than one candidate of scattered electron, choose the one with highest 3-momentum mag
         scatteredIdx = i;
-        dp = 10. - ptmp;
-      }
+      //  dp = 10. - ptmp;
+      //}
     }
     if(scatteredIdx ==-1){
-      inv_quant quantities = {-999., -999., -999., -999.};
+      inv_quant quantities = {-99999., -99999., -99999., -99999.};
       return quantities;
     }
     ROOT::Math::PxPyPzMVector q(e1 - parts[scatteredIdx]);
@@ -97,15 +102,9 @@ namespace util {
     double Q2 = - q.Dot(q);  
     double t = Delta.Dot(Delta);
     inv_quant quantities = {nu, Q2, Q2/2./P.mass()/nu, t};
-    //inv_quant quantities = {-999., -999., -999., -999.};
     return quantities;
   }
-
-  
-  
   
-  
-
   inline double get_nu(inv_quant quantities) { return quantities.nu / 1000.; }
   inline double get_Q2(inv_quant quantities) { return quantities.Q2; }
   inline double get_x(inv_quant quantities) { return quantities.x; }
diff --git a/benchmarks/dvmp/analysis/vm_invar.cxx b/benchmarks/dvmp/analysis/vm_invar.cxx
index edaa03ad2adb1546f15a1d547c5e75c9685d3e46..21be3710106ac4495b03c26ae5a9d2eed4499b80 100644
--- a/benchmarks/dvmp/analysis/vm_invar.cxx
+++ b/benchmarks/dvmp/analysis/vm_invar.cxx
@@ -70,18 +70,15 @@ int vm_invar(const std::string& config_name)
 
   // utility lambda functions to bind the vector meson and decay particle
   // types
-  auto momenta_from_tracking = [decay_mass](const std::vector<eic::TrackParametersData>& tracks) {
-    return util::momenta_from_tracking(tracks, decay_mass);
-  };
-
-  auto calc_inv_quant_rec = [vm_mass](const std::vector<ROOT::Math::PxPyPzMVector>& parts) {
-    return util::calc_inv_quant_rec(parts, vm_mass);
+  
+  auto calc_inv_quant_rec = [vm_mass, decay_mass](const std::vector<ROOT::Math::PxPyPzMVector>& parts) {
+    return util::calc_inv_quant_rec(parts, vm_mass, decay_mass);
   };
 
   //====================================================================
 
   // Define analysis flow
-  auto d_im = d.Define("p_rec", momenta_from_tracking, {"outputTrackParameters"})
+  auto d_im = d.Define("p_rec", util::momenta_RC, {"DummyReconstructedParticles"})
                   .Define("N", "p_rec.size()")
                   .Define("p_sim", util::momenta_from_simulation, {"mcparticles2"})
                   //================================================================
@@ -124,7 +121,7 @@ int vm_invar(const std::string& config_name)
     auto& hnu_sim = *h_nu_sim;
     // histogram style
     hnu_rec.SetLineColor(plot::kMpOrange);
-    hnu_rec.SetLineWidth(2);
+    hnu_rec.SetLineWidth(1);
     hnu_sim.SetLineColor(plot::kMpBlue);
     hnu_sim.SetLineWidth(2);
     // axes
@@ -151,7 +148,7 @@ int vm_invar(const std::string& config_name)
     auto& hQ2_sim = *h_Q2_sim;
     // histogram style
     hQ2_rec.SetLineColor(plot::kMpOrange);
-    hQ2_rec.SetLineWidth(2);
+    hQ2_rec.SetLineWidth(1);
     hQ2_sim.SetLineColor(plot::kMpBlue);
     hQ2_sim.SetLineWidth(2);
     // axes
@@ -178,7 +175,7 @@ int vm_invar(const std::string& config_name)
     auto& hx_sim = *h_x_sim;
     // histogram style
     hx_rec.SetLineColor(plot::kMpOrange);
-    hx_rec.SetLineWidth(2);
+    hx_rec.SetLineWidth(1);
     hx_sim.SetLineColor(plot::kMpBlue);
     hx_sim.SetLineWidth(2);
     // axes
@@ -205,7 +202,7 @@ int vm_invar(const std::string& config_name)
     auto& ht_sim = *h_t_sim;
     // histogram style
     ht_rec.SetLineColor(plot::kMpOrange);
-    ht_rec.SetLineWidth(2);
+    ht_rec.SetLineWidth(1);
     ht_sim.SetLineColor(plot::kMpBlue);
     ht_sim.SetLineWidth(2);
     // axes
diff --git a/benchmarks/dvmp/analysis/vm_mass.cxx b/benchmarks/dvmp/analysis/vm_mass.cxx
index 37c5d386386049b517de0ccc1a5d457936f3ac9c..48b05db406d0853205e66d72333a7e2257c53a0e 100644
--- a/benchmarks/dvmp/analysis/vm_mass.cxx
+++ b/benchmarks/dvmp/analysis/vm_mass.cxx
@@ -14,6 +14,8 @@
 #include <nlohmann/json.hpp>
 #include <string>
 #include <vector>
+#include "eicd/ReconstructedParticleCollection.h"
+#include "eicd/ReconstructedParticleData.h"
 
 // Run VM invariant-mass-based benchmarks on an input reconstruction file for
 // a desired vector meson (e.g. jpsi) and a desired decay particle (e.g. muon)
@@ -22,6 +24,19 @@
 // TODO: I think it would be better to pass small json configuration file to
 //       the test, instead of this ever-expanding list of function arguments.
 // FIXME: MC does not trace back into particle history. Need to fix that
+
+//double RBW(double*x, double*par){
+//    double mean = par[0];
+//    double GAMMA = par[1];
+//    double N = par[2];
+//    double gamma = mean*TMath::Sqrt(mean*mean + GAMMA*GAMMA);
+//    double k = 2.*mean*GAMMA*gamma/TMath::Pi()*TMath::Sqrt(2./(mean*mean + gamma));
+//    double eval = N*k/((x[0]*x[0]-mean*mean)*(x[0]*x[0]-mean*mean) + mean*mean*GAMMA*GAMMA);
+//    return(eval);
+//}
+//double fFlat(double*x, double*par){
+//    return(par[0]);
+//}
 int vm_mass(const std::string& config_name)
 {
   // read our configuration
@@ -72,23 +87,20 @@ int vm_mass(const std::string& config_name)
 
   // utility lambda functions to bind the vector meson and decay particle
   // types
-  auto momenta_from_tracking = [decay_mass](const std::vector<eic::TrackParametersData>& tracks) {
-    return util::momenta_from_tracking(tracks, decay_mass);
-  };
-  auto find_decay_pair = [vm_mass](const std::vector<ROOT::Math::PxPyPzMVector>& parts) {
-    return util::find_decay_pair(parts, vm_mass);
+  
+  auto find_decay_pair = [vm_mass, decay_mass](const std::vector<ROOT::Math::PxPyPzMVector>& parts) {
+    return util::find_decay_pair(parts, vm_mass, decay_mass);
   };
 
   // util::PrintGeant4(mcparticles2);
   // Define analysis flow
-  auto d_im = d.Define("p_rec", momenta_from_tracking, {"outputTrackParameters"})
+  auto d_im = d.Define("p_rec", util::momenta_RC, {"DummyReconstructedParticles"})       //using dummy rc
                   .Define("N", "p_rec.size()")
                   .Define("p_sim", util::momenta_from_simulation, {"mcparticles2"})
                   .Define("decay_pair_rec", find_decay_pair, {"p_rec"})
                   .Define("decay_pair_sim", find_decay_pair, {"p_sim"})
                   .Define("p_vm_rec", "decay_pair_rec.first + decay_pair_rec.second")
                   .Define("p_vm_sim", "decay_pair_sim.first + decay_pair_sim.second")
-                  //.Define("p_vm_sim", util::get_sum, {"decay_pair_sim"})
                   .Define("mass_rec", "p_vm_rec.M()")
                   .Define("mass_sim", "p_vm_sim.M()")
                   .Define("pt_rec", "p_vm_rec.pt()")
@@ -99,19 +111,18 @@ int vm_mass(const std::string& config_name)
                   .Define("eta_sim", "p_vm_sim.eta()");
 
   // Define output histograms
-  auto h_im_rec =
-      d_im.Histo1D({"h_im_rec", ";m_{ll'} (GeV/c^{2});#", 100, -1.1, vm_mass + 5}, "mass_rec");
-  auto h_im_sim =
-      d_im.Histo1D({"h_im_sim", ";m_{ll'} (GeV/c^{2});#", 100, -1.1, vm_mass + 5}, "mass_sim");
+  //auto h_im_rec = d_im.Histo1D({"h_im_rec", ";m_{ll'} (GeV/c^{2});#", (int)(vm_mass+0.5)*2*100, 0., 2.*(int)(vm_mass+0.5)}, "mass_rec"); //real rec 
+  auto h_im_rec = d_im.Histo1D({"h_im_rec", ";m_{ll'} (GeV/c^{2});#", 50, 1., 5.}, "mass_rec");//for dummy_rec
+  auto h_im_sim = d_im.Histo1D({"h_im_sim", ";m_{ll'} (GeV/c^{2});#", 50, 1., 5.}, "mass_sim");
 
-  auto h_pt_rec = d_im.Histo1D({"h_pt_rec", ";p_{T} (GeV/c);#", 400, 0., 40.}, "pt_rec");
-  auto h_pt_sim = d_im.Histo1D({"h_pt_sim", ";p_{T} (GeV/c);#", 400, 0., 40.}, "pt_sim");
+  auto h_pt_rec = d_im.Histo1D({"h_pt_rec", ";p_{T} (GeV/c);#", 50, 0., 10.}, "pt_rec");
+  auto h_pt_sim = d_im.Histo1D({"h_pt_sim", ";p_{T} (GeV/c);#", 50, 0., 10.}, "pt_sim");
 
-  auto h_phi_rec = d_im.Histo1D({"h_phi_rec", ";#phi_{ll'};#", 90, -M_PI, M_PI}, "phi_rec");
-  auto h_phi_sim = d_im.Histo1D({"h_phi_sim", ";#phi_{ll'};#", 90, -M_PI, M_PI}, "phi_sim");
+  auto h_phi_rec = d_im.Histo1D({"h_phi_rec", ";#phi_{ll'};#", 45, -M_PI, M_PI}, "phi_rec");
+  auto h_phi_sim = d_im.Histo1D({"h_phi_sim", ";#phi_{ll'};#", 45, -M_PI, M_PI}, "phi_sim");
 
-  auto h_eta_rec = d_im.Histo1D({"h_eta_rec", ";#eta_{ll'};#", 1000, -5., 5.}, "eta_rec");
-  auto h_eta_sim = d_im.Histo1D({"h_eta_sim", ";#eta_{ll'};#", 1000, -5., 5.}, "eta_sim");
+  auto h_eta_rec = d_im.Histo1D({"h_eta_rec", ";#eta_{ll'};#", 50, -2., 2.}, "eta_rec");
+  auto h_eta_sim = d_im.Histo1D({"h_eta_sim", ";#eta_{ll'};#", 50, -2., 2.}, "eta_sim");
 
   // Plot our histograms.
   // TODO: to start I'm explicitly plotting the histograms, but want to
@@ -129,7 +140,7 @@ int vm_mass(const std::string& config_name)
     h11.SetLineColor(plot::kMpBlue);
     h11.SetLineWidth(2);
     h12.SetLineColor(plot::kMpOrange);
-    h12.SetLineWidth(2);
+    h12.SetLineWidth(1);
     // axes
     h11.GetXaxis()->CenterTitle();
     h11.GetYaxis()->CenterTitle();
@@ -159,13 +170,24 @@ int vm_mass(const std::string& config_name)
     h21.SetLineColor(plot::kMpBlue);
     h21.SetLineWidth(2);
     h22.SetLineColor(plot::kMpOrange);
-    h22.SetLineWidth(2);
+    h22.SetLineWidth(1);
     // axes
     h21.GetXaxis()->CenterTitle();
     h21.GetYaxis()->CenterTitle();
     // draw everything
+    TF1* mfPt = new TF1("mfPt", "[0]*exp(-[1]*x)", 1.2, 10.);
+    mfPt->SetParameters(5., 1.);
+    mfPt->SetParLimits(0, 0., 1000000.);
+    mfPt->SetParLimits(1, 0., 1000000.);
+    mfPt->SetNpx(1000);
+    mfPt->SetLineColor(2);
+    mfPt->SetLineStyle(7);
+    h21.Fit(mfPt, "", "", 1.2, 10.);
     h21.DrawClone("hist");
     h22.DrawClone("hist same");
+    mfPt->Draw("same");
+    
+    
     // FIXME hardcoded beam configuration
     plot::draw_label(10, 100, detector);
     TText* tptr2;
@@ -189,7 +211,7 @@ int vm_mass(const std::string& config_name)
     h31.SetLineColor(plot::kMpBlue);
     h31.SetLineWidth(2);
     h32.SetLineColor(plot::kMpOrange);
-    h32.SetLineWidth(2);
+    h32.SetLineWidth(1);
     // axes
     h31.GetXaxis()->CenterTitle();
     h31.GetYaxis()->CenterTitle();
@@ -219,7 +241,7 @@ int vm_mass(const std::string& config_name)
     h41.SetLineColor(plot::kMpBlue);
     h41.SetLineWidth(2);
     h42.SetLineColor(plot::kMpOrange);
-    h42.SetLineWidth(2);
+    h42.SetLineWidth(1);
     // axes
     h41.GetXaxis()->CenterTitle();
     h41.GetYaxis()->CenterTitle();
diff --git a/include/util.h b/include/util.h
index 6a24b293c26963b4999fc63df821ab3418c694a8..eddf13933a08e4d0c3b0de952b421fb1904e8ea8 100644
--- a/include/util.h
+++ b/include/util.h
@@ -10,11 +10,14 @@
 #include <limits>
 #include <string>
 #include <vector>
+#include "TF1.h"
 
 #include <Math/Vector4D.h>
 
 #include "dd4pod/Geant4ParticleCollection.h"
 #include "eicd/TrackParametersCollection.h"
+#include "eicd/ReconstructedParticleCollection.h"
+#include "eicd/ReconstructedParticleData.h"
 
 namespace util {
 
@@ -56,7 +59,7 @@ namespace util {
   }
 
   // Get a vector of 4-momenta from raw tracking info, using an externally
-  // provided particle mass assumption.
+  // provided particle mass assumption. //outputTrackParameters
   inline auto momenta_from_tracking(const std::vector<eic::TrackParametersData>& tracks,
                                     const double                                 mass)
   {
@@ -75,7 +78,17 @@ namespace util {
     });
     return momenta;
   }
-
+  //=====================================================================================
+  inline auto momenta_RC(const std::vector<eic::ReconstructedParticleData>& parts)
+  {
+    std::vector<ROOT::Math::PxPyPzMVector> momenta{parts.size()};
+    // transform our raw tracker info into proper 4-momenta
+    std::transform(parts.begin(), parts.end(), momenta.begin(), [](const auto& part) {
+      return ROOT::Math::PxPyPzMVector{part.p.x, part.p.y, part.p.z, part.mass};
+    });
+    return momenta;
+  }
+  //=====================================================================================
   // Get a vector of 4-momenta from the simulation data.
   // TODO: Add PID selector (maybe using ranges?)
   inline auto momenta_from_simulation(const std::vector<dd4pod::Geant4ParticleData>& parts)
@@ -91,7 +104,7 @@ namespace util {
   // Find the decay pair candidates from a vector of particles (parts),
   // with invariant mass closest to a desired value (pdg_mass)
   inline std::pair<ROOT::Math::PxPyPzMVector, ROOT::Math::PxPyPzMVector>
-  find_decay_pair(const std::vector<ROOT::Math::PxPyPzMVector>& parts, const double pdg_mass)
+  find_decay_pair(const std::vector<ROOT::Math::PxPyPzMVector>& parts, const double pdg_mass, const double daughter_mass)
   {
     int    first     = -1;
     int    second    = -1;
@@ -101,7 +114,9 @@ namespace util {
     // for each combination, and remember which combination is the closest
     // to the desired pdg_mass
     for (size_t i = 0; i < parts.size(); ++i) {
+      if( fabs(parts[i].mass() - daughter_mass)/daughter_mass > 0.01) continue;
       for (size_t j = i + 1; j < parts.size(); ++j) {
+        if( fabs(parts[j].mass() - daughter_mass)/daughter_mass > 0.01) continue;
         const double new_mass{(parts[i] + parts[j]).mass()};
         if (fabs(new_mass - pdg_mass) < fabs(best_mass - pdg_mass)) {
           first     = i;