/* Copyright 2008-2009, Technische Universitaet Muenchen,
Authors: Christian Hoeppner & Sebastian Neubert
This file is part of GENFIT.
GENFIT is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GENFIT 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with GENFIT. If not, see .
*/
#include "AbsTrackRep.h"
#include "StateOnPlane.h"
#include "AbsMeasurement.h"
#include
#include
namespace genfit {
AbsTrackRep::AbsTrackRep() :
pdgCode_(0), propDir_(0), debugLvl_(0)
{
;
}
AbsTrackRep::AbsTrackRep(int pdgCode, char propDir) :
pdgCode_(pdgCode), propDir_(propDir), debugLvl_(0)
{
;
}
AbsTrackRep::AbsTrackRep(const AbsTrackRep& rep) :
TObject(rep), pdgCode_(rep.pdgCode_), propDir_(rep.propDir_), debugLvl_(rep.debugLvl_)
{
;
}
double AbsTrackRep::extrapolateToMeasurement(StateOnPlane& state,
const AbsMeasurement* measurement,
bool stopAtBoundary,
bool calcJacobianNoise) const {
return this->extrapolateToPlane(state, measurement->constructPlane(state), stopAtBoundary, calcJacobianNoise);
}
TVectorD AbsTrackRep::get6DState(const StateOnPlane& state) const {
TVector3 pos, mom;
getPosMom(state, pos, mom);
TVectorD stateVec(6);
stateVec(0) = pos.X();
stateVec(1) = pos.Y();
stateVec(2) = pos.Z();
stateVec(3) = mom.X();
stateVec(4) = mom.Y();
stateVec(5) = mom.Z();
return stateVec;
}
void AbsTrackRep::get6DStateCov(const MeasuredStateOnPlane& state, TVectorD& stateVec, TMatrixDSym& cov) const {
TVector3 pos, mom;
getPosMomCov(state, pos, mom, cov);
stateVec.ResizeTo(6);
stateVec(0) = pos.X();
stateVec(1) = pos.Y();
stateVec(2) = pos.Z();
stateVec(3) = mom.X();
stateVec(4) = mom.Y();
stateVec(5) = mom.Z();
}
double AbsTrackRep::getPDGCharge() const {
TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(pdgCode_);
assert(particle != NULL);
return particle->Charge()/(3.);
}
double AbsTrackRep::getMass(const StateOnPlane& /*state*/) const {
return TDatabasePDG::Instance()->GetParticle(pdgCode_)->Mass();
}
void AbsTrackRep::calcJacobianNumerically(const genfit::StateOnPlane& origState,
const genfit::SharedPlanePtr destPlane,
TMatrixD& jacobian) const {
// Find the transport matrix for track propagation from origState to destPlane
// I.e. this finds
// d stateDestPlane / d origState |_origState
jacobian.ResizeTo(getDim(), getDim());
// no science behind these values, I verified that forward and
// backward propagation yield inverse matrices to good
// approximation. In order to avoid bad roundoff errors, the actual
// step taken is determined below, separately for each direction.
const double defaultStepX = 1.E-5;
double stepX;
// Calculate derivative for all three dimensions successively.
// The algorithm follows the one in TF1::Derivative() :
// df(x) = (4 D(h/2) - D(h)) / 3
// with D(h) = (f(x + h) - f(x - h)) / (2 h).
//
// Could perhaps do better by also using f(x) which would be stB.
TVectorD rightShort(getDim()), rightFull(getDim());
TVectorD leftShort(getDim()), leftFull(getDim());
for (size_t i = 0; i < getDim(); ++i) {
{
genfit::StateOnPlane stateCopy(origState);
double temp = stateCopy.getState()(i) + defaultStepX / 2;
// Find the actual size of the step, which will differ from
// defaultStepX due to roundoff. This is the step-size we will
// use for this direction. Idea taken from Numerical Recipes,
// 3rd ed., section 5.7.
//
// Note that if a number is exactly representable, it's double
// will also be exact. Outside denormals, this also holds for
// halving. Unless the exponent changes (which it only will in
// the vicinity of zero) adding or subtracing doesn't make a
// difference.
//
// We determine the roundoff error for the half-step. If this
// is exactly representable, the full step will also be.
stepX = 2 * (temp - stateCopy.getState()(i));
(stateCopy.getState())(i) = temp;
extrapolateToPlane(stateCopy, destPlane);
rightShort = stateCopy.getState();
}
{
genfit::StateOnPlane stateCopy(origState);
(stateCopy.getState())(i) -= stepX / 2;
extrapolateToPlane(stateCopy, destPlane);
leftShort = stateCopy.getState();
}
{
genfit::StateOnPlane stateCopy(origState);
(stateCopy.getState())(i) += stepX;
extrapolateToPlane(stateCopy, destPlane);
rightFull = stateCopy.getState();
}
{
genfit::StateOnPlane stateCopy(origState);
(stateCopy.getState())(i) -= stepX;
extrapolateToPlane(stateCopy, destPlane);
leftFull = stateCopy.getState();
}
// Calculate the derivatives for the individual components of
// the track parameters.
for (size_t j = 0; j < getDim(); ++j) {
double derivFull = (rightFull(j) - leftFull(j)) / 2 / stepX;
double derivShort = (rightShort(j) - leftShort(j)) / stepX;
jacobian(j, i) = 1./3.*(4*derivShort - derivFull);
}
}
}
bool AbsTrackRep::switchPDGSign() {
TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(-pdgCode_);
if(particle != NULL) {
pdgCode_ *= -1;
return true;
}
return false;
}
void AbsTrackRep::Print(const Option_t*) const {
std::cout << "genfit::AbsTrackRep, pdgCode = " << pdgCode_ << ". PropDir = " << (int)propDir_ << "\n";
}
} /* End of namespace genfit */