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.trfbase.PropStat;
9   import org.lcsim.recon.tracking.trfutil.TRFMath;
10  import org.lcsim.recon.tracking.trfutil.Assert;
11  import org.lcsim.recon.tracking.trfcyl.SurfCylinder;
12  import org.lcsim.recon.tracking.trfzp.SurfZPlane;
13  import org.lcsim.recon.tracking.trfzp.PropZZ;
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 a Cylinder to a ZPlane in a constant magnetic field.
20   *<p>
21   * Propagation will fail if either the origin is not a Cylinder
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  
30  public class PropCylZ extends PropDirected
31  {
32      
33      // Assign track parameter indices.
34      private static final int   IX = SurfZPlane.IX;
35      private static final int   IY   = SurfZPlane.IY;
36      private static final int   IDXDZ = SurfZPlane.IDXDZ;
37      private static final int   IDYDZ = SurfZPlane.IDYDZ;
38      private static final int   IQP_Z  = SurfZPlane.IQP;
39      
40      private static final int   IPHI = SurfCylinder.IPHI;
41      private static final int   IZ_CYL= SurfCylinder.IZ;
42      private static final int   IALF = SurfCylinder.IALF;
43      private static final int   ITLM = SurfCylinder.ITLM;
44      private static final int   IQPT  = SurfCylinder.IQPT;
45      
46      
47      // attributes
48      
49      private double _bfac;
50      private PropZZ _propzz;
51      
52      
53      // static methods
54      
55      /**
56       *Return a String representation of the class' type name.
57       *Included for completeness with the C++ version.
58       *
59       * @return   A String representation of the class' type name.
60       */
61      public static String typeName()
62      { return "PropCylZ";
63      }
64      
65      /**
66       *Return a String representation of the class' type name.
67       *Included for completeness with the C++ version.
68       *
69       * @return   A String representation of the class' type name.
70       */
71      public static String staticType()
72      { return typeName();
73      }
74      
75      /**
76       *Construct an instance from a constant solenoidal magnetic field in Tesla.
77       *
78       * @param   bfield The magnetic field strength in Tesla.
79       */
80      public PropCylZ(double bfield)
81      {
82          _bfac = TRFMath.BFAC*bfield;
83          _propzz = new PropZZ(bfield);
84          
85      }
86      
87      /**
88       *Clone an instance.
89       *
90       * @return A Clone of this instance.
91       */
92      public Propagator newPropagator( )
93      {
94          return new PropCylZ( bField() );
95          
96      }
97      
98      /**
99       *Propagate a track without error in the specified direction.
100      *
101      * The track parameters for a cylinder are:
102      * phi z alpha tan(lambda) curvature
103      *
104      * @param   trv The VTrack to propagate.
105      * @param   srf The Surface to which to propagate.
106      * @param   dir The direction in which to propagate.
107      * @return The propagation status.
108      */
109     public PropStat vecDirProp( VTrack trv, Surface srf,
110             PropDir dir)
111     {
112         TrackDerivative deriv = null;
113         return vecDirProp(trv, srf, dir, deriv);
114         
115     }
116     
117     /**
118      *Propagate a track without error in the specified direction
119      *and return the derivative matrix in deriv.
120      *
121      * The track parameters for a cylinder are:
122      * phi z alpha tan(lambda) curvature
123      *
124      * @param   trv The VTrack to propagate.
125      * @param   srf The Surface to which to propagate.
126      * @param   dir The direction in which to propagate.
127      * @param   deriv The track derivatives to update at the surface srf.
128      * @return The propagation status.
129      */
130     public PropStat vecDirProp( VTrack trv, Surface srf,
131             PropDir dir, TrackDerivative deriv)
132     {
133         PropStat pstat = new PropStat();
134         Propagator.reduceDirection(dir);
135         // Check destination is a ZPlane.
136         Assert.assertTrue( srf.pureType().equals(SurfZPlane.staticType()) );
137         if ( !srf.pureType( ).equals(SurfZPlane.staticType()) )
138             return pstat;
139         
140         VTrack trv0 = trv; // want to change this vector
141         TrackDerivative deriv1 = new TrackDerivative();
142         TrackDerivative deriv2 = new TrackDerivative();
143         
144         if ( deriv != null ) pstat = vecTransformCylZ( _bfac, trv0, dir, deriv1 );
145         else pstat = vecTransformCylZ( _bfac, trv0, dir, deriv );
146         
147         if ( ! pstat.success() ) return pstat;
148         
149         if ( deriv != null ) pstat = _propzz.vecDirProp(trv0,srf,dir,deriv2);
150         else pstat = _propzz.vecDirProp(trv0,srf,dir, deriv);
151         
152         if ( pstat.success() )
153         {
154             trv = trv0;
155             if ( deriv != null )  deriv.set(deriv2.times(deriv1));
156         }
157         
158         return pstat;
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      *Return a String representation of the class' type name.
174      *Included for completeness with the C++ version.
175      *
176      * @return   A String representation of the class' type name.
177      */
178     public String type()
179     { return staticType();
180     }
181     
182     /**
183      *output stream
184      * @return  A String representation of this instance.
185      */
186     public String toString()
187     {
188         return "Cylinder-ZPlane propagation with constant "
189                 + bField() + " Tesla field";
190         
191     }
192     
193     //**********************************************************************
194     
195     // Private function to propagate a track without error
196     // The corresponding track parameters are:
197     // On ZPlane:
198     // z (cm) is fixed
199     // 0 - x (cm)
200     // 1 - y (cm)
201     // 2 - dx/dz
202     // 3 - dy/dz
203     // 4 - q/p   p is momentum of a track, q is its charge
204     // On Cylinder:
205     // r (cm) is fixed
206     // 0 - phi
207     // 1 - z (cm)
208     // 2 - alpha = phi_dir - phi; tan(alpha) = r*dphi/dr
209     // 3 - sin(lambda) = dz/ds; tan(lambda) = dz/dsT
210     // 4 - q/pT (1/GeV/c) (pT is component of p parallel to cylinder)
211     // If deriviv is nonzero, return the derivative matrix there.
212     
213     private PropStat
214             vecTransformCylZ( double B, VTrack trv,
215             PropDir dir,
216             TrackDerivative deriv )
217     {
218         
219         // construct return status
220         PropStat pstat = new PropStat();
221         
222         // fetch the originating surface and vector
223         Surface srf1 = trv.surface();
224         // TrackVector vec1 = trv.get_vector();
225         
226         // Check origin is a Cylinder.
227         Assert.assertTrue( srf1.pureType().equals(SurfCylinder.staticType()) );
228         if ( !srf1.pureType( ).equals(SurfCylinder.staticType()) )
229             return pstat;
230         SurfCylinder scy1 = ( SurfCylinder ) srf1;
231         
232         
233         // Fetch the R of the cylinder and the starting track vector.
234         int ir  = SurfCylinder.RADIUS;
235         double Rcyl = scy1.parameter(ir);
236         
237         TrackVector vec = trv.vector();
238         double c1 = vec.get(IPHI);                 // phi
239         double c2 = vec.get(IZ_CYL);               // z
240         double c3 = vec.get(IALF);                 // alpha
241         double c4 = vec.get(ITLM);                 // tan(lambda)
242         double c5 = vec.get(IQPT);                 // q/pt
243         
244         // check that dz != 0
245         if(c4 == 0.) return pstat;
246         
247         double zpos = c2;
248         double cos_c1 = Math.cos(c1);
249         double sin_c1 = Math.sin(c1);
250         double cos_dir = Math.cos(c1+c3);
251         double sin_dir = Math.sin(c1+c3);
252         double c4_hat2 = 1+c4*c4;
253         double c4_hat  = Math.sqrt(c4_hat2);
254         
255         double a1 = Rcyl*cos_c1;
256         double a2 = Rcyl*sin_c1;
257         double a3 = cos_dir/c4;
258         double a4 = sin_dir/c4;
259         double a5 = c5/c4_hat;
260         
261         
262         // if tan(lambda)=dz/dst > 0 : dz>0; dzdst < 0 dz<0
263         
264         int sign_dz = 0;
265         if(c4 > 0) sign_dz =  1;
266         if(c4 < 0) sign_dz = -1;
267         
268         vec.set(IX     , a1);
269         vec.set(IY     , a2);
270         vec.set(IDXDZ  , a3);
271         vec.set(IDYDZ  , a4);
272         vec.set(IQP_Z  , a5);
273         
274         // Update trv
275         SurfZPlane szp = new SurfZPlane(zpos);
276         trv.setSurface(szp.newPureSurface());
277         trv.setVector(vec);
278         
279         // set new direction of the track
280         if(sign_dz ==  1) trv.setForward();
281         if(sign_dz == -1) trv.setBackward();
282         
283         // Set the return status.
284         pstat.setSame();
285         
286         // exit now if user did not ask for error matrix.
287         if ( deriv == null ) return pstat;
288         
289         double a34_hat = sign_dz*Math.sqrt(a3*a3 + a4*a4);
290         double a34_hat2 = a34_hat*a34_hat;
291         
292         double Rcos_phi = a3/Math.sqrt(1.+a34_hat2)*sign_dz;
293         double Rsin_phi = a4/Math.sqrt(1.+a34_hat2)*sign_dz;
294         // ddphi / dc
295         
296         double ddphi_dc2 = -B*a5*Math.sqrt(a34_hat2+1.)*sign_dz;
297         double ddphi_dc2_nob = -Math.sqrt(a34_hat2+1.)*sign_dz;
298         
299         // da1 / dc
300         
301         double da1_dc1 = -Rcyl*sin_c1;
302         
303         // da2 / dc
304         
305         double da2_dc1 =  Rcyl*cos_c1;
306         
307         // da3 / dc
308         
309         double da3_dc1 = -sin_dir/c4;
310         double da3_dc3 = -sin_dir/c4;
311         double da3_dc4 = -cos_dir/(c4*c4);
312         
313         // da4 / dc
314         
315         double da4_dc1 =  cos_dir/c4;
316         double da4_dc3 =  cos_dir/c4;
317         double da4_dc4 = -sin_dir/(c4*c4);
318         
319         // da5 / dc
320         
321         double da5_dc4 =  -c5*c4/(c4_hat*c4_hat2);
322         double da5_dc5 =   1./c4_hat;
323         
324         // da1n/ dc
325         
326         double da1n_dc1 = da1_dc1;
327         double da1n_dc2 = Rcos_phi*ddphi_dc2_nob;
328         double da1n_dc3 = 0.;
329         double da1n_dc4 = 0.;
330         double da1n_dc5 = 0.;
331         
332         // da2n/ dc
333         
334         double da2n_dc1 = da2_dc1;
335         double da2n_dc2 = Rsin_phi*ddphi_dc2_nob;
336         double da2n_dc3 = 0.;
337         double da2n_dc4 = 0.;
338         double da2n_dc5 = 0.;
339         
340         // da3n/ dc
341         
342         double da3n_dc1 = da3_dc1;
343         double da3n_dc2 = - a4*ddphi_dc2;
344         double da3n_dc3 = da3_dc3;
345         double da3n_dc4 = da3_dc4;
346         double da3n_dc5 = 0.;
347         
348         // da4n/ dc
349         
350         double da4n_dc1 = da4_dc1;
351         double da4n_dc2 = a3*ddphi_dc2;
352         double da4n_dc3 = da4_dc3;
353         double da4n_dc4 = da4_dc4;
354         double da4n_dc5 = 0.;
355         
356         // da5n
357         
358         double da5n_dc1 = 0.;
359         double da5n_dc2 = 0.;
360         double da5n_dc3 = 0.;
361         double da5n_dc4 = da5_dc4;
362         double da5n_dc5 = da5_dc5;
363         
364         deriv.set(IX,IPHI      , da1n_dc1);
365         deriv.set(IX,IZ_CYL    , da1n_dc2);
366         deriv.set(IX,IALF      , da1n_dc3);
367         deriv.set(IX,ITLM      , da1n_dc4);
368         deriv.set(IX,IQPT      , da1n_dc5);
369         deriv.set(IY,IPHI      , da2n_dc1);
370         deriv.set(IY,IZ_CYL    , da2n_dc2);
371         deriv.set(IY,IALF      , da2n_dc3);
372         deriv.set(IY,ITLM      , da2n_dc4);
373         deriv.set(IY,IQPT      , da2n_dc5);
374         deriv.set(IDXDZ,IPHI   , da3n_dc1);
375         deriv.set(IDXDZ,IZ_CYL , da3n_dc2);
376         deriv.set(IDXDZ,IALF   , da3n_dc3);
377         deriv.set(IDXDZ,ITLM   , da3n_dc4);
378         deriv.set(IDXDZ,IQPT   , da3n_dc5);
379         deriv.set(IDYDZ,IPHI   , da4n_dc1);
380         deriv.set(IDYDZ,IZ_CYL , da4n_dc2);
381         deriv.set(IDYDZ,IALF   , da4n_dc3);
382         deriv.set(IDYDZ,ITLM   , da4n_dc4);
383         deriv.set(IDYDZ,IQPT   , da4n_dc5);
384         deriv.set(IQP_Z,IPHI   , da5n_dc1);
385         deriv.set(IQP_Z,IZ_CYL , da5n_dc2);
386         deriv.set(IQP_Z,IALF   , da5n_dc3);
387         deriv.set(IQP_Z,ITLM   , da5n_dc4);
388         deriv.set(IQP_Z,IQPT   , da5n_dc5);
389         
390         return pstat;
391     }
392 }