00001
#include <stdio.h>
00002
#include <stdlib.h>
00003
#include "StiUtilities/StiDebug.h"
00004
#include "StiTrackNodeHelper.h"
00005
#include "StiElossCalculator.h"
00006
#include "StiHitErrorCalculator.h"
00007
#include "StMessMgr.h"
00008
#include "TArrayD.h"
00009
#if ROOT_VERSION_CODE < 331013
00010
#include "TCL.h"
00011
#else
00012
#include "TCernLib.h"
00013
#endif
00014
00015
#define NICE(a) ( ((a) <= -M_PI)? ((a)+2*M_PI) :\
00016
((a) > M_PI)? ((a)-2*M_PI) : (a))
00017
00018
#define sinX(a) StiTrackNode::sinX(a)
00019
static const double kMaxEta = 1.5;
00020
static const double kMaxCur = 0.2;
00021
00022
static const double DY=0.9,DZ=0.9,DEta=0.1,DPti=3,DTan=0.1;
00023
static const double MAXSTEP[]={0,DY,DZ,DEta,DPti,DTan};
00024
static const double ERROR_FACTOR = 2.;
00025
int StiTrackNodeHelper::_debug = 0;
00026
int StiTrackNodeHelper::mgCutStep=0;
00027
00028
int errTest(StiNodePars &predP,StiNodeErrs &predE,
00029
const StiHit *hit,StiHitErrs &hitErr,
00030 StiNodePars &fitdP,StiNodeErrs &fitdE,
double chi2);
00031
00032
00033
void StiTrackNodeHelper::set(
double chi2Max,
double chi2Vtx,
double errConfidence,
int iter)
00034 {
00035 reset();
00036 mChi2Max = chi2Max;
00037 mChi2Vtx = chi2Vtx;
00038 mNodeErrFactor = 10;
00039 mHitsErrFactor = 1.;
00040
if (errConfidence>0.1) {
00041 mNodeErrFactor = (1./(errConfidence));
00042 mHitsErrFactor = (1./(1. - errConfidence));
00043 }
00044 mIter = iter;
00045
if (!mIter) mFlipFlopNode = 0;
00046 }
00047
00048
void StiTrackNodeHelper::reset()
00049 {
00050 memset(mBeg,
'A',mEnd-mBeg+1);
00051 mWorstNode =0;
00052 mVertexNode=0;
00053 mUsed = 0;
00054 mCurvQa.reset();
00055 mTanlQa.reset();
00056 }
00057
00058
00059
void StiTrackNodeHelper::set(
StiKalmanTrackNode *pNode,
StiKalmanTrackNode *sNode)
00060 {
00061
if(!pNode) reset();
00062 mParentNode = pNode;
00063 mTargetNode = sNode;
00064 mTargetHz = mTargetNode->
getHz();
00065 mParentHz = mTargetHz;
00066
if (mParentNode) {
00067 mParentHz = mParentNode->getHz();
00068 assert(fabs(mParentHz-mParentNode->mFP._hz)<1e-10);
00069 mParentNode->mFP.check(
"2StiTrackNodeHelper::set");
00070 }
00071
if (mTargetNode->isValid()) {
00072 mTargetNode->mFP.check(
"1StiTrackNodeHelper::set");
00073 assert(fabs(mTargetHz-mTargetNode->mFP._hz)<1e-10);
00074 }
00075
00076 mDetector = mTargetNode->getDetector();
00077
if (!mDetector) mVertexNode = mTargetNode;
00078 mHit = mTargetNode->getHit();
00079
if (mHit) {
00080
double time = 0;
00081
if (mHit->vy() || mHit->vz()) time = mTargetNode->getTime();
00082 mHitPars[0]=mHit->x();
00083 mHitPars[1]=mHit->y(time);
00084 mHitPars[2]=mHit->z(time);
00085 }
00086
00087
if (!mIter) mTargetNode->mFlipFlop=0;
00088 }
00089
00090
int StiTrackNodeHelper::propagatePars(
const StiNodePars &parPars
00091 , StiNodePars &rotPars
00092 , StiNodePars &proPars)
00093 {
00094
int ierr = 0;
00095 alpha = mTargetNode->_alpha - mParentNode->_alpha;
00096 ca=1;sa=0;
00097 parPars.check(
"1propagatePars");
00098 rotPars = parPars;
00099
if (fabs(alpha) > 1.e-6) {
00100
00101
double xt1=parPars._x;
00102
double yt1=parPars._y;
00103
double cosCA0 = parPars._cosCA;
00104
double sinCA0 = parPars._sinCA;
00105
00106 ca = cos(alpha);
00107 sa = sin(alpha);
00108
00109 rotPars._x = xt1*ca + yt1*sa;
00110 rotPars._y= -xt1*sa + yt1*ca;
00111 rotPars._cosCA = cosCA0*ca+sinCA0*sa;
00112 rotPars._sinCA = -cosCA0*sa+sinCA0*ca;
00113
double nor = 0.5*(rotPars._sinCA*rotPars._sinCA+rotPars._cosCA*rotPars._cosCA +1);
00114 rotPars._cosCA /= nor;
00115 rotPars._sinCA /= nor;
00116 rotPars._eta= NICE(parPars._eta-alpha);
00117 }
00118 ierr = rotPars.check();
00119
if (ierr)
return 1;
00120
00121
00122 x1 = rotPars._x;
00123 x2 = (mDetector)? mDetector->getPlacement()->getNormalRadius():mHitPars[0];
00124 dx = x2-x1;
00125 rho = 0.5*(mTargetHz*rotPars._ptin+rotPars._curv);
00126 dsin = rho*dx;
00127 sinCA2=rotPars._sinCA + dsin;
00128
if (sinCA2> 0.95) sinCA2= 0.95;
00129
if (sinCA2<-0.95) sinCA2=-0.95;
00130 cosCA2 = ::sqrt((1.-sinCA2)*(1.+sinCA2));
00131 sumSin = rotPars._sinCA+sinCA2;
00132 sumCos = rotPars._cosCA+cosCA2;
00133 dy = dx*(sumSin/sumCos);
00134 y2 = rotPars._y+dy;
00135 dl0 = rotPars._cosCA*dx+rotPars._sinCA*dy;
00136 sind = dl0*rho;
00137
if (fabs(dsin) < 0.02 && rotPars._cosCA >0) {
00138 dl = dl0*(1.+sind*sind/6);
00139 }
else {
00140
double cosd = cosCA2*rotPars._cosCA+sinCA2*rotPars._sinCA;
00141 dl = atan2(sind,cosd)/rho;
00142 }
00143
00144 proPars._x = x2;
00145 proPars._y = y2;
00146 proPars._z= rotPars._z + dl*rotPars._tanl;
00147 proPars._eta = (rotPars._eta+rho*dl);
00148 proPars._eta = NICE(proPars._eta);
00149 proPars._ptin = rotPars._ptin;
00150 proPars._hz = mTargetHz;
00151 proPars._curv = proPars._ptin*mTargetHz;
00152 proPars._tanl = rotPars._tanl;
00153 proPars._sinCA = sinCA2;
00154 proPars._cosCA = cosCA2;
00155 ierr = proPars.check();
00156
if (ierr)
return 2;
00157
return 0;
00158 }
00159
00160
int StiTrackNodeHelper::propagateFitd()
00161 {
00162
00163
00164
00165
int ierr = 0;
00166 mBestPars._ptin *= (1+mMcs._ptinCorr);
00167 mBestPars._curv *= (1+mMcs._ptinCorr);
00168 mMtx.A[4][4] = (mMtx.A[4][4]+1)*(1+mMcs._ptinCorr) -1;
00169
00170 StiNodePars rotPars;
00171 ierr = propagatePars(mFitdParentPars,rotPars,mPredPars);
00172
if (ierr)
return 1;
00173
00174 mPredPars._hz = mTargetHz;
00175 mPredPars._ptin *= (1+mMcs._ptinCorr);
00176 mPredPars._curv *= (1+mMcs._ptinCorr);
00177 mPredPars.ready();
00178 ierr = mPredPars.check();
00179
if (ierr)
return 2;
00180
return 0;
00181 }
00182
00183
00184
00185
00186
int StiTrackNodeHelper::propagateMtx()
00187 {
00188
00189
double fYE= dx*(1.+mBestParentRotPars._cosCA*cosCA2+mBestParentRotPars._sinCA*sinCA2)/(sumCos*cosCA2);
00190
00191
double dLdEta = dy/cosCA2;
00192
double fZE = mBestPars._tanl*dLdEta;
00193
00194
double fZT= dl;
00195
00196
00197
00198
double fEC = dx/cosCA2;
00199
00200
double fYC=(dl0)/sumCos*fEC;
00201
00202
double dang = dl*rho;
00203
double C2LDX = dl*dl*(
00204 0.5*sinCA2*pow((1+pow(dang/2,2)*sinX(dang/2)),2) +
00205 cosCA2*dang*sinX(dang));
00206
00207
double fZC = mBestPars._tanl*C2LDX/cosCA2;
00208
00209 fEC*=mTargetHz; fYC*=mTargetHz;fZC*=mTargetHz;
00210
00211
00212 mMtx.reset();
00213
00214 mMtx.A[0][0] = -1;
00215 mMtx.A[1][0] = -sinCA2/cosCA2;
00216 mMtx.A[2][0] = -mBestPars._tanl/cosCA2 ;
00217 mMtx.A[3][0] = -mBestPars._curv/cosCA2 ; ;
00218
00219 mMtx.A[1][3]=fYE; mMtx.A[1][4]=fYC; mMtx.A[2][3]=fZE;
00220 mMtx.A[2][4]=fZC; mMtx.A[2][5]=fZT; mMtx.A[3][4]=fEC;
00221
double fYX = mMtx.A[1][0];
00222 mMtx.A[1][0] = fYX*ca-sa;
00223 mMtx.A[1][1] = fYX*sa+ca-1;
00224
return 0;
00225 }
00226
00227
int StiTrackNodeHelper::propagateError()
00228 {
00229 mPredErrs = mFitdParentErrs;
00230 StiTrackNode::errPropag6(mPredErrs.A,mMtx.A,kNPars);
00231 mPredErrs.recov();
00232 mPredErrs._cEE+=mMcs._cEE;
00233 mPredErrs._cPP+=mMcs._cPP;
00234 mPredErrs._cTP+=mMcs._cTP;
00235 mPredErrs._cTT+=mMcs._cTT;
00236
int ierr = mPredErrs.check();
00237
if (ierr)
return 1;
00238
return 0;
00239 }
00240
00241
00242
int StiTrackNodeHelper::makeFit(
int smooth)
00243 {
00244
static int nCall=0;
00245 nCall++;
00246 StiDebug::Break(nCall);
00247
int ierr=0;
00248 mState = 0;
00249 mChi2 = 1e13;
00250
if (mParentNode) {
00251
00252
00253
00254
if (smooth) {
00255 mBestParentPars = mJoinPars;
00256 mBestParentErrs = mJoinErrs;
00257 mBestDelta = mJoinErrs.getDelta();
00258 }
else {
00259
double delta = mFitdErrs.getDelta();
00260
double er1 = delta*delta;
00261
double er2 = mSavdDelta*mSavdDelta;
00262
double wt = er1/(er1+er2);
00263 mBestParentPars = mFitdPars;
00264 mBestParentPars.merge(wt,mSavdParentPars);
00265 mBestDelta = sqrt(er1*er2/(er1+er2));
00266
00267 }
00268 mBestParentPars.check(
"1makeFit");
00269 mFitdParentPars = mFitdPars;
00270 mFitdParentErrs = mFitdErrs;
00271 mFitdParentPars.check(
"2makeFit");
00272 mFitdParentErrs.check(
"3makeFit");
00273
00274 ierr = propagatePars(mBestParentPars,mBestParentRotPars,mBestPars);
00275
if(ierr)
return 1;
00276 ierr = propagateMtx();
if(ierr)
return 2;
00277 ierr = propagateMCS();
if(ierr)
return 3;
00278 ierr = propagateFitd();
if(ierr)
return 4;
00279 ierr = propagateError();
if(ierr)
return 5;
00280
00281 }
00282 mState = StiTrackNode::kTNReady;
00283
00284
00285
00286 mSavdParentPars = mTargetNode->mFP;
00287 mSavdDelta = (mTargetNode->isValid())? mTargetNode->mFE.getDelta():3e33;
00288
00289
if (!mParentNode) {
00290
if (!smooth) mgCutStep = 0;
00291 mPredErrs = mTargetNode->mFE;
00292 ierr = mPredErrs.check();
if (ierr)
return 11;
00293 mPredPars = mTargetNode->mFP;
00294 ierr = mPredPars.check();
if (ierr)
return 12;
00295 mBestPars = mPredPars;
00296 mBestDelta = mPredErrs.getDelta();
00297 mJoinPars = mPredPars;
00298 resetError(mNodeErrFactor);
00299 }
00300
00301 mFitdPars = mPredPars;
00302 mFitdErrs = mPredErrs;
00303
00304
int ians = 1;
00305 mChi2 =0;
00306
do {
00307
if (!mHit)
break;
00308 setHitErrs();
00309
if (nudge())
return 13;
00310 mChi2 = 3e33;
00311
double chi2 = evalChi2();
00312
if (mTargetNode == mVertexNode) {
00313
if (chi2>mChi2Vtx)
return 14;
00314 }
else {
00315
if (chi2>mChi2Max)
break;
00316 }
00317 mChi2 = chi2;
if (mChi2>999) mChi2=999;
00318 ians = updateNode();
00319
if (!ians)
break;
00320
if (debug() & 8) {cout << Form(
"%5d ",ians); StiKalmanTrackNode::PrintStep();}
00321
if (mTargetNode == mVertexNode)
return 15;
00322 mState = StiTrackNode::kTNReady;
00323 mFitdPars = mPredPars;
00324 mFitdErrs = mPredErrs;
00325 mChi2 = 3e33;
00326 }
while(0);
00327
00328 ierr = (!smooth)? save():join();
00329
if (ierr)
return 16;
00330
00331
00332
do {
00333
if (!smooth)
break;
00334
if (!mHit)
break;
00335
if (mDetector && (!mFlipFlopNode || mTargetNode->mFlipFlop > mFlipFlopNode->mFlipFlop))
00336 {mFlipFlopNode=mTargetNode;}
00337
if(mState!=StiTrackNode::kTNFitEnd)
break;
00338 mUsed++;
00339
if (mDetector && (!mWorstNode || mChi2>mWorstNode->getChi2()))
00340 {mWorstNode=mTargetNode;}
00341
if (!mParentNode)
break;
00342
double accu,errr;
00343 accu = mJoinPars._ptin - mBestParentPars._ptin*(1+mMcs._ptinCorr);
00344 errr = sqrt(0.5*(fabs(mJoinErrs._cPP)+fabs(mBestParentErrs._cPP)));
00345 mCurvQa.add(accu/errr);
00346 accu = mJoinPars._tanl - mBestParentPars._tanl;
00347 errr = sqrt(0.5*(fabs(mJoinErrs._cTT)+fabs(mBestParentErrs._cTT)));
00348 mTanlQa.add(accu/errr);
00349 }
while(0);
00350
00351
return 0;
00352 }
00353
00354
00355
int StiTrackNodeHelper::join()
00356 {
00357
enum {kOLdValid=1,kNewFitd=2,kJoiUnFit=4};
00358
00359
00360
00361
int ierr = 0;
00362
double chi2;
00363
00364 StiDebug::Break(mTargetNode->mId);
00365
int kase = mTargetNode->isValid();
00366
if (mState==StiTrackNode::kTNFitEnd) kase |=kNewFitd;
00367
static int oldJoinPrim = StiDebug::iFlag(
"StiOldJoinPrim");
00368
if (!oldJoinPrim) {
00369
if (mTargetNode==mVertexNode) kase = kNewFitd;
00370
00371
00372 }
00373
do {
00374
switch(kase) {
00375
case 0:
00376 mChi2 = (mHit)? 3e33:0;
00377 mState = StiTrackNode::kTNReady;
00378
00379
case kNewFitd:
00380 mJoinPars = mFitdPars;
00381 mJoinErrs = mFitdErrs;
00382 kase = -1;
break;
00383
00384
case kOLdValid|kNewFitd|kJoiUnFit:
00385 mChi2 = 3e33;
00386 mFitdPars = mPredPars;
00387 mFitdErrs = mPredErrs;
00388 mState = StiTrackNode::kTNReady;
00389
00390
case kOLdValid:;
00391
case kOLdValid|kNewFitd:;
00392
00393 chi2 = joinTwo(kNPars,mTargetNode->mPP().P,mTargetNode->mPE().A
00394 ,kNPars,mFitdPars.P ,mFitdErrs.A
00395 ,mJoinPars.P ,mJoinErrs.A);
00396 mJoinPars._hz = mTargetHz;
00397 mJoinErrs.recov();
00398
00399
00400
if (kase == (kOLdValid|kNewFitd)) {
00401 assert(mHrr.hYY > mJoinErrs._cYY);
00402 assert(mHrr.hZZ > mJoinErrs._cZZ);
00403
if (mHrr.hYY <= mJoinErrs._cYY) {
00404 LOG_DEBUG << Form(
"StiTrackNodeHelper::updateNode() WRONG hYY(%g) < nYY(%g)"
00405 ,mHrr.hYY,mFitdErrs._cYY)<< endm;
00406
return -13;
00407 }
00408
if (mHrr.hZZ <= mJoinErrs._cZZ) {
00409 LOG_DEBUG << Form(
"StiTrackNodeHelper::updateNode() WRONG hZZ(%g) < nZZ(%g)"
00410 ,mHrr.hZZ,mFitdErrs._cZZ) << endm;
00411
return -14;
00412 }
00413 }
00414 mJoinPars.ready();
00415 ierr = mJoinPars.check();
if (ierr)
return 2;
00416
if (kase!=(kOLdValid|kNewFitd)) {kase = -1;
break;}
00417
00418 mChi2 = 3e33;
00419
00420 chi2 = recvChi2();
00421 mChi2 = 3e33;
00422
if (chi2>mChi2Max && mTargetNode!=mVertexNode)
00423 { kase |=kJoiUnFit;
break;}
00424 mChi2 = (chi2>999)? 999:chi2;
00425 mState = StiTrackNode::kTNFitEnd;
00426 kase = -1;
break;
00427
00428
default: assert(0);
00429 }
00430 }
while(kase>=0);
00431
00432 assert(fabs(mJoinPars._hz-mTargetHz)<=1e-10);
00433 assert(fabs(mTargetNode->getHz()-mTargetHz)<=1e-10);
00434
00435
00436 mTargetNode->mFE = mJoinErrs;
00437 mTargetNode->mPE() = mJoinErrs;
00438 mTargetNode->mFP = mJoinPars;
00439 mTargetNode->mPP() = mJoinPars;
00440 mTargetNode->mHrr = mHrr;
00441
if (mTargetNode!=mVertexNode) mTargetNode->mUnTouch = mUnTouch;
00442 mTargetNode->_state = mState;
00443
if (mHit && ((mChi2<1000) != (mTargetNode->getChi2()<1000))) mTargetNode->mFlipFlop++;
00444
if (mTargetNode!=mVertexNode) mTargetNode->setChi2(mChi2);
00445
00446
00447
double myMaxChi2 = (mTargetNode==mVertexNode)? 1000:mChi2Max;
00448
if (mState == StiTrackNode::kTNFitEnd) {
00449 assert(mChi2 <myMaxChi2);
00450 }
else {
00451 assert(mChi2 <=0 || mChi2 >=myMaxChi2);
00452 }
00453
00454
return 0;
00455 }
00456
00457
double StiTrackNodeHelper::joinTwo(
int nP1,
const double *P1,
const double *E1
00458 ,
int nP2,
const double *P2,
const double *E2
00459 ,
double *PJ,
double *EJ)
00460 {
00461
00462 assert(nP1<=nP2);
00463
int nE1 = nP1*(nP1+1)/2;
00464
int nE2 = nP2*(nP2+1)/2;
00465 TArrayD ard(nE2*6);
00466
double *a = ard.GetArray();
00467
double *sumE = (a);
00468
double *sumEI = (a+=nE2);
00469
double *e1sumEIe1 = (a+=nE2);
00470
double *subP = (a+=nE2);
00471
double *sumEIsubP = (a+=nE2);
00472
double chi2=3e33,p,q;
00473
00474
00475
const double *p1 = P1, *p2 = P2, *e1 = E1, *e2 = E2, *t;
00476
double choice = (nP1==nP2)? 0:1;
00477
if (!choice ) {
00478
for (
int i=0,n=1;i<nE2;i+=(++n)) {
00479 p=fabs(e1[i]);q=fabs(e2[i]);choice += (p-q)/(p+q+1e-10);
00480 }}
00481
if ( choice >0) {t = p2; p2 = p1; p1 = t; t = e2; e2 = e1; e1 = t;}
00482
00483
do {
00484
00485 TCL::vadd(e1,e2,sumE,nE1);
00486
int negati = sumE[2]<0;
00487
if (negati) TCL::vcopyn(sumE,sumE,nE1);
00488
int ign0re = sumE[0]<=0;
00489
if (ign0re) sumE[0] = 1;
00490 TCL::trsinv(sumE,sumEI,nP1);
00491
if (ign0re) {sumE[0] = 0; sumEI[0] = 0;}
00492
if (negati) {TCL::vcopyn(sumE,sumE,nE1);TCL::vcopyn(sumEI,sumEI,nE1);}
00493 TCL::vsub(p2 ,p1 ,subP ,nP1);
00494 TCL::trasat(subP,sumEI,&chi2,1,nP1);
00495
if (!EJ)
break;
00496 TCL::trqsq (e1 ,sumEI,e1sumEIe1,nP2);
00497 TCL::vsub(e1,e1sumEIe1,EJ,nE2);
00498 }
while(0);
00499
00500
if (PJ) {
00501 TCL::tras(subP ,sumEI,sumEIsubP,1,nP1);
00502 TCL::tras(sumEIsubP,e1 ,PJ ,1,nP2);
00503 TCL::vadd(PJ ,p1 ,PJ ,nP2);
00504 }
00505
return chi2;
00506 }
00507
#if 0
00508
00509
double StiTrackNodeHelper::joinVtx(
const double *P1,
const double *E1
00510 ,
const double *P2,
const double *E2
00511 ,
double *PJ,
double *EJ)
00512 {
00513
enum {nP1=3,nE1=6,nP2=kNPars,nE2=kNErrs};
00514
double E1m[nE1],E2m[nE2];
00515
00516 TCL::vzero(E1m ,nE1);
00517 TCL::ucopy(E2,E2m ,nE2);
00518 TCL::vadd (E1,E2m,E2m,nE1);
00519
return joinTwo(nP1,P1,E1m,nP2,P2,E2m,PJ,EJ);
00520
00521 }
00522
#endif//0
00523
#if 0
00524
00525
double StiTrackNodeHelper::joinVtx(
const double *P1,
const double *E1
00526 ,
const double *P2,
const double *E2
00527 ,
double *PJ,
double *EJ)
00528 {
00529
enum {nP1=3,nE1=6,nP2=kNPars,nE2=kNErrs};
00530
00531 TArrayD ard(nE2*7);
00532
double *p = ard.GetArray();
00533
double *sumE = (p);
00534
double *sumEI = (p+=nE2);
00535
double *sumEI_E1_sumEI = (p+=nE2);
00536
double *E2_sumEI_E2 = (p+=nE2);
00537
double *E2_sumEI_E1_sumEI_E2 = (p+=nE2);
00538
double *sumEIsubP = (p+=nE2);
00539
double *subP = (p+=nE2);
00540
00541
double chi2=3e33;
00542
00543
00544
do {
00545
00546 TCL::ucopy(E2,sumE,nE1);
00547
int ign0re = sumE[0]<=0;
00548
if (ign0re) sumE[0] = 1;
00549 TCL::trsinv(sumE,sumEI,nP1);
00550
if (ign0re) {sumE[0] = 0; sumEI[0] = 0;}
00551 TCL::vsub(P1 ,P2 ,subP ,nP1);
00552 TCL::trasat(subP,sumEI,&chi2,1,nP1);
00553
if (!EJ)
break;
00554 TCL::trqsq (E2 ,sumEI,E2_sumEI_E2,nP2);
00555 TCL::vsub(E2,E2_sumEI_E2,EJ,nE2);
00556
00557 TCL::trqsq (sumEI,E1,sumEI_E1_sumEI,nP1);
00558 TCL::trqsq (E2,sumEI_E1_sumEI,E2_sumEI_E1_sumEI_E2,nP2);
00559 TCL::vadd(EJ,E2_sumEI_E1_sumEI_E2,EJ,nE2);
00560
00561 }
while(0);
00562
00563
if (PJ) {
00564 TCL::tras(subP ,sumEI,sumEIsubP,1,nP1);
00565 TCL::tras(sumEIsubP,E2 ,PJ ,1,nP2);
00566 TCL::vadd(PJ ,P2 ,PJ ,nP2);
00567 }
00568
return chi2;
00569 }
00570
#endif//1
00571
00572
double StiTrackNodeHelper::joinVtx(
const double *Y,
const StiHitErrs &B
00573 ,
const StiNodePars &X,
const StiNodeErrs &A
00574 , StiNodePars *M, StiNodeErrs *C)
00575 {
00576
00577
00578
00579
00580
00581
enum {nP1=3,nE1=6,nP2=6,nE2=21};
00582
00583 StiNodeErrs Ai=A;
00584
00585 Ai._cXX=1;
00586 TCL::trsinv(Ai.A,Ai.A,nP2);
00587 Ai._cXX=0;
00588
00589
00590
double Ai11i[6],Ai10[3][3],T10[3][3],dif[6],m[6];
00591 Ai.get11(Ai11i);
00592 Ai.get10(Ai10[0]);
00593 TCL::trsinv(Ai11i ,Ai11i,3);
00594 TCL::trsa (Ai11i,Ai10[0],T10[0],3,3);
00595 TCL::ucopy(Y,m,3);
00596 TCL::vsub (X.P,Y,dif,3);
00597 TCL::mxmpy(T10[0],dif,m+3,3,3,1);
00598 TCL::vadd(X.P+3,m+3,m+3,3);
00599
if (M) {TCL::ucopy(m,M->P,nP2); M->ready();}
00600
00601 TCL::vsub(X.P,m,dif,nP2);
00602
double chi2;
00603 TCL::trasat(dif,Ai.A,&chi2,1,nP2);
00604
if (!C)
return chi2;
00605
00606 C->reset();
00607
00608
double TX[nP1][nP2];memset(TX[0],0,
sizeof(TX));
00609
for (
int i=0;i<3;i++) {TCL::ucopy(T10[i],TX[i],3); TX[i][i+3]=1;}
00610
double C11[nE1];
00611 TCL::trasat(TX[0],A.A,C11,nP1,nP2);
00612 C->set11(C11);
00613
00614
double TY[nP2][nP1];memset(TY[0],0,
sizeof(TX));
00615
for (
int i=0;i<3;i++) {TCL::vcopyn(T10[i],TY[i+3],3); TY[i][i]=1;}
00616 TY[0][0] = 0;
00617
double CYY[nE2];
00618 TCL::trasat(TY[0],B.A,CYY,nP2,nP1);
00619 TCL::vadd(CYY,C->A,C->A,nE2);
00620
return chi2;
00621 }
00622
00623
int StiTrackNodeHelper::save()
00624 {
00625 assert(fabs(mPredPars._hz-mTargetHz)<=1e-10);
00626 assert(fabs(mFitdPars._hz-mTargetHz)<=1e-10);
00627 assert(fabs(mTargetNode->getHz()-mTargetHz)<=1e-10);
00628
00629 mTargetNode->mPP() = mPredPars;
00630 mTargetNode->mFP = mFitdPars;
00631 mTargetNode->mPE() = mPredErrs;
00632 mTargetNode->mFE = mFitdErrs;
00633 mTargetNode->_state = mState;
00634
if (mHit && ((mChi2<1000) != (mTargetNode->getChi2()<1000))) mTargetNode->mFlipFlop++;
00635
if (mTargetNode!=mVertexNode) mTargetNode->setChi2(mChi2);
00636
return 0;
00637 }
00638
00647
00648
int StiTrackNodeHelper::propagateMCS()
00649 {
00650 mMcs.reset();
00651
if (!mDetector)
return 0;
00652
if (fabs(mBestPars._ptin)<=1e-3)
return 0;
00653
double pt = 1./fabs(mBestPars._ptin);
00654
00655
double relRadThickness;
00656
00657
double pL1,pL2,pL3,d1,d2,d3,dxEloss,dx;
00658 pL1=0.5*pathIn(mParentNode->getDetector(),&mBestParentPars);
00659
00660 pL3=0.5*pathIn(mDetector,&mBestPars);
00661
00662 pL2= fabs(dl);
00663
double x0p =-1;
00664
double x0Gas=-1;
00665
double x0=-1;
00666 dx = mBestPars._x - mBestParentRotPars._x;
00667 d1 = mParentNode->getDensity();
00668 x0p = mParentNode->getX0();
00669 d3 = mDetector->getMaterial()->getDensity();
00670 x0 = mDetector->getMaterial()->getX0();
00671
00672
00673
if (pL2> (pL1+pL3)) {
00674
00675 pL2=pL2-pL1-pL3;
00676
if (dx>0) {
00677 x0Gas = mDetector->getGas()->getX0();
00678 d2 = mDetector->getGas()->getDensity();
00679 }
else {
00680 x0Gas = mParentNode->getGasX0();
00681 d2 = mParentNode->getGasDensity();
00682 }
00683
00684 relRadThickness = 0.;
00685 dxEloss = 0;
00686
00687
if (x0p>0.) {
00688 relRadThickness += pL1/x0p;
00689 dxEloss += d1*pL1;
00690 }
00691
if (x0Gas>0.) {
00692 relRadThickness += pL2/x0Gas;
00693 dxEloss += d2*pL2;
00694 }
00695
if (x0>0.){
00696 relRadThickness += pL3/x0;
00697 dxEloss += d3*pL3;
00698 }
00699 }
else {
00700 relRadThickness = 0.;
00701 dxEloss = 0;
00702
if (x0p>0.) {
00703 relRadThickness += pL1/x0p;
00704 dxEloss += d1*pL1;
00705 }
00706
if (x0>0.){
00707 relRadThickness += pL3/x0;
00708 dxEloss += d3*pL3;
00709 }
00710 }
00711
double tanl = mBestPars._tanl;
00712
double pti = mBestPars._ptin;
00713
double p2 = (1.+tanl*tanl)*pt*pt;
00714
double m = StiKalmanTrackFinderParameters::instance()->getMassHypothesis();
00715
double m2 = m*m;
00716
double e2 = p2+m2;
00717
double beta2 = p2/e2;
00718
double theta2 = StiKalmanTrackNode::mcs2(relRadThickness,beta2,p2);
00719
double cos2Li = (1.+ tanl*tanl);
00720
double f = mHitsErrFactor;
00721 mMcs._cEE = cos2Li *theta2*f;
00722 mMcs._cPP = tanl*tanl*pti*pti *theta2*f;
00723 mMcs._cTP = pti*tanl*cos2Li *theta2*f;
00724 mMcs._cTT = cos2Li*cos2Li *theta2*f;
00725
00726
double dE=0;
00727
double sign = (dx>0)? 1:-1;
00728
00729
00730 StiElossCalculator * calculator = mDetector->getElossCalculator();
00731
double eloss = calculator->calculate(1.,m, beta2);
00732 dE = sign*dxEloss*eloss;
00733
00734 mMcs._ptinCorr = ::sqrt(e2)*dE/p2;
00735
if (fabs(mMcs._ptinCorr)>0.1) mMcs._ptinCorr = (dE<0)? -0.1:0.1;
00736
return 0;
00737 }
00738
00752
00753
double StiTrackNodeHelper::evalChi2()
00754 {
00755
double r00, r01,r11,chi2;
00756
00757
00758
if (fabs(mPredPars._sinCA)>0.99 )
return 1e41;
00759
if (fabs(mPredPars._eta) >kMaxEta)
return 1e41;
00760
if (fabs(mPredPars._curv) >kMaxCur)
return 1e41;
00761
if (!mDetector) {
00762 mHitPars[0] = mPredPars._x;
00763
00764 chi2 = joinVtx(mHitPars,mHrr,mPredPars,mPredErrs);
00765 }
else {
00766
00767 r00=mPredErrs._cYY+mHrr.hYY;
00768 r01=mPredErrs._cZY+mHrr.hZY;
00769 r11=mPredErrs._cZZ+mHrr.hZZ;
00770 mDetm = r00*r11 - r01*r01;
00771
if (mDetm<r00*r11*1.e-5) {
00772 LOG_DEBUG << Form(
"StiTrackNodeHelper::evalChi2 *** zero determinant %g",mDetm)<< endm;
00773
return 1e60;
00774 }
00775
double tmp=r00; r00=r11; r11=tmp; r01=-r01;
00776
00777
double dyt=(mPredPars._y-mHitPars[1]);
00778
double dzt=(mPredPars._z-mHitPars[2]);
00779 chi2 = (dyt*r00*dyt + 2*r01*dyt*dzt + dzt*r11*dzt)/mDetm;
00780 }
00781
return chi2;
00782 }
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
double StiTrackNodeHelper::recvChi2()
00808 {
00809
if (fabs(mJoinPars._sinCA)>0.99 )
return 1e41;
00810
if (fabs(mJoinPars._eta) >kMaxEta)
return 1e41;
00811
if (fabs(mJoinPars._curv) >kMaxCur)
return 1e41;
00812
if (!mDetector) {
00813
00814
double chi2 =joinVtx(mHitPars,mHrr ,mPredPars ,mPredErrs );
00815
return chi2;
00816 }
00817
00818 StiHitErrs myHrr = mHrr;
00819 StiNodeErrs recovErrs;
00820 StiNodePars recovPars;
00821
double f = -(1./mHitsErrFactor);
00822 myHrr*=f;
00823
double r11,r12,r22;
00824
if ((r11=myHrr.hYY+mJoinErrs._cYY) >=0)
return 1e41;
00825
if ((r22=myHrr.hZZ+mJoinErrs._cZZ) >=0)
return 1e41;
00826 r12 =myHrr.hZY+mJoinErrs._cZY;
00827
if (r11*r22-r12*r12<0)
return 1e41;
00828
00829
00830
double chi2 = joinTwo(3,mHitPars , myHrr.A
00831 ,3,mJoinPars.P,mJoinErrs.A
00832 ,recovPars.P,recovErrs.A);
00833
if (fabs(recovPars._y-mHitPars[1])>10) StiDebug::Break(-1);
00834
if (fabs(recovPars._z-mHitPars[2])>10) StiDebug::Break(-1);
00835
00836 mUnTouch.set(recovPars,recovErrs);
00837
return -chi2;
00838 }
00839
00840
int StiTrackNodeHelper::setHitErrs()
00841 {
00842 getHitErrors(mHit,&mFitdPars,&mHrr);
00843 mHrr*=mHitsErrFactor;
00844
return 0;
00845 }
00846
00866
00867
int StiTrackNodeHelper::updateNode()
00868 {
00869
static int nCall=0; nCall++;
00870 mState = StiTrackNode::kTNFitBeg;
00871 assert(mPredErrs._cXX<1e-8);
00872
double r00,r01,r11;
00873 StiDebug::Break(mTargetNode->mId);
00874
if (!mDetector) {
00875 mHitPars[0] = mPredPars._x;
00876
00877
double chi2 = joinVtx(mHitPars,mHrr,mPredPars,mPredErrs,&mFitdPars,&mFitdErrs);
00878 mFitdPars._curv = mTargetHz*mFitdPars._ptin;
00879 assert(chi2>900 || fabs(mChi2-chi2)<1e-10);
00880 }
else {
00881
00882 r00=mHrr.hYY+mPredErrs._cYY;
00883 r01=mHrr.hZY+mPredErrs._cZY;
00884 r11=mHrr.hZZ+mPredErrs._cZZ;
00885 mDetm=r00*r11 - r01*r01;
00886
if (!(mDetm>(r00*r11)*1.e-5))
return 99;
00887 assert(mDetm>(r00*r11)*1.e-5);
00888
00889
00890
double tmp=r00; r00=r11/mDetm; r11=tmp/mDetm; r01=-r01/mDetm;
00891
00892
double k00=mPredErrs._cYY*r00+mPredErrs._cZY*r01, k01=mPredErrs._cYY*r01+mPredErrs._cZY*r11;
00893
double k10=mPredErrs._cZY*r00+mPredErrs._cZZ*r01, k11=mPredErrs._cZY*r01+mPredErrs._cZZ*r11;
00894
double k20=mPredErrs._cEY*r00+mPredErrs._cEZ*r01, k21=mPredErrs._cEY*r01+mPredErrs._cEZ*r11;
00895
double k30=mPredErrs._cPY*r00+mPredErrs._cPZ*r01, k31=mPredErrs._cPY*r01+mPredErrs._cPZ*r11;
00896
double k40=mPredErrs._cTY*r00+mPredErrs._cTZ*r01, k41=mPredErrs._cTY*r01+mPredErrs._cTZ*r11;
00897
00898
double myY = mPredPars._y;
00899
double myZ = mPredPars._z;
00900
double dyt = mHitPars[1] - myY;
00901
double dzt = mHitPars[2] - myZ;
00902
double dPt = k30*dyt + k31*dzt;
00903
double dEt = k20*dyt + k21*dzt;
00904
double dTa = k40*dyt + k41*dzt;
00905
double eta = NICE(mPredPars._eta + dEt);
00906
double pti = mPredPars._ptin+ dPt;
00907
double tanl = mPredPars._tanl + dTa;
00908
00909
00910
00911
00912
00913
double p0 = myY + k00*dyt + k01*dzt;
00914
double p1 = myZ + k10*dyt + k11*dzt;
00915
00916
double sinCA = sin(eta);
00917
00918
00919
00920 mFitdPars._hz = mTargetHz;
00921 mFitdPars._x = mPredPars._x;
00922 mFitdPars._y = p0;
00923 mFitdPars._z = p1;
00924 mFitdPars._eta = eta;
00925 mFitdPars._ptin = pti;
00926 mFitdPars._curv = mTargetHz*pti;
00927 mFitdPars._tanl = tanl;
00928 mFitdPars._sinCA = sinCA;
00929 mFitdPars._cosCA = ::sqrt((1.-mFitdPars._sinCA)*(1.+mFitdPars._sinCA));
00930
if (!mDetector)
00931 assert(fabs(mFitdPars._y-mHitPars[1])>1e-10 || fabs(mHitPars[0])<4);
00932
00933
00934
if (mFitdPars.check())
return -11;
00935
00936
double c00=mPredErrs._cYY;
00937
double c10=mPredErrs._cZY, c11=mPredErrs._cZZ;
00938
double c20=mPredErrs._cEY, c21=mPredErrs._cEZ;
00939
double c30=mPredErrs._cPY, c31=mPredErrs._cPZ;
00940
double c40=mPredErrs._cTY, c41=mPredErrs._cTZ;
00941 mFitdErrs._cYY-=k00*c00+k01*c10;
00942 mFitdErrs._cZY-=k10*c00+k11*c10;mFitdErrs._cZZ-=k10*c10+k11*c11;
00943 mFitdErrs._cEY-=k20*c00+k21*c10;mFitdErrs._cEZ-=k20*c10+k21*c11;mFitdErrs._cEE-=k20*c20+k21*c21;
00944 mFitdErrs._cPY-=k30*c00+k31*c10;mFitdErrs._cPZ-=k30*c10+k31*c11;mFitdErrs._cPE-=k30*c20+k31*c21;mFitdErrs._cPP-=k30*c30+k31*c31;
00945 mFitdErrs._cTY-=k40*c00+k41*c10;mFitdErrs._cTZ-=k40*c10+k41*c11;mFitdErrs._cTE-=k40*c20+k41*c21;mFitdErrs._cTP-=k40*c30+k41*c31;mFitdErrs._cTT-=k40*c40+k41*c41;
00946 }
00947
if (mFitdErrs.check())
return -12;
00948
00949
00950
00951
static int ERRTEST=0;
00952
if(ERRTEST) errTest(mPredPars,mPredErrs,mHit,mHrr,mFitdPars,mFitdErrs,mChi2);
00953
00954
00955
00956
if (mDetector) {
00957
if (mHrr.hYY <= mFitdErrs._cYY) {
00958 LOG_DEBUG << Form(
"StiTrackNodeHelper::updateNode() WRONG hYY(%g) < nYY(%g)"
00959 ,mHrr.hYY,mFitdErrs._cYY)<< endm;
00960
return -13;
00961 }
00962
if (mHrr.hZZ <= mFitdErrs._cZZ) {
00963 LOG_DEBUG << Form(
"StiTrackNodeHelper::updateNode() WRONG hZZ(%g) < nZZ(%g)"
00964 ,mHrr.hZZ,mFitdErrs._cZZ)<< endm;
00965
return -14;
00966 }
00967 }
00968
if (mTargetNode && debug() & 8) mTargetNode->PrintpT(
"U");
00969 mState = StiTrackNode::kTNFitEnd;
00970
return 0;
00971 }
00972
00973
00974
void StiTrackNodeHelper::resetError(
double fk)
00975 {
00976
if (fk)
do {
00977
if(mPredErrs._cYY>DY*DY)
break;
00978
if(mPredErrs._cZZ>DZ*DZ)
break;
00979
if(mPredErrs._cEE>DEta*DEta)
break;
00980
if(mPredErrs._cPP>DPti*DPti)
break;
00981
if(mPredErrs._cTT>DTan*DTan)
break;
00982 mPredErrs*=fk;
00983
return;
00984 }
while(0);
00985
00986 mPredErrs.reset();
00987 mPredErrs._cYY=DY*DY;
00988 mPredErrs._cZZ=DZ*DZ;
00989 mPredErrs._cEE=DEta*DEta;
00990 mPredErrs._cPP=DPti*DPti;
00991 mPredErrs._cTT=DTan*DTan;
00992 }
00993
00994
int StiTrackNodeHelper::cutStep(StiNodePars *pars,StiNodePars *base)
00995 {
00996
double fact=1,dif,fak;
00997
double cuts[kNPars];
00998 memcpy(cuts,MAXSTEP,
sizeof(cuts));
00999
if (mBestDelta<DY) {cuts[1]=mBestDelta;cuts[2]=mBestDelta;}
01000
01001
for (
int jx=0;jx<kNPars;jx++) {
01002 dif =(fabs((*pars)[jx]-(*base)[jx]));
01003 fak = (dif >cuts[jx]) ? cuts[jx]/dif:1;
01004
if (fak < fact) fact = fak;
01005 }
01006
if (fact>=1)
return 0;
01007 mgCutStep++;
01008
for (
int jx=0;jx<kNPars;jx++) {
01009 dif =(*pars)[jx]-(*base)[jx];
01010 (*pars)[jx] = (*base)[jx] +dif*fact;
01011 }
01012 pars->ready();
01013
return 1;
01014 }
01015
01016
int StiTrackNodeHelper::nudge()
01017 {
01018
if(!mHit)
return 0;
01019 StiNodePars *pars = &mBestPars;
01020
for (
int i=0;i<2;i++,pars =&mPredPars) {
01021
double deltaX = mHitPars[0]-pars->_x;
01022
if (fabs(deltaX) <1e-6)
continue;
01023
double deltaL = deltaX/pars->_cosCA;
01024
double deltaE = pars->_curv*deltaL;
01025 pars->_x = mHitPars[0];
01026 pars->_y += pars->_sinCA *deltaL;
01027 pars->_z += pars->_tanl *deltaL;
01028 pars->_eta += deltaE;
01029 pars->_cosCA -= pars->_sinCA *deltaE;
01030 pars->_sinCA += pars->_cosCA *deltaE;
01031
if (pars->_cosCA>=1.) pars->ready();
01032
if (pars->check())
return 1;
01033 }
01034
return 0;
01035 }
01036
01037
double StiTrackNodeHelper::pathIn(
const StiDetector *det,StiNodePars *pars)
01038 {
01039
if (!det)
return 0.;
01040
double thickness = det->
getShape()->
getThickness();
01041
double t = pars->_tanl;
01042
double c = pars->_cosCA;
01043
return (thickness*::sqrt(1.+t*t)) / c;
01044 }
01045
01046
int StiTrackNodeHelper::getHitErrors(
const StiHit *hit,
const StiNodePars *pars,StiHitErrs *hrr)
01047 {
01048 hrr->reset();
01049
const StiDetector *det = hit->detector();
01050
const StiHitErrorCalculator *calc = (det)? det->
getHitErrorCalculator():0;
01051
if (calc) {
01052 calc->calculateError(pars,hrr->hYY,hrr->hZZ);
01053 }
else {
01054
const float *ermx = hit->errMtx();
01055
for (
int i=0;i<6;i++){hrr->A[i]=ermx[i];}
01056 }
01057
return (!det);
01058 }
01059
01060
int errTest(StiNodePars &predP,StiNodeErrs &predE,
01061
const StiHit *hit ,StiHitErrs &hitErr,
01062 StiNodePars &fitdP,StiNodeErrs &fitdE,
double chi2)
01063 {
01064
01065 StiNodePars mineP,hittP;
01066 StiNodeErrs mineE,hittE;
01067 hittP._x = hit->x();
01068 hittP._y = hit->y();
01069 hittP._z = hit->z();
01070 memcpy(hittE.A,hitErr.A,
sizeof(StiNodeErrs));
01071
01072
double myChi2 = StiTrackNodeHelper::joinTwo(
01073 3,hittP.P,hittE.A,
01074 6,predP.P,predE.A,
01075 mineP.P,mineE.A);
01076
01077
01078
int ndif = 0;
01079
for (
int i=0;i<kNPars;i++) {
01080
double diff = fabs(mineP.P[i]-fitdP.P[i]);
01081
if (diff < 1e-10)
continue;
01082 diff/=0.5*(fabs(mineP.P[i])+fabs(fitdP.P[i]));
01083
if (diff < 1e-5 )
continue;
01084 ndif++;
01085 LOG_DEBUG << Form(
"errTest(P): %g(%d) - %g(%d) = %g",mineE.A[i],i,fitdE.A[i],i,diff)<< endm;
01086 }
01087
if (ndif){ mineP.print();fitdP.print();}
01088
01089
for (
int i=0;i<kNErrs;i++) {
01090
double diff = fabs(mineE.A[i]-fitdE.A[i]);
01091
if (diff < 1e-10)
continue;
01092 diff/=0.5*(fabs(mineE.A[i])+fabs(fitdE.A[i]));
01093
if (diff < 1e-5 )
continue;
01094 ndif+=100;
01095 LOG_DEBUG << Form(
"errTest(E): %g(%d) - %g(%d) = %g",mineE.A[i],i,fitdE.A[i],i,diff)<< endm;
01096 }
01097
if (ndif>=100){ mineE.print();fitdE.print();}
01098
01099
double diff = fabs((chi2-myChi2)/(chi2+myChi2));
01100
if (diff > 1e-5 ) {
01101 ndif+=1000;
01102 LOG_DEBUG << Form(
"errTest(C): %g() - %g() = %g",myChi2,chi2,diff)<< endm;
01103 }
01104
01105
return ndif;
01106 }
01107
01108
01109
void QaFit::add(
double val)
01110 {
01111
double v = val;
double p = mPrev; mPrev = v;
01112
int n = (mTally)? 2:1;
01113 mTally++;
01114
for (
int i=0;i<n;i++) {
01115 mAver[i] +=v;
01116 mErrr[i] +=v*v;
01117
if (mMaxi[i]<fabs(v)) mMaxi[i]=fabs(v);
01118
if (v<0) mNega[i]++;
01119 v = v*p;
01120 }
01121 }
01122
01123
void QaFit::finish()
01124 {
01125
if( mEnded)
return;
01126
if(!mTally)
return;
01127 mEnded = 1;
01128
int n = mTally;
01129
for (
int i=0;i<2;i++) {
01130 mAver[i]/= n;
01131 mErrr[i]/= n;
01132
if (mErrr[i]<1e-10) mErrr[i]=1e-10;
01133 mErrr[i] = sqrt(mErrr[i]);
01134
if (!(--n))
break;
01135 }
01136 }
01137
01138
double QaFit::getAccu(
int k)
01139 {
01140 finish();
01141
if (mTally-k<=1)
return 0;
01142
return mErrr[k];
01143 }
01144
01145
double QaFit::getNStd(
int k)
01146 {
01147 finish();
01148
int n = mTally-k;
01149
if (!n)
return 0;
01150
return mAver[k]*sqrt(
double(n));
01151 }
01152
01153
double QaFit::getNSgn(
int k)
01154 {
01155 finish();
01156
int n = mTally-k;
01157
if (!n)
return 0;
01158
return (n-2*mNega[k])/sqrt(
double(n));
01159 }
01160
01161
void QaFit::getInfo(
double *info)
01162 {
01163
for (
int i=0;i<2;i++) {
01164
int l = i*4;
01165 info[l+0]=getAccu(i);
01166 info[l+1]=getNStd(i);
01167 info[l+2]=getNSgn(i);
01168 info[l+3]=getMaxi(i);
01169 }
01170 }
01171
01172
01173