4 #include "TMatrixDSym.h"
5 #include "TMatrixDSymEigen.h"
9 using namespace recob::tracking;
15 vector<size_t> breakpoints;
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 {
100 double best_logL = std::numeric_limits<double>::max();
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_;
133 return ScanResult(best_p, std::max(lunc,runc), best_logL);
136 void TrajectoryMCSFitter::linearRegression(
const recob::TrackTrajectory& traj,
const size_t firstPoint,
const size_t lastPoint,
Vector_t& pcdir)
const {
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);
221 result = std::numeric_limits<double>::max();
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;
232 return std::numeric_limits<double>::max();
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 ) {
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
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.
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.
double Length(size_t startAt=0) const
Returns the approximate length of the trajectory.
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 ...
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.
recob::tracking::Vector_t Vector_t
BEGIN_PROLOG could also be cout