View Javadoc

1   /**
2    * @version $Id: FastMCTrackFactory.java,v 1.3 2011/04/02 16:35:41 jstrube Exp $
3    */
4   package org.lcsim.mc.fast.tracking.fix;
5   
6   import static java.lang.Math.PI;
7   import static java.lang.Math.abs;
8   import static java.lang.Math.sqrt;
9   import static org.lcsim.event.LCIOParameters.ParameterName.omega;
10  import static org.lcsim.event.LCIOParameters.ParameterName.phi0;
11  import hep.physics.matrix.SymmetricMatrix;
12  import hep.physics.vec.Hep3Vector;
13  
14  import java.io.IOException;
15  import java.util.Random;
16  
17  import org.lcsim.conditions.ConditionsManager;
18  import org.lcsim.conditions.ConditionsSet;
19  import org.lcsim.event.EventHeader;
20  import org.lcsim.event.LCIOParameters;
21  import org.lcsim.event.MCParticle;
22  import org.lcsim.event.Track;
23  import org.lcsim.mc.fast.tracking.ResolutionTable;
24  import org.lcsim.mc.fast.tracking.SimpleTables;
25  import org.lcsim.mc.fast.tracking.TrackResolutionTables;
26  import org.lcsim.spacegeom.SpacePoint;
27  import org.lcsim.spacegeom.SpaceVector;
28  import org.lcsim.util.swim.HelixSwimmer;
29  
30  import Jama.EigenvalueDecomposition;
31  import Jama.Matrix;
32  import Jama.util.Maths;
33  
34  /**
35   * @author jstrube This class creates a new FastMC Track. It is used as the interface between the track measurement and the detector. Since Track doesn't know anything about the magnetic field, and
36   *         the material, it cannot transport its own parameters. Changing the reference point of a track requires swimming; it is therefore done in this class.
37   * 
38   */
39  public class FastMCTrackFactory {
40      private TrackResolutionTables _tables;
41      private SimpleTables _simpleTables;
42      private ConditionsManager _manager;
43      private double _Bz;
44      private HelixSwimmer _swimmer;
45      private static Random rDummy = new Random();
46      private static SpacePoint pDummy = new SpacePoint();
47  
48      /**
49       * This constructor obtains the necessary information for construction like the field and the resolution tables from the event.
50       * 
51       * @param event The current event
52       * @param beamConstraint A switch to obtain the resolution tables with or without beamconstraint
53       */
54      public FastMCTrackFactory(EventHeader event, boolean beamConstraint) {
55          this(event.getDetectorName(), event.getDetector().getFieldMap().getField(new double[3])[2], beamConstraint);
56      }
57  
58      /**
59       * This constructor is only to be used by unit tests. It will instantiate the Factory with a detector name and a field.
60       * 
61       */
62      public FastMCTrackFactory(String detectorName, double field, boolean beamConstraint) {
63          _Bz = field;
64          _manager = ConditionsManager.defaultInstance();
65          try {
66              // new detector, run 0
67              _manager.setDetector(detectorName, 0);
68          } catch (ConditionsManager.ConditionsNotFoundException e) {
69              System.err.print("Conditions for detector " + detectorName + " not found!");
70          }
71          ConditionsSet trackParameters = _manager.getConditions("TrackParameters");
72          ConditionsSet simpleTrack = _manager.getConditions("SimpleTrack");
73          try {
74              _tables = new TrackResolutionTables(trackParameters, beamConstraint);
75              _simpleTables = new SimpleTables(simpleTrack);
76          } catch (IOException e) {
77          }
78          _swimmer = new HelixSwimmer(field);
79      }
80  
81      /**
82       * Creates a track from an MCParticle
83       * @param part The MCParticle that is transformed to a track
84       * @return A FastMCTrack instance that contains information about the particle that was used as input
85       */
86      public Track getTrack(MCParticle part) {
87          FastMCTrack t = (FastMCTrack) getTrack(part.getMomentum(), part.getOrigin(), (int) part.getCharge());
88          t._particle = part;
89          return t;
90      }
91  
92      /**
93       * Creates a track from an MCParticle without smearing the parameters
94       * @param part The MCParticle that is transformed to a track
95       * @return A FastMCTrack instance that contains information about the particle that was used as input
96       */
97      public Track getUnsmearedTrack(MCParticle part) {
98          FastMCTrack t = (FastMCTrack) getTrack(new SpaceVector(part.getMomentum()), new SpacePoint(part.getOrigin()), pDummy, (int) part.getCharge(), rDummy, false);
99          t._particle = part;
100         return t;
101     }
102 
103     /**
104      * Creates a new Track with the given parameters. See #{@link #getTrack(SpacePoint, SpacePoint, SpacePoint, int, Random)} for details.
105      * 
106      * @param momentum The momentum at a given location
107      * @param location The location where the momentum is measured
108      * @param charge The charge of the Particle that created the Track
109      * @return A new NewTFastMCTrackect with the desired properties
110      */
111     public Track getTrack(SpaceVector momentum, SpacePoint location, int charge) {
112         return getTrack(momentum, location, pDummy, charge, rDummy);
113     }
114 
115     /**
116      * Creates a new Track with the given parameters. See #{@link #getTrack(SpacePoint, SpacePoint, SpacePoint, int, Random)} for details.
117      * 
118      * @param momentum The momentum at a given location
119      * @param location The location where the momentum is measured
120      * @param charge The charge of the Particle that created the Track
121      * @param random A random generator instance
122      * @return A new NewTrFastMCTrackct with the desired properties
123      */
124     public Track getTrack(SpaceVector momentum, SpacePoint location, int charge, Random random) {
125         return getTrack(momentum, location, pDummy, charge, random);
126     }
127 
128     /**
129      * Creates a new Track with the given parameters. See #{@link #getTrack(SpacePoint, SpacePoint, SpacePoint, int, Random)} for details.
130      * 
131      * @param momentum The momentum at a given location
132      * @param location The location where the momentum is measured
133      * @param referencePoint The point with respect to which the parameters are measured
134      * @param charge The charge of the Particle that created the Track
135      * @return A new NewTrFastMCTrackct with the desired properties
136      */
137     public Track getTrack(SpaceVector momentum, SpacePoint location, SpacePoint referencePoint, int charge) {
138         return getTrack(momentum, location, referencePoint, charge, rDummy);
139     }
140 
141     /**
142      * This version is only to be used in unit tests.
143      * 
144      * @param momentum The momentum at a given location
145      * @param location The location where the momentum is measured
146      * @param referencePoint The point with respect to which the parameters are measured
147      * @param charge The charge of the Particle that created the Track
148      * @param random A random generator instance
149      * @param shouldISmear This parameter switches smearing on/off. It should always be true except in Unit tests.
150      * @return A new NewTracFastMCTrack with the desired properties
151      */
152     public Track getTrack(SpaceVector momentum, SpacePoint location, SpacePoint referencePoint, int charge, Random random, boolean shouldISmear) {
153         _swimmer.setTrack(momentum, location, charge);
154         double alpha = _swimmer.getTrackLengthToPoint(referencePoint);
155         SpacePoint poca = _swimmer.getPointAtLength(alpha);
156         SpaceVector momentumAtPoca = _swimmer.getMomentumAtLength(alpha);
157         LCIOParameters parameters = LCIOParameters.SpaceMomentum2Parameters(poca, momentumAtPoca, referencePoint, charge, _Bz);
158         SymmetricMatrix errorMatrix = new SymmetricMatrix(5);
159         // this sets the measurement error
160         double cosTheta = abs(momentumAtPoca.cosTheta());
161         double p_mag = momentumAtPoca.magnitude();
162         ResolutionTable table = cosTheta < _tables.getPolarInner() ? _tables.getBarrelTable() : _tables.getEndcapTable();
163         for (int i = 0; i < 5; i++) {
164             for (int j = 0; j <= i; j++) {
165                 double iVal = table.findTable(i, j).interpolateVal(cosTheta, p_mag);
166                 errorMatrix.setElement(i, j, iVal);
167             }
168         }
169         // it's a bit inefficient to always have this condition here, although it's only used in tests.
170         LCIOParameters smearParams = shouldISmear ? smearParameters(parameters, errorMatrix, random) : parameters;
171 
172         // System.out.println("Charge: " + charge);
173         // System.out.println("TrackFactory: POCA " + poca);
174         // System.out.println("TrackFactory: Momentum " + momentumAtPoca);
175         // System.out.println("TrackFactory: Parameters: " + smearParams);
176         // System.out.println("TrackFactory: POCA from parameters: " + LCIOTrackParameters.Parameters2Position(smearParams, referencePoint));
177         // System.out.println("TrackFactory: Parameters from POCA: " + LCIOTrackParameters.SpaceMomentum2Parameters(poca, momentumAtPoca, referencePoint, charge, _Bz));
178         return new FastMCTrack(referencePoint, smearParams, errorMatrix, charge);
179     }
180 
181     /**
182      * Returns a new Track object initialized with the given values, and with its parameters smeared according to the Tables that are read from the detector. This method can take a random seed
183      * 
184      * @param momentum The momentum at a given location
185      * @param location The location where the momentum is measured
186      * @param referencePoint The point with respect to which the parameters are measured
187      * @param charge The charge of the Particle that created the Track
188      * @param random A random generator instance
189      * @return A new NewTraFastMCTrackt with the desired properties
190      */
191     public Track getTrack(SpaceVector momentum, SpacePoint location, SpacePoint referencePoint, int charge, Random random) {
192         return getTrack(momentum, location, referencePoint, charge, random, true);
193     }
194 
195     public Track getTrack(Hep3Vector momentum, Hep3Vector location, int charge) {
196         return getTrack(new SpaceVector(momentum), new SpacePoint(location), pDummy, charge, rDummy);
197     }
198 
199     /**
200      * Swims the Track to a new reference point and calculates the parameters anew. It has to be done here, because it involves swimming, which has to be done outside the track
201      * @param track The track to be swum
202      * @param referencePoint The new reference point for the track to swim to
203      */
204     public void setNewReferencePoint(Track track, SpacePoint referencePoint) {
205         _swimmer.setTrack(track);
206         double alpha = _swimmer.getTrackLengthToPoint(referencePoint);
207 
208         // TODO this involves transportation of the full covariance matrix.
209         // See Paul Avery's notes for details.
210         throw new RuntimeException("not yet implemented !");
211     }
212 
213     /**
214      * Smears the measurement matrix with a Gaussian error
215      * @param oldParams The unsmeared Parameters
216      * @param errorMatrix The measurement error matrix
217      * @param random A random generator
218      * @return A new set of smeared parameters
219      */
220     private static LCIOParameters smearParameters(LCIOParameters oldParams, SymmetricMatrix sm, Random random) {
221         Matrix errorMatrix = Maths.toJamaMatrix(sm);
222         EigenvalueDecomposition eigen = errorMatrix.eig();
223         double[] realEigen = eigen.getRealEigenvalues();
224         double[] imaginaryEigen = eigen.getImagEigenvalues();
225         Matrix eigenValues = eigen.getV();
226         if (eigenValues.det() == 0) {
227             throw new RuntimeException("ErrorMatrix does not have orthogonal basis");
228         }
229         for (int i = 0; i < imaginaryEigen.length; i++) {
230             if (imaginaryEigen[i] != 0)
231                 throw new RuntimeException("ErrorMatrix has imaginary eigenvalues");
232         }
233         Matrix x = new Matrix(5, 1);
234         for (int i = 0; i < 5; i++) {
235             if (realEigen[i] <= 0)
236                 throw new RuntimeException("non-positive eigenvalue encountered");
237             x.set(i, 0, sqrt(realEigen[i]) * random.nextGaussian());
238         }
239         Matrix shift = eigenValues.times(x);
240         Matrix params = new Matrix(oldParams.getValues(), 5);
241         // calculate the new parameters
242         double[] parameters = params.plus(shift).getColumnPackedCopy();
243         double pt = oldParams.getPt() * oldParams.get(omega) / parameters[omega.ordinal()];
244         // adjust the new parameters if necessary
245         if (parameters[phi0.ordinal()] > PI) {
246             parameters[phi0.ordinal()] -= 2 * PI;
247         } else if (parameters[phi0.ordinal()] < -PI) {
248             parameters[phi0.ordinal()] += 2 * PI;
249         }
250         return new LCIOParameters(parameters, pt);
251     }
252 }