00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
#include <Stiostream.h>
00347
#include <stdexcept>
00348
#include <math.h>
00349
#include <stdio.h>
00350
using namespace std;
00351
00352
#include "StiHit.h"
00353
#include "StiDetector.h"
00354
#include "StiPlacement.h"
00355
#include "StiMaterial.h"
00356
#include "StiShape.h"
00357
#include "StiPlanarShape.h"
00358
#include "StiCylindricalShape.h"
00359
#include "StiKalmanTrackNode.h"
00360
#include "StiElossCalculator.h"
00361
#include "StiTrackingParameters.h"
00362
#include "StiKalmanTrackFinderParameters.h"
00363
#include "StiHitErrorCalculator.h"
00364
#include "StiTrackNodeHelper.h"
00365
#include "StiFactory.h"
00366
#include "TString.h"
00367
#if ROOT_VERSION_CODE < 331013
00368
#include "TCL.h"
00369
#else
00370
#include "TCernLib.h"
00371
#endif
00372
#include "THelixTrack.h"
00373
#include "StThreeVector.hh"
00374
#include "StThreeVectorF.hh"
00375
00376
#include "TRMatrix.h"
00377
#include "TRVector.h"
00378
#include "StarMagField.h"
00379
#include "TMath.h"
00380
#include "StMessMgr.h"
00381
00382
#define PrP(A) { LOG_INFO << "\t" << (#A) << " = \t" << ( A ) }
00383
#define PrPP(A,B) {LOG_INFO << "=== StiKalmanTrackNode::" << (#A); PrP((B)); LOG_INFO << endm;}
00384
00385
00386
00387
00388
00389
00390
00391
00392
static const double kMaxEta = 1.25;
00393
static const double kMaxSinEta = sin(kMaxEta);
00394
static const double kMaxCur = 0.2;
00395
static const double kFarFromBeam = 10.;
00396
static const Double_t kMaxZ = 250;
00397
static const Double_t kMaxR = 250;
00398 StiNodeStat StiKalmanTrackNode::mgP;
00399
00400
00401
static const int idx33[3][3] = {{0,1,3},{1,2,4},{3,4,5}};
00402
static const int idx55[5][5] =
00403 {{0,1,3,6,10},{1,2,4,7,11},{3,4,5, 8,12},{6,7, 8, 9,13},{10,11,12,13,14}};
00404
static const int idx55tpt[5][5] =
00405 {{0,1,2,3, 4},{1,5,6,7, 8},{2,6,9,10,11},{3,7,10,12,13},{ 4, 8,11,13,14}};
00406
00407
static const int idx66[6][6] =
00408 {{ 0, 1, 3, 6,10,15},{ 1, 2, 4, 7,11,16},{ 3, 4, 5, 8,12,17}
00409 ,{ 6, 7, 8, 9,13,18},{10,11,12,13,14,19},{15,16,17,18,19,20}};
00410
00411
bool StiKalmanTrackNode::useCalculatedHitError =
true;
00412 TString StiKalmanTrackNode::comment(
"Legend: \tE - extapolation\tM Multiple scattering\tV at Vertex\tB at beam\tR at Radius\tU Updated\n");
00413 TString StiKalmanTrackNode::commentdEdx(
"");
00414
00415
00416
00417
#ifdef STI_DERIV_TEST
00418
int StiKalmanTrackNode::fDerivTestOn=0;
00419
#endif
00420
#ifndef STI_DERIV_TEST
00421
int StiKalmanTrackNode::fDerivTestOn=-10;
00422
#endif
00423
00424
double StiKalmanTrackNode::fDerivTest[kNPars][kNPars];
00425
int gCurrShape=0;
00426
00427
void StiKalmanTrackNode::Break(
int kase)
00428 {
00429
static int myBreak=-2005;
00430
if (kase!=myBreak)
return;
00431 LOG_DEBUG << Form(
"*** Break(%d) ***",kase)<< endm;
00432 }
00433
00434
00435
00436
00437
00438
00439
int StiKalmanTrackNode::_debug = 0;
00440
int StiKalmanTrackNode::_laser = 0;
00441
00442
00443 void StiKalmanTrackNode::reset()
00444 {
00445
static int myCount=0;
00446 StiTrackNode::reset();
00447 memset(_beg,0,_end-_beg+1);
00448 _ext=0; _inf=0;
00449 mId = ++myCount;
00450
00451 Break(mId);
00452 }
00453
00454
void StiKalmanTrackNode::unset()
00455 {
00456 reduce();
00457
if (_inf) BFactory::Free(_inf); _inf=0;
00458 }
00459
00460 void StiKalmanTrackNode::resetError(
double fak)
00461 {
00462
static const double DY=0.3,DZ=0.3,DEta=0.03,DPti=1.,DTan=0.05;
00463
00464
if (!fak) {
00465
mFE.reset();
00466
mFE._cYY=DY*DY;
00467
mFE._cZZ=DZ*DZ;
00468
mFE._cEE=DEta*DEta;
00469
mFE._cPP=DPti*DPti;
00470
mFE._cTT=DTan*DTan;
00471 }
else {
00472
for (
int i=0;i<kNErrs;i++)
mFE.A[i] *=fak;
00473 }
00474 mPE() =
mFE;
00475 }
00476
00481
00482 void StiKalmanTrackNode::setState(
const StiKalmanTrackNode * n)
00483 {
00484 _state = n->_state;
00485 _alpha = n->
_alpha;
00486 mFP = n->
mFP;
00487
mFE = n->
mFE;
00488 mFP._hz=0;
00489 nullCount = n->
nullCount;
00490 contiguousHitCount = n->
contiguousHitCount;
00491 contiguousNullCount = n->
contiguousNullCount;
00492 setChi2(1e62);
00493 }
00494
00503
00504 void StiKalmanTrackNode::get(
double& alpha,
00505
double& xRef,
00506
double x[kNPars],
00507
double e[kNErrs],
00508
double& chi2)
00509 {
00510 alpha = _alpha;
00511 xRef = getRefPosition();
00512 memcpy(x,&mFP._x,kNPars*
sizeof(mFP._x));
00513 memcpy(e,
mFE.A,
sizeof(
mFE));
00514 chi2 = getChi2();
00515 }
00516
00517
00525
00526 double StiKalmanTrackNode::getPt()
const
00527
{
00528
return (fabs(mFP._ptin)<1e-6) ? 1e6: 1./fabs(mFP._ptin);
00529 }
00530
00531
void StiKalmanTrackNode::propagateCurv(
const StiKalmanTrackNode *parent)
00532 {
00533 mFP._ptin=parent->
mFP._ptin;
00534 mFP._curv=
getHz()*mFP._ptin;
00535 }
00536
00543
00544 double StiKalmanTrackNode::getHz()
const
00545
{
00546
static const Double_t EC = 2.99792458e-4;
00547
if (
mHz)
return mHz;
00548
double h[3];
00549 StarMagField::Instance()->
BField(&(getGlobalPoint().x()),h);
00550 h[2] = EC*h[2];
00551
if (fabs(h[2]) < 3e-33) h[2]=3e-33;
00552
mHz = h[2];
00553
return mHz;
00554 }
00555
00585
00586 void StiKalmanTrackNode::getMomentum(
double p[3],
double e[6])
const
00587
{
00588
00589
00590
enum {jX=0,jY,jZ,jE,jP,jT};
00591
00592
double pt =
getPt();
00593 p[0] = pt*mFP._cosCA;
00594 p[1] = pt*mFP._sinCA;
00595 p[2] = pt*mFP._tanl;
00596
00597
00598
if (!e)
return;
00599
00600
double F[3][kNPars]; memset(F,0,
sizeof(F));
00601
double dPtdPi = -pt*pt;
if (mFP._ptin<0) dPtdPi=-dPtdPi;
00602 F[jX][jE] = -pt *mFP._sinCA;
00603 F[jX][jP] = dPtdPi*mFP._cosCA;
00604 F[jX][jT] = 0;
00605
00606 F[jY][jE] = pt *mFP._cosCA;
00607 F[jY][jP] = dPtdPi*mFP._sinCA;
00608 F[jY][jT] = 0;
00609
00610 F[jZ][jE] = 0;
00611 F[jZ][jP] = dPtdPi*mFP._tanl;
00612 F[jZ][jT] = pt;
00613
00614
00615 TCL::trasat(F[0],
mFE.A,e,3,kNPars);
00616 }
00617
00636
00637 void StiKalmanTrackNode::getGlobalRadial(
double x[6],
double e[15])
00638 {
00639
enum {jRad=0,jPhi,jZ,jTan,jPsi,jCur, kX=0,kY,kZ,kE,kC,kT};
00640
double alpha,xRef,chi2;
00641
double xx[kNPars],ee[kNErrs];
00642
00643
get(alpha,xRef,xx,ee,chi2);
00644
00645 x[jRad] = sqrt(pow(xx[kX],2)+pow(xx[kY],2));
00646 x[jPhi] = atan2(xx[kY],xx[kX]) + alpha;
00647 x[jZ ] = xx[kZ];
00648 x[jTan] = xx[kT];
00649 x[jPsi] = xx[kE] + alpha;
00650 x[jCur] = xx[kC];
00651
if (!e)
return;
00652
00653
double F[kNErrs][kNErrs]; memset(F,0,
sizeof(F));
00654 F[jPhi][kX] = -1e5;
00655 F[jPhi][kY] = 1e5;
00656
if (fabs(xx[kY])>1e-5) F[jPhi][kX] = -1./(xx[kY]);
00657
if (fabs(xx[kX])>1e-5) F[jPhi][kY] = 1./(xx[kX]);
00658 F[jZ][kZ] = 1.;
00659 F[jTan][kT] = 1;
00660 F[jPsi][kE] = 1;
00661 F[jCur][kC] = 1;
00662 memset(e,0,
sizeof(*e)*15);
00663
for (
int k1=0;k1<kNPars;k1++) {
00664
for (
int k2=0;k2<kNPars;k2++) {
00665
double cc =
mFE.A[idx66[k1][k2]];
00666
for (
int j1=jPhi;j1<= 5;j1++){
00667
for (
int j2=jPhi;j2<=j1;j2++){
00668 e[idx55[j1-1][j2-1]]+= cc*F[j1][k1]*F[j2][k2];
00669 }}}}
00670
00671 }
00672
00701
00702 void StiKalmanTrackNode::getGlobalTpt(
float x[6],
float e[15])
00703 {
00704
enum {jRad=0,jPhi,jZ,jTan,jPsi,jCur,jPt=jCur};
00705
static const double DEG = 180./M_PI;
00706
static double fak[6] = {1,0,1,1,DEG,0};
00707
00708
double xx[6],ee[15];
00709
getGlobalRadial(xx,ee);
00710
double pt =
getPt();
00711 fak[jPhi] = DEG*xx[jRad];
00712 fak[jPt] = (double(
getCharge())/pt)/xx[jCur];
00713
00714
for (
int i=0;i<6;i++) {x[i] = (
float)(fak[i]*xx[i]);}
00715
if (!e)
return;
00716
00717
for (
int j1=jPhi;j1<= 5;j1++){
00718
for (
int j2=jPhi;j2<=j1;j2++){
00719 e[idx55tpt[j1-1][j2-1]] = (
float)fak[j1]*fak[j2]*ee[idx55[j1-1][j2-1]];
00720 }}
00721
00722 }
00723
00724 double StiKalmanTrackNode::getPhase()
const
00725
{
00729
return getPsi()-getHelicity()*M_PI/2;
00730
00731 }
00732
00733
double StiKalmanTrackNode::getPsi()
const
00734
{
00735
return nice(mFP._eta+_alpha);
00736 }
00737
00738
00752
00753
00754 void StiKalmanTrackNode::getGlobalMomentum(
double p[3],
double e[6])
const
00755
{
00756
00757
enum {jXX=0,jXY,jYY};
00758
00759 getMomentum(p,e);
00760
00761
00762
00763
00764
double px=p[0];
00765
double py=p[1];
00766
double cosAlpha = cos(_alpha);
00767
double sinAlpha = sin(_alpha);
00768 p[0] = cosAlpha*px - sinAlpha*py;
00769 p[1] = sinAlpha*px + cosAlpha*py;
00770
if (e==0)
return;
00771
00772
00773
00774
double cXX = e[jXX];
00775
double cXY = e[jXY];
00776
double cYY = e[jYY];
00777
double cc = cosAlpha*cosAlpha;
00778
double ss = sinAlpha*sinAlpha;
00779
double cs = cosAlpha*sinAlpha;
00780 e[jXX] = cc*cXX - 2.*cs*cXY + ss*cYY;
00781 e[jYY] = ss*cXX + 2.*cs*cXY + cc*cYY;
00782 e[jXY] = cs*cXX + (cc-ss)*cXY - cs*cYY;
00783 }
00784
00785
00786
00801
00802 int StiKalmanTrackNode::propagate(
StiKalmanTrackNode *pNode,
00803
const StiDetector * tDet,
int dir)
00804 {
00805
static int nCall=0; nCall++;
00806 Break(nCall);
00807
int position = 0;
00808
setState(pNode);
00809 setDetector(tDet);
00810
if (debug()) ResetComment(::Form(
"%30s ",tDet->
getName().c_str()));
00811
00812 StiPlacement * place = tDet->
getPlacement();
00813
00814
double nNormalRadius = place->getNormalRadius();
00815
00816
StiShape * sh = tDet->
getShape();
00817
int shapeCode = sh->
getShapeCode();
00818
double endVal,dAlpha;
00819
switch (shapeCode) {
00820
00821
case kPlanar: endVal = nNormalRadius;
00822 {
00823 dAlpha = place->getNormalRefAngle();
00824 dAlpha = nice(dAlpha - _alpha);
00825
00826 position =
rotate(dAlpha);
00827
if (position)
return -10;
00828 }
00829
break;
00830
case kDisk:
00831
case kCylindrical: endVal = nNormalRadius;
00832 {
00833
double xy[4];
00834 position = cylCross(endVal,&mFP._cosCA,mFP._curv,xy);
00835
if (position)
return -11;
00836 dAlpha = atan2(xy[1],xy[0]);
00837 position =
rotate(dAlpha);
00838
if (position)
return -11;
00839 }
00840
break;
00841
default: assert(0);
00842 }
00843
00844 position =
propagate(endVal,shapeCode,dir);
00845
00846
if (position>kEdgeZplus || position<0)
return position;
00847
propagateError();
00848
if (debug() & 8) { PrintpT(
"E");}
00849
00850
00851
if (StiKalmanTrackFinderParameters::instance()->mcsCalculated() && fabs(
getHz())>1e-5 )
00852
propagateMCS(pNode,tDet);
00853
if (debug() & 8) { PrintpT(
"M");}
00854
return position;
00855 }
00856
00857
00868 bool StiKalmanTrackNode::propagate(
const StiKalmanTrackNode *parentNode,
StiHit * vertex,
int dir)
00869 {
00870
static int nCall=0; nCall++;
00871 Break(nCall);
00872
00873
setState(parentNode);
00874 TCircle tc(&mFP._x,&mFP._cosCA,mFP._curv);
00875
double xy[2]; xy[0]=vertex->x(),xy[1]=vertex->y();
00876
double s = tc.Path(xy); tc.Move(s);
00877
double ang = atan2(tc.Dir()[1],tc.Dir()[0]);
00878 vertex->rotate(ang);
00879
rotate(ang);
00880
if (debug()) ResetComment(::Form(
"Vtx:%8.3f %8.3f %8.3f",vertex->x(),vertex->y(),vertex->z()));
00881
if (
propagate(vertex->x(),kPlanar,dir))
return false;
00882
propagateError();
00883
if (debug() & 8) { PrintpT(
"V");}
00884 setHit(vertex);
00885 setDetector(0);
00886
return true;
00887 }
00888
00889
00892 bool StiKalmanTrackNode::propagateToBeam(
const StiKalmanTrackNode *parentNode,
int dir)
00893 {
00894
setState(parentNode);
00895
if (debug()) {
00896
if (parentNode->getDetector())
00897 ResetComment(::Form(
"%30s ",parentNode->getDetector()->getName().c_str()));
00898
else ResetComment(
"Unknown Detector");
00899 }
00900
if (
propagate(0., kPlanar,dir) < 0)
return false;
00901
propagateError();
00902
if (debug() & 8) { PrintpT(
"B");}
00903 setHit(0);
00904 setDetector(0);
00905
return true;
00906 }
00907
00908
00911 int StiKalmanTrackNode::propagateToRadius(
StiKalmanTrackNode *pNode,
double radius,
int dir)
00912 {
00913
int position = 0;
00914
setState(pNode);
00915
if (debug()) ResetComment(::Form(
"%30s ",pNode->getDetector()->getName().c_str()));
00916 position =
propagate(radius,kCylindrical,dir);
00917
if (position<0)
return position;
00918
propagateError();
00919
if (debug() & 8) { PrintpT(
"R");}
00920 _detector = 0;
00921
return position;
00922 }
00923
00924
00925
00934
00935 int StiKalmanTrackNode::propagate(
double xk,
int option,
int dir)
00936 {
00937
static int nCalls=0;
00938 nCalls++;
00939 assert(fDerivTestOn!=-10 || _state==kTNRotEnd ||_state>=kTNReady);
00940 _state = kTNProBeg;
00941
00942 mgP.x1=mFP._x; mgP.y1=mFP._y; mgP.cosCA1 =mFP._cosCA; mgP.sinCA1 =mFP._sinCA;
00943
double rho = mFP._curv;
00944 mgP.x2 = xk;
00945
00946 mgP.dx=mgP.x2-mgP.x1;
00947
double test = (dir)? mgP.dx:-mgP.dx;
00948
00949
00950
00951
double dsin = mFP._curv*mgP.dx;
00952 mgP.sinCA2=mgP.sinCA1 + dsin;
00953
00954
if (fabs(mgP.sinCA2)>kMaxSinEta)
return -4;
00955 mgP.cosCA2 = ::sqrt((1.-mgP.sinCA2)*(1.+mgP.sinCA2));
00956
00957 test = (2*dir-1)*mgP.dx*mgP.cosCA1;
00958
if (test<0) mgP.cosCA2 = -mgP.cosCA2;
00959
00960
int nIt = (mgP.cosCA2 <0)? 2:1;
00961
int ians = 0;
00962 StiNodePars save = mFP;
00963
for (
int iIt=0; iIt<nIt; iIt++) {
00964 ians = -1;
00965 mFP = save;
00966 mgP.cosCA2 = (!iIt)? fabs(mgP.cosCA2):-fabs(mgP.cosCA2);
00967 mgP.sumSin = mgP.sinCA1+mgP.sinCA2;
00968 mgP.sumCos = mgP.cosCA1+mgP.cosCA2;
00969
if (fabs(mgP.sumCos)<1e-6)
continue;
00970 mgP.dy = mgP.dx*(mgP.sumSin/mgP.sumCos);
00971 mgP.y2 = mgP.y1+mgP.dy;
00972
00973
00974 mgP.dl0 = mgP.cosCA1*mgP.dx+mgP.sinCA1*mgP.dy;
00975
double sind = mgP.dl0*rho;
00976
00977
if (fabs(dsin) < 0.02 && mgP.cosCA1 >0 && mgP.cosCA2 >0) {
00978 mgP.dl = mgP.dl0*(1.+sind*sind/6);
00979 }
else {
00980
double cosd = mgP.cosCA2*mgP.cosCA1+mgP.sinCA2*mgP.sinCA1;
00981 mgP.dl = atan2(sind,cosd)/rho;
00982 }
00983
00984 mFP._z += mgP.dl*mFP._tanl;
00985 mFP._y = mgP.y2;
00986 mFP._eta = nice(mFP._eta+rho*mgP.dl);
00987 mFP._x = mgP.x2;
00988 mFP._sinCA = mgP.sinCA2;
00989 mFP._cosCA = mgP.cosCA2;
00990 ians = locate();
00991
if (ians<=kEdgeZplus && ians>=0)
break;
00992 }
00993
if (ians>kEdgeZplus || ians<0)
return ians;
00994
if (mFP._x> kFarFromBeam) {
00995
if (fabs(mFP._eta)>kMaxEta)
return kEnded;
00996
if (mFP._x*mgP.cosCA2+mFP._y*mgP.sinCA2<=0)
return kEnded;
00997 }
00998 mFP._hz =
getHz();
00999 mFP._curv = mFP._hz*mFP._ptin;
01000 mPP() = mFP;
01001 _state = kTNProEnd;
01002
return ians;
01003 }
01004
01005
01006
int StiKalmanTrackNode::nudge(
StiHit *hitp)
01007 {
01008
StiHit *hit = hitp;
01009
if (!hit) hit = getHit();
01010
double deltaX = 0;
01011
if (hit) { deltaX = hit->x()-mFP._x;}
01012
else {
if (_detector) deltaX = _detector->getPlacement()->getNormalRadius()-mFP._x;}
01013
if(fabs(deltaX)>5)
return -1;
01014
if (fabs(deltaX) <1.e-3)
return 0;
01015
double deltaS = mFP._curv*(deltaX);
01016
double sCA2 = mFP._sinCA + deltaS;
01017
if (fabs(sCA2)>0.99)
return -2;
01018
double cCA2,deltaY,deltaL,sind;
01019
if (fabs(deltaS) < 1e-3 && fabs(mFP._eta)<1) {
01020 cCA2= mFP._cosCA - mFP._sinCA/mFP._cosCA*deltaS;
01021
if (cCA2> 1) cCA2= 1;
01022
if (cCA2<-1) cCA2=-1;
01023 deltaY = deltaX*(mFP._sinCA+sCA2)/(mFP._cosCA+cCA2);
01024 deltaL = deltaX*mFP._cosCA + deltaY*mFP._sinCA;
01025 sind = deltaL*mFP._curv;
01026 deltaL = deltaL*(1.+sind*sind/6);
01027 }
else {
01028 cCA2= sqrt((1.-sCA2)*(1.+sCA2));
01029
if (mFP._cosCA <0) cCA2 = -cCA2;
01030 deltaY = deltaX*(mFP._sinCA+sCA2)/(mFP._cosCA+cCA2);
01031 deltaL = deltaX*mFP._cosCA + deltaY*mFP._sinCA;
01032 sind = deltaL*mFP._curv;
01033 deltaL = asin(sind)/mFP._curv;
01034 }
01035
double deltaZ = mFP._tanl*(deltaL);
01036 mFP._sinCA = mgP.sinCA2 = sCA2;
01037 mFP._cosCA = mgP.cosCA2 = cCA2;
01038 mgP.sumSin = mgP.sinCA1+mgP.sinCA2;
01039 mgP.sumCos = mgP.cosCA1+mgP.cosCA2;
01040 mFP._x += deltaX;
01041 mFP._y += deltaY;
01042 mFP._z += deltaZ;
01043 mFP._eta += deltaL*mFP._curv;
01044 mgP.dx += deltaX;
01045 mgP.dy += deltaY;
01046 mgP.dl0 += deltaL;
01047 mgP.dl += deltaL;
01048
01049
01050
01051
if (fabs(mFP._sinCA)>=1) {
01052 LOG_DEBUG << Form(
"StiKalmanTrackNode::nudge WRONG WRONG WRONG sinCA=%g",mFP._sinCA)
01053 << endm;
01054 mFP.print();
01055
return -13;
01056 }
01057 assert(fabs(mFP._cosCA) <= 1.);
01058 mPP() = mFP;
01059
return 0;
01060 }
01061
01064 void StiKalmanTrackNode::propagateMtx()
01065 {
01066
01067
double fYE= mgP.dx*(1.+mgP.cosCA1*mgP.cosCA2+mgP.sinCA1*mgP.sinCA2)/(mgP.sumCos*mgP.cosCA2);
01068
01069
double fEC = mgP.dx/mgP.cosCA2;
01070
01071
double fYC=(mgP.dy*mgP.sinCA2+mgP.dx*mgP.cosCA2)/mgP.sumCos*fEC;
01072
01073
double dang = mgP.dl*mFP._curv;
01074
double C2LDX = mgP.dl*mgP.dl*(
01075 0.5*mgP.sinCA2*pow((1+pow(dang/2,2)*sinX(dang/2)),2) +
01076 mgP.cosCA2*dang*sinX(dang));
01077
01078
double fZC = mFP._tanl*C2LDX/mgP.cosCA2;
01079
01080
double dLdEta = mgP.dy/mgP.cosCA2;
01081
double fZE = mFP._tanl*dLdEta;
01082
01083
01084
double fZT= mgP.dl;
01085
double hz =
getHz(); fEC *=hz; fYC*=hz; fZC*=hz;
01086
01087
double ca =1, sa=0;
01088
if (mMtx().A[0][0]) { ca = mMtx().A[0][0]+1.;sa = mMtx().A[0][1];}
01089 mMtx().
reset();
01090
01091 mMtx().A[0][0] = -1;
01092 mMtx().A[1][0] = -mgP.sinCA2/mgP.cosCA2;
01093 mMtx().A[2][0] = -mFP._tanl /mgP.cosCA2;
01094 mMtx().A[3][0] = -mFP._curv /mgP.cosCA2;
01095
01096 mMtx().A[1][3]=fYE; mMtx().A[1][4]=fYC; mMtx().A[2][3]=fZE;
01097 mMtx().A[2][4]=fZC; mMtx().A[2][5]=fZT; mMtx().A[3][4]=fEC;
01098
if (sa) {
01099
double fYX = mMtx().A[1][0];
01100 mMtx().A[1][0] = fYX*ca-sa;
01101 mMtx().A[1][1] = fYX*sa+ca-1;
01102 }
01103 }
01104
01105
01106
01107
01110 void StiKalmanTrackNode::propagateError()
01111 {
01112
static int nCall=0; nCall++;
01113 Break(nCall);
01114 assert(fDerivTestOn!=-10 || _state==kTNProEnd);
01115
01116
if (debug() & 1)
01117 {
01118 LOG_DEBUG <<
"Prior Error:"
01119 <<
"cYY:"<<
mFE._cYY<<endm;
01120 LOG_DEBUG <<
"cZY:"<<
mFE._cZY<<
" cZZ:"<<
mFE._cZZ<<endm;
01121 LOG_DEBUG <<
"cEY:"<<
mFE._cEY<<
" cEZ:"<<
mFE._cEZ<<endm;
01122 LOG_DEBUG <<
"cPY:"<<
mFE._cPY<<
" cPZ:"<<
mFE._cPZ<<endm;
01123 LOG_DEBUG <<
"cTY:"<<
mFE._cTY<<
" cTZ:"<<
mFE._cTZ<<endm;
01124 }
01125 propagateMtx();
01126 errPropag6(mFE.A,mMtx().A,kNPars);
01127
int smallErr = !(mFE._cYY>1e-20 && mFE._cZZ>1e-20 && mFE._cEE>1e-20&& mFE._cPP>1.e-30&& mFE._cTT>1.e-20);
01128
if (smallErr) {
01129 LOG_INFO << Form(
"***SmallErr: cYY=%g cZZ=%g cEE=%g cCC=%g cTT=%g"
01130 ,mFE._cYY,mFE._cZZ,mFE._cEE,mFE._cPP,mFE._cTT) << endm;
01131 assert(mFE._cYY>0 && mFE._cZZ>0 && mFE._cEE>0 && mFE._cPP>0 && mFE._cTT>0);
01132 }
01133 assert(fabs(mFE._cXX)<1.e-6);
01134 assert(mFE._cYY*mFE._cZZ-mFE._cZY*mFE._cZY>0);
01135 mFE._cXX = mFE._cYX= mFE._cZX = mFE._cEX = mFE._cPX = mFE._cTX = 0;
01136 mFE.recov();
01137 mFE.check(
"StiKalmanTrackNode::propagateError");
01138
01139
#ifdef Sti_DEBUG
01140
if (debug() & 4) {
01141 PrPP(propagateError,C);
01142 TRMatrix F(kNPars,kNPars,f[0]); PrPP(propagateError,F);
01143
01144 C = TRSymMatrix(F,TRArray::kAxSxAT,C); PrPP(propagateError,C);
01145 TRSymMatrix C1(kNPars,mFE.A); PrPP(propagateError,C1);
01146 C1.Verify(C);
01147 }
01148
#endif
01149
if (debug() & 1)
01150 {
01151 LOG_DEBUG <<
"Post Error:"
01152 <<
"cYY:"<<mFE._cYY<<endm;
01153 LOG_DEBUG <<
"cZY:"<<mFE._cZY<<
" cZZ:"<<mFE._cZZ<<endm;
01154 LOG_DEBUG <<
"cEY:"<<mFE._cEY<<
" cEZ:"<<mFE._cEZ<<endm;
01155 LOG_DEBUG <<
"cCY:"<<mFE._cPY<<
" cCZ:"<<mFE._cPZ<<endm;
01156 LOG_DEBUG <<
"cTY:"<<mFE._cTY<<
" cTZ:"<<mFE._cTZ<<endm;
01157 }
01158
01159
if (_hit) setHitErrors();
01160
01161
01162 mPE() = mFE;
01163 _state = kTNReady;
01164 }
01165
01166
01182
01183 double StiKalmanTrackNode::pathLToNode(
const StiKalmanTrackNode *
const oNode)
01184 {
01185
const StThreeVector<double> delta =
01186 getGlobalPoint() - oNode->
getGlobalPoint();
01187
double R =
getCurvature();
01188
01189
return length(delta, R);
01190 }
01191
01192
01193
inline double StiKalmanTrackNode::length(
const StThreeVector<double>& delta,
double curv)
01194 {
01195
01196
double m = delta.perp();
01197
double as = 0.5*m*curv;
01198
double lxy=0;
01199
if (fabs(as)<0.01) { lxy = m*(1.+as*as/24);}
01200
else { lxy = 2.*asin(as)/curv;}
01201
return sqrt(lxy*lxy+delta.z()*delta.z());
01202 }
01203
01204
01218 double StiKalmanTrackNode::evaluateChi2(
const StiHit * hit)
01219 {
01220
double r00, r01,r11;
01221
01222
01223
double dsin =mFP._curv*(hit->x()-mFP._x);
01224
if (fabs(mFP._sinCA+dsin)>0.99 )
return 1e41;
01225
if (fabs(mFP._eta) >kMaxEta)
return 1e41;
01226
if (fabs(mFP._curv) >kMaxCur)
return 1e41;
01227
01228 setHitErrors(hit);
01229 r00=mHrr.hYY+
mFE._cYY;
01230 r01=mHrr.hZY+
mFE._cZY;
01231 r11=mHrr.hZZ+
mFE._cZZ;
01232
01233
#ifdef Sti_DEBUG
01234
TRSymMatrix R(2,
01235 r00,
01236 r01, r11);
01237
#endif
01238
_det=r00*r11 - r01*r01;
01239
if (_det<r00*r11*1.e-5) {
01240 LOG_DEBUG << Form(
"StiKalmanTrackNode::evalChi2 *** zero determinant %g",_det)<< endm;
01241
return 1e60;
01242 }
01243
double tmp=r00; r00=r11; r11=tmp; r01=-r01;
01244
double deltaX = hit->x()-mFP._x;
01245
double deltaL = deltaX/mFP._cosCA;
01246
double deltaY = mFP._sinCA *deltaL;
01247
double deltaZ = mFP._tanl *deltaL;
01248
double dyt=(mFP._y-hit->y()) + deltaY;
01249
double dzt=(mFP._z-hit->z()) + deltaZ;
01250
double cc= (dyt*r00*dyt + 2*r01*dyt*dzt + dzt*r11*dzt)/_det;
01251
01252
#ifdef Sti_DEBUG
01253
if (debug() & 4) {
01254 TRSymMatrix G(R,TRArray::kInverted);
01255 TRVector r(2,hit->y()-mFP._y,hit->z()-mFP._z);
01256 Double_t chisq = G.Product(r,TRArray::kATxSxA);
01257 Double_t diff = chisq - cc;
01258 Double_t sum = chisq + cc;
01259
if (diff > 1e-7 || (sum > 2. && (2 * diff ) / sum > 1e-7)) {
01260 LOG_DEBUG <<
"Failed:\t" << chisq <<
"\t" << cc <<
"\tdiff\t" << diff << endm;
01261 }
01262 }
01263
#endif
01264
if (debug() & 8) {comment += Form(
" chi2 = %6.2f",cc);}
01265
return cc;
01266 }
01267
01268
int StiKalmanTrackNode::isEnded()
const
01269
{
01270
01271
if(fabs(mFP._eta )<=kMaxEta)
return 0;
01272
return 1;
01273 }
01274
01275
int StiKalmanTrackNode::isDca()
const
01276
{
01277
return (fabs(mFP._x)<=0);
01278 }
01279
01280
01289 void StiKalmanTrackNode::propagateMCS(
StiKalmanTrackNode * previousNode,
const StiDetector * tDet)
01290 {
01291 propagateCurv(previousNode);
01292
double pt =
getPt();
01293
#if 0
01294
if (pt>=1e3) {
01295 mPP() = mFP; mPE() =
mFE;
01296
return;
01297 }
01298
#endif
01299
double relRadThickness;
01300
01301
double pL1,pL2,pL3,d1,d2,d3,dxEloss=0;
01302 pL1=previousNode->
pathlength()/2.;
01303
01304 pL3=
pathlength()/2.;
01305
01306 pL2=
pathLToNode(previousNode);
01307
if (pL1<0) pL1=0;
01308
if (pL2<0) pL2=0;
01309
if (pL3<0) pL3=0;
01310
double x0p =-1;
01311
double x0Gas=-1;
01312
double x0=-1;
01313 d1 = previousNode->
getDensity();
01314 x0p = previousNode->
getX0();
01315 d3 = tDet->
getMaterial()->getDensity();
01316 x0 = tDet->
getMaterial()->getX0();
01317
01318
01319
if (pL2> (pL1+pL3))
01320 {
01321 pL2=pL2-pL1-pL3;
01322
if (mgP.dx>0)
01323 {
01324 x0Gas = tDet->
getGas()->getX0();
01325 d2 = tDet->
getGas()->getDensity();
01326 }
01327
else
01328 {
01329 x0Gas = previousNode->
getGasX0();
01330 d2 = previousNode->
getGasDensity();
01331 }
01332 relRadThickness = 0.;
01333 dxEloss = 0;
01334
if (x0p>0.)
01335 {
01336 relRadThickness += pL1/x0p;
01337 dxEloss += d1*pL1;
01338 }
01339
if (x0Gas>0.)
01340 {
01341 relRadThickness += pL2/x0Gas;
01342 dxEloss += d2*pL2;
01343 }
01344
if (x0>0.)
01345 {
01346 relRadThickness += pL3/x0;
01347 dxEloss += d3*pL3;
01348 }
01349 }
01350
else
01351 {
01352 relRadThickness = 0.;
01353 dxEloss = 0;
01354
if (x0p>0.)
01355 {
01356 relRadThickness += pL1/x0p;
01357 dxEloss += d1*pL1;
01358 }
01359
if (x0>0.)
01360 {
01361 relRadThickness += pL3/x0;
01362 dxEloss += d3*pL3;
01363 }
01364 }
01365
if (pt > 0.350 && TMath::Abs(
getHz()) < 1e-3) pt = 0.350;
01366
double p2=(1.+mFP._tanl*mFP._tanl)*pt*pt;
01367
double m=StiKalmanTrackFinderParameters::instance()->massHypothesis();
01368
double m2=m*m;
01369
double e2=p2+m2;
01370
double beta2=p2/e2;
01371
01372
double theta2=mcs2(relRadThickness,beta2,p2);
01373
01374
double pti = mFP._ptin, tanl = mFP._tanl;
01375
01376
double cos2Li = (1.+ tanl*tanl);
01377
01378
mFE._cEE += cos2Li *theta2;
01379
mFE._cPP += tanl*tanl*pti*pti *theta2;
01380
mFE._cTP += pti*tanl*cos2Li *theta2;
01381
mFE._cTT += cos2Li*cos2Li *theta2;
01382
01383
#ifdef STI_ERROR_TEST
01384
testError(
mFE.A,1);
01385
#endif // STI_ERROR_TEST
01386
double dE=0;
01387
double sign = (mgP.dx>0)? 1:-1;
01388
01389
01390 StiElossCalculator * calculator = tDet->
getElossCalculator();
01391
double eloss = calculator->calculate(1.,m, beta2);
01392 dE = sign*dxEloss*eloss;
01393
if (TMath::Abs(dE)>0)
01394 {
01395
if (debug()) {
01396 commentdEdx = Form(
"%6.3g cm(%5.2f) %6.3g keV %6.3f GeV",mgP.dx,100*relRadThickness,1e6*dE,TMath::Sqrt(e2)-m);
01397 }
01398
double correction =1. + ::sqrt(e2)*dE/p2;
01399
if (correction>1.1) correction = 1.1;
01400
else if (correction<0.9) correction = 0.9;
01401 mFP._curv = mFP._curv*correction;
01402 mFP._ptin = mFP._ptin*correction;
01403 }
01404 mPP() = mFP; mPE() =
mFE;
01405
01406 }
01407
01408
01428
01429 int StiKalmanTrackNode::updateNode()
01430 {
01431
static int nCall=0; nCall++;
01432 assert(fDerivTestOn!=-10 || _state>=kTNReady);
01433 _state = kTNFitBeg;
01434
#ifdef STI_ERROR_TEST
01435
testError(
mFE.A,0);
01436
#endif //STI_ERROR_TEST
01437
assert(
mFE._cXX<1e-8);
01438
double r00,r01,r11;
01439 r00 = mHrr.hYY +
mFE._cYY;
01440 r01 = mHrr.hZY +
mFE._cZY;
01441 r11 = mHrr.hZZ +
mFE._cZZ;
01442
#ifdef Sti_DEBUG
01443
TRSymMatrix V(2,mHrr.hYY,
01444 mHrr.hZY, mHrr.hZZ);
01445 TRSymMatrix R1(2,r00,
01446 r01, r11);
01447
static const TRMatrix H(2,5, 1., 0., 0., 0., 0.,
01448 0., 1., 0., 0., 0.);
01449
#endif
01450
_det=r00*r11 - r01*r01;
01451
if (!finite(_det) || _det<(r00*r11)*1.e-5) {
01452 LOG_DEBUG << Form(
"StiKalmanTrackNode::updateNode *** zero determinant %g",_det)
01453 << endm;
01454
return -11;
01455 }
01456
01457
double tmp=r00; r00=r11/_det; r11=tmp/_det; r01=-r01/_det;
01458
01459
double k00=
mFE._cYY*r00+
mFE._cZY*r01, k01=
mFE._cYY*r01+
mFE._cZY*r11;
01460
double k10=
mFE._cZY*r00+
mFE._cZZ*r01, k11=
mFE._cZY*r01+
mFE._cZZ*r11;
01461
double k20=
mFE._cEY*r00+
mFE._cEZ*r01, k21=
mFE._cEY*r01+
mFE._cEZ*r11;
01462
double k30=
mFE._cPY*r00+
mFE._cPZ*r01, k31=
mFE._cPY*r01+
mFE._cPZ*r11;
01463
double k40=
mFE._cTY*r00+
mFE._cTZ*r01, k41=
mFE._cTY*r01+
mFE._cTZ*r11;
01464
double dyt = getHit()->y() - mFP._y;
01465
double dzt = getHit()->z() - mFP._z;
01466
double dp3 = k30*dyt + k31*dzt;
01467
double dp2 = k20*dyt + k21*dzt;
01468
double dp4 = k40*dyt + k41*dzt;
01469
#ifdef Sti_DEBUG
01470
double dp0 = k00*dyt + k01*dz;
01471
double dp1 = k10*dyt + k11*dz;
01472
if (debug() & 4) {
01473 PrPP(
updateNode,R1);
01474 PrPP(
updateNode,V);
01475 }
01476 TRSymMatrix C(kNPars,
mFE.A);
01477 TRSymMatrix R(H,TRArray::kAxSxAT,C);
01478 R += V;
01479 TRSymMatrix G(R,TRArray::kInverted);
01480
if (debug() & 4) {
01481 PrPP(
updateNode,C);
01482 PrPP(
updateNode,R);
01483 PrPP(
updateNode,G);
01484 }
01485
01486 TRMatrix T(C,TRArray::kSxAT,H);
01487 TRMatrix K(T,TRArray::kAxS,G);
01488 TRMatrix K1(5,2,
01489 k00, k01,
01490 k10, k11,
01491 k20, k21,
01492 k30, k31,
01493 k40, k41);
01494
if (debug() & 4) {
01495 PrPP(
updateNode,T);
01496 PrPP(
updateNode,K1);
01497 PrPP(
updateNode,K);
01498 K1.Verify(K);
01499 }
01500 TRVector dR(2,dyt, dzt);
01501 TRVector dP1(5, dp0, dp1, dp2, dp3, dp4);
01502 TRVector dP(K,TRArray::kAxB,dR);
01503
if (debug() & 4) dP1.Verify(dP);
01504
#endif
01505
double eta = nice(mFP._eta + dp2);
01506
if (fabs(eta)>kMaxEta)
return -14;
01507
double pti = mFP._ptin + dp3;
01508
double cur = pti*
getHz();
01509
if (fabs(cur)>kMaxCur)
return -16;
01510 assert(finite(cur));
01511
double tanl = mFP._tanl + dp4;
01512
01513
double p0 = mFP._y + k00*dyt + k01*dzt;
01514
01515
if (fabs(p0)>kMaxR)
01516 {
01517 LOG_DEBUG <<
"updateNode()[1] -W- _y:"<<mFP._y<<
" _z:"<<mFP._z<<endm;
01518
return -12;
01519 }
01520
double p1 = mFP._z + k10*dyt + k11*dzt;
01521
if (fabs(p1)>kMaxZ)
01522 {
01523 LOG_DEBUG <<
"updateNode()[2] -W- _y:"<<mFP._y<<
" _z:"<<mFP._z<<endm;
01524
return -13;
01525 }
01526
01527
double sinCA = sin(eta);
01528
01529
01530 mFP._y = p0;
01531 mFP._z = p1;
01532 mFP._eta = eta;
01533 mFP._ptin = pti;
01534 mFP._curv = cur;
01535 mFP._tanl = tanl;
01536 mFP._sinCA = sinCA;
01537 mFP._cosCA = ::sqrt((1.-mFP._sinCA)*(1.+mFP._sinCA));
01538 mFP._hz =
getHz();
01539
01540
01541
double c00=
mFE._cYY;
01542
double c10=
mFE._cZY, c11=
mFE._cZZ;
01543
double c20=
mFE._cEY, c21=
mFE._cEZ;
01544
double c30=
mFE._cPY, c31=
mFE._cPZ;
01545
double c40=
mFE._cTY, c41=
mFE._cTZ;
01546
mFE._cYY-=k00*c00+k01*c10;
01547
mFE._cZY-=k10*c00+k11*c10;
mFE._cZZ-=k10*c10+k11*c11;
01548
mFE._cEY-=k20*c00+k21*c10;
mFE._cEZ-=k20*c10+k21*c11;
mFE._cEE-=k20*c20+k21*c21;
01549
mFE._cPY-=k30*c00+k31*c10;
mFE._cPZ-=k30*c10+k31*c11;
mFE._cPE-=k30*c20+k31*c21;
mFE._cPP-=k30*c30+k31*c31;
01550
mFE._cTY-=k40*c00+k41*c10;
mFE._cTZ-=k40*c10+k41*c11;
mFE._cTE-=k40*c20+k41*c21;
mFE._cTP-=k40*c30+k41*c31;
mFE._cTT-=k40*c40+k41*c41;
01551
01552
if (
mFE._cYY >= mHrr.hYY ||
mFE._cZZ >= mHrr.hZZ) {
01553 LOG_DEBUG << Form(
"StiKalmanTrackNode::updateNode *** _cYY >= hYY || _cZZ >= hZZ %g %g %g %g"
01554 ,
mFE._cYY,mHrr.hYY,
mFE._cZZ,mHrr.hZZ)<< endm;
01555
return -14;
01556 }
01557
if (
mFE.check())
return -14;
01558
01559
#ifdef Sti_DEBUG
01560
TRSymMatrix W(H,TRArray::kATxSxA,G);
01561 TRSymMatrix C0(C);
01562 C0 -= TRSymMatrix(C,TRArray::kRxSxR,W);
01563 TRSymMatrix C1(kNPars,
mFE.A);
01564
if (debug() & 4) {
01565 PrPP(
updateNode,W);
01566 PrPP(
updateNode,C0);
01567 PrPP(
updateNode,C1);
01568 C1.Verify(C0);
01569 }
01570
01571
01572
01573 TRMatrix A(K,TRArray::kAxB,H);
01574 TRMatrix P(TRArray::kUnit,kNPars);
01575 P -= A;
01576 TRSymMatrix C2(P,TRArray::kAxSxAT,C);
01577 TRSymMatrix Y(K,TRArray::kAxSxAT,V);
01578 C2 += Y;
01579
if (debug() & 4) {
01580 PrPP(
updateNode,C2); PrPP(
updateNode,Y); PrPP(
updateNode,C2);
01581 C2.Verify(C0);
01582 C2.Verify(C1);
01583 }
01584
#endif
01585
if (debug() & 8) PrintpT(
"U");
01586 _state = kTNFitEnd;
01587
return 0;
01588 }
01589
01590
01602 int StiKalmanTrackNode::rotate (
double alpha)
01603 {
01604 assert(fDerivTestOn!=-10 || _state>=kTNReady);
01605 mMtx().A[0][0]=0;
01606
if (fabs(alpha)<1.e-6)
return 0;
01607 _state = kTNRotBeg;
01608 _alpha += alpha;
01609 _alpha = nice(_alpha);
01610
01611
01612
double xt1=mFP._x;
01613
double yt1=mFP._y;
01614 mgP.sinCA1 = mFP._sinCA;
01615 mgP.cosCA1 = mFP._cosCA;
01616
double ca = cos(alpha);
01617
double sa = sin(alpha);
01618 mFP._x = xt1*ca + yt1*sa;
01619 mFP._y= -xt1*sa + yt1*ca;
01620 mFP._cosCA = mgP.cosCA1*ca+mgP.sinCA1*sa;
01621 mFP._sinCA = -mgP.cosCA1*sa+mgP.sinCA1*ca;
01622
double nor = 0.5*(mFP._sinCA*mFP._sinCA+mFP._cosCA*mFP._cosCA +1);
01623 mFP._cosCA /= nor;
01624 mFP._sinCA /= nor;
01625
01626 mFP._eta= nice(mFP._eta-alpha);
01627 mFP._sinCA = sin(mFP._eta);
01628 mFP._cosCA = cos(mFP._eta);
01629
#ifdef Sti_DEBUG
01630
TRSymMatrix C(kNPars,
mFE.A);
01631
if (debug() & 4) {PrPP(
rotate,C);}
01632
#endif
01633
01634 assert(fabs(mFP._sinCA)<=1.);
01635 assert(fabs(mFP._cosCA)<=1.);
01636 memset(mMtx().A,0,
sizeof(mMtx()));
01637 mMtx().A[0][0]= ca-1;
01638 mMtx().A[0][1]= sa;
01639 mMtx().A[1][0]=-sa;
01640 mMtx().A[1][1]= ca-1;
01641
01642 _state = kTNRotEnd;
01643 mPP() = mFP;
01644
return 0;
01645 }
01646
01647
01648
01651 ostream&
operator<<(ostream& os,
const StiKalmanTrackNode& n)
01652 {
01653
const StiDetector *det = n.getDetector();
01654
if (det) os <<
"Det:"<<n.getDetector()->getName();
01655
else os <<
"Det:UNknown";
01656 os <<
" a:" << 180*n._alpha/M_PI<<
" degs"
01657 <<
"\tx:" << n.mFP._x
01658 <<
" p0:" << n.mFP._y
01659 <<
" p1:" << n.mFP._z
01660 <<
" p2:" << n.mFP._eta
01661 <<
" p3:" << n.mFP._ptin
01662 <<
" p4:" << n.mFP._tanl
01663 <<
" c00:" <<n.mFE._cYY<<
" c11:"<<n.mFE._cZZ
01664 <<
" pT:" << n.getPt() << endl;
01665
if (n.debug() & 2) {
01666
StiHit * hit = n.getHit();
01667
if (hit) os <<
"\thas hit with chi2 = " << n.getChi2()
01668 <<
" n:"<<n.hitCount
01669 <<
" null:"<<n.nullCount
01670 << endl<<
"\t hit:"<<*hit;
01671 }
01672
else os << endl;
01673
return os;
01674 }
01675
01676
01677
double StiKalmanTrackNode::getWindowY()
01678 {
01679
const StiDetector * detector = getDetector();
01680
const StiTrackingParameters * parameters = detector->getTrackingParameters();
01681
double searchWindowScale = parameters->getSearchWindowScale();
01682
double minSearchWindow = parameters->getMinSearchWindow();
01683
double maxSearchWindow = parameters->getMaxSearchWindow();
01684
01685
const StiHitErrorCalculator * calc = detector->getHitErrorCalculator();
01686
double myEyy,myEzz;
01687 calc->calculateError(&mFP,myEyy,myEzz);
01688
double window = searchWindowScale*::sqrt(
mFE._cYY+myEyy);
01689
if (window<minSearchWindow) window = minSearchWindow;
01690
else if (window>maxSearchWindow) window = maxSearchWindow;
01691
return window;
01692 }
01693
01694
01695
double StiKalmanTrackNode::getWindowZ()
01696 {
01697
const StiDetector * detector = getDetector();
01698
const StiTrackingParameters * parameters = detector->getTrackingParameters();
01699
double searchWindowScale = parameters->getSearchWindowScale();
01700
double minSearchWindow = parameters->getMinSearchWindow();
01701
double maxSearchWindow = parameters->getMaxSearchWindow();
01702
01703
const StiHitErrorCalculator * calc = detector->getHitErrorCalculator();
01704
double myEyy,myEzz;
01705 calc->calculateError(&mFP,myEyy,myEzz);
01706
01707
double window = searchWindowScale*::sqrt(
mFE._cZZ+myEzz);
01708
if (window<minSearchWindow) window = minSearchWindow;
01709
else if (window>maxSearchWindow) window = maxSearchWindow;
01710
return window;
01711 }
01712
01713
01714 StThreeVector<double>
StiKalmanTrackNode::getHelixCenter()
const
01715
{
01716
if (mFP._curv==0)
throw logic_error(
"StiKalmanTrackNode::getHelixCenter() -F- _curv==0 ");
01717
double xt0 = mFP._x-mFP._sinCA/mFP._curv;
01718
double yt0 = mFP._y+mFP._cosCA/(mFP._curv);
01719
double zt0 = mFP._z+mFP._tanl*asin(mFP._sinCA)/mFP._curv;
01720
double cosAlpha = cos(_alpha);
01721
double sinAlpha = sin(_alpha);
01722
return (StThreeVector<double>(cosAlpha*xt0-sinAlpha*yt0,sinAlpha*xt0+cosAlpha*yt0,zt0));
01723 }
01724
01725
int StiKalmanTrackNode::locate()
01726 {
01727
enum {kNStd = 5};
01728
int position;
01729
double yOff, yAbsOff, detHW, detHD,edge,innerY, outerY, innerZ, outerZ, zOff, zAbsOff;
01730
01731
const StiDetector *tDet = getDetector();
01732
if (!tDet)
return 0;
01733
const StiPlacement *place = tDet->
getPlacement();
01734
const StiShape *sh = tDet->
getShape();
01735
01736
if (fabs(mFP._z)>kMaxZ || fabs(mFP._y)> kMaxR)
return -1;
01737 edge = 2.;
01738
if (mFP._x<50.) edge = 0.3;
01739
01740 Int_t shapeCode = sh->
getShapeCode();
01741
switch (shapeCode) {
01742
case kDisk:
01743
case kCylindrical:
01744 yOff = nice(_alpha - place->getLayerAngle());
01745 yAbsOff = fabs(yOff);
01746 yAbsOff -=kNStd*sqrt((
mFE._cXX+
mFE._cYY)/(mFP._x*mFP._x+mFP._y*mFP._y));
01747
if (yAbsOff<0) yAbsOff=0;
01748 detHW = ((
StiCylindricalShape *) sh)->getOpeningAngle()/2.;
01749 innerY = outerY = detHW;
01750
break;
01751
case kPlanar:
01752
default:
01753 yOff = mFP._y - place->getNormalYoffset();
01754 yAbsOff = fabs(yOff) - kNStd*sqrt(
mFE._cYY);
01755
if (yAbsOff<0) yAbsOff=0;
01756 detHW = sh->
getHalfWidth();
01757 innerY = detHW - edge;
01758
01759
01760 outerY = innerY + edge;
01761
break;
01762 }
01763 zOff = mFP._z - place->getZcenter();
01764 zAbsOff = fabs(zOff);
01765 detHD = sh->
getHalfDepth();
01766 innerZ = detHD - edge;
01767 outerZ = innerZ + edge;
01768
if (yAbsOff<innerY && zAbsOff<innerZ)
01769 position = kHit;
01770
else if (yAbsOff>outerY && (yAbsOff-outerY)>(zAbsOff-outerZ))
01771
01772
01773 position = yOff>0 ? kMissPhiPlus : kMissPhiMinus;
01774
else if (zAbsOff>outerZ && (zAbsOff-outerZ)>(yAbsOff-outerY))
01775
01776 position = zOff>0 ? kMissZplus : kMissZminus;
01777
else if ((yAbsOff-innerY)>(zAbsOff-innerZ))
01778
01779 position = yOff>0 ? kEdgePhiPlus : kEdgePhiMinus;
01780
else
01781
01782 position = zOff>0 ? kEdgeZplus : kEdgeZminus;
01783
if (debug()&8) {
01784 comment += ::Form(
"R %8.3f y/z %8.3f/%8.3f",
01785 mFP._x, mFP._y, mFP._z);
01786
if (position>kEdgeZplus || position<0)
01787 comment += ::Form(
" missed %2d y0/z0 %8.3f/%8.3f dY/dZ %8.3f/%8.3f",
01788 position, yOff, zOff, detHW, detHD);
01789 }
01790
return position;
01791 }
01792
01793 void StiKalmanTrackNode::initialize(
StiHit *h)
01794 {
01795
reset();
01796 setHit(h);
01797 _detector = h->detector();
01798 _alpha = _detector->getPlacement()->getNormalRefAngle();
01799 mFP._sinCA = 0.6;
01800 mFP._cosCA = 0.8;
01801 mFP._x = h->x();
01802 mFP._y = h->y();
01803 mFP._z = h->z();
01804 mFP._hz =
getHz();
01805
resetError();
01806 mPP() = mFP;
01807 setHitErrors();
01808 _state = kTNInit;
01809 setChi2(0.1);
01810 }
01811
01812 StiKalmanTrackNode::StiKalmanTrackNode(
const StiKalmanTrackNode &n)
01813 {
01814 _ext=0; _inf=0 ; *
this = n;
01815 }
01816
01817
const StiKalmanTrackNode& StiKalmanTrackNode::operator=(
const StiKalmanTrackNode &n)
01818 {
01819 StiTrackNode::operator=(n);
01820 memcpy(_beg,n.
_beg,_end-_beg+1);
01821
if (n.
_ext) { extend();*_ext = *n.
_ext;}
01822
else {
if(_ext) _ext->reset(); }
01823
if (n.
_inf) { extinf();*_inf = *n.
_inf;}
01824
else {
if(_inf) {
BFactory::Free(_inf); _inf=0;}}
01825
return *
this;
01826 }
01827
01828
void StiKalmanTrackNode::setHitErrors(
const StiHit *hit)
01829 {
01830
if (!hit) hit = _hit;
01831 assert(hit);
01832 StiTrackNodeHelper::getHitErrors(hit,&mFP,&mHrr);
01833 }
01834
01835 StiHitErrs StiKalmanTrackNode::getGlobalHitErrs(
const StiHit *hit)
const
01836
{
01837 StiHitErrs hr;
01838 StiTrackNodeHelper::getHitErrors(hit,&mFP,&hr);
01839 hr.rotate(_alpha);
01840
return hr;
01841 }
01842
#if 1
01843
01844
int StiKalmanTrackNode::testError(
double *emx,
int begend)
01845 {
01846
01847
01848
01849
01850
static int nCall=0; nCall++;
01851
static const double dia[6] = { 1000.,1000., 1000.,1000.,1000,1000.};
01852
static double emxBeg[kNErrs];
01853
01854
if (!begend) { memcpy(emxBeg,emx,
sizeof(emxBeg));}
01855
int ians=0,j1,j2,jj;
01856
for (j1=0; j1<5;j1++){
01857 jj = idx55[j1][j1];
01858
if (!(emx[jj]>0)) {;
01859 LOG_DEBUG << Form(
"<StiKalmanTrackNode::testError> Negative diag %g[%d][%d]",emx[jj],j1,j1)
01860 << endm;
01861
continue;}
01862
if (emx[jj]<=10*dia[j1] )
continue;
01863 assert(finite(emx[jj]));
01864 LOG_DEBUG << Form(
"<StiKalmanTrackNode::testError> Huge diag %g[%d][%d]",emx[jj],j1,j1)
01865 << endm;
01866
continue;
01867
01868
01869 }
01870
for (j1=0; j1< 5;j1++){
01871
for (j2=0; j2<j1;j2++){
01872 jj = idx55[j1][j2];
01873 assert(finite(emx[jj]));
01874
double cormax = emx[idx55[j1][j1]]*emx[idx55[j2][j2]];
01875
if (emx[jj]*emx[jj]<cormax)
continue;
01876 cormax= sqrt(cormax);
01877
01878 }}
01879
return ians;
01880 }
01881
#endif//0
01882
01883
void StiKalmanTrackNode::numeDeriv(
double val,
int kind,
int shape,
int dir)
01884 {
01885
double maxStep[kNPars]={0.1,0.1,0.1,0.01,0.001,0.01};
01886
if (fDerivTestOn<0)
return;
01887 gCurrShape = shape;
01888 fDerivTestOn=-1;
01889
double save[20];
01890
StiKalmanTrackNode myNode;
01891
double *pars = &myNode.
mFP._x;
01892
int state=0;
01893 saveStatics(save);
01894
if (fabs(mFP._curv)> 0.02)
goto FAIL;
01895
int ipar;
01896
for (ipar=1;ipar<kNPars;ipar++)
01897 {
01898
for (
int is=-1;is<=1;is+=2) {
01899 myNode = *
this;
01900 backStatics(save);
01901
double step = 0.1*sqrt((
mFE.A)[idx66[ipar][ipar]]);
01902
if (step>maxStep[ipar]) step = maxStep[ipar];
01903
01904
01905 pars[ipar] +=step*is;
01906
01907 myNode.
mFP._sinCA = sin(myNode.
mFP._eta);
01908
if (fabs(myNode.
mFP._sinCA) > 0.9)
goto FAIL;
01909 myNode.
mFP._cosCA = cos(myNode.
mFP._eta);
01910
01911
switch (kind) {
01912
case 1:
01913 state = myNode.
propagate(val,shape,dir);
break;
01914
case 2:
01915 state = myNode.
rotate(val);
break;
01916
default: assert(0);
01917 }
01918
if(state )
goto FAIL;
01919
01920
for (
int jpar=1;jpar<kNPars;jpar++) {
01921
if (is<0) {
01922 fDerivTest[jpar][ipar]= pars[jpar];
01923 }
else {
01924
double tmp = fDerivTest[jpar][ipar];
01925 fDerivTest[jpar][ipar] = (pars[jpar]-tmp)/(2.*step);
01926
if (ipar==jpar) fDerivTest[jpar][ipar]-=1.;
01927 }
01928 }
01929 }
01930 }
01931 fDerivTestOn=1;backStatics(save);
return;
01932 FAIL:
01933 fDerivTestOn=0;backStatics(save);
return;
01934 }
01935
01936
int StiKalmanTrackNode::testDeriv(
double *der)
01937 {
01938
if (fDerivTestOn!=1)
return 0;
01939
double *num = fDerivTest[0];
01940
int nerr = 0;
01941
for (
int i=1;i<kNErrs;i++) {
01942
int ipar = i/kNPars;
01943
int jpar = i%kNPars;
01944
if (ipar==jpar)
continue;
01945
if (ipar==0)
continue;
01946
if (jpar==0)
continue;
01947
double dif = fabs(num[i]-der[i]);
01948
if (fabs(dif) <= 1.e-5)
continue;
01949
if (fabs(dif) <= 0.2*0.5*fabs(num[i]+der[i]))
continue;
01950 nerr++;
01951 LOG_DEBUG << Form(
"***Wrong deriv [%d][%d] = %g %g %g",ipar,jpar,num[i],der[i],dif)
01952 << endm;
01953 }
01954 fDerivTestOn=0;
01955
return nerr;
01956 }
01957
01958
void StiKalmanTrackNode::saveStatics(
double *sav)
01959 {
01960 sav[ 0]=mgP.x1;
01961 sav[ 1]=mgP.x2;
01962 sav[ 2]=mgP.y1;
01963 sav[ 3]=mgP.y2;
01964 sav[ 5]=mgP.dx;
01965 sav[ 6]=mgP.cosCA1;
01966 sav[ 7]=mgP.sinCA1;
01967 sav[ 8]=mgP.cosCA2;
01968 sav[ 9]=mgP.sinCA2;
01969 sav[10]=mgP.sumSin;
01970 sav[11]=mgP.sumCos;
01971 sav[14]=mgP.dl;
01972 sav[15]=mgP.dl0;
01973 sav[16]=mgP.dy;
01974 }
01975
01976
void StiKalmanTrackNode::backStatics(
double *sav)
01977 {
01978 mgP.x1= sav[ 0];
01979 mgP.x2= sav[ 1];
01980 mgP.y1= sav[ 2];
01981 mgP.y2= sav[ 3];
01982 mgP.dx= sav[ 5];
01983 mgP.cosCA1= sav[ 6];
01984 mgP.sinCA1= sav[ 7];
01985 mgP.cosCA2= sav[ 8];
01986 mgP.sinCA2= sav[ 9];
01987 mgP.sumSin= sav[10];
01988 mgP.sumCos= sav[11];
01989 mgP.dl= sav[14];
01990 mgP.dl0= sav[15];
01991 mgP.dy= sav[16];
01992 }
01993
01994
void StiKalmanTrackNode::PrintpT(Char_t *opt) {
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006 Double_t dpTOverpT = 100*TMath::Sqrt(
mFE._cPP/(mFP._ptin*mFP._ptin));
02007
if (dpTOverpT > 9999.9) dpTOverpT = 9999.9;
02008 comment += ::Form(
" %s pT %8.3f+-%6.1f sy %6.4f",opt,
getPt(),dpTOverpT,TMath::Sqrt(
mFE._cYY));
02009 }
02010
02011
void StiKalmanTrackNode::PrintStep() {
02012 LOG_INFO << comment <<
"\t" << commentdEdx << endm;
02013 ResetComment();
02014 }
02015
02016 int StiKalmanTrackNode::print(
const char *opt)
const
02017
{
02018
static const char *txt =
"xyzeptchXYZEPTCH";
02019
static const char *hhh =
"uvwUVW";
02020
static const char *HHH =
"xyzXYZ";
02021
if (!opt || !opt[0]) opt =
"2xh";
02022
StiHit *hit = getHit();
02023
if (strchr(opt,
'h') && !hit)
return 0;
02024 TString ts;
02025
if (!isValid()) ts+=
"*";
02026
if (hit) {ts+=(getChi2()>1e3)?
"h":
"H";}
02027 LOG_DEBUG << Form(
"%p(%s)",(
void*)
this,ts.Data());
02028
if (strchr(opt,
'2')) LOG_DEBUG << Form(
"\t%s=%g",
"ch2",getChi2());
02029
02030
for (
int i=0;txt[i];i++) {
02031
if (!strchr(opt,txt[i]))
continue;
02032
int j = i%8;
02033
double val=0,err=0;
02034
if (i<=8 || i>11) {
02035 val = mFP[j];
02036
int jj = idx66[j][j];
02037 err=0;
02038
if (j<6) {err = sqrt(fabs(
mFE.A[jj]));
if (
mFE.A[jj]<0) err*= -1;}
02039 }
else {
02040
switch (j) {
02041
case 0: val = x_g();
break;
02042
case 1: val = y_g();
break;
02043
case 2: val = z_g();
break;
02044
case 3: val = getPsi();
break;
02045 } }
02046 LOG_DEBUG << Form(
"\t%c=%g",txt[i],val);
02047
if (err) LOG_DEBUG << Form(
"(%6.1g)",err);
02048 }
02049
02050
for (
int i=0;hit && hhh[i];i++) {
02051
if (!strchr(opt,hhh[i]))
continue;
02052
double val=0,err=0;
02053
switch(i) {
02054
case 0:val = hit->x();
break;
02055
case 1:val = hit->y(); err = ::sqrt(getEyy());
break;
02056
case 2:val = hit->z(); err = ::sqrt(getEzz());
break;
02057
case 3:val = hit->x_g();
break;
02058
case 4:val = hit->y_g();
break;
02059
case 5:val = hit->z_g(); err = ::sqrt(getEzz());
break;
02060 }
02061 LOG_DEBUG << Form(
"\th%c=%g",HHH[i],val);
02062
if (err) LOG_DEBUG << Form(
"(%6.1g)",err);
02063 }
02064 LOG_DEBUG << endm;
02065
return 1;
02066 }
02067
02068 StiNodeExt *StiKalmanTrackNode::nodeExtInstance()
02069 {
02070
static StiFactory<StiNodeExt,StiNodeExt> *extFactory=0;
02071
if (!extFactory) {
02072 extFactory = StiFactory<StiNodeExt,StiNodeExt>::myInstance();
02073 extFactory->setMaxIncrementCount(400000);
02074 extFactory->setFastDelete();
02075 }
02076
return extFactory->getInstance();
02077 }
02078
02079 StiNodeInf *StiKalmanTrackNode::nodeInfInstance()
02080 {
02081
static StiFactory<StiNodeInf,StiNodeInf> *infFactory=0;
02082
if (!infFactory) {
02083 infFactory = StiFactory<StiNodeInf,StiNodeInf>::myInstance();
02084 infFactory->setMaxIncrementCount(40000);
02085 infFactory->setFastDelete();
02086 }
02087
return infFactory->getInstance();
02088 }
02089
02090
void StiKalmanTrackNode::extend()
02091 {
02092
if(_ext)
return;
02093 _ext = nodeExtInstance();
02094 }
02095
02096
void StiKalmanTrackNode::extinf()
02097 {
02098
if(_inf)
return;
02099 _inf = nodeInfInstance();
02100 }
02101
02102
void StiKalmanTrackNode::saveInfo(
int kase)
02103 {
02104
if (kase){};
02105 extinf();
02106 _inf->mPP = mPP();
02107 _inf->mPE = mPE();
02108 _inf->mHrr = mHrr;
02109 }
02110
02111
02112
void StiKalmanTrackNode::reduce()
02113 {
02114
if(!_ext)
return;
02115
BFactory::Free(_ext); _ext=0;
02116 }
02117
02118
02119
02120 StThreeVector<double> StiKalmanTrackNode::getPoint()
const
02121
{
02122
return StThreeVector<double>(mFP._x,mFP._y,mFP._z);
02123 }
02124
02125
02126 StThreeVector<double> StiKalmanTrackNode::getGlobalPoint()
const
02127
{
02128
double ca = cos(_alpha),sa=sin(_alpha);
02129
return StThreeVector<double>(ca*mFP._x-sa*mFP._y, sa*mFP._x+ca*mFP._y, mFP._z);
02130 }
02131
02132
02133
double StiKalmanTrackNode::x_g()
const
02134
{
02135
return cos(_alpha)*mFP._x-sin(_alpha)*mFP._y;
02136 }
02137
02138
02139
double StiKalmanTrackNode::y_g()
const
02140
{
02141
return sin(_alpha)*mFP._x+cos(_alpha)*mFP._y;
02142 }
02143
02144
02145
double StiKalmanTrackNode::z_g()
const
02146
{
02147
return mFP._z;
02148 }
02149
02150
02151
void StiKalmanTrackNode::setUntouched()
02152 {
02153 mUnTouch.set(mPP(),mPE());
02154 }
02155
02156
double StiKalmanTrackNode::getTime() {
02157
static const double smax = 1e3;
02158
double time = 0;
02159
if (! _laser) {
02160
double d = sqrt(mFP._x*mFP._x+mFP._y*mFP._y);
02161
double sn = fabs(mFP._cosCA*mFP._y - mFP._sinCA*mFP._x)/d;
02162
if (sn<0.2) {
02163 d *= (1.+sn*sn/6);
02164 }
else {
02165 d *= asin(sn)/sn;
02166 }
02167 d *= sqrt(1.+mFP._tanl*mFP._tanl);
02168
double beta = 1;
02169
double pt = fabs(mFP._ptin);
02170
if (pt>0.1) {
02171 pt = 1./pt;
02172
double p2=(1.+mFP._tanl*mFP._tanl)*pt*pt;
02173
double m=StiKalmanTrackFinderParameters::instance()->massHypothesis();
02174
double m2=m*m;
02175
double e2=p2+m2;
02176
double beta2=p2/e2;
02177 beta = TMath::Sqrt(beta2);
02178 }
02179 time = d/(TMath::Ccgs()*beta*1e-6);
02180 }
else {
02181
if (TMath::Abs(mFP._z) > 20.0) {
02182
static const double Radius = 197.;
02183
static const int nsurf = 6;
02184
static const double surf[6] = {-Radius*Radius, 0, 0, 0, 1, 1};
02185
double dir[3] = {mFP._cosCA,mFP._sinCA,mFP._tanl};
02186 THelixTrack tc(&mFP._x,dir,mFP._curv);
02187
double s = tc.Step(smax, surf, nsurf,0,0,1);
02188
if (TMath::Abs(s) < smax)
02189 time = TMath::Abs(s)/(TMath::Ccgs()*1e-6);
02190 }
02191 }
02192
return time;
02193 }
02194