/* This file is part of MAUS: http://micewww.pp.rl.ac.uk:8080/projects/maus
*
* MAUS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MAUS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MAUS. If not, see .
*
*/
#include "src/common_cpp/Recon/EMR/TrackRange.hh"
namespace TrackRange {
double range_piecewise(std::vector points) {
if ( !points.size() )
return -1.;
// Loop over the points, add a piece of track for each pair
double range(0.);
for (size_t i = 0; i < points.size()-1; i++) {
MAUS::ThreeVector Pi = points[i];
MAUS::ThreeVector Pj = points[i+1];
if ( Pi.z() == Pj.z() )
continue;
range += sqrt(pow(Pj.x()-Pi.x(), 2)+pow(Pj.y()-Pi.y(), 2)+pow(Pj.z()-Pi.z(), 2));
}
return range;
}
double range_piecewise_error(std::vector points,
std::vector errors) {
if ( !points.size() )
return -1.;
// Loop over the points, add a piece of track for each pair
double error2(0.);
for (size_t i = 0; i < points.size()-1; i++) {
MAUS::ThreeVector Pi = points[i];
MAUS::ThreeVector Pj = points[i+1];
MAUS::ThreeVector ei = errors[i];
MAUS::ThreeVector ej = errors[i+1];
double Rij = sqrt(pow(Pj.x()-Pi.x(), 2)+pow(Pj.y()-Pi.y(), 2)+pow(Pj.z()-Pi.z(), 2));
if ( !Rij )
continue;
double e2x = pow((Pj.x()-Pi.x())/Rij, 2)*(pow(ei.x(), 2)+pow(ej.x(), 2));
double e2y = pow((Pj.y()-Pi.y())/Rij, 2)*(pow(ei.y(), 2)+pow(ej.y(), 2));
double e2z = pow((Pj.z()-Pi.z())/Rij, 2)*(pow(ei.z(), 2)+pow(ej.z(), 2));
error2 += e2x + e2y + e2z;
}
return sqrt(error2);
}
TF1* f_path(0);
double range_integral(std::vector parx,
std::vector pary,
double zstart,
double zend) {
if ( !parx.size() )
return -1.;
if ( parx.size() == 1 )
return zend-zstart;
size_t n = parx.size()-1; // Order of the polynomial
double par[2*n+1];
par[0] = n; // Tells the function the order of the polynomial
for (size_t p = 1; p < n+1; p++) {
par[p] = p*parx[p]; // (n-1) parameters from the xz fit
par[n+p] = p*pary[p]; // (n-1) parameters from the yz fit
}
// Path function of the 3D track, follows the variations in the two projections
if (!f_path)
f_path = new TF1("f_path", fpath, zstart, zend, 2*n+1);
f_path->SetParameters(par); // Tells the function the size of the array
double range = f_path->Integral(zstart, zend, f_path->GetParameters(), 1e-3);
// delete f_path;
return range;
}
double range_integral_error(std::vector parx,
std::vector pary,
std::vector eparx,
std::vector epary,
double zstart,
double zend,
double ezstart,
double ezend) {
if ( !parx.size() )
return -1.;
if ( parx.size() == 1 )
return sqrt(pow(ezstart, 2)+pow(ezend, 2));
size_t n = parx.size()-1; // Order of the polynomial
double par[2*n+3];
par[0] = n; // Tells the function the order of the polynomial
for (size_t p = 1; p < n+1; p++) {
par[p] = p*parx[p]; // (n-1) parameters from the xz fit
par[n+p] = p*pary[p]; // (n-1) parameters from the yz fit
}
// Error function of the 3D track, follows the variations in the two projections
TF1* f_error = new TF1("f_error", fpath_error, zstart, zend, 2*n+3);
// Each derivative in a parameter contributes to the total uncertainty
double error2(0.);
for (size_t k = 1; k < n+1; k++) {
par[2*n+1] = k; // Sets the order of the parameter (1->n)
par[2*n+2] = 0; // Sets the orientation of the projection
f_error->SetParameters(par); // Tells the function the size of the array
double integralx = f_error->Integral(zstart, zend, f_error->GetParameters(), 1e-3);
error2 += pow(k*integralx, 2)*eparx[k*(n+2)];
par[2*n+2] = 1; // Sets the orientation of the projection
f_error->SetParameters(par); // Tells the function the size of the array
double integraly = f_error->Integral(zstart, zend, f_error->GetParameters(), 1e-3);
error2 += pow(k*integraly, 2)*epary[k*(n+2)];
}
delete f_error;
// The uncertainty on the boundaries contributes to the total uncertainty as well
double drdzstart = fpath(&zstart, par);
double drdzend = fpath(&zend, par);
error2 += pow(drdzstart*ezstart, 2);
error2 += pow(drdzend*ezend, 2);
return sqrt(error2);
}
double fpol(double* x, double* par) {
double y(0.);
for (size_t p = 0; p < par[0]; p++)
y += par[p+1]*pow(x[0], p);
return y;
}
double fpath(double* x, double* par) {
size_t n = par[0]; // Number of derivative parameters
double parx[n+1], pary[n+1]; // Parameter containers
parx[0] = n;
pary[0] = n;
for (size_t i = 1; i < n+1; i++) {
parx[i] = par[i];
pary[i] = par[n+i];
}
double dpolx = fpol(x, parx); // Derivative of the xz polynome in z
double dpoly = fpol(x, pary); // Derivative of the yz polynome in z
return sqrt(1 + pow(dpolx, 2) + pow(dpoly, 2));
}
double fpath_error(double* x, double* par) {
size_t n = par[0]; // Number of derivative parameters
size_t k = par[2*n+1]; // Order of the parameter
double p = fpath(x, par); // Path function in x
double parq[n+1];
parq[0] = n;
for (size_t i = 1; i < n+1; i++) {
if ( !par[2*n+2] ) {
parq[i] = par[i];
} else {
parq[i] = par[n+i];
}
}
double dpol = fpol(x, parq);
return dpol*pow(x[0], k-1)/p; // p > 1, safe
}
} // namespace TrackRange