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" 41 constexpr
auto range_gramper_cm()
43 std::array<float, 29> Range_grampercm{{
44 9.833E-1, 1.786E0, 3.321E0, 6.598E0, 1.058E1, 3.084E1, 4.250E1, 6.732E1,
45 1.063E2, 1.725E2, 2.385E2, 4.934E2, 6.163E2, 8.552E2, 1.202E3, 1.758E3,
46 2.297E3, 4.359E3, 5.354E3, 7.298E3, 1.013E4, 1.469E4, 1.910E4, 3.558E4,
47 4.326E4, 5.768E4, 7.734E4, 1.060E5, 1.307E5}};
48 for (
float&
value : Range_grampercm) {
51 return Range_grampercm;
54 constexpr
auto Range_grampercm = range_gramper_cm();
55 constexpr std::array<float, 29> KE_MeV{{
56 10, 14, 20, 30, 40, 80, 100, 140, 200, 300,
57 400, 800, 1000, 1400, 2000, 3000, 4000, 8000, 10000, 14000,
58 20000, 30000, 40000, 80000, 100000, 140000, 200000, 300000, 400000}};
59 TGraph
const KEvsR{29, Range_grampercm.data(), KE_MeV.data()};
60 TSpline3
const KEvsR_spline3{
"KEvsRS", &KEvsR};
63 TVector3
const basex{1, 0, 0};
64 TVector3
const basey{0, 1, 0};
65 TVector3
const basez{0, 0, 1};
66 constexpr
float kcal{0.0024};
70 explicit FcnWrapper(std::vector<double>&& xmeas,
71 std::vector<double>&& ymeas,
72 std::vector<double>&& eymeas)
79 my_mcs_chi2(
double const*
x)
const 86 auto const n = xmeas_.size();
87 assert(
n == ymeas_.size());
88 assert(
n == eymeas_.size());
90 for (std::size_t i = 0; i <
n; ++i) {
91 double const xx = xmeas_[i];
92 double const yy = ymeas_[i];
93 double const ey = eymeas_[i];
95 if (
std::abs(ey) < std::numeric_limits<double>::epsilon()) {
96 std::cout <<
" Zero denominator in my_mcs_chi2 ! " <<
std::endl;
100 constexpr
double rad_length{14.0};
101 double const l0 = xx / rad_length;
105 res1 = (13.6 /
p) * std::sqrt(l0) * (1.0 + 0.038 * std::log(l0));
107 res1 = std::sqrt(res1 * res1 + theta0 * theta0);
109 double const diff = yy - res1;
113 result += 2.0 / (4.6) * theta0;
115 if (std::isnan(result) || std::isinf(result)) {
116 MF_LOG_DEBUG(
"TrackMomentumCalculator") <<
" Is nan in my_mcs_chi2 ! ";
124 std::vector<double>
const xmeas_;
125 std::vector<double>
const ymeas_;
126 std::vector<double>
const eymeas_;
133 TrackMomentumCalculator::TrackMomentumCalculator(
double const min,
138 for (
int i = 1; i <=
n_steps; i++) {
207 if (trkrange < 0 || std::isnan(trkrange)) {
209 <<
"Invalid track range " << trkrange <<
" return -1";
214 constexpr
double Muon_M = 105.7, Proton_M = 938.272;
216 if (
abs(pdg) == 13) {
218 KE = KEvsR_spline3.Eval(trkrange);
219 }
else if (
abs(pdg) == 2212) {
221 if (trkrange > 0 && trkrange <= 80)
222 KE = 29.9317 *
std::pow(trkrange, 0.586304);
223 else if (trkrange > 80 && trkrange <= 3.022E3)
225 149.904 + (3.34146 * trkrange) + (-0.00318856 * trkrange * trkrange) +
226 (4.34587E-6 * trkrange * trkrange * trkrange) +
227 (-3.18146
E-9 * trkrange * trkrange * trkrange * trkrange) +
228 (1.17854E-12 * trkrange * trkrange * trkrange * trkrange * trkrange) +
229 (-1.71763
E-16 * trkrange * trkrange * trkrange * trkrange * trkrange *
239 Momentum = std::sqrt((KE * KE) + (2 * M * KE));
241 Momentum = Momentum / 1000;
256 std::vector<float> recoX;
257 std::vector<float> recoY;
258 std::vector<float> recoZ;
262 for (
int i = 0; i < n_points; i++) {
264 recoX.push_back(
pos.X());
265 recoY.push_back(
pos.Y());
266 recoZ.push_back(
pos.Z());
269 if (recoX.size() < 2)
275 constexpr
double seg_size{10.};
277 auto const segments =
getSegTracks_(recoX, recoY, recoZ, seg_size);
278 if (!segments.has_value())
281 auto const seg_steps = segments->x.size();
285 double const recoL = segments->L.at(seg_steps - 1);
286 if (recoL < minLength || recoL >
maxLength)
289 std::vector<float> dEi;
290 std::vector<float> dEj;
291 std::vector<float> dthij;
292 std::vector<float> ind;
304 for (
int k = start1;
k <= end1; ++
k) {
305 double const p_test = 0.001 +
k * 0.01;
307 for (
int l = start2;
l <= end2; ++
l) {
308 double const res_test = 2.0;
309 double const fv =
my_mcs_llhd(dEi, dEj, dthij, ind, p_test, res_test);
328 if (LLHDp != -1 && LLHDm != -1 && LLHDp > LLHDm) {
344 std::vector<float> recoX;
345 std::vector<float> recoY;
346 std::vector<float> recoZ;
349 for (
int i = 0; i < n_points; ++i) {
350 auto const index = dir ? i : n_points - 1 - i;
352 recoX.push_back(
pos.X());
353 recoY.push_back(
pos.Y());
354 recoZ.push_back(
pos.Z());
357 if (recoX.size() < 2)
363 constexpr
double seg_size{5.0};
364 auto const segments =
getSegTracks_(recoX, recoY, recoZ, seg_size);
365 if (!segments.has_value())
368 auto const seg_steps = segments->x.size();
372 double const recoL = segments->L.at(seg_steps - 1);
376 std::vector<float> dEi;
377 std::vector<float> dEj;
378 std::vector<float> dthij;
379 std::vector<float> ind;
383 double const p_range = recoL * kcal;
384 double const logL =
my_mcs_llhd(dEi, dEj, dthij, ind, p_range, 5.65);
391 std::vector<float>& ej,
392 std::vector<float>& th,
393 std::vector<float>& ind,
395 double const thick)
const 397 int const a1 = segments.
x.size();
398 int const a2 = segments.
y.size();
399 int const a3 = segments.
z.size();
401 if (a1 != a2 || a1 != a3) {
402 std::cout <<
" ( Get thij ) Error ! " <<
std::endl;
406 auto const& segnx = segments.
nx;
407 auto const& segny = segments.
ny;
408 auto const& segnz = segments.
nz;
409 auto const& segL = segments.
L;
412 double thick1 = thick + 0.13;
414 for (
int i = 0; i < tot; i++) {
415 double const dx = segnx.at(i);
416 double const dy = segny.at(i);
417 double const dz = segnz.at(i);
419 TVector3
const vec_z{dx, dy, dz};
423 double const switcher = basex.Dot(vec_z);
425 vec_y = vec_z.Cross(basex).Unit();
426 vec_x = vec_y.Cross(vec_z);
430 vec_y = basez.Cross(vec_z).Unit();
431 vec_x = vec_y.Cross(vec_z);
434 TVector3
const Rx{vec_x.Dot(basex), vec_x.Dot(basey), vec_x.Dot(basez)};
435 TVector3
const Ry{vec_y.Dot(basex), vec_y.Dot(basey), vec_y.Dot(basez)};
436 TVector3
const Rz{vec_z.Dot(basex), vec_z.Dot(basey), vec_z.Dot(basez)};
438 double const refL = segL.at(i);
440 for (
int j = i; j < tot; j++) {
441 double const L1 = segL.at(j);
442 double const L2 = segL.at(j + 1);
444 double const dz1 = L1 - refL;
445 double const dz2 = L2 - refL;
447 if (dz1 <= thick1 && dz2 > thick1) {
448 double const here_dx = segnx.at(j);
449 double const here_dy = segny.at(j);
450 double const here_dz = segnz.at(j);
452 TVector3
const here_vec{here_dx, here_dy, here_dz};
453 TVector3
const rot_here{
454 Rx.Dot(here_vec), Ry.Dot(here_vec), Rz.Dot(here_vec)};
456 double const scx = rot_here.X();
457 double const scy = rot_here.Y();
458 double const scz = rot_here.Z();
463 constexpr
double ULim = 10000.0;
464 constexpr
double LLim = -10000.0;
466 double const cL = kcal;
467 double const Li = segL.at(i);
468 double const Lj = segL.at(j);
470 if (azy <= ULim && azy >= LLim) {
471 ei.push_back(Li * cL);
472 ej.push_back(Lj * cL);
477 if (azx <= ULim && azx >= LLim) {
478 ei.push_back(Li * cL);
479 ej.push_back(Lj * cL);
496 std::vector<float> recoX;
497 std::vector<float> recoY;
498 std::vector<float> recoZ;
502 for (
int i = 0; i < n_points; i++) {
504 recoX.push_back(
pos.X());
505 recoY.push_back(
pos.Y());
506 recoZ.push_back(
pos.Z());
509 if (recoX.size() < 2)
516 auto const segments =
getSegTracks_(recoX, recoY, recoZ, seg_size);
517 if (!segments.has_value())
520 auto const seg_steps = segments->x.size();
524 double const recoL = segments->L.at(seg_steps - 1);
525 if (recoL < minLength || recoL >
maxLength)
528 double ymax = -999.0;
529 double ymin = +999.0;
531 std::vector<double> xmeas;
532 std::vector<double> ymeas;
533 std::vector<double> eymeas;
537 for (
int j = 0; j <
n_steps; j++) {
538 double const trial =
steps.at(j);
541 if (std::isnan(
mean) || std::isinf(
mean)) {
542 mf::LogDebug(
"TrackMomentumCalculator") <<
"Returned mean is either nan or infinity.";
545 if (std::isnan(rms) || std::isinf(rms)) {
546 mf::LogDebug(
"TrackMomentumCalculator") <<
"Returned rms is either nan or infinity.";
549 if (std::isnan(rmse) || std::isinf(rmse)) {
550 mf::LogDebug(
"TrackMomentumCalculator") <<
"Returned rmse is either nan or infinity.";
554 xmeas.push_back(trial);
555 ymeas.push_back(rms);
564 assert(xmeas.size() == ymeas.size());
565 assert(xmeas.size() == eymeas.size());
570 TGraphErrors gr_meas{
n_steps, xmeas.data(), ymeas.data(),
nullptr, eymeas.data()};
572 gr_meas.SetTitle(
"(#Delta#theta)_{rms} versus material thickness; Material " 573 "thickness in cm; (#Delta#theta)_{rms} in mrad");
575 gr_meas.SetLineColor(kBlack);
576 gr_meas.SetMarkerColor(kBlack);
577 gr_meas.SetMarkerStyle(20);
578 gr_meas.SetMarkerSize(1.2);
580 gr_meas.GetXaxis()->SetLimits(
steps.at(0) -
steps.at(0),
582 gr_meas.SetMinimum(0.0);
583 gr_meas.SetMaximum(1.80 * ymax);
585 ROOT::Minuit2::Minuit2Minimizer mP{};
587 ROOT::Math::Functor FCA([&
wrapper](
double const* xs) {
return wrapper.my_mcs_chi2(xs); }, 2);
590 mP.SetLimitedVariable(0,
"p_{MCS}", 1.0, 0.01, 0.001, 7.5);
591 mP.SetLimitedVariable(1,
"#delta#theta", 0.0, 1.0, 0.0, 45.0);
592 mP.SetMaxFunctionCalls(1.E9);
593 mP.SetMaxIterations(1.E9);
594 mP.SetTolerance(0.01);
598 bool const mstatus = mP.Minimize();
602 const double* pars = mP.X();
603 const double* erpars = mP.Errors();
605 double const deltap = (recoL * kcal) / 2.0;
607 double const p_mcs = pars[0] + deltap;
608 double const p_mcs_e [[maybe_unused]] = erpars[0];
609 return mstatus ? p_mcs : -1.0;
614 std::vector<float>
const& yyy,
615 std::vector<float>
const& zzz)
617 auto const n = xxx.size();
618 auto const y_size = yyy.size();
619 auto const z_size = zzz.size();
621 if (n != y_size || n != z_size) {
622 cout <<
" ( Get reco tacks ) Error ! " <<
endl;
629 auto xs =
const_cast<float*
>(xxx.data());
630 auto ys =
const_cast<float*
>(yyy.data());
631 auto zs =
const_cast<float*
>(zzz.data());
633 auto const narrowed_size =
637 gr_reco_yz = TGraph{narrowed_size, zzz.data(), yyy.data()};
638 gr_reco_xz = TGraph{narrowed_size, zzz.data(), xxx.data()};
639 gr_reco_xy = TGraph{narrowed_size, xxx.data(), yyy.data()};
644 std::optional<TrackMomentumCalculator::Segments>
646 std::vector<float>
const& yyy,
647 std::vector<float>
const& zzz,
648 double const seg_size)
656 if ((a1 != a2) || (a1 != a3) || (a2 != a3)) {
657 cout <<
" ( Digitize reco tacks ) Error ! " <<
endl;
661 int const stopper =
seg_stop / seg_size;
663 std::vector<float> segx, segnx;
664 std::vector<float> segy, segny;
665 std::vector<float> segz, segnz;
666 std::vector<float> segL;
676 double x00 = xxx.at(0);
677 double y00 = yyy.at(0);
678 double z00 = zzz.at(0);
682 std::vector<float> vx;
683 std::vector<float> vy;
684 std::vector<float> vz;
686 for (
int i = 0; i <
a1; i++) {
699 segL.push_back(stag);
719 for (
int i = indC; i < a1 - 1; i++) {
720 double const x1 = xxx.at(i);
721 double const y1 = yyy.at(i);
722 double const z1 = zzz.at(i);
726 double const x2 = xxx.at(i + 1);
727 double const y2 = yyy.at(i + 1);
728 double const z2 = zzz.at(i + 1);
732 if (dr1 < seg_size) {
740 if (dr1 <= seg_size && dr2 > seg_size) {
741 double const dx = x2 -
x1;
742 double const dy = y2 - y1;
743 double const dz = z2 - z1;
744 double const dr = std::sqrt(dx * dx + dy * dy + dz * dz);
747 cout <<
" ( Zero ) Error ! " <<
endl;
752 2.0 * ((x1 - x0) * dx + (y1 - y0) * dy + (z1 - z0) * dz) / (dr * dr);
754 double const gamma = (dr1 * dr1 - seg_size * seg_size) / (dr * dr);
755 double const delta = beta * beta - 4.0 *
gamma;
758 cout <<
" ( Discriminant ) Error ! " <<
endl;
762 double const lysi1 = (-beta + std::sqrt(delta)) / 2.0;
763 double const t = lysi1;
765 double const xp = x1 + t * dx;
766 double const yp = y1 + t * dy;
767 double const zp = z1 + t * dz;
773 segL.push_back(1.0 *
n_seg * 1.0 * seg_size + stag);
790 auto const na = vx.size();
795 for (std::size_t i = 0; i < na; ++i) {
805 std::vector<double> mx;
806 std::vector<double>
my;
807 std::vector<double> mz;
811 for (std::size_t i = 0; i < na; ++i) {
812 double const xxw1 = vx.at(i);
813 double const yyw1 = vy.at(i);
814 double const zzw1 = vz.at(i);
816 mx.push_back(xxw1 - sumx);
817 my.push_back(yyw1 - sumy);
818 mz.push_back(zzw1 - sumz);
820 double const xxw0 = mx.at(i);
821 double const yyw0 = my.at(i);
822 double const zzw0 = mz.at(i);
824 m(0, 0) += xxw0 * xxw0 / na;
825 m(0, 1) += xxw0 * yyw0 / na;
826 m(0, 2) += xxw0 * zzw0 / na;
828 m(1, 0) += yyw0 * xxw0 / na;
829 m(1, 1) += yyw0 * yyw0 / na;
830 m(1, 2) += yyw0 * zzw0 / na;
832 m(2, 0) += zzw0 * xxw0 / na;
833 m(2, 1) += zzw0 * yyw0 / na;
834 m(2, 2) += zzw0 * zzw0 / na;
837 TMatrixDSymEigen
me(m);
839 TVectorD eigenval = me.GetEigenValues();
840 TMatrixD eigenvec = me.GetEigenVectors();
842 double max1 = -666.0;
846 for (
int i = 0; i < 3; ++i) {
847 double const p1 = eigenval(i);
855 double ax = eigenvec(0, ind1);
856 double ay = eigenvec(1, ind1);
857 double az = eigenvec(2, ind1);
860 if (segx.at(
n_seg - 1) - segx.at(
n_seg - 2) > 0)
865 if (segy.at(
n_seg - 1) - segy.at(
n_seg - 2) > 0)
870 if (segz.at(
n_seg - 1) - segz.at(
n_seg - 2) > 0)
894 else if (dr1 > seg_size) {
895 double const dx = x1 - x0;
896 double const dy = y1 - y0;
897 double const dz = z1 - z0;
901 cout <<
" ( Zero ) Error ! " <<
endl;
905 double const t = seg_size / dr;
906 double const xp = x0 + t * dx;
907 double const yp = y0 + t * dy;
908 double const zp = z0 + t * dz;
913 segL.push_back(1.0 *
n_seg * 1.0 * seg_size + stag);
932 double na = vx.size();
938 for (std::size_t i = 0; i < na; ++i) {
948 std::vector<double> mx;
949 std::vector<double>
my;
950 std::vector<double> mz;
954 for (
int i = 0; i < na; ++i) {
955 double const xxw1 = vx.at(i);
956 double const yyw1 = vy.at(i);
957 double const zzw1 = vz.at(i);
959 mx.push_back(xxw1 - sumx);
960 my.push_back(yyw1 - sumy);
961 mz.push_back(zzw1 - sumz);
963 double const xxw0 = mx.at(i);
964 double const yyw0 = my.at(i);
965 double const zzw0 = mz.at(i);
967 m(0, 0) += xxw0 * xxw0 / na;
968 m(0, 1) += xxw0 * yyw0 / na;
969 m(0, 2) += xxw0 * zzw0 / na;
971 m(1, 0) += yyw0 * xxw0 / na;
972 m(1, 1) += yyw0 * yyw0 / na;
973 m(1, 2) += yyw0 * zzw0 / na;
975 m(2, 0) += zzw0 * xxw0 / na;
976 m(2, 1) += zzw0 * yyw0 / na;
977 m(2, 2) += zzw0 * zzw0 / na;
980 TMatrixDSymEigen
me(m);
982 TVectorD eigenval = me.GetEigenValues();
983 TMatrixD eigenvec = me.GetEigenVectors();
985 double max1 = -666.0;
988 for (
int i = 0; i < 3; ++i) {
989 double const p1 = eigenval(i);
997 double ax = eigenvec(0, ind1);
998 double ay = eigenvec(1, ind1);
999 double az = eigenvec(2, ind1);
1002 if (segx.at(
n_seg - 1) - segx.at(
n_seg - 2) > 0)
1007 if (segy.at(
n_seg - 1) - segy.at(
n_seg - 2) > 0)
1012 if (segz.at(
n_seg - 1) - segz.at(
n_seg - 2) > 0)
1017 segnx.push_back(ax);
1018 segny.push_back(ay);
1019 segnz.push_back(az);
1023 return std::nullopt;
1048 return std::make_optional<Segments>(
Segments{segx, segnx, segy, segny, segz, segnz, segL});
1051 std::tuple<double, double, double>
1053 double const thick)
const 1055 auto const& segnx = segments.
nx;
1056 auto const& segny = segments.
ny;
1057 auto const& segnz = segments.
nz;
1058 auto const& segL = segments.
L;
1060 int const a1 = segnx.size();
1061 int const a2 = segny.size();
1062 int const a3 = segnz.size();
1064 if (a1 != a2 || a1 != a3) {
1065 cout <<
" ( Get RMS ) Error ! " <<
endl;
1066 return std::make_tuple(0., 0., 0.);
1069 int const tot = a1 - 1;
1071 double const thick1 = thick + 0.13;
1073 std::vector<float> buf0;
1075 for (
int i = 0; i < tot; i++) {
1076 double const dx = segnx.at(i);
1077 double const dy = segny.at(i);
1078 double const dz = segnz.at(i);
1080 TVector3
const vec_z{dx, dy, dz};
1084 double const switcher = basex.Dot(vec_z);
1086 if (switcher <= 0.995) {
1087 vec_y = vec_z.Cross(basex).Unit();
1088 vec_x = vec_y.Cross(vec_z);
1092 vec_y = basez.Cross(vec_z).Unit();
1093 vec_x = vec_y.Cross(vec_z);
1096 TVector3
const Rx{vec_x.Dot(basex), vec_x.Dot(basey), vec_x.Dot(basez)};
1097 TVector3
const Ry{vec_y.Dot(basex), vec_y.Dot(basey), vec_y.Dot(basez)};
1098 TVector3
const Rz{vec_z.Dot(basex), vec_z.Dot(basey), vec_z.Dot(basez)};
1100 double const refL = segL.at(i);
1102 for (
int j = i; j < tot; j++) {
1103 double const L1 = segL.at(j);
1104 double const L2 = segL.at(j + 1);
1106 double const dz1 = L1 - refL;
1107 double const dz2 = L2 - refL;
1109 if (dz1 <= thick1 && dz2 > thick1) {
1110 double const here_dx = segnx.at(j);
1111 double const here_dy = segny.at(j);
1112 double const here_dz = segnz.at(j);
1114 TVector3
const here_vec{here_dx, here_dy, here_dz};
1115 TVector3
const rot_here{Rx.Dot(here_vec), Ry.Dot(here_vec), Rz.Dot(here_vec)};
1117 double const scx = rot_here.X();
1118 double const scy = rot_here.Y();
1119 double const scz = rot_here.Z();
1126 double const ULim = 10000.0;
1127 double const LLim = -10000.0;
1129 if (azx <= ULim && azx >= LLim) {
1130 buf0.push_back(azx);
1138 int const nmeas = buf0.size();
1145 for (
int i = 0; i < nmeas; i++) {
1151 for (
int i = 0; i < nmeas; i++)
1152 rms += ((buf0.at(i)) * (buf0.at(i)));
1155 rms = std::sqrt(rms);
1156 rmse = rms / std::sqrt(2.0 * tot);
1163 double const lev1 = 2.50;
1165 for (
int i = 0; i < nmeas; i++) {
1166 double const amp = buf0.at(i);
1167 if (amp < (mean + lev1 * rms1) && amp > (mean - lev1 * rms1)) {
1173 rms = rms / (ntot1);
1174 rms = std::sqrt(rms);
1175 rmse = rms / std::sqrt(2.0 * ntot1);
1176 return std::make_tuple(mean, rms, rmse);
1182 double thetayz = -999.0;
1184 if (vz > 0 && vy > 0) {
1186 thetayz = std::atan(ratio);
1189 else if (vz < 0 && vy > 0) {
1191 thetayz = std::atan(ratio);
1192 thetayz = TMath::Pi() - thetayz;
1195 else if (vz < 0 && vy < 0) {
1197 thetayz = std::atan(ratio);
1198 thetayz = thetayz + TMath::Pi();
1201 else if (vz > 0 && vy < 0) {
1203 thetayz = std::atan(ratio);
1204 thetayz = 2.0 * TMath::Pi() - thetayz;
1207 else if (vz == 0 && vy > 0) {
1208 thetayz = TMath::Pi() / 2.0;
1211 else if (vz == 0 && vy < 0) {
1212 thetayz = 3.0 * TMath::Pi() / 2.0;
1215 if (thetayz > TMath::Pi()) {
1216 thetayz = thetayz - 2.0 * TMath::Pi();
1219 return 1000.0 * thetayz;
1226 cout <<
" Error : The code tries to divide by zero ! " <<
endl;
1230 double const arg = (xx - Q) / s;
1231 double const result =
1232 -0.5 * std::log(2.0 * TMath::Pi()) - std::log(s) - 0.5 * arg * arg;
1234 if (std::isnan(result) || std::isinf(result)) {
1235 cout <<
" Is nan ! my_g ! " << -std::log(s) <<
", " << s <<
endl;
1243 std::vector<float>
const& dEj,
1244 std::vector<float>
const& dthij,
1245 std::vector<float>
const& ind,
1247 double const x1)
const 1250 double theta0x =
x1;
1252 double result = 0.0;
1253 double nnn1 = dEi.size();
1255 double red_length = (10.0) / 14.0;
1258 for (
int i = 0; i < nnn1; i++) {
1259 double Ei = p - dEi.at(i);
1260 double Ej = p - dEj.at(i);
1262 if (Ei > 0 && Ej < 0)
1263 addth = 3.14 * 1000.0;
1268 double tH0 = (13.6 / std::sqrt(Ei * Ej)) *
1269 (1.0 + 0.038 * std::log(red_length)) * std::sqrt(red_length);
1273 if (ind.at(i) == 1) {
1274 rms = std::sqrt(tH0 * tH0 +
pow(theta0x, 2.0));
1276 double const DT = dthij.at(i) + addth;
1277 double const prob =
my_g(DT, 0.0, rms);
1279 result = result - 2.0 * prob;
1283 if (std::isnan(result) || std::isinf(result)) {
1284 std::cout <<
" Is nan ! my_mcs_llhd ( 1 ) ! " <<
std::endl;
double beta(double KE, const simb::MCParticle *part)
double rms(sqlite3 *db, std::string const &table_name, std::string const &column_name)
double my_g(double xx, double Q, double s) const
double GetMomentumMultiScatterChi2(art::Ptr< recob::Track > const &trk)
int getDeltaThetaij_(std::vector< float > &ei, std::vector< float > &ej, std::vector< float > &th, std::vector< float > &ind, Segments const &segments, double thick) const
constexpr T sum_of_squares(T x, T y)
Point_t const & LocationAtPoint(size_t i) const
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
std::optional< Segments > getSegTracks_(std::vector< float > const &xxx, std::vector< float > const &yyy, std::vector< float > const &zzz, double seg_size)
double find_angle(double vz, double vy) const
std::tuple< double, double, double > getDeltaThetaRMS_(Segments const &segments, double thick) const
static int max(int a, int b)
double gamma(double KE, const simb::MCParticle *part)
std::vector< float > steps
double GetMuMultiScatterLLHD3(art::Ptr< recob::Track > const &trk, bool dir)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
double my_mcs_llhd(std::vector< float > const &dEi, std::vector< float > const &dEj, std::vector< float > const &dthij, std::vector< float > const &ind, double x0, double x1) const
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
TVector3 GetMultiScatterStartingPoint(art::Ptr< recob::Track > const &trk)
Provides recob::Track data product.
static constexpr double zs
static constexpr double ys
double GetMomentumMultiScatterLLHD(art::Ptr< recob::Track > const &trk)
double mean(sqlite3 *db, std::string const &table_name, std::string const &column_name)
TPolyLine3D * gr_reco_xyz
double GetTrackMomentum(double trkrange, int pdg) const
QTextStream & endl(QTextStream &s)
bool plotRecoTracks_(std::vector< float > const &xxx, std::vector< float > const &yyy, std::vector< float > const &zzz)