#include "TMath.h"
#include "TRotation.h"
#include "TVector3.h"
#include "hkalgeomtools.h"
#include "hkalmatrixtools.h"
#include "hkaltracksite.h"
#include "hkaltrackstate.h"
#include <iostream>
using namespace std;
#include <cstdlib>
ClassImp(HKalTrackSite)
HKalTrackSite::HKalTrackSite(Int_t measDim, Int_t stateDimSec, Int_t stateDimVirtLay)
: TObject(), bActive(kTRUE), effErrMat(measDim, measDim), effMeasVec(measDim) {
Int_t nCoordSys = 2;
trackStates = new HKalTrackState**[nCoordSys];
for(Int_t i = 0; i < nCoordSys; i++) {
trackStates[i] = new HKalTrackState*[kNumKalStates];
}
for(Int_t stateType = 0; stateType < kNumKalStates; stateType++) {
trackStates[kSecCoord][stateType] = new HKalTrackState((Kalman::kalFilterTypes)stateType, measDim, stateDimSec);
}
for(Int_t stateType = 0; stateType < kNumKalStates; stateType++) {
trackStates[kLayCoord][stateType] = new HKalTrackState((Kalman::kalFilterTypes)stateType, measDim, stateDimVirtLay);
}
hits = new TObjArray();
hits->Add(new HKalMdcHit(measDim));
}
HKalTrackSite::~HKalTrackSite() {
delete hits;
delete [] trackStates;
}
HKalMdcHit* HKalTrackSite::getHitPtr(Int_t idx) {
if(idx >= hits->GetEntries() || idx < 0 || hits->GetEntries() == 0) {
Error("getHit()", Form("No hit at index %i. Only %i hits stored. Returning first hit object.", idx, hits->GetEntries()));
return (HKalMdcHit*)hits->At(0);
} else {
return (HKalMdcHit*)hits->At(idx);
}
}
void HKalTrackSite::transformHit(const TRotation &transMat) {
for(Int_t i = 0; i < hits->GetLast() + 1; i++) {
getHitPtr(i)->transformHit(transMat);
}
getHitPtr()->transformLayer(transMat);
}
void HKalTrackSite::transformStates(const TRotation &transMat) {
for(Int_t stateType = 0; stateType < kNumKalStates; stateType++) {
if(getHitType() == Kalman::kSegHit) {
trackStates[kSecCoord][stateType]->transform(transMat, getHitPtr(0)->getMeasLayer());
}
if(getHitType() == Kalman::kWireHit) {
trackStates[kSecCoord][stateType]->transform(transMat, getHitPtr(0)->getVirtPlane());
}
}
}
void HKalTrackSite::addHit(HKalMdcHit *newhit) {
hits->Add(newhit);
}
void HKalTrackSite::calcJacLayToSec(TMatrixD &jac, const TVectorD &svLay, const HKalPlane &plane) const {
Int_t secDim = getStateDim(kSecCoord);
Int_t layDim = getStateDim(kLayCoord);
Int_t nRows = jac.GetNrows();
Int_t nCols = jac.GetNcols();
if(nRows != secDim || nCols != layDim) {
jac.ResizeTo(secDim, layDim);
::Warning("calcJacobianFromLayerToSector()", Form("Output parameter for Jacobian matrix had to be resized from %ix%i to %ix%i.", nRows, nCols, secDim, layDim));
}
#if kalDebug > 0
if(svLay.GetNrows() != layDim) {
::Error("calcJacobianFromLayerToSector()", Form("Input state vector has dimension %i, but needs to be %i.", svLay.GetNrows(), layDim));
return;
}
#endif
const TVector3 &u = plane.getAxisU();
const TVector3 &v = plane.getAxisV();
const TVector3 &w = plane.getNormal();
Double_t tu = svLay(kIdxTanPhi);
Double_t tv = svLay(kIdxTanTheta);
TVector3 dir = tu*u + tv*v + w;
Double_t dirz2 = dir.Z() * dir.Z();
jac.Zero();
jac(kIdxX0, kIdxX0) = u.X();
jac(kIdxY0, kIdxX0) = u.Y();
jac(kIdxX0, kIdxY0) = v.X();
jac(kIdxY0, kIdxY0) = v.Y();
if(secDim > 5) {
jac(kIdxZ0, kIdxX0) = u.Z();
jac(kIdxZ0, kIdxY0) = v.Z();
}
jac(kIdxTanPhi, kIdxTanPhi) = (tv*u.X()*v.Z() + u.X()*w.Z() - tv*u.Z()*v.X() - u.Z()*w.X()) / dirz2;
jac(kIdxTanPhi, kIdxTanTheta) = (tu*u.Z()*v.X() + v.X()*w.Z() - tu*u.X()*v.Z() - v.Z()*w.X()) / dirz2;
jac(kIdxTanTheta, kIdxTanPhi) = (tv*u.y()*v.Z() + u.Y()*w.Z() - tv*u.Z()*v.Y() - u.Z()*w.Y()) / dirz2;
jac(kIdxTanTheta, kIdxTanTheta) = (tu*u.Z()*v.Y() + v.Y()*w.Z() - tu*u.Y()*v.Z() - v.Z()*w.Y()) / dirz2;
jac(kIdxQP, kIdxQP) = 1.;
}
void HKalTrackSite::calcJacSecToLay(TMatrixD &jac, const TVectorD &svSec, const HKalPlane &plane) const {
Int_t secDim = getStateDim(kSecCoord);
Int_t layDim = getStateDim(kLayCoord);
Int_t nRows = jac.GetNrows();
Int_t nCols = jac.GetNcols();
if(nRows != layDim || nCols != secDim) {
jac.ResizeTo(layDim, secDim);
::Warning("calcJacobianFromLayerToSector()", Form("Output parameter for Jacobian matrix had to be resized from %ix%i to %ix%i.", nRows, nCols, layDim, secDim));
}
#if kalDebug > 0
if(svSec.GetNrows() != secDim) {
::Error("calcJacobianFromSectorToLayer()", Form("Input state vector has dimension %i, but needs to be %i", svSec.GetNrows(), secDim));
return;
}
#endif
const TVector3 &u = plane.getAxisU();
const TVector3 &v = plane.getAxisV();
const TVector3 &w = plane.getNormal();
TVector3 dir;
Double_t tx = svSec(kIdxTanPhi);
Double_t ty = svSec(kIdxTanTheta);
dir.SetXYZ(tx, ty, 1.);
Double_t aw = dir * w;
Double_t aw2 = aw * aw;
jac.Zero();
jac(kIdxX0, kIdxX0) = u.X();
jac(kIdxX0, kIdxY0) = u.Y();
jac(kIdxY0, kIdxX0) = v.X();
jac(kIdxY0, kIdxY0) = v.Y();
if(secDim > 5) {
jac(kIdxX0, kIdxZ0) = u.Z();
jac(kIdxY0, kIdxZ0) = v.Z();
}
jac(kIdxTanPhi, kIdxTanPhi) = (ty*u.X()*w.Y() + u.X()*w.Z() - ty*u.Y()*w.X() - u.Z()*w.X()) / aw2;
jac(kIdxTanPhi, kIdxTanTheta) = (tx*u.Y()*w.X() + u.Y()*w.Z() - tx*u.X()*w.Y() - u.Z()*w.Y()) / aw2;
jac(kIdxTanTheta, kIdxTanPhi) = (ty*v.X()*w.Y() + v.X()*w.Z() - ty*v.Y()*w.X() - v.Z()*w.X()) / aw2;
jac(kIdxTanTheta, kIdxTanTheta) = (tx*v.Y()*w.X() + v.Y()*w.Z() - tx*v.X()*w.Y() - v.Z()*w.Y()) / aw2;
jac(kIdxQP, kIdxQP) = 1.;
}
void HKalTrackSite::clearHits() {
hits->Delete();
effMeasVec.Zero();
effErrMat.Zero();
bActive = kTRUE;
}
void HKalTrackSite::sortHits() {
hits->Sort();
}
void HKalTrackSite::print(const Option_t *opt) const {
cout<<"**** Print content of site ****"<<endl;
TString stropt(opt);
if(stropt.Contains("Hit", TString::kIgnoreCase) || stropt.IsNull()) {
for(Int_t i = 0; i < getNcompetitors(); i++) {
cout<<"Printing hit number "<<i<<" in site."<<endl;
getHit(i).print("Hit");
}
}
if(stropt.Contains("Pred", TString::kIgnoreCase) || stropt.IsNull()) {
trackStates[kSecCoord][kPredicted] ->print("SFCQ");
}
if(stropt.Contains("Filt", TString::kIgnoreCase) || stropt.IsNull()) {
trackStates[kSecCoord][kFiltered] ->print("SC");
}
if(stropt.Contains("Smoo", TString::kIgnoreCase) || stropt.IsNull()) {
trackStates[kSecCoord][kSmoothed] ->print("SC");
}
if(stropt.Contains("Inv", TString::kIgnoreCase) || stropt.IsNull()) {
trackStates[kSecCoord][kInvFiltered]->print("SC");
}
cout<<"**** End print of site ****"<<endl;
}
void HKalTrackSite::transform(const TRotation &transMat) {
#if kalDebug > 1
if(transMat.IsIdentity()) {
Warning("transform()", "Rotation matrix for coordinate transformation not set.");
}
#endif
transformStates(transMat);
transformHit(transMat);
}
void HKalTrackSite::transVirtLayToSec(Kalman::kalFilterTypes stateType,
Int_t iHit,
Bool_t bCovUD) {
Int_t secDim = getStateDim();
Int_t layDim = getStateDim(kLayCoord);
const HKalPlane &virtPlane = getHitVirtPlane(iHit);
const TVectorD &svLay = getStateVec(stateType, kLayCoord);
TVectorD svSec(secDim);
HKalTrackState::transformFromLayerToSector(svSec, svLay, virtPlane);
setStateVec(stateType, svSec, kSecCoord);
TMatrixD jacLaySec(secDim, layDim);
calcJacLayToSec(jacLaySec, svLay, virtPlane);
TMatrixD jacLaySecTrans = TMatrixD(TMatrixD::kTransposed, jacLaySec);
const TMatrixD &covLay = getStateCovMat(stateType, kLayCoord);
if(bCovUD) {
TMatrixD U(layDim, layDim);
TMatrixD D(layDim, layDim);
HKalMatrixTools::resolveUD(U, D, covLay);
TMatrixD covLayUD = U * D * TMatrixD(TMatrixD::kTransposed, U);
TMatrixD covSec = jacLaySec * covLayUD * jacLaySecTrans;
if(!covSec.IsSymmetric()) {
HKalMatrixTools::makeSymmetric(covSec);
}
HKalMatrixTools::decomposeUD(covSec);
setStateCovMat(stateType, covSec, kSecCoord);
} else {
TMatrixD covSec = jacLaySec * covLay * jacLaySecTrans;
setStateCovMat(stateType, covSec, kSecCoord);
}
}
void HKalTrackSite::transSecToVirtLay(Kalman::kalFilterTypes stateType,
Int_t iHit,
Bool_t bCovUD) {
Int_t secDim = getStateDim();
Int_t layDim = getStateDim(kLayCoord);
const HKalPlane &virtPlane = getHitVirtPlane(iHit);
const TVectorD &svSec = getStateVec(stateType, kSecCoord);
TVectorD svLay(layDim);
HKalTrackState::transformFromSectorToLayer(svLay, svSec, virtPlane);
setStateVec(stateType, svLay, kLayCoord);
TMatrixD jacSecLay(layDim, secDim);
calcJacSecToLay(jacSecLay, svSec, virtPlane);
TMatrixD jacSecLayTrans = TMatrixD(TMatrixD::kTransposed, jacSecLay);
const TMatrixD &covSec = getStateCovMat(stateType, kSecCoord);
if(bCovUD) {
TMatrixD U(secDim, secDim);
TMatrixD D(secDim, secDim);
HKalMatrixTools::resolveUD(U, D, covSec);
TMatrixD covSecUD = U * D * TMatrixD(TMatrixD::kTransposed, U);
TMatrixD covLay = jacSecLay * covSecUD * jacSecLayTrans;
if(!covLay.IsSymmetric()) {
HKalMatrixTools::makeSymmetric(covLay);
}
HKalMatrixTools::decomposeUD(covLay);
setStateCovMat(stateType, covLay, kLayCoord);
} else {
TMatrixD covLay = jacSecLay * covSec * jacSecLayTrans;
if(!covLay.IsSymmetric()) {
HKalMatrixTools::makeSymmetric(covLay);
}
setStateCovMat(stateType, covLay, kLayCoord);
}
}
TMatrixD const& HKalTrackSite::getErrMat(Int_t idx) const {
if(idx < 0) {
#if kalDebug > 0
if(getHitsTotalWeight() > 0. && effErrMat.NonZeros() == 0) {
Warning("getErrMat()", "Effective measurement covariance is zero.");
effErrMat.Print();
}
#endif
return effErrMat;
}
return getHit(idx).getErrMat();
}
HKalMdcHit const& HKalTrackSite::getHit(Int_t idx) const {
if(idx >= hits->GetEntries() || idx < 0 || hits->GetEntries() == 0) {
Error("getHit()", Form("No hit at index %i. %i hits are stored.", idx, hits->GetEntries()));
return (const HKalMdcHit&) (* (HKalMdcHit*)hits->At(0));
} else {
return (const HKalMdcHit&) (* (HKalMdcHit*)hits->At(idx));
}
}
Double_t HKalTrackSite::getHitsTotalWeight() const {
Double_t totalWeight = 0.;
for(Int_t i = 0; i < getNcompetitors(); i++) {
totalWeight += getHit(i).getWeight();
}
return totalWeight;
}
TVectorD const& HKalTrackSite::getHitVec(Int_t idx) const {
if(idx < 0) {
#if kalDebug > 0
if(getHitsTotalWeight() > 0. && effMeasVec.NonZeros() == 0) {
Warning("getHitVec()", "Effective measurement vector is zero.");
}
#endif
return effMeasVec;
}
return getHit(idx).getHitVec();
}
void HKalTrackSite::setNdafs(Int_t n) {
for(Int_t i = 0; i < getNcompetitors(); i++ ) {
getHitPtr(i)->setNdafs(n);
}
}
void HKalTrackSite::getPosAndDirFromState(TVector3 &pos, TVector3 &dir, kalFilterTypes stateType) const {
if(getHitType() == Kalman::kWireHit) {
const HKalPlane &plane = getHit().getVirtPlane();
trackStates[kSecCoord][stateType]->calcPosAndDirAtPlane(pos, dir, plane);
} else {
const HKalPlane &plane = getHit().getMeasLayer();
trackStates[kSecCoord][stateType]->calcPosAndDirAtPlane(pos, dir, plane);
}
}
void HKalTrackSite::setEffErrMat(const TMatrixD &errMat) {
#if kalDebug > 0
if(errMat.GetNrows() != getMeasDim() || errMat.GetNcols() != getMeasDim()) {
Warning("setEffErrMat()", Form("Measurement vector is %i-dimensional. New effective error matrix is %ix%i.",
errMat.GetNrows(), errMat.GetNcols(), getMeasDim()));
} else {
effErrMat = errMat;
}
#else
effErrMat = errMat;
#endif
}
void HKalTrackSite::setEffMeasVec(const TVectorD &measVec) {
#if kalDebug > 0
if(measVec.GetNrows() != getMeasDim()) {
Warning("setEffMeasVec()", Form("New effective measurement vector is %i-dimensional, but must be %i-dimensional.",
measVec.GetNrows(), getMeasDim()));
} else {
effMeasVec = measVec;
}
#else
effMeasVec = measVec;
#endif
}