diff --git a/benchmarks/dvmp/analysis/dvmp.h b/benchmarks/dvmp/analysis/dvmp.h index 20e6b9537a5a7c4478993f1bc74c1a3fb92b042e..40f3e82b7689cd010eaf930ca8464c9bfc642390 100644 --- a/benchmarks/dvmp/analysis/dvmp.h +++ b/benchmarks/dvmp/analysis/dvmp.h @@ -19,95 +19,134 @@ namespace util { //======================================================================================================== // for structure functions - struct inv_quant { // add more when needed - double nu, Q2, x, t; + double nu, Q2, x, y, t; }; - - // for simu - 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]);//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}; - return quantities; + //import Geant4 and set the wanted particles in the intended order + //0:e0 1:p0 2:e1 3:p1 4:recoil system (without p1) 5:l1 from 4 6:l2 from 4 + inline auto momenta_sort_sim(const std::vector<dd4pod::Geant4ParticleData>& parts, std::string_view mother, std::string_view daughter){//mother and daughter are not used yet; will be useful when generater is different and/or when the mcparticles doesn't follow the same order in all events + std::vector<ROOT::Math::PxPyPzMVector> momenta{7}; + int order_map[7] = {0, 3, 2, 6, 5, 7, 8}; + for(int i = 0 ; i < 7 ; i++){ + double px = parts[order_map[i]].psx; + double py = parts[order_map[i]].psy; + double pz = parts[order_map[i]].psz; + double mass = parts[order_map[i]].mass; + double e = sqrt(px*px + py*py + pz*pz + mass*mass); + momenta[i].SetPxPyPzE(px, py, pz, e); + } + //for(int i = 0 ; i < 7 ; i++){ + // cout<<Form("sim, idx = %d, P(px, py, pz, mass) = (%f, %f, %f, %f)", i, momenta[i].px(), momenta[i].py(), momenta[i].pz(), momenta[i].mass())<<endl; + //} + //cout<<"========================================="<<endl; + return momenta; } - //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){ + //import Reconstructed particles and set the wanted particles in the intended order======================== + inline auto momenta_sort_rec(const std::vector<eic::ReconstructedParticleData>& parts, std::string_view mother, std::string_view daughter){ + std::vector<ROOT::Math::PxPyPzMVector> momenta{7}; + //0:e0 1:p0 2:e1 3:p1 4:recoil system (without p1) 5:l1 from recoil decay 6:l2 from recoil decay + for(int i = 0 ; i < 7 ; i++) momenta[i].SetPxPyPzE(0., 0., 0., 0.); //initialize as all 0 + + //manually set incoming electron and proton; + double e0_mass = get_pdg_mass("electron"); + double e0_pz = 1.305e-8 - 10.; + momenta[0].SetPxPyPzE(0., 0., e0_pz, sqrt(e0_mass*e0_mass + e0_pz*e0_pz)); + double p0_mass = get_pdg_mass("proton"); + double p0_pz = 99.995598 + 1.313e-7 + 8.783e-11; + momenta[1].SetPxPyPzE(0., 0., p0_pz, sqrt(p0_mass*p0_mass + p0_pz*p0_pz)); + + //FIXME search for recoil proton, add feature to deal with multiple protons in one event + for(int i = 0 ; i < parts.size() ; i++){ + if(parts[i].pid!=2212) continue; + //px, py, pz, e, mass are not consistent for smeared dummy rc. this is a temp solution, replacing non-smeared energy by the re-calculated energy + //double energy_tmp = sqrt(parts[i].p.x*parts[i].p.x + parts[i].p.y*parts[i].p.y + parts[i].p.z*parts[i].p.z + parts[i].mass*parts[i].mass);//tmpsolution + double energy_tmp = parts[i].energy; + momenta[3].SetPxPyPzE(parts[i].p.x, parts[i].p.y, parts[i].p.z, energy_tmp); + } + + //search for di-lepton pair for the decay in recoil + int daughter_pid = -1; //unsigned + if(daughter == "electron"){ + daughter_pid = 11; + }else if(daughter == "muon"){ + daughter_pid = 13; + } 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)) { + double best_mass = -999.; + for (int i = 0 ; i < parts.size() ; ++i) { + if( fabs(parts[i].pid)!=daughter_pid) continue; + for (int j = i + 1 ; j < parts.size() ; ++j) { + if( parts[j].pid!= - parts[i].pid) continue; + ROOT::Math::PxPyPzMVector lpt_1(0.,0.,0.,0.); + //double energy_tmp1 = sqrt(parts[i].p.x*parts[i].p.x + parts[i].p.y*parts[i].p.y + parts[i].p.z*parts[i].p.z + parts[i].mass*parts[i].mass);//tmpsolution + double energy_tmp1 = parts[i].energy; + lpt_1.SetPxPyPzE(parts[i].p.x, parts[i].p.y, parts[i].p.z, energy_tmp1); + ROOT::Math::PxPyPzMVector lpt_2(0.,0.,0.,0.); + //double energy_tmp2 = sqrt(parts[j].p.x*parts[j].p.x + parts[j].p.y*parts[j].p.y + parts[j].p.z*parts[j].p.z + parts[j].mass*parts[j].mass);//tmpsolution + double energy_tmp2 = parts[j].energy; + lpt_2.SetPxPyPzE(parts[j].p.x, parts[j].p.y, parts[j].p.z, energy_tmp2); + const double new_mass{(lpt_1 + lpt_2).mass()}; + if (fabs(new_mass - get_pdg_mass(mother)) < fabs(best_mass - get_pdg_mass(mother))) { first = i; second = j; best_mass = new_mass; + momenta[5].SetPxPyPzE(parts[i].p.x, parts[i].p.y, parts[i].p.z, energy_tmp1); + momenta[6].SetPxPyPzE(parts[j].p.x, parts[j].p.y, parts[j].p.z, energy_tmp2); } + } } - - 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")); - 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; - + //FIXME search for scattered electron, need improvement with more complex events //float dp = 10.; for(int i = 0 ; i < parts.size(); i++){ 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(parts[i].pid != 11) continue; + //float ptmp = sqrt(parts[i].p.x*parts[i].p.x + parts[i].p.y*parts[i].p.y + parts[i].p.z*parts[i].p.z); //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; + //double energy_tmp = sqrt(parts[i].p.x*parts[i].p.x + parts[i].p.y*parts[i].p.y + parts[i].p.z*parts[i].p.z + parts[i].mass*parts[i].mass);//tmpsolution + double energy_tmp = parts[i].energy; + momenta[2].SetPxPyPzE(parts[i].p.x, parts[i].p.y, parts[i].p.z, energy_tmp); // dp = 10. - ptmp; //} } - if(scatteredIdx ==-1){ - inv_quant quantities = {-99999., -99999., -99999., -99999.}; - 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}; + //for(int i = 0 ; i < 7 ; i++){ + // cout<<Form("dum, idx = %d, P(px, py, pz, mass) = (%f, %f, %f, %f)", i, momenta[i].px(), momenta[i].py(), momenta[i].pz(), momenta[i].mass())<<endl; + //} + //cout<<"========================================="<<endl; + return momenta; + } + + inline inv_quant calc_inv_quant(const std::vector<ROOT::Math::PxPyPzMVector>& parts) + { + //0:e0 1:p0 2:e1 3:p1 4:recoil system (without p1) 5:l1 from 4 6:l2 from 4 + ROOT::Math::PxPyPzMVector q(parts[0] - parts[2]); + ROOT::Math::PxPyPzMVector k(parts[0]); + ROOT::Math::PxPyPzMVector P(parts[1]); + ROOT::Math::PxPyPzMVector Delta(parts[3] - parts[1]);//exact + ROOT::Math::PxPyPzMVector Delta_prime(parts[0] - parts[2] - parts[5] - parts[6]);//exclude gamma radiation in jpsi decay + + double nu = q.Dot(P) / P.mass(); + double Q2 = -q.Dot(q); + double t = 0.; + //if(parts[4].px() == 0. && parts[4].py() == 0. && parts[4].pz() == 0. && parts[4].mass() == 0.){ + //t = Delta_prime.Dot(Delta_prime); + //}else{ + t = Delta.Dot(Delta); + //} + double y = q.Dot(P) / k.Dot(P); + inv_quant quantities = {nu, Q2, Q2/2./P.mass()/nu, y, t}; 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_y(inv_quant quantities) { return quantities.y; } 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 21be3710106ac4495b03c26ae5a9d2eed4499b80..5c544e2be49d801889135bd67be94eb86120439e 100644 --- a/benchmarks/dvmp/analysis/vm_invar.cxx +++ b/benchmarks/dvmp/analysis/vm_invar.cxx @@ -71,41 +71,46 @@ int vm_invar(const std::string& config_name) // utility lambda functions to bind the vector meson and decay particle // types - 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); + auto momenta_sort_sim = [vm_name, decay_name](const std::vector<dd4pod::Geant4ParticleData>& parts){ + return util::momenta_sort_sim(parts, vm_name, decay_name); + }; + auto momenta_sort_rec = [vm_name, decay_name](const std::vector<eic::ReconstructedParticleData>& parts){ + return util::momenta_sort_rec(parts, vm_name, decay_name); }; - //==================================================================== // Define analysis flow - auto d_im = d.Define("p_rec", util::momenta_RC, {"DummyReconstructedParticles"}) - .Define("N", "p_rec.size()") - .Define("p_sim", util::momenta_from_simulation, {"mcparticles2"}) - //================================================================ - .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"}) + auto d_im = d.Define("p_rec_sorted", momenta_sort_rec, {"DummyReconstructedParticles"}) + .Define("p_sim_sorted", momenta_sort_sim, {"mcparticles2"}) + .Define("N", "p_rec_sorted.size()") + .Define("invariant_quantities_rec", util::calc_inv_quant, {"p_rec_sorted"}) + .Define("invariant_quantities_sim", util::calc_inv_quant, {"p_sim_sorted"}) + .Define("y_rec", util::get_y, {"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("y_sim", util::get_y, {"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 - 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_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};#", 50, 0., 15.}, "Q2_sim"); + auto h_x_sim = d_im.Histo1D({"h_x_sim", ";x;#", 50, 0., 0.1}, "x_sim"); + auto h_y_sim = d_im.Histo1D({"h_y_sim", ";y;#", 50, 0., 1.}, "y_sim"); + auto h_t_sim = d_im.Histo1D({"h_t_sim", ";t;#", 50, -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};#", 50, 0., 15.}, "Q2_rec"); + auto h_x_rec = d_im.Histo1D({"h_x_rec", ";x;#", 50, 0., 0.1}, "x_rec"); + auto h_y_rec = d_im.Histo1D({"h_y_rec", ";y;#", 50, 0., 1.}, "y_rec"); + auto h_t_rec = d_im.Histo1D({"h_t_rec", ";t;#", 50, -1., 0.}, "t_rec"); - 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 // factorize out the plotting code moving forward. @@ -117,18 +122,18 @@ int vm_invar(const std::string& config_name) c.Divide(2, 2, 0.0001, 0.0001); // pad 1 nu c.cd(1); - auto& hnu_rec = *h_nu_rec; - auto& hnu_sim = *h_nu_sim; + auto& hy_rec = *h_y_rec; + auto& hy_sim = *h_y_sim; // histogram style - hnu_rec.SetLineColor(plot::kMpOrange); - hnu_rec.SetLineWidth(1); - hnu_sim.SetLineColor(plot::kMpBlue); - hnu_sim.SetLineWidth(2); + hy_rec.SetLineColor(plot::kMpOrange); + hy_rec.SetLineWidth(1); + hy_sim.SetLineColor(plot::kMpBlue); + hy_sim.SetLineWidth(2); // axes - hnu_sim.GetXaxis()->CenterTitle(); + hy_sim.GetXaxis()->CenterTitle(); // draw everything - hnu_sim.DrawClone("hist"); - hnu_rec.DrawClone("hist same"); + hy_sim.DrawClone("hist"); + hy_rec.DrawClone("hist same"); // FIXME hardcoded beam configuration plot::draw_label(10, 100, detector); TText* tptr1; @@ -196,7 +201,7 @@ int vm_invar(const std::string& config_name) tptr3->SetTextColor(plot::kMpOrange); t3->Draw(); - // pad 3 x + // pad 4 t c.cd(4); auto& ht_rec = *h_t_rec; auto& ht_sim = *h_t_sim; diff --git a/benchmarks/dvmp/analysis/vm_mass.cxx b/benchmarks/dvmp/analysis/vm_mass.cxx index 48b05db406d0853205e66d72333a7e2257c53a0e..9d9b32b1aa8d0b51113483587c9b8d552f373aec 100644 --- a/benchmarks/dvmp/analysis/vm_mass.cxx +++ b/benchmarks/dvmp/analysis/vm_mass.cxx @@ -175,17 +175,17 @@ int vm_mass(const std::string& config_name) 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.); + //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"); + //mfPt->Draw("same"); // FIXME hardcoded beam configuration diff --git a/options/tracker_reconstruction.py b/options/tracker_reconstruction.py index 50fff6b829cb92e79c0c2d4a68a4c12a68d5755e..6bef5d7b817f3bc0910830e4bb17b7598f3c38bc 100644 --- a/options/tracker_reconstruction.py +++ b/options/tracker_reconstruction.py @@ -57,8 +57,7 @@ podioinput = PodioInput("PodioReader", dummy = MC2DummyParticle("MC2Dummy", inputCollection="mcparticles", outputCollection="DummyReconstructedParticles", - smearing=0.0 - ) + smearing = 0.0) ## copiers to get around input --> output copy bug. Note the "2" appended to the output collection. copier = MCCopier("MCCopier",