4 #include "TMatrixDSym.h" 5 #include "TMatrixDSymEigen.h" 16 vector<float> segradlengths;
17 vector<float> cumseglens;
18 breakTrajInSegments(traj, breakpoints, segradlengths, cumseglens);
26 for (
unsigned int p = 0; p<segradlengths.size(); p++) {
27 linearRegression(traj, breakpoints[p], breakpoints[p+1], pcdir1);
29 if (segradlengths[p]<-100. || segradlengths[p-1]<-100.) {
30 dtheta.push_back(-999.);
32 const double cosval = pcdir0.X()*pcdir1.X()+pcdir0.Y()*pcdir1.Y()+pcdir0.Z()*pcdir1.Z();
35 double dt = 1000.*acos(cosval);
44 vector<float> cumLenFwd;
45 vector<float> cumLenBwd;
46 for (
unsigned int i = 0; i<cumseglens.size()-2; i++) {
47 cumLenFwd.push_back(cumseglens[i]);
48 cumLenBwd.push_back(cumseglens.back()-cumseglens[i+2]);
50 const ScanResult fwdResult = doLikelihoodScan(dtheta, segradlengths, cumLenFwd,
true, momDepConst, pid);
51 const ScanResult bwdResult = doLikelihoodScan(dtheta, segradlengths, cumLenBwd,
false, momDepConst, pid);
54 fwdResult.
p,fwdResult.
pUnc,fwdResult.
logL,
55 bwdResult.
p,bwdResult.
pUnc,bwdResult.
logL,
56 segradlengths,dtheta);
59 void TrajectoryMCSFitter::breakTrajInSegments(
const recob::TrackTrajectory& traj, vector<size_t>&
breakpoints, vector<float>& segradlengths, vector<float>& cumseglens)
const {
61 const double trajlen = traj.
Length();
62 const int nseg =
std::max(minNSegs_,
int(trajlen/segLen_));
63 const double thisSegLen = trajlen/double(nseg);
66 constexpr
double lar_radl_inv = 1./14.0;
67 cumseglens.push_back(0.);
70 breakpoints.push_back(nextValid);
76 thislen += ( (pos1-pos0).
R() );
79 if (thislen>=thisSegLen) {
80 breakpoints.push_back(nextValid);
81 if (npoints>=minHitsPerSegment_) segradlengths.push_back(thislen*lar_radl_inv);
82 else segradlengths.push_back(-999.);
83 cumseglens.push_back(cumseglens.back()+thislen);
92 segradlengths.push_back(thislen*lar_radl_inv);
93 cumseglens.push_back(cumseglens.back()+thislen);
98 const TrajectoryMCSFitter::ScanResult TrajectoryMCSFitter::doLikelihoodScan(std::vector<float>& dtheta, std::vector<float>& seg_nradlengths, std::vector<float>& cumLen,
bool fwdFit,
bool momDepConst,
int pid)
const {
101 double best_p = -1.0;
102 std::vector<float> vlogL;
103 for (
double p_test = pMin_; p_test <= pMax_; p_test+=pStep_) {
104 double logL = mcsLikelihood(p_test, angResol_, dtheta, seg_nradlengths, cumLen, fwdFit, momDepConst, pid);
105 if (logL < best_logL) {
108 best_idx = vlogL.size();
110 vlogL.push_back(logL);
116 for (
int j=best_idx-1;j>=0;j--) {
117 double dLL = vlogL[j]-vlogL[best_idx];
119 lunc = (best_idx-j)*pStep_;
125 if (best_idx<
int(vlogL.size()-1)) {
126 for (
unsigned int j=best_idx+1;j<vlogL.size();j++) {
127 double dLL = vlogL[j]-vlogL[best_idx];
129 runc = (j-best_idx)*pStep_;
140 size_t nextValid = firstPoint;
141 while (nextValid<lastPoint) {
147 const double norm = 1./double(npoints);
152 nextValid = firstPoint;
153 while (nextValid<lastPoint) {
155 const double xxw0 = p.X()-avgpos.X();
156 const double yyw0 = p.Y()-avgpos.Y();
157 const double zzw0 = p.Z()-avgpos.Z();
158 m(0, 0) += xxw0*xxw0*
norm;
159 m(0, 1) += xxw0*yyw0*
norm;
160 m(0, 2) += xxw0*zzw0*
norm;
161 m(1, 0) += yyw0*xxw0*
norm;
162 m(1, 1) += yyw0*yyw0*
norm;
163 m(1, 2) += yyw0*zzw0*
norm;
164 m(2, 0) += zzw0*xxw0*
norm;
165 m(2, 1) += zzw0*yyw0*
norm;
166 m(2, 2) += zzw0*zzw0*
norm;
170 const TMatrixDSymEigen me(m);
171 const auto& eigenval = me.GetEigenValues();
172 const auto& eigenvec = me.GetEigenVectors();
175 double maxeval = eigenval(0);
176 for (
int i=1; i<3; ++i) {
177 if (eigenval(i)>maxeval) {
179 maxeval = eigenval(i);
183 pcdir =
Vector_t(eigenvec(0, maxevalidx),eigenvec(1, maxevalidx),eigenvec(2, maxevalidx));
188 double TrajectoryMCSFitter::mcsLikelihood(
double p,
double theta0x, std::vector<float>& dthetaij, std::vector<float>& seg_nradl, std::vector<float>& cumLen,
bool fwd,
bool momDepConst,
int pid)
const {
190 const int beg = (fwd ? 0 : (dthetaij.size()-1));
191 const int end = (fwd ? dthetaij.size() : -1);
192 const int incr = (fwd ? +1 : -1);
196 const double m = mass(pid);
197 const double m2 = m*m;
198 const double Etot = sqrt(p*p + m2);
201 double const fixedterm = 0.5 * std::log( 2.0 * M_PI );
203 for (
int i = beg; i !=
end; i+=incr ) {
211 constexpr
double kcal = 0.002105;
212 const double Eij = Etot - kcal*cumLen[i];
216 const double Eij = GetE(Etot,cumLen[i],m);
224 const double pij = sqrt(Eij2 - m2);
225 const double beta = sqrt( 1. - ((m2)/(pij*pij + m2)) );
226 constexpr
double tuned_HL_term1 = 11.0038;
227 constexpr
double HL_term2 = 0.038;
228 const double tH0 = ( (momDepConst ? MomentumDependentConstant(pij) : tuned_HL_term1) / (pij*beta) ) * ( 1.0 + HL_term2 * std::log( seg_nradl[i] ) ) * sqrt( seg_nradl[i] );
229 const double rms = sqrt( 2.0*( tH0 * tH0 + theta0x * theta0x ) );
231 std::cout <<
" Error : RMS cannot be zero ! " << std::endl;
234 const double arg = dthetaij[i]/rms;
235 result += ( std::log( rms ) + 0.5 * arg * arg + fixedterm);
241 double TrajectoryMCSFitter::energyLossLandau(
const double mass2,
const double e2,
const double x)
const {
245 if (x<=0.)
return 0.;
246 constexpr
double Iinv2 = 1./(188.E-6*188.E-6);
247 constexpr
double matConst = 1.4*18./40.;
248 constexpr
double me = 0.511;
249 constexpr
double kappa = 0.307075;
250 constexpr
double j = 0.200;
252 const double beta2 = (e2-mass2)/e2;
253 const double gamma2 = 1./(1.0 - beta2);
254 const double epsilon = 0.5*kappa*x*matConst/beta2;
256 return 0.001*epsilon*( log(2.*me*beta2*gamma2*epsilon*Iinv2) + j - beta2 );
259 double TrajectoryMCSFitter::energyLossBetheBloch(
const double mass,
const double e2)
const {
261 constexpr
double Iinv = 1./188.E-6;
262 constexpr
double matConst = 1.4*18./40.;
263 constexpr
double me = 0.511;
264 constexpr
double kappa = 0.307075;
266 const double beta2 = (e2-mass*mass)/e2;
267 const double gamma2 = 1./(1.0 - beta2);
268 const double massRatio = me/mass;
269 const double argument = (2.*me*gamma2*beta2*Iinv) * std::sqrt(1+2*std::sqrt(gamma2)*massRatio + massRatio*massRatio);
271 double dedx = kappa*matConst/beta2;
273 if (mass==0.0)
return(0.0);
274 if (argument <= exp(beta2)) {
277 dedx *= (log(argument)-beta2)*1.
E-3;
278 if (dedx<0.) dedx = 0.;
283 double TrajectoryMCSFitter::GetE(
const double initial_E,
const double length_travelled,
const double m)
const {
285 const double step_size = length_travelled / nElossSteps_;
287 double current_E = initial_E;
288 const double m2 = m*m;
290 for (
auto i = 0; i < nElossSteps_; ++i) {
292 double dedx = energyLossBetheBloch(m,current_E);
293 current_E -= (dedx * step_size);
296 current_E -= energyLossLandau(m2,current_E*current_E,step_size);
298 if ( current_E <= m ) {
T DirectionAtPoint(unsigned int p) const
Direction at point p. Use e.g. as:
recob::tracking::Vector_t Vector_t
Helper class to compute the middle point in a point set.
size_t LastValidPoint() const
Returns the index of the last valid point in the trajectory.
void add(Point const &p)
Accumulates a point.
double Length(size_t startAt=0) const
Returns the approximate length of the trajectory.
Provides recob::Track data product.
A trajectory in space reconstructed from hits.
T LocationAtPoint(unsigned int p) const
Position at point p. Use e.g. as:
Utilities to extend the interface of geometry vectors.
Class storing the result of the Maximum Likelihood fit of Multiple Coulomb Scattering angles between ...
geo::Point_t middlePoint() const
size_t FirstValidPoint() const
Returns the index of the first valid point in the trajectory.
static constexpr size_t InvalidIndex
Value returned on failed index queries.
size_t NextValidPoint(size_t index) const
Returns the index of the next valid point in the trajectory.
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
recob::tracking::Vector_t Vector_t