00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "GaudiKernel/ToolFactory.h"
00012
00013
00014 #include "CLHEP/Matrix/DiagMatrix.h"
00015 #include "CLHEP/Matrix/Matrix.h"
00016 #include "CLHEP/Units/PhysicalConstants.h"
00017
00018
00019 #include "Event/TrackKeys.h"
00020
00021
00022 #include "TrackKalmanFilter.h"
00023
00024 static const ToolFactory<TrackKalmanFilter> s_factory;
00025 const IToolFactory& TrackKalmanFilterFactory = s_factory;
00026
00027
00028
00029
00030 TrackKalmanFilter::TrackKalmanFilter( const std::string& type,
00031 const std::string& name,
00032 const IInterface* parent) :
00033 GaudiTool( type, name, parent)
00034 {
00035 declareInterface<ITrackFitter>( this );
00036
00037
00038 m_zPositions.push_back( 990.0*mm );
00039 m_zPositions.push_back( 2165.0*mm );
00040 m_zPositions.push_back( 9450.0*mm );
00041 m_zPositions.push_back( 11900.0*mm );
00042
00043 declareProperty( "Extrapolator" , m_extrapolatorName = "TrackFirstCleverExtrapolator" );
00044 declareProperty( "Projector" , m_projectorName = "TrackMasterProjector" );
00045 declareProperty( "ZPositions" , m_zPositions );
00046 declareProperty( "StatesAtMeasZPos" , m_statesAtMeasZPos = false );
00047 declareProperty( "StateAtBeamLine" , m_stateAtBeamLine = true );
00048 declareProperty( "NumberFitIter" , m_numFitIter = 5 );
00049 declareProperty( "Chi2Outliers" , m_chi2Outliers = 9.0 );
00050 declareProperty( "StoreTransport" , m_storeTransport = true );
00051
00052 m_state = NULL;
00053 m_nodes.clear();
00054 m_K = HepVector(5,0);
00055 }
00056
00057
00058
00059
00060 TrackKalmanFilter::~TrackKalmanFilter() {
00061 }
00062
00063
00064
00065
00066 StatusCode TrackKalmanFilter::initialize()
00067 {
00068 m_extrapolator = tool<ITrackExtrapolator>(m_extrapolatorName);
00069
00070 m_projector = tool<ITrackProjector>(m_projectorName);
00071
00072 m_debugLevel = msgLevel( MSG::DEBUG );
00073
00074 return StatusCode::SUCCESS;
00075 }
00076
00077
00078
00079
00080 StatusCode TrackKalmanFilter::failure(const std::string& comment) {
00081 info() << "TrackKalmanFilter failure: " << comment << endreq;
00082 return StatusCode::FAILURE;
00083 }
00084
00085
00086
00087
00088 StatusCode TrackKalmanFilter::iniKalman(Track & track)
00089 {
00090
00091 if (m_state != NULL) { delete m_state; m_state = 0; }
00092
00093
00094
00095
00096 m_nodes.clear();
00097 debug() << "- iniKalman: getting track measurements ..." << endreq;
00098 std::vector<Measurement*>& measures = track.measurements();
00099 debug() << "- iniKalman: getting track nodes ..." << endreq;
00100 std::vector<Node*>& nodes = track.nodes();
00101 if (nodes.size() > 0)
00102 for (std::vector<Node*>::iterator it = nodes.begin(); it != nodes.end();
00103 it++) delete *it;
00104 nodes.clear();
00105 debug() << "- iniKalman: private nodes vector cleared ..." << endreq;
00106
00107 m_nodes.reserve(measures.size());
00108 for (std::vector<Measurement*>::iterator it = measures.begin();
00109 it != measures.end(); it++) {
00110 Measurement& meas = *(*it);
00111 FitNode* node = new FitNode(meas);
00112 m_nodes.push_back(node);
00113 track.addToNodes(node);
00114 }
00115 debug() << "- iniKalman: private nodes vector rebuilt ..." << endreq;
00116
00117 if ( m_debugLevel )
00118 debug() << " track nodes size \t" << m_nodes.size() << endreq;
00119
00120 return StatusCode::SUCCESS;
00121 }
00122
00123
00124
00125
00126 StatusCode TrackKalmanFilter::fit(Track& track, const State& state)
00127 {
00128 debug() << "-> calling filter(track,state) ..." << endreq;
00129 StatusCode sc = filter(track,state);
00130 if (sc.isFailure()) return failure(" unable to filter the track");
00131
00132 debug() << "-> calling smoother(track) ..." << endreq;
00133 sc = smoother(track);
00134 if (sc.isFailure()) return failure(" unable to smooth the track");
00135
00136 return sc;
00137 }
00138
00139
00140
00141
00142 StatusCode TrackKalmanFilter::filter(Track& track, const State& state)
00143 {
00144 StatusCode sc = StatusCode::SUCCESS;
00145 sc = iniKalman(track);
00146 if (sc.isFailure()) return failure(" not able to create Nodes");
00147
00148 m_state = state.clone();
00149
00150 if ( m_debugLevel ) {
00151 debug() << " seed state at z \t " << m_state->z() << endreq
00152 << " seed state vector \t" << m_state->stateVector() << endreq
00153 << " seed state cov \t" << m_state->covariance() << endreq
00154 << " track nodes size \t" << m_nodes.size() << endreq;
00155 }
00156
00157 std::vector<FitNode*>::iterator iNode = m_nodes.begin();
00158 double z = (*iNode)->measurement().z();
00159
00160 debug() << "Z-positions of seed state/meas.begin = "
00161 << state.z() << " / " << z << endreq;
00162
00163 debug() << "- propagating the state ..." << endreq;
00164
00165 sc = m_extrapolator->propagate(*m_state,z);
00166 if (sc.isFailure())
00167 return failure(" unable to extrapolate to 1st measurement");
00168
00169
00170 unsigned int nNodes = 0;
00171 debug() << "- looping over nodes ..." << endreq;
00172 for (iNode = m_nodes.begin(); iNode != m_nodes.end(); ++iNode) {
00173 FitNode& node = *(*iNode);
00174 debug() << "-> predict(...) for node # " << nNodes << endreq;
00175 sc = predict(node,*m_state);
00176 if (sc.isFailure()) return failure(" unable to predict at node");
00177 debug() << "-> filter(...) for node # " << nNodes++ << endreq;
00178 sc = filter(node);
00179 if (sc.isFailure()) return failure(" unable to filter node ");
00180 }
00181
00182 computeChiSq(track);
00183
00184 return sc;
00185 }
00186
00187
00188
00189
00190 StatusCode TrackKalmanFilter::predict(FitNode& aNode, State& aState) {
00191
00192 Measurement& thisMeasure = aNode.measurement();
00193
00194
00195 HepVector prevStateVec = aState.stateVector();
00196 HepSymMatrix prevStateCov = aState.covariance();
00197 double z = thisMeasure.z();
00198
00199 StatusCode sc = m_extrapolator->propagate(aState,z);
00200 if (sc.isFailure())
00201 return failure(" Unable to predit state at next measurement");
00202
00203 const HepMatrix& F = m_extrapolator->transportMatrix();
00204 aNode.setTransportMatrix( F );
00205 aNode.setTransportVector( aState.stateVector() - F * prevStateVec );
00206 aNode.setNoiseMatrix( aState.covariance() - prevStateCov.similarity(F) );
00207
00208
00209 aNode.setPredictedState(aState);
00210
00211 if ( m_debugLevel ) {
00212 debug() << " predicted state at z \t" << z << endreq;
00213 debug() << " predicted state vector \t" << aState.stateVector() << endreq;
00214 debug() << " predicted state cov \t" << aState.covariance() << endreq;
00215 debug() << " transport matrix \t" << aNode.transportMatrix() << endreq;
00216 debug() << " transport vector \t" << aNode.transportVector() << endreq;
00217 debug() << " noise matrix \t" << aNode.noiseMatrix() << endreq;
00218 }
00219
00220 return StatusCode::SUCCESS;
00221 }
00222
00223
00224
00225
00226 StatusCode TrackKalmanFilter::filter(FitNode& node)
00227 {
00228
00229 Measurement& meas = node.measurement();
00230 State& state = node.state();
00231
00232 debug() << "z-position of State = " << state.z() << endreq;
00233 debug() << "z-position of Meas = " << meas.z() << endreq;
00234 debug() << "-> calling filter(state,meas) ..." << endreq;
00235 StatusCode sc = filter(state, meas);
00236 if (sc.isFailure()) return failure("Unable to filter the node!");
00237
00238 debug() << "z-position of State = " << state.z() << endreq;
00239 debug() << "z-position of Meas = " << meas.z() << endreq;
00240
00241 double tMeasureError = meas.errMeasure();
00242 debug() << "getting info from projection ..." << endreq;
00243 double res = m_projector->residual();
00244 const HepVector& H = m_projector->projectionMatrix();
00245
00246
00247 node.setProjectionMatrix( H );
00248
00249 double HK = dot ( H, m_K);
00250 res *= (1 - HK);
00251 double errorRes = (1 - HK) * (tMeasureError*tMeasureError);
00252
00253 debug() << "res/errRes = " << res << " / " << errorRes << endreq;
00254
00255 debug() << "setting info in node ..." << endreq;
00256 node.setResidual(res);
00257 node.setErrResidual(sqrt(errorRes));
00258
00259
00260 debug() << "setting filteredState" << endreq;
00261 node.setFilteredState(state);
00262 debug() << "just set filteredState" << endreq;
00263
00264 if ( m_debugLevel ) {
00265 debug() << " bef print" << endreq;
00266 debug() << " filtered residual and error \t" << node.residual() << ", "
00267 <<node.errResidual() << endreq;;
00268 debug() << " aft print" << endreq;
00269 }
00270
00271 return StatusCode::SUCCESS;
00272 }
00273
00274
00275
00276
00277
00278
00279 StatusCode TrackKalmanFilter::filter(State& state, Measurement& meas) {
00280
00281 debug() << "In filter(state,meas)" << endreq;
00282 debug() << "z-position of State = " << state.z() << endreq;
00283 debug() << "z-position of Meas = " << meas.z() << endreq;
00284
00285 if ( fabs(meas.z() - state.z()) > 1e-6) {
00286 warning() << "z-position of State (=" << state.z()
00287 << ") and Measurement (= " << meas.z()
00288 << ") are not equal." << endreq;
00289 }
00290
00291
00292 HepVector& tX = state.stateVector();
00293 HepSymMatrix& tC = state.covariance();
00294
00295 debug() << "filter(state,meas): projecting ..." << endreq;
00296
00297 StatusCode sc = m_projector->project(state,meas);
00298 if (sc.isFailure())
00299 return failure(" Not able to project a state into a measurement");
00300 debug() << "filter(state,meas): projection done" << endreq;
00301
00302
00303 double errorMeas = meas.errMeasure();
00304 double res = m_projector->residual();
00305 double errorRes = m_projector->errResidual();
00306 double errorRes2 = (errorRes*errorRes);
00307 const HepVector& H = m_projector->projectionMatrix();
00308
00309
00310 m_K = (tC * H)/errorRes2;
00311
00312
00313 tX += m_K * res;
00314
00315 HepMatrix B = HepDiagMatrix(tC.num_row(), 1) - ( m_K * H.T());
00316 tC.assign( B * tC * B.T() + ( m_K * pow(errorMeas, 2.0) * m_K.T()));
00317
00318 if ( m_debugLevel ) {
00319 debug() << " measure and error \t" << meas.measure() << ", "
00320 << errorMeas << endreq
00321 << " residual and error \t" << res << ", "
00322 << errorRes << endreq
00323 << " projection matrix \t" << H << endreq
00324 << " gain matrix \t" << m_K << endreq
00325 << " filter state vector \t" << tX << endreq
00326 << " filter state covariance \t"<< tC << endreq;
00327 }
00328
00329 return sc;
00330 }
00331
00332
00333
00334
00335
00336
00337
00338 StatusCode TrackKalmanFilter::smooth(FitNode& thisNode,
00339 const FitNode& prevNode)
00340 {
00341 debug() << "just entered smooth(node0,node1)" << endreq;
00342
00343
00344 const HepVector& prevNodeX = prevNode.predictedState().stateVector();
00345 const HepSymMatrix& prevNodeC = prevNode.predictedState().covariance();
00346
00347 debug() << "calling checkInvertMatrix ..." << endreq;
00348
00349 StatusCode sc = checkInvertMatrix(prevNodeC);
00350 if ( sc.isFailure() ) return failure(" not valid matrix in smoother");
00351
00352 debug() << "inverting matrix ..." << endreq;
00353
00354 HepSymMatrix invPrevNodeC = prevNodeC;
00355 sc = invertMatrix(invPrevNodeC);
00356 if ( sc.isFailure() ) return failure(" inverting matrix in smoother");
00357 debug() << "matrix inverted ..." << endreq;
00358
00359
00360 HepVector& thisNodeX = thisNode.state().stateVector();
00361 HepSymMatrix& thisNodeC = thisNode.state().covariance();
00362
00363
00364 const HepMatrix& F = prevNode.transportMatrix();
00365
00366 debug() << "calculation of gain matrix A ..." << endreq;
00367
00368 HepMatrix A = thisNodeC * F.T() * invPrevNodeC;
00369
00370
00371 const HepVector& prevNodeSmoothedX = prevNode.state().stateVector();
00372 const HepSymMatrix& prevNodeSmoothedC = prevNode.state().covariance();
00373
00374
00375 thisNodeX += A * (prevNodeSmoothedX - prevNodeX);
00376
00377
00378 HepSymMatrix covDiff = prevNodeSmoothedC- prevNodeC;
00379 HepSymMatrix covUpDate = covDiff.similarity(A);
00380 thisNodeC += covUpDate;
00381
00382 debug() << "calling checkPositiveMatrix ..." << endreq;
00383
00384 sc = checkPositiveMatrix(thisNodeC);
00385 if (sc.isFailure()) return Warning("non-positive Matrix in smoother");
00386 debug() << "checkPositiveMatrix done" << endreq;
00387
00388
00389 debug() << "dims of H is"
00390 << thisNode.projectionMatrix().num_row() << "x"
00391 << thisNode.projectionMatrix().num_col() << endreq;
00392 const HepVector& H = thisNode.projectionMatrix();
00393 debug() << "projecting ..." << endreq;
00394 sc = m_projector->project(thisNode.state(),thisNode.measurement());
00395 if (sc.isFailure()) Warning(" unable to project the smooth node");
00396 double res = m_projector->residual();
00397 thisNode.setResidual(res);
00398 double errRes = thisNode.errResidual();
00399 double errRes2 = errRes*errRes - covUpDate.similarity(H);
00400 debug() << "errRes2 = " << errRes2 << endreq;
00401 if (errRes2 >0.) errRes = sqrt(errRes2);
00402 else return Warning( "Negative residual error in smoother!" );
00403 thisNode.setErrResidual(sqrt(errRes));
00404
00405 if ( m_debugLevel ) {
00406 debug() << " A matrix \t" << A << endreq
00407 << " smooth state vector \t" << thisNodeX << endreq
00408 << " smooth state covariance \t"<< thisNodeC << endreq
00409 << " smooth residual, error and chi2 \t" << res << ", "
00410 << errRes << ", " << thisNode.chi2() << endreq;
00411 }
00412
00413 return StatusCode::SUCCESS;
00414 }
00415
00416
00417
00418
00419 StatusCode TrackKalmanFilter::smoother(Track& track)
00420 {
00421 StatusCode sc = StatusCode::SUCCESS;
00422
00423 std::vector<FitNode*>::reverse_iterator riNode = m_nodes.rbegin();
00424 FitNode* oldNode = *riNode;
00425 ++riNode;
00426
00427 debug() << "starting loop over nodes..." << endreq;
00428 while (riNode != m_nodes.rend()) {
00429 debug() << " call to smooth(node0,node1)..." << endreq;
00430 sc = smooth( *(*riNode), *oldNode );
00431 if ( sc.isFailure() ) return failure("Unable to smooth node!");
00432 oldNode = *riNode;
00433 ++riNode;
00434 }
00435
00436 computeChiSq(track);
00437
00438 return StatusCode::SUCCESS;
00439 }
00440
00441
00442
00443
00444 void TrackKalmanFilter::computeChiSq(Track& track)
00445 {
00446 double chi2 = 0.;
00447 for (std::vector<FitNode*>::iterator it = m_nodes.begin();
00448 it != m_nodes.end(); it++)
00449 chi2 += (*it)->chi2();
00450 int ndof = -(m_state->nParameters());
00451 ndof += m_nodes.size();
00452
00453 debug() << "NDoF = " << m_nodes.size() << "-" << m_state->nParameters()
00454 << " = " << ndof << endreq;
00455
00456 double chi2Norma = 0.;
00457 if (ndof != 0) chi2Norma = chi2 /((double) (ndof));
00458 track.setChi2PerDoF(chi2Norma);
00459 track.setNDoF(ndof);
00460
00461 if ( m_debugLevel ) {
00462 debug() << " track ndof \t" << track.nDoF() << endreq
00463 << " track chi2, chi2/ndof \t " << track.chi2() << ", "
00464 << track.chi2PerDoF() << endreq;
00465 }
00466
00467 }
00468
00469
00470
00471
00472 StatusCode TrackKalmanFilter::checkInvertMatrix(const HepSymMatrix& mat)
00473 {
00474 int nParam = (int) mat.num_row();
00475 for (int i=0; i<nParam; ++i){
00476 for (int j=0; j<nParam; ++j){
00477 if (mat[i][j] > 1e20)
00478 return Warning( "Covariance errors too big to invert!");
00479 }
00480 }
00481 return StatusCode::SUCCESS;
00482 }
00483
00484
00485
00486
00487 StatusCode TrackKalmanFilter::checkPositiveMatrix(HepSymMatrix& mat)
00488 {
00489 int nParam = (int) mat.num_row();
00490 for (int i=0; i<nParam; ++i){
00491 if (mat[i][i] <= 0.)
00492 return Warning( "Covariance matrix has non-positive elements!" );
00493 }
00494
00495 return StatusCode::SUCCESS;
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 StatusCode TrackKalmanFilter::invertMatrix(HepSymMatrix& invPrevNodeC){
00509
00510 StatusCode sc = StatusCode::SUCCESS;
00511
00512
00513 cToG3(invPrevNodeC);
00514
00515 HepSymMatrix tempMatrix = invPrevNodeC;
00516
00517 int ifail;
00518 invPrevNodeC.invert(ifail);
00519
00520
00521 cToG4(invPrevNodeC);
00522
00523 if (ifail !=0){
00524 warning()
00525 <<"failed to invert covariance matrix, failure code " <<ifail<<endreq;
00526 sc = StatusCode::FAILURE;
00527 }
00528 return sc;
00529 }
00530
00531
00532
00533
00534 StatusCode TrackKalmanFilter::cToG3(HepSymMatrix& C){
00535
00536
00537 C[0][0] /= cm2;
00538 C[0][1] /= cm2;
00539 C[0][2] /= cm;
00540 C[0][3] /= cm;
00541 C[0][4] = C[0][4]*GeV/cm;
00542
00543 C[1][1] /= cm2;
00544 C[1][2] /= cm;
00545 C[1][3] /= cm;
00546 C[1][4] = C[1][4]*GeV/cm;
00547
00548 C[2][4] = C[2][4]*GeV;
00549
00550 C[3][4] = C[3][4]*GeV;
00551
00552 C[4][4] = C[4][4]*GeV*GeV;
00553
00554 return StatusCode::SUCCESS;
00555
00556 }
00557
00558
00559
00560
00561 StatusCode TrackKalmanFilter::cToG4(HepSymMatrix& invC){
00562
00563
00564 invC[0][0] /= cm2;
00565 invC[0][1] /= cm2;
00566 invC[0][2] /= cm;
00567 invC[0][3] /= cm;
00568 invC[0][4] = invC[0][4]*GeV/cm;
00569
00570 invC[1][1] /= cm2;
00571 invC[1][2] /= cm;
00572 invC[1][3] /= cm;
00573 invC[1][4] = invC[1][4]*GeV/cm;
00574
00575 invC[2][4] = invC[2][4]*GeV;
00576
00577 invC[3][4] = invC[3][4]*GeV;
00578
00579 invC[4][4] = invC[4][4]*GeV*GeV;
00580
00581 return StatusCode::SUCCESS;
00582 }
00583
00584