Sti/StiKalmanTrackNode.cxx

00001 //StiKalmanTrack.cxx 00002 /* 00003 * $Id: StiKalmanTrackNode.cxx,v 2.120 2008/12/26 15:18:00 fisyak Exp $ 00004 * 00005 * /author Claude Pruneau 00006 * 00007 * $Log: StiKalmanTrackNode.cxx,v $ 00008 * Revision 2.120 2008/12/26 15:18:00 fisyak 00009 * Enlarge fitting volume from 200 => 250 cm 00010 * 00011 * Revision 2.119 2008/06/11 22:04:37 fisyak 00012 * Add dead material 00013 * 00014 * Revision 2.118 2008/06/09 20:12:09 perev 00015 * BigStepBack 00016 * 00017 * Revision 2.115 2008/04/03 20:03:36 fisyak 00018 * Straighten out DB access via chairs 00019 * 00020 * Revision 2.114 2008/03/25 18:02:53 perev 00021 * remove field field from everythere 00022 * 00023 * Revision 2.113 2007/09/10 21:26:52 perev 00024 * getPt non positive bug fix. introduces 3 month ago 00025 * 00026 * Revision 2.112 2007/08/30 19:13:27 fine 00027 * replace the repmaining cout with LOG_DEBUG 00028 * 00029 * Revision 2.111 2007/08/16 20:21:24 fine 00030 * replace printf with logger 00031 * 00032 * Revision 2.110 2007/07/12 00:21:00 perev 00033 * Normal radius instead of layer one 00034 * 00035 * Revision 2.109 2007/06/25 19:31:52 perev 00036 * Init of _sinCA and _cosCA non zeros now 00037 * 00038 * Revision 2.108 2007/06/07 20:13:42 perev 00039 * BugFix in getPt() 00040 * 00041 * Revision 2.107 2007/06/06 04:03:03 perev 00042 * getTime() cleanup 00043 * 00044 * Revision 2.106 2007/04/30 19:53:16 fisyak 00045 * Correct time of flight calculation, add time of flight corrrection for Laser 00046 * 00047 * Revision 2.105 2007/03/21 17:47:24 fisyak 00048 * Time of Flight 00049 * 00050 * Revision 2.104 2006/12/24 02:16:36 perev 00051 * _inf=0 added in copy constructor 00052 * 00053 * Revision 2.103 2006/12/18 01:17:41 perev 00054 * Info block added and filled for pulls 00055 * 00056 * Revision 2.102 2006/10/16 20:29:35 fisyak 00057 * Clean up useless classes 00058 * 00059 * Revision 2.101 2006/10/09 15:47:07 fisyak 00060 * take out Central represantation, remove StiDedxCalculator 00061 * 00062 * Revision 2.100 2006/05/31 03:58:06 fisyak 00063 * Add Victor's dca track parameters, clean up 00064 * 00065 * Revision 2.99 2006/04/15 23:12:10 perev 00066 * Supress printout 00067 * 00068 * Revision 2.98 2006/04/07 18:01:56 perev 00069 * Back to the latest Sti 00070 * 00071 * Revision 2.96 2006/02/16 20:44:50 perev 00072 * assert changed back 00073 * 00074 * Revision 2.95 2006/02/15 19:07:18 perev 00075 * assrt in nudge cos < 1 00076 * 00077 * Revision 2.94 2006/02/14 18:10:41 perev 00078 * getGlobalHitErrors added+CleanUp 00079 * 00080 * Revision 2.93 2005/12/31 01:37:12 perev 00081 * Primary node perpendicular to track 00082 * 00083 * Revision 2.92 2005/12/20 00:41:21 perev 00084 * unassigned sind fixed(thanxYF) 00085 * 00086 * Revision 2.91 2005/12/18 23:41:46 perev 00087 * Dependency from StiKalmanTrackNode removed 00088 * 00089 * Revision 2.90 2005/12/08 22:05:45 perev 00090 * nudge assert replaced by print. But very strangeStiKalmanTrackNode.cxx 00091 * 00092 * Revision 2.89 2005/12/07 22:29:27 perev 00093 * Big Cleanup 00094 * 00095 * Revision 2.88 2005/08/09 14:55:34 perev 00096 * extend()/reduce() of node 00097 * 00098 * Revision 2.87 2005/08/04 03:52:54 perev 00099 * Cleanup 00100 * 00101 * Revision 2.86 2005/07/20 17:24:25 perev 00102 * Nudge actions in evaluateChi2 added 00103 * 00104 * Revision 2.85 2005/06/14 22:22:46 perev 00105 * Replace assert to error return 00106 * 00107 * Revision 2.84 2005/06/03 19:57:04 perev 00108 * Bug fix, violation of array size 00109 * 00110 * Revision 2.83 2005/06/02 17:27:41 perev 00111 * More weak assert in nudge() 00112 * 00113 * Revision 2.82 2005/05/31 16:47:56 perev 00114 * technical reorganization 00115 * 00116 * Revision 2.81 2005/05/12 18:10:04 perev 00117 * dL/dCurv more accurate 00118 * 00119 * Revision 2.80 2005/05/04 19:33:00 perev 00120 * Supress assert 00121 * 00122 * Revision 2.79 2005/04/30 20:45:18 perev 00123 * Less strong test for assert in propagateError 00124 * 00125 * Revision 2.78 2005/04/25 20:20:25 fisyak 00126 * replace assert by print out 00127 * 00128 * Revision 2.77 2005/04/12 14:35:39 fisyak 00129 * Add print out for dE/dx 00130 * 00131 * Revision 2.76 2005/04/11 22:48:30 perev 00132 * assert removed 00133 * 00134 * Revision 2.75 2005/04/11 17:33:55 perev 00135 * Wrong sorting accounted, check for accuracy inctreased 00136 * 00137 * Revision 2.74 2005/04/11 14:32:18 fisyak 00138 * Use gdrelx from GEANT for dE/dx calculation with accouning density effect 00139 * 00140 * Revision 2.73 2005/03/30 21:01:43 perev 00141 * asserts replaced to prints 00142 * 00143 * Revision 2.72 2005/03/28 05:52:40 perev 00144 * Reorganization of node container 00145 * 00146 * Revision 2.71 2005/03/24 19:28:35 perev 00147 * Switch off DerivTest 00148 * 00149 * Revision 2.70 2005/03/24 18:05:07 perev 00150 * Derivatives and their test fixed to eta==Psi model 00151 * 00152 * Revision 2.69 2005/03/19 00:20:33 perev 00153 * Assert for zero determinant ==> print 00154 * 00155 * Revision 2.68 2005/03/18 17:35:38 perev 00156 * some asserts removed 00157 * 00158 * Revision 2.67 2005/03/18 17:13:07 perev 00159 * assert in rotate fix 00160 * 00161 * Revision 2.66 2005/03/17 06:24:52 perev 00162 * A lot of changes. _eta now is Psi 00163 * 00164 * Revision 2.65 2005/02/25 17:05:41 perev 00165 * Scaling for errors added 00166 * 00167 * Revision 2.64 2005/02/19 20:23:37 perev 00168 * Cleanup 00169 * 00170 * Revision 2.63 2005/02/18 19:02:55 fisyak 00171 * Add debug print out for extendToVertex 00172 * 00173 * Revision 2.62 2005/02/17 23:19:02 perev 00174 * NormalRefangle + Error reseting 00175 * 00176 * Revision 2.61 2005/02/17 19:58:06 fisyak 00177 * Add debug print out flags 00178 * 00179 * Revision 2.60 2005/02/16 17:47:16 perev 00180 * assert in nudge 1==>5 00181 * 00182 * Revision 2.59 2005/02/07 18:33:42 fisyak 00183 * Add VMC dead material 00184 * 00185 * Revision 2.58 2005/01/20 16:51:32 perev 00186 * Remove redundant print 00187 * 00188 * Revision 2.57 2005/01/17 01:31:25 perev 00189 * New parameter model 00190 * 00191 * Revision 2.56 2005/01/06 00:59:41 perev 00192 * Initial errors tuned 00193 * 00194 * Revision 2.55 2005/01/04 01:37:47 perev 00195 * minor bug fix 00196 * 00197 * Revision 2.54 2004/12/23 18:15:46 perev 00198 * Cut for -ve cosCA added 00199 * 00200 * Revision 2.53 2004/12/14 17:10:17 perev 00201 * Propagate for 0 not called 00202 * 00203 * Revision 2.52 2004/12/13 22:52:23 perev 00204 * Off testError 00205 * 00206 * Revision 2.51 2004/12/13 20:01:38 perev 00207 * old version of testError temporary activated 00208 * 00209 * Revision 2.50 2004/12/12 01:34:24 perev 00210 * More smart testError, partial error reset 00211 * 00212 * Revision 2.49 2004/12/11 22:17:49 pruneau 00213 * new eloss calculation 00214 * 00215 * Revision 2.48 2004/12/11 04:31:36 perev 00216 * set of bus fixed 00217 * 00218 * Revision 2.47 2004/12/10 15:51:44 fisyak 00219 * Remove fudge factor from eloss calculation, add more debug printout and tests, reorder calculation of cov. matrix for low triangular form 00220 * 00221 * Revision 2.46 2004/12/08 16:56:16 fisyak 00222 * Fix sign in dE/dx; move from upper to lower triangular matrix convention (StEvent) for px,py,pz 00223 * 00224 * Revision 2.45 2004/12/05 00:39:07 fisyak 00225 * Add test suit for matrix manipulation debugging under overall CPPFLAGS=-DSti_DEBUG 00226 * 00227 * Revision 2.44 2004/12/01 14:04:57 pruneau 00228 * z propagation fix 00229 * 00230 * Revision 2.43 2004/11/24 17:59:26 fisyak 00231 * Set ionization potential for Ar in eloss calculateion instead 5 00232 * 00233 * Revision 2.42 2004/11/22 19:43:06 pruneau 00234 * commented out offending cout statement 00235 * 00236 * Revision 2.41 2004/11/22 19:23:20 pruneau 00237 * minor changes 00238 * 00239 * Revision 2.40 2004/11/10 21:46:02 pruneau 00240 * added extrapolation function; minor change to updateNode function 00241 * 00242 * Revision 2.39 2004/11/08 15:32:54 pruneau 00243 * 3 sets of modifications 00244 * (1) Changed the StiPlacement class to hold keys to both the radial and angle placement. Propagated the use 00245 * of those keys in StiSvt StiTpc StiSsd and all relevant Sti classes. 00246 * (2) Changed the StiKalmanTrackFinder::find(StiTrack*) function's algorithm for the navigation of the 00247 * detector volumes. The new code uses an iterator to visit all relevant volumes. The code is now more robust and compact 00248 * as well as much easier to read and maintain. 00249 * (3) Changed the chi2 calculation in StiKalmanTrack::getChi2 and propagated the effects of this change 00250 * in both StiTrackingPlots and StiStEventFiller classes. 00251 * 00252 * Revision 2.38 2004/10/27 03:25:49 perev 00253 * Version V3V 00254 * 00255 * Revision 2.37 2004/10/26 21:53:23 pruneau 00256 * No truncation but bad hits dropped 00257 * 00258 * Revision 2.36 2004/10/26 06:45:37 perev 00259 * version V2V 00260 * 00261 * Revision 2.35 2004/10/25 14:15:56 pruneau 00262 * various changes to improve track quality. 00263 * 00264 * Revision 2.34 2004/03/24 22:01:07 pruneau 00265 * Removed calls to center representation and replaced by normal representation 00266 * 00267 * Revision 2.33 2004/03/17 21:01:53 andrewar 00268 * Trapping for negative track error (^2) values _cYY and _cZZ. This should 00269 * be a temporary fix until the root of the problem is found. Problem seems 00270 * localized to trackNodes without hits. 00271 * Also trapping for asin(x), x>1 in ::length; point to point cord length 00272 * on the helix is greater than twice radius of curvature. This should also be 00273 * resovled. 00274 * 00275 * Revision 2.32 2004/01/30 21:40:21 pruneau 00276 * some clean up of the infinite checks 00277 * 00278 * Revision 2.31 2003/09/02 17:59:41 perev 00279 * gcc 3.2 updates + WarnOff 00280 * 00281 * Revision 2.30 2003/08/13 21:04:21 pruneau 00282 * transfered relevant tracking pars to detector builders 00283 * 00284 * Revision 2.29 2003/08/02 08:23:10 pruneau 00285 * best performance so far 00286 * 00287 * Revision 2.28 2003/07/30 19:18:58 pruneau 00288 * sigh 00289 * 00290 * Revision 2.26 2003/07/15 13:56:19 andrewar 00291 * Revert to previous version to remove bug. 00292 * 00293 * Revision 2.24 2003/05/22 18:42:33 andrewar 00294 * Changed max eloss correction from 1% to 10%. 00295 * 00296 * Revision 2.23 2003/05/09 22:07:57 pruneau 00297 * Added protection to avoid 90deg tracks and ill defined eloss 00298 * 00299 * Revision 2.22 2003/05/09 14:57:20 pruneau 00300 * Synching 00301 * 00302 * Revision 2.21 2003/05/08 18:49:09 pruneau 00303 * fudge=1 00304 * 00305 * Revision 2.20 2003/05/07 03:01:39 pruneau 00306 * *** empty log message *** 00307 * 00308 * Revision 2.19 2003/05/03 14:37:22 pruneau 00309 * *** empty log message *** 00310 * 00311 * Revision 2.18 2003/05/01 20:46:47 pruneau 00312 * changed error parametrization 00313 * 00314 * Revision 2.17 2003/04/22 21:20:17 pruneau 00315 * Added hit filter 00316 * Tuning og finder pars 00317 * Tuning of KalmanTrackNode 00318 * 00319 * Revision 2.16 2003/04/17 22:49:36 andrewar 00320 * Fixed getPhase function to conform to StHelixModel convention. 00321 * 00322 * Revision 2.15 2003/03/31 17:18:56 pruneau 00323 * various 00324 * 00325 * Revision 2.14 2003/03/13 21:21:27 pruneau 00326 * getPhase() fixed. MUST inclde -helicity()*pi/2 00327 * 00328 * Revision 2.13 2003/03/13 18:59:13 pruneau 00329 * various updates 00330 * 00331 * Revision 2.12 2003/03/12 17:57:31 pruneau 00332 * Elss calc updated. 00333 * 00334 * Revision 2.11 2003/03/04 21:31:05 pruneau 00335 * Added getX0() and getGasX0() conveninence methods. 00336 * 00337 * Revision 2.10 2003/03/04 18:41:27 pruneau 00338 * Fixed StiHit to use global coordinates as well as locals. 00339 * Fixed Logic Bug in StiKalmanTrackFinder 00340 * 00341 * Revision 2.9 2003/03/04 15:25:48 andrewar 00342 * Added several functions for radlength calculation. 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 // Local Track Model 00385 // 00386 // x[0] = y coordinate 00387 // x[1] = z position along beam axis 00388 // x[2] = (Psi) 00389 // x[3] = C (local) curvature of the track 00390 // x[4] = tan(l) 00391 00392 static const double kMaxEta = 1.25; // 72 degrees for laser tracks 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 //debug vars 00415 //#define STI_ERROR_TEST 00416 //#define STI_DERIV_TEST 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 /* bit mask for debug printout 00434 0 => 1 - covariance and propagate matrices 00435 1 => 2 - hit associated with the node 00436 2 => 4 - test matrix manipulation 00437 3 => 8 - test locate 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 // keep in mind that _eta == CA 00589 // keep in mind that pt == SomeCoef/rho 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 // if e==0, error calculation is not needed, then return 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 // first get p & e in the local ref frame 00757 enum {jXX=0,jXY,jYY}; 00758 00759 getMomentum(p,e); 00760 // now rotate the p & e in the global ref frame 00761 // for the time being, assume an azimuthal rotation 00762 // by alpha is sufficient. 00763 // transformation matrix - needs to be set 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 // original error matrix 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 //double nLayerRadius = place->getLayerRadius (); 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 { //flat volume 00823 dAlpha = place->getNormalRefAngle(); 00824 dAlpha = nice(dAlpha - _alpha); 00825 // bail out if the rotation fails... 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 // Multiple scattering 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; // track does not reach vertex "plane" 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; // track does not reach vertex "plane" 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 // numeDeriv(xk,1,option,dir); 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 // if track is coming back stop tracking 00949 //VP if (test<0) return -3; //Unfortunatelly correct order not garanteed 00950 00951 double dsin = mFP._curv*mgP.dx; 00952 mgP.sinCA2=mgP.sinCA1 + dsin; 00953 // Orientation is bad. Fit is non reliable 00954 if (fabs(mgP.sinCA2)>kMaxSinEta) return -4; 00955 mgP.cosCA2 = ::sqrt((1.-mgP.sinCA2)*(1.+mgP.sinCA2)); 00956 // Check what sign of cosCA2 must be 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++) {//try 2 cases, +ve and -ve cosCA 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) { //tiny angle 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); /*VP*/ 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) { //Small angle approx 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 // assert(fabs(mFP._sinCA) < 1.); 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 // fYE == dY/dEta 01067 double fYE= mgP.dx*(1.+mgP.cosCA1*mgP.cosCA2+mgP.sinCA1*mgP.sinCA2)/(mgP.sumCos*mgP.cosCA2); 01068 // fEC == dEta/dRho 01069 double fEC = mgP.dx/mgP.cosCA2; 01070 // fYC == dY/dRho 01071 double fYC=(mgP.dy*mgP.sinCA2+mgP.dx*mgP.cosCA2)/mgP.sumCos*fEC; 01072 // fZC == dZ/dRho 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 // fZE == dZ/dEta 01080 double dLdEta = mgP.dy/mgP.cosCA2; 01081 double fZE = mFP._tanl*dLdEta; 01082 01083 // fZT == dZ/dTanL; 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 // X related derivatives 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 // C^k-1_k = F_k * C_k-1 * F_kT + Q_k 01144 C = TRSymMatrix(F,TRArray::kAxSxAT,C); PrPP(propagateError,C); 01145 TRSymMatrix C1(kNPars,mFE.A); PrPP(propagateError,C1); 01146 C1.Verify(C);//,1e-7,2); 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 // now set hiterrors 01159 if (_hit) setHitErrors(); 01160 01161 // set state node is ready 01162 mPE() = mFE; 01163 _state = kTNReady; 01164 } 01165 01166 //______________________________________________________________________________ 01182 //delta(mgP.dx,dy,dz) = here - there 01183 double StiKalmanTrackNode::pathLToNode(const StiKalmanTrackNode * const oNode) 01184 { 01185 const StThreeVector<double> delta = 01186 getGlobalPoint() - oNode->getGlobalPoint(); 01187 double R = getCurvature(); 01188 // s = 2c * asin( t/(2c)); t=::sqrt(mgP.dx^2+dy^2+dz^2) 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 //If required, recalculate the errors of the detector hits. 01222 //Do not attempt this calculation for the main vertex. 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 // Half path length in previous node 01301 double pL1,pL2,pL3,d1,d2,d3,dxEloss=0; 01302 pL1=previousNode->pathlength()/2.; 01303 // Half path length in this node 01304 pL3=pathlength()/2.; 01305 // Gap path length 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 //cout << " m2:"<<m2<<" p2:"<<p2<<" beta2:"<<beta2; 01372 double theta2=mcs2(relRadThickness,beta2,p2); 01373 //cout << " theta2:"<<theta2; 01374 double pti = mFP._ptin, tanl = mFP._tanl; 01375 01376 double cos2Li = (1.+ tanl*tanl); // 1/cos(lamda)**2 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 // const static double I2Ar = (15.8*18) * (15.8*18) * 1e-18; // GeV**2 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 // inverse matrix 01457 double tmp=r00; r00=r11/_det; r11=tmp/_det; r01=-r01/_det; 01458 // update error matrix 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 // K = C * HT * G 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);//,1e-7,2); 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 // update Kalman state 01513 double p0 = mFP._y + k00*dyt + k01*dzt; 01514 //VP mFP._y += k00*dy + k01*dz; 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 //mFP._tanl += k40*dyt + k41*dzt; 01527 double sinCA = sin(eta); 01528 // The following test introduces a track propagation error but happens 01529 // only when the track should be aborted so we don't care... 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 // update error matrix 01541 double c00=mFE._cYY; 01542 double c10=mFE._cZY, c11=mFE._cZZ; 01543 double c20=mFE._cEY, c21=mFE._cEZ;//, c22=mFE._cEE; 01544 double c30=mFE._cPY, c31=mFE._cPZ;//, c32=mFE._cPE, c33=mFE._cPP; 01545 double c40=mFE._cTY, c41=mFE._cTZ;//, c42=mFE._cTE, c43=mFE._cTP, c44=mFE._cTT; 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 // update of the covariance matrix: 01571 // C_k = (I - K_k * H_k) * C^k-1_k * (I - K_k * H_k)T + K_k * V_k * KT_k 01572 // P* C^k-1_k * PT 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) //throw ( Exception) 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 //cout << " new _alpha:"<< 180.*_alpha/3.1415927<<endl; 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); /*VP*/ 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 //cout << " mFP._sinCA:"<<mFP._sinCA<<endl; 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; /*VP*/ 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 //fast way out for projections going out of fiducial volume 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 //YF edge is tolerance when we consider that detector is hit. // edge = 0; //VP the meaning of edge is not clear 01740 Int_t shapeCode = sh->getShapeCode(); 01741 switch (shapeCode) { 01742 case kDisk: 01743 case kCylindrical: // cylinder 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 //outerY = innerY + 2*edge; 01759 //outerZ = innerZ + 2*edge; 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 // outside detector to positive or negative y (phi) 01772 // if the track is essentially tangent to the plane, terminate it. 01773 position = yOff>0 ? kMissPhiPlus : kMissPhiMinus; 01774 else if (zAbsOff>outerZ && (zAbsOff-outerZ)>(yAbsOff-outerY)) 01775 // outside detector to positive or negative z (west or east) 01776 position = zOff>0 ? kMissZplus : kMissZminus; 01777 else if ((yAbsOff-innerY)>(zAbsOff-innerZ)) 01778 // positive or negative phi edge 01779 position = yOff>0 ? kEdgePhiPlus : kEdgePhiMinus; 01780 else 01781 // positive or negative z edge 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 // Test and correct error matrix. Output : number of fixes 01847 // DO NOT IMPROVE weird if() here. This accounts NaN 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 //return 0; 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 // ians++; emx[jj]=dia[j1]; 01868 // for (j2=0; j2<5;j2++){if (j1!=j2) emx[idx55[j1][j2]]=0;} 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 // ians++;emx[jj]= (emx[jj]<0) ? -cormax:cormax; 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 // if (step>0.1*fabs(pars[ipar])) step = 0.1*pars[ipar]; 01904 // if (fabs(step)<1.e-7) step = 1.e-7; 01905 pars[ipar] +=step*is; 01906 // Update sinCA & cosCA 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: //propagate 01913 state = myNode.propagate(val,shape,dir); break; 01914 case 2: //rotate 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 // opt = "E" extapolation 01996 // "M" Multiple scattering 01997 // "V" at Vertex 01998 // "B" at beam 01999 // "R" at Radius 02000 // "U" Updated 02001 // mFP fit parameters 02002 // mFE fit errors 02003 // _ext->mPP 02004 // _ext->mPE 02005 // _ext->mMtx 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) { //local coord 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 {//global coordinate 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 }//end for i 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); // mksec 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); // mksec 02190 } 02191 } 02192 return time; 02193 } 02194

Generated on Sun Mar 15 04:54:47 2009 for StRoot by doxygen 1.3.7