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