00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "GaudiKernel/ToolFactory.h"
00012
00013
00014 #include "KalmanFilter.h"
00015
00016
00017 #include "CLHEP/Matrix/DiagMatrix.h"
00018 #include "CLHEP/Matrix/Matrix.h"
00019 #include "CLHEP/Units/PhysicalConstants.h"
00020
00021 static const ToolFactory<KalmanFilter> s_factory;
00022 const IToolFactory& KalmanFilterFactory = s_factory;
00023
00024 KalmanFilter::KalmanFilter( const std::string& type,
00025 const std::string& name,
00026 const IInterface* parent) :
00027 GaudiTool( type, name, parent)
00028 {
00029 declareInterface<ITrackFitter>( this );
00030
00031 declareProperty("Extrapolator",m_extrapolatorName = "MasterExtrapolator");
00032
00033 declareProperty("Projector",m_projectorName = "MasterProjector");
00034
00035 m_state = NULL;
00036 m_nodes.clear();
00037 m_K = HepVector(5,0);
00038 }
00039
00040 KalmanFilter::~KalmanFilter() {
00041 }
00042
00043 StatusCode KalmanFilter::initialize()
00044 {
00045 m_extrapolator = get<ITrackExtrapolator>(m_extrapolatorName);
00046
00047 m_projector = get<ITrackProjector>(m_projectorName);
00048
00049 return StatusCode::SUCCESS;
00050 }
00051
00052 StatusCode KalmanFilter::failure(const std::string& comment){
00053 info() << " Kalman Filter failure: " << comment << endreq;
00054 return StatusCode::FAILURE;
00055 }
00056
00057
00058
00059
00060
00061 StatusCode KalmanFilter::fit(Track& track, const State& state)
00062 {
00063 StatusCode sc = filter(track,state);
00064 if (sc.isFailure()) return failure(" No able to filter the track");
00065
00066 return sc = smoother(track);
00067 if (sc.isFailure()) return failure(" No able to smooth the track");
00068
00069 return sc;
00070 }
00071
00072 StatusCode KalmanFilter::iniKalman(Track & track)
00073 {
00074
00075 if (m_state != NULL) delete m_state;
00076
00077
00078
00079 m_nodes.clear();
00080 std::vector<Measurement*>& measures = track.measurements();
00081 std::vector<Node*>& nodes = track.nodes();
00082 if (nodes.size() > 0)
00083 for (std::vector<Node*>::iterator it = nodes.begin(); it != nodes.end();
00084 it++) delete *it;
00085 nodes.clear();
00086 for (std::vector<Measurement*>::iterator it = measures.begin();
00087 it != measures.end(); it++) {
00088 Measurement& meas = *(*it);
00089 FitNode* node = new FitNode(meas);
00090 m_nodes.push_back(node);
00091 track.addToNodes(node);
00092 }
00093
00094 if (msgLevel(MSG::DEBUG)) {
00095 debug() << " seed state vector \t" << m_state->stateVector() << endreq;
00096 debug() << " seed state cov \t" << m_state->covariance() << endreq;
00097 debug() << " track nodes size \t" << m_nodes.size() << endreq;
00098 }
00099
00100 return StatusCode::SUCCESS;
00101 }
00102
00103 StatusCode KalmanFilter::filter(Track& track, const State& state)
00104 {
00105 StatusCode sc = StatusCode::SUCCESS;
00106 sc = iniKalman(track);
00107 if (sc.isFailure()) return failure(" Not able to create Nodes");
00108
00109 m_state = state.clone();
00110
00111 std::vector<FitNode*>::iterator iNode = m_nodes.begin();
00112 double z = (*iNode)->measurement().z();
00113
00114 sc = m_extrapolator->propagate(*m_state,z);
00115 if (sc.isFailure())
00116 return failure(" Not able to extrapolate to 1st measurement");
00117
00118
00119 for (iNode = m_nodes.begin(); iNode != m_nodes.end(); ++iNode) {
00120 FitNode& node = *(*iNode);
00121 sc = predict(node,*m_state);
00122 if (sc.isFailure()) return failure(" not able to predict at node");
00123 sc = filter(node);
00124 if (sc.isFailure()) return failure(" not able to filter node ");
00125 }
00126
00127 computeChiSq(track);
00128 return sc;
00129 }
00130
00131 StatusCode KalmanFilter::smoother(Track& track)
00132 {
00133 StatusCode sc = StatusCode::SUCCESS;
00134
00135 std::vector<FitNode*>::reverse_iterator riNode = m_nodes.rbegin();
00136 FitNode* oldNode = *riNode;
00137 ++riNode;
00138
00139 while (riNode != m_nodes.rend()) {
00140 sc = smooth( *(*riNode), *oldNode );
00141 if (sc.isFailure()) return failure(" not able to smooth node");
00142 oldNode = *riNode;
00143 ++riNode;
00144 }
00145
00146 computeChiSq(track);
00147
00148 return StatusCode::SUCCESS;
00149 }
00150
00151 void KalmanFilter::computeChiSq(Track& track)
00152 {
00153 double chi2 = 0.;
00154 for (std::vector<FitNode*>::iterator it = m_nodes.begin();
00155 it != m_nodes.end(); it++)
00156 chi2 += (*it)->chi2();
00157 int ndof = -(m_state->nParameters());
00158 ndof += m_nodes.size();
00159 double chi2Norma = 0.;
00160 if (ndof != 0) chi2Norma = chi2 /((float) (ndof));
00161 track.setChi2PerDoF(chi2Norma);
00162 track.setNDoF(ndof);
00163
00164 if (msgLevel(MSG::DEBUG)) {
00165 debug() << " track ndof \t" << track.chi2() << endreq;
00166 debug() << " track chi2, chi2/ndof \t " << track.chi2() << ", "
00167 << track.chi2PerDoF() << endreq;
00168 }
00169
00170 }
00171
00172
00173
00174
00175 StatusCode KalmanFilter::predict(FitNode& aNode, State& aState) {
00176
00177 Measurement& thisMeasure = aNode.measurement();
00178
00179
00180 HepVector prevStateVec = aState.stateVector();
00181 HepSymMatrix prevStateCov = aState.covariance();
00182 double z = thisMeasure.z();
00183
00184 StatusCode sc = m_extrapolator->propagate(aState,z);
00185 if (sc.isFailure())
00186 return failure(" No able to predit state at next measurement");
00187
00188 const HepMatrix& F = m_extrapolator->transportMatrix();
00189 aNode.setTransportMatrix( F );
00190 aNode.setTransportVector( aState.stateVector() - F * prevStateVec );
00191 aNode.setNoiseMatrix( aState.covariance() - prevStateCov.similarity(F) );
00192
00193
00194 aNode.setPredictedState(aState);
00195
00196 if (msgLevel(MSG::DEBUG)) {
00197 debug() << " predicted state at z \t" << z << endreq;
00198 debug() << " predicted state vector \t" << aState.stateVector() << endreq;
00199 debug() << " predicted state cov \t" << aState.covariance() << endreq;
00200 debug() << " transport matrix \t" << aNode.transportMatrix() << endreq;
00201 debug() << " transport vector \t" << aNode.transportVector() << endreq;
00202 debug() << " noise matrix \t" << aNode.noiseMatrix() << endreq;
00203 }
00204
00205 return StatusCode::SUCCESS;
00206 }
00207
00208 StatusCode KalmanFilter::filter(FitNode& node)
00209 {
00210
00211 Measurement& meas = node.measurement();
00212 State& state = node.state();
00213
00214 StatusCode sc = filter(state, meas);
00215 if (sc.isFailure()) return failure("Not able to filter the node!");
00216
00217 double tMeasureError = meas.errMeasure();
00218 double res = m_projector->residual();
00219 const HepVector& H = m_projector->projectionMatrix();
00220
00221 double HK = dot ( H, m_K);
00222 res *= (1 - HK);
00223 double errorRes = (1 - HK) * pow(tMeasureError, 2.0);
00224
00225 node.setResidual(res);
00226 node.setErrResidual(sqrt(errorRes));
00227
00228
00229 node.setFilteredState(state);
00230
00231 if (msgLevel(MSG::DEBUG)) {
00232 debug() << " filtered residual and error \t" << node.residual() << ", "
00233 <<node.errResidual() << endreq;;
00234 }
00235
00236 return StatusCode::SUCCESS;
00237 }
00238
00239
00240
00241
00242
00243
00244 StatusCode KalmanFilter::filter(State& state, Measurement& meas) {
00245
00246
00247 if ( fabs(meas.z() - state.z()) > 1e-6) {
00248 warning() << "z position of TrState (=" << state.z()
00249 << ") and TrStateMeasurement (= " << meas.z()
00250 << ") are not equal." << endreq;
00251 }
00252
00253
00254 HepVector& tX = state.stateVector();
00255 HepSymMatrix& tC = state.covariance();
00256
00257
00258 StatusCode sc = m_projector->project(state,meas);
00259 if (sc.isFailure())
00260 return failure(" Not able to project a state into a measurement");
00261
00262
00263 double errorMeas = meas.errMeasure();
00264 double res = m_projector->residual();
00265 double errorRes = m_projector->errResidual();
00266 double errorRes2 = (errorRes*errorRes);
00267 const HepVector& H = m_projector->projectionMatrix();
00268
00269
00270 m_K = (tC * H)/errorRes2;
00271
00272
00273 tX += m_K * res;
00274
00275 HepMatrix B = HepDiagMatrix(tC.num_row(), 1) - ( m_K * H.T());
00276 tC.assign( B * tC * B.T() + ( m_K * pow(errorMeas, 2.0) * m_K.T()));
00277
00278 if (msgLevel(MSG::DEBUG)) {
00279 debug() << " measure and error \t" << meas.measure() << ", "
00280 << errorMeas << endreq;
00281 debug() << " residual and error \t" << res << ", "
00282 << errorRes << endreq;
00283 debug() << " projection matrix \t" << H << endreq;
00284 debug() << " gain matrix \t" << m_K << endreq;
00285 debug() << " filter state vector \t" << tX << endreq;
00286 debug() << " filter state covariance \t"<< tC << endreq;
00287 }
00288
00289 return sc;
00290 }
00291
00292
00293
00294
00295
00296
00297
00298 StatusCode KalmanFilter::smooth(FitNode& thisNode, FitNode& prevNode){
00299
00300
00301
00302 HepVector& prevNodeX = prevNode.predictedState().stateVector();
00303 HepSymMatrix& prevNodeC = prevNode.predictedState().covariance();
00304
00305
00306 StatusCode sc = checkInvertMatrix(prevNodeC);;
00307 if ( sc.isFailure() ) return failure(" not valid matrix in smoother");
00308
00309
00310 HepSymMatrix invPrevNodeC = prevNodeC;
00311 sc = invertMatrix(invPrevNodeC);
00312 if ( sc.isFailure() ) return failure(" inverting matrix in smoother");
00313
00314
00315 HepVector& thisNodeX = thisNode.state().stateVector();
00316 HepSymMatrix& thisNodeC = thisNode.state().covariance();
00317
00318
00319 const HepMatrix& F = prevNode.transportMatrix();
00320
00321
00322 HepMatrix A = thisNodeC * F.T() * invPrevNodeC;
00323
00324
00325 HepVector& prevNodeSmoothedX = prevNode.state().stateVector();
00326 HepSymMatrix& prevNodeSmoothedC = prevNode.state().covariance();
00327
00328
00329 thisNodeX += A * (prevNodeSmoothedX - prevNodeX);
00330
00331
00332 HepSymMatrix covDiff = prevNodeSmoothedC- prevNodeC;
00333 HepSymMatrix covUpDate = covDiff.similarity(A);
00334 thisNodeC += covUpDate;
00335
00336
00337 sc = checkPositiveMatrix(thisNodeC);
00338 if (sc.isFailure()) return Warning(" not postive Matrix in smoother");
00339
00340
00341 const HepVector& H = thisNode.projectionMatrix();
00342 sc = m_projector->project(thisNode.state(),thisNode.measurement());
00343 if (sc.isFailure()) Warning(" unable to project the smooth node");
00344 double res = m_projector->residual();
00345 thisNode.setResidual(res);
00346 double errRes = thisNode.errResidual();
00347 double errRes2 = errRes*errRes - covUpDate.similarity(H);
00348 if (errRes2 >0.) errRes = sqrt(errRes2);
00349 else return Warning(" negative error residuals in smoother");
00350 thisNode.setErrResidual(sqrt(errRes));
00351
00352 if (msgLevel(MSG::DEBUG)) {
00353 debug() << " A matrix \t" << A << endreq;;
00354 debug() << " smooth state vector \t" << thisNodeX << endreq;
00355 debug() << " smooth state covariance \t"<< thisNodeC << endreq;
00356 debug() << " smooth residual, error and chi2 \t" << res << ", "
00357 << errRes << ", " << thisNode.chi2() << endreq;
00358 }
00359
00360 return StatusCode::SUCCESS;
00361 }
00362
00363 StatusCode KalmanFilter::checkInvertMatrix(HepSymMatrix& mat)
00364 {
00365 int nParam = (int) mat.num_row();
00366 for (int i=0; i<nParam; ++i){
00367 for (int j=0; j<nParam; ++j){
00368 if (mat[i][j] > 1e20)
00369 return Warning("covariance errors too big to invert");
00370 }
00371 }
00372 return StatusCode::SUCCESS;
00373 }
00374
00375 StatusCode KalmanFilter::checkPositiveMatrix(HepSymMatrix& mat)
00376 {
00377 int nParam = (int) mat.num_row();
00378 for (int i=0; i<nParam; ++i){
00379 if (mat[i][i] <= 0.)
00380 return Warning("covariance errors too big to convert");
00381 }
00382
00383
00384 return StatusCode::SUCCESS;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 StatusCode KalmanFilter::invertMatrix(HepSymMatrix& invPrevNodeC){
00398
00399 StatusCode sc = StatusCode::SUCCESS;
00400
00401
00402 cToG3(invPrevNodeC);
00403
00404 HepSymMatrix tempMatrix = invPrevNodeC;
00405
00406 int ifail;
00407 invPrevNodeC.invert(ifail);
00408
00409
00410 cToG4(invPrevNodeC);
00411
00412 if (ifail !=0){
00413 warning()
00414 <<"failed to invert covariance matrix, failure code " <<ifail<<endreq;
00415 sc = StatusCode::FAILURE;
00416 }
00417 return sc;
00418 }
00419
00420
00421
00422
00423 StatusCode KalmanFilter::cToG3(HepSymMatrix& C){
00424
00425
00426 C[0][0] /= cm2;
00427 C[0][1] /= cm2;
00428 C[0][2] /= cm;
00429 C[0][3] /= cm;
00430 C[0][4] = C[0][4]*GeV/cm;
00431
00432 C[1][1] /= cm2;
00433 C[1][2] /= cm;
00434 C[1][3] /= cm;
00435 C[1][4] = C[1][4]*GeV/cm;
00436
00437 C[2][4] = C[2][4]*GeV;
00438
00439 C[3][4] = C[3][4]*GeV;
00440
00441 C[4][4] = C[4][4]*GeV*GeV;
00442
00443 return StatusCode::SUCCESS;
00444
00445 }
00446
00447
00448
00449
00450 StatusCode KalmanFilter::cToG4(HepSymMatrix& invC){
00451
00452
00453 invC[0][0] /= cm2;
00454 invC[0][1] /= cm2;
00455 invC[0][2] /= cm;
00456 invC[0][3] /= cm;
00457 invC[0][4] = invC[0][4]*GeV/cm;
00458
00459 invC[1][1] /= cm2;
00460 invC[1][2] /= cm;
00461 invC[1][3] /= cm;
00462 invC[1][4] = invC[1][4]*GeV/cm;
00463
00464 invC[2][4] = invC[2][4]*GeV;
00465
00466 invC[3][4] = invC[3][4]*GeV;
00467
00468 invC[4][4] = invC[4][4]*GeV*GeV;
00469
00470 return StatusCode::SUCCESS;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483