StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StFtpcTrack.cc
1 // $Id: StFtpcTrack.cc,v 1.39 2014/07/24 23:07:59 jeromel Exp $
2 // $Log: StFtpcTrack.cc,v $
3 // Revision 1.39 2014/07/24 23:07:59 jeromel
4 // Fix for C++11 compliance
5 //
6 // Revision 1.38 2012/06/17 19:13:36 fisyak
7 // Resolve ambiguity in TMath::Power
8 //
9 // Revision 1.37 2008/07/03 07:22:35 jcs
10 // improved LOG_WARN message
11 //
12 // Revision 1.36 2008/07/03 05:25:44 jcs
13 // exit momentum fit if plength >= NoSolution/2 for any hit
14 //
15 // Revision 1.35 2008/06/24 08:12:48 jcs
16 // If NoSolution found for MomentumFit with primary vertex, set mFromMainVertex = kFALSE for the track to avoid looping in StarMagField 3D field interpolation
17 //
18 // Revision 1.34 2008/06/11 18:41:31 fine
19 // Add FATAL_ERROR message
20 //
21 // Revision 1.33 2007/01/15 08:23:02 jcs
22 // replace printf, cout and gMesMgr with Logger commands
23 //
24 // Revision 1.32 2004/02/12 19:37:10 oldi
25 // *** empty log message ***
26 //
27 // Revision 1.31 2004/01/28 01:41:32 jeromel
28 // *** empty log message ***
29 //
30 // Revision 1.30 2003/11/26 11:34:45 jcs
31 // change Sign(Float_t, Double_t) to Sign(Double_t,Double_t)
32 //
33 // Revision 1.29 2003/09/16 15:27:02 jcs
34 // removed inline as it would leave a few undefined reference
35 //
36 // Revision 1.28 2003/09/16 14:08:04 jeromel
37 // Removed inline to resolve undefined symbol in lib
38 //
39 // Revision 1.27 2003/09/02 17:58:16 perev
40 // gcc 3.2 updates + WarnOff
41 //
42 // Revision 1.26 2003/01/20 09:16:30 oldi
43 // Calculation of residuals simplified.
44 //
45 // Revision 1.25 2003/01/16 18:04:33 oldi
46 // Bugs eliminated. Now it compiles on Solaris again.
47 // Split residuals for global and primary fit.
48 //
49 // Revision 1.24 2002/11/28 09:39:25 oldi
50 // Problem in momentum fit eliminated. Negative vertex Id is not used anymore.
51 // It was used do decide for global or primary fit.
52 // Code was prepared to fill momentum values at outermost points on tracks.
53 // This feature is not used up to now.
54 // Code cleanups.
55 //
56 // Revision 1.23 2002/11/06 13:45:59 oldi
57 // Global/primary fit handling simplified.
58 // Code clean ups.
59 //
60 // Revision 1.22 2002/10/31 13:40:01 oldi
61 // Method GetSector() added.
62 // Method GetMeanR() and GetMeanAlpha() added.
63 // dca set to zero if no vertex was found (tracking done with arbitrary vertex at (0., 0., 0.))
64 // Code cleanup.
65 //
66 // Revision 1.21 2002/10/24 16:37:41 oldi
67 // dca (impact parameter) is calculated using StHelix::distance(vertexPos), now.
68 // Therefore it is the smallest three dimensional distance of the helix to the
69 // primary vertex.
70 // dca for primary tracks is filled correctly, now. (Even though this value
71 // shouldn't be of great use.)
72 // Code clean-ups.
73 //
74 // Revision 1.20 2002/10/11 15:45:14 oldi
75 // Get FTPC geometry and dimensions from database.
76 // No field fit activated: Returns momentum = 0 but fits a helix.
77 // Bug in TrackMaker fixed (events with z_vertex > outer_ftpc_radius were cut).
78 // QA histograms corrected (0 was supressed).
79 // Code cleanup (several lines of code changed due to *params -> Instance()).
80 // cout -> gMessMgr.
81 //
82 // Revision 1.19 2002/10/03 10:33:59 oldi
83 // Usage of gufld removed.
84 // Magnetic field is read by StMagUtilities, now.
85 //
86 // Revision 1.18 2002/04/29 15:50:01 oldi
87 // All tracking parameters moved to StFtpcTrackingParameters.cc/hh.
88 // In a future version the actual values should be moved to an .idl file (the
89 // interface should be kept as is in StFtpcTrackingParameters.cc/hh).
90 //
91 // Revision 1.17 2002/04/22 14:18:17 oldi
92 // Assume hit resolution to be 0.1mm if it is equal to 0.
93 //
94 // Revision 1.16 2002/04/08 15:37:59 oldi
95 // Switch for magnetic field factor installed.
96 // Minor corrections/improvements.
97 //
98 // Revision 1.15 2002/04/05 16:50:42 oldi
99 // Cleanup of MomentumFit (StFtpcMomentumFit is now part of StFtpcTrack).
100 // Each Track inherits from StHelix, now.
101 // Therefore it is possible to calculate, now:
102 // - residuals
103 // - vertex estimations obtained by back extrapolations of FTPC tracks
104 // Chi2 was fixed.
105 // Many additional minor (and major) changes.
106 //
107 // Revision 1.14 2002/02/21 22:57:57 oldi
108 // Fixes to avoid warnings during optimized compilation.
109 //
110 // Revision 1.13 2002/01/29 11:08:10 oldi
111 // Write() renamed to WriteCluster() resp. WriteTrack() to avoid compiler warnings.
112 // As a result the functions TObject::Write() are available again (directly).
113 //
114 // Revision 1.12 2001/05/04 09:19:58 oldi
115 // For non main vertex tracks the momentum of the fit with vertex constraint was
116 // stored. To fix this Fit-> was changed to looseFit-> at the appropriate
117 // locations.
118 //
119 // Revision 1.11 2001/01/25 15:21:57 oldi
120 // Review of the complete code.
121 // Fix of several bugs which caused memory leaks:
122 // - Tracks were not allocated properly.
123 // - Tracks (especially split tracks) were not deleted properly.
124 // - TClonesArray seems to have a problem (it could be that I used it in a
125 // wrong way). I changed all occurences to TObjArray which makes the
126 // program slightly slower but much more save (in terms of memory usage).
127 // Speed up of HandleSplitTracks() which is now 12.5 times faster than before.
128 // Cleanup.
129 //
130 // Revision 1.10 2000/11/10 18:38:02 oldi
131 // Changes due to replacement of StThreeVector by TVector3.
132 // Points can be added to a track on either end now.
133 // New data members for dE/dx information.
134 // Cleanup.
135 //
136 // Revision 1.9 2000/09/07 11:35:39 jcs
137 // Set flag,id_start_vertex,nrec,nmax,nfit for FTPC primary tracks
138 //
139 // Revision 1.8 2000/07/18 21:22:16 oldi
140 // Changes due to be able to find laser tracks.
141 // Cleanup: - new functions in StFtpcConfMapper, StFtpcTrack, and StFtpcPoint
142 // to bundle often called functions
143 // - short functions inlined
144 // - formulas of StFormulary made static
145 // - avoid streaming of objects of unknown size
146 // (removes the bunch of CINT warnings during compile time)
147 // - two or three minor bugs cured
148 //
149 // Revision 1.7 2000/07/17 14:54:22 jcs
150 // save results of constrained fit
151 //
152 // Revision 1.6 2000/07/12 11:58:40 jcs
153 // calculate and save FTPC track parameters for unconstrained fit
154 //
155 // Revision 1.5 2000/07/03 12:42:57 jcs
156 // save (pre)Vertex id and unconstrained fit results
157 //
158 // Revision 1.4 2000/06/07 11:48:56 oldi
159 // Added function GetEta().
160 // In SetProperties(Bool_t usage, Int_t tracknumber): calculation of
161 // mRowsWithPoints added.
162 // CalculateNMax() changed. It calculates now the (arbitrary) angle and radius
163 // in the inner and outer padrow.
164 //
165 // Revision 1.3 2000/05/12 12:59:15 oldi
166 // removed delete operator for mSegment in StFtpcConfMapper (mSegment was deleted twice),
167 // add two new constructors for StFtpcTracker to be able to refit already existing tracks,
168 // minor cosmetics
169 //
170 // Revision 1.2 2000/05/11 15:14:50 oldi
171 // Changed class names *Hit.* due to already existing class StFtpcHit.cxx in StEvent
172 //
173 // Revision 1.1 2000/05/10 13:39:22 oldi
174 // Initial version of StFtpcTrackMaker
175 //
176 
177 //----------Author: Holm G. Hümmler, Markus D. Oldenburg
178 //----------Last Modified: 10.11.2000
179 //----------Copyright: &copy MDO Production 1999
180 
181 #include "StFtpcTrack.hh"
182 #include "StFtpcTrackingParams.hh"
183 #include "StFormulary.hh"
184 #include "StFtpcVertex.hh"
185 #include "StFtpcPoint.hh"
186 #include "StFtpcConfMapPoint.hh"
187 
188 #include "SystemOfUnits.h"
189 #include "PhysicalConstants.h"
190 #include "StMessMgr.h"
191 
192 #include <math.h>
193 
195 // //
196 // StFtpcTrack class - representation of one track for the FTPC trackers. //
197 // //
198 // This class contains all data members which are the output of the FTPC tracker. //
199 // //
201 
202 
203 ClassImp(StFtpcTrack)
204 
205 
207 {
208  // Default constructor.
209  // Creates a ObjArray of the hits belonging to the track.
210 
211  SetDefaults();
212 }
213 
214 
215 StFtpcTrack::StFtpcTrack(Int_t tracknumber)
216 {
217  // Same as default constructor except that the track number is set.
218 
219  SetDefaults();
220  SetTrackNumber(tracknumber);
221 }
222 
223 
224 StFtpcTrack::~StFtpcTrack()
225 {
226  // Destructor.
227 
228  delete mPoints;
229  delete mPointNumbers;
230 }
231 
232 
233 void StFtpcTrack::SetDefaults()
234 {
235  // Executes the default setup for the track.
236 
237  mPoints = new TObjArray(0);
238  mPointNumbers = new MIntArray();
239 
240  mTrackNumber = -1;
241  mGlobTrackId = -1;
242 
243  SetRadius(0.);
244  SetCenterX(0.);
245  SetCenterY(0.);
246  SetAlpha0(0.);
247  SetPid(0);
248  SetNMax(0);
249 
250  ComesFromMainVertex(kFALSE);
251 
252  mP.SetX(0.);
253  mP.SetY(0.);
254  mP.SetZ(0.);
255 
256  mV.SetX(0.);
257  mV.SetY(0.);
258  mV.SetZ(0.);
259 
260  mL.SetX(0.);
261  mL.SetY(0.);
262  mL.SetZ(0.);
263 
264  mQ = 0;
265  mChiSq[0] = 0.;
266  mChiSq[1] = 0.;
267  mTheta = 0.;
268  mDca = 0.;
269 
270  mTrackLength = 0.;
271 
272  mdEdx = 0.;
273  mNumdEdxHits = 0;
274 
275  return;
276 }
277 
278 
279 void StFtpcTrack::SetTrackNumber(Int_t number)
280 {
281  // Sets the tracknumber.
282  // If the track has already some hits assigned the track number of the hits is also set.
283 
284  mTrackNumber = number;
285 
286  for (Int_t i = 0; i < mPoints->GetEntriesFast(); i++) {
287  ((StFtpcPoint*)mPoints->At(i))->SetTrackNumber(number);
288  }
289 
290  return;
291 }
292 
293 
294 void StFtpcTrack::AddPoint(StFtpcPoint* point)
295 {
296  // Adds a given point to the track.
297 
298  mPointNumbers->AddLast(point->GetHitNumber());
299  mPoints->AddLast(point);
300  point->SetUsage(kTRUE);
301  point->SetTrackNumber(GetTrackNumber());
302 
303  return;
304 }
305 
306 
307 void StFtpcTrack::AddForwardPoint(StFtpcPoint* point)
308 {
309  // Shifts all found points by one. Adds a given point in the (now) empty first slot.
310 
311  Int_t num = mPoints->GetEntriesFast();
312  mPoints->Expand(num+1);
313 
314  for (Int_t i = num-1; i >= 0; i--) {
315  mPoints->AddAt(mPoints->At(i), i+1);
316  }
317 
318  mPoints->AddFirst(point);
319  mPointNumbers->ShiftByOneAndAddAtFirst(point->GetHitNumber());
320  point->SetUsage(kTRUE);
321  point->SetTrackNumber(GetTrackNumber());
322 
323  return;
324 }
325 
326 
327 Int_t StFtpcTrack::GetHemisphere() const
328 {
329  // Returns +1 if z of track is positiv, -1 otherwise.
330  return (Int_t)TMath::Sign(1., ((StFtpcPoint *)(GetHits()->First()))->GetZ());
331 }
332 
333 
334 Int_t StFtpcTrack::GetSector() const
335 {
336  // Returns sector of track. Assumes that the track doesn't cross more than one sector.
337  return ((StFtpcPoint *)GetHits()->First())->GetSector();
338 }
339 
340 
341 Double_t StFtpcTrack::CalcAlpha0()
342 {
343  // Calculates the starting angle (with respect to the x-axis) of xt.
344 
345  StFtpcConfMapPoint *trackpoint = (StFtpcConfMapPoint *)mPoints->First();
346  Double_t asin_arg = StFormulary::CheckASinArg((trackpoint->GetYt() - GetCenterY())/GetRadius());
347  Double_t alpha0 = 0.;
348 
349  if (trackpoint->GetXt() >= GetCenterX() && trackpoint->GetYt() > GetCenterY()) {
350  alpha0 = TMath::ASin(asin_arg);
351  }
352 
353  else if (trackpoint->GetXt() < GetCenterX() && trackpoint->GetYt() >= GetCenterY()) {
354  alpha0 = -TMath::ASin(asin_arg) + TMath::Pi();
355  }
356 
357  else if (trackpoint->GetXt() <= GetCenterX() && trackpoint->GetYt() < GetCenterY()) {
358  alpha0 = TMath::ASin(-asin_arg) + TMath::Pi();
359  }
360 
361  else if (trackpoint->GetXt() > GetCenterX() && trackpoint->GetYt() <= GetCenterY()) {
362  alpha0 = -TMath::ASin(-asin_arg) + 2 * TMath::Pi();
363  }
364 
365  return alpha0;
366 }
367 
368 
369 void StFtpcTrack::SetProperties(Bool_t usage, Int_t tracknumber)
370 {
371  // Sets number of next hit. Counting is started from the vertex. (The tracker finds hits on tracks vice versa!)
372  // Sets the usage of all points belonging to this track to the value of mUsage and
373  // sets the track number of all points belonging to this track to the value of fTrackNumber.
374 
375  mRowsWithPoints = 0;
376 
377  for (Int_t i = 0; i < mPoints->GetEntriesFast(); i++) {
378  StFtpcConfMapPoint *p = (StFtpcConfMapPoint *)mPoints->At(i);
379 
380  if (usage == kTRUE) {
381  mRowsWithPoints += (Int_t)TMath::Power(2., (Int_t)(((p->GetPadRow()-1)%StFtpcTrackingParams::Instance()->NumberOfPadRowsPerSide())+1));
382 
383  if (i != 0) {
384  p->SetNextHitNumber(((StFtpcConfMapPoint *)mPoints->At(i-1))->GetHitNumber());
385  }
386 
387  else {
388  p->SetNextHitNumber(-1);
389  }
390  }
391 
392  else {
393  p->SetNextHitNumber(-1);
394  }
395 
396  p->SetUsage(usage);
397  p->SetTrackNumber(tracknumber);
398  }
399 
400  return;
401 }
402 
403 
404 void StFtpcTrack::SetPointDependencies()
405 {
406  // Sets number of next hit. Counting is started from the vertex. (The tracker finds hits on tracks vice versa!)
407 
408  mRowsWithPoints = 0;
409 
410  for (Int_t i = 0; i < mPoints->GetEntriesFast(); i++) {
411  StFtpcPoint *p = (StFtpcPoint *)mPoints->At(i);
412 
413  mRowsWithPoints += (Int_t)TMath::Power(2., (Int_t) (((p->GetPadRow()-1)%StFtpcTrackingParams::Instance()->NumberOfPadRowsPerSide())+1));
414 
415  if (i != 0) {
416  p->SetNextHitNumber(((StFtpcPoint *)mPoints->At(i-1))->GetHitNumber());
417  }
418 
419  else {
420  p->SetNextHitNumber(-1);
421  }
422  }
423 
424 
425 
426  return;
427 }
428 
429 
430 void StFtpcTrack::CalculateNMax()
431 {
432  // Calculates the max. possible number of points on this track.
433  // Up to now this is only a approximation. The calculated value would be right if:
434  // - the track would be a straight line
435  //
436  // In addition this funtion calculates the radius and the angle of a potential
437  // track point in the first (inner) and the last (outer) pad row.
438 
439  Short_t nmax = 0;
440 
441  StFtpcConfMapPoint *lastpoint = (StFtpcConfMapPoint *)this->GetHits()->Last();
442  StFtpcConfMapPoint *firstpoint = (StFtpcConfMapPoint *)this->GetHits()->First();
443 
444  Double_t z2 = firstpoint->GetZ();
445  Double_t z1 = lastpoint->GetZ();
446  Double_t x2 = firstpoint->GetX();
447  Double_t x1 = lastpoint->GetX();
448  Double_t r2 = TMath::Sqrt((firstpoint->GetX() * firstpoint->GetX()) + (firstpoint->GetY() * firstpoint->GetY()));
449  Double_t r1 = TMath::Sqrt((lastpoint->GetX() * lastpoint->GetX()) + (lastpoint->GetY() * lastpoint->GetY()));
450 
451  Double_t r, x;
452 
453  for (Int_t i = 0; i < StFtpcTrackingParams::Instance()->NumberOfPadRowsPerSide(); i++) {
454  r = (r2 - r1) / (z2 - z1) * (TMath::Sign(Double_t(StFtpcTrackingParams::Instance()->PadRowPosZ(i)), z1) - z1) + r1;
455  x = (x2 - x1) / (z2 - z1) * (TMath::Sign(Double_t(StFtpcTrackingParams::Instance()->PadRowPosZ(i)), z1) - z1) + x1;
456 
457  if (i == 0) {
458  mRFirst = r;
459 
460  Double_t ratio = x/r;
461  if (TMath::Abs(ratio) > 1.) {
462  if (ratio > 0) ratio = 1.;
463  else ratio = -1.;
464  }
465 
466  mAlphaFirst = TMath::ACos(ratio);
467  }
468 
469  if (i == 9) {
470  mRLast = r;
471 
472  Double_t ratio = x/r;
473  if (TMath::Abs(ratio) > 1.) {
474  if (ratio > 0) ratio = 1.;
475  else ratio = -1.;
476  }
477 
478  mAlphaLast = TMath::ACos(ratio);
479  }
480 
481  if (r < StFtpcTrackingParams::Instance()->OuterRadius() && r > StFtpcTrackingParams::Instance()->InnerRadius()) {
482  nmax++;
483  }
484  }
485 
486  mNMax = nmax;
487 
488  return;
489 }
490 
491 
492 Double_t StFtpcTrack::CalcDca(StFtpcVertex *vertex, Bool_t primaryFit)
493 {
494  // Calculates distance of closest approach to vertex.
495 
496  // call fit class
497  MomentumFit(primaryFit ? vertex : 0);
498  StThreeVector<Double_t> vertexPos(vertex->GetX(), vertex->GetY(), vertex->GetZ());
499  return distance(vertexPos);
500 }
501 
502 
503 void StFtpcTrack::CalcResiduals(Bool_t primaryFit) {
504  // Calculates the residuals to the momentum fit helix for each point.
505 
506  StThreeVector<Double_t> nv(0., 0., 1.);
507 
508  for (Int_t i = 0; i < mPoints->GetEntriesFast(); i++) {
509  // loop over all points on track
510  StFtpcPoint *hit = (StFtpcPoint*)mPoints->At(i);
511  StThreeVector<Double_t> hitpos(hit->GetX(), hit->GetY(), hit->GetZ());
512 
513  Double_t pl = pathLength(hitpos, nv);
514  Double_t x_hel = x(pl);
515  Double_t y_hel = y(pl);
516  Double_t x_hit = hit->GetX();
517  Double_t y_hit = hit->GetY();
518 
519  if (primaryFit) {
520  hit->SetXPrimResidual(x_hit - x_hel);
521  hit->SetYPrimResidual(y_hit - y_hel);
522  hit->SetRPrimResidual(TMath::Sqrt(x_hit*x_hit + y_hit*y_hit) - TMath::Sqrt(x_hel*x_hel + y_hel*y_hel));
523  hit->SetPhiPrimResidual(TMath::ATan2(y_hit, x_hit) - TMath::ATan2(y_hel, x_hel));
524  }
525 
526  else { // global fit
527  hit->SetXGlobResidual(x_hit - x_hel);
528  hit->SetYGlobResidual(y_hit - y_hel);
529  hit->SetRGlobResidual(TMath::Sqrt(x_hit*x_hit + y_hit*y_hit) - TMath::Sqrt(x_hel*x_hel + y_hel*y_hel));
530  hit->SetPhiGlobResidual(TMath::ATan2(y_hit, x_hit) - TMath::ATan2(y_hel, x_hel));
531  }
532  }
533 
534  return;
535 }
536 
537 
538 void StFtpcTrack::Fit()
539 {
540  // call fit class
541  MomentumFit();
542 
543  mP.SetX(momentum().x());
544  mP.SetY(momentum().y());
545  mP.SetZ(momentum().z());
546  mChiSq[0] = chi2Rad();
547  mChiSq[1] = chi2Lin();
548  mTheta = momentum().theta();
549 
550  return;
551 }
552 
553 
554 void StFtpcTrack::Fit(StFtpcVertex *vertex, Double_t max_Dca, Bool_t primary_fit)
555 {
556  // Fitting.
557 
558  // call fit class
559  MomentumFit();
560  CalcGlobResiduals();
561 
562  // tracks are treated as the particles fly
563  StFtpcPoint *firstP = (StFtpcPoint *)mPoints->At(GetNumberOfPoints()-1);
564  StFtpcPoint *lastP = (StFtpcPoint *)mPoints->At(0);
565 
566  StThreeVector<Double_t> vertexPos(vertex->GetX(), vertex->GetY(), vertex->GetZ());
567  StThreeVector<Double_t> lastPoint(lastP->GetX(), lastP->GetY(), lastP->GetZ());
568  StThreeVector<Double_t> firstPoint;
569  StThreeVector<Double_t> nv(0., 0., 1.);
570 
571  mDca = distance(vertexPos);
572 
573  if (!primary_fit) { // global fit
574  firstPoint = StThreeVector<Double_t>(firstP->GetX(), firstP->GetY(), firstP->GetZ());
575 
576  if (mDca > max_Dca) {
577  mFromMainVertex = (Bool_t)kFALSE;
578  }
579 
580  else {
581  mFromMainVertex = (Bool_t)kTRUE;
582  }
583  }
584 
585  else { // primary fit
586 
587  if (mDca > max_Dca) { // no refit
588  firstPoint = StThreeVector<Double_t>(firstP->GetX(), firstP->GetY(), firstP->GetZ());
589  mFromMainVertex = (Bool_t)kFALSE;
590  }
591 
592  else {
593  MomentumFit(vertex); // refit
594  if (pathLength(lastPoint, nv) >= NoSolution/2){
595  LOG_WARN << "NoSolution found for MomentumFit with primary vertex - set mFromMainVertex = kFALSE for track " <<mTrackNumber<< endm;
596  mFromMainVertex = (Bool_t)kFALSE;
597  }
598  else {
599  CalcPrimResiduals();
600 
601  firstPoint = StThreeVector<Double_t>(vertexPos.x(), vertexPos.y(), vertexPos.z());
602  mFromMainVertex = (Bool_t)kTRUE;
603  mDca = distance(vertexPos); // change dca (even if this dca isn't very useful)
604  }
605  }
606  }
607 
608  Double_t pl = pathLength(firstPoint, nv);
609  mTrackLength = pathLength(lastPoint, nv);
610 
611  mP.SetX(momentum().x());
612  mP.SetY(momentum().y());
613  mP.SetZ(momentum().z());
614  mV.SetX(x(pl));
615  mV.SetY(y(pl));
616  mV.SetZ(z(pl));
617  mL.SetX(x(mTrackLength));
618  mL.SetY(y(mTrackLength));
619  mL.SetZ(z(mTrackLength));
620 
621  mChiSq[0] = chi2Rad();
622  mChiSq[1] = chi2Lin();
623  mFitRadius = 1./curvature();
624  mTheta = mP.Theta();
625 
626  if (vertex->GetId() == 0) { // no vertex found, tracking done with arbitray vertex at 0., 0., 0.
627  mDca = 0.; // set dca to zero
628  }
629 
630  return;
631 }
632 
633 
634 void StFtpcTrack::MomentumFit(StFtpcVertex *vertex)
635 {
636  Double_t xWeight[11], yWeight[11];
637  Double_t xval[11], yval[11], zval[11];
638  Double_t xhelix[11], yhelix[11], zhelix[11];
639  Int_t i, j;
640 
641  mIterSteps = 10;
642  mYCenter = 0.;
643  mXCenter = 0.;
644 
645  if (vertex) {
646  //additional point needed
647  mVertexPointOffset = 1;
648 
649  //vertex used as additional point on track
650  xval[0] = vertex->GetX() * centimeter;
651  yval[0] = vertex->GetY() * centimeter;
652  zval[0] = vertex->GetZ() * centimeter;
653 
654  // use vertex error as weight (if it exists)
655  xWeight[0] = (vertex->GetXerr() == 0.) ? 100. : 1./(vertex->GetXerr() * centimeter);
656  yWeight[0] = (vertex->GetYerr() == 0.) ? 100. : 1./(vertex->GetYerr() * centimeter);
657  }
658 
659  else {
660  //no additional point needed
661  mVertexPointOffset = 0;
662  }
663 
664  Int_t backw_counter = 0;
665  // initialize position arrays
666  // these values will later be manipulated, mPoint array will not be touched
667  for(i = 0; i < GetNumberOfPoints(); i++) {
668  backw_counter = GetNumberOfPoints() - 1 - i + mVertexPointOffset;
669  StFtpcPoint *point = (StFtpcPoint*)mPoints->At(i);
670 
671  xval[backw_counter] = point->GetX() * centimeter;
672  yval[backw_counter] = point->GetY() * centimeter;
673  zval[backw_counter] = point->GetZ() * centimeter;
674 
675  // hit resolution taken from hit error (or set to 100)
676  xWeight[backw_counter] = (point->GetXerr() == 0.) ? 100. : 1./(point->GetXerr() * centimeter);
677  yWeight[backw_counter] = (point->GetYerr() == 0.) ? 100. : 1./(point->GetYerr() * centimeter);
678  }
679 
681  // calculate first guess momentum from helix fit
683 
684  CircleFit(xval, yval, xWeight, yWeight, GetNumberOfPoints() + mVertexPointOffset);
685  LineFit(xval, yval, zval, xWeight, yWeight, GetNumberOfPoints() + mVertexPointOffset);
686 
687  // determine helix parameters
688  Double_t dipAngle = fabs(atan(1/(mFitRadius*mArcSlope)));
689 
690  if (zval[1] < 0) {
691  dipAngle *= -1;
692  }
693 
694  Double_t startPhase = atan((yval[0]-mYCenter)/(xval[0]-mXCenter));
695 
696  if (xval[0]-mXCenter < 0) {
697  startPhase += pi;
698  }
699 
700  else if (yval[0]-mYCenter < 0) {
701  startPhase += twopi;
702  }
703 
704  Int_t orientation = 1;
705 
706  if (mArcSlope * zval[1] < 0) {
707  orientation = -1;
708  }
709 
710  // create helix
711  Double_t startAngle = mArcOffset + mArcSlope * zval[0];
712  Double_t startX = mXCenter + mFitRadius * cos(startAngle);
713  Double_t startY = mYCenter + mFitRadius * sin(startAngle);
714 
715  StThreeVector<Double_t> startHit(startX, startY, zval[0]);
716  setParameters(1/mFitRadius, dipAngle, startPhase, startHit, orientation);
717 
718  // get z-component of B-field at 0,0,0 for first momentum guess
719  Float_t pos[3] = {0., 0., 0.};
720  Float_t centralField[3];
721  StFtpcTrackingParams::Instance()->MagField()->B3DField(pos, centralField);
722  centralField[0] *= kilogauss;
723  centralField[1] *= kilogauss;
724  centralField[2] *= kilogauss;
725  mZField = (Double_t) centralField[2];
726 
727  // get momentum at track origin and charge
728  StThreeVector<Double_t> rv(0., 0., zval[0]);
729  StThreeVector<Double_t> nv(0., 0., 1.);
730  Double_t pl = pathLength(rv, nv);
731  mHelixMomentum = momentumAt(pl, mZField);
732  SetCharge(charge(mZField));
733 
734  // store helix fitted hit positions
735  for(i = 0; i < GetNumberOfPoints() + mVertexPointOffset; i++) {
736  StThreeVector<Double_t> rvec(0., 0., zval[i]);
737  StThreeVector<Double_t> nvec(0., 0., 1.);
738  Double_t plength = pathLength(rvec, nvec);
739  if (plength >= NoSolution/2) {
740  LOG_WARN << "Helix Fit found NoSolution for hit " << i <<" - not possible to track helix momentum through measured field for this track"<< endm;
741  return;
742  }
743  xhelix[i] = x(plength);
744  yhelix[i] = y(plength);
745  zhelix[i] = z(plength);
746  }
747 
749  // track helix momentum through measured field:
751 
752  // initialize position and momentum
753  StThreeVector<Double_t> currentPosition(xhelix[0 + mVertexPointOffset],
754  yhelix[0 + mVertexPointOffset],
755  zhelix[0 + mVertexPointOffset]);
756  pl = pathLength(currentPosition, nv);
757  StThreeVector<Double_t> currentMomentum(momentumAt(pl, mZField));
758 
759 
760  if (StFtpcTrackingParams::Instance()->MagFieldFactor()) {
761 
762  // iterate over points
763  Double_t stepSize;
764 
765  for(i = 1 + mVertexPointOffset; i < GetNumberOfPoints() + mVertexPointOffset; i++) {
766  stepSize = (zval[i] - zval[i-1]) / mIterSteps;
767 
768  // iterate between points
769  for(j = 0; j < mIterSteps; j++) {
770  // store momentum for position propagation
771  Double_t propagateXMomentum = currentMomentum.x();
772  Double_t propagateYMomentum = currentMomentum.y();
773  Double_t propagateZMomentum = currentMomentum.z();
774 
775  // get local magnetic field
776  Float_t positionArray[3] = {(Float_t) (currentPosition.x()),
777  (Float_t) (currentPosition.y()),
778  (Float_t) (currentPosition.z() + stepSize/2)};
779  Float_t localField[3];
780  StFtpcTrackingParams::Instance()->MagField()->B3DField(positionArray, localField);
781 
782  StThreeVector<Double_t> fieldVector
783  ((Double_t) localField[0] * kilogauss/tesla*c_light*nanosecond/meter,
784  (Double_t) localField[1] * kilogauss/tesla*c_light*nanosecond/meter,
785  (Double_t) localField[2] * kilogauss/tesla*c_light*nanosecond/meter);
786 
787  // calculate new momentum as helix segment
788  Double_t absMomentum = abs(currentMomentum);
789  StThreeVector<Double_t> perpField =
790  currentMomentum.cross(fieldVector) * (Double_t)mQ/absMomentum;
791  Double_t twistRadius = (absMomentum/abs(perpField)) * meter/GeV;
792 
793  Double_t stepLength = stepSize/cos(currentMomentum.theta());
794 
795  Double_t newMomentumCross = absMomentum*stepLength/twistRadius;
796  Double_t newMomentumParallel =
797  ::sqrt(absMomentum * absMomentum - newMomentumCross * newMomentumCross);
798  currentMomentum.setMagnitude(newMomentumParallel);
799  StThreeVector<Double_t> momentumChange(perpField);
800  momentumChange.setMagnitude(newMomentumCross);
801  currentMomentum = currentMomentum+momentumChange;
802 
803  // propagate position
804  propagateXMomentum = (propagateXMomentum + currentMomentum.x())/2;
805  propagateYMomentum = (propagateYMomentum + currentMomentum.y())/2;
806  propagateZMomentum = (propagateZMomentum + currentMomentum.z())/2;
807  currentPosition.setX(currentPosition.x() + stepSize *
808  (propagateXMomentum / propagateZMomentum));
809  currentPosition.setY(currentPosition.y() + stepSize *
810  (propagateYMomentum / propagateZMomentum));
811  currentPosition.setZ(currentPosition.z() + stepSize);
812  }
813 
814  // change position array to compensate for distortion
815  StThreeVector<Double_t> rvec(0., 0., zval[i]);
816  StThreeVector<Double_t> nvec(0., 0., 1.);
817  Double_t plength=pathLength(rvec, nvec);
818 
819  if (zval[1] > 0) {
820  xval[i] += (x(plength) - currentPosition.x());
821  yval[i] += (y(plength) - currentPosition.y());
822  }
823 
824  else {
825  xval[i] -= (x(plength) - currentPosition.x());
826  yval[i] -= (y(plength) - currentPosition.y());
827  }
828 
829  // calculate fit quality indicators only if needed
830  // Double_t distHitHelix=::sqrt((xval[i]-x(plength))*(xval[i]-x(plength))+(yval[i]-y(plength))*(yval[i]-y(plength)));
831  // Double_t distHelixFit=::sqrt((x(plength)-currentPosition.x())*(x(plength)-currentPosition.x())+(y(plength)-currentPosition.y())*(y(plength)-currentPosition.y()));
832 
833  }
834 
836  // refit helix
838 
839  CircleFit(xval, yval, xWeight, yWeight, GetNumberOfPoints()+mVertexPointOffset);
840  LineFit(xval, yval, zval, xWeight, yWeight, GetNumberOfPoints()+mVertexPointOffset);
841 
842  // determine helix parameters
843  dipAngle = fabs(atan(1/(mFitRadius*mArcSlope)));
844 
845  if (zval[1] < 0) {
846  dipAngle*=-1;
847  }
848 
849  startPhase = atan((yval[0]-mYCenter)/(xval[0]-mXCenter));
850 
851  if (xval[0] - mXCenter < 0) {
852  startPhase+=pi;
853  }
854 
855  else if (yval[0]-mYCenter<0) {
856  startPhase+=twopi;
857  }
858 
859  orientation = 1;
860 
861  if (mArcSlope * zval[1] < 0) {
862  orientation = -1;
863  }
864 
865  // set helix parameters to new values
866  startAngle = mArcOffset + mArcSlope * zval[0];
867  startX = mXCenter + mFitRadius * cos(startAngle);
868  startY = mYCenter + mFitRadius * sin(startAngle);
869  startHit.setX(startX);
870  startHit.setY(startY);
871 
872  setParameters(1/mFitRadius, dipAngle, startPhase, startHit, orientation);
873  }
874 
875  // set final momentum value
876  pl = pathLength(rv, nv);
877  mFullMomentum = momentumAt(pl, mZField);
878 }
879 
880 
882 // Circle fitting program
883 //
884 // This function will fit a circle to the points in the matrix x and y.
885 // 'num' is the number of points in x and y
886 // 'xc' is the found center in x
887 // 'yc' is the found center in y
888 // 'R' is the radius of the fitted circle
889 // 'chi2' error in fit
890 //
891 // Written by Mike Heffner Sept 21 1998
892 // error calculation added Oct 3 1998, Mike Heffner
893 // fit with point errors added May 1999 Holm Huemmler
894 //
895 // Fitting algorithm by: N.Chernov,G.Ososkov, Computer Physics
896 // Communications 33(1984) 329-333
898 
899 
900 Int_t StFtpcTrack::CircleFit(Double_t x[],Double_t y[], Double_t xw[], Double_t yw[], Int_t num)
901 {
902 #ifndef __IOSTREAM__
903 #include <Stiostream.h>
904 #endif
905 
906  Int_t i;
907  Int_t debug = 0; //set to 1 for debug messages
908 
909  if (num ==0 ) {
910  // added to remove error from zero input
911  return 0;
912  }
913 
914  //-------------------------------------------------
916  // calculate the center of gravity of the points.
917  // then transform to that origin
918  Double_t xav = 0;
919  Double_t yav = 0;
920  Double_t xwav = 0;
921  Double_t ywav = 0;
922  Double_t wei[11];
923 
924  for(i=0;i<num;i++) {
925  wei[i] = xw[i] + yw[i];
926  xav += x[i] * wei[i];
927  yav += y[i] * wei[i];
928  xwav += wei[i];
929  ywav += wei[i];
930  }
931 
932  xav = xav/xwav;
933  yav = yav/ywav;
934 
935  //gMessMgr->precision(16);
936 
937  if (debug) {
938  LOG_INFO << "from circle fitting program" << endm;
939  }
940 
941  for(i=0;i<num;i++) {
942 
943  if (debug) {
944  LOG_INFO << "x: " << x[i] << " y: " << y[i] << "xw: " << xw[i] << " yw: " << yw[i] << endm;
945  }
946 
947  x[i] = x[i] - xav;
948  y[i] = y[i] - yav;
949  }
950 
952  // calculate some moments of the points
953 
954  Double_t F = 0;
955  Double_t G = 0;
956  Double_t H = 0;
957  Double_t P = 0;
958  Double_t Q = 0;
959  Double_t T = 0;
960  Double_t gamma0 = 0;
961  Double_t wF = 0;
962  Double_t wG = 0;
963  Double_t wH = 0;
964  Double_t wP = 0;
965  Double_t wQ = 0;
966  Double_t wT = 0;
967  Double_t wgamma0 = 0;
968 
969  // change error parameters to 1d, 2d errors not usable in this fit
970  for(i = 0; i < num; i++) {
971  F += wei[i] * (3 * x[i] * x[i] + y[i] * y[i]);
972  wF += wei[i];
973  G += wei[i] * (x[i] * x[i] + 3 * y[i] * y[i]);
974  wG += wei[i];
975  H += wei[i] * 2 * x[i] *y[i];
976  wH += wei[i];
977  P += wei[i] * x[i] * (x[i] * x[i] + y[i] * y[i]);
978  wP += wei[i];
979  Q += wei[i] * y[i] * (x[i] * x[i] + y[i] * y[i]);
980  wQ += wei[i];
981  T += wei[i] * (x[i] * x[i] + y[i] * y[i]) * (x[i] * x[i] + y[i] * y[i]);
982  wT += wei[i];
983  gamma0 += wei[i] * (x[i] * x[i] + y[i] * y[i]);
984  wgamma0 += wei[i];
985  }
986 
987  gamma0 = gamma0/wgamma0;
988  F = F/wF;
989  G = G/wG;
990  H = H/wH;
991  P = P/wP;
992  Q = Q/wQ;
993  T = T/wT;
994 
995  Double_t A = -F -G;
996  Double_t B = F * G - T - H * H;
997  Double_t C = T * (F + G) - 2 * (P *P + Q * Q);
998  Double_t D = T * (H * H - F * G) + 2 * (P * P * G + Q * Q * F) - 4 * P * Q *H;
999 
1000  Double_t A0 = A / gamma0;
1001  Double_t B0 = B / (gamma0*gamma0);
1002  Double_t C0 = C / (gamma0*gamma0*gamma0);
1003  Double_t D0 = D / (gamma0*gamma0*gamma0*gamma0);
1004 
1006  // now solve the equation by Newton method
1007 
1008  Int_t MaxIter = 100;
1009  Double_t w = 1.;
1010  Double_t wNew = 0.;
1011  Double_t f = 0., fp = 0.;
1012  Double_t xc = 0., yc = 0.;
1013 
1014  if (debug) {
1015  LOG_INFO << "Solving by Newton method" << endm;
1016  }
1017 
1018  for(i = 0; i < MaxIter; i++) {
1019  f = w*w*w*w + A0 * w*w*w + B0 * w*w + C0 * w + D0;
1020  fp = 4 * w*w*w + 3 * A0 * w*w + 2 * B0 * w + C0;
1021  wNew = w - f / fp;
1022 
1023  if (debug) {
1024  LOG_INFO << "Iteration Number" << i << endm;
1025  }
1026 
1027  if ((wNew-w) < 10e-16 && (w-wNew) < 10e-16) {
1028  break;
1029  }
1030 
1031  w = wNew;
1032  }
1033 
1035  // compute the output variables
1036  Double_t gamma = gamma0 * wNew;
1037  Double_t b = (Q - H * P / (F - gamma)) / (G - gamma - H * H / (F - gamma));
1038  Double_t a = (P - H * b) / (F - gamma);
1039 
1040  Double_t R = 0;
1041  if ((wNew-w) < 10e-16 && (w-wNew) < 10e-16) {
1042  R = ::sqrt(a * a + b * b + gamma);
1043  xc = a + xav;
1044  yc = b + yav;
1045  }
1046 
1047  // compute chi2
1048  Double_t chi2 = 0.;
1049  Double_t variance = 0.;
1050  // Double_t wchi2=0;
1051  // for(i=0;i<num;i++)
1052  // {
1053  // x[i] = x[i] + xav;
1054  // y[i] = y[i] + yav;
1055 
1056  // Double_t err = R - ::sqrt(xw[i]*(x[i]-xc)*xw[i]*(x[i]-xc)
1057  // + yw[i]*(y[i]-yc)*yw[i]*(y[i]-yc));
1058  // chi2 += err*err;
1059  // wchi2 += xw[i]*xw[i]+yw[i]*yw[i];
1060  // }
1061  // chi2 *= num / wchi2;
1062 
1063 
1064  for (i = 0; i < num; i++) {
1065  x[i] = x[i] + xav;
1066  y[i] = y[i] + yav;
1067 
1068  Double_t err = R - ::sqrt((x[i] - xc) * (x[i] - xc) + (y[i] - yc) * (y[i] - yc));
1069  chi2 += err * err;
1070 
1071  if (i>0) {
1072  // approximation for sigma r, more precise using atan...
1073  variance += 1 / (xw[i] * xw[i]) + 1 / (yw[i] * yw[i]);
1074  }
1075  }
1076 
1077  variance /= (num-1);
1078  chi2 /= variance;
1079 
1080  mXCenter = xc;
1081  mYCenter = yc;
1082  mFitRadius = R;
1083  mChi2Rad = chi2;
1084 
1085  return 1;
1086 }
1087 
1088 void StFtpcTrack::LineFit(Double_t *xval, Double_t *yval, Double_t *zval, Double_t *xw, Double_t *yw, Int_t num)
1089 {
1090  Double_t x_ss = 0., x_sang = 0., x_sz = 0., x_szang = 0., x_szz = 0.;
1091  Double_t weight, t;
1092  Int_t i;
1093  Double_t angle = 0., lastangle = 0.;
1094 
1095  for(i = 0; i < num; i++) {
1096  // calculate angle and eliminate steps in atan function
1097  angle = atan((yval[i]-mYCenter)/(xval[i]-mXCenter));
1098 
1099  if (xval[i] - mXCenter < 0) {
1100  angle += pi;
1101  }
1102 
1103  else if (yval[i] - mYCenter < 0) {
1104  angle += twopi;
1105  }
1106 
1107  // shift into same phase
1108  if (i != 0) {
1109  if (angle>lastangle+pi) angle -= twopi;
1110  if (angle<lastangle-pi) angle += twopi;
1111  }
1112 
1113  lastangle = angle;
1114 
1115  // do sums
1116  weight = ::sqrt(xw[i] * xw[i] * cos(angle) * cos(angle)
1117  + yw[i] * yw[i] * sin(angle) * sin(angle));
1118  x_ss += weight;
1119  x_sang += weight * angle;
1120  x_sz += weight * zval[i];
1121  x_szang += weight * zval[i] * angle;
1122  x_szz += weight * zval[i] * zval[i];
1123  }
1124 
1125  t = x_ss * x_szz - x_sz * x_sz;
1126 
1127  if (t != 0) {
1128  mArcOffset = ((x_szz * x_sang) - (x_sz * x_szang)) / t;
1129  mArcSlope = ((x_ss * x_szang) - (x_sz * x_sang)) / t;
1130  }
1131 
1132  else {
1133  mArcOffset = 0;
1134  mArcSlope = 0;
1135  }
1136 
1137  Double_t chi2 = 0., variance = 0.;
1138 
1139  for(i = 0; i < num; i++) {
1140  Double_t angle = atan((yval[i] - mYCenter) / (xval[i] - mXCenter));
1141 
1142  if (xval[i]-mXCenter<0) {
1143  angle+=pi;
1144  }
1145 
1146  else if (yval[i] -mYCenter < 0) {
1147  angle += twopi;
1148  }
1149 
1150  Double_t lastangle = mArcOffset + mArcSlope*zval[i];
1151 
1152  // shift into same phase
1153  if (i != 0){
1154  if (angle>lastangle+pi) angle-=twopi;
1155  if (angle<lastangle-pi) angle+=twopi;
1156  }
1157 
1158  Double_t err = (angle - (mArcOffset + mArcSlope*zval[i]));
1159  chi2 += err*err;
1160 
1161  if (i>0) {
1162  // approximation for sigma r, more precise using atan...
1163  Double_t temp= ((1 / xw[i] * 1 / xw[i]) + (1 / yw[i] * 1 / yw[i]))
1164  * ((mArcSlope * (zval[i] - zval[0])) * (mArcSlope * (zval[i] - zval[0])))
1165  / ((xval[i] - xval[0]) * (xval[i] - xval[0]) + (yval[i] - yval[0]) * (yval[i] - yval[0]));
1166  variance += temp;
1167  }
1168  }
1169 
1170  variance /= (num-1);
1171  chi2 /= variance;
1172  mChi2Lin = chi2;
1173 }
1174 
1175 void StFtpcTrack::CalcGlobResiduals()
1176 {
1177  // calulates the global fit residuals for each point on track
1178 
1179  CalcResiduals((Bool_t)kFALSE);
1180 }
1181 
1182 
1183 void StFtpcTrack::CalcPrimResiduals()
1184 {
1185  // calulates the primary fit residuals for each point on track
1186 
1187  CalcResiduals((Bool_t)kTRUE);
1188 }
1189 
1190 
1191 Double_t StFtpcTrack::GetMeanAlpha()
1192 {
1193  // Returns mean phi angle of track.
1194 
1195  Double_t phi = mAlphaFirst+mAlphaLast;
1196 
1197  if (phi >= 2*TMath::Pi()) phi -= 2*TMath::Pi();
1198  else if (phi <= -2*TMath::Pi()) phi += 2*TMath::Pi();
1199 
1200  return phi/2.;
1201 }
1202 
1203 
1204 Double_t StFtpcTrack::GetPt() const
1205 {
1206  // Returns transverse momentum.
1207 
1208  return TMath::Sqrt(mP.X() * mP.X() + mP.Y() * mP.Y());
1209 }
1210 
1211 
1212 Double_t StFtpcTrack::GetP() const
1213 {
1214  // Returns total momentum.
1215 
1216  return TMath::Sqrt(mP.X() * mP.X() + mP.Y() * mP.Y() + mP.Z() * mP.Z());
1217 }
1218 
1219 
1220 Double_t StFtpcTrack::GetPseudoRapidity() const
1221 {
1222  // Returns the pseudo rapidity of the particle.
1223 
1224  return 0.5 * TMath::Log((GetP() + GetPz()) / (GetP() - GetPz()));
1225 }
1226 
1227 
1228 Double_t StFtpcTrack::GetEta() const
1229 {
1230  // This function returns the value of GetPseudoRapidity().
1231 
1232  return GetPseudoRapidity();
1233 }
1234 
1235 
1236 Double_t StFtpcTrack::GetRapidity() const
1237 {
1238  // Returns the rapidity of the particle with the assumption that the particle is a pion (+/-).
1239 
1240  return 0.5 * TMath::Log((M_PION_PLUS + GetPz()) / (M_PION_PLUS - GetPz()));
1241 }
1242 
1243 
1244 // momentum fit functions
1245 
1246 StThreeVector<Double_t> StFtpcTrack::helixMomentum() const
1247 {
1248  return mHelixMomentum;
1249 }
1250 
1251 
1252 StThreeVector<Double_t> StFtpcTrack::momentum() const
1253 {
1254  return mFullMomentum;
1255 }
1256 
1257 
1258 Double_t StFtpcTrack::chi2Rad() const
1259 {
1260  return mChi2Rad;
1261 }
1262 
1263 
1264 Double_t StFtpcTrack::chi2Lin() const
1265 {
1266  return mChi2Lin;
1267 }
1268 
1269 
1270 StThreeVector<Double_t> StFtpcTrack::localMomentum(Double_t s)
1271 {
1272  return momentumAt(s, mZField);
1273 }
1274 
1275 
void setParameters(double c, double dip, double phase, const StThreeVector< double > &o, int h)
starting point
Definition: StHelix.cc:139
double x(double s) const
coordinates of helix at point s
Definition: StHelix.hh:182
virtual void B3DField(const Float_t x[], Float_t B[])
Bfield in Cartesian coordinates - 3D field.
double distance(const StThreeVector< double > &p, bool scanPeriods=true) const
minimal distance between point and helix
Definition: StHelix.cc:240
pair< double, double > pathLength(double r) const
path length at given r (cylindrical r)
Definition: StHelix.cc:351