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);