View Javadoc

1   package org.lcsim.recon.tracking.trfcylplane;
2   
3   import org.lcsim.recon.tracking.trfbase.Propagator;
4   import org.lcsim.recon.tracking.trfbase.PropDirected;
5   import org.lcsim.recon.tracking.trfbase.PropDir;
6   import org.lcsim.recon.tracking.trfbase.TrackVector;
7   import org.lcsim.recon.tracking.trfbase.TrackDerivative;
8   import org.lcsim.recon.tracking.trfzp.PropZZ;
9   import org.lcsim.recon.tracking.trfbase.PropStat;
10  import org.lcsim.recon.tracking.trfutil.TRFMath;
11  import org.lcsim.recon.tracking.trfutil.Assert;
12  import org.lcsim.recon.tracking.trfxyp.SurfXYPlane;
13  import org.lcsim.recon.tracking.trfzp.SurfZPlane;
14  import org.lcsim.recon.tracking.trfbase.Surface;
15  import org.lcsim.recon.tracking.trfbase.VTrack;
16  import org.lcsim.recon.tracking.trfbase.ETrack;
17  
18  /**
19   * Propagates tracks from an XYPlane to a ZPlane in a constant magnetic field.
20   *<p>
21   * Propagation will fail if either the origin is not an XYPlane
22   * or destination is not a ZPlane.
23   * Propagator works incorrectly for tracks with very small curvatures.
24   *<p>
25   *@author Norman A. Graf
26   *@version 1.0
27   *
28   */
29  public class PropXYZ extends PropDirected
30  {
31      
32      // attributes
33      
34      private double _bfac;
35      private PropZZ _propzz;
36      
37      // Assign track parameter indices.
38      
39      private static final int IV = SurfXYPlane.IV;
40      private static final int   IZ   = SurfXYPlane.IZ;
41      private static final int   IDVDU = SurfXYPlane.IDVDU;
42      private static final int   IDZDU = SurfXYPlane.IDZDU;
43      private static final int   IQP_XY  = SurfXYPlane.IQP;
44      
45      private static final int   IX = SurfZPlane.IX;
46      private static final int   IY   = SurfZPlane.IY;
47      private static final int   IDXDZ = SurfZPlane.IDXDZ;
48      private static final int   IDYDZ = SurfZPlane.IDYDZ;
49      private static final int   IQP_Z  = SurfZPlane.IQP;
50      
51      // static methods
52      
53      
54      /**
55       *Return a String representation of the class' type name.
56       *Included for completeness with the C++ version.
57       *
58       * @return   A String representation of the class' type name.
59       */
60      public static String typeName()
61      { return "PropXYZ";
62      }
63      
64      /**
65       *Return a String representation of the class' type name.
66       *Included for completeness with the C++ version.
67       *
68       * @return   A String representation of the class' type name.
69       */
70      public static String staticType()
71      { return typeName();
72      }
73      
74      /**
75       *Construct an instance from a constant solenoidal magnetic field in Tesla.
76       *
77       * @param   bfield The magnetic field strength in Tesla.
78       */
79      public PropXYZ(double bfield)
80      {
81          _bfac = TRFMath.BFAC*bfield;
82          _propzz = new PropZZ(bfield);
83      }
84      
85      
86      /**
87       *Clone an instance.
88       *
89       * @return A Clone of this instance.
90       */
91      public Propagator newPropagator( )
92      {
93          return new PropXYZ( bField() );
94      }
95      
96      /**
97       *Propagate a track without error in the specified direction
98       *and return the derivative matrix in deriv.
99       *
100      * The track parameters for a cylinder are:
101      * phi z alpha tan(lambda) curvature
102      *
103      * @param   trv The VTrack to propagate.
104      * @param   srf The Surface to which to propagate.
105      * @param   dir The direction in which to propagate.
106      * @param   deriv The track derivatives to update at the surface srf.
107      * @return The propagation status.
108      */
109     public  PropStat vecDirProp( VTrack trv, Surface srf,
110             PropDir dir,TrackDerivative deriv)
111     {
112         PropStat pstat = new PropStat();
113         Propagator.reduceDirection(dir);
114         
115         // Check destination is a ZPlane.
116         Assert.assertTrue( srf.pureType().equals(SurfZPlane.staticType()) );
117         if ( !srf.pureType( ).equals(SurfZPlane.staticType()) )
118             return pstat;
119         
120         // Fetch phi of the destination plane
121         
122         VTrack trv0 = trv; // we wish to modify this track!
123         TrackDerivative deriv1 = new TrackDerivative();
124         TrackDerivative deriv2 = new TrackDerivative();
125         
126         if ( deriv != null )  pstat = vecTransformXYZ( _bfac, trv0, dir, deriv1 );
127         else pstat = vecTransformXYZ( _bfac, trv0, dir, deriv);
128         
129         if ( ! pstat.success() ) return pstat;
130         
131         if ( deriv != null ) pstat = _propzz.vecDirProp(trv0,srf,dir, deriv2);
132         else pstat = _propzz.vecDirProp(trv0,srf,dir, deriv);
133         
134         if ( pstat.success() )
135         {
136             //trv = trv0;
137             if ( deriv != null )  deriv.set(deriv2.times(deriv1));
138         }
139         
140         return pstat;
141     }
142     
143     /**
144      *Propagate a track without error in the specified direction.
145      *
146      * The track parameters for a cylinder are:
147      * phi z alpha tan(lambda) curvature
148      *
149      * @param   trv The VTrack to propagate.
150      * @param   srf The Surface to which to propagate.
151      * @param   dir The direction in which to propagate.
152      * @return The propagation status.
153      */
154     public  PropStat vecDirProp( VTrack trv, Surface srf,
155             PropDir dir)
156     {
157         TrackDerivative deriv = null;
158         return vecDirProp(trv, srf, dir, deriv);
159         
160     }
161     
162     /**
163      *Return the strength of the magnetic field in Tesla.
164      *
165      * @return The strength of the magnetic field in Tesla.
166      */
167     public double bField()
168     {
169         return _bfac/TRFMath.BFAC;
170     }
171     
172     
173     /**
174      *Return a String representation of the class' type name.
175      *Included for completeness with the C++ version.
176      *
177      * @return   A String representation of the class' type name.
178      */
179     public String type()
180     { return staticType();
181     }
182     
183     /**
184      *output stream
185      * @return  A String representation of this instance.
186      */
187     public String toString()
188     {
189         return "XYPlane-ZPlane propagation with constant "
190                 + bField() + " Tesla field";
191         
192     }
193     
194     
195     
196     //**********************************************************************
197     
198     // Private function to propagate a track without error
199     // The corresponding track parameters are:
200     // On ZPlane:
201     // z (cm) is fixed
202     // 0 - x (cm)
203     // 1 - y (cm)
204     // 2 - dx/dz
205     // 3 - dy/dz
206     // 4 - q/p   p is momentum of a track, q is its charge
207     // On XYPlane:
208     // u (cm) is fixed
209     // 0 - v (cm)
210     // 1 - z (cm)
211     // 2 - dv/du
212     // 3 - dz/du
213     // 4 - q/p   p is momentum of a track, q is its charge
214     // If deriv is nonzero, return the derivative matrix there.
215     
216     private PropStat
217             vecTransformXYZ( double B, VTrack trv,
218             PropDir dir,
219             TrackDerivative deriv)
220     {
221         
222         // construct return status
223         PropStat pstat = new PropStat();
224         
225         // fetch the originating surface and vector
226         Surface srf1 = trv.surface();
227         // TrackVector vec1 = trv.get_vector();
228         
229         // Check origin is a XYPlane.
230         Assert.assertTrue( srf1.pureType().equals(SurfXYPlane.staticType()) );
231         if ( !srf1.pureType( ).equals(SurfXYPlane.staticType()) )
232             return pstat;
233         SurfXYPlane sxyp1 = (SurfXYPlane) srf1;
234         
235         // Fetch the dist and phi of the plane and the starting track vector.
236         int iphi  = SurfXYPlane.NORMPHI;
237         int idist = SurfXYPlane.DISTNORM;
238         double sphi = sxyp1.parameter(iphi);
239         double    u = sxyp1.parameter(idist);
240         TrackVector vec = trv.vector();
241         double b1 = vec.get(IV);                  // v
242         double b2 = vec.get(IZ);                  // z
243         double b3 = vec.get(IDVDU);               // dv/du
244         double b4 = vec.get(IDZDU);               // dz/du
245         double b5 = vec.get(IQP_XY);              // q/p
246         
247         // check that dz != 0
248         if(b4 == 0.) return pstat;
249         
250         double zpos = b2;
251         double cos_sphi = Math.cos(sphi);
252         double sin_sphi = Math.sin(sphi);
253         
254         double a1 = u*cos_sphi - b1*sin_sphi;
255         double a2 = b1*cos_sphi + u*sin_sphi;
256         double a3 = cos_sphi/b4 - b3/b4*sin_sphi;
257         double a4 = b3/b4*cos_sphi + sin_sphi/b4;
258         double a5 = b5;
259         
260         
261         // if dz/du*du/dt > 0 and forward : dz>0; dz/du*du/dt < 0 dz<0
262         // if dz/du*du/dt < 0 and backward : dz>0; dz/du*du/dt > 0 dz<0
263         
264         int sign_du = 0;
265         if(trv.isForward())  sign_du =  1;
266         if(trv.isBackward()) sign_du = -1;
267         if(sign_du == 0)
268         {
269             System.out.println("PropXYZ._vec_propagate: Unknown direction of a track ");
270             System.exit(1);
271         }
272         
273         int sign_dz = 0;
274         if(b4*sign_du > 0) sign_dz =  1;
275         if(b4*sign_du < 0) sign_dz = -1;
276         
277         vec.set(IX     , a1);
278         vec.set(IY     , a2);
279         vec.set(IDXDZ  , a3);
280         vec.set(IDYDZ  , a4);
281         vec.set(IQP_Z  , a5);
282         
283         // Update trv
284         SurfZPlane szp = new SurfZPlane(zpos);
285         trv.setSurface(szp.newPureSurface());
286         trv.setVector(vec);
287         
288         // set new direction of the track
289         if(sign_dz ==  1) trv.setForward();
290         if(sign_dz == -1) trv.setBackward();
291         
292         // Set the return status.
293         pstat.setSame();
294         
295         // exit now if user did not ask for error matrix.
296         if ( deriv == null ) return pstat;
297         
298         double a34_hat = sign_dz*Math.sqrt(a3*a3 + a4*a4);
299         double a34_hat2 = a34_hat*a34_hat;
300         
301         double Rcos_phi = a3/Math.sqrt(1.+a34_hat2)*sign_dz;
302         double Rsin_phi = a4/Math.sqrt(1.+a34_hat2)*sign_dz;
303         
304         // ddphi / db
305         
306         double ddphi_db2 = -B*a5*Math.sqrt(a34_hat2+1.)*sign_dz;
307         double ddphi_db2_nob = -Math.sqrt(a34_hat2+1.)*sign_dz;
308         
309         // da3 / db
310         
311         double da3_db3 = -sin_sphi/b4;
312         double da3_db4 = (-cos_sphi + b3*sin_sphi)/(b4*b4);
313         
314         // da4 / db
315         
316         double da4_db3 =  cos_sphi/b4;
317         double da4_db4 = (- sin_sphi - b3*cos_sphi)/(b4*b4);
318         
319         // da1/ db
320         
321         double da1n_db1 = -sin_sphi;
322         double da1n_db2 = Rcos_phi*ddphi_db2_nob;
323         double da1n_db3 = 0.;
324         double da1n_db4 = 0.;
325         double da1n_db5 = 0.;
326         
327         // da2/ db
328         
329         double da2n_db1 = cos_sphi;
330         double da2n_db2 = Rsin_phi*ddphi_db2_nob;
331         double da2n_db3 = 0.;
332         double da2n_db4 = 0.;
333         double da2n_db5 = 0.;
334         
335         // da3/ db
336         
337         double da3n_db1 = 0.;
338         double da3n_db2 = -a4*ddphi_db2;
339         double da3n_db3 = da3_db3;
340         double da3n_db4 = da3_db4;
341         double da3n_db5 = 0.;
342         
343         // da4/ db
344         
345         double da4n_db1 = 0.;
346         double da4n_db2 = a3*ddphi_db2;
347         double da4n_db3 = da4_db3;
348         double da4n_db4 = da4_db4;
349         double da4n_db5 = 0.;
350         
351         // da5n
352         
353         double da5n_db1 = 0.;
354         double da5n_db2 = 0.;
355         double da5n_db3 = 0.;
356         double da5n_db4 = 0.;
357         double da5n_db5 = 1.;
358         
359         deriv.set(IX,IV        , da1n_db1);
360         deriv.set(IX,IZ        , da1n_db2);
361         deriv.set(IX,IDVDU     , da1n_db3);
362         deriv.set(IX,IDZDU     , da1n_db4);
363         deriv.set(IX,IQP_XY    , da1n_db5);
364         deriv.set(IY,IV        , da2n_db1);
365         deriv.set(IY,IZ        , da2n_db2);
366         deriv.set(IY,IDVDU     , da2n_db3);
367         deriv.set(IY,IDZDU     , da2n_db4);
368         deriv.set(IY,IQP_XY    , da2n_db5);
369         deriv.set(IDXDZ,IV     , da3n_db1);
370         deriv.set(IDXDZ,IZ     , da3n_db2);
371         deriv.set(IDXDZ,IDVDU  , da3n_db3);
372         deriv.set(IDXDZ,IDZDU  , da3n_db4);
373         deriv.set(IDXDZ,IQP_XY , da3n_db5);
374         deriv.set(IDYDZ,IV     , da4n_db1);
375         deriv.set(IDYDZ,IZ     , da4n_db2);
376         deriv.set(IDYDZ,IDVDU  , da4n_db3);
377         deriv.set(IDYDZ,IDZDU  , da4n_db4);
378         deriv.set(IDYDZ,IQP_XY , da4n_db5);
379         deriv.set(IQP_Z,IV     , da5n_db1);
380         deriv.set(IQP_Z,IZ     , da5n_db2);
381         deriv.set(IQP_Z,IDVDU  , da5n_db3);
382         deriv.set(IQP_Z,IDZDU  , da5n_db4);
383         deriv.set(IQP_Z,IQP_XY , da5n_db5);
384         
385         return pstat;
386     }
387     
388 }
389