diff --git a/benchmarks/dvmp/analysis/dvmp.h b/benchmarks/dvmp/analysis/dvmp.h
index 371b454f8d92f4c0cd5b17edd4a8f5e1ecc77e77..3baf03ad4d9d8213d52ada928b34ed74631fa0e4 100644
--- a/benchmarks/dvmp/analysis/dvmp.h
+++ b/benchmarks/dvmp/analysis/dvmp.h
@@ -28,24 +28,88 @@ namespace util {
   // for structure functions
 
   struct inv_quant { // add more when needed
-    double nu, Q2, x;
+    double nu, Q2, x, t;
   };
 
   // for simu
-  inline inv_quant calc_inv_quant_simu(const std::vector<ROOT::Math::PxPyPzMVector>& parts)
+  inline inv_quant calc_inv_quant_sim(const std::vector<ROOT::Math::PxPyPzMVector>& parts)
   {
     ROOT::Math::PxPyPzMVector q(parts[0] - parts[2]);
     ROOT::Math::PxPyPzMVector P(parts[3]);
+    ROOT::Math::PxPyPzMVector Delta(parts[6] - parts[3]);
 
     double    nu         = q.Dot(P) / P.mass();
     double    Q2         = -q.Dot(q);
-    inv_quant quantities = {nu, Q2, Q2 / 2. / P.mass() / nu};
+    double t = Delta.Dot(Delta);
+    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){
+    int first = -1;
+    int second = -1;
+    double best_mass = -1;
 
-  inline double get_nu_simu(inv_quant quantities) { return quantities.nu / 1000.; }
-  inline double get_Q2_simu(inv_quant quantities) { return quantities.Q2; }
-  inline double get_x_simu(inv_quant quantities) { return quantities.x; }
+    // 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) {
+      for (int j = i + 1; j < parts.size(); ++j) {
+        const double new_mass{(parts[i] + parts[j]).mass()};
+        if (fabs(new_mass - pdg_mass) < fabs(best_mass - pdg_mass)) {
+          first = i;
+          second = j;
+          best_mass = new_mass;
+        }
+      }
+    }
+    if (first < 0 || parts.size() < 3 ){
+      inv_quant quantities = {-999., -999., -999., -999.};
+      return quantities;
+    }
+    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);
+    int scatteredIdx = -1;
+    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
+        scatteredIdx = i;
+        dp = 10. - ptmp;
+      }
+    }
+    if(scatteredIdx ==-1){
+      inv_quant quantities = {-999., -999., -999., -999.};
+      return quantities;
+    }
+    ROOT::Math::PxPyPzMVector q(e1 - parts[scatteredIdx]);
+    ROOT::Math::PxPyPzMVector Delta(q - pair_4p);
+
+    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 = {-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; }
+  inline double get_t(inv_quant quantities) { return quantities.t; }
 
   // for tracking, add later
 
diff --git a/benchmarks/dvmp/analysis/vm_invar.cxx b/benchmarks/dvmp/analysis/vm_invar.cxx
index bbc4db2739073fb604c4bbeb7b2d5d0746d03b3a..edaa03ad2adb1546f15a1d547c5e75c9685d3e46 100644
--- a/benchmarks/dvmp/analysis/vm_invar.cxx
+++ b/benchmarks/dvmp/analysis/vm_invar.cxx
@@ -74,6 +74,10 @@ int vm_invar(const std::string& config_name)
     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);
+  };
+
   //====================================================================
 
   // Define analysis flow
@@ -81,10 +85,16 @@ int vm_invar(const std::string& config_name)
                   .Define("N", "p_rec.size()")
                   .Define("p_sim", util::momenta_from_simulation, {"mcparticles2"})
                   //================================================================
-                  .Define("invariant_quantities", util::calc_inv_quant_simu, {"p_sim"})
-                  .Define("nu_sim", util::get_nu_simu, {"invariant_quantities"})
-                  .Define("Q2_sim", util::get_Q2_simu, {"invariant_quantities"})
-                  .Define("x_sim", util::get_x_simu, {"invariant_quantities"});
+                  .Define("invariant_quantities_rec", calc_inv_quant_rec, {"p_rec"})
+                  .Define("invariant_quantities_sim", util::calc_inv_quant_sim, {"p_sim"})
+                  .Define("nu_rec", util::get_nu, {"invariant_quantities_rec"})
+                  .Define("Q2_rec", util::get_Q2, {"invariant_quantities_rec"})
+                  .Define("x_rec", util::get_x, {"invariant_quantities_rec"})
+                  .Define("t_rec", util::get_t, {"invariant_quantities_rec"})
+                  .Define("nu_sim", util::get_nu, {"invariant_quantities_sim"})
+                  .Define("Q2_sim", util::get_Q2, {"invariant_quantities_sim"})
+                  .Define("x_sim", util::get_x, {"invariant_quantities_sim"})
+                  .Define("t_sim", util::get_t, {"invariant_quantities_sim"});
   //================================================================
 
   // Define output histograms
