/* Copyright 2008-2010, Technische Universitaet Muenchen,
Authors: Christian Hoeppner & Sebastian Neubert & Johannes Rauch
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 .
*/
/** @addtogroup RKTrackRep
* @{
*/
#ifndef genfit_RKTrackRep_h
#define genfit_RKTrackRep_h
#include "AbsTrackRep.h"
#include "StateOnPlane.h"
#include "RKTools.h"
#include "StepLimits.h"
namespace genfit {
/**
* @brief Helper for RKTrackRep
*/
struct RKStep {
MatStep matStep_; // material properties and stepsize
M1x7 state7_; // 7D state vector
StepLimits limits_;
RKStep() {
memset(state7_, 0x00, 7*sizeof(double));
}
};
/**
* @brief Helper for RKTrackRep
*/
struct ExtrapStep {
M7x7 jac7_; // 5D jacobian of transport
M7x7 noise7_; // 5D noise matrix
ExtrapStep() {
memset(jac7_, 0, sizeof(M7x7));
memset(noise7_, 0, sizeof(M7x7));
}
};
/**
* @brief AbsTrackRep with 5D track parameterization in plane coordinates: (q/p, u', v', u, v)
*
* q/p is charge over momentum.
* u' and v' are direction tangents.
* u and v are positions on a DetPlane.
*/
class RKTrackRep : public AbsTrackRep {
public:
RKTrackRep();
RKTrackRep(int pdgCode, char propDir = 0);
virtual ~RKTrackRep();
virtual AbsTrackRep* clone() const {return new RKTrackRep(*this);}
virtual double extrapolateToPlane(StateOnPlane& state,
const SharedPlanePtr& plane,
bool stopAtBoundary = false,
bool calcJacobianNoise = false) const;
using AbsTrackRep::extrapolateToLine;
virtual double extrapolateToLine(StateOnPlane& state,
const TVector3& linePoint,
const TVector3& lineDirection,
bool stopAtBoundary = false,
bool calcJacobianNoise = false) const;
virtual double extrapolateToPoint(StateOnPlane& state,
const TVector3& point,
bool stopAtBoundary = false,
bool calcJacobianNoise = false) const {
return extrapToPoint(state, point, NULL, stopAtBoundary, calcJacobianNoise);
}
virtual double extrapolateToPoint(StateOnPlane& state,
const TVector3& point,
const TMatrixDSym& G, // weight matrix (metric)
bool stopAtBoundary = false,
bool calcJacobianNoise = false) const {
return extrapToPoint(state, point, &G, stopAtBoundary, calcJacobianNoise);
}
virtual double extrapolateToCylinder(StateOnPlane& state,
double radius,
const TVector3& linePoint = TVector3(0.,0.,0.),
const TVector3& lineDirection = TVector3(0.,0.,1.),
bool stopAtBoundary = false,
bool calcJacobianNoise = false) const;
virtual double extrapolateToSphere(StateOnPlane& state,
double radius,
const TVector3& point = TVector3(0.,0.,0.),
bool stopAtBoundary = false,
bool calcJacobianNoise = false) const;
virtual double extrapolateBy(StateOnPlane& state,
double step,
bool stopAtBoundary = false,
bool calcJacobianNoise = false) const;
unsigned int getDim() const {return 5;}
virtual TVector3 getPos(const StateOnPlane& state) const;
virtual TVector3 getMom(const StateOnPlane& state) const;
virtual void getPosMom(const StateOnPlane& state, TVector3& pos, TVector3& mom) const;
virtual double getMomMag(const StateOnPlane& state) const;
virtual double getMomVar(const MeasuredStateOnPlane& state) const;
virtual TMatrixDSym get6DCov(const MeasuredStateOnPlane& state) const;
virtual void getPosMomCov(const MeasuredStateOnPlane& state, TVector3& pos, TVector3& mom, TMatrixDSym& cov) const;
virtual double getCharge(const StateOnPlane& state) const;
virtual double getQop(const StateOnPlane& state) const {return state.getState()(0);}
double getSpu(const StateOnPlane& state) const;
double getTime(const StateOnPlane& state) const;
virtual void getForwardJacobianAndNoise(TMatrixD& jacobian, TMatrixDSym& noise, TVectorD& deltaState) const;
virtual void getBackwardJacobianAndNoise(TMatrixD& jacobian, TMatrixDSym& noise, TVectorD& deltaState) const;
std::vector getSteps() const;
virtual double getRadiationLenght() const;
virtual void setPosMom(StateOnPlane& state, const TVector3& pos, const TVector3& mom) const;
virtual void setPosMom(StateOnPlane& state, const TVectorD& state6) const;
virtual void setPosMomErr(MeasuredStateOnPlane& state, const TVector3& pos, const TVector3& mom, const TVector3& posErr, const TVector3& momErr) const;
virtual void setPosMomCov(MeasuredStateOnPlane& state, const TVector3& pos, const TVector3& mom, const TMatrixDSym& cov6x6) const;
virtual void setPosMomCov(MeasuredStateOnPlane& state, const TVectorD& state6, const TMatrixDSym& cov6x6) const;
virtual void setChargeSign(StateOnPlane& state, double charge) const;
virtual void setQop(StateOnPlane& state, double qop) const {state.getState()(0) = qop;}
void setSpu(StateOnPlane& state, double spu) const;
void setTime(StateOnPlane& state, double time) const;
//! The actual Runge Kutta propagation
/** propagate state7 with step S. Fills SA (Start directions derivatives dA/S).
* If jacobian is NULL, only the state is propagated,
* otherwise also the 7x7 jacobian is calculated.
* If varField is false, the magnetic field will only be evaluated at the starting position.
* The return value is an estimation on how good the extrapolation is, and it is usually fine if it is > 1.
* It gives a suggestion how you must scale S so that the quality will be sufficient.
*/
double RKPropagate(M1x7& state7,
M7x7* jacobian,
M1x3& SA,
double S,
bool varField = true,
bool calcOnlyLastRowOfJ = false) const;
virtual bool isSameType(const AbsTrackRep* other);
virtual bool isSame(const AbsTrackRep* other);
private:
void initArrays() const;
virtual double extrapToPoint(StateOnPlane& state,
const TVector3& point,
const TMatrixDSym* G = NULL, // weight matrix (metric)
bool stopAtBoundary = false,
bool calcJacobianNoise = false) const;
void getState7(const StateOnPlane& state, M1x7& state7) const;
void getState5(StateOnPlane& state, const M1x7& state7) const; // state7 must already lie on plane of state!
void transformPM7(const MeasuredStateOnPlane& state,
M7x7& out7x7) const;
void calcJ_pM_5x7(M5x7& J_pM, const TVector3& U, const TVector3& V, const M1x3& pTilde, double spu) const;
void transformPM6(const MeasuredStateOnPlane& state,
M6x6& out6x6) const;
void transformM7P(const M7x7& in7x7,
const M1x7& state7,
MeasuredStateOnPlane& state) const; // plane must already be set!
void calcJ_Mp_7x5(M7x5& J_Mp, const TVector3& U, const TVector3& V, const TVector3& W, const M1x3& A) const;
void calcForwardJacobianAndNoise(const M1x7& startState7, const DetPlane& startPlane,
const M1x7& destState7, const DetPlane& destPlane) const;
void transformM6P(const M6x6& in6x6,
const M1x7& state7,
MeasuredStateOnPlane& state) const; // plane and charge must already be set!
//! Propagates the particle through the magnetic field.
/** If the propagation is successful and the plane is reached, the function returns true.
* Propagated state and the jacobian of the extrapolation are written to state7 and jacobianT.
* The jacobian is only calculated if jacobianT != NULL.
* In the main loop of the Runge Kutta algorithm, the estimateStep() is called
* and may reduce the estimated stepsize so that a maximum momentum loss will not be exceeded,
* and stop at material boundaries.
* If this is the case, RKutta() will only propagate the reduced distance and then return. This is to ensure that
* material effects, which are calculated after the propagation, are taken into account properly.
*/
bool RKutta(const M1x4& SU,
const DetPlane& plane,
double charge,
double mass,
M1x7& state7,
M7x7* jacobianT,
M1x7* J_MMT_unprojected_lastRow,
double& coveredDistance, // signed
double& flightTime,
bool& checkJacProj,
M7x7& noiseProjection,
StepLimits& limits,
bool onlyOneStep = false,
bool calcOnlyLastRowOfJ = false) const;
double estimateStep(const M1x7& state7,
const M1x4& SU,
const DetPlane& plane,
const double& charge,
double& relMomLoss,
StepLimits& limits) const;
TVector3 pocaOnLine(const TVector3& linePoint,
const TVector3& lineDirection,
const TVector3& point) const;
//! Handles propagation and material effects
/** #extrapolateToPlane(), #extrapolateToPoint() and #extrapolateToLine() etc. call this function.
* #Extrap() needs a plane as an argument, hence #extrapolateToPoint() and #extrapolateToLine() create virtual detector planes.
* In this function, #RKutta() is called and the resulting points and point paths are filtered
* so that the direction doesn't change and tiny steps are filtered out.
* After the propagation the material effects are called via the MaterialEffects singleton.
* #Extrap() will loop until the plane is reached, unless the propagation fails or the maximum number of
* iterations is exceeded.
*/
double Extrap(const DetPlane& startPlane, // plane where Extrap starts
const DetPlane& destPlane, // plane where Extrap has to extrapolate to
double charge,
double mass,
bool& isAtBoundary,
M1x7& state7,
double& flightTime,
bool fillExtrapSteps,
TMatrixDSym* cov = nullptr,
bool onlyOneStep = false,
bool stopAtBoundary = false,
double maxStep = 1.E99) const;
void checkCache(const StateOnPlane& state, const SharedPlanePtr* plane) const;
double momMag(const M1x7& state7) const;
mutable StateOnPlane lastStartState_; //! state where the last extrapolation has started
mutable StateOnPlane lastEndState_; //! state where the last extrapolation has ended
mutable std::vector RKSteps_; //! RungeKutta steps made in the last extrapolation
mutable int RKStepsFXStart_; //!
mutable int RKStepsFXStop_; //!
mutable std::vector ExtrapSteps_; //! steps made in Extrap during last extrapolation
mutable TMatrixD fJacobian_; //!
mutable TMatrixDSym fNoise_; //!
mutable bool useCache_; //! use cached RKSteps_ for extrapolation
mutable unsigned int cachePos_; //!
// auxiliary variables and arrays
// needed in Extrap()
mutable StepLimits limits_; //!
mutable M7x7 noiseArray_; //! noise matrix of the last extrapolation
mutable M7x7 noiseProjection_; //!
mutable M7x7 J_MMT_; //!
public:
ClassDef(RKTrackRep, 1)
};
} /* End of namespace genfit */
/** @} */
#endif // genfit_RKTrackRep_h