From 3d618a33fecc88fb8490b3f857179317ec4ab873 Mon Sep 17 00:00:00 2001
From: Marshall Scott <mbscott@anl.gov>
Date: Mon, 1 Mar 2021 10:09:30 -0500
Subject: [PATCH] Ongoing dis_electron Q2 analysis. An issue with Q2 being
 basically zero for the electrons.

---
 benchmarks/dis/analysis/dis_electrons.cxx | 250 ++++++++++------------
 1 file changed, 114 insertions(+), 136 deletions(-)

diff --git a/benchmarks/dis/analysis/dis_electrons.cxx b/benchmarks/dis/analysis/dis_electrons.cxx
index f0a19595..63515079 100644
--- a/benchmarks/dis/analysis/dis_electrons.cxx
+++ b/benchmarks/dis/analysis/dis_electrons.cxx
@@ -6,96 +6,52 @@
 #include <util.h>
 
 #include "ROOT/RDataFrame.hxx"
+#include <TFitResult.h>
+#include <TH1D.h>
+#include <TRandom3.h>
+#include <algorithm>
 #include <cmath>
+#include <eicd/ReconstructedParticleData.h>
 #include <fmt/color.h>
 #include <fmt/core.h>
 #include <fstream>
 #include <iostream>
 #include <nlohmann/json.hpp>
 #include <string>
-#include <vector>
-#include <eicd/ReconstructedParticleData.h>
-#include <TH1D.h>
-#include <TFitResult.h>
-#include <TRandom3.h>
-#include <algorithm>
 #include <utility>
+#include <vector>
 
-
-// Get a vector of 4-momenta from the reconstructed data.
-inline auto momenta_from_reconstruction(const std::vector<eic::ReconstructedParticleData>& parts)
-{
-  std::vector<ROOT::Math::PxPyPzEVector> momenta{parts.size()};
-  // transform our reconstructed particle data into 4-momenta
-  std::transform(parts.begin(), parts.end(), momenta.begin(), [](const auto& part) {
-    return ROOT::Math::PxPyPzEVector{part.p.x, part.p.y, part.p.z, part.energy};
-  });
-  return momenta;
-}
-
-// Convert PxPyPzMVector to PxPyPzEVector
-inline auto convertMtoE(const std::vector<ROOT::Math::PxPyPzMVector>& mom)
-{
-  std::vector<ROOT::Math::PxPyPzEVector> momenta{mom.size()};
-  std::transform(mom.begin(), mom.end(), momenta.begin(), [](const auto& part) {
-    return ROOT::Math::PxPyPzEVector{part.Px(), part.Py(), part.Pz(), part.energy()};
-  });
-  return momenta;
-}
-
-// Momentum sorting bool
-bool sort_mom_bool(ROOT::Math::PxPyPzEVector &mom1, ROOT::Math::PxPyPzEVector &mom2)
+// Reconstuction functions
+bool mom_sort_recon(eic::ReconstructedParticleData& part1, eic::ReconstructedParticleData& part2)
 {
-  return  mom1.energy() > mom2.energy(); 
+  return (part1.p.x * part1.p.x + part1.p.y * part1.p.y + part1.p.z * part1.p.z >
+          part2.p.x * part2.p.x + part2.p.y * part2.p.y + part2.p.z * part2.p.z);
 }
 
-// Momentunm sorting function
-inline auto sort_momenta(const std::vector<ROOT::Math::PxPyPzEVector>& mom)
+inline auto momenta_from_recon(const std::vector<eic::ReconstructedParticleData>& parts)
 {
-  std::vector <ROOT::Math::PxPyPzEVector> sort_mom = mom;
-  sort(sort_mom.begin(), sort_mom.end(), sort_mom_bool);
-  return sort_mom;
+  std::vector<eic::ReconstructedParticleData> sort_parts = parts;
+  sort(sort_parts.begin(), sort_parts.end(), mom_sort_recon);
+  return sort_parts;
 }
 
