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 #include "FtfBaseTrack.h"
00027
00028 #include "FtfGeneral.h"
00029 #include <rtsLog.h>
00030 #include <limits.h>
00031
00032
00033 void ftfMatrixDiagonal ( double *h, double &h11, double &h22, double &h33 ) ;
00034
00035
00036
00037
00038 FtfBaseTrack::FtfBaseTrack ( ){
00039 firstHit = 0 ;
00040 lastHit = 0 ;
00041 }
00042
00043
00044
00045 int FtfBaseTrack::fitHelix ( )
00046 {
00047 if ( fitCircle ( ) ){
00048 LOG(ERR, " Problem in Fit_Circle " ) ;
00049 return 1 ;
00050 }
00051
00052
00053
00054 if ( fitLine ( )) {
00055 LOG(ERR, " Problem fitting a line " ) ;
00056 return 1 ;
00057 }
00058 return 0 ;
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 int FtfBaseTrack::fitCircle ( )
00073 {
00074 double wsum = 0.0 ;
00075 double xav = 0.0 ;
00076 double yav = 0.0 ;
00077
00078
00079
00080 for ( startLoop() ; done() ; nextHit() ) {
00081
00082 FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
00083 cHit->wxy = 1.0F/ (double)(cHit->dx*cHit->dx + cHit->dy*cHit->dy) ;
00084 wsum += cHit->wxy ;
00085 xav += cHit->wxy * cHit->x ;
00086 yav += cHit->wxy * cHit->y ;
00087 }
00088 if ( getPara()->vertexConstrainedFit ) {
00089 wsum += getPara()->xyWeightVertex ;
00090 xav += getPara()->xVertex ;
00091 yav += getPara()->yVertex ;
00092 }
00093 xav = xav / wsum ;
00094 yav = yav / wsum ;
00095
00096
00097
00098 double xxav = 0.0 ;
00099 double xyav = 0.0 ;
00100 double yyav = 0.0 ;
00101 double xi, yi ;
00102
00103 for ( startLoop() ; done() ; nextHit() ) {
00104 FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
00105 xi = cHit->x - xav ;
00106 yi = cHit->y - yav ;
00107 xxav += xi * xi * cHit->wxy ;
00108 xyav += xi * yi * cHit->wxy ;
00109 yyav += yi * yi * cHit->wxy ;
00110 }
00111 if ( getPara()->vertexConstrainedFit ) {
00112 xi = getPara()->xVertex - xav ;
00113 yi = getPara()->yVertex - yav ;
00114 xxav += xi * xi * getPara()->xyWeightVertex ;
00115 xyav += xi * yi * getPara()->xyWeightVertex ;
00116 yyav += yi * yi * getPara()->xyWeightVertex ;
00117 }
00118 xxav = xxav / wsum ;
00119 xyav = xyav / wsum ;
00120 yyav = yyav / wsum ;
00121
00122
00123
00124
00125
00126
00127
00128 double a = fabs( xxav - yyav ) ;
00129 double b = 4.0 * xyav * xyav ;
00130
00131 double asqpb = a * a + b ;
00132 double rasqpb = sqrt ( asqpb) ;
00133
00134 double splus = 1.0 + a / rasqpb ;
00135 double sminus = b / (asqpb * splus) ;
00136
00137 splus = sqrt (0.5 * splus ) ;
00138 sminus = sqrt (0.5 * sminus) ;
00139
00140
00141
00142 double sinrot, cosrot ;
00143 if ( xxav <= yyav ) {
00144 cosrot = sminus ;
00145 sinrot = splus ;
00146 }
00147 else {
00148 cosrot = splus ;
00149 sinrot = sminus ;
00150 }
00151
00152
00153
00154 if ( xyav < 0.0 ) sinrot = - sinrot ;
00155
00156
00157
00158
00159
00160
00161
00162
00163 if ( cosrot*xav+sinrot*yav < 0.0 ) {
00164 cosrot = -cosrot ;
00165 sinrot = -sinrot ;
00166 }
00167
00168
00169
00170 double rrav = xxav + yyav ;
00171 double rscale = sqrt(rrav) ;
00172
00173 xxav = 0.0 ;
00174 yyav = 0.0 ;
00175 xyav = 0.0 ;
00176 double xrrav = 0.0 ;
00177 double yrrav = 0.0 ;
00178 double rrrrav = 0.0 ;
00179
00180 double xixi, yiyi, riri, wiriri, xold, yold ;
00181 for ( startLoop() ; done() ; nextHit() ) {
00182 FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
00183 xold = cHit->x - xav ;
00184 yold = cHit->y - yav ;
00185
00186
00187
00188 xi = ( cosrot * xold + sinrot * yold ) / rscale ;
00189 yi = ( -sinrot * xold + cosrot * yold ) / rscale ;
00190
00191 xixi = xi * xi ;
00192 yiyi = yi * yi ;
00193 riri = xixi + yiyi ;
00194 wiriri = cHit->wxy * riri ;
00195
00196 xyav += cHit->wxy * xi * yi ;
00197 xxav += cHit->wxy * xixi ;
00198 yyav += cHit->wxy * yiyi ;
00199
00200 xrrav += wiriri * xi ;
00201 yrrav += wiriri * yi ;
00202 rrrrav += wiriri * riri ;
00203 }
00204
00205
00206
00207 if ( getPara()->vertexConstrainedFit ) {
00208 xold = getPara()->xVertex - xav ;
00209 yold = getPara()->yVertex - yav ;
00210
00211
00212
00213 xi = ( cosrot * xold + sinrot * yold ) / rscale ;
00214 yi = ( -sinrot * xold + cosrot * yold ) / rscale ;
00215
00216 xixi = xi * xi ;
00217 yiyi = yi * yi ;
00218 riri = xixi + yiyi ;
00219 wiriri = getPara()->xyWeightVertex * riri ;
00220
00221 xyav += getPara()->xyWeightVertex * xi * yi ;
00222 xxav += getPara()->xyWeightVertex * xixi ;
00223 yyav += getPara()->xyWeightVertex * yiyi ;
00224
00225 xrrav += wiriri * xi ;
00226 yrrav += wiriri * yi ;
00227 rrrrav += wiriri * riri ;
00228 }
00229
00230
00231
00232
00233
00234 xxav = xxav / wsum ;
00235 yyav = yyav / wsum ;
00236 xrrav = xrrav / wsum ;
00237 yrrav = yrrav / wsum ;
00238 rrrrav = rrrrav / wsum ;
00239 xyav = xyav / wsum ;
00240
00241 int const ntry = 5 ;
00242
00243
00244
00245
00246 double xrrxrr = xrrav * xrrav ;
00247 double yrryrr = yrrav * yrrav ;
00248 double rrrrm1 = rrrrav - 1.0 ;
00249 double xxyy = xxav * yyav ;
00250
00251 double c0 = rrrrm1*xxyy - xrrxrr*yyav - yrryrr*xxav ;
00252 double c1 = - rrrrm1 + xrrxrr + yrryrr - 4.0*xxyy ;
00253 double c2 = 4.0 + rrrrm1 - 4.0*xxyy ;
00254 double c4 = - 4.0 ;
00255
00256
00257
00258 double c2d = 2.0 * c2 ;
00259 double c4d = 4.0 * c4 ;
00260
00261
00262
00263
00264 double lamda = 0.0 ;
00265 double dlamda = 0.0 ;
00266
00267 double chiscl = wsum * rscale * rscale ;
00268 double dlamax = 0.001 / chiscl ;
00269
00270 double p, pd ;
00271 for ( int itry = 1 ; itry <= ntry ; itry++ ) {
00272 p = c0 + lamda * (c1 + lamda * (c2 + lamda * lamda * c4 )) ;
00273 pd = (c1 + lamda * (c2d + lamda * lamda * c4d)) ;
00274 dlamda = -p / pd ;
00275 lamda = lamda + dlamda ;
00276 if (fabs(dlamda)< dlamax) break ;
00277 }
00278
00279 chi2[0] = (double)(chiscl * lamda) ;
00280
00281
00282
00283
00284 double h11 = xxav - lamda ;
00285 double h14 = xrrav ;
00286 double h22 = yyav - lamda ;
00287 double h24 = yrrav ;
00288 double h34 = 1.0 + 2.0*lamda ;
00289 if ( h11 == 0.0 || h22 == 0.0 ){
00290 LOG(ERR, " Problems fitting a circle " ) ;
00291 return 1 ;
00292 }
00293 double rootsq = (h14*h14)/(h11*h11) + 4.0*h34 ;
00294
00295 double ratio, kappa, beta ;
00296 if ( fabs(h22) > fabs(h24) ) {
00297 ratio = h24 / h22 ;
00298 rootsq = ratio * ratio + rootsq ;
00299 kappa = 1.0 / sqrt(rootsq) ;
00300 beta = - ratio * kappa ;
00301 }
00302 else {
00303 ratio = h22 / h24 ;
00304 rootsq = 1.0 + ratio * ratio * rootsq ;
00305 beta = 1.0 / sqrt(rootsq) ;
00306 if ( h24 > 0 ) beta = - beta ;
00307 kappa = -ratio * beta ;
00308 }
00309 double alph = - (h14/h11) * kappa ;
00310
00311
00312
00313
00314 double kappa1 = kappa / rscale ;
00315 double dbro = 0.5 / kappa1 ;
00316
00317
00318
00319 double alphr = (cosrot * alph - sinrot * beta)* dbro ;
00320 double betar = (sinrot * alph + cosrot * beta)* dbro ;
00321
00322
00323
00324 double acent = (double)(xav - alphr) ;
00325 double bcent = (double)(yav - betar ) ;
00326 double radius = (double)dbro ;
00327
00328
00329
00330
00331 q = ( ( yrrav < 0 ) ? 1 : -1 ) * getPara()->bFieldPolarity ;
00332 pt = (double)fabs(2.9979e-3 * getPara()->bField * radius ) ;
00333
00334
00335
00336 double x0, y0 ;
00337 if ( getPara()->vertexConstrainedFit ) {
00338 flag = 1 ;
00339 x0 = getPara()->xVertex ;
00340 y0 = getPara()->yVertex ;
00341 phi0 = getPara()->phiVertex ;
00342 r0 = getPara()->rVertex ;
00343 psi = (double)atan2(bcent-y0,acent-x0) ;
00344 psi = psi + getPara()->bFieldPolarity*q * 0.5F * pi ;
00345 if ( psi < 0 ) psi = psi + twoPi ;
00346 }
00347 else {
00348 FtfBaseHit* lHit = (FtfBaseHit *)lastHit ;
00349 flag = 0 ;
00350 psi = (double)atan2(bcent-(lHit->y),acent-(lHit->x)) ;
00351 x0 = acent - radius * cos(psi);
00352 y0 = bcent - radius * sin(psi);
00353 psi = psi + getPara()->bFieldPolarity*q * 0.5F * pi ;
00354 phi0 = atan2(y0,x0);
00355 if ( phi0 < 0 ) phi0 += twoPi ;
00356 r0 = sqrt ( x0 * x0 + y0 * y0 ) ;
00357 }
00358
00359
00360
00361
00362 if ( getPara()->getErrors ) getErrorsCircleFit ( acent, bcent, radius ) ;
00363
00364 return 0 ;
00365
00366
00367
00368 }
00369
00370
00371
00372 int FtfBaseTrack::fitLine ( )
00373 {
00374
00375
00376
00377 double sum = 0.F ;
00378 double ss = 0.F ;
00379 double sz = 0.F ;
00380 double sss = 0.F ;
00381 double ssz = 0.F ;
00382
00383
00384
00385 double dx, dy ;
00386 double radius = (double)fabs(pt / ( 2.9979e-3 * getPara()->bField ) ) ;
00387 if ( getPara()->vertexConstrainedFit ) {
00388 dx = ((FtfBaseHit *)firstHit)->x - getPara()->xVertex ;
00389 dy = ((FtfBaseHit *)firstHit)->y - getPara()->yVertex ;
00390 }
00391 else {
00392 dx = ((FtfBaseHit *)firstHit)->x - ((FtfBaseHit *)lastHit)->x ;
00393 dy = ((FtfBaseHit *)firstHit)->y - ((FtfBaseHit *)lastHit)->y ;
00394 }
00395 double localPsi = 0.5F * sqrt ( dx*dx + dy*dy ) / radius ;
00396 if ( localPsi > 1. ) localPsi = 1. ;
00397
00398
00399 length = 2.0F * radius * asin ( localPsi ) ;
00400
00401 FtfBaseHit *previousHit = 0 ;
00402
00403 for ( startLoop() ; done() ; nextHit() ) {
00404 FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
00405 if ( currentHit != firstHit ) {
00406 dx = cHit->x - previousHit->x ;
00407 dy = cHit->y - previousHit->y ;
00408 dpsi = 0.5F * (double)sqrt ( dx*dx + dy*dy ) / radius ;
00409 if ( dpsi > 1.) {
00410
00411 dpsi = 1.;
00412 }
00413 cHit->s = previousHit->s - 2.0F * radius * (double)asin ( dpsi ) ;
00414 }
00415 else
00416 cHit->s = length;
00417
00418 sum += cHit->wz ;
00419 ss += cHit->wz * cHit->s ;
00420 sz += cHit->wz * cHit->z ;
00421 sss += cHit->wz * cHit->s * cHit->s ;
00422 ssz += cHit->wz * cHit->s * cHit->z ;
00423 previousHit = cHit ;
00424 }
00425
00426 double det = sum * sss - ss * ss;
00427 if ( fabs(det) < 1e-20){
00428 chi2[1] = 99999.F ;
00429 return 0 ;
00430 }
00431
00432
00433
00434 tanl = (double)((sum * ssz - ss * sz ) / det );
00435 z0 = (double)((sz * sss - ssz * ss ) / det );
00436
00437
00438
00439 chi2[1] = 0.F ;
00440 double r1 ;
00441 for ( startLoop() ; done() ; nextHit() ) {
00442 FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
00443 r1 = cHit->z - tanl * cHit->s - z0 ;
00444 chi2[1] += (double) ( (double)cHit->wz * (r1 * r1) );
00445 }
00446
00447
00448
00449
00450
00451
00452
00453 dtanl = (double) ( sum / det );
00454 dz0 = (double) ( sss / det );
00455
00456 return 0 ;
00457 }
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 int FtfBaseTrack::getErrorsCircleFit ( double a, double b, double r ) {
00478
00479 double h[9] = { 0. };
00480 double dx, dy ;
00481 double h11, h22, h33 ;
00482 static int j ;
00483 static double ratio, c1, s1;
00484 static double hyp;
00485
00486
00487 for (j = 0; j < 9; j++ ) {
00488 h[j] = 0.;
00489 }
00490
00491
00492
00493
00494
00495 if ( pt < getPara()->ptMinHelixFit ) {
00496 for ( startLoop() ; done() ; nextHit() ) {
00497
00498 FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
00499 cHit->wxy = 1.0F/ (double)(cHit->dx*cHit->dx + cHit->dy*cHit->dy) ;
00500 }
00501 }
00502
00503
00504
00505 for ( startLoop() ; done() ; nextHit() ) {
00506 FtfBaseHit* cHit = (FtfBaseHit *)currentHit ;
00507 dx = cHit->x - a;
00508 dy = cHit->y - b;
00509 hyp = (double)sqrt( dx * dx + dy * dy );
00510 s1 = dx / hyp;
00511 c1 = dy / hyp;
00512 ratio = r / hyp;
00513 h[0] += cHit->wxy * (ratio * (s1 * s1 - 1) + 1);
00514 h[1] += cHit->wxy * ratio * s1 * c1;
00515 h[2] += cHit->wxy * s1;
00516 h[4] += cHit->wxy * (ratio * (c1 * c1 - 1) + 1);
00517 h[5] += cHit->wxy * c1;
00518 h[8] += cHit->wxy ;
00519 }
00520 h[3] = h[1];
00521 h[6] = h[2];
00522 h[7] = h[5];
00523
00524 ftfMatrixDiagonal ( h, h11, h22, h33 ) ;
00525
00526
00527
00528 dpt = (double)fabs(2.9979e-3 * getPara()->bField * h33 );
00529
00530
00531
00532 if ( getPara()->vertexConstrainedFit ) {
00533 dx = a ;
00534 dy = b ;
00535 }
00536 else {
00537 dx = ((FtfBaseHit *)lastHit)->x + a - ((FtfBaseHit *)firstHit)->x ;
00538 dy = ((FtfBaseHit *)lastHit)->y + b + ((FtfBaseHit *)firstHit)->y ;
00539 }
00540 double w = dy / dx ;
00541 dpsi = (double)(( 1. / ( 1. + w*w ) ) * ( h22 / dx - dy * h11 / ( dx*dx ) )) ;
00542
00543 return 0 ;
00544 }
00545
00546
00547
00548
00549 void FtfBaseTrack::Print ( int level )
00550 {
00551 double pmom, pz;
00552
00553
00554
00555 if ( level > 9 ) {
00556 pz = pt * tanl ;
00557 pmom = (double)sqrt ( pz * pz + pt * pt ) ;
00558 LOG(NOTE, " =======> Track %d <========\n", id ) ;
00559 LOG(NOTE, "p, pt, q %7.2f %7.2f %2d \n", pmom, pt, q ) ;
00560 }
00561 if ( level > 19 ) {
00562 LOG(NOTE, "r0, z0, nHits %7.2f %7.2f %d \n", r0, z0, nHits ) ;
00563 LOG(NOTE, "phi0, psi, tanl %7.2f %7.2f %7.2f \n", phi0, psi, tanl ) ;
00564 }
00565
00566 if ( level > 29 ) {
00567 LOG(NOTE, "chi2 (s,z) %6.2e %6.2e \n", chi2[0], chi2[1] ) ;
00568 }
00569
00570
00571 if ( fmod((double)level,10.) > 0 ) {
00572 LOG(NOTE, "*** Clusters in this track *** " ) ;
00573 ((FtfBaseHit *)firstHit)->print ( 10 ) ;
00574 for ( startLoop() ; done() ; nextHit() ) {
00575 ((FtfBaseHit *)currentHit)->print ( 1 ) ;
00576 }
00577 }
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 Ftf3DHit FtfBaseTrack::closestApproach ( double xBeam, double yBeam ) {
00590 double rc, xc, yc ;
00591 return getClosest ( xBeam, yBeam, rc, xc, yc ) ;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 Ftf3DHit FtfBaseTrack::getClosest ( double xBeam, double yBeam,
00606 double &rc, double &xc, double &yc ) {
00607 double xp, yp, zp ;
00608 xp = yp = 0. ;
00609
00610
00611
00612
00613
00614
00615 double tPhi0 = psi + double(q)*getPara()->bFieldPolarity * 0.5 * M_PI / fabs((double)q) ;
00616
00617 double x0 = r0 * cos(phi0) ;
00618 double y0 = r0 * sin(phi0) ;
00619 rc = pt / fabs( bFactor * getPara()->bField ) ;
00620 xc = x0 - rc * cos(tPhi0) ;
00621 yc = y0 - rc * sin(tPhi0) ;
00622
00623
00624
00625
00626
00627 getClosest ( xBeam, yBeam, rc, xc, yc, xp, yp ) ;
00628
00629
00630
00631
00632 double angle = atan2 ( (yp-yc), (xp-xc) ) ;
00633 if ( angle < 0. ) angle = angle + 2.0 * M_PI ;
00634
00635 double dangle = angle - tPhi0 ;
00636
00637 if ( fabs(dangle) < 1.e-4 ) dangle = 0 ;
00638 dangle = fmod ( dangle, 2.0 * M_PI ) ;
00639 if ( (float(q)*getPara()->bFieldPolarity * dangle) < 0 )
00640 dangle = dangle + getPara()->bFieldPolarity*float(q) * 2. * M_PI ;
00641
00642 double stot = fabs(dangle) * rc ;
00643 zp = z0 - stot * tanl ;
00644
00645 Ftf3DHit tHit(xp,yp,zp) ;
00646 return tHit ;
00647 }
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660 int FtfBaseTrack::getClosest ( double xBeam, double yBeam,
00661 double rc, double xc, double yc,
00662 double& xClosest, double& yClosest ) {
00663
00664
00665
00666 double dx = xc - xBeam ;
00667 double dy = yc - yBeam ;
00668
00669
00670
00671 double fact = rc / sqrt ( dx * dx + dy * dy ) ;
00672 double f1 = 1. + fact ;
00673 double f2 = 1. - fact ;
00674
00675 double dx1 = dx * f1 ;
00676 double dy1 = dy * f1 ;
00677 double d1 = sqrt ( dx1 * dx1 + dy1 * dy1 ) ;
00678
00679 double dx2 = dx * f2 ;
00680 double dy2 = dy * f2 ;
00681 double d2 = sqrt ( dx2 * dx2 + dy2 * dy2 ) ;
00682
00683
00684
00685 if ( d1 < d2 ) {
00686 xClosest = dx1 + xBeam ;
00687 yClosest = dy1 + yBeam ;
00688 }
00689 else {
00690 xClosest = dx2 + xBeam ;
00691 yClosest = dy2 + yBeam ;
00692 }
00693 return 0 ;
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 Ftf3DHit FtfBaseTrack::extraRadius ( double r ) {
00711 double phi ;
00712
00713
00714
00715 double x, y, z, rc, xc, yc ;
00716 x = y = z = 0.F ;
00717
00718
00719
00720 Ftf3DHit tHit(0,0,0) ;
00721 if ( extraRCyl ( r, phi, z, rc, xc, yc ) ) return tHit ;
00722
00723
00724
00725 x = r * cos(phi) ;
00726 y = r * sin(phi) ;
00727 tHit.x = x ;
00728 tHit.y = y ;
00729 tHit.z = z ;
00730
00731 return tHit ;
00732 }
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747 int FtfBaseTrack::extraRCyl ( double &r, double &phi, double &z,
00748 double &rc, double &xc, double &yc ) {
00749
00750 double td ;
00751 double fac1,sfac, fac2 ;
00752
00753
00754
00755
00756
00757 double tPhi0 = psi + getPara()->bFieldPolarity*double(q) * 0.5 * M_PI / fabs((double)q) ;
00758 double x0 = r0 * cos(phi0) ;
00759 double y0 = r0 * sin(phi0) ;
00760 rc = fabs(pt / ( bFactor * getPara()->bField )) ;
00761 xc = x0 - rc * cos(tPhi0) ;
00762 yc = y0 - rc * sin(tPhi0) ;
00763
00764
00765
00766 fac1 = xc*xc + yc*yc ;
00767 sfac = sqrt( fac1 ) ;
00768
00769
00770
00771
00772
00773
00774 if ( fabs(sfac-rc) > r || fabs(sfac+rc) < r ) {
00775
00776 return 1 ;
00777 }
00778
00779
00780
00781 fac2 = ( r*r + fac1 - rc*rc) / (2.00 * r * sfac ) ;
00782 phi = atan2(yc,xc) + getPara()->bFieldPolarity*float(q)*acos(fac2) ;
00783 td = atan2(r*sin(phi) - yc,r*cos(phi) - xc) ;
00784
00785
00786 if ( td < 0 ) td = td + 2. * M_PI ;
00787 double dangle = tPhi0 - td ;
00788 dangle = fmod ( dangle, 2.0 * M_PI ) ;
00789 if ( r < r0 ) dangle *= -1 ;
00790
00791 if ( (getPara()->bFieldPolarity*float(q) * dangle) < 0 )
00792 dangle = dangle + getPara()->bFieldPolarity*float(q) * 2. * M_PI ;
00793
00794 double stot = fabs(dangle) * rc ;
00795
00796 if ( r > r0 ) z = z0 + stot * tanl ;
00797 else z = z0 - stot * tanl ;
00798
00799
00800
00801 return 0 ;
00802 }
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 int FtfBaseTrack::intersectorZLine ( double a, double b, Ftf3DHit& cross ) {
00825 Ftf3DHit cross1, cross2;
00826
00827 if (0 != intersectorZLine(a, b, cross1, cross2))
00828 return 1;
00829
00830 double r1sq = cross1.x*cross1.x + cross1.y*cross1.y;
00831 double r2sq = cross2.x*cross2.x + cross2.y*cross2.y;
00832
00833 if (r1sq < r2sq) {
00834 cross = cross1;
00835 } else {
00836 cross = cross2;
00837 }
00838
00839 return 0;
00840 }
00841
00842 int FtfBaseTrack::intersectorZLine ( double a, double b,
00843 Ftf3DHit& cross1, Ftf3DHit& cross2 ) {
00844
00845
00846
00847 double x0 = r0 * cos(phi0) ;
00848 double y0 = r0 * sin(phi0) ;
00849
00850 double trackPhi0 = psi + getPara()->bFieldPolarity*q * 0.5 * M_PI / fabs((double)q) ;
00851 double rc = pt / fabs( bFactor * getPara()->bField ) ;
00852 double xc = x0 - rc * cos(trackPhi0) ;
00853 double yc = y0 - rc * sin(trackPhi0) ;
00854
00855 double ycPrime = yc - b ;
00856 double aa = ( 1. + a * a ) ;
00857 double bb = -2. * ( xc + a * ycPrime ) ;
00858 double cc = ( xc * xc + ycPrime * ycPrime - rc * rc ) ;
00859
00860 double racine = bb * bb - 4. * aa * cc ;
00861 if ( racine < 0 ) {
00862 cross1.set(0,0,0);
00863 cross2.set(0,0,0);
00864 return 1 ;
00865 }
00866 double rootRacine = sqrt(racine) ;
00867
00868 double oneOverA = 1./aa;
00869
00870
00871
00872 double x1 = 0.5 * oneOverA * ( -1. * bb + rootRacine ) ;
00873 double y1 = a * x1 + b ;
00874
00875
00876
00877 double x2 = 0.5 * oneOverA * ( -1. * bb - rootRacine ) ;
00878 double y2 = a * x2 + b ;
00879
00880
00881
00882
00883
00884 double angle, dangle, stot;
00885
00886 angle = atan2 ( (y1-yc), (x1-xc) ) ;
00887 if ( angle < 0. ) angle = angle + 2.0 * M_PI ;
00888
00889 dangle = angle - trackPhi0 ;
00890 dangle = fmod ( dangle, 2.0 * M_PI ) ;
00891
00892 if ( (getPara()->bFieldPolarity*q * dangle) > 0 )
00893 dangle = dangle - getPara()->bFieldPolarity*q * 2. * M_PI ;
00894
00895 stot = fabs(dangle) * rc ;
00896 double z1 = z0 + stot * tanl ;
00897
00898 cross1.set ( x1, y1, z1 ) ;
00899
00900
00901
00902
00903
00904 angle = atan2 ( (y2-yc), (x2-xc) ) ;
00905 if ( angle < 0. ) angle = angle + 2.0 * M_PI ;
00906
00907 dangle = angle - trackPhi0 ;
00908 dangle = fmod ( dangle, 2.0 * M_PI ) ;
00909
00910 if ( (getPara()->bFieldPolarity*q * dangle) > 0 )
00911 dangle = dangle - getPara()->bFieldPolarity*q * 2. * M_PI ;
00912
00913 stot = fabs(dangle) * rc ;
00914 double z2 = z0 + stot * tanl ;
00915
00916 cross2.set ( x2, y2, z2 ) ;
00917
00918 return 0 ;
00919 }
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936 int FtfBaseTrack::intersectorYCteLine ( double a, Ftf3DHit& cross ) {
00937
00938
00939
00940 double x0 = r0*cos(phi0);
00941 double y0 = r0*sin(phi0);
00942
00943 double trackPhi0= psi + getPara()->bFieldPolarity*q*0.5*M_PI/fabs((float)q);
00944 double rcoc = pt / fabs( bFactor * getPara()->bField ) ;
00945 double xcoc = x0 - (rcoc*cos(trackPhi0));
00946 double ycoc = y0 - (rcoc*sin(trackPhi0));
00947
00948
00949
00950 double xHit = a ;
00951
00952 double f1 = (xHit-xcoc)*(xHit-xcoc);
00953 double r2 = rcoc*rcoc;
00954 if ( f1 > r2 ) {
00955 return 1 ;
00956 }
00957
00958 double sf2 = sqrt(r2-f1);
00959 double y1 = ycoc + sf2;
00960 double y2 = ycoc - sf2;
00961 double yHit = y1;
00962 if ( fabs(y2) < fabs(y1) ) yHit=y2;
00963
00964
00965 double angle = atan2 ( (yHit-ycoc), (xHit-xcoc) ) ;
00966 if ( angle < 0. ) angle = angle + 2.0 * M_PI ;
00967
00968 double dangle = angle - trackPhi0 ;
00969 dangle = fmod ( dangle, 2.0 * M_PI ) ;
00970 if ( (getPara()->bFieldPolarity*q * dangle) > 0 )
00971 dangle = dangle - getPara()->bFieldPolarity*q * 2. * M_PI ;
00972
00973 double stot = fabs(dangle) * rcoc ;
00974 double zHit = z0 + stot * tanl;
00975
00976 cross.set(xHit,yHit,zHit);
00977
00978 return 0 ;
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994 double FtfBaseTrack::arcLength ( double x1, double y1, double x2, double y2 )
00995 {
00996 double x0, y0, xc, yc, rc ;
00997 double angle_1, angle_2, d_angle, sleng_xy, sleng ;
00998
00999
01000
01001
01002 x0 = r0 * cos(phi0) ;
01003 y0 = r0 * sin(phi0) ;
01004 rc = pt / fabs( bFactor * getPara()->bField ) ;
01005
01006 double tPhi0 = psi + getPara()->bFieldPolarity*double(q) * 0.5 * M_PI / fabs((double)q) ;
01007 xc = x0 - rc * cos(tPhi0) ;
01008 yc = y0 - rc * sin(tPhi0) ;
01009
01010
01011
01012 angle_1 = atan2 ( (y1-yc), (x1-xc) ) ;
01013 if ( angle_1 < 0 ) angle_1 = angle_1 + 2. * M_PI ;
01014 angle_2 = atan2 ( (y2-yc), (x2-xc) ) ;
01015 if ( angle_2 < 0 ) angle_2 = angle_2 + 2. * M_PI ;
01016 d_angle = getPara()->bFieldPolarity*double(q) * ( angle_1 - angle_2 ) ;
01017 d_angle = fmod ( d_angle, 2. * M_PI ) ;
01018 if ( d_angle < 0 ) d_angle = d_angle + 2. * M_PI ;
01019
01020
01021
01022 sleng_xy = fabs ( rc ) * d_angle ;
01023 sleng = sleng_xy * sqrt ( 1.0 + tanl * tanl ) ;
01024 return sleng ;
01025
01026 }
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037 int FtfBaseTrack::phiRotate ( double deltaPhi ) {
01038 phi0 += deltaPhi ;
01039 if ( phi0 > 2. * M_PI ) phi0 -= 2. * M_PI ;
01040 if ( phi0 < 0 ) phi0 += 2. * M_PI ;
01041 psi += deltaPhi ;
01042 if ( psi > 2. * M_PI ) psi -= 2. * M_PI ;
01043 if ( psi < 0 ) psi += 2. * M_PI ;
01044
01045 return 0 ;
01046 }
01047
01048
01049
01050 int FtfBaseTrack::refitHelix ( int mod, int modEqual, int rowMin, int rowMax ) {
01051 typedef FtfBaseHit* hitPointer;
01052
01053 if ( nHits < 1 || nHits > 500 ) {
01054 LOG(ERR, "FtfBaseTrack:refitHelix: nHits %d out of range \n", nHits ) ;
01055 return 1 ;
01056 }
01057
01058 hitPointer* hitP = new hitPointer[nHits];
01059 int nHitsOrig = nHits ;
01060
01061 int counter = 0 ;
01062 for ( startLoop() ; done() ; nextHit() ) {
01063 hitP[counter] = (FtfBaseHit *)currentHit ;
01064
01065 counter++ ;
01066 }
01067
01068 int row ;
01069 firstHit = 0 ;
01070 counter = 0 ;
01071 for ( int i = 0 ; i < nHitsOrig ; i++ ) {
01072 row = hitP[i]->row ;
01073 hitP[i]->nextTrackHit = 0 ;
01074 if ( row%mod != modEqual ) continue ;
01075 if ( row < rowMin || row > rowMax ) continue ;
01076
01077 if ( firstHit == 0 ) firstHit = hitP[i] ;
01078 else
01079 ((FtfBaseHit *)lastHit)->nextTrackHit = (void *)hitP[i] ;
01080 lastHit = (void *)hitP[i] ;
01081 counter++ ;
01082 }
01083 nHits = counter ;
01084
01085 int problem = 0 ;
01086 if ( nHits > 5 ) fitHelix ( ) ;
01087 else problem = 1 ;
01088
01089
01090
01091 firstHit = 0 ;
01092 for ( int i = 0 ; i < nHitsOrig ; i++ ) {
01093 row = hitP[i]->row ;
01094 if ( firstHit == 0 ) firstHit = hitP[i] ;
01095 else
01096 ((FtfBaseHit *)lastHit)->nextTrackHit = (void *)hitP[i] ;
01097 lastHit = (void *)hitP[i] ;
01098 }
01099 nHits = nHitsOrig ;
01100
01101 delete []hitP ;
01102
01103 return problem ;
01104 }
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117 void FtfBaseTrack::updateToRadius ( double radius ) {
01118
01119 double phiExtra, zExtra, rCircle, xCircleCenter, yCircleCenter ;
01120
01121 int ok = extraRCyl ( radius, phiExtra, zExtra, rCircle, xCircleCenter, yCircleCenter ) ;
01122 if ( ok ) {
01123
01124
01125 return ;
01126 }
01127
01128
01129
01130
01131
01132
01133
01134 double xExtra = radius * cos(phiExtra) ;
01135 double yExtra = radius * sin(phiExtra) ;
01136
01137 double tPhi = atan2(yExtra-yCircleCenter,xExtra-xCircleCenter);
01138
01139
01140
01141 if ( phiExtra < 0 ) phiExtra += 2 * M_PI ;
01142
01143 double tPsi = tPhi - getPara()->bFieldPolarity * double(q) * 0.5 * M_PI / fabs((double)q) ;
01144 if ( tPsi > 2. * M_PI ) tPsi -= 2. * M_PI ;
01145 if ( tPsi < 0. ) tPsi += 2. * M_PI ;
01146
01147
01148
01149 r0 = radius ;
01150 phi0 = phiExtra ;
01151 z0 = zExtra ;
01152 psi = tPsi ;
01153 }
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166 void FtfBaseTrack::updateToClosestApproach ( double xBeam, double yBeam, double rMax ) {
01167 double rc, xc, yc ;
01168 Ftf3DHit closest = getClosest ( xBeam, yBeam, rc, xc, yc ) ;
01169
01170
01171
01172 double radius = sqrt(closest.x*closest.x+closest.y*closest.y);
01173 if ( radius > rMax ) return ;
01174
01175 double tPhi = atan2(closest.y-yc,closest.x-xc);
01176
01177
01178
01179
01180 double tPsi = tPhi - getPara()->bFieldPolarity*double(q) * 0.5 * M_PI / fabs((double)q) ;
01181 if ( tPsi > 2. * M_PI ) tPsi -= 2. * M_PI ;
01182 if ( tPsi < 0. ) tPsi += 2. * M_PI ;
01183
01184
01185
01186 r0 = radius ;
01187 phi0 = atan2(closest.y,closest.x) ;
01188 if ( phi0 < 0 ) phi0 += 2. * M_PI ;
01189 z0 = closest.z ;
01190 psi = tPsi ;
01191 }
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207 Ftf3DHit FtfBaseTrack::extrapolate2PathLength(double pathlength)
01208 {
01209
01210
01211
01212 double Bfield=fabs(getPara()->bField) * getPara()->bFieldPolarity * 0.01;
01213 double c=0.3;
01214 double lambda=atan(tanl);
01215 double kapa=(c*q*Bfield)/pt;
01216 double heli=-((q*Bfield)/fabs(q*Bfield));
01217 double phi=psi-heli*M_PI/2;
01218
01219 double x0=r0*cos(phi0);
01220 double y0=r0*sin(phi0);
01221
01222 Ftf3DHit CoordOfExtrapol;
01223 CoordOfExtrapol.x = x0 + (1/kapa)*(cos(phi+heli*pathlength*kapa*cos(lambda))-cos(phi));
01224 CoordOfExtrapol.y = y0 + (1/kapa)*(sin(phi+heli*pathlength*kapa*cos(lambda))-sin(phi));
01225 CoordOfExtrapol.z = z0 + pathlength*sin(lambda);
01226
01227
01228
01229
01230
01231
01232
01233 return CoordOfExtrapol;
01234 }
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249 double FtfBaseTrack::getRadius()
01250 {
01251 double radius=pt / fabs( bFactor * getPara()->bField );
01252
01253 return radius;
01254 }
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269 double FtfBaseTrack::getXCenter() {
01270
01271 double tPhi0 = psi + getPara()->bFieldPolarity*double(q) * 0.5 * M_PI / fabs((double)q) ;
01272
01273 double x0=r0*cos(phi0);
01274
01275 return ( x0- getRadius() * cos(tPhi0) );
01276 }
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290 double FtfBaseTrack::getYCenter()
01291 {
01292
01293 double tPhi0 = psi + getPara()->bFieldPolarity*double(q) * 0.5 * M_PI / fabs((double)q) ;
01294
01295 double y0=r0*sin(phi0);
01296
01297 return ( y0 - getRadius() * sin(tPhi0) );
01298 }
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322 double FtfBaseTrack::pathLength(double Rx, double Ry, double Rz, double Nx, double Ny, double Nz )
01323 {
01324
01325
01326
01327 double Bfield=fabs(getPara()->bField) * getPara()->bFieldPolarity * 0.01;
01328
01329
01330 int heli= (int) -((q*Bfield)/fabs(q*Bfield));
01331 int H = (heli>=0) ? 1 : -1;
01332
01333
01334 double x0=r0*cos(phi0);
01335 double y0=r0*sin(phi0);
01336
01337
01338
01339 double DipAngle = atan(tanl);
01340 double CosDipAngle = cos(DipAngle);
01341 double SinDipAngle = sin(DipAngle);
01342
01343
01344 double Phase = psi-heli*M_PI/2;
01345 double CosPhase = cos(Phase);
01346 double SinPhase = sin(Phase);
01347 if (fabs(Phase) > M_PI) Phase = atan2(SinPhase, CosPhase);
01348
01349
01350 double Curvature = (0.3*q*Bfield)/pt;
01351
01352
01353
01354 const double NoSolution = LONG_MAX ;
01355 const double MaxPrecisionNeeded = 0.0001;
01356 const int MaxIterations = 20;
01357
01358 double A = Curvature*( (x0*Nx+y0*Ny+z0*Nz) - (Rx*Nx+Ry*Ny+Rz*Nz) ) -
01359 Nx*CosPhase -
01360 Ny*SinPhase;
01361 double t = H*Curvature*CosDipAngle;
01362
01363 double a, f, fp, s;
01364 double sOld = s = 0;
01365 int i;
01366 for (i=0; i<MaxIterations; i++)
01367 {
01368 a = t*s+Phase;
01369 f = A +
01370 Nx*cos(a) +
01371 Ny*sin(a) +
01372 Nz*Curvature*SinDipAngle*s;
01373
01374 fp = -Nx*sin(a)*t +
01375 Ny*cos(a)*t +
01376 Nz*Curvature*SinDipAngle;
01377 s -= f/fp;
01378 if (fabs(sOld-s) < MaxPrecisionNeeded) break;
01379 sOld = s;
01380 }
01381
01382 if (i == MaxIterations) s = NoSolution;
01383
01384 return s;
01385 }