6 #include "cetlib/pow.h" 17 #include "Math/Functor.h" 18 #include "Math/GenVector/PositionVector3D.h" 19 #include "Minuit2/Minuit2Minimizer.h" 22 #include "TGraphErrors.h" 24 #include "TMatrixDSymEigen.h" 25 #include "TMatrixDSymfwd.h" 26 #include "TMatrixDfwd.h" 28 #include "TMatrixTSym.h" 29 #include "TPolyLine3D.h" 31 #include "TVectorDfwd.h" 42 constexpr
double LAr_density{1.396};
43 constexpr
double rad_length{14.0};
44 constexpr
double m_muon{0.1057};
45 constexpr
auto range_gramper_cm()
47 std::array<double, 73> Range_grampercm{
48 {0.9833, 1.36, 1.786, 2.507, 3.321, 4.859, 6.598, 8.512, 10.58, 12.78,
49 15.1, 17.52, 20.04, 25.31, 30.84, 36.59, 42.5, 54.73, 67.32, 86.66,
50 106.3, 139.4, 172.5, 205.6, 238.5, 271.1, 303.5, 335.7, 367.7, 431.0,
51 493.4, 555.2, 616.3, 736.8, 855.2, 1030.0, 1202.0, 1482.0, 1758.0, 2029.0,
52 2297.0, 2562.0, 2825.0, 3085.0, 3343.0, 3854.0, 4359.0, 4859.0, 5354.0, 6333.0,
53 7298.0, 8726.0, 10130.0, 12430.0, 14690.0, 16920.0, 19100.0, 21260.0, 23380.0, 25480.0,
54 27550.0, 31610.0, 35580.0, 39460.0, 43260.0, 50620.0, 57680.0, 67780.0, 77340.0, 92220.0,
55 1.06e+05, 1.188e+05, 1.307e+05}};
56 for (
double&
value : Range_grampercm) {
59 return Range_grampercm;
62 constexpr
auto Range_grampercm = range_gramper_cm();
63 constexpr std::array<double, 73> KE_MeV{
64 {10.0, 12.0, 14.0, 17.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0,
65 50.0, 55.0, 60.0, 70.0, 80.0, 90.0, 100.0, 120.0, 140.0, 170.0,
66 200.0, 250.0, 300.0, 350.0, 400.0, 450.0, 500.0, 550.0, 600.0, 700.0,
67 800.0, 900.0, 1000.0, 1200.0, 1400.0, 1700.0, 2000.0, 2500.0, 3000.0, 3500.0,
68 4000.0, 4500.0, 5000.0, 5500.0, 6000.0, 7000.0, 8000.0, 9000.0, 10000.0, 12000.0,
69 14000.0, 17000.0, 20000.0, 25000.0, 30000.0, 35000.0, 40000.0, 45000.0, 50000.0, 55000.0,
70 60000.0, 70000.0, 80000.0, 90000.0, 1
e+05, 1.2e+05, 1.4e+05, 1.7e+05, 2
e+05, 2.5e+05,
71 3
e+05, 3.5e+05, 4
e+05}};
72 TGraph
const KEvsR{73, Range_grampercm.data(), KE_MeV.data()};
73 TSpline3
const KEvsR_spline3{
"KEvsRS", &KEvsR};
75 constexpr std::array<double, 73> KE_MeV_Pi{
76 {11.1928, 13.4567, 15.6946, 19.0487, 22.3945, 27.9408, 33.4579, 38.9494, 44.4198,
77 49.8612, 55.2838, 60.6757, 66.0632, 76.7631, 87.3839, 97.9617, 108.461, 129.341,
78 150.023, 180.793, 211.275, 261.704, 311.585, 361.284, 410.705, 459.809, 508.805,
79 557.727, 606.592, 704.011, 801.047, 898.111, 994.983, 1188.51, 1381.61, 1671.44,
80 1961.46, 2442.32, 2925.25, 3406.69, 3888.88, 4370.85, 4853.71, 5335.02, 5816.14,
81 6778.21, 7739.41, 8699.89, 9658.32, 11572.9, 13480.8, 16335.1, 19171.0, 23866.9,
82 28529.9, 33169.1, 37734.7, 42284.0, 46770.4, 51233.2, 55648.5, 64349.8, 72904.4,
83 81303.4, 89561.4, 1.06e+05, 1.21e+05, 1.43e+05, 1.65e+05, 1.98e+05, 2.28e+05, 2.55e+05,
85 TGraph
const KEvsRPi{73, Range_grampercm.data(), KE_MeV_Pi.data()};
86 TSpline3
const KEvsRPi_spline3{
"KEvsRS_pion", &KEvsRPi};
89 std::vector<double> dedx_GeV_per_cm()
92 std::vector<double>
dEdx{
93 {5.687, 4.979, 4.461, 3.902, 3.502, 3.042, 2.731, 2.508, 2.34, 2.21, 2.107, 2.023, 1.954,
94 1.848, 1.771, 1.713, 1.67, 1.609, 1.57, 1.536, 1.519, 1.508, 1.51, 1.517, 1.526, 1.537,
95 1.548, 1.559, 1.57, 1.591, 1.61, 1.628, 1.645, 1.675, 1.7, 1.733, 1.761, 1.799, 1.829,
96 1.855, 1.877, 1.897, 1.914, 1.93, 1.944, 1.969, 1.991, 2.01, 2.028, 2.058, 2.084, 2.119,
97 2.149, 2.193, 2.232, 2.269, 2.304, 2.337, 2.369, 2.4, 2.43, 2.49, 2.548, 2.606, 2.663,
98 2.776, 2.888, 3.055, 3.224, 3.498, 3.774, 4.052, 4.332}};
100 value *= LAr_density * 1
e-3;
105 const int ndedx = 73;
106 const std::vector<double> dEdx_GeV_per_cm = dedx_GeV_per_cm();
107 const std::vector<double> E_GeV{
108 {0.115695, 0.117697, 0.119693, 0.122694, 0.125695, 0.13069, 0.135694, 0.14069, 0.145714,
109 0.150689, 0.155682, 0.160666, 0.165693, 0.17566, 0.185714, 0.1957, 0.205644, 0.225683,
110 0.245698, 0.275669, 0.305658, 0.355669, 0.405711, 0.45563, 0.505671, 0.555646, 0.605694,
111 0.655676, 0.705661, 0.805664, 0.905689, 1.00557, 1.10606, 1.30529, 1.50571, 1.8061,
112 2.10565, 2.60614, 3.1058, 3.60555, 4.10536, 4.60521, 5.10609, 5.606, 6.10591,
113 7.10579, 8.10569, 9.10561, 10.1106, 12.1105, 14.1104, 17.1103, 20.1103, 25.1102,
114 30.1102, 35.1102, 40.1101, 45.1101, 50.1101, 55.1101, 60.1101, 70.1101, 80.1101,
115 90.1101, 100.1, 120.1, 140.1, 170.1, 200.1, 250.1, 300.1, 350.1,
117 TGraph
const dEdx_vs_E{ndedx, E_GeV.data(), dEdx_GeV_per_cm.data()};
118 TSpline3
const dEdx_vs_E_spline3{
"dEdx_vs_E", &dEdx_vs_E};
120 TVector3
const basex{1, 0, 0};
121 TVector3
const basey{0, 1, 0};
122 TVector3
const basez{0, 0, 1};
123 constexpr
double kcal{0.0024};
125 constexpr
double MomentumDependentConstant(
const double p)
130 return (a / (p * p)) + c;
132 double ComputeExpetecteRMS(
const double p,
const double red_length)
134 double beta = std::sqrt(1 - ((m_muon * m_muon) / (p * p + m_muon * m_muon)));
135 return (MomentumDependentConstant(p) / (p * beta)) *
136 (1.0 + 0.038 * TMath::Log(red_length / cet::square(beta))) * std::sqrt(red_length);
140 explicit FcnWrapper(std::vector<double>&& xmeas,
141 std::vector<double>&& ymeas,
142 std::vector<double>&& eymeas,
144 : xmeas_{std::move(xmeas)}
145 , ymeas_{std::move(ymeas)}
146 , eymeas_{std::move(eymeas)}
147 , correction_{correction}
150 double my_mcs_chi2(
double const*
x)
const 155 double theta0 = x[1];
157 auto const n = xmeas_.size();
158 assert(
n == ymeas_.size());
159 assert(
n == eymeas_.size());
161 for (std::size_t i = 0; i <
n; ++i) {
162 double const xx = xmeas_[i];
163 double const yy = ymeas_[i];
164 double const ey = eymeas_[i];
166 if (
std::abs(ey) < std::numeric_limits<double>::epsilon()) {
167 std::cout <<
" Zero denominator in my_mcs_chi2 ! " << std::endl;
171 double const l0 = xx / rad_length;
175 double beta = std::sqrt(1 - ((m_muon * m_muon) / (p * p + m_muon * m_muon)));
177 res1 = (13.6 / (p * beta)) * (1.0 + 0.038 * TMath::Log(l0 / cet::square(beta))) *
181 res1 = std::hypot(res1, theta0);
183 double const diff = yy - res1;
184 result += cet::square(diff / ey);
187 if (std::isnan(result) || std::isinf(result)) {
188 MF_LOG_DEBUG(
"TrackMomentumCalculator") <<
" Is nan in my_mcs_chi2 ! ";
196 std::vector<double>
const xmeas_;
197 std::vector<double>
const ymeas_;
198 std::vector<double>
const eymeas_;
199 double const correction_;
202 class FcnWrapperLLHD {
204 explicit FcnWrapperLLHD(std::vector<double>&& dEi,
205 std::vector<double>&& dEj,
206 std::vector<double>&& dthij,
207 std::vector<double>&& ind,
208 std::vector<bool>&& dthij_valid,
211 : dEi_{std::move(dEi)}
212 , dEj_{std::move(dEj)}
213 , dthij_{std::move(dthij)}
214 , ind_{std::move(ind)}
215 , dthij_valid_{std::move(dthij_valid)}
216 , stepsize_{stepsize}
217 , correction_{correction}
220 double my_mcs_llhd(
double const* x)
const 224 double red_length = stepsize_ / rad_length;
227 double theta0 = x[1];
230 double Etot = std::hypot(p, m_muon);
235 auto const n = dEi_.size();
237 bool addpenality =
false;
238 for (std::size_t i = 0; i <
n; ++i) {
240 if (Ei >= E_GeV[0]) {
241 dEi = dEdx_vs_E_spline3.Eval(Ei) * stepsize_;
244 dEi = dEdx_GeV_per_cm[0] * stepsize_;
253 if (dthij_valid_.at(i) ==
false)
continue;
256 double pij = std::sqrt(Ei * Ei - m_muon * m_muon);
261 double tH0 = ComputeExpetecteRMS(pij, red_length);
267 double rms_square = -1.0;
272 rms_square = cet::sum_of_squares(tH0, theta0);
277 prob = -0.5 * std::log(2.0 * TMath::Pi()) - 0.5 * std::log(rms_square) -
278 0.5 * DT * DT / rms_square;
280 if (addpenality) { prob -= 2 * rms_square; }
282 result = result - 2.0 * prob;
289 std::vector<double>
const dEi_;
290 std::vector<double>
const dEj_;
291 std::vector<double>
const dthij_;
292 std::vector<double>
const ind_;
293 std::vector<bool>
const dthij_valid_;
294 double const stepsize_;
295 double const correction_;
302 TrackMomentumCalculator::TrackMomentumCalculator(
double const min,
304 double const stepsize,
305 int const angleMethod,
313 for (
int i = 1; i <=
n_steps; i++) {
394 if (trkrange < 0 || std::isnan(trkrange)) {
395 mf::LogError(
"TrackMomentumCalculator") <<
"Invalid track range " << trkrange <<
" return -1";
399 double KE, Momentum, M;
400 constexpr
double Muon_M = m_muon * 1e3, Proton_M = 938.272, Pion_M = 139.57039;
402 if (
abs(pdg) == 13) {
404 KE = KEvsR_spline3.Eval(trkrange);
406 else if (
abs(pdg) == 2212) {
408 if (trkrange > 0 && trkrange <= 80)
409 KE = 29.9317 * std::pow(trkrange, 0.586304);
410 else if (trkrange > 80 && trkrange <= 3.022E3)
411 KE = 149.904 + (3.34146 * trkrange) + (-0.00318856 * trkrange * trkrange) +
412 (4.34587E-6 * trkrange * trkrange * trkrange) +
413 (-3.18146
E-9 * trkrange * trkrange * trkrange * trkrange) +
414 (1.17854E-12 * trkrange * trkrange * trkrange * trkrange * trkrange) +
415 (-1.71763
E-16 * trkrange * trkrange * trkrange * trkrange * trkrange * trkrange);
419 else if (
abs(pdg) == 211) {
421 KE = KEvsRPi_spline3.Eval(trkrange);
429 Momentum = std::sqrt((KE * KE) + (2 * M * KE));
431 Momentum = Momentum / 1000;
446 const bool checkValidPoints,
447 const int maxMomentum_MeV,
448 const double min_resolution,
449 const double max_resolution,
450 const bool check_valid_scattered,
451 const double angle_correction)
454 std::vector<double> recoX;
455 std::vector<double> recoY;
456 std::vector<double> recoZ;
460 for (
int i = 0; i < n_points; i++) {
463 recoX.push_back(pos.X());
464 recoY.push_back(pos.Y());
465 recoZ.push_back(pos.Z());
468 if (recoX.size() < 2)
return -1.0;
474 auto const segments =
getSegTracks_(recoX, recoY, recoZ, seg_size, check_valid_scattered);
475 if (!segments.has_value())
return -1.0;
477 auto const seg_steps = segments->x.size();
478 if (seg_steps < 2)
return -1;
480 double const recoSegmentLength = segments->L.at(seg_steps - 1);
481 if (recoSegmentLength < minLength || recoSegmentLength >
maxLength)
return -1;
483 std::vector<double> dEi;
484 std::vector<double> dEj;
485 std::vector<double> dthij;
486 std::vector<double> ind;
487 std::vector<bool> dthij_valid = segments->nvalid;
488 if (
getDeltaThetaij_(dEi, dEj, dthij, ind, *segments, seg_size, angle_correction) != 0)
491 auto const ndEi = dEi.size();
492 if (ndEi < 1)
return -1;
494 double correction = 1.;
498 auto recoL = trk->
Length();
501 ROOT::Minuit2::Minuit2Minimizer mP{};
502 FcnWrapperLLHD
const wrapper{std::move(dEi),
506 std::move(dthij_valid),
509 ROOT::Math::Functor FCA([&wrapper](
double const* xs) {
return wrapper.my_mcs_llhd(xs); }, 2);
515 double startpoint = 2;
516 if (startpoint < min_resolution)
517 startpoint = (max_resolution - min_resolution) / 2.;
518 bool fixresolution =
false;
519 double maxres = max_resolution;
520 if (max_resolution == 0 || max_resolution <= min_resolution) {
521 fixresolution =
true;
522 startpoint = min_resolution;
529 mP.SetLimitedVariable(0,
"p_{MCS}", minP * 2, minP * 0.1, minP * 0.6, maxMomentum_MeV / 1.e3);
530 mP.SetLimitedVariable(1,
"#delta#theta", startpoint, startpoint / 2., min_resolution, maxres);
531 if (fixresolution) { mP.FixVariable(1); }
532 mP.SetMaxFunctionCalls(1.E9);
533 mP.SetMaxIterations(1.E9);
534 mP.SetTolerance(0.01);
538 bool const mstatus = mP.Minimize();
542 const double* pars = mP.X();
544 double const p_mcs = pars[0];
546 return mstatus ? p_mcs : -1.0;
554 if (LLHDp != -1 && LLHDm != -1 && LLHDp > LLHDm) {
569 std::vector<double> recoX;
570 std::vector<double> recoY;
571 std::vector<double> recoZ;
574 for (
int i = 0; i < n_points; ++i) {
575 auto const index = dir ? i : n_points - 1 - i;
577 recoX.push_back(pos.X());
578 recoY.push_back(pos.Y());
579 recoZ.push_back(pos.Z());
582 if (recoX.size() < 2)
return -1.0;
586 constexpr
double seg_size{5.0};
587 auto const segments =
getSegTracks_(recoX, recoY, recoZ, seg_size);
588 if (!segments.has_value())
return -1.0;
590 auto const seg_steps = segments->x.size();
591 if (seg_steps < 2)
return -1;
593 double const recoSegmentLength = segments->L.at(seg_steps - 1);
594 if (recoSegmentLength < 15.0 || recoSegmentLength >
maxLength)
return -1;
596 std::vector<double> dEi;
597 std::vector<double> dEj;
598 std::vector<double> dthij;
599 std::vector<double> ind;
600 double angle_correction = 1;
601 if (
getDeltaThetaij_(dEi, dEj, dthij, ind, *segments, seg_size, angle_correction) != 0)
604 auto const recoL = trk->
Length();
605 double const p_range = recoL * kcal;
606 double const logL =
my_mcs_llhd(dEi, dEj, dthij, ind, p_range, 5.65);
612 std::vector<double>& ej,
613 std::vector<double>& th,
614 std::vector<double>& ind,
617 double const angle_correction)
const 619 auto const& segnx = segments.
nx;
620 auto const& segny = segments.
ny;
621 auto const& segnz = segments.
nz;
622 auto const& segL = segments.
L;
624 int const a1 = segnx.size();
625 int const a2 = segny.size();
626 int const a3 = segnz.size();
628 if (a1 != a2 || a1 != a3) {
629 std::cout <<
" ( Get thij ) Error ! " << std::endl;
635 for (
int i = 0; i < tot - 1; i++) {
636 double const dx = segnx.at(i);
637 double const dy = segny.at(i);
638 double const dz = segnz.at(i);
641 TVector3
const vec_z{dx, dy, dz};
645 double const switcher = basex.Dot(vec_z);
647 vec_y = vec_z.Cross(basex).Unit();
648 vec_x = vec_y.Cross(vec_z);
652 vec_y = basez.Cross(vec_z).Unit();
653 vec_x = vec_y.Cross(vec_z);
656 TVector3
const Rx{vec_x.Dot(basex), vec_x.Dot(basey), vec_x.Dot(basez)};
657 TVector3
const Ry{vec_y.Dot(basex), vec_y.Dot(basey), vec_y.Dot(basez)};
658 TVector3
const Rz{vec_z.Dot(basex), vec_z.Dot(basey), vec_z.Dot(basez)};
660 double const here_dx = segnx.at(i + 1);
661 double const here_dy = segny.at(i + 1);
662 double const here_dz = segnz.at(i + 1);
664 TVector3
const here_vec{here_dx, here_dy, here_dz};
665 TVector3
const rot_here{Rx.Dot(here_vec), Ry.Dot(here_vec), Rz.Dot(here_vec)};
667 double const scx = rot_here.X();
668 double const scy = rot_here.Y();
669 double const scz = rot_here.Z();
674 constexpr
double ULim = 10000.0;
675 constexpr
double LLim = -10000.0;
677 double const Li = segL.at(i);
678 double const Lj = segL.at(i + 1);
680 if (azy <= ULim && azy >= LLim) {
682 if (azx <= ULim && azx >= LLim) {
692 th.push_back(std::hypot(azx, azy) /
703 const bool checkValidPoints,
704 const int maxMomentum_MeV,
705 const double min_resolution,
706 const double max_resolution)
708 std::vector<double> recoX;
709 std::vector<double> recoY;
710 std::vector<double> recoZ;
714 for (
int i = 0; i < n_points; i++) {
717 recoX.push_back(pos.X());
718 recoY.push_back(pos.Y());
719 recoZ.push_back(pos.Z());
722 if (recoX.size() < 2)
return -1.0;
727 auto const segments =
getSegTracks_(recoX, recoY, recoZ, seg_size);
728 if (!segments.has_value())
return -1.0;
730 auto const seg_steps = segments->x.size();
731 if (seg_steps < 2)
return -1;
733 double const recoSegmentLength = segments->L.at(seg_steps - 1);
734 if (recoSegmentLength < minLength || recoSegmentLength >
maxLength)
return -1;
736 double ymax = -999.0;
737 double ymin = +999.0;
739 std::vector<double> xmeas;
740 std::vector<double> ymeas;
741 std::vector<double> eymeas;
745 for (
int j = 0; j <
n_steps; j++) {
746 double const trial =
steps.at(j);
750 if (std::isnan(
mean) || std::isinf(
mean)) {
751 mf::LogDebug(
"TrackMomentumCalculator") <<
"Returned mean is either nan or infinity.";
754 if (std::isnan(rms) || std::isinf(rms)) {
755 mf::LogDebug(
"TrackMomentumCalculator") <<
"Returned rms is either nan or infinity.";
758 if (std::isnan(rmse) || std::isinf(rmse)) {
759 mf::LogDebug(
"TrackMomentumCalculator") <<
"Returned rmse is either nan or infinity.";
763 if (
mean == -1 && rms == -1 && rmse == -1)
continue;
764 xmeas.push_back(trial);
765 ymeas.push_back(rms);
767 std::hypot(rmse, 0.05 * rms));
769 if (ymin > rms) ymin = rms;
770 if (ymax < rms) ymax = rms;
773 assert(xmeas.size() == ymeas.size());
774 assert(xmeas.size() == eymeas.size());
775 if (xmeas.empty()) {
return -1.0; }
777 TGraphErrors gr_meas{
n_steps, xmeas.data(), ymeas.data(),
nullptr, eymeas.data()};
779 gr_meas.SetTitle(
"(#Delta#theta)_{rms} versus material thickness; Material " 780 "thickness in cm; (#Delta#theta)_{rms} in mrad");
782 gr_meas.SetLineColor(kBlack);
783 gr_meas.SetMarkerColor(kBlack);
784 gr_meas.SetMarkerStyle(20);
785 gr_meas.SetMarkerSize(1.2);
788 gr_meas.SetMinimum(0.0);
789 gr_meas.SetMaximum(1.80 * ymax);
791 double correction = 1.;
794 ROOT::Minuit2::Minuit2Minimizer mP{};
795 FcnWrapper
const wrapper{std::move(xmeas), std::move(ymeas), std::move(eymeas), correction};
796 ROOT::Math::Functor FCA([&wrapper](
double const* xs) {
return wrapper.my_mcs_chi2(xs); }, 2);
799 double startpoint = 2;
800 if (startpoint < min_resolution) startpoint = (max_resolution - min_resolution) / 2.;
801 bool fixresolution =
false;
802 double maxres = max_resolution;
803 if (max_resolution == 0 || max_resolution <= min_resolution) {
804 fixresolution =
true;
805 startpoint = min_resolution;
810 mP.SetLimitedVariable(0,
"p_{MCS}", 1.0, 0.01, 0.001, maxMomentum_MeV / 1.e3);
811 mP.SetLimitedVariable(1,
"#delta#theta", startpoint, startpoint / 2., min_resolution, maxres);
812 if (fixresolution) { mP.FixVariable(1); }
813 mP.SetMaxFunctionCalls(1.E9);
814 mP.SetMaxIterations(1.E9);
815 mP.SetTolerance(0.01);
819 bool const mstatus = mP.Minimize();
823 const double* pars = mP.X();
825 auto const recoL = trk->
Length();
826 double const deltap = (recoL * kcal) / 2.0;
828 double const p_mcs = pars[0] + deltap;
830 return mstatus ? p_mcs : -1.0;
834 std::vector<double>
const& yyy,
835 std::vector<double>
const& zzz)
837 auto const n = xxx.size();
838 auto const y_size = yyy.size();
839 auto const z_size = zzz.size();
841 if (n != y_size || n != z_size) {
842 cout <<
" ( Get reco tacks ) Error ! " << endl;
849 auto xs =
const_cast<double*
>(xxx.data());
850 auto ys =
const_cast<double*
>(yyy.data());
851 auto zs =
const_cast<double*
>(zzz.data());
853 auto const narrowed_size =
static_cast<int>(
n);
855 gr_reco_xyz =
new TPolyLine3D{narrowed_size, zs, xs, ys};
856 gr_reco_yz = TGraph{narrowed_size, zzz.data(), yyy.data()};
857 gr_reco_xz = TGraph{narrowed_size, zzz.data(), xxx.data()};
858 gr_reco_xy = TGraph{narrowed_size, xxx.data(), yyy.data()};
867 const std::vector<double> segy,
868 const std::vector<double> segz,
869 std::vector<double>& segnx,
870 std::vector<double>& segny,
871 std::vector<double>& segnz,
872 std::vector<bool>& segn_isvalid,
873 std::vector<double>& vx,
874 std::vector<double>& vy,
875 std::vector<double>& vz,
876 bool check_valid_scattered)
878 auto const na = vx.size();
887 if (check_valid_scattered && na <= 2) { isvalid =
false; }
890 for (std::size_t i = 0; i < na; ++i) {
900 std::vector<double> mx;
901 std::vector<double> my;
902 std::vector<double> mz;
907 for (std::size_t i = 0; i < na; ++i) {
908 double const xxw1 = vx.at(i);
909 double const yyw1 = vy.at(i);
910 double const zzw1 = vz.at(i);
912 mx.push_back(xxw1 - sumx);
913 my.push_back(yyw1 - sumy);
914 mz.push_back(zzw1 - sumz);
916 double const xxw0 = mx.at(i);
917 double const yyw0 = my.at(i);
918 double const zzw0 = mz.at(i);
920 m(0, 0) += xxw0 * xxw0 / na;
921 m(0, 1) += xxw0 * yyw0 / na;
922 m(0, 2) += xxw0 * zzw0 / na;
924 m(1, 0) += yyw0 * xxw0 / na;
925 m(1, 1) += yyw0 * yyw0 / na;
926 m(1, 2) += yyw0 * zzw0 / na;
928 m(2, 0) += zzw0 * xxw0 / na;
929 m(2, 1) += zzw0 * yyw0 / na;
930 m(2, 2) += zzw0 * zzw0 / na;
933 TMatrixDSymEigen me(m);
936 TVectorD eigenval = me.GetEigenValues();
937 TMatrixD eigenvec = me.GetEigenVectors();
939 double max1 = -666.0;
944 for (
int i = 0; i < 3; ++i) {
945 double const p1 = eigenval(i);
954 double ax = eigenvec(0, ind1);
955 double ay = eigenvec(1, ind1);
956 double az = eigenvec(2, ind1);
961 if (segx.at(
n_seg - 1) - segx.at(
n_seg - 2) > 0)
966 if (segy.at(
n_seg - 1) - segy.at(
n_seg - 2) > 0)
971 if (segz.at(
n_seg - 1) - segz.at(
n_seg - 2) > 0)
979 segn_isvalid.push_back(isvalid);
995 std::vector<double>
const& xxx,
996 std::vector<double>
const& yyy,
997 std::vector<double>
const& zzz,
998 double const seg_size,
999 bool const check_valid_scattered)
1003 int a1 = xxx.size();
1004 int a2 = yyy.size();
1005 int a3 = zzz.size();
1007 if ((a1 != a2) || (a1 != a3) || (a2 != a3)) {
1008 cout <<
" ( Digitize reco tacks ) Error ! " << endl;
1009 return std::nullopt;
1012 int const stopper =
seg_stop / seg_size;
1015 std::vector<double> segx, segnx;
1016 std::vector<double> segy, segny;
1017 std::vector<double> segz, segnz;
1018 std::vector<bool> segn_isvalid;
1019 std::vector<double> segL;
1027 double x00 = xxx.at(0);
1028 double y00 = yyy.at(0);
1029 double z00 = zzz.at(0);
1036 std::vector<double> vx;
1037 std::vector<double> vy;
1038 std::vector<double> vz;
1040 for (
int i = 0; i <
a1; i++) {
1045 double const RR0 = std::hypot(x00 - x0, y00 - y0, z00 - z0);
1072 for (
int i = indC; i < a1 - 1; i++) {
1074 double const x1 = xxx.at(i);
1075 double const y1 = yyy.at(i);
1076 double const z1 = zzz.at(i);
1079 double const dr1 = std::hypot(x1 - x0, y1 - y0, z1 - z0);
1082 double const x2 = xxx.at(i + 1);
1083 double const y2 = yyy.at(i + 1);
1084 double const z2 = zzz.at(i + 1);
1087 double const dr2 = std::hypot(x2 - x0, y2 - y0, z2 - z0);
1089 if (dr1 < seg_size) {
1106 if (dr1 <= seg_size && dr2 > seg_size) {
1107 double const dx = x2 -
x1;
1108 double const dy = y2 -
y1;
1109 double const dz = z2 - z1;
1110 double const dr = std::hypot(dx, dy, dz);
1113 cout <<
" ( Zero ) Error ! " << endl;
1114 return std::nullopt;
1117 double const beta = 2.0 * ((x1 - x0) * dx + (y1 - y0) * dy + (z1 - z0) * dz) / (dr * dr);
1119 double const gamma = (dr1 * dr1 - seg_size * seg_size) / (dr * dr);
1120 double const delta = beta * beta - 4.0 * gamma;
1123 cout <<
" ( Discriminant ) Error ! " << endl;
1124 return std::nullopt;
1128 double const lysi1 = (-beta + std::sqrt(delta)) / 2.0;
1129 double const t = lysi1;
1132 double const xp = x1 + t * dx;
1133 double const yp = y1 + t * dy;
1134 double const zp = z1 + t * dz;
1141 segL.push_back(
n_seg * seg_size);
1161 return std::nullopt;
1166 segx, segy, segz, segnx, segny, segnz, segn_isvalid, vx, vy, vz, check_valid_scattered);
1173 else if (dr1 > seg_size) {
1179 double const dx = x1 - x0;
1180 double const dy = y1 - y0;
1181 double const dz = z1 - z0;
1182 double const dr = std::hypot(dx, dy, dz);
1185 cout <<
" ( Zero ) Error ! " << endl;
1186 return std::nullopt;
1190 double const t = seg_size / dr;
1191 double const xp = x0 + t * dx;
1192 double const yp = y0 + t * dy;
1193 double const zp = z0 + t * dz;
1198 segL.push_back(1.0 *
n_seg * 1.0 * seg_size + stag);
1216 return std::nullopt;
1221 segx, segy, segz, segnx, segny, segnz, segn_isvalid, vx, vy, vz, check_valid_scattered);
1238 return std::make_optional<Segments>(
1239 Segments{segx, segnx, segy, segny, segz, segnz, segL, segn_isvalid});
1247 double const thick)
const 1249 auto const& segnx = segments.
nx;
1250 auto const& segny = segments.
ny;
1251 auto const& segnz = segments.
nz;
1252 auto const& segL = segments.
L;
1254 int const a1 = segnx.size();
1255 int const a2 = segny.size();
1256 int const a3 = segnz.size();
1258 if (a1 != a2 || a1 != a3) {
1259 cout <<
" ( Get RMS ) Error ! " << endl;
1260 return std::make_tuple(0., 0., 0.);
1265 std::vector<double> buf0;
1267 for (
int i = 0; i < tot; i++) {
1268 double const dx = segnx.at(i);
1269 double const dy = segny.at(i);
1270 double const dz = segnz.at(i);
1272 TVector3
const vec_z{dx, dy, dz};
1276 double const switcher = basex.Dot(vec_z);
1278 if (switcher <= 0.995) {
1279 vec_y = vec_z.Cross(basex).Unit();
1280 vec_x = vec_y.Cross(vec_z);
1284 vec_y = basez.Cross(vec_z).Unit();
1285 vec_x = vec_y.Cross(vec_z);
1288 TVector3
const Rx{vec_x.Dot(basex), vec_x.Dot(basey), vec_x.Dot(basez)};
1289 TVector3
const Ry{vec_y.Dot(basex), vec_y.Dot(basey), vec_y.Dot(basez)};
1290 TVector3
const Rz{vec_z.Dot(basex), vec_z.Dot(basey), vec_z.Dot(basez)};
1292 double const refL = segL.at(i);
1294 for (
int j = i; j < tot; j++) {
1295 double const L1 = segL.at(j);
1297 double const dz1 = L1 - refL;
1300 double const here_dx = segnx.at(j);
1301 double const here_dy = segny.at(j);
1302 double const here_dz = segnz.at(j);
1304 TVector3
const here_vec{here_dx, here_dy, here_dz};
1305 TVector3
const rot_here{Rx.Dot(here_vec), Ry.Dot(here_vec), Rz.Dot(here_vec)};
1307 double const scx = rot_here.X();
1308 double const scy = rot_here.Y();
1309 double const scz = rot_here.Z();
1314 constexpr
double ULim = 10000.0;
1315 constexpr
double LLim = -10000.0;
1317 if (azy <= ULim && azy >= LLim) {
1319 if (azx <= ULim && azx >= LLim) {
1321 buf0.push_back(azx);
1324 buf0.push_back(azy);
1327 buf0.push_back(std::hypot(azx, azy));
1336 int const nmeas = buf0.size();
1343 for (
int i = 0; i < nmeas; i++) {
1350 for (
int i = 0; i < nmeas; i++)
1351 rms += ((buf0.at(i)) * (buf0.at(i)));
1354 rms = std::sqrt(rms);
1355 rmse = rms / std::sqrt(2.0 * tot);
1362 double const lev1 = 2.50;
1364 for (
int i = 0; i < nmeas; i++) {
1365 double const amp = buf0.at(i);
1366 if (amp < (mean + lev1 * rms1) && amp > (mean - lev1 * rms1)) {
1372 rms = rms / (ntot1);
1373 rms = std::sqrt(rms);
1374 rmse = rms / std::sqrt(2.0 * ntot1);
1375 return std::make_tuple(mean, rms, rmse);
1380 double thetayz = -999.0;
1382 if (vz > 0 && vy > 0) {
1384 thetayz = std::atan(ratio);
1387 else if (vz < 0 && vy > 0) {
1389 thetayz = std::atan(ratio);
1390 thetayz = TMath::Pi() - thetayz;
1393 else if (vz < 0 && vy < 0) {
1395 thetayz = std::atan(ratio);
1396 thetayz = thetayz + TMath::Pi();
1399 else if (vz > 0 && vy < 0) {
1401 thetayz = std::atan(ratio);
1402 thetayz = 2.0 * TMath::Pi() - thetayz;
1405 else if (vz == 0 && vy > 0) {
1406 thetayz = TMath::Pi() / 2.0;
1409 else if (vz == 0 && vy < 0) {
1410 thetayz = 3.0 * TMath::Pi() / 2.0;
1412 else if (vz > 0 && vy == 0) {
1415 else if (vz < 0 && vy == 0) {
1416 thetayz = TMath::Pi();
1419 if (thetayz > TMath::Pi()) { thetayz = thetayz - 2.0 * TMath::Pi(); }
1421 return 1000.0 * thetayz;
1427 cout <<
" Error : The code tries to divide by zero ! " << endl;
1431 double const arg = (xx - Q) / s;
1432 double const result = -0.5 * std::log(2.0 * TMath::Pi()) - std::log(s) - 0.5 * arg * arg;
1434 if (std::isnan(result) || std::isinf(result)) {
1435 cout <<
" Is nan ! my_g ! " << -std::log(s) <<
", " << s << endl;
1442 std::vector<double>
const& dEj,
1443 std::vector<double>
const& dthij,
1444 std::vector<double>
const& ind,
1446 double const x1)
const 1449 double theta0x =
x1;
1451 double result = 0.0;
1452 double nnn1 = dEi.size();
1457 for (
int i = 0; i < nnn1; i++) {
1458 double Ei = p - dEi.at(i);
1459 double Ej = p - dEj.at(i);
1462 if (Ei > 0 && Ej < 0) addth = 3.14 * 1000.0;
1470 (13.6 / std::sqrt(Ei * Ej)) * (1.0 + 0.038 * std::log(red_length)) * std::sqrt(red_length);
1474 if (ind.at(i) == 1) {
1476 rms = std::hypot(tH0, theta0x);
1478 double const DT = dthij.at(i) + addth;
1479 double const prob =
my_g(DT, 0.0, rms);
1481 result = result - 2.0 * prob;
1485 if (std::isnan(result) || std::isinf(result)) {
1486 std::cout <<
" Is nan ! my_mcs_llhd ( 1 ) ! " << std::endl;
Provides recob::Track data product.
double GetMomentumMultiScatterLLHD(art::Ptr< recob::Track > const &trk, const bool checkValidPoints=false, const int maxMomentum_MeV=7500, const double min_resolution=0.001, const double max_resolution=800, const bool check_valid_scattered=false, const double angle_correction=0.757)
Calculate muon momentum (GeV) using multiple coulomb scattering by log likelihood.
double GetMomentumMultiScatterChi2(art::Ptr< recob::Track > const &trk, const bool checkValidPoints=false, const int maxMomentum_MeV=7500, const double min_resolution=0, const double max_resolution=45)
Calculate muon momentum (GeV) using multiple coulomb scattering. Chi2 minimization of the Highland fo...
double my_g(double xx, double Q, double s) const
chi square minizer using Minuit2, it will minize (xx-Q)/s
Float_t y1[n_points_granero]
Float_t x1[n_points_granero]
Point_t const & LocationAtPoint(size_t i) const
Access to track position at different points.
bool HasValidPoint(size_t i) const
Various functions related to the presence and the number of (valid) points.
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
constexpr auto abs(T v)
Returns the absolute value of the argument.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
std::optional< Segments > getSegTracks_(std::vector< double > const &xxx, std::vector< double > const &yyy, std::vector< double > const &zzz, double seg_size, bool check_valid_scattered=false)
Split tracks into segments to calculate the scattered angle later. Check DOI 10.1088/1748-0221/12/10/...
Float_t y2[n_points_geant4]
int getDeltaThetaij_(std::vector< double > &ei, std::vector< double > &ej, std::vector< double > &th, std::vector< double > &ind, Segments const &segments, double thick, double const angle_correction) const
Gets the scatterd angle for all the segments.
ScatterAngleMethods fMCSAngleMethod
Use scattered angle z-x (z is along the particle's direction)
double Length(size_t p=0) const
Access to various track properties.
double find_angle(double vz, double vy) const
Gets angle between two vy and vz.
double my_mcs_llhd(std::vector< double > const &dEi, std::vector< double > const &dEj, std::vector< double > const &dthij, std::vector< double > const &ind, double x0, double x1) const
Minimizer of log likelihood for scattered angle.
bool plotRecoTracks_(std::vector< double > const &xxx, std::vector< double > const &yyy, std::vector< double > const &zzz)
Struct to store segments. x, y and z are the 3D points of the segment nx, ny, nz forms the vector tha...
std::tuple< double, double, double > getDeltaThetaRMS_(Segments const &segments, double thick) const
Gets the scattered angle RMS for a all segments.
Use space angle: sqrt( zx^2 + zy^2 )/sqrt(2)
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
void compute_max_fluctuation_vector(const std::vector< double > segx, const std::vector< double > segy, const std::vector< double > segz, std::vector< double > &segnx, std::vector< double > &segny, std::vector< double > &segnz, std::vector< bool > &segn_isvalid, std::vector< double > &vx, std::vector< double > &vy, std::vector< double > &vz, bool check_valid_scattered)
Computes the vector with most scattering inside a segment with size steps_size.
double GetMuMultiScatterLLHD3(art::Ptr< recob::Track > const &trk, bool dir)
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
TVector3 GetMultiScatterStartingPoint(art::Ptr< recob::Track > const &trk)
Float_t x2[n_points_geant4]
TPolyLine3D * gr_reco_xyz
std::vector< double > steps
double GetTrackMomentum(double trkrange, int pdg) const