@@ -92,6 +102,12 @@ int vm_invar(const std::string& config_name)
   auto h_nu_sim = d_im.Histo1D({"h_nu_sim", ";#nu/1000;#", 100, 0., 2.}, "nu_sim");
   auto h_Q2_sim = d_im.Histo1D({"h_Q2_sim", ";Q^{2};#", 100, 0., 15.}, "Q2_sim");
   auto h_x_sim  = d_im.Histo1D({"h_x_sim", ";x;#", 100, 0., 0.1}, "x_sim");
+  auto h_t_sim  = d_im.Histo1D({"h_t_sim", ";t;#", 100, -1., 0.}, "t_sim");
+  
+  auto h_nu_rec = d_im.Histo1D({"h_nu_rec", ";#nu/1000;#", 100, 0., 2.}, "nu_rec");
+  auto h_Q2_rec = d_im.Histo1D({"h_Q2_rec", ";Q^{2};#", 100, 0., 15.}, "Q2_rec");
+  auto h_x_rec  = d_im.Histo1D({"h_x_rec", ";x;#", 100, 0., 0.1}, "x_rec");
+  auto h_t_rec  = d_im.Histo1D({"h_t_rec", ";t;#", 100, -1., 0.}, "t_rec");
 
   // Plot our histograms.
   // TODO: to start I'm explicitly plotting the histograms, but want to
@@ -100,85 +116,119 @@ int vm_invar(const std::string& config_name)
 
     // Print canvas to output file
 
-    TCanvas c{"canvas2", "canvas2", 1800, 600};
-    c.Divide(3, 1, 0.0001, 0.0001);
+    TCanvas c{"canvas2", "canvas2", 1200, 900};
+    c.Divide(2, 2, 0.0001, 0.0001);
     // pad 1 nu
     c.cd(1);
-    // gPad->SetLogx(false);
-    // gPad->SetLogy(false);
-    auto& hnu = *h_nu_sim;
+    auto& hnu_rec = *h_nu_rec;
+    auto& hnu_sim = *h_nu_sim;
     // histogram style
-    hnu.SetLineColor(plot::kMpBlue);
-    hnu.SetLineWidth(2);
+    hnu_rec.SetLineColor(plot::kMpOrange);
+    hnu_rec.SetLineWidth(2);
+    hnu_sim.SetLineColor(plot::kMpBlue);
+    hnu_sim.SetLineWidth(2);
     // axes
-    hnu.GetXaxis()->CenterTitle();
-    // hnu.GetXaxis()->SetTitle("#times1000");
+    hnu_sim.GetXaxis()->CenterTitle();
     // draw everything
-    hnu.DrawClone("hist");
+    hnu_sim.DrawClone("hist");
+    hnu_rec.DrawClone("hist same");
     // FIXME hardcoded beam configuration
     plot::draw_label(10, 100, detector);
-    TText* tptr21;
-    auto   t21 = new TPaveText(.6, .8417, .9, .925, "NB NDC");
-    t21->SetFillColorAlpha(kWhite, 0);
-    t21->SetTextFont(43);
-    t21->SetTextSize(25);
-    tptr21 = t21->AddText("simulated");
-    tptr21->SetTextColor(plot::kMpBlue);
-    // tptr1 = t1->AddText("reconstructed");
-    // tptr1->SetTextColor(plot::kMpOrange);
-    t21->Draw();
+    TText* tptr1;
+    auto   t1 = new TPaveText(.6, .8417, .9, .925, "NB NDC");
+    t1->SetFillColorAlpha(kWhite, 0);
+    t1->SetTextFont(43);
+    t1->SetTextSize(25);
+    tptr1 = t1->AddText("simulated");
+    tptr1->SetTextColor(plot::kMpBlue);
+    tptr1 = t1->AddText("rec(PlaceHolder)");
+    tptr1->SetTextColor(plot::kMpOrange);
+    t1->Draw();
 
     // pad 2 Q2
     c.cd(2);
-    // gPad->SetLogx(false);
-    // gPad->SetLogy(false);
-    auto& hQ2 = *h_Q2_sim;
+    auto& hQ2_rec = *h_Q2_rec;
+    auto& hQ2_sim = *h_Q2_sim;
     // histogram style
-    hQ2.SetLineColor(plot::kMpBlue);
-    hQ2.SetLineWidth(2);
+    hQ2_rec.SetLineColor(plot::kMpOrange);
+    hQ2_rec.SetLineWidth(2);
+    hQ2_sim.SetLineColor(plot::kMpBlue);
+    hQ2_sim.SetLineWidth(2);
     // axes
-    hQ2.GetXaxis()->CenterTitle();
+    hQ2_sim.GetXaxis()->CenterTitle();
     // draw everything
-    hQ2.DrawClone("hist");
+    hQ2_sim.DrawClone("hist");
+    hQ2_rec.DrawClone("hist same");
     // FIXME hardcoded beam configuration
     plot::draw_label(10, 100, detector);
