StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StEStructTrack.cxx
1 /**********************************************************************
2  *
3  * $Id: StEStructTrack.cxx,v 1.12 2013/02/08 19:32:52 prindle Exp $
4  *
5  * Author: Jeff Porter merge of code from Aya Ishihara and Jeff Reid
6  *
7  **********************************************************************
8  *
9  * Description: Persistent track information
10  *
11  **********************************************************************/
12 
13 #include "StEStructTrack.h"
14 #include "StPhysicalHelix.hh"
15 #include "SystemOfUnits.h"
16 
17 #ifndef ST_NO_NAMESPACES
18 using namespace units;
19 #endif
20 
21 ClassImp(StEStructTrack)
22 
23 // Setting BField is important when we read EStruct format events and we need to reconstruct the helix.
24 // We should somehow be getting BField from the file, or somewhere. Can change event to event in principle.
25 // For now we force person running EStruct correlation analysis to set BField appropriately.
26 // Set it to 0 when reading MuDst (and helix is calculated properly) or to the correct signed valuem to recalculate the helix.
27 // For 200 GeV AuAu run in 2011 following is good.
28 //Float_t StEStructTrack::BField = 4.9845;
29 Float_t StEStructTrack::BField = 4.9845;
30 
31 
32 StThreeVectorD StEStructTrack::PrimVertex = StThreeVectorD(0,0,0);
34  mPx = track->Px();
35  mPy = track->Py();
36  mPz = track->Pz();
37 
38  mEta = track->Eta();
39  mPhi = track->Phi();
40 
41  mBxPrimary = track->BxPrimary();
42  mByPrimary = track->ByPrimary();
43  mBzPrimary = track->BzPrimary();
44 
45  mBxGlobal = track->BxGlobal();
46  mByGlobal = track->ByGlobal();
47  mBzGlobal = track->BzGlobal();
48 
49  mPIDe_dEdx = track->PIDe_dEdx();
50  mPIDpi_dEdx = track->PIDpi_dEdx();
51  mPIDp_dEdx = track->PIDp_dEdx();
52  mPIDk_dEdx = track->PIDk_dEdx();
53  mPIDd_dEdx = track->PIDd_dEdx();
54 
55  mPIDe_ToF = track->PIDe_ToF();
56  mPIDpi_ToF = track->PIDpi_ToF();
57  mPIDp_ToF = track->PIDp_ToF();
58  mPIDk_ToF = track->PIDk_ToF();
59  mPIDd_ToF = track->PIDd_ToF();
60 
61  mChi2 = track->Chi2();
62  mBeta = track->beta();
63  mDedx = track->Dedx();
64  mAssignedMass=track->AssignedMass();
65 
66  mNFitPoints = track->NFitPoints();
67  mNFoundPoints = track->NFoundPoints();
68  mNMaxPoints = track->NMaxPoints();
69 
70  mDetectorID = track->DetectorID();
71  mFlag = track->Flag();
72 
73  mCharge = track->Charge();
74 
75  mMap[0] = track->TopologyMapData(0);
76  mMap[1] = track->TopologyMapData(1);
77  mTPCNHits = track->TopologyMapTPCNHits();
78 
79  mHelix = track->Helix();
80  //
81  // check to see if one can complete ... requires event level information
82  // such as bfield. If so, complete and set, if not set incomplete.
83  //
84  if(track->isComplete()){
85  FillTransientData();
86  mStartPos=track->StartPos();
87  FillTpcReferencePoints();
88  mIsComplete=true;
89  } else {
90  mIsComplete=false;
91  }
92 }
93 
94 //----------------------------------------------------------
95 void StEStructTrack::FillTransientData(){
96 
97  if (0 != StEStructTrack::BField) {
98  StThreeVectorD momentum(mPx,mPy,mPz);
99  StThreeVectorD origin(mBxPrimary,mByPrimary,mBzPrimary);
100  origin += StEStructTrack::PrimVertex;
101  mHelix = StPhysicalHelixD(momentum,origin,StEStructTrack::BField*kilogauss,mCharge);
102  }
103 
104  evalPt();
105  evalPtot();
106  evalYt();
107  evalXt();
108  evalCurvature();
109  evalFourMomentum();
110  evalMass();
111  evalPID();
112 
113 };
114 
115 //----------------------------------------------------------
116 void StEStructTrack::evalYt(){
117  float _r=mPt/0.13957;
118  mYt = log(sqrt(1+_r*_r)+_r);
119 
120  mytbin=(int) floor((mYt-1.0)/0.5);
121  if(mytbin>6)mytbin=6; // Why 6?
122  if(mytbin<0)mytbin=0;
123 };
124 
125 //----------------------------------------------------------
126 void StEStructTrack::evalXt(){
127  //
128  // cut and paste from Aya's code
129  //
130  // Aya calls this Xmt, it doesn't seem to be what she used for the XtXt paper, so I'll use the standard instead
131  /*float PionMass = 0.139;
132  float Temperature = 0.25;
133  float Minimum = (1+(PionMass/Temperature))*exp(-PionMass/Temperature);
134  float mtOnly = sqrt((mPx*mPx)+(mPy*mPy)+PionMass*PionMass);
135  mXt=1-(1+(mtOnly/Temperature))*exp(-mtOnly/Temperature)/Minimum;*/
136 
137  float PionMass = 0.139;
138  float mt = Mt(PionMass);
139  mXt = 1 - exp( -1*(mt-PionMass)/0.4 );
140 
141 };
142 
143 
144 //----------------------------------------------------------
145 void StEStructTrack::evalPID(){
146  // Combine dEdx and ToF information
147  // Our numbering: (should we maybe be more forward thinking, with room for e, Lambda, K0??)
148  // pi = 1
149  // K = 2
150  // p = 3
151 
152  // If there is ToF information and dEdx information require it to be consistent.
153  // For Hijing we seem to have mDedx = mBeta = 0. Use tight cuts on mPIDpi_dEdx etc.
154  float pi = fabs(mPIDpi_dEdx);
155  float k = fabs(mPIDk_dEdx);
156  float p = fabs(mPIDp_dEdx);
157  int dpi = 0;
158  int dK = 0;
159  int dp = 0;
160  int mPID_dEdx = 0;
161  if (mDedx > 0) {
162  mPID_dEdx = 1;
163  if (fabs(pi)<2) {
164  dpi = 1;
165  if (fabs(k)>2 && fabs(p)>2) {
166  dpi = 2;
167  mPID_dEdx = 2;
168  }
169  }
170  if (fabs(k)<2) {
171  dK = 1;
172  if (fabs(pi)>2 && fabs(p)>2) {
173  dK = 2;
174  mPID_dEdx = 2;
175  }
176  }
177  if (fabs(p)<2) {
178  dp = 1;
179  if (fabs(pi)>2 && fabs(k)>2) {
180  dp = 2;
181  mPID_dEdx = 2;
182  }
183  }
184  }
185 
186  // Something like 30% of tracks have no ToF?
187  // Is a ToF hit that is not within a PID band more important than a missing ToF hit?
188 // The widths of the mass bands expand rapidly with p_t, so pi and K have a big overlap by 1.5 GeV/c.
189 // Try a hard mass cut as it appears the yields fall off so there is little ambiguity.
190  double tnpi = mPIDpi_ToF;
191  double tnK = mPIDk_ToF;
192  double tnp = mPIDp_ToF;
193  int tpi = 0;
194  int tK = 0;
195  int tp = 0;
196  int mPID_ToF = 0;
197  if (mBeta > 0) {
198  mPID_ToF = 1;
199  if (0.05 < mMass && mMass <= 0.25) {
200  mPID_ToF = 2;
201  tpi = 2;
202  } else if (0.4 < mMass && mMass <= 0.65) {
203  mPID_ToF = 2;
204  tK = 2;
205  } else if (0.8 < mMass && mMass <= 1.15) {
206  mPID_ToF = 2;
207  tp = 2;
208  }
209  }
210 
211  if (mPID_dEdx==2 && mPID_ToF==2) {
212  // Both ToF and dEdx identified particle. Require they agree.
213  if (dpi==2 && tpi==2) {
214  mPID = 1;
215  } else if (dK==2 && tK==2) {
216  mPID = 2;
217  } else if (dp==2 && tp==2) {
218  mPID = 3;
219  } else {
220  mPID = 0;
221  }
222  } else if (mPID_dEdx==2) {
223  // Only dEdx identified particle. ToF can be ambiguous but must be consistent if it is there
224  if (mPID_ToF==1) {
225  if (dpi==2 && tpi==1) {
226  mPID = 1;
227  } else if (dK==2 && tK==1) {
228  mPID = 2;
229  } else if (dp==2 && tp==1) {
230  mPID = 3;
231  } else {
232  mPID = 0;
233  }
234  } else {
235  if (dpi==2) {
236  mPID = 1;
237  } else if (dK==2) {
238  mPID = 2;
239  } else if (dp==2) {
240  mPID = 3;
241  } else {
242  mPID = 0;
243  }
244  }
245  } else if (mPID_ToF==2) {
246  // Only ToF identified particle. dEdx can be ambiguous but must be consistent if it is there
247  if (mPID_dEdx==1) {
248  if (tpi==2 && dpi==1) {
249  mPID = 1;
250  } else if (tK==2 && dK==1) {
251  mPID = 2;
252  } else if (tp==2 && dp==1) {
253  mPID = 3;
254  } else {
255  mPID = 0;
256  }
257  } else {
258  if (tpi==2) {
259  mPID = 1;
260  } else if (tK==2) {
261  mPID = 2;
262  } else if (tp==2) {
263  mPID = 3;
264  } else {
265  mPID = 0;
266  }
267  }
268  } else if (0 == mDedx && 0 == mBeta) {
269  if (pi < 0.1 && tnpi < 0.1) {
270  mPID = 1;
271  } else if (k < 0.1 && tnK < 0.1) {
272  mPID = 2;
273  } else if (p < 0.1 && tnp < 0.1) {
274  mPID = 3;
275  } else {
276  mPID = 0;
277  }
278  } else {
279  mPID = 0;
280  }
281 };
282 
283 //----------------------------------------------------------
284 void StEStructTrack::evalCurvature(){
285  // store helix curvature.
286  // Seems that curvature from helix is _not_ signed.
287  // Sign of curvature is -helicity. (When magnetic field along +Z direction
288  // helicity of a positive particle is negative.)
289  double b = mHelix.h();
290  double c = mHelix.curvature();
291  mCurvature = -mHelix.h()*fabs(mHelix.curvature());
292 };
293 
294 
295 //----------------------------------------------------------
296 void StEStructTrack::evalFourMomentum(const float mass){
297 
298  float lMass=mass;
299  if(lMass<=0)lMass=0.13957;
300 
301  mFourMomentum.setPx(mPx);
302  mFourMomentum.setPy(mPy);
303  mFourMomentum.setPz(mPz);
304  mFourMomentum.setE(sqrt(mPt*mPt+mPz*mPz+lMass*lMass));
305 
306 }
307 
308 //----------------------------------------------------------
309 void StEStructTrack::FillTpcReferencePoints() {
310  // Uses fitted helix to calculate intersection points in the TPC
311 
312  static StThreeVectorF WestEnd(0.,0.,200.);
313  static StThreeVectorF EastEnd(0.,0.,-200.);
314  static StThreeVectorF EndCapNormal(0.,0.,1.0);
315 
316  // In this use, pathLength(r) returns the helix path length to the intersection of a cylinder with radius r.
317  // There are 2 mathematical solutions, so both are returned in the pairD class where first < second.
318  // If the first is <0 it is unphysical, so we would use the second.
319 
320  // The exit point is a special case, we need to find if the track exited the side or endcaps of TPC
321  pairD candidates = mHelix.pathLength(200.0);
322  double sideLength = (candidates.first > 0) ? candidates.first : candidates.second;
323  double endLength = mHelix.pathLength(WestEnd,EndCapNormal);
324  int endcap;
325  if (endLength < 0.0) {
326  endcap = +1;
327  endLength = mHelix.pathLength(EastEnd,EndCapNormal);
328  } else {
329  endcap = -1;
330  }
331  double firstExitLength = endLength;
332  if (endLength > sideLength) {
333  mEndCapOuter = 0;
334  firstExitLength = sideLength;
335  } else {
336  mEndCapOuter = endcap;
337  }
338  mNominalTpcExitPoint = mHelix.at(firstExitLength);
339 
340  candidates = mHelix.pathLength(50.0);
341  sideLength = (candidates.first > 0) ? candidates.first : candidates.second;
342  mNominalTpcEntrancePoint = mHelix.at(sideLength);
343 
344  // With cuts |\eta| < 1 and |V_z| < 50cm all tracks should cross 127cm radius before
345  // intersecting endcap. (Need to double check this is true for lowest momentum helix we accept.)
346  mMidTPCRadius = 127.0;
347  candidates = mHelix.pathLength(mMidTPCRadius);
348  sideLength = (candidates.first > 0) ? candidates.first : candidates.second;
349  mMidTpcPoint = mHelix.at(sideLength);
350 
351  // Add OuterMid point at 163.5. This is to help with my crossing cut for LS tracks that have different pt.
352  // Possible track may have excited via endcap at this radius.
353  mOuterMidTPCRadius = 163.5;
354  candidates = mHelix.pathLength(mOuterMidTPCRadius);
355  sideLength = (candidates.first > 0) ? candidates.first : candidates.second;
356  firstExitLength = endLength;
357  if (endLength > sideLength) {
358  mEndCapOuterMid = 0;
359  firstExitLength = sideLength;
360  } else {
361  mEndCapOuterMid = endcap;
362  }
363  mOuterMidTpcPoint = mHelix.at(firstExitLength);
364 
365  // Store maximum radius this track will get to. Not all tracks get to specific radii.
366  double curve = mHelix.curvature();
367  if (curve > 0.000001) {
368  mMaxRadius = 2/curve;
369  } else {
370  mMaxRadius = 99999.0; // Arbitrary number bigger than anything we care about.
371  }
372  // Store radius of track intersection with endcap.
373  StThreeVectorF vendcap = mHelix.at(endLength);
374  mEndCapRadius = sqrt(vendcap.x()*vendcap.x() + vendcap.y()*vendcap.y());
375 
376  mIsComplete=true; // finished with calculations
377 
378 }
379 
380 
381 //----------------------------------------------------------
382 // older stuff ... should look at some time in the future ...
383 //----------------------------------------------------------
384 
385 Float_t StEStructTrack::Pt() const { return mPt; };
386 Float_t StEStructTrack::Ptot() const { return mPtot; };
387 
388 Float_t StEStructTrack::Mt(Float_t mass) const {
389  return sqrt((mPt*mPt)+(mass*mass));
390 }
391 
392 Float_t StEStructTrack::E(Float_t mass) const {
393  return sqrt((mPt*mPt)+(mPz*mPz)+(mass*mass));
394 }
395 
396 Float_t StEStructTrack::Yt(Float_t mass) const {
397  if (0 == mass) {
398  return mYt;
399  } else {
400  Float_t E = this->E(mass);
401  return 0.5*log((E+mPt)/(E-mPt));
402  }
403 }
404 
405 Float_t StEStructTrack::Eta(Float_t mass) const {
406  if (0 == mass) {
407  return mEta;
408  } else {
409  return this->Rapidity(mass);
410  }
411 }
412 
413 Float_t StEStructTrack::Rapidity(Float_t mass) const {
414  Float_t E = this->E(mass);
415  return 0.5*log((E+mPz)/(E-mPz));
416 }
417 
418 Float_t StEStructTrack::Dca() const {
419  return (sqrt((mBxPrimary*mBxPrimary)+(mByPrimary*mByPrimary)+(mBzPrimary*mBzPrimary)));
420 }
421 
422 Float_t StEStructTrack::DcaPrimary() const {
423  return (sqrt((mBxPrimary*mBxPrimary)+(mByPrimary*mByPrimary)+(mBzPrimary*mBzPrimary)));
424 }
425 
426 Float_t StEStructTrack::DcaGlobal() const {
427  return (sqrt((mBxGlobal*mBxGlobal)+(mByGlobal*mByGlobal)+(mBzGlobal*mBzGlobal)));
428 }
429 
430 /**********************************************************************
431  *
432  * $Log: StEStructTrack.cxx,v $
433  * Revision 1.12 2013/02/08 19:32:52 prindle
434  * Added "Triggered" histograms in StEStruct2ptCorrelations.
435  * Protected against using tracks cuts in StEStruct2ptCorrelations when reading EStruct format events.
436  * Added comment in EventMaker/StEStructTrack.cxx pointing out need to set BField correctly
437  * when reading EStruct format events. (This should be read from file somehow, but...)
438  *
439  * Revision 1.11 2012/11/16 21:24:37 prindle
440  * Changes to support reading/writing of EStructEvent. Fill helix as transient and
441  * get BField from file (?).
442  *
443  * Revision 1.10 2011/08/02 20:36:57 prindle
444  * Event: modifications for ZDCCoincidence
445  * Track: big changes in evalPID. These should be superseded when TOF-dEdx
446  * space is understood better.
447  *
448  * Revision 1.9 2010/09/02 21:26:29 prindle
449  * Track: Added ToF pid information, modify dEdx, add combined pid code.
450  *
451  * Revision 1.8 2010/03/02 21:47:18 prindle
452  * Support to retrieve track radius when it crosses endplate
453  * Add way to retrieve centrality
454  *
455  * Revision 1.7 2008/12/02 23:45:48 prindle
456  * Added curvature and calculation of OuterMidTpcPoint.
457  *
458  * Revision 1.6 2006/02/22 22:06:07 prindle
459  * Removed all references to multRef (?)
460  *
461  * Revision 1.5 2005/09/14 17:21:19 msd
462  * Simplified helix fitting by taking helix from mudst instead of calculating from scratch
463  *
464  * Revision 1.4 2005/07/07 19:31:13 fisyak
465  * Add default for mHelix
466  *
467  * Revision 1.3 2005/03/03 01:32:03 porter
468  * fixed a bug setting 4-momentum and added data (+accessors)
469  * to the track class
470  *
471  * Revision 1.2 2004/06/28 23:24:11 chunhuih
472  *
473  * added 'const' specification to some member functions, including some of the
474  * return types, so that they can be used by a const StEStructTrack object.
475  *
476  * Revision 1.1 2003/10/15 18:20:51 porter
477  * initial check in of Estruct Analysis maker codes.
478  *
479  *
480  *********************************************************************/
481 
482 
483 
484 
485 
486 
487 
488 
489 
490 
491