4 #include "TMatrixDSym.h"
5 #include "TMatrixDSymEigen.h"
13 using namespace recob::tracking;
25 vector<size_t> breakpoints;
26 vector<float> segradlengths;
27 vector<float> cumseglens;
28 breakTrajInSegments(traj, breakpoints, segradlengths, cumseglens);
38 for (
unsigned int p = 0;
p<segradlengths.size();
p++) {
39 linearRegression(traj, breakpoints[
p], breakpoints[p+1], pcdir1);
41 if (segradlengths[p]<-100. || segradlengths[p-1]<-100.) {
42 dtheta.push_back(-999.);
44 const double cosval = pcdir0.X()*pcdir1.X()+pcdir0.Y()*pcdir1.Y()+pcdir0.Z()*pcdir1.Z();
47 double dt = 1000.*acos(cosval);
55 vector<Vector_t> barycenters;
57 vector<float> dthetaPoly;
58 for (
unsigned int p = 0;
p<segradlengths.size();
p++) {
59 findSegmentBarycenter(traj, breakpoints[
p], breakpoints[p+1], bary);
60 barycenters.push_back(bary);
62 for (
unsigned int p = 2;
p<segradlengths.size();
p++) {
63 if (segradlengths[
p]<-100. || segradlengths[
p-1]<-100. || segradlengths[
p-2]<-100.) {
64 dtheta.push_back(-999.);
67 float norm=sqrt(dbcp.X()*dbcp.X()+dbcp.Y()*dbcp.Y()+dbcp.Z()*dbcp.Z());
70 Vector_t dbcm=barycenters[
p-1]-barycenters[
p-2];
71 norm=sqrt(dbcm.X()*dbcm.X()+dbcm.Y()*dbcm.Y()+dbcm.Z()*dbcm.Z());
74 const double cosval = dbcp.X()*dbcm.X()+dbcp.Y()*dbcm.Y()+dbcp.Z()*dbcm.Z();
78 double dt = 1000.*acos(cosval);
79 dthetaPoly.push_back(dt);
90 vector<float> cumLenFwd;
91 vector<float> cumLenBwd;
92 for (
unsigned int i = 0; i<cumseglens.size()-2; i++) {
94 cumLenFwd.push_back(cumseglens[i]);
95 cumLenBwd.push_back(cumseglens.back()-cumseglens[i+2]);
97 const ScanResult fwdResult = doLikelihoodScan(dtheta, segradlengths, cumLenFwd,
true, momDepConst, pid);
98 const ScanResult bwdResult = doLikelihoodScan(dtheta, segradlengths, cumLenBwd,
false, momDepConst, pid);
107 fwdResult.
p,fwdResult.
pUnc,fwdResult.
logL,
108 bwdResult.
p,bwdResult.
pUnc,bwdResult.
logL,
109 segradlengths,dtheta);
112 void TrajectoryMCSFitterICARUS::breakTrajInSegments(
const recob::TrackTrajectory& traj, vector<size_t>& breakpoints, vector<float>& segradlengths, vector<float>& cumseglens)
const {
114 const double trajlen = traj.
Length();
115 const int nseg = std::max(minNSegs_,
int(trajlen/segLen_));
116 const double thisSegLen = trajlen/double(nseg);
119 constexpr
double lar_radl_inv = 1./14.0;
120 cumseglens.push_back(0.);
123 breakpoints.push_back(nextValid);
129 thislen += ( (pos1-pos0).R() );
132 if (thislen>=thisSegLen) {
133 breakpoints.push_back(nextValid);
134 if (npoints>=minHitsPerSegment_) segradlengths.push_back(thislen*lar_radl_inv);
135 else segradlengths.push_back(-999.);
136 cumseglens.push_back(cumseglens.back()+thislen);
145 segradlengths.push_back(thislen*lar_radl_inv);
146 cumseglens.push_back(cumseglens.back()+thislen);
151 const TrajectoryMCSFitterICARUS::ScanResult TrajectoryMCSFitterICARUS::doLikelihoodScan(std::vector<float>& dtheta, std::vector<float>& seg_nradlengths, std::vector<float>& cumLen,
bool fwdFit,
bool momDepConst,
int pid)
const {
153 double best_logL = std::numeric_limits<double>::max();
154 double best_p = -1.0;
155 std::vector<float> vlogL;
156 for (
double p_test = pMin_; p_test <= pMax_; p_test+=pStep_) {
157 double logL = mcsLikelihood(p_test, angResol_, dtheta, seg_nradlengths, cumLen, fwdFit, momDepConst, pid);
158 if (logL < best_logL) {
161 best_idx = vlogL.size();
171 vlogL.push_back(logL);
177 for (
int j=best_idx-1;j>=0;j--) {
178 double dLL = vlogL[j]-vlogL[best_idx];
180 lunc = (best_idx-j)*pStep_;
186 if (best_idx<
int(vlogL.size()-1)) {
187 for (
unsigned int j=best_idx+1;j<vlogL.size();j++) {
188 double dLL = vlogL[j]-vlogL[best_idx];
190 runc = (j-best_idx)*pStep_;
194 return ScanResult(best_p, std::max(lunc,runc), best_logL);
196 void TrajectoryMCSFitterICARUS::findSegmentBarycenter(
const recob::TrackTrajectory& traj,
const size_t firstPoint,
const size_t lastPoint,
Vector_t& bary)
const {
199 size_t nextValid = firstPoint;
200 while (nextValid<lastPoint) {
214 size_t nextValid = firstPoint;
215 while (nextValid<lastPoint) {
221 const double norm = 1./double(npoints);
226 nextValid = firstPoint;
227 while (nextValid<lastPoint) {
229 const double xxw0 =
p.X()-avgpos.X();
230 const double yyw0 =
p.Y()-avgpos.Y();
231 const double zzw0 =
p.Z()-avgpos.Z();
232 m(0, 0) += xxw0*xxw0*
norm;
233 m(0, 1) += xxw0*yyw0*
norm;
234 m(0, 2) += xxw0*zzw0*
norm;
235 m(1, 0) += yyw0*xxw0*
norm;
236 m(1, 1) += yyw0*yyw0*
norm;
237 m(1, 2) += yyw0*zzw0*
norm;
238 m(2, 0) += zzw0*xxw0*
norm;
239 m(2, 1) += zzw0*yyw0*
norm;
240 m(2, 2) += zzw0*zzw0*
norm;
244 const TMatrixDSymEigen me(m);
245 const auto& eigenval = me.GetEigenValues();
246 const auto& eigenvec = me.GetEigenVectors();
249 double maxeval = eigenval(0);
250 for (
int i=1; i<3; ++i) {
251 if (eigenval(i)>maxeval) {
253 maxeval = eigenval(i);
257 pcdir =
Vector_t(eigenvec(0, maxevalidx),eigenvec(1, maxevalidx),eigenvec(2, maxevalidx));
262 double TrajectoryMCSFitterICARUS::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 {
264 const int beg = (fwd ? 0 : (dthetaij.size()-1));
265 const int end = (fwd ? dthetaij.size() : -1);
266 const int incr = (fwd ? +1 : -1);
272 const double m =
mass(pid);
273 const double m2 = m*
m;
274 const double Etot = sqrt(p*p + m2);
277 double const fixedterm = 0.5 * std::log( 2.0 * M_PI );
279 for (
int i = beg; i !=
end; i+=incr ) {
287 constexpr
double kcal = 0.002105;
288 const double Eij = Etot - kcal*cumLen[i];
292 const double Eij = GetE(Etot,cumLen[i],m);
297 result = std::numeric_limits<double>::max();
301 const double pij = sqrt(Eij2 - m2);
302 const double beta = sqrt( 1. - ((m2)/(pij*pij + m2)) );
303 constexpr
double tuned_HL_term1 = 11.0038;
304 constexpr
double HL_term2 = 0.038;
305 const double tH0 = ( (momDepConst ? MomentumDependentConstant(pij) : tuned_HL_term1) / (pij*beta) ) * ( 1.0 + HL_term2 * std::log( seg_nradl[i] ) ) * sqrt( seg_nradl[i] );
306 const double rms = sqrt( 2.0*( tH0 * tH0 + theta0x * theta0x ) );
309 return std::numeric_limits<double>::max();
311 const double arg = dthetaij[i]/rms;
312 result += ( std::log( rms ) + 0.5 * arg * arg + fixedterm);
319 double TrajectoryMCSFitterICARUS::energyLossLandau(
const double mass2,
const double e2,
const double x)
const {
323 if (x<=0.)
return 0.;
324 constexpr
double Iinv2 = 1./(188.E-6*188.E-6);
325 constexpr
double matConst = 1.4*18./40.;
326 constexpr
double me = 0.511;
327 constexpr
double kappa = 0.307075;
328 constexpr
double j = 0.200;
330 const double beta2 = (e2-mass2)/e2;
331 const double gamma2 = 1./(1.0 - beta2);
332 const double epsilon = 0.5*kappa*x*matConst/beta2;
334 return 0.001*epsilon*( log(2.*me*beta2*gamma2*epsilon*Iinv2) + j - beta2 );
337 double TrajectoryMCSFitterICARUS::energyLossBetheBloch(
const double mass,
const double e2)
const {
339 constexpr
double Iinv = 1./188.E-6;
340 constexpr
double matConst = 1.4*18./40.;
341 constexpr
double me = 0.511;
342 constexpr
double kappa = 0.307075;
344 const double beta2 = (e2-mass*
mass)/e2;
345 const double gamma2 = 1./(1.0 - beta2);
346 const double massRatio = me/
mass;
347 const double argument = (2.*me*gamma2*beta2*Iinv) * std::sqrt(1+2*std::sqrt(gamma2)*massRatio + massRatio*massRatio);
349 double dedx = kappa*matConst/beta2;
351 if (mass==0.0)
return(0.0);
352 if (argument <=
exp(beta2)) {
355 dedx *= (log(argument)-beta2)*1.
E-3;
356 if (dedx<0.) dedx = 0.;
361 double TrajectoryMCSFitterICARUS::GetE(
const double initial_E,
const double length_travelled,
const double m)
const {
363 const double step_size = length_travelled / nElossSteps_;
365 double current_E = initial_E;
366 const double m2 = m*
m;
368 for (
auto i = 0; i < nElossSteps_; ++i) {
370 double dedx = energyLossBetheBloch(m,current_E);
371 current_E -= (dedx * step_size);
374 current_E -= energyLossLandau(m2,current_E*current_E,step_size);
376 if ( current_E <= m ) {
383 double TrajectoryMCSFitterICARUS::GetOptimalSegLen(
const double guess_p,
const int n_points,
const int plane,
const double length_travelled)
const {
386 double initial_p=guess_p*-0.211*length_travelled;
388 if(initial_p<MIN_P) initial_p=MIN_P;
394 double DsTot=length_travelled;
396 double LogTerm=0.038;
399 double xi=(sigma/DsTot)*(initial_p/2.)/p0*sqrt(X0/length_travelled)/sqrt(
double(n_points))*sinb;
401 double m=1/sqrt(6*xi);
406 double alfa=1+LogTerm*log(DsTot/sinb/
double(m)/X0);
408 double m_corr=(m==1)?m:sqrt(m/(m-1));
410 double xiCorr=sigma/DsTot*((initial_p/2.)/p0)*sqrt(X0/length_travelled)*sqrt((
double)n_points)*sinb/alfa;
412 double m2=m_corr/sqrt(6.*xiCorr);
419 void TrajectoryMCSFitterICARUS::ComputeD3P() {
425 TH1D* hd3pv=
new TH1D(
"hd3pv",
"hd3pv",100,-5.,5.);
427 for (
unsigned int j=0;j<hits2d.size()-2;j+=3) {
430 res=computeResidual(j,a);
440 bool writeHisto=
true;
442 TFile *f =
new TFile(
"d3phisto.root",
"UPDATE");
457 double TrajectoryMCSFitterICARUS::computeResidual(
int i,
double& alfa)
const
479 double ym=y0+(x1-x0)/(x2-x0)*(y2-y0);
486 double K=(x1-x0)/(x2-x0);
488 alfa=1/sqrt(1+K*K+(1-K)*(1-K));
490 double res=dy*(alfa);
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
process_name opflash particleana ie x
T DirectionAtPoint(unsigned int p) const
Direction at point p. Use e.g. as:
recob::tracking::Vector_t Vector_t
geo::WireID WireID() const
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.
WireID_t Wire
Index of the wire within its plane.
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
void add(Point const &p)
Accumulates a point.
Offers proxy::Tracks and proxy::Track class for recob::Track access.
double Length(size_t startAt=0) const
Returns the approximate length of the trajectory.
standard_singlep gaussian distribution X0
size_t NPoints() const
Returns the number of stored trajectory points.
A trajectory in space reconstructed from hits.
T LocationAtPoint(unsigned int p) const
Position at point p. Use e.g. as:
auto end(FixedBins< T, C > const &) noexcept
Utilities to extend the interface of geometry vectors.
Provides recob::Track data product.
auto norm(Vector const &v)
Return norm of the specified vector.
Class storing the result of the Maximum Likelihood fit of Multiple Coulomb Scattering angles between ...
float PeakTime() const
Time of the signal peak, in tick units.
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.
2D representation of charge deposited in the TDC/wire plane
recob::tracking::Vector_t Vector_t