/* 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 . */ /* */ /** @addtogroup RKTrackRep * @{ */ #ifndef RKTRACKREP_H #define RKTRACKREP_H #include "GFAbsTrackRep.h" #include "GFDetPlane.h" #include "GFTrackCand.h" #include /** @brief Track Representation module based on a Runge-Kutta algorithm including a full material model * * @author Christian Höppner (Technische Universität München, original author) * @author Johannes Rauch (Technische Universität München, author) * * The Runge Kutta implementation stems from GEANT3 originally (R. Brun et al.). * Porting to %C goes back to Igor Gavrilenko @ CERN. * The code was taken from the Phast analysis package of the COMPASS experiment * (Sergei Gerrassimov @ CERN). */ class RKTrackRep : public GFAbsTrackRep { public: // Constructors/Destructors --------- RKTrackRep(); RKTrackRep(const TVector3& pos, const TVector3& mom, const TVector3& poserr, const TVector3& momerr, const int& PDGCode); RKTrackRep(const GFTrackCand* aGFTrackCandPtr); RKTrackRep(const TVector3& pos, const TVector3& mom, const int& PDGCode); RKTrackRep(const GFDetPlane& pl, const TVector3& mom, const int& PDGCode); virtual ~RKTrackRep(); virtual GFAbsTrackRep* clone() const {return new RKTrackRep(*this);} virtual GFAbsTrackRep* prototype()const{return new RKTrackRep();} //! returns the tracklength spanned in this extrapolation /** The covariance matrix is transformed from the plane coordinate system to the master reference system (for the propagation) and, after propagation, back to the plane coordinate system.\n * Also the parameter spu (which is +1 or -1 and indicates the direction of the particle) is calculated and stored in #fCacheSpu. The plane is stored in #fCachePlane. * \n * * Master reference system (MARS): * \f{eqnarray*}x & = & O_{x}+uU_{x}+vV_{x}\\y & = & O_{y}+uU_{y}+vV_{y}\\z & = & O_{z}+uU_{z}+vV_{z}\\a_{x} & = & \frac{\mbox{spu}}{\widetilde{p}}\left(N_{x}+u\prime U_{x}+v\prime V_{x}\right)\\a_{y} & = & \frac{\mbox{spu}}{\widetilde{p}}\left(N_{y}+u\prime U_{y}+v\prime V_{y}\right)\\a_{z} & = & \frac{\mbox{spu}}{\widetilde{p}}\left(N_{z}+u\prime U_{z}+v\prime V_{z}\right)\\\frac{q}{p} & = & \frac{q}{p}\f} * Plane coordinate system: * \f{eqnarray*}u & = & \left(x-O_{x}\right)U_{x}+\left(y-O_{y}\right)U_{y}+\left(z-O_{z}\right)U_{z}\\v & = & \left(x-O_{x}\right)U_{x}+\left(y-O_{y}\right)U_{y}+\left(z-O_{z}\right)U_{z}\\u\prime & = & \frac{a_{x}U_{x}+a_{y}U_{y}+a_{z}U_{z}}{a_{x}N_{x}+a_{y}N_{y}+a_{z}N_{z}}\\v\prime & = & \frac{a_{x}V_{x}+a_{y}V_{y}+a_{z}V_{z}}{a_{x}N_{x}+a_{y}N_{y}+a_{z}N_{z}}\\\frac{q}{p} & = & \frac{q}{p}\\\mbox{spu} & = & \frac{a_{x}N_{x}+a_{y}N_{y}+a_{z}N_{z}}{|a_{x}^{2}N_{x}^{2}+a_{y}^{2}N_{y}^{2}+a_{z}^{2}N_{z}^{2}|}=\pm1\f} * * Jacobians:\n * \f$J_{p,M}=\left(\begin{array}{ccccc}\frac{\partial x}{\partial u} & \frac{\partial x}{\partial v} & \frac{\partial x}{\partial u\prime} & \frac{\partial x}{\partial v\prime} & \frac{\partial x}{\partial\frac{q}{p}}\\\frac{\partial y}{\partial u} & \frac{\partial y}{\partial v} & \frac{\partial y}{\partial u\prime} & \frac{\partial y}{\partial v\prime} & \frac{\partial y}{\partial\frac{q}{p}}\\\frac{\partial z}{\partial u} & \frac{\partial z}{\partial v} & \frac{\partial z}{\partial u\prime} & \frac{\partial z}{\partial v\prime} & \frac{\partial z}{\partial\frac{q}{p}}\\\frac{\partial a_{x}}{\partial u} & \frac{\partial a_{x}}{\partial v} & \frac{\partial a_{x}}{\partial u\prime} & \frac{\partial a_{x}}{\partial v\prime} & \frac{\partial a_{x}}{\partial\frac{q}{p}}\\\frac{\partial a_{y}}{\partial u} & \frac{\partial a_{y}}{\partial v} & \frac{\partial a_{y}}{\partial u\prime} & \frac{\partial a_{y}}{\partial v\prime} & \frac{\partial a_{y}}{\partial\frac{q}{p}}\\\frac{\partial a_{z}}{\partial u} & \frac{\partial a_{z}}{\partial v} & \frac{\partial a_{z}}{\partial u\prime} & \frac{\partial a_{z}}{\partial v\prime} & \frac{\partial a_{z}}{\partial\frac{q}{p}}\\\frac{\partial\frac{q}{p}}{\partial u} & \frac{\partial\frac{q}{p}}{\partial v} & \frac{\partial\frac{q}{p}}{\partial u\prime} & \frac{\partial\frac{q}{p}}{\partial v\prime} & \frac{\partial\frac{q}{p}}{\partial\frac{q}{p}}\end{array}\right)\f$ * * \f$J_{p,M}=\left(\begin{array}{cccccc}U_{x} & V_{x} & 0 & 0 & 0\\U_{y} & V_{y} & 0 & 0 & 0\\U_{z} & V_{z} & 0 & 0 & 0\\0 & 0 & \left\{ \frac{\textrm{spu}}{\widetilde{p}}U_{x}-\left[\frac{\textrm{spu}}{\widetilde{p}^{3}}\widetilde{p}_{x}\left(U_{x}\widetilde{p}_{x}+U_{y}\widetilde{p}_{y}+U_{z}\widetilde{p}_{z}\right)\right]\right\} & \left\{ \frac{\textrm{spu}}{\widetilde{p}}V_{x}-\left[\frac{\textrm{spu}}{\widetilde{p}^{3}}\widetilde{p}_{x}\left(V_{x}\widetilde{p}_{x}+V_{y}\widetilde{p}_{y}+V_{z}\widetilde{p}_{z}\right)\right]\right\} & 0\\0 & 0 & \left\{ \frac{\textrm{spu}}{\widetilde{p}}U_{y}-\left[\frac{\textrm{spu}}{\widetilde{p}^{3}}\widetilde{p}_{y}\left(U_{x}\widetilde{p}_{x}+U_{y}\widetilde{p}_{y}+U_{z}\widetilde{p}_{z}\right)\right]\right\} & \left\{ \frac{\textrm{spu}}{\widetilde{p}}V_{y}-\left[\frac{\textrm{spu}}{\widetilde{p}^{3}}\widetilde{p}_{y}\left(V_{x}\widetilde{p}_{x}+V_{y}\widetilde{p}_{y}+V_{z}\widetilde{p}_{z}\right)\right]\right\} & 0\\0 & 0 & \left\{ \frac{\textrm{spu}}{\widetilde{p}}U_{z}-\left[\frac{\textrm{spu}}{\widetilde{p}^{3}}\widetilde{p}_{z}\left(U_{x}\widetilde{p}_{x}+U_{y}\widetilde{p}_{y}+U_{z}\widetilde{p}_{z}\right)\right]\right\} & \left\{ \frac{\textrm{spu}}{\widetilde{p}}V_{z}-\left[\frac{\textrm{spu}}{\widetilde{p}^{3}}\widetilde{p}_{z}\left(V_{x}\widetilde{p}_{x}+V_{y}\widetilde{p}_{y}+V_{z}\widetilde{p}_{z}\right)\right]\right\} & 0\\0 & 0 & 0 & 0 & 1\end{array}\right)\f$ * * with * \f{eqnarray*}\widetilde{p} & = & \sqrt{\widetilde{p}_{x}^{2}+\widetilde{p}_{y}^{2}+\widetilde{p}_{z}^{2}}\\\widetilde{p}_{x} & = & \textrm{spu}\left(N_{x}+u\prime U_{x}+v\prime V_{x}\right)\\\widetilde{p}_{y} & = & \textrm{spu}\left(N_{y}+u\prime U_{y}+v\prime V_{y}\right)\\\widetilde{p}_{z} & = & \textrm{spu}\left(N_{z}+u\prime U_{z}+v\prime V_{z}\right)\f} * * \f$J_{M,p}=\left(\begin{array}{ccccccc}\frac{\partial u}{\partial x} & \frac{\partial u}{\partial y} & \frac{\partial u}{\partial z} & \frac{\partial u}{\partial a_{x}} & \frac{\partial u}{\partial a_{y}} & \frac{\partial u}{\partial a_{z}} & \frac{\partial u}{\partial\frac{q}{p}}\\\frac{\partial v}{\partial x} & \frac{\partial v}{\partial y} & \frac{\partial v}{\partial z} & \frac{\partial v}{\partial a_{x}} & \frac{\partial v}{\partial a_{y}} & \frac{\partial v}{\partial a_{z}} & \frac{\partial v}{\partial\frac{q}{p}}\\\frac{\partial u\prime}{\partial x} & \frac{\partial u\prime}{\partial y} & \frac{\partial u\prime}{\partial z} & \frac{\partial u\prime}{\partial a_{x}} & \frac{\partial u\prime}{\partial a_{y}} & \frac{\partial u\prime}{\partial a_{z}} & \frac{\partial u\prime}{\partial\frac{q}{p}}\\\frac{\partial v\prime}{\partial x} & \frac{\partial v\prime}{\partial y} & \frac{\partial v\prime}{\partial z} & \frac{\partial v\prime}{\partial a_{x}} & \frac{\partial v\prime}{\partial a_{y}} & \frac{\partial v\prime}{\partial a_{z}} & \frac{\partial v\prime}{\partial\frac{q}{p}}\\ \frac{\partial\frac{q}{p}}{\partial x} & \frac{\partial\frac{q}{p}}{\partial y} & \frac{\partial\frac{q}{p}}{\partial z} & \frac{\partial\frac{q}{p}}{\partial a_{x}} & \frac{\partial\frac{q}{p}}{\partial a_{y}} & \frac{\partial\frac{q}{p}}{\partial a_{z}} & \frac{\partial\frac{q}{p}}{\partial\frac{q}{p}}\\ \\\end{array}\right)\f$ * * \f$J_{M,p}=\left(\begin{array}{ccccccc} U_{x} & U_{y} & U_{z} & 0 & 0 & 0 & 0\\ V_{x} & V_{y} & V_{z} & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & \frac{U_{x}\left(a_{y}N_{y}+a_{z}N_{z}\right)-N_{x}\left(a_{y}U_{y}+a_{z}U_{z}\right)}{\left(a_{x}N_{x}+a_{y}N_{y}+a_{z}N_{z}\right)^{2}} & \frac{U_{y}\left(a_{x}N_{x}+a_{z}N_{z}\right)-N_{y}\left(a_{x}U_{x}+a_{z}U_{z}\right)}{\left(a_{x}N_{x}+a_{y}N_{y}+a_{z}N_{z}\right)^{2}} & \frac{U_{z}\left(a_{x}N_{x}+a_{y}N_{y}\right)-N_{z}\left(a_{x}U_{x}+a_{y}U_{y}\right)}{\left(a_{x}N_{x}+a_{y}N_{y}+a_{z}N_{z}\right)^{2}} & 0\\ 0 & 0 & 0 & \frac{V_{x}\left(a_{y}N_{y}+a_{z}N_{z}\right)-N_{x}\left(a_{y}V_{y}+a_{z}V_{z}\right)}{\left(a_{x}N_{x}+a_{y}N_{y}+a_{z}N_{z}\right)^{2}} & \frac{V_{y}\left(a_{x}N_{x}+a_{z}N_{z}\right)-N_{y}\left(a_{x}V_{x}+a_{z}V_{z}\right)}{\left(a_{x}N_{x}+a_{y}N_{y}+a_{z}N_{z}\right)^{2}} & \frac{V_{z}\left(a_{x}N_{x}+a_{y}N_{y}\right)-N_{z}\left(a_{x}V_{x}+a_{y}V_{y}\right)}{\left(a_{x}N_{x}+a_{y}N_{y}+a_{z}N_{z}\right)^{2}} & 0\\ 0 & 0 & 0 & 0 & 0 & 0 & 1\\ \\\end{array}\right)\f$ * */ double extrapolate(const GFDetPlane&, TMatrixT& statePred, TMatrixT& covPred); //! returns the tracklength spanned in this extrapolation double extrapolate(const GFDetPlane&, TMatrixT& statePred); //! This method is to extrapolate the track to point of closest approach to a point in space void extrapolateToPoint(const TVector3& pos, TVector3& poca, TVector3& dirInPoca); //! This method extrapolates to the point of closest approach to a line void extrapolateToLine(const TVector3& point1, const TVector3& point2, TVector3& poca, TVector3& dirInPoca, TVector3& poca_onwire); //! make step of h cm along the track, returns the tracklength spanned in this extrapolation /** Also returns the position and direction by reference. * It does NOT alter the state of the trackrep and starts extrapolating from #fRefPlane. */ double stepalong(double h, TVector3& point, TVector3& dir); //! Returns position of the track in the plane /** If #GFDetPlane equals the reference plane #fRefPlane, returns current position; otherwise it extrapolates * the track to the plane and returns the position. */ TVector3 getPos(const GFDetPlane&); //! Returns momentum of the track in the plane /** If #GFDetPlane equals the reference plane #fRefPlane, returns current momentum; otherwise it extrapolates * the track to the plane and returns the momentum. */ TVector3 getMom(const GFDetPlane&); //! Gets position and momentum in the plane /** If #GFDetPlane equals the reference plane #fRefPlane, it gets current position and momentum; otherwise it extrapolates * the track to the plane and gets the position and momentum. */ void getPosMom(const GFDetPlane&,TVector3& pos,TVector3& mom); //! Returns charge double getCharge()const {return fCharge;} int getPDG() {return fPdg;}; //! deprecated void switchDirection(){fDirection = (!fDirection);} //! Set PDG particle code void setPDG(int); //! Sets state, plane and (optionally) covariance /** This function also sets the parameter #fSpu to the value stored in #fCacheSpu. Therefore it has to be ensured that * the plane #pl is the same as the plane of the last extrapolation (i.e. #fCachePlane), where #fCacheSpu was calculated. * Hence, if the argument #pl is not equal to #fCachePlane, an error message is shown an an exception is thrown. */ void setData(const TMatrixT& st, const GFDetPlane& pl, const TMatrixT* cov=NULL, const TMatrixT* aux=NULL); const TMatrixT* getAuxInfo(const GFDetPlane& pl); bool hasAuxInfo() { return true; } void getPosMomCov(const GFDetPlane& pl, TVector3& pos, TVector3& mom, TMatrixT& cov); //to be implemented soon private: RKTrackRep& operator=(const RKTrackRep* ){return *this;}; // rhs // [R.K.03/2017] unused variable(s) //! Propagates the particle through the magnetic field. /** If the propagation is successfull and the plane is reached, the function returns true. * The argument P has to contain the state (#P[0] - #P[6]) and a unity matrix (#P[7] - #P[55]) * with the last column multiplied wit q/p (hence #P[55] is not 1 but q/p). * Propagated state and the jacobian (with the last column multiplied wit q/p) of the extrapolation are written to #P. * In the main loop of the Runge Kutta algorithm, the steppers in #fEffect are called * and may reduce the estimated stepsize so that a maximum momentum loss will not be exceeded. * 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 GFDetPlane& plane,double* P, double& coveredDistance, std::vector& points, std::vector& pointLengths, const double& maxLen=-1, bool calcCov=true) const; TVector3 poca2Line(const TVector3& extr1,const TVector3& extr2,const TVector3& point) const; //! Handles propagation and material effects /** extrapolate(), extrapolateToPoint() and extrapolateToLine() 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 in #fEffect are called. * Extrap() will loop until the plane is reached, unless the propagation fails or the maximum number of * iterations is exceeded. */ double Extrap(const GFDetPlane& plane, TMatrixT* state, TMatrixT* cov=NULL) const; //RKTrackRep(const RKTrackRep& rhs){}; // data members bool fDirection; //! PDG particle code int fPdg; //! Mass (in GeV) double fMass; //! Charge double fCharge; GFDetPlane fCachePlane; double fCacheSpu; double fSpu; TMatrixT fAuxInfo; public: ClassDef(RKTrackRep,4) }; #endif /** @} */