View Javadoc

1   package org.lcsim.recon.tracking.trfcyl;
2   
3   import org.lcsim.recon.tracking.trfutil.Assert;
4   
5   import org.lcsim.recon.tracking.trfbase.Interactor;
6   import org.lcsim.recon.tracking.trfbase.ETrack;
7   import org.lcsim.recon.tracking.trfbase.PropDir;
8   import org.lcsim.recon.tracking.trfbase.Propagator;
9   import org.lcsim.recon.tracking.trfbase.Surface;
10  import org.lcsim.recon.tracking.trfbase.TrackError;
11  import org.lcsim.recon.tracking.trfbase.TrackVector;
12  
13  import org.lcsim.recon.tracking.trfeloss.DeDx;
14  
15  import static org.lcsim.recon.tracking.trfcyl.SurfCylinder.IALF;
16  import static org.lcsim.recon.tracking.trfcyl.SurfCylinder.IPHI;
17  import static org.lcsim.recon.tracking.trfcyl.SurfCylinder.IQPT;
18  import static org.lcsim.recon.tracking.trfcyl.SurfCylinder.ITLM;
19  import static org.lcsim.recon.tracking.trfcyl.SurfCylinder.IZ;
20  
21  import static java.lang.Math.abs;
22  import static java.lang.Math.sqrt;
23  import static java.lang.Math.cos;
24  
25  /**
26   * Class for modifying the covariance matrix of a track which
27   * has been propagated to an InteractingLayer containing
28   * a LayerCylinder. The modifications correspond to energy
29   *loss in a cylindrical shell whose material is
30   *represented by the thickness and energy loss model
31   * is represented by a DeDx class.
32   *
33   *@author Norman A. Graf
34   *@version 1.0
35   *
36   */
37  public class CylEloss extends Interactor
38  {
39      
40      //attributes
41      
42      private double _thickness;
43      private DeDx _dedx;
44      
45      //methods
46      
47      //
48      
49      /**
50       *Construct an instance from the cylindrical shell's thickness and dE/dx class.
51       *
52       * @param   thickness The thickness of the cylindrical shell.
53       * @param   dedx The DeDx model of energy loss to use.
54       */
55      public CylEloss(double thickness, DeDx dedx)
56      {
57          _thickness = thickness;
58          _dedx = dedx;
59      }
60      
61      //
62      
63      /**
64       *Interact the given track in this cylindrical shell,
65       *using the DeDx model for energy loss.
66       *Note that both the track parameters and the
67       *covariance matrix are updated to reflect the uncertainty caused
68       *by traversing the cylindrical shell of material.
69       *
70       * @param   tre The ETrack to scatter.
71       */
72      public void interact(ETrack tre)
73      {
74          // This can only be used with cylinders... check that we have one..
75          
76          SurfCylinder cyl = new SurfCylinder(10.0);
77          Surface srf = tre.surface();
78          Assert.assertTrue( srf.pureType().equals(cyl.pureType()) );
79          
80          TrackError cleanError = tre.error();
81          TrackError newError = new TrackError(cleanError);
82          
83          TrackVector theVec = tre.vector();
84          TrackVector newVector = new TrackVector(theVec);
85          
86          double pionMass = 0.13957; // GeV
87          double ptmax = 10000.; // GeV
88          
89          double pinv = Math.abs(theVec.get(SurfCylinder.IQPT)*Math.cos(Math.atan(theVec.get(SurfCylinder.ITLM))));
90          
91          // make sure pinv is greater than a threshold (1/ptmax)
92          // in this case assume q = 1, otherwise q = q/pt/abs(q/pt)
93          
94          double sign = 1;
95          if(pinv < 1./ptmax)
96              pinv = 1./ptmax;
97          else
98              sign = theVec.get(SurfCylinder.IQPT)/Math.abs(theVec.get(SurfCylinder.IQPT));
99          
100         // Evaluate the initial energy assuming the particle is a pion.
101         
102         double trackEnergy = Math.sqrt(1./pinv/pinv+pionMass*pionMass);
103         
104         double trueLength = _thickness/Math.abs(Math.cos(theVec.get(SurfCylinder.IALF)))/
105                 Math.cos(Math.atan(theVec.get(SurfCylinder.ITLM)));
106         // assume the energy loss distribution to be Gaussian
107         double stdEnergy = _dedx.sigmaEnergy(trackEnergy, trueLength);
108         
109         double stdMomentum = stdEnergy;
110         // What direction are we going?
111         // If forward, that means we lose energy
112         // backwards means gain energy
113         if(tre.isTrackBackward()) trueLength = -trueLength;
114         trackEnergy = _dedx.loseEnergy(trackEnergy, trueLength);
115         
116         double newMomentum = trackEnergy>pionMass ?
117             Math.sqrt(trackEnergy*trackEnergy-
118                 pionMass*pionMass): 1./pinv;
119         
120         // Only vec(SurfCylinder.IQPT) changes due to E loss.
121         newVector.set(SurfCylinder.IQPT, 1./newMomentum/Math.cos(Math.atan(theVec.get(SurfCylinder.ITLM)))*sign);
122         
123         // Also only error(SurfCylinder.IQPT,IQPT) changes.
124         double stdVec = theVec.get(SurfCylinder.IQPT)*theVec.get(SurfCylinder.IQPT)*stdMomentum*Math.cos(Math.atan(
125                 theVec.get(SurfCylinder.ITLM)));
126         stdVec *= stdVec;
127         newError.set(SurfCylinder.IQPT, SurfCylinder.IQPT,  newError.get(SurfCylinder.IQPT, SurfCylinder.IQPT) + stdVec);
128         
129         tre.setVectorAndKeepDirection(newVector);
130         tre.setError( newError );
131         
132     }
133     
134     public void interact_dir(ETrack theTrack, PropDir direction )
135     {
136         // This can only be used with cylinders... check that we have one..
137         
138         Surface srf = theTrack.surface();
139         Assert.assertTrue( srf instanceof SurfCylinder );
140         
141         // Reduced direction must be forward or backward.
142         
143         Propagator.reduceDirection(direction);
144         Assert.assertTrue(direction == PropDir.FORWARD || direction == PropDir.BACKWARD);
145         
146         TrackError cleanError = theTrack.error();
147         TrackError newError = new TrackError(cleanError);
148         
149         TrackVector theVec = theTrack.vector();
150         TrackVector newVector = new TrackVector(theVec);
151         
152         double pionMass = 0.13957; // GeV
153         double ptmax = 10000.; // GeV
154         
155         double tanlm = theVec.get(ITLM);
156         double coslm = 1. / sqrt(1. + tanlm*tanlm);
157         double pinv = abs(theVec.get(IQPT)*coslm);
158         
159         // make sure pinv is greater than a threshold (1/ptmax)
160         // in this case assume q = 1, otherwise q = q/pt/abs(q/pt)
161         
162         int sign = 1;
163         if ( pinv < 1./ptmax )
164             pinv = 1./ptmax;
165         else
166             sign = (int) (theVec.get(IQPT)/abs(theVec.get(IQPT)));
167         
168         // Evaluate the initial energy assuming the particle is a pion.
169         
170         double trackEnergy = sqrt(1./pinv/pinv+pionMass*pionMass);
171         
172         double trueLength = _thickness/abs(cos(theVec.get(IALF)))/coslm;
173         
174         // assume the energy loss distribution to be Gaussian
175         double stdEnergy = _dedx.sigmaEnergy(trackEnergy, trueLength);
176         
177         double stdMomentum = stdEnergy;
178         if(direction == PropDir.BACKWARD)
179             trueLength = -trueLength;
180         _dedx.loseEnergy(trackEnergy, trueLength);
181         
182         double newMomentum = trackEnergy>pionMass ?
183             sqrt(trackEnergy*trackEnergy-
184                 pionMass*pionMass): 1./pinv;
185         
186         // Only vec(IQPT) changes due to E loss.
187         newVector.set(IQPT, 1./newMomentum/coslm*sign);
188         
189         // Also only error(IQPT,IQPT) changes.
190         double stdVec = theVec.get(IQPT)*theVec.get(IQPT)*stdMomentum*coslm;
191         stdVec *= stdVec;
192         newError.set(IQPT, IQPT, newError.get(IQPT, IQPT) + stdVec);
193         
194 // TODO introduce axial definition to ETrack
195 //  // Axial track?
196 //  if(theTrack.is_axial()) {
197 //    newError(IPHI,IZ) = 0.;
198 //    newError(IZ,IZ) = 0.;
199 //    newError(IALF,IZ) = 0.;
200 //    newError(ITLM,IZ) = 0.;
201 //    newError(IQPT,IZ) = 0.;
202 //    newError(IPHI,ITLM) = 0.;
203 //    newError(IALF,ITLM) = 0.;
204 //    newError(ITLM,ITLM) = 0.;
205 //    newError(IQPT,ITLM) = 0.;
206 //  }
207         
208         theTrack.setVector(newVector);
209         theTrack.setError( newError );
210         
211     }
212     
213 //
214     
215     /**
216      *Return the thickness of material in the cylindrical shell.
217      *
218      * @return The thickness of the  energy loss material.
219      */
220     public double thickness()
221     {
222         return _thickness;
223     }
224     
225 //
226     
227     /**
228      *Return the energy loss model used in this Interactor.
229      *
230      * @return The DeDx class representing energy loss.
231      */
232     public DeDx dEdX()
233     {
234         return _dedx; //cng shallow copy!
235     }
236     
237 //
238     
239     /**
240      *Make a clone of this object.
241      *
242      * @return A Clone of this instance.
243      */
244     public Interactor newCopy()
245     {
246         return new CylEloss(_thickness, _dedx);
247     }
248     
249     
250     /**
251      *output stream
252      *
253      * @return A String representation of this instance.
254      */
255     public String toString()
256     {
257         return "CylEloss with thickness "+_thickness+" and energy loss "+_dedx;
258     }
259 }