-    TText* tptr22;
-    auto   t22 = new TPaveText(.6, .8417, .9, .925, "NB NDC");
-    t22->SetFillColorAlpha(kWhite, 0);
-    t22->SetTextFont(43);
-    t22->SetTextSize(25);
-    tptr22 = t22->AddText("simulated");
-    tptr22->SetTextColor(plot::kMpBlue);
-    // tptr1 = t1->AddText("reconstructed");
-    // tptr1->SetTextColor(plot::kMpOrange);
-    t22->Draw();
-
-    // pad 1 nu
+    TText* tptr2;
+    auto   t2 = new TPaveText(.6, .8417, .9, .925, "NB NDC");
+    t2->SetFillColorAlpha(kWhite, 0);
+    t2->SetTextFont(43);
+    t2->SetTextSize(25);
+    tptr2 = t2->AddText("simulated");
+    tptr2->SetTextColor(plot::kMpBlue);
+    tptr2 = t2->AddText("rec(PlaceHolder)");
+    tptr2->SetTextColor(plot::kMpOrange);
+    t2->Draw();
+    
+    // pad 3 x
     c.cd(3);
-    // gPad->SetLogx(false);
-    // gPad->SetLogy(false);
-    auto& hx = *h_x_sim;
+    auto& hx_rec = *h_x_rec;
+    auto& hx_sim = *h_x_sim;
     // histogram style
-    hx.SetLineColor(plot::kMpBlue);
-    hx.SetLineWidth(2);
+    hx_rec.SetLineColor(plot::kMpOrange);
+    hx_rec.SetLineWidth(2);
+    hx_sim.SetLineColor(plot::kMpBlue);
+    hx_sim.SetLineWidth(2);
     // axes
-    hx.GetXaxis()->CenterTitle();
+    hx_sim.GetXaxis()->CenterTitle();
     // draw everything
-    hx.DrawClone("hist");
+    hx_sim.DrawClone("hist");
+    hx_rec.DrawClone("hist same");
     // FIXME hardcoded beam configuration
     plot::draw_label(10, 100, detector);
-    TText* tptr23;
-    auto   t23 = new TPaveText(.6, .8417, .9, .925, "NB NDC");
-    t23->SetFillColorAlpha(kWhite, 0);
-    t23->SetTextFont(43);
-    t23->SetTextSize(25);
-    tptr23 = t23->AddText("simulated");
-    tptr23->SetTextColor(plot::kMpBlue);
-    // tptr1 = t1->AddText("reconstructed");
-    // tptr1->SetTextColor(plot::kMpOrange);
-    t23->Draw();
-
+    TText* tptr3;
+    auto   t3 = new TPaveText(.6, .8417, .9, .925, "NB NDC");
+    t3->SetFillColorAlpha(kWhite, 0);
+    t3->SetTextFont(43);
+    t3->SetTextSize(25);
+    tptr3 = t3->AddText("simulated");
+    tptr3->SetTextColor(plot::kMpBlue);
+    tptr3 = t3->AddText("rec(PlaceHolder)");
+    tptr3->SetTextColor(plot::kMpOrange);
+    t3->Draw();
+    
+    // pad 3 x
+    c.cd(4);
+    auto& ht_rec = *h_t_rec;
+    auto& ht_sim = *h_t_sim;
+    // histogram style
+    ht_rec.SetLineColor(plot::kMpOrange);
+    ht_rec.SetLineWidth(2);
+    ht_sim.SetLineColor(plot::kMpBlue);
+    ht_sim.SetLineWidth(2);
+    // axes
+    ht_sim.GetXaxis()->CenterTitle();
+    // draw everything
+    ht_sim.DrawClone("hist");
+    ht_rec.DrawClone("hist same");
+    // FIXME hardcoded beam configuration
+    plot::draw_label(10, 100, detector);
+    TText* tptr4;
+    auto   t4 = new TPaveText(.6, .8417, .9, .925, "NB NDC");
+    t4->SetFillColorAlpha(kWhite, 0);
+    t4->SetTextFont(43);
+    t4->SetTextSize(25);
+    tptr4 = t4->AddText("simulated");
+    tptr4->SetTextColor(plot::kMpBlue);
+    tptr4 = t4->AddText("rec(PlaceHolder)");
+    tptr4->SetTextColor(plot::kMpOrange);
+    t4->Draw();
+    
     c.Print(fmt::format("{}InvariantQuantities.png", output_prefix).c_str());
+    
+    
   }
 
   // TODO we're not actually getting the resolutions yet
diff --git a/include/util.h b/include/util.h
index 56fb12893787e1d1fff00bd01653ad23b149f48e..6a24b293c26963b4999fc63df821ab3418c694a8 100644
--- a/include/util.h
+++ b/include/util.h
@@ -48,6 +48,8 @@ namespace util {
       return 3.0969;
     } else if (part == "upsilon") {
       return 9.49630;
+    } else if (part == "proton"){
+      return 0.938272;
     } else {
       throw unknown_particle_error{part};
     }