-// Q2 calculation from 4 Vector
-inline auto Q2(const std::vector<ROOT::Math::PxPyPzEVector>& mom)
+inline auto Q2_from_recon(const std::vector<eic::ReconstructedParticleData>& parts)
 {
-  std::vector<double> Q2Vec(mom.size() );
-  ROOT::Math::PxPyPzEVector beamMom = {0, 0, 18, 18};
-  std::transform(mom.begin(), mom.end(), Q2Vec.begin(), [beamMom](const auto& part) {
-    return -(part - beamMom).M2();
+  std::vector<double> Q2Vec(parts.size());
+  double              beamEnergy = 18;
+  std::transform(parts.begin(), parts.end(), Q2Vec.begin(), [beamEnergy](const auto& part) {
+    double q2 = pow(beamEnergy - part.energy, 2.0) - part.p.x * part.p.x - part.p.y * part.p.y -
+                pow(beamEnergy - part.p.z, 2.0);
+    return -q2;
   });
   return Q2Vec;
 }
 
-// Difference between two 4 Vectors
-inline auto sub(const std::vector<ROOT::Math::PxPyPzEVector>& mom1, const std::vector<ROOT::Math::PxPyPzEVector>& mom2)
-{
-  std::vector<ROOT::Math::PxPyPzEVector> sub(mom1.size() );
-  for (int i = 0; i < sub.size(); i++)
-  {
-    sub[i] = mom1[i] - mom2[i];
-  }
-  return sub;
-}
-
-// Multiplies a double by a gaussian distributed number 
-inline auto randomize(const std::vector<double>& doubleVec)
-{
-  std::vector<double> outVec(doubleVec.size() );
-  TRandom3 rand;
-  std::transform(doubleVec.begin(), doubleVec.end(), outVec.begin(), [&rand](const auto& indouble) {
-    return indouble * rand.Gaus(1.0, 0.2);
-  });
-  return outVec;
-}
-
-//Simulation functions
-/*
+// Simulation functions
 bool mom_sort_sim(dd4pod::Geant4ParticleData& part1, dd4pod::Geant4ParticleData& part2)
 {
-  return (part1.psx*part1.psx + part1.psy*part1.psy + part1.psz*part1.psz > 
-          part2.psx*part2.psx + part2.psy*part2.psy + part2.psz*part2.psz);
+  return (part1.psx * part1.psx + part1.psy * part1.psy + part1.psz * part1.psz >
+          part2.psx * part2.psx + part2.psy * part2.psy + part2.psz * part2.psz);
 }
 
 inline auto momenta_from_sim(const std::vector<dd4pod::Geant4ParticleData>& parts)
@@ -107,11 +63,13 @@ inline auto momenta_from_sim(const std::vector<dd4pod::Geant4ParticleData>& part
 
 inline auto Q2_from_sim(const std::vector<dd4pod::Geant4ParticleData>& parts)
 {
-  std::vector<double> Q2Vec(parts.size() );
-  double beamEnergy = 18;
+  std::vector<double> Q2Vec(parts.size());
+  double              beamEnergy = 18;
   std::transform(parts.begin(), parts.end(), Q2Vec.begin(), [beamEnergy](const auto& part) {
-    double energy = sqrt(part.psx*part.psx + part.psy*part.psy + part.psz*part.psz + part.mass*part.mass);
-    double q2 = pow(beamEnergy - energy, 2.0) - part.psx*part.psx - part.psy*part.psy - pow(part.psz - beamEnergy, 2.0);
+    double energy = sqrt(part.psx * part.psx + part.psy * part.psy + part.psz * part.psz +
+                         part.mass * part.mass);
+    double q2     = pow(beamEnergy - energy, 2.0) - part.psx * part.psx - part.psy * part.psy -
+                pow(part.psz - beamEnergy, 2.0);
     return -q2;
   });
   return Q2Vec;
@@ -120,14 +78,46 @@ inline auto Q2_from_sim(const std::vector<dd4pod::Geant4ParticleData>& parts)
 inline auto elec_PID_sim(const std::vector<dd4pod::Geant4ParticleData>& parts)
 {
   std::vector<dd4pod::Geant4ParticleData> electrons;
-  for (auto part : parts)
-  {
-    if (part.pdgID == 11){electrons.push_back(part);}
+  for (auto part : parts) {
+    if (part.pdgID == 11) {
+      electrons.push_back(part);
+    }
   }
   return electrons;
 }
-*/
 
+inline auto mass_from_recon(const std::vector<eic::ReconstructedParticleData>& parts)
+{
+  std::vector<double> mass(parts.size());
+  std::transform(parts.begin(), parts.end(), mass.begin(),
+                 [](const auto& part) { return part.mass; });
+  return mass;
+}
+
+inline auto mass_random(const std::vector<double>& massVec)
+{
+  std::vector<double> mass(massVec.size());
+  TRandom3            rand;
+  std::transform(massVec.begin(), massVec.end(), mass.begin(),
+                 [&rand](const auto& inmass) { return inmass * rand.Gaus(1.0, 0.2); });
+  return mass;
+}
+
+inline auto mass_from_simulation(const std::vector<ROOT::Math::PxPyPzMVector>& momenta)
+{
+  std::vector<double> mass(momenta.size());
+  std::transform(momenta.begin(), momenta.end(), mass.begin(),
+                 [](const auto& mom) { return mom.mass(); });
+  return mass;
+}
+
+inline auto getSimPID(const std::vector<dd4pod::Geant4ParticleData>& parts)
+{
+  std::vector<int> pid(parts.size());
+  std::transform(parts.begin(), parts.end(), pid.begin(),
+                 [](const auto& part) { return part.pdgID; });
+  return pid;
+}
 
 int dis_electrons(const std::string& config_name)
 {
@@ -159,11 +149,10 @@ int dis_electrons(const std::string& config_name)
        {"target", "0.1"}}};
 
   // Run this in multi-threaded mode if desired
-  //ROOT::EnableImplicitMT(kNumThreads);
+  // ROOT::EnableImplicitMT(kNumThreads);
 
-  //Particle number enumeration
-  enum sidis_particle_ID
-  {
+  // Particle number enumeration
+  enum sidis_particle_ID {
     electron = 11,
     pi_0     = 111,
     pi_plus  = 211,
@@ -175,7 +164,6 @@ int dis_electrons(const std::string& config_name)
     neutron  = 2112
   };
 
-
   const double electron_mass = util::get_pdg_mass("electron");
 
   // Ensure our output prefix always ends on a dot, a slash or a dash
@@ -193,63 +181,52 @@ int dis_electrons(const std::string& config_name)
         return util::momenta_from_tracking(tracks, electron_mass);
       };
 
-/*
-  //Old dataframe
-  auto d0 = d.Define("p_rec", momenta_from_tracking, {"outputTrackParameters"})
-                .Define("N", "p_rec.size()")
-                .Define("p_sim", util::momenta_from_simulation, {"mcparticles2"})
-                .Define("mom_sim", util::mom, {"p_sim"})
-                .Define("mom_rec", util::mom, {"p_rec"});
-*/
-
-  auto d0 = d.Define("p_recon", momenta_from_reconstruction, {"DummyReconstructedParticles"})
-                .Define("p_recon_sort", sort_momenta, {"p_recon"})
-                .Define("Q2_recon", Q2, {"p_recon_sort"})
-                .Define("Q2_recon_rand", randomize, {"Q2_recon"})
-                .Define("elec_Q2_recon_rand", "Q2_recon_rand[0]")
-                .Define("p_sim_M", util::momenta_from_simulation, {"mcparticles2"})
-                .Define("p_sim", convertMtoE, {"p_sim_M"})
-                .Define("p_sim_sort", sort_momenta, {"p_sim"})
-                .Define("Q2_sim", Q2, {"p_sim_sort"})
+  /*
+    //Old dataframe
+    auto d0 = d.Define("p_rec", momenta_from_tracking, {"outputTrackParameters"})
+                  .Define("N", "p_rec.size()")
+                  .Define("p_sim", util::momenta_from_simulation, {"mcparticles2"})
+                  .Define("mom_sim", util::mom, {"p_sim"})
+                  .Define("mom_rec", util::mom, {"p_rec"});
+  */
+
+  auto d0 = d.Define("sorted_recon", momenta_from_recon, {"DummyReconstructedParticles"})
+                .Define("Q2_recon", Q2_from_recon, {"sorted_recon"})
+                .Define("elec_Q2_recon", "Q2_recon[0]")
+                .Define("sorted_sim", momenta_from_sim, {"mcparticles2"})
+                .Define("Q2_sim", Q2_from_sim, {"sorted_sim"})
                 .Define("elec_Q2_sim", "Q2_sim[0]")
-                .Define("Q2_diff", "(elec_Q2_recon_rand - elec_Q2_sim)/elec_Q2_sim")
-                .Define("p_diff", sub, {"p_recon","p_sim"});
-                /*
                 .Define("electrons_sim", elec_PID_sim, {"sorted_sim"})
-                .Define("Q2_sim_elec_pid", Q2_from_sim, {"electrons_sim"})
+                .Define("Q2_sim_elec_pid", Q2_from_sim, {"sorted_sim"})
                 .Define("elec_Q2_sim_pid", "Q2_sim_elec_pid[0]");
-                */
-  //Testing script
-/*
-  auto dis = d0.Display({"p_diff"});
-  //dis -> Print();
-  cout << *d0.Max<double>("elec_Q2_recon_rand") << " " << *d0.Min<double>("elec_Q2_recon_rand") << endl;
-  cout << *d0.Max<double>("elec_Q2_sim") << " " << *d0.Min<double>("elec_Q2_sim") << endl;
-/**/
-  //cout << *d0.Count() << endl;
-  //Momentum
-  //auto h_mom_sim = d0.Histo1D({"h_mom_sim", "; GeV; counts", 100, 0, 50}, "mom_sim");
-  //auto h_mom_rec = d0.Histo1D({"h_mom_rec", "; GeV; counts", 100, 0, 50}, "mom_rec");
-  //Q2
-  auto h_Q2_sim = d0.Histo1D({"h_Q2_sim", "; GeV; counts", 100, -5, 25}, "elec_Q2_sim");
-  auto h_Q2_rec = d0.Histo1D({"h_Q2_rec", "; GeV; counts", 100, -5, 25}, "elec_Q2_recon_rand");
-  auto h_Q2_res = d0.Histo1D({"h_Q2_res", ";    ; counts", 100, -10, 10}, "Q2_diff");
-/*
-  TH1D *h_Q2_res = (TH1D *)h_Q2_sim -> Clone();
-  TH1D *h_Q2_rec_copy = (TH1D *)h_Q2_rec -> Clone();
-  h_Q2_res -> Scale(1.0 / h_Q2_res -> Integral() );
-  h_Q2_res -> Add(h_Q2_rec_copy, -1.0 / h_Q2_rec_copy -> Integral() );
- */
-  TFitResultPtr f1  = h_Q2_res -> Fit("gaus", "S");
-  f1 -> Print("V");
-/*
-  printf("chisq %f A %f mean %f sigma %f \n", f1 -> Chi2(), 
-                                              f1 -> GetParameter(0), 
-                                              f1 -> GetParameter(1),
-                                              f1 -> GetParameter(2));
-*/
+  // Testing script
+  /*
+    auto dis = d0.Display({"Q2_sim", "elec_Q2_recon", "elec_Q2_sim", "elec_Q2_sim_pid"});
+    dis -> Print();
+    cout << *d0.Max<double>("elec_Q2_recon") << " " << *d0.Min<double>("elec_Q2_recon") << endl;
+  */
+  // cout << *d0.Count() << endl;
+  // Momentum
+  // auto h_mom_sim = d0.Histo1D({"h_mom_sim", "; GeV; counts", 100, 0, 50}, "mom_sim");
+  // auto h_mom_rec = d0.Histo1D({"h_mom_rec", "; GeV; counts", 100, 0, 50}, "mom_rec");
+  // Q2
+  auto h_Q2_sim = d0.Histo1D({"h_Q2_sim", "; GeV; counts", 100, -50, 50}, "elec_Q2_sim");
+  auto h_Q2_rec = d0.Histo1D({"h_Q2_rec", "; GeV; counts", 100, -50, 50}, "elec_Q2_recon");
+
+  TH1D* h_Q2_res      = (TH1D*)h_Q2_sim->Clone();
+  TH1D* h_Q2_rec_copy = (TH1D*)h_Q2_rec->Clone();
+  h_Q2_res->Scale(1.0 / h_Q2_res->Integral());
+  h_Q2_res->Add(h_Q2_rec_copy, -1.0 / h_Q2_rec_copy->Integral());
+
+  TFitResultPtr f1 = h_Q2_res->Fit("gaus", "S");
+  f1->Print("V");
+  /*
+    printf("chisq %f A %f mean %f sigma %f \n", f1 -> Chi2(),
+                                                f1 -> GetParameter(0),
+                                                f1 -> GetParameter(1),
+                                                f1 -> GetParameter(2));
+  */
 
-  
   auto c = new TCanvas();
 
   // Plot our histograms.
@@ -260,10 +237,11 @@ int dis_electrons(const std::string& config_name)
     c.cd();
     // gPad->SetLogx(false);
     gPad->SetLogy(true);
-    //auto& h1 = *h_mom_sim;
-    //auto& h2 = *h_mom_rec;
+    // auto& h1 = *h_mom_sim;
+    // auto& h2 = *h_mom_rec;
     auto& h1 = *h_Q2_sim;
     auto& h2 = *h_Q2_rec;
+    h2.Scale(2.0);
     // histogram style
     h1.SetLineColor(plot::kMpBlue);
     h1.SetLineWidth(2);
-- 
GitLab