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.trfxyp.SurfXYPlane;
13  import org.lcsim.recon.tracking.trfxyp.PropXYXY;
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 XYPlane in a constant field.
20   *<p>
21   * Propagation will fail if either the origin is not a Cylinder
22   * or destination is not a XYPlane.
23   * Propagator works incorrectly for tracks with very small curvatures.
24   *<p>
25   *
26   *@author Norman A. Graf
27   *@version 1.0
28   *
29   */
30  
31  public class PropCylXY extends PropDirected
32  {
33      
34      // Assign track parameter indices.
35      
36      private static final int IV = SurfXYPlane.IV;
37      private static final int IZC   = SurfXYPlane.IZ;
38      private static final int IDVDU = SurfXYPlane.IDVDU;
39      private static final int IDZDU = SurfXYPlane.IDZDU;
40      private static final int IQP_XY  = SurfXYPlane.IQP;
41      
42      private static final int IPHI = SurfCylinder.IPHI;
43      private static final int IZ   = SurfCylinder.IZ;
44      private static final int IALF = SurfCylinder.IALF;
45      private static final int ITLM = SurfCylinder.ITLM;
46      private static final int IQPT  = SurfCylinder.IQPT;
47      
48      
49      // attributes
50      
51      private double _bfac;
52      private PropXYXY _propxyxy;
53      
54      // static methods
55      
56      /**
57       *Return a String representation of the class' type name.
58       *Included for completeness with the C++ version.
59       *
60       * @return   A String representation of the class' type name.
61       */
62      public static String typeName()
63      { return "PropCylXY"; }
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      /**
77       *Construct an instance from a constant solenoidal magnetic field in Tesla.
78       *
79       * @param   bfield The magnetic field strength in Tesla.
80       */
81      public PropCylXY(double bfield)
82      {
83          _bfac = TRFMath.BFAC*bfield;
84          _propxyxy = new PropXYXY(bfield);
85          
86      }
87      
88      /**
89       *Clone an instance.
90       *
91       * @return A Clone of this instance.
92       */
93      public Propagator newPropagator( )
94      {
95          return new PropCylXY( bField() );
96          
97      }
98      
99      /**
100      *Propagate a track without error in the specified direction.
101      *
102      * The track parameters for a cylinder are:
103      * phi z alpha tan(lambda) curvature
104      *
105      * @param   trv The VTrack to propagate.
106      * @param   srf The Surface to which to propagate.
107      * @param   dir The direction in which to propagate.
108      * @return The propagation status.
109      */
110     public PropStat vecDirProp( VTrack trv, Surface srf,
111             PropDir dir)
112     {
113         TrackDerivative deriv = null;
114         return vecDirProp(trv, srf, dir, deriv);
115         
116     }
117     
118     /**
119      *Propagate a track without error in the specified direction
120      *and return the derivative matrix in deriv.
121      *
122      * The track parameters for a cylinder are:
123      * phi z alpha tan(lambda) curvature
124      *
125      * @param   trv The VTrack to propagate.
126      * @param   srf The Surface to which to propagate.
127      * @param   dir The direction in which to propagate.
128      * @param   deriv The track derivatives to update at the surface srf.
129      * @return The propagation status.
130      */
131     public PropStat vecDirProp( VTrack trv, Surface srf,
132             PropDir dir, TrackDerivative deriv )
133     {
134         PropStat pstat = new PropStat();
135         Propagator.reduceDirection(dir);
136         
137         // Check destination is a XYPlane.
138         Assert.assertTrue( srf.pureType().equals(SurfXYPlane.staticType()) );
139         if ( !srf.pureType( ).equals(SurfXYPlane.staticType()) )
140             return pstat;
141         SurfXYPlane sxyp2 = ( SurfXYPlane ) srf;
142         
143         // Fetch phi of the destination plane
144         
145         int iphi  = SurfXYPlane.NORMPHI;
146         double phi_n = sxyp2.parameter(iphi);
147         VTrack trv0 = trv; // want to change this vector.
148         TrackDerivative deriv1 = new TrackDerivative();
149         TrackDerivative deriv2 = new TrackDerivative();
150         
151         if ( deriv != null ) pstat = vecTransformCylXY( _bfac, trv0, phi_n, dir,deriv1 );
152         else pstat = vecTransformCylXY( _bfac, trv0, phi_n, dir, deriv );
153         
154         if ( ! pstat.success() ) return pstat;
155         
156         if ( deriv != null ) pstat = _propxyxy.vecDirProp(trv0,srf,dir,deriv2);
157         else  pstat = _propxyxy.vecDirProp(trv0,srf,dir, deriv);
158         
159         if ( pstat.success() )
160         {
161             trv = trv0;
162             if ( deriv != null )  deriv.set(deriv2.times(deriv1));
163         }
164         
165         return pstat;
166     }
167     
168     /**
169      *Return the strength of the magnetic field in Tesla.
170      *
171      * @return The strength of the magnetic field in Tesla.
172      */
173     public double bField()
174     {
175         return _bfac/TRFMath.BFAC;
176     }
177     
178     /**
179      *Return a String representation of the class' type name.
180      *Included for completeness with the C++ version.
181      *
182      * @return   A String representation of the class' type name.
183      */
184     public String type()
185     { return staticType(); }
186     
187     /**
188      *output stream
189      * @return  A String representation of this instance.
190      */
191     public String toString()
192     {
193         return "Cylinder-XYPlane propagation with constant "
194                 + bField() + " Tesla field";
195         
196     }
197     
198     //**********************************************************************
199     
200     // Private function to propagate a track without error
201     // The corresponding track parameters are:
202     // On Cylinder:
203     // r (cm) is fixed
204     // 0 - phi
205     // 1 - z (cm)
206     // 2 - alpha = phi_dir - phi; tan(alpha) = r*dphi/dr
207     // 3 - sin(lambda) = dz/ds; tan(lambda) = dz/dsT
208     // 4 - q/pT (1/GeV/c) (pT is component of p parallel to cylinder)
209     // On XYPlane:
210     // u (cm) is fixed
211     // 0 - v (cm)
212     // 1 - z (cm)
213     // 2 - dv/du
214     // 3 - dz/du
215     // 4 - q/p   p is momentum of a track, q is its charge
216     // If pderiv is nonzero, return the derivative matrix there.
217     
218     PropStat
219             vecTransformCylXY( double B, VTrack trv, double phi_n,
220             PropDir dir,
221             TrackDerivative deriv )
222     {
223         
224         // construct return status
225         PropStat pstat = new PropStat();
226         
227         // fetch the originating surface and vector
228         Surface srf1 = trv.surface();
229         // TrackVector vec1 = trv.get_vector();
230         
231         // Check origin is a Cylinder.
232         Assert.assertTrue( srf1.pureType().equals(SurfCylinder.staticType()) );
233         if ( !srf1.pureType( ).equals(SurfCylinder.staticType()) )
234             return pstat;
235         SurfCylinder scy1 = ( SurfCylinder ) srf1;
236         
237         // Fetch the R of the cylinder and the starting track vector.
238         int ir  = SurfCylinder.RADIUS;
239         double Rcyl = scy1.parameter(ir);
240         
241         TrackVector vec = trv.vector();
242         double c1 = vec.get(IPHI);                 // phi
243         double c2 = vec.get(IZ);                   // z
244         double c3 = vec.get(IALF);                 // alpha
245         double c4 = vec.get(ITLM);                 // tan(lambda)
246         double c5 = vec.get(IQPT);                 // q/pt
247         
248         // rotate coordinate system on phi_n
249         
250         c1 -= phi_n;
251         if(c1 < 0.) c1 += TRFMath.TWOPI;
252         
253         double cos_c1 = Math.cos(c1);
254         
255         double u = Rcyl*cos_c1;
256         if( u < 0. )
257         {
258             u = - u;
259             cos_c1 = - cos_c1;
260             c1 -= Math.PI;
261             if(c1 < 0.) c1 += TRFMath.TWOPI;
262             phi_n = phi_n + Math.PI;
263             if( phi_n >= TRFMath.TWOPI) phi_n -= TRFMath.TWOPI;
264         }
265         
266         double sin_c1  = Math.sin(c1);
267         double cos_dir = Math.cos(c1+c3);
268         double sin_dir = Math.sin(c1+c3);
269         double c4_hat2 = 1+c4*c4;
270         double c4_hat  = Math.sqrt(c4_hat2);
271         
272         // check if du == 0 ( that is track moves parallel to the destination plane )
273         // du = pt*cos_dir
274         if(cos_dir/c5 == 0.) return pstat;
275         
276         double tan_dir = sin_dir/cos_dir;
277         
278         double b1 = Rcyl*sin_c1;
279         double b2 = c2;
280         double b3 = tan_dir;
281         double b4 = c4/cos_dir;
282         double b5 = c5/c4_hat;
283         
284         int sign_du = 0;
285         if(cos_dir > 0) sign_du =  1;
286         if(cos_dir < 0) sign_du = -1;
287         
288         vec.set(IV     , b1);
289         vec.set(IZ     , b2);
290         vec.set(IDVDU  , b3);
291         vec.set(IDZDU  , b4);
292         vec.set(IQP_XY , b5);
293         
294         // Update trv
295         SurfXYPlane sxyp = new SurfXYPlane(u,phi_n);
296         trv.setSurface(sxyp.newPureSurface());
297         trv.setVector(vec);
298         
299         // set new direction of the track
300         if(sign_du ==  1) trv.setForward();
301         if(sign_du == -1) trv.setBackward();
302         
303         // Set the return status.
304         pstat.setSame();
305         
306         // exit now if user did not ask for error matrix.
307         if ( deriv == null ) return pstat;
308         
309         double b34_hat = Math.sqrt(1 + b3*b3 + b4*b4);
310         double invert_rsinphi =  (b5*B)*sign_du*b34_hat;
311         
312         
313         // du_dc
314         
315         double du_dc1 = -Rcyl*sin_c1;
316         
317         // db1_dc
318         
319         double db1_dc1 = Rcyl*cos_c1;
320         
321         // db2_dc
322         
323         double db2_dc2 = 1.;
324         
325         // db3_dc
326         
327         double db3_dc1 = 1./(cos_dir*cos_dir);
328         double db3_dc3 = 1./(cos_dir*cos_dir);
329         
330         // db4_dc
331         
332         double db4_dc1 = b4*tan_dir;
333         double db4_dc3 = b4*tan_dir;
334         double db4_dc4 = 1/cos_dir;
335         
336         // db5_dc
337         
338         double db5_dc4 = -c4*c5/(c4_hat*c4_hat2);
339         double db5_dc5 = 1./c4_hat;
340         
341         // db3_n_db
342         
343         double db3_n_du  = -(1. + b3*b3)*invert_rsinphi;
344         
345         // db4_n_db
346         
347         double db4_n_du  = -b4*b3*invert_rsinphi;
348         
349         
350         // db1_n_dc
351         
352         double db1_n_dc1 = db1_dc1 - b3 * du_dc1;
353         double db1_n_dc2 = 0.;
354         double db1_n_dc3 = 0.;
355         double db1_n_dc4 = 0.;
356         double db1_n_dc5 = 0.;
357         
358         // db2_n_dc
359         
360         double db2_n_dc1 = -b4 * du_dc1;
361         double db2_n_dc2 = db2_dc2;
362         double db2_n_dc3 = 0.;
363         double db2_n_dc4 = 0.;
364         double db2_n_dc5 = 0.;
365         
366         // db3_n_dc
367         
368         double db3_n_dc1 = db3_dc1 + db3_n_du * du_dc1;
369         double db3_n_dc2 = 0.;
370         double db3_n_dc3 = db3_dc3;
371         double db3_n_dc4 = 0.;
372         double db3_n_dc5 = 0.;
373         
374         // db4_n_dc
375         
376         double db4_n_dc1 = db4_dc1 + db4_n_du * du_dc1;
377         double db4_n_dc2 = 0.;
378         double db4_n_dc3 = db4_dc3;
379         double db4_n_dc4 = db4_dc4;
380         double db4_n_dc5 = 0.;
381         
382         // db5_n_dc
383         
384         double db5_n_dc1 = 0.;
385         double db5_n_dc2 = 0.;
386         double db5_n_dc3 = 0.;
387         double db5_n_dc4 = db5_dc4;
388         double db5_n_dc5 = db5_dc5;
389         
390         deriv.set(IV,IPHI      , db1_n_dc1);
391         deriv.set(IV,IZ        , db1_n_dc2);
392         deriv.set(IV,IALF      , db1_n_dc3);
393         deriv.set(IV,ITLM      , db1_n_dc4);
394         deriv.set(IV,IQPT      , db1_n_dc5);
395         deriv.set(IZ,IPHI      , db2_n_dc1);
396         deriv.set(IZ,IZ        , db2_n_dc2);
397         deriv.set(IZ,IALF      , db2_n_dc3);
398         deriv.set(IZ,ITLM      , db2_n_dc4);
399         deriv.set(IZ,IQPT      , db2_n_dc5);
400         deriv.set(IDVDU,IPHI   , db3_n_dc1);
401         deriv.set(IDVDU,IZ     , db3_n_dc2);
402         deriv.set(IDVDU,IALF   , db3_n_dc3);
403         deriv.set(IDVDU,ITLM   , db3_n_dc4);
404         deriv.set(IDVDU,IQPT   , db3_n_dc5);
405         deriv.set(IDZDU,IPHI   , db4_n_dc1);
406         deriv.set(IDZDU,IZ     , db4_n_dc2);
407         deriv.set(IDZDU,IALF   , db4_n_dc3);
408         deriv.set(IDZDU,ITLM   , db4_n_dc4);
409         deriv.set(IDZDU,IQPT   , db4_n_dc5);
410         deriv.set(IQP_XY,IPHI  , db5_n_dc1);
411         deriv.set(IQP_XY,IZ    , db5_n_dc2);
412         deriv.set(IQP_XY,IALF  , db5_n_dc3);
413         deriv.set(IQP_XY,ITLM  , db5_n_dc4);
414         deriv.set(IQP_XY,IQPT  , db5_n_dc5);
415         
416         return pstat;
417     }
418     
419     
420     
421 }