View Javadoc

1   package org.lcsim.mc.fast.tracking;
2   
3   import Jama.util.Maths;
4   import hep.physics.matrix.SymmetricMatrix;
5   import Jama.Matrix;
6   import hep.physics.particle.Particle;
7   
8   import hep.physics.vec.BasicHep3Vector;
9   import hep.physics.vec.Hep3Vector;
10  import hep.physics.vec.VecOp;
11  import org.lcsim.constants.Constants;
12  import org.lcsim.event.MCParticle;
13  
14  /**
15   * Holds DOCA parameters and error matrix of track. Can be initialized with a MC truth particle. <br>
16   *
17   * @author Tony Johnson, Wolfgang Walkowiak
18   * @version $Id: DocaTrackParameters.java,v 1.9 2007/10/16 18:16:50 cassell Exp $
19   */
20  public class DocaTrackParameters implements TrackParameters {
21      private Hep3Vector m_pdoca_ref = null;
22      private Hep3Vector m_xdoca_ref = null;
23      private Hep3Vector m_xref = null;
24      private SymmetricMatrix m_err = new SymmetricMatrix(5);
25      private double[] m_parm = new double[5];
26      private double m_Bz = 0.;
27      private double m_chi2 = -1.;
28      private double m_l0 = 0.;
29      private double m_l_ref = 0.;
30      private int m_ndf = 5;
31  
32      // ====================================================
33      //
34      // Constructors
35      //
36      // ====================================================
37      public DocaTrackParameters(double bField) {
38          reset();
39          m_Bz = bField;
40      }
41  
42      public DocaTrackParameters(MCParticle p, double bField) {
43          this(bField, p.getMomentum(), p.getOrigin(), p.getCharge());
44      }
45  
46      public DocaTrackParameters(double bField, Particle p) {
47          this(bField, p.getMomentum(), p.getOrigin(), p.getType().getCharge());
48      }
49  
50      public DocaTrackParameters(double bField, Hep3Vector momentum, Hep3Vector x, double q) {
51          reset();
52          m_Bz = bField;
53          calculateDoca(momentum, x, q);
54      }
55  
56      public DocaTrackParameters(double bField, double[] momentum, double[] x, double q) {
57          reset();
58          m_Bz = bField;
59          calculateDoca(momentum, x, q);
60      }
61  
62      public DocaTrackParameters(double bField, double[] momentum, double[] x, double q, SymmetricMatrix errorMatrix) {
63          this(bField, momentum, x, q);
64          this.m_err = errorMatrix;
65      }
66  
67      public DocaTrackParameters(double bField, double[] parameters) {
68          m_Bz = bField;
69          m_parm = parameters;
70      }
71  
72      public DocaTrackParameters(double bField, double[] parameters, SymmetricMatrix errorMatrix) {
73          this(bField, parameters);
74          this.m_err = errorMatrix;
75      }
76  
77      public DocaTrackParameters(double bField, double[] parameters, SymmetricMatrix errorMatrix, double chi2) {
78          this(bField, parameters);
79          this.m_err = errorMatrix;
80          setChi2(chi2);
81      }
82  
83      public DocaTrackParameters(double bField, double[] parameters, SymmetricMatrix errorMatrix, double chi2, int ndf) {
84          this(bField, parameters);
85          this.m_err = errorMatrix;
86          setChi2(chi2);
87          setNDF(ndf);
88      }
89  
90      public double getD0() {
91          return m_parm[0];
92      }
93  
94      /**
95       * Get the error matrix as a 2-D array
96       * @see #getTrackParameter
97       */
98      public SymmetricMatrix getErrorMatrix() {
99          return m_err;
100     }
101 
102     /**
103      * Get momentum at DOCA.
104      */
105     public double[] getMomentum() {
106         return new double[] { getPX(), getPY(), getPZ() };
107     }
108 
109     public double getOmega() {
110         return m_parm[2];
111     }
112 
113     public double getPX() {
114         return getPt() * Math.cos(m_parm[1]);
115     }
116 
117     public double getPY() {
118         return getPt() * Math.sin(m_parm[1]);
119     }
120 
121     public double getPZ() {
122         return getPt() * m_parm[4];
123     }
124 
125     public double getPhi0() {
126         return m_parm[1];
127     }
128 
129     /**
130      * Get total momentum at DOCA.
131      */
132     public double getPtot() {
133         return Math.sqrt((getPX() * getPX()) + (getPY() * getPY()) + (getPZ() * getPZ()));
134     }
135 
136     public double getTanL() {
137         return m_parm[4];
138     }
139 
140     /**
141      * Get an individual track parameter. <br>
142      *
143      * The track parameters for LCD are defined as follows
144      * <table>
145      * <tr>
146      * <th>Index</th>
147      * <th>Meaning</th>
148      * </tr>
149      * <tr>
150      * <td>0</td>
151      * <td>d0 = XY impact parameter</td>
152      * <tr>
153      * <tr>
154      * <td>1</td>
155      * <td>phi0</td>
156      * <tr>
157      * </td>
158      * <tr>
159      * <tr>
160      * <td>2</td>
161      * <td>omega = 1/curv.radius (negative for negative tracks)</td>
162      * <tr>
163      * <tr>
164      * <td>3</td>
165      * <td>z0 = z of track (z impact parameter)</td>
166      * <tr>
167      * <tr>
168      * <td>4</td>
169      * <td>s = tan lambda</td>
170      * <tr>
171      * </table>
172      * @param i The index of the track parameter
173      * @return The track parameter with the specified index
174      *
175      *         All parameters are given at the DOCA.
176      */
177     public double getTrackParameter(int i) {
178         return m_parm[i];
179     }
180 
181     /**
182      * Get the track parameters as an array
183      * @see #getTrackParameter
184      */
185     public double[] getTrackParameters() {
186         return m_parm;
187     }
188 
189     /**
190      * Get the unit charge, ie +1, 0, -1.
191      */
192     public int getUnitCharge() {
193         if (m_Bz != 0) {
194             return (int) Math.signum(m_parm[2]);
195         } else {
196             return 0;
197         }
198     }
199 
200     public double getZ0() {
201         return m_parm[3];
202     }
203 
204     /**
205      * Get cos(Theta) as calculated from the momentum vector at the DOCA. <br>
206      *
207      * Note: This is the same as getCosTheta()
208      */
209 
210     public double magnitude() {
211         return Math.sqrt(VecOp.dot(getDocaVec(), getDocaVec()));
212     }
213 
214     public double magnitudeSquared() {
215         return VecOp.dot(getDocaVec(), getDocaVec());
216     }
217 
218     public double[] v() {
219         return getDoca();
220     }
221 
222     // IHep3Vector methods
223     public double x() {
224         return getDocaX();
225     }
226 
227     public double y() {
228         return getDocaY();
229     }
230 
231     public double z() {
232         return getDocaZ();
233     }
234 
235     /**
236      * Store the chi2.
237      */
238     void setChi2(double chi2) {
239         m_chi2 = chi2;
240     }
241 
242     /**
243      * Return the chi2 from smearing. <br>
244      *
245      * Note: The chi2 is to be calculated and stored by the smearing routine using setChi2().
246      */
247     double getChi2() {
248         return m_chi2;
249     }
250 
251     /**
252      * get cos(theta) at DOCA.
253      */
254     double getCosTheta() {
255         return getPZ() / getPtot();
256     }
257 
258     /**
259      * Get coordinates of DOCA.
260      */
261     double[] getDoca() {
262         return new double[] { getDocaX(), getDocaY(), getDocaZ() };
263     }
264 
265     double[] getDocaMomentum(double[] refPoint) {
266         return getDocaMomentumVec(refPoint).v();
267     }
268 
269     /**
270      * Calculate and get Doca momentum on track with respect to any space point.
271      */
272     Hep3Vector getDocaMomentumVec(Hep3Vector refPoint) {
273         if ((refPoint.x() != 0.) || (refPoint.y() != 0.)) {
274             checkCalcDoca(refPoint);
275 
276             return m_pdoca_ref;
277         } else {
278             return getMomentumVec();
279         }
280     }
281 
282     Hep3Vector getDocaMomentumVec(double[] refPoint) {
283         return getDocaMomentumVec(new BasicHep3Vector(refPoint[0], refPoint[1], refPoint[2]));
284     }
285 
286     double[] getDocaPosition(double[] refPoint) {
287         return getDocaPositionVec(refPoint).v();
288     }
289 
290     // ====================================================
291     //
292     // methods
293     //
294     // ====================================================
295 
296     /**
297      * Calculate and get Doca position on track with respect to any space point.
298      */
299     Hep3Vector getDocaPositionVec(Hep3Vector refPoint) {
300         if ((refPoint.x() != 0.) || (refPoint.y() != 0.)) {
301             checkCalcDoca(refPoint);
302 
303             return m_xdoca_ref;
304         } else {
305             return getDocaVec();
306         }
307     }
308 
309     Hep3Vector getDocaPositionVec(double[] refPoint) {
310         return getDocaPositionVec(new BasicHep3Vector(refPoint[0], refPoint[1], refPoint[2]));
311     }
312 
313     /**
314      * Calculate and get path length on track for a doca to any space point in respect to the track defining doca (with respect to the origin). The length l is given in the transverse plane. <br>
315      * Use L = l*tan(lambda) to convert.
316      */
317     double getDocaTransversePathLength(Hep3Vector refPoint) {
318         if ((refPoint.x() != 0.) || (refPoint.y() != 0)) {
319             checkCalcDoca(refPoint);
320 
321             return m_l_ref;
322         } else {
323             return 0.;
324         }
325     }
326 
327     double getDocaTransversePathLength(double[] refPoint) {
328         return getDocaTransversePathLength(new BasicHep3Vector(refPoint[0], refPoint[1], refPoint[2]));
329     }
330 
331     /**
332      * Get coordinates of DOCA.
333      */
334     Hep3Vector getDocaVec() {
335         return new BasicHep3Vector(getDocaX(), getDocaY(), getDocaZ());
336     }
337 
338     double getDocaX() {
339         return (-m_parm[0] * Math.sin(m_parm[1]));
340     }
341 
342     double getDocaY() {
343         return (m_parm[0] * Math.cos(m_parm[1]));
344     }
345 
346     double getDocaZ() {
347         return (m_parm[3]);
348     }
349 
350     /**
351      * Set the (transverse) path length l0 to original track vertex.
352      */
353     void setL0(double l0) {
354         m_l0 = l0;
355     }
356 
357     /**
358      * Get the (transverse) path length l0 to original track vertex.
359      */
360     double getL0() {
361         return m_l0;
362     }
363 
364     double[] getMomentum(double l) {
365         return getMomentumVec(l).v();
366     }
367 
368     /**
369      * Calculate and get momentum on track with respect to any path length l on track (l in xy plane).
370      */
371     Hep3Vector getMomentumVec(double l) {
372         double phi0 = m_parm[1];
373         double omega = m_parm[2];
374         double tanl = m_parm[4];
375 
376         int iq = getUnitCharge();
377 
378         double phi = phi0 + (omega * l);
379         double pt = Constants.fieldConversion * iq * m_Bz / omega;
380 
381         double px = pt * Math.cos(phi);
382         double py = pt * Math.sin(phi);
383         double pz = pt * tanl;
384 
385         // System.out.println("l: "+l+" p: ("+px+", "+py+", "+pz+")");
386         return new BasicHep3Vector(px, py, pz);
387     }
388 
389     Hep3Vector getMomentumVec() {
390         return new BasicHep3Vector(getPX(), getPY(), getPZ());
391     }
392 
393     /**
394      * Change the number degrees of freedom.
395      */
396     void setNDF(int ndf) {
397         m_ndf = ndf;
398     }
399 
400     /**
401      * Get the number degrees of freedom.
402      *
403      * Default is 5 unless changed with setNDF().
404      */
405     int getNDF() {
406         return m_ndf;
407     }
408 
409     double[] getPosition(double l) {
410         return getPositionVec(l).v();
411     }
412 
413     /**
414      * Calculate and get position on track with respect to any path length l on track (l in xy plane).
415      */
416     Hep3Vector getPositionVec(double l) {
417         double d0 = m_parm[0];
418         double phi0 = m_parm[1];
419         double omega = m_parm[2];
420         double z0 = m_parm[3];
421         double tanl = m_parm[4];
422 
423         double phi = phi0 + l * omega;
424         double rho = 1 / omega;
425 
426         double x = (rho * Math.sin(phi)) - ((rho + d0) * Math.sin(phi0));
427         double y = (-rho * Math.cos(phi)) + ((rho + d0) * Math.cos(phi0));
428         double z = z0 + (l * tanl);
429 
430         return new BasicHep3Vector(x, y, z);
431     }
432 
433     /**
434      * Get transverse momentum at DOCA.
435      */
436     double getPt() {
437         if (m_parm[2] != 0.) {
438             return Math.abs(Constants.fieldConversion * m_Bz / m_parm[2]);
439         } else {
440             return 0.;
441         }
442     }
443 
444     /**
445      * Get theta angle at DOCA.
446      */
447     double getTheta() {
448         return Math.atan2(getPt(), getPZ());
449     }
450 
451     /**
452      * Calculate the error matrix for the momentum for a point on the track specified by l. Result is given as a 3x3 array for the matrix.
453      */
454     SymmetricMatrix calcMomentumErrorMatrix(double l) {
455         double rho = 1. / getOmega();
456         double phi = getPhi0() + (getOmega() * l);
457         double tanl = getTanL();
458         double c = Constants.fieldConversion * Math.abs(m_Bz);
459         double sphi = Math.sin(phi);
460         double cphi = Math.cos(phi);
461 
462         Matrix tMatrix = new Matrix(5, 3, 0.);
463         tMatrix.set(1, 0, -c * rho * sphi);
464         tMatrix.set(1, 1, c * rho * cphi);
465         tMatrix.set(2, 0, (-c * rho * rho * cphi) - (c * rho * l * sphi));
466         tMatrix.set(2, 1, (-c * rho * rho * sphi) + (c * rho * l * cphi));
467         tMatrix.set(2, 2, -c * rho * rho * tanl);
468         tMatrix.set(4, 2, c * rho);
469 
470         Matrix errorMatrix = Maths.toJamaMatrix(getErrorMatrix());
471         Matrix pErrorMatrix = tMatrix.transpose().times(errorMatrix.times(tMatrix));
472 
473         return new SymmetricMatrix(Maths.fromJamaMatrix(pErrorMatrix));
474     }
475 
476     /**
477      * Calculate the error matrix for the position coordinates for a point on the track specified by l. Result is given as a 3x3 array for the matrix.
478      */
479     double[][] calcPositionErrorMatrix(double l) {
480         double d0 = getD0();
481         double rho = 1. / getOmega();
482         double phi = getPhi0() + (getOmega() * l);
483         double sphi0 = Math.sin(getPhi0());
484         double cphi0 = Math.cos(getPhi0());
485         double sphi = Math.sin(phi);
486         double cphi = Math.cos(phi);
487 
488         Matrix tMatrix = new Matrix(5, 3, 0.);
489         tMatrix.set(0, 0, -sphi0);
490         tMatrix.set(0, 1, cphi0);
491         tMatrix.set(1, 0, (rho * cphi) - ((rho + d0) * cphi0));
492         tMatrix.set(1, 1, (rho * sphi) - ((rho + d0) * sphi0));
493         tMatrix.set(2, 0, (rho * l * cphi) - (rho * rho * (sphi - sphi0)));
494         tMatrix.set(2, 1, (rho * l * sphi) + (rho * rho * (cphi - cphi0)));
495         tMatrix.set(3, 2, 1.);
496         tMatrix.set(4, 2, l);
497 
498         Matrix errorMatrix = Maths.toJamaMatrix(getErrorMatrix());
499 
500         // MyContext.println(MyContext.getHeader());
501         // MyContext.printMatrix("Error matrix:",errorMatrix,10,15);
502         // MyContext.printMatrix("Transf matrix:",tMatrix,10,15);
503         Matrix xErrorMatrix = tMatrix.transpose().times(errorMatrix.times(tMatrix));
504 
505         return xErrorMatrix.getArrayCopy();
506     }
507 
508     // ====================================================
509     //
510     // private methods
511     //
512     // ====================================================
513 
514     /*
515      * Calculate the DOCA for a set of parameters with respect to the origin.
516      */
517     private void calculateDoca(double[] momentum, double[] trackPoint, double q) {
518         Hep3Vector p = new BasicHep3Vector(momentum[0], momentum[1], momentum[2]);
519         Hep3Vector x = new BasicHep3Vector(trackPoint[0], trackPoint[1], trackPoint[2]);
520         calculateDoca(p, x, q);
521     }
522 
523     /*
524      * Calculate the DOCA for a set of parameters in vectors with respect to the origin.
525      */
526     private void calculateDoca(Hep3Vector momentum, Hep3Vector trackPoint, double charge) {
527         reset();
528 
529         Hep3Vector xOrigin = new BasicHep3Vector(0., 0., 0.);
530 
531         Hep3Vector[] result = calculateDoca(momentum, trackPoint, charge, xOrigin);
532         Hep3Vector xdoca = result[0];
533         Hep3Vector pdoca = result[1];
534         Hep3Vector dphdl = result[2];
535 
536         int iq = (int) (charge / Math.abs(charge));
537         double pt = Math.sqrt((pdoca.x() * pdoca.x()) + (pdoca.y() * pdoca.y()));
538 
539         // now calculate track parameters
540         double d0 = Math.sqrt((xdoca.x() * xdoca.x()) + (xdoca.y() * xdoca.y()));
541         if (VecOp.cross(xdoca, pdoca).z() > 0) {
542             d0 = -d0;
543         }
544 
545         double phi0 = Math.atan2(pdoca.y(), pdoca.x());
546         if (phi0 > Math.PI) {
547             phi0 -= (2 * Math.PI);
548         }
549         if (phi0 < -Math.PI) {
550             phi0 += (2 * Math.PI);
551         }
552 
553         double omega = Constants.fieldConversion * iq * m_Bz / pt;
554         double tanl = pdoca.z() / pt;
555         double z0 = xdoca.z();
556 
557         // now fill trackparameters
558         m_parm[0] = d0;
559         m_parm[1] = phi0;
560         m_parm[2] = omega;
561         m_parm[3] = z0;
562         m_parm[4] = tanl;
563 
564         // save the distance to orignial track vertex
565         m_l0 = -dphdl.y();
566 
567         // System.out.println("DocaTrackParameters: xdoca = ("+
568         // xdoca.x()+", "+xdoca.y()+", "+xdoca.z()+")");
569         // System.out.println("DocaTrackParameters: pdoca = ("+
570         // pdoca.x()+", "+pdoca.y()+", "+pdoca.z()+")");
571         // System.out.println("DocaTrackParameters: d0: "+m_parm[0]+
572         // " phi0: "+m_parm[1]+" omega: "+m_parm[2]+
573         // " z0: "+m_parm[3]+" tanl: "+m_parm[4]);
574         // System.out.println("DocaTrackParameters: m_l0 = "+m_l0);
575     }
576 
577     /*
578      * Calculate DOCA position and momentum vectors with respect to any space point.
579      */
580     private Hep3Vector[] calculateDoca(Hep3Vector momentum, Hep3Vector trackPoint, double charge, Hep3Vector refPoint) {
581         // subtract refPoint
582         Hep3Vector xp = VecOp.sub(trackPoint, refPoint);
583 
584         int iq = (int) (charge / Math.abs(charge));
585         double pt = Math.sqrt((momentum.x() * momentum.x()) + (momentum.y() * momentum.y()));
586         double tanl = momentum.z() / pt;
587         double rho = pt / (m_Bz * Constants.fieldConversion);
588 
589         BasicHep3Vector xdoca;
590         Hep3Vector pdoca;
591         Hep3Vector dphdl;
592 
593         // System.out.println("calculateDoca: m_flip: "+m_flip+" iq: "+iq);
594         if (xp.magnitude() > 0.) // no need for calculation if xp = (0,0,0) !
595         {
596             // calculate position and momentum at doca
597             Hep3Vector nzv = new BasicHep3Vector(0., 0., iq);
598             Hep3Vector xxc = new BasicHep3Vector(VecOp.cross(momentum, nzv).x(), VecOp.cross(momentum, nzv).y(), 0.);
599             Hep3Vector nxxc = VecOp.unit(xxc);
600             BasicHep3Vector xc = (BasicHep3Vector) VecOp.add(xp, VecOp.mult(rho, nxxc));
601             xc.setV(xc.x(), xc.y(), 0.);
602 
603             Hep3Vector nxc = VecOp.unit(xc);
604 
605             BasicHep3Vector catMC = (BasicHep3Vector) VecOp.cross(nzv, nxc);
606             catMC.setV(catMC.x(), catMC.y(), 0.);
607 
608             Hep3Vector ncatMC = VecOp.unit(catMC);
609 
610             pdoca = new BasicHep3Vector(pt * ncatMC.x(), pt * ncatMC.y(), momentum.z());
611 
612             double dphi = Math.asin(VecOp.cross(nxxc, nxc).z());
613             double dl = -dphi * rho * iq;
614 
615             xdoca = (BasicHep3Vector) VecOp.add(xc, VecOp.mult(-rho, nxc));
616             xdoca.setV(xdoca.x(), xdoca.y(), xp.z() + (dl * tanl));
617 
618             // save dphi and dl
619             dphdl = new BasicHep3Vector(dphi, dl, 0.);
620         } else {
621             xdoca = (BasicHep3Vector) xp;
622             pdoca = momentum;
623             dphdl = new BasicHep3Vector();
624         }
625 
626         // add refPoint back in again
627         xdoca = (BasicHep3Vector) VecOp.add(xdoca, refPoint);
628 
629         return new Hep3Vector[] { xdoca, pdoca, dphdl };
630     }
631 
632     /*
633      * Calculate Doca for this track with respect to any space point, if this has not been done before.
634      */
635     private void checkCalcDoca(Hep3Vector refPoint) {
636         // hassle with calculation only, if not done before yet!
637         if ((m_xref == null) || (refPoint.x() != m_xref.x()) || (refPoint.y() != m_xref.y()) || (refPoint.z() != m_xref.z())) {
638             m_xref = refPoint;
639 
640             // find doca vectors
641             Hep3Vector xdoca = getDocaVec();
642             Hep3Vector pdoca = getMomentumVec();
643             int iq = getUnitCharge();
644 
645             // calculate doca to refPoint
646             Hep3Vector[] result = calculateDoca(pdoca, xdoca, (double) iq, refPoint);
647             m_xdoca_ref = result[0];
648             m_pdoca_ref = result[1];
649 
650             // distance along track to original point
651             m_l_ref = result[2].y();
652         }
653     }
654 
655     private void reset() {
656         for (int i = 0; i < 5; i++) {
657             m_parm[i] = 0;
658             for (int j = 0; j <= i; j++) {
659                 m_err.setElement(i, j, 0);
660             }
661         }
662         m_l0 = 0.;
663     }
664 
665     void setErrorMatrix(SymmetricMatrix error) {
666         m_err = error;
667     }
668 }