Print

Print


Author: [log in to unmask]
Date: Tue Sep  8 15:55:32 2015
New Revision: 3553

Log:
Fix bugs in the calculation of the momentum and charge of a track.  This was causing tracks to get extrapolated in the wrong direction and with the wrong curvature.  Rewrite the extrapolation code so it's easier to follow.

Modified:
    java/trunk/recon/src/main/java/org/hps/recon/particle/ReconParticleDriver.java
    java/trunk/tracking/src/main/java/org/hps/recon/tracking/TrackDataDriver.java
    java/trunk/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java

Modified: java/trunk/recon/src/main/java/org/hps/recon/particle/ReconParticleDriver.java
 =============================================================================
--- java/trunk/recon/src/main/java/org/hps/recon/particle/ReconParticleDriver.java	(original)
+++ java/trunk/recon/src/main/java/org/hps/recon/particle/ReconParticleDriver.java	Tue Sep  8 15:55:32 2015
@@ -160,7 +160,7 @@
      */
     @Override
     protected void detectorChanged(Detector detector) {
-        //matcher.enablePlots(true);
+        matcher.enablePlots(true);
         
         // Set the magnetic field parameters to the appropriate values.
         Hep3Vector ip = new BasicHep3Vector(0., 0., 1.);
@@ -168,6 +168,9 @@
         if (bField < 0) {
             flipSign = -1;
         }
+       
+        matcher.setBFieldMap(detector.getFieldMap());
+        
     }
 
     /**
@@ -480,7 +483,7 @@
 
     @Override
     protected void endOfData() { 
-        //matcher.saveHistograms();
+        matcher.saveHistograms();
     }
 
     // ==============================================================

Modified: java/trunk/tracking/src/main/java/org/hps/recon/tracking/TrackDataDriver.java
 =============================================================================
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/TrackDataDriver.java	(original)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/TrackDataDriver.java	Tue Sep  8 15:55:32 2015
@@ -243,7 +243,7 @@
                 
                 // Extrapolate the track to the face of the Ecal and get the TrackState
                 TrackState state 
-                    = TrackUtils.extrapolateTrackUsingFieldMap(track, extStartPos, ecalPosition, stepSize, bFieldMap, false);
+                    = TrackUtils.extrapolateTrackUsingFieldMap(track, extStartPos, ecalPosition, stepSize, bFieldMap);
                 track.getTrackStates().add(state);
                 
                 // The track time is the mean t0 of hits on a track

Modified: java/trunk/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java
 =============================================================================
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java	(original)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java	Tue Sep  8 15:55:32 2015
@@ -1,4 +1,11 @@
 package org.hps.recon.tracking;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import hep.physics.matrix.SymmetricMatrix;
 import hep.physics.vec.BasicHep3Vector;
@@ -6,15 +13,7 @@
 import hep.physics.vec.Hep3Vector;
 import hep.physics.vec.SpacePoint;
 import hep.physics.vec.VecOp;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.hps.recon.tracking.EventQuality.Quality;
-import org.hps.recon.tracking.gbl.HelicalTrackStripGbl;
-import static org.lcsim.constants.Constants.fieldConversion;
+
 import org.lcsim.detector.ITransform3D;
 import org.lcsim.detector.solids.Box;
 import org.lcsim.detector.solids.Point3D;
@@ -22,6 +21,7 @@
 import org.lcsim.detector.tracker.silicon.HpsSiSensor;
 import org.lcsim.detector.tracker.silicon.SiSensor;
 import org.lcsim.event.EventHeader;
+import org.lcsim.event.LCIOParameters.ParameterName;
 import org.lcsim.event.LCRelation;
 import org.lcsim.event.MCParticle;
 import org.lcsim.event.RawTrackerHit;
@@ -48,6 +48,11 @@
 import org.lcsim.util.swim.Helix;
 import org.lcsim.util.swim.Line;
 import org.lcsim.util.swim.Trajectory;
+
+import org.hps.recon.tracking.EventQuality.Quality;
+import org.hps.recon.tracking.gbl.HelicalTrackStripGbl;
+
+import static org.lcsim.constants.Constants.fieldConversion;
 
 /**
  * Assorted helper functions for the track and helix objects in lcsim. Re-use as
@@ -456,7 +461,7 @@
         double area2 = TrackUtils.findTriangleArea(vertices.get(1).x(), vertices.get(1).y(), vertices.get(2).x(), vertices.get(2).y(), trackPosition.y(), trackPosition.z());
         double area3 = TrackUtils.findTriangleArea(vertices.get(2).x(), vertices.get(2).y(), vertices.get(3).x(), vertices.get(3).y(), trackPosition.y(), trackPosition.z());
         double area4 = TrackUtils.findTriangleArea(vertices.get(3).x(), vertices.get(3).y(), vertices.get(0).x(), vertices.get(0).y(), trackPosition.y(), trackPosition.z());
-
+        //System.out.println("Current Momentum: " + currentMomentum.toString());
         return (area1 > 0 && area2 > 0 && area3 > 0 && area4 > 0) || (area1 < 0 && area2 < 0 && area3 < 0 && area4 < 0);
     }
 
@@ -1037,138 +1042,122 @@
         }
         return isolations;
     }
-
-    /**
-     * iteratively extrapolates a track to a specified value of z using the full
-     * field map.
-     *
-     * @param track
-     * @param start = value to start extrapolation (use analytic=constant field
-     * calculation up to here)
-     * @param zFinal = value to extrapolate to
-     * @param step = step size
-     * @param bmap = the field map
-     * @param debugOk
-     * @return
-     */
-    public static TrackState extrapolateTrackUsingFieldMap(Track track, double start, double zFinal, double step, FieldMap bmap, boolean debugOk) {
-        Trajectory _trajectory;
-        double startFringe = start;
-        HelicalTrackFit helix = getHTF(track);
-
-        // if looking upstream, we'll be propagating backwards
-        if (zFinal < 0)
-            step = -step;
-        if (debugOk)
-            System.out.println(track.toString());
-
-        double sStartFringe = HelixUtils.PathToXPlane(helix, startFringe, 1000.0, 1).get(0);
-        if (debugOk)
-            System.out.println("path to end of fringe = " + sStartFringe + "; zFinal = " + zFinal);
-        double xtmp = startFringe;
-        double ytmp = HelixUtils.PointOnHelix(helix, sStartFringe).y();
-        double ztmp = HelixUtils.PointOnHelix(helix, sStartFringe).z();
-        double Rorig = helix.R();
-        double xCtmp = helix.xc();
-        double yCtmp = helix.yc();
-        double q = Math.signum(helix.curvature());
-        double phitmp = calculatePhi(xtmp, ytmp, xCtmp, yCtmp, q);
-        if (debugOk) {
-            System.out.println("\nOriginal xtmp = " + xtmp + "; ytmp = " + ytmp + "; ztmp = " + ztmp + "; phitmp = " + phitmp);
-
-            System.out.println("nOriginal Rorig = " + Rorig + "; xCtmp = " + xCtmp + "; yCtmp = " + yCtmp);
-        }
-        if (debugOk)
-            System.out.println("Original Direction at Fringe: " + HelixUtils.Direction(helix, startFringe).toString());
-        double Rtmp = Rorig;
-        // now start stepping through the fringe field
-        Hep3Vector r0Tmp = HelixUtils.PointOnHelix(helix, sStartFringe);
-        org.lcsim.spacegeom.SpacePoint r0 = new org.lcsim.spacegeom.SpacePoint(r0Tmp);
-        Hep3Vector bMid = bmap.getField(new BasicHep3Vector(0, 0, 500.0));
-        double pTot = helix.p(bMid.y());//50 cm ~ middle of dipole
-        Hep3Vector dirOrig = HelixUtils.Direction(helix, sStartFringe);
-        Hep3Vector p0 = VecOp.mult(pTot, dirOrig);
-        Hep3Vector dirTmp = dirOrig;
-        org.lcsim.spacegeom.SpacePoint rTmp = r0;
-        Hep3Vector pTmp = p0;
-        double pXOrig = p0.x();
-        double pXTmp = pXOrig;
-        double totalS = sStartFringe;
-        double myBField = bMid.y();
-        // follow trajectory while: in fringe field, before end point, and we don't have a looper
-        while (Math.signum(step) * xtmp < Math.signum(step) * zFinal && Math.signum(pXOrig * pXTmp) > 0) {
-            if (debugOk) {
-                System.out.println("New step in Fringe Field");
-                System.out.println("rTmp = " + rTmp.toString());
-                System.out.println("pTmp = " + pTmp.toString());
-                System.out.println("OriginalHelix pos = " + HelixUtils.PointOnHelix(helix, totalS));
-                System.out.println("OriginalHelix Momentum = " + VecOp.mult(pTot, HelixUtils.Direction(helix, totalS)));
+   
+    /**
+     * Iteratively extrapolates a track to a specified value of x 
+     * (z in detector frame) using the full 3D field map.
+     *
+     * @param track The {@link Track} object to extrapolate.
+     * @param startPositionX The position from which to start the extrapolation
+     *                       from.  The track will be extrapolated to this 
+     *                       point using a constant field. 
+     * @param endPositionX The position to extrapolate the track to. 
+     * @param stepSize The step size determining how far a track will be 
+     *                 extrapolated after every iteration. 
+     * @param fieldMap The 3D field map
+     * @return A {@link TrackState} at the final extrapolation point.  Note
+     *         that the "Tracking" frame is used for the reference point 
+     *         coordinate system.
+     */
+    public static TrackState extrapolateTrackUsingFieldMap(Track track, double startPositionX, double endPositionX, double stepSize, FieldMap fieldMap) { 
+
+        // Start by extrapolating the track to the approximate point where the
+        // fringe field begins.
+        Hep3Vector currentPosition = TrackUtils.extrapolateHelixToXPlane(track, startPositionX); 
+        //System.out.println("Track position at start of fringe: " + currentPosition.toString()); 
+     
+        // Get the HelicalTrackFit object associated with the track.  This will
+        // be used to calculate the path length to the start of the fringe and
+        // to find the initial momentum of the track.
+        HelicalTrackFit helicalTrackFit = TrackUtils.getHTF(track);
+        
+        // Calculate the path length to the start of the fringe field.
+        double pathToStart = HelixUtils.PathToXPlane(helicalTrackFit, startPositionX, 0., 0).get(0);
+      
+        // Get the momentum of the track and calculate the magnitude. The 
+        // momentum can be calculate using the track curvature and magnetic
+        // field strength in the middle of the analyzing magnet.
+        // FIXME: The position of the middle of the analyzing magnet should 
+        //        be retrieved from the compact description.
+        double bFieldY = fieldMap.getField(new BasicHep3Vector(0, 0, 500.0)).y();
+        double p = Math.abs(helicalTrackFit.p(bFieldY)); 
+       
+        // Get a unit vector giving the track direction at the start of the of
+        // the fringe field
+        Hep3Vector helixDirection = HelixUtils.Direction(helicalTrackFit, pathToStart);
+        // Calculate the momentum vector at the start of the fringe field
+        Hep3Vector currentMomentum = VecOp.mult(p, helixDirection);
+        //System.out.println("Track momentum vector: " + currentMomentum.toString());
+
+        // Get the charge of the track.
+        double q = Math.signum(track.getTrackStates().get(0).getOmega());
+        // HACK: LCSim doesn't deal well with negative fields so they are 
+        //       turned to positive for tracking purposes.  As a result, 
+        //       the charge calculated using the B-field, will be wrong
+        //       when the field is negative and needs to be flipped.
+        if (bFieldY < 0) q = q*(-1);
+        
+        // Swim the track through the B-field until the end point is reached.
+        // The position of the track will be incremented according to the step
+        // size up to ~90% of the final position.  At this point, a finer
+        // track size will be used.
+       boolean stepSizeChange = false; 
+       while (currentPosition.x() < endPositionX) { 
+            
+            // The field map coordinates are in the detector frame so the 
+            // extrapolated track position needs to be transformed from the
+            // track frame to detector.
+            Hep3Vector currentPositionDet = CoordinateTransformations.transformVectorToDetector(currentPosition);
+            
+            // Get the field at the current position along the track. 
+            bFieldY = fieldMap.getField(currentPositionDet).y();
+            //System.out.println("Field along y (z in detector): " + bField);
+            
+            // Get a tracjectory (Helix or Line objects) created with the 
+            // track parameters at the current position.
+            Trajectory trajectory = getTrajectory(currentMomentum, new org.lcsim.spacegeom.SpacePoint(currentPosition), q, bFieldY);  
+            
+            // Using the new trajectory, extrapolated the track by a step and
+            // update the extrapolated position.
+            currentPosition = trajectory.getPointAtDistance(stepSize); 
+            //System.out.println("Current position: " + ((Hep3Vector) currentPosition).toString());
+            
+            // Calculate the momentum vector at the new position. This will 
+            // be used when creating the trajectory that will be used to 
+            // extrapolate the track in the next iteration.
+            currentMomentum = VecOp.mult(currentMomentum.magnitude(), trajectory.getUnitTangentAtLength(stepSize));
+           
+            // If the position of the track along X (or z in the detector frame)
+            // is at 90% of the total distance, reduce the step size.
+            if (currentPosition.x()/endPositionX > .80 && !stepSizeChange) { 
+                stepSize /= 10; 
+                //System.out.println("Changing step size: " + stepSize);
+                stepSizeChange = true;
             }
-
-            myBField = bmap.getField(new BasicHep3Vector(rTmp.y(), rTmp.z(), rTmp.x())).y(); // note weird co ordinates for track vs det   
-            if (debugOk)
-                System.out.println("rTmp.x() = " + rTmp.x() + " field = " + myBField);
-            _trajectory = getTrajectory(pTmp, rTmp, q, myBField);
-            rTmp = _trajectory.getPointAtDistance(step);
-            pTmp = VecOp.mult(pTot, _trajectory.getUnitTangentAtLength(step));
-            pXTmp = pTmp.x();
-            xtmp = rTmp.x();
-            if (debugOk) {
-                System.out.println("##############   done...    #############");
-
-                System.out.println("\n");
-            }
-            totalS += step;
-        }
-        myBField = bmap.getField(new BasicHep3Vector(rTmp.y(), rTmp.z(), rTmp.x())).y(); // note weird co ordinates for track vs det   
-        _trajectory = getTrajectory(pTmp, rTmp, q, myBField);
-        // Go with finer granularity in the end
-        rTmp = _trajectory.getPointAtDistance(0);
-        xtmp = rTmp.x();
-        pTmp = VecOp.mult(pTot, _trajectory.getUnitTangentAtLength(step));
-        pXTmp = pTmp.x();
-        step = step / 10.0;
-
-        while (Math.signum(step) * xtmp < Math.signum(step) * zFinal && Math.signum(pXOrig * pXTmp) > 0) {
-            if (debugOk) {
-                System.out.println("New step in Fringe Field");
-                System.out.println("rTmp = " + rTmp.toString());
-                System.out.println("pTmp = " + pTmp.toString());
-                System.out.println("OriginalHelix pos = " + HelixUtils.PointOnHelix(helix, totalS));
-                System.out.println("OriginalHelix Momentum = " + VecOp.mult(pTot, HelixUtils.Direction(helix, totalS)));
-            }
-
-            myBField = bmap.getField(new BasicHep3Vector(rTmp.y(), rTmp.z(), rTmp.x())).y(); // note weird co ordinates for track vs det   
-
-            if (debugOk)
-                System.out.println("rTmp.x() = " + rTmp.x() + " field = " + myBField);
-            _trajectory = getTrajectory(pTmp, rTmp, q, myBField);
-            rTmp = _trajectory.getPointAtDistance(step);
-            pTmp = VecOp.mult(pTot, _trajectory.getUnitTangentAtLength(step));
-            pXTmp = pTmp.x();
-            xtmp = rTmp.x();
-            if (debugOk) {
-                System.out.println("##############   done...    #############");
-                System.out.println("\n");
-            }
-            totalS += step;
-        }
-
-        // ok, done with field.
-        //store the helical track parameters at rTmp
-        double pars[] = {Math.sqrt(rTmp.x() * rTmp.x() + rTmp.y() * rTmp.y()),
-            calculatePhi(pTmp.x(), pTmp.y()),
-            calculateCurvature(pTmp.magnitude(), q, myBField),
-            calculateLambda(pTmp.z(), pTmp.magnitude()),
-            rTmp.z()};
-        Hep3Vector pointInTrking = new BasicHep3Vector(rTmp.x(), rTmp.y(), rTmp.z());
-
-        if (debugOk)
-            System.out.println("Position xfinal (tracking) :  x = " + zFinal + "; y = " + pointInTrking.y() + "; z = " + pointInTrking.z());
-        BaseTrackState ts = new BaseTrackState(pars, myBField);
-        ts.setReferencePoint(pointInTrking.v());
-        ts.setLocation(TrackState.AtCalorimeter);
-        return ts;
+       }
+       
+       // Calculate the track parameters at the Extrapolation point
+       double doca = currentPosition.x()*currentPosition.x() + currentPosition.y()*currentPosition.y();
+       double phi = TrackUtils.calculatePhi(currentMomentum.x(), currentMomentum.y());
+       double curvature = TrackUtils.calculateCurvature(currentMomentum.magnitude(), q, bFieldY);
+       double z = currentPosition.z();
+       double tanLambda = TrackUtils.calculateTanLambda(currentMomentum.z(), currentMomentum.magnitude());
+     
+       double[] trackParameters = new double[5];
+       trackParameters[ParameterName.d0.ordinal()] = doca; 
+       trackParameters[ParameterName.phi0.ordinal()] = phi; 
+       trackParameters[ParameterName.omega.ordinal()] = curvature; 
+       trackParameters[ParameterName.z0.ordinal()] = z; 
+       trackParameters[ParameterName.tanLambda.ordinal()] = tanLambda; 
+      
+       // Create a track state at the extrapolation point
+       TrackState trackState = new BaseTrackState(trackParameters, 
+               currentPosition.v(), 
+               track.getTrackStates().get(0).getCovMatrix(), 
+               TrackState.AtOther, 
+               bFieldY);
+       
+       return trackState;
     }
 
     public static double calculatePhi(double x, double y, double xc, double yc, double sign) {
@@ -1179,14 +1168,23 @@
         return Math.atan2(py, px);
     }
 
-    public static double calculateLambda(double pz, double p) {
+    public static double calculateTanLambda(double pz, double p) {
         return Math.atan2(pz, p);
     }
 
     public static double calculateCurvature(double p, double q, double B) {
         return q * B / p;
-    }
-
+    } 
+
+    /**
+     * 
+     * 
+     * @param p0
+     * @param r0
+     * @param q
+     * @param B
+     * @return
+     */
     public static Trajectory getTrajectory(Hep3Vector p0, org.lcsim.spacegeom.SpacePoint r0, double q, double B) {
         SpaceVector p = new CartesianVector(p0.v());
         double phi = Math.atan2(p.y(), p.x());
@@ -1195,6 +1193,7 @@
 
         if (q != 0 && field != 0) {
             double radius = p.rxy() / (q * field);
+            //System.out.println("[GetTrajectory] : Current Radius: " + radius);
             return new Helix(r0, radius, phi, lambda);
         } else
             return new Line(r0, phi, lambda);