StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StMiniMcHelper.cxx
1 
22 #include "StMiniMcHelper.h"
23 #include <cmath>
24 #include "TMath.h"
25 
26 //#include "StPhysicalHelixD.hh"
27 #include "TRandom.h"
28 
29 // from ben norman.
30 // global X & Y coordinates of X unit vector in local coords, by sector
31 // (X => parallel to padrow in XY plane, right handed wrt Y)
32 static Double_t sectorX[] = {
33  0, 0,
34  0.866025403784439, -0.5,
35  0.5, -0.866025403784439,
36  0, -1,
37  -0.5, -0.866025403784439,
38  -0.866025403784439, -0.5,
39  -1, 0,
40  -0.866025403784439, 0.5,
41  -0.5, 0.866025403784438,
42  0, 1,
43  0.5, 0.866025403784439,
44  0.866025403784438, 0.5,
45  1, 0,
46  0.866025403784439, 0.5,
47  0.5, 0.866025403784438,
48  0, 1,
49  -0.5, 0.866025403784439,
50  -0.866025403784439, 0.5,
51  -1, 0,
52  -0.866025403784439, -0.5,
53  -0.5, -0.866025403784439,
54  0, -1,
55  0.5, -0.866025403784439,
56  0.866025403784438, -0.5,
57  1, 0
58 };
59 
60 // global X & Y coordinates of Y unit vector in local coords, by sector
61 // (Y => normal to padrow in XY plane, radially outward from Z axis)
62 static Double_t sectorY[] = {
63  0,0,
64  0.5, 0.866025403784439,
65  0.866025403784439, 0.5,
66  1, 0,
67  0.866025403784439, -0.5,
68  0.5, -0.866025403784439,
69  0, -1,
70  -0.5, -0.866025403784439,
71  -0.866025403784439, -0.5,
72  -1, 0,
73  -0.866025403784439, 0.5,
74  -0.5, 0.866025403784438,
75  0, 1,
76  -0.5, 0.866025403784439,
77  -0.866025403784439, 0.5,
78  -1, 0,
79  -0.866025403784439, -0.5,
80  -0.5, -0.866025403784439,
81  0, -1,
82  0.5, -0.866025403784439,
83  0.866025403784438, -0.5,
84  1, 0,
85  0.866025403784438, 0.5,
86  0.5, 0.866025403784439,
87  0, 1
88 };
89 
90 //--------------------------------------------------------------
91 /*
92  distance in 2d
93  */
94 
95 double distance(double a1, double b1, double a2, double b2){
96  return ::sqrt( (a1-b1)*(a1-b1) + (a2-b2)*(a2-b2) );
97 }
98 
99 /*
100  distance in 3d
101 */
102 double distance(const StThreeVectorF& point1,
103  const StThreeVectorF& point2)
104 {
105  return (point1-point2).mag();
106 }
107 
108 
109 double dca3d(const StPhysicalHelixD& helix, const StThreeVectorF& point)
110 {
111  return helix.distance(point);
112 
113 }
114 
115 double dca2d(const StPhysicalHelixD& helix, const StThreeVectorF& point,
116  const StThreeVectorF* origin)
117 {
118  if(fabs(helix.curvature())<=static_cast<double>(0)){
119  return lineDca2D(helix,point,*origin);
120  }
121  else{
122  return helixDca2D(helix,point);
123  }
124 }
125 
126 
127 //
128 // i like this one better. dip angle in s-z plane
129 // should be exact assuming a circle in x-y
130 // (redundant StTrack* for debugging)
131 double dcaz(const StPhysicalHelixD& helix, const StThreeVectorF& point,
132  const StTrack* track)
133 {
134  double z0 = helix.origin().z();
135  double phi = atan2(point.y()-helix.ycenter(),
136  point.x()-helix.xcenter());
137  int h = helix.h(); // -sign(q*B) (+ := ccw looking down from +z)
138  double dphi = h*(phi-helix.phase());
139 
140  // half circle assumption
141  dphi = (fabs(dphi) < M_PI ) ? dphi :
142  ((dphi<0) ? 2*M_PI + dphi : 2*M_PI - dphi);
143 
144  double arclength= (1./helix.curvature()) * dphi;
145 
146  double dcaZ = (point.z() - (z0 + arclength*tan(helix.dipAngle())));
147  /*
148  if(gRandom->Rndm(1)<0.1){
149  cout << "--------" << endl;
150  cout << "zpoint=" << point.z() << endl;
151  if(track)
152  cout << "pt=" << track->geometry()->momentum().perp()
153  << ",fit pts=" << track->fitTraits().numberOfFitPoints(kTpcId)
154  << endl;
155 
156  cout << ">>>zdca=" << dcaZ
157  << ", dphi=" << dphi*180./M_PI
158  << ", z0=" << z0 << ",arclength=" << arclength << endl
159  << ", dip=" << helix.dipAngle()*180./M_PI
160  << ", arc/tan(dip)="<< arclength/tan(helix.dipAngle()) << endl
161  << ">>>dca.z= " << point.z()-helix.at(helix.pathLength(point)).z()
162  << endl;
163  cout << "--------" << endl;
164  }
165  */
166  return dcaZ;
167 
168 }
169 
170 /*
171 double dcaz(const StPhysicalHelixD& helix, const StThreeVectorF& point)
172 {
173  pairD path = helix.pathLength(point.perp());
174 
175  const StThreeVectorD& pos1 = helix.at(path.first);
176  const StThreeVectorD& pos2 = helix.at(path.second);
177  const StThreeVectorD dis1 = point - pos1;
178  const StThreeVectorD dis2 = point - pos2;
179 
180  double dcaZ = (dis1.mag() < dis2.mag()) ? dis1.z() : dis2.z();
181  if(isnan(dcaZ)) return 999;
182  return dcaZ;
183 }
184 */
185 
186 double crossingAngle(const StPhysicalHelixD& helix,
187  const StTpcHit* hit, float bField)
188 {
189  if(fabs(helix.curvature())<=static_cast<double>(0)){
190  return lineCrossingAngle(helix,hit);
191  }
192  else{
193  return helixCrossingAngle(helix,hit,bField);
194  }
195 }
196 
197 double padrowDca(const StPhysicalHelixD& helix,
198  const StTpcHit* hit)
199 {
200  if(fabs(helix.curvature())<=static_cast<double>(0)){
201  return linePadrowDca(helix,hit);
202  }
203  else{
204  return helixPadrowDca(helix,hit);
205  }
206 }
207 
208 //-----------------------------------------------------
209 
210 
211 // from ben
212 
213 double
214 propagateToPadrow(const StPhysicalHelixD& helix,
215  const StTpcHit* hit)
216 {
217  // calculate intersection of helix (circle) with hit's padrow.
218  // There's a little trig to do, and 4 cases, but the net result is
219  // that if we define
220  //
221  // R = radius of helix's circular projection
222  // d = distance from center of circle to hit
223  // x = signed displacement from hit to track in sector's local x direction
224  // dHat = unit vector pointing from center to hit
225  // xHat = unit vector pointing along the padrow (x direction in sector's
226  // local coordinates)
227  // cos(theta) = dHat . xHat
228  //
229  // Then
230  //
231  // x = -d*cos(theta) +- ::sqrt(R^2 - d^2*(1-cos^2(theta)))
232  //
233  // '-' is used if cos(theta)<0, and '+' if cos(theta)>0. The overall sign
234  // is determined by whether or not the hit is in the circle, as above.
235 
236  double R = 1./helix.curvature();
237  double dX = hit->position().x() - helix.xcenter();
238  double dY = hit->position().y() - helix.ycenter();
239 
240  // before continuing, make sure that there *is* a solution, i.e., that the
241  // circle does intersect the padrow. We determine this by projecting the
242  // vector between the hit and the circle's center onto the padrow's radial
243  // normal. If this is >= R, we have no intersection and return the helix
244  // path length to the point nearest to the padrow.
245 
246  double d = TMath::Sqrt(dX*dX + dY*dY);
247  double dPerp = dX*sectorY[2*hit->sector()] +
248  dY*sectorY[2*hit->sector() + 1];
249 
250  double x;
251  if(dPerp >= R){
252  // this shouldn't happen for hi-pt, but...
253  //
254  // take cross product (Sin) to find displacement along padrow to point
255  // nearest circle
256  x = - dX*sectorY[2*hit->sector() + 1] + // padrow normal x d
257  dY*sectorY[2*hit->sector()];
258  }else{
259  // find analytic solution of intersection
260  double cosTheta = (dX*sectorX[2*hit->sector()] +
261  dY*sectorX[2*hit->sector() + 1])/d;
262 
263  x = -d*cosTheta + (cosTheta<0 ? -1. : 1.) *
264  TMath::Sqrt(R*R - d*d*(1 - cosTheta*cosTheta));
265  }
266 
267  // finally, propegate along local X direction x units from hit to track
268  // (reuse dX,dY)
269  dX = hit->position().x() + x*sectorX[2*hit->sector()];
270  dY = hit->position().y() + x*sectorX[2*hit->sector() + 1];
271 
272  /*
273  if(mDebug){
274  cout << " Position on helix & padrow in sector " << hit->sector()
275  << " closest to point '" << hit->position() << "' is (" << dX << ", "
276  << dY << "). ";
277  }
278  */
279  double s = helix.pathLength(dX, dY);
280 
281  /* non-analytic solution in helix, not used
282  // normal to plane
283  StThreeVectorD n(sectorY[2*hit->sector()], sectorY[2*hit->sector() + 1], 0);
284  // point on plane
285  double s = helix.pathLength(hit->position(), n);
286  */
287  return s;
288 
289 }
290 
291 
292 
293 double
294 helixPadrowDca(const StPhysicalHelixD& helix,
295  const StTpcHit* hit)
296 {
297  // let propegateToPadrow do the work of finding the intersection of
298  // the helix with the padrow
299  double s = propagateToPadrow(helix, hit);
300  double dX = hit->position().x() - helix.x(s);
301  double dY = hit->position().y() - helix.y(s);
302  double dca = TMath::Sqrt(dX*dX + dY*dY);
303 
304  // get our sign from the simple xyDca calculation
305  if (helixDca2D(helix, hit->position()) < 0) dca *= -1.;
306 
307  /*
308  if(mDebug){
309  cout << " Dca of helix '" << helix << "' to hit '"
310  << hit->position() << "' along padrow is " << dca << endl;
311  }
312  */
313  return dca;
314 }
315 
316 double helixCrossingAngle(float pt,float phi,int sector)
317 {
318  double px=pt*cos(phi);
319  double py=pt*sin(phi);
320  double cosTheta = (px*sectorY[2*sector] +
321  py*sectorY[2*sector + 1])/pt;
322 
323  if (cosTheta < 0){
324  cosTheta *= -1.;
325  px *= -1; py *= -1;
326  }
327 
328  double theta = TMath::ACos(cosTheta);
329  if (px*sectorY[2*sector + 1] -
330  py*sectorY[2*sector] > 0) theta *= -1.;
331 
332  // if(mDebug) cout << " finally theta=" << theta << endl;
333 
334  return theta;
335 }
336 
337 
338 double
339 helixCrossingAngle(const StPhysicalHelixD& helix,
340  const StTpcHit* hit,
341  float bField){
342 
343  // first, we need the track momentum direction at the hit's padrow.
344  double s = propagateToPadrow(helix, hit);
345 
346  // to suppress warning messages
347  StPhysicalHelixD helixTemp(helix);
348 
349  StThreeVectorD p(helixTemp.momentumAt(s, bField));
350 
351  // calculate the cosine of the angle between the radially outward normal
352  // to the padrow (i.e. the local Y unit vector) and the track tangent.
353  double cosTheta = (p.x()*sectorY[2*hit->sector()] +
354  p.y()*sectorY[2*hit->sector() + 1])/p.perp();
355 
356  /*
357  if(mDebug){
358  cout << " Cos of rossing angle of helixTemp '" << helixTemp << "' in sector "
359  << hit->sector() << " is " << cosTheta << ", ";
360  }
361  */
362  // if the cosine is negative, take the inverse of the momentum vector
363  // to bring it between 0 and pi/2.
364  if (cosTheta < 0){
365  cosTheta *= -1.;
366  p.setX(-p.x());
367  p.setY(-p.y());
368  }
369 
370  //if(mDebug) cout << " changed to " << cosTheta << ", ";
371 
372  // use the cross product to determine whether this angle should be
373  // negative or positive.
374  // if cross product is along positive z, then p was clockwise from sectorY
375  double theta = TMath::ACos(cosTheta);
376  if (p.x()*sectorY[2*hit->sector() + 1] -
377  p.y()*sectorY[2*hit->sector()] > 0) theta *= -1.;
378 
379  // if(mDebug) cout << " finally theta=" << theta << endl;
380 
381  return theta;
382 } // crossingAngle
383 
384 double helixDca2D(const StPhysicalHelixD &helix, const StThreeVectorF& point)
385 {
386  return (distance(helix.xcenter(),point.x(),helix.ycenter(),point.y())
387  -(1./helix.curvature()));
388 }
389 
390 /*
391  return StThreeVectorF of point on the line closet to the input point
392  in xy plane. z coordinate is ignored.
393 
394 */
395 
397 lineAt2d(const StPhysicalHelixD& helix,
398  const StThreeVectorF& point)
399 {
400  // note: phase for straight lines is defined as phase=psi-pi/2.
401  // where psi is the 'direction' the line is pointing.
402  // the relationship b/psi and the slope is
403  // slope = tan(psi).
404 
405  const StThreeVectorD& origin = helix.origin();
406  double cosPhase = cos(helix.phase());
407  double sinPhase = sin(helix.phase());
408 
409  double px = point.x();
410  double py = point.y();
411  double dx = px-origin.x();
412  double dy = py-origin.y();
413 
414  double s = cosPhase*dy-sinPhase*dx;
415 
416  // point on line closest to point in xy plane.
417  double xDca = origin.x() - s*sinPhase;
418  double yDca = origin.y() + s*cosPhase;
419 
420  StThreeVectorF vec(xDca,yDca,0); // z coordinate ignored
421  return vec;
422 }
423 
424 
425 
426 
427 double
428 linePadrowDca(const StPhysicalHelixD& helix,
429  const StTpcHit* hit)
430 {
431  // note: phase for straight lines is defined as phase=psi-pi/2.
432  // where psi is the 'direction' the line is pointing.
433  // the relationship b/psi and the slope is
434  // slope = tan(psi).
435 
436  // point on line closest to hit in xy plane.
437 
438  StThreeVectorF at = lineAt2d(helix,hit->position());
439 
440  // vector perpendicular to the line in xy
441  StThreeVectorF perp = (hit->position() - at);
442 
443  // padplane dca
444  double cosTheta =
445  (perp.x()*sectorX[2*hit->sector()] +
446  perp.y()*sectorX[2*hit->sector()+1])/perp.perp();
447 
448  double padrowDca = perp.perp()/fabs(cosTheta);
449 
450  // get sign from lineDca2D
451  StThreeVectorF origin(0,0,0);
452  double sign = lineDca2D(helix,hit->position(),origin);
453 
454  return (sign>=0) ? padrowDca : -padrowDca;
455 }
456 
457 double
458 lineCrossingAngle(const StPhysicalHelixD& helix,
459  const StTpcHit* hit)
460 {
461  // psi
462  double psi = helix.phase() + TMath::Pi()/2.;
463  double psiX = cos(psi);
464  double psiY = sin(psi);
465 
466  double cosTheta =
467  psiX*sectorY[2*hit->sector()] + psiY*sectorY[2*hit->sector()+1];
468 
469  // should never be negative
470  if(cosTheta<0){
471  cout << "%%% line crossing angle negative? "
472  << cosTheta << endl;
473  return 99;
474  }
475 
476  // sign from the cross product (psi X sector Normal).
477  double sign = psiX*sectorY[2*hit->sector()+1]-psiY*sectorY[2*hit->sector()];
478 
479  return (sign>0) ? acos(cosTheta) : -acos(cosTheta);
480 }
481 
482 double
483 lineCrossingAngle(const StPhysicalHelixD& helix,
484  const int sector)
485 {
486  // psi
487  double psi = helix.phase() + TMath::Pi()/2.;
488  double psiX = cos(psi);
489  double psiY = sin(psi);
490 
491  double cosTheta =
492  psiX*sectorY[2*sector] + psiY*sectorY[2*sector+1];
493 
494  // should never be negative
495  if(cosTheta<0){
496  cout << "%%% line crossing angle negative? "
497  << cosTheta << endl;
498  return 99;
499  }
500 
501  // sign from the cross product (psi X sector Normal).
502  double sign = psiX*sectorY[2*sector+1]-psiY*sectorY[2*sector];
503 
504  return (sign>0) ? acos(cosTheta) : -acos(cosTheta);
505 }
506 
507 double
508 lineDca2D(const StPhysicalHelixD& helix,
509  const StThreeVectorF& hit,
510  const StThreeVectorF& origin)
511 {
512  // point on line closest to hit (in xy plane)
513  StThreeVectorF atHit = lineAt2d(helix,hit);
514 
515  // point on line closest to 'origin' in xy
516  StThreeVectorF atOrigin = lineAt2d(helix,origin);
517 
518  // vector from atOrigin to atHit
519  StThreeVectorF origin2atHit = (atHit-atOrigin);
520 
521  // vector fom atOrigin to hit
522  StThreeVectorF origin2hit = (hit-atOrigin);
523 
524  // vector perpendicular to the line to hit.
525  StThreeVectorF dca = (hit-atHit);
526 
527  // sign determined from origin2atHit X orgin2hit
528  double cross = origin2atHit.x()*origin2hit.y()
529  - origin2atHit.y()*origin2hit.x();
530 
531  return (cross>=0) ? dca.perp() : - dca.perp();
532 
533 }
534 
535 //
536 // $Log $
537 //
int h() const
y-center of circle in xy-plane
Definition: StHelix.hh:174
double x(double s) const
coordinates of helix at point s
Definition: StHelix.hh:182
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
double ycenter() const
x-center of circle in xy-plane
Definition: StHelix.cc:215
const StThreeVector< double > & origin() const
-sign(q*B);
Definition: StHelix.hh:224
double xcenter() const
aziumth in xy-plane measured from ring center
Definition: StHelix.cc:207
double phase() const
1/R in xy-plane
Definition: StHelix.hh:180