Print

Print


Commit in lcsim/src/org/lcsim/contrib/JanStrube/tracking on MAIN
TransitionalTrack.java+209added 1.1
Trajectory.java+47added 1.1
Line.java+365added 1.1
HelixSwimmerTrackConsistencyTest.java+91added 1.1
Helix.java+223added 1.1
NewTrackTest.java+65-201.1 -> 1.2
HelixSwimmer.java+132-1351.2 -> 1.3
NewFastMCTrackFactory.java+122-361.2 -> 1.3
+1254-191
5 added + 3 modified, total 8 files
Added a new TestSuite. First set of tests pass, some inconsistencies between the TrackFactory and HelixSwimmer are still unresolved

lcsim/src/org/lcsim/contrib/JanStrube/tracking
TransitionalTrack.java added at 1.1
diff -N TransitionalTrack.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ TransitionalTrack.java	17 Jul 2006 10:12:39 -0000	1.1
@@ -0,0 +1,209 @@
+/**
+ * @version $Id: TransitionalTrack.java,v 1.1 2006/07/17 10:12:39 jstrube Exp $
+ */
+package org.lcsim.contrib.JanStrube.tracking;
+
+import java.util.List;
+
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+
+/**
+ * @author jstrube
+ *
+ */
+public class TransitionalTrack implements Track {
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#fitSuccess()
+     */
+    public boolean fitSuccess() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getCharge()
+     */
+    public int getCharge() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getChi2()
+     */
+    public double getChi2() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getErrorMatrix()
+     */
+    public double[][] getErrorMatrix() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getErrorMatrixElement(int, int)
+     */
+    public double getErrorMatrixElement(int i, int j) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getMomentum()
+     */
+    public double[] getMomentum() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getNDF()
+     */
+    public int getNDF() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getPX()
+     */
+    public double getPX() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getPY()
+     */
+    public double getPY() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getPZ()
+     */
+    public double getPZ() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getRadiusOfInnermostHit()
+     */
+    public double getRadiusOfInnermostHit() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getReferencePoint()
+     */
+    public double[] getReferencePoint() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getReferencePointX()
+     */
+    public double getReferencePointX() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getReferencePointY()
+     */
+    public double getReferencePointY() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getReferencePointZ()
+     */
+    public double getReferencePointZ() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getSubdetectorHitNumbers()
+     */
+    public int[] getSubdetectorHitNumbers() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getTrackParameter(int)
+     */
+    public double getTrackParameter(int i) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getTrackParameters()
+     */
+    public double[] getTrackParameters() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getTrackerHits()
+     */
+    public List<TrackerHit> getTrackerHits() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getTracks()
+     */
+    public List<Track> getTracks() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getType()
+     */
+    public int getType() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getdEdx()
+     */
+    public double getdEdx() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#getdEdxError()
+     */
+    public double getdEdxError() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.lcsim.event.Track#isReferencePointPCA()
+     */
+    public boolean isReferencePointPCA() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+}

lcsim/src/org/lcsim/contrib/JanStrube/tracking
Trajectory.java added at 1.1
diff -N Trajectory.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Trajectory.java	17 Jul 2006 10:12:39 -0000	1.1
@@ -0,0 +1,47 @@
+package org.lcsim.contrib.JanStrube.tracking;
+
+import org.lcsim.spacegeom.SpacePoint;
+
+import hep.physics.vec.Hep3Vector;
+
+/**
+ * A particle trajectory (either a Helix or a Line)
+ * @author tonyj
+ * @version $Id: Trajectory.java,v 1.1 2006/07/17 10:12:39 jstrube Exp $
+ */
+public interface Trajectory
+{
+   /**
+    * Gets a point after traveling distance alpha from the origin along the trajectory
+    */
+   SpacePoint getPointAtDistance(double alpha);
+  /**
+    * Calculates the distance at which the trajectory first reaches radius R.
+    * Returns Double.NaN if the trajectory does not intercept the cylinder.
+    * In principle there could be multiple solutions, so this method should
+    * always return the minimum <b>positive</b> solution.
+    */
+   
+   public double getDistanceToInfiniteCylinder(double r);
+  /** 
+    * Calculate the distance along the trajectory to reach a given Z plane.
+    * Note distance may be negative.
+    */
+   public double getDistanceToZPlane(double z);
+   
+  /**
+    * Obtain the point of closest approach (POCA)
+    * of the trajectory to a point. The return value is the distance
+    * parameter s, such that getPointAtDistance(s) is the POCA.
+    * @param point Point in space to swim to
+    * @return The length parameter s
+    */
+   public double getTrackLengthToPoint(SpacePoint point);
+   
+   /**
+    * Returns the momentum at a given distance from the origin
+    * @param alpha The length along the trajectory from the origin
+    * @return The momentum at the given distance
+    */
+   public SpacePoint getMomentumAtLength(double alpha);
+}

lcsim/src/org/lcsim/contrib/JanStrube/tracking
Line.java added at 1.1
diff -N Line.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Line.java	17 Jul 2006 10:12:39 -0000	1.1
@@ -0,0 +1,365 @@
+package org.lcsim.contrib.JanStrube.tracking;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+import org.lcsim.spacegeom.CartesianPoint;
+import org.lcsim.spacegeom.SpacePoint;
+
+/**
+ * A straight line
+ * 
+ * @author tonyj
+ * @version $Id: Line.java,v 1.1 2006/07/17 10:12:39 jstrube Exp $
+ */
+public class Line implements Trajectory {
+    /**
+     * Routine to find where two lines meet. This will probably be replaced by a more general vertexing solution at some
+     * point, but for now it works.
+     */
+    @Deprecated
+    static public double[] getPOCAOfLines(Line line1, Line line2) {
+        double[] output = line1.findTrackToTrackPOCA(line2);
+        return output;
+    }
+    private double sinPhi;
+    private double cosPhi;
+    private double sinLambda;
+    private double cosLambda;
+
+    private Hep3Vector origin;
+
+    /**
+     * Defines a line in space. The direction of the line is defined by the angles phi and lambda, such that the
+     * Cartesian unit vector is (cos(lambda)*cos(phi), cos(lambda)*sin(phi), sin(lambda)).
+     * 
+     * @param origin A point on the line
+     */
+    public Line(Hep3Vector origin, double phi, double lambda) {
+        this.origin = origin;
+        sinPhi = Math.sin(phi);
+        cosPhi = Math.cos(phi);
+        sinLambda = Math.sin(lambda);
+        cosLambda = Math.cos(lambda);
+    }
+
+    /**
+     * Defines a line in space. The line is defined by a point and a direction vector. The magnitude of the direction
+     * vector is ignored.
+     * 
+     * @param origin A point on the line
+     * @param dir The signed direction of the line
+     */
+    public Line(Hep3Vector origin, Hep3Vector dir) {
+        // The easy bit:
+        this.origin = origin;
+
+        // The hard bit: find the direction as (cosPhi, sinPhi, cosLambda, sinLambda)
+        double normalization = dir.magnitude();
+        Hep3Vector dirNormalized = hep.physics.vec.VecOp.unit(dir);
+
+        // cosPhi, sinPhi, sinLambda are fairly easy.
+        // It helps that the signed unit vector is (cos(lambda)*cos(phi), cos(lambda)*sin(phi), sin(lambda)).
+        double phi = hep.physics.vec.VecOp.phi(dirNormalized);
+        cosPhi = Math.cos(phi);
+        sinPhi = Math.sin(phi);
+        sinLambda = dirNormalized.z();
+
+        // cosLambda is harder. First find the absolute value:
+        double cosLambdaSquared = (dirNormalized.x() * dirNormalized.x() + dirNormalized.y() * dirNormalized.y());
+        if (cosLambdaSquared == 0.0) {
+            // Easy case
+            cosLambda = 0.0;
+        } else {
+            // Need to tease it apart using either X or Y. Choose the one with the bigger lever arm...
+            boolean useX = (Math.abs(dir.x()) > Math.abs(dir.y()));
+
+            // We will use one of the relations:
+            // vx = cosLambda * cosPhi
+            // vy = cosLambda * sinPhi
+            // where the unit direction vector is (vx, vy, vz)
+            if (useX) {
+                cosLambda = dirNormalized.x() / cosPhi;
+            } else {
+                cosLambda = dirNormalized.y() / sinPhi;
+            }
+        }
+    }
+
+    /**
+     * An internal utility routine to find the distance of closest approach (DOCA) of the line to a point. This is a
+     * simple 2D vector calculation: * Let the displacement vector from the origin to point be d. * Decompose d into a
+     * component parallel to the line (d_parallel) and a component perpendicular to the line (d_perp): d = d_parallel +
+     * d_perp * Take the dot product with the unit vector v along the line to obtain and use the parallel/perpendicular
+     * properties to obtain: |d.v| = |d_parallel| * Hence the DOCA, |d_perp|, is given by |d_perp|^2 = |d|^2 -
+     * |d_parallel|^2 = |d|^2 - |d.v|^2
+     */
+    protected double findDOCAToPoint(Hep3Vector point) {
+        // The first line is kind of ugly.
+        Hep3Vector displacement = new BasicHep3Vector(point.x() - origin.x(), point.y() - origin.y(), point.z()
+                - origin.z());
+        Hep3Vector lineDirection = this.getUnitVector();
+        double dotProduct = VecOp.dot(displacement, lineDirection);
+        double doca = Math.sqrt(displacement.magnitudeSquared() - dotProduct * dotProduct);
+        return doca;
+    }
+
+    /**
+     * An internal utility routine. This finds all intercepts of the line on a infinite cylinder of radius r. The
+     * cylinder's axis is the same as the z-axis. The return value is an array of signed distances from the origin point
+     * to the intercept point. If there are no solutions, the return value is null.
+     */
+    protected double[] findInterceptsOnCylinder(double r) {
+        if (cosLambda == 0.0) {
+            throw new AssertionError("Don't call this private routine with a line that's parallel to the z-axis!");
+        }
+
+        // Treat this first as a problem in the XY plane, then think about Z later.
+        // Track is described as
+        // position(t) = (x0, y0) + t(vx, vy)
+        // i.e.
+        // x = x0 + t(vx)
+        // y = y0 + t(vy) = y0 + ((x-x0)/vx)(vy)
+        // = [y0 - x0.vy/vx] + [x.vy/vx]
+        // = c + m.x
+        // Circle is described as
+        // x*x + y*y = r*r
+        // Solve for x and y:
+        // x*x + (c+mx)*(c+mx) = r*r
+        // x*x + c*c + 2*c*m*x + m*m*x*x = r*r
+        // (m*m + 1).x^2 + (2*c*m).x + (c*c - r*r) = 0
+        // Thus, solving the quadratic,
+        // x = [ -(2*c*m) +- sqrt( (2*c*m)^2 - 4*(m*m+1)*(c*c-r*r) ) ] / [2*(m*m+1)]
+
+        double x0 = origin.x();
+        double y0 = origin.y();
+        double vx = cosLambda * cosPhi;
+        double vy = cosLambda * sinPhi;
+
+        double c = y0 - (x0 * vy) / vx;
+        double m = vy / vx;
+
+        if (vx == 0.0) {
+            // This is a special case where the line is perpendicular to the x-axis.
+            // Handle this by flipping the x and y coordinates.
+            x0 = origin.y();
+            y0 = origin.x();
+            vx = cosLambda * sinPhi;
+            vy = cosLambda * cosPhi;
+            c = y0 - (x0 * vy) / vx;
+            m = vy / vx;
+        }
+
+        // Solve the quadratic...
+        double termA = (m * m + 1.0);
+        double termB = (2.0 * c * m);
+        double termC = (c * c - r * r);
+        double sqrtTerm = termB * termB - 4.0 * termA * termC;
+
+        double[] xSolutions = null; // This will hold the co-ordinates of the solutions
+
+        if (sqrtTerm > 0.0) {
+            // Two solutions.
+            xSolutions = new double[2];
+            xSolutions[0] = ( -termB + Math.sqrt(sqrtTerm)) / (2.0 * termA);
+            xSolutions[1] = ( -termB - Math.sqrt(sqrtTerm)) / (2.0 * termA);
+        } else if (sqrtTerm == 0.0) {
+            // One solution
+            xSolutions = new double[1];
+            xSolutions[0] = ( -termB) / (2.0 * termA);
+        } else if (sqrtTerm < 0.0) {
+            // No solutions
+        }
+
+        double[] distances = null; // The array of signed distances we'll return
+        if (xSolutions == null) {
+            // No solutions -- distances stays null
+        } else {
+            // Unit vector is (cosLambda*cosPhi, cosLambda*sinPhi, sinLambda), so
+            // we can calculate the distances easily...
+            distances = new double[xSolutions.length];
+            for (int i = 0; i < distances.length; i++ ) {
+                // Calculate in a way that remains correct even if we flipped x and y
+                // co-ordinates:
+                distances[i] = (xSolutions[i] - x0) / vx;
+            }
+        }
+
+        return distances;
+    }
+
+    /**
+     * An internal utility routine to obtain the point of closest approach (POCA) of the line to a point. The return
+     * value is the distance parameter s, such that getPointAtDistance(s) is the POCA. The vector calculation is as
+     * follows: Let the origin point be x and the unit vector along the line be v. Let the point we're trying to find
+     * the POCA to be p. Suppose the POCA is at x' = x + sv such that the scalar distance parameter we want is s. Then
+     * the displacement vector from the POCA to p is d = x' - p But x' is the POCA, so d is perpendicular to v: 0 = d.v =
+     * (x' - p).v = (x + sv - p).v So (x-p).v + sv.v = 0 But v is a unit vector, so s = (p-x).v
+     */
+    protected double findPOCAToPoint(Hep3Vector point) {
+        // Find (p-x)
+        Hep3Vector originToPoint = new BasicHep3Vector(point.x() - origin.x(), point.y() - origin.y(), point.z()
+                - origin.z());
+        Hep3Vector lineDirection = this.getUnitVector();
+        double dotProduct = VecOp.dot(originToPoint, lineDirection);
+        return dotProduct;
+    }
+
+    /**
+     * Internal utility routine to find where two lines meet. This will probably be replaced by a more general vertexing
+     * solution at some point, but for now it works.
+     */
+    @Deprecated private double[] findTrackToTrackPOCA(Line otherLine)
+    {
+	Line line1 = this;
+	Line line2 = otherLine;
+
+	// Unit vectors of the two lines:
+	Hep3Vector v1 = line1.getUnitVector();
+	Hep3Vector v2 = line2.getUnitVector();
+	// Origin points on the two lines:
+	Hep3Vector x1 = line1.origin;
+	Hep3Vector x2 = line2.origin;
+
+        // Find the common perpendicular:
+	Hep3Vector perp = VecOp.cross(v1, v2);
+	if (perp.magnitude() == 0.0)
+	    // Lines are parallel!
+	    return null;
+	
+	    // Let the origin point along the lines be x1 and x2.
+	    // Let the unit vectors along the lines be v1 and v2.
+            // Suppose that the points of closest approach are at:
+            // x1' = x1 + a(v1)
+            // x2' = x2 + b(v2)
+            // Construct a vector p1 which is perpendicular to perp and to v1:
+            // p1 = v1 x perp = v1 x (v1 x v2) = v1(v1.v2) - v2(v1.v1)
+            // p2 = v2 x perp = v2 x (v1 x v2) = v1(v2.v2) - v2(v1.v2)
+            // Then v1.p1 = (v1.v1)(v1.v2) - (v1.v2)(v1.v1) = 0
+            // v1.p2 = (v1.v1)(v2.v2) - (v1.v2)(v1.v2) = L
+            // v2.p1 = (v2.v1)(v1.v2) - (v2.v2)(v1.v1) = -L
+            // v2.p2 = (v2.v1)(v2.v2) - (v2.v2)(v1.v2) = 0
+            // Thus,
+            // (x2'-x1').p1 = (x2 + b(v2) - x1 -a(v1)).p1
+            // = x2.p1 + b(v2.p1) - x1.p1 - a(v1.p1)
+            // = x2.p1 - bL - x1.p1
+            // and similarly,
+            // (x2'-x1').p2 = x2.p2 -x1.p2 - aL
+            // But p1 and p2 are perpendicular to perp, and (x2'-x1') is parallel
+            // to perp for x1' and x2' the closest points. So
+            // (x2'-x1').p1 = x2.p1 - bL - x1.p1 = 0
+            // (x2'-x1').p2 = x2.p2 - x1.p2 - aL = 0
+            // Hence,
+            // -bL = -x2.p1 + x1.p1 => b = (x2-x1).p1 / L
+            // -aL = -x2.p2 + x1.p2 => a = (x2-x1).p2 / L
+            // and so the POCA is at
+            // (x1' + x2')/2 = (x1 + a(v1) + x2 + b(v2)) / 2
+            // = (x1 + [(x2-x1).p2/L]v1 + x2 + [(x2-x1).p1/L]v2) / 2
+
+	    // p1 = v1 x perp (and similarly p2)
+	    Hep3Vector p1 = VecOp.cross(v1, perp);
+	    Hep3Vector p2 = VecOp.cross(v2, perp);
+
+	    // L = (v1.v1)(v2.v2) - (v1.v2)(v1.v2) = 1 - (v1.v2)^2
+	    double L = 1.0 - (VecOp.dot(v1,v2) * VecOp.dot(v1,v2));
+
+	    // a = (x2-x1).p2 / L
+	    // b = (x2-x1).p1 / L
+	    double a = VecOp.dot(VecOp.sub(x2,x1), p2) / L;
+	    double b = VecOp.dot(VecOp.sub(x2,x1), p1) / L;
+
+	    double[] output = new double[2];
+	    output[0] = a;
+	    output[1] = b;
+	    return output;
+	}
+
+    /**
+     * Return the direction of the line. Marked Deprecated since this should really be replaced by a general method for
+     * the Trajectory interface, perhaps getDirection(double alpha) for distance parameter alpha.
+     */
+    @Deprecated
+    public Hep3Vector getDirection() {
+        return this.getUnitVector();
+    }
+
+    /**
+     * Calculates the distance at which the trajectory first reaches radius R. Returns Double.NaN if the trajectory does
+     * not intercept the cylinder. In principle there could be multiple solutions, so this method should always return
+     * the minimum <b>positive</b> solution.
+     */
+    public double getDistanceToInfiniteCylinder(double r) {
+        if (cosLambda == 0.0) {
+            // This is a special case where the line is parallel to the z-axis.
+            // There can be no well-defined answer in this case
+            return Double.NaN;
+        }
+        // Find the intercepts on the cylinder (Cartesian):
+        double[] distances = this.findInterceptsOnCylinder(r);
+        // Which is the best?
+        double bestDistance = -1.0;
+        for (int i = 0; i < distances.length; i++ ) {
+            if (distances[i] >= 0.0) {
+                // Potentially valid -- is it the best so far?
+                if (bestDistance < 0.0 || distances[i] < bestDistance) {
+                    // Yes!
+                    bestDistance = distances[i];
+                }
+            }
+        }
+        if (bestDistance < 0.0) {
+            // There was no valid (positive) solution
+            return Double.NaN;
+        }
+        return bestDistance;
+    }
+
+    /**
+     * Calculate the distance along the trajectory to reach a given Z plane. Note distance may be negative.
+     */
+    public double getDistanceToZPlane(double z) {
+        return (z - origin.z()) / sinLambda;
+    }
+
+    /**
+     * Gets a point after traveling distance alpha from the trajectory's origin point along the trajectory
+     */
+    public SpacePoint getPointAtDistance(double alpha) {
+        double z = origin.z() + alpha * sinLambda;
+        double dr = alpha * cosLambda;
+        double x = origin.x() + dr * cosPhi;
+        double y = origin.y() + dr * sinPhi;
+        return new CartesianPoint(x, y, z);
+    }
+
+    /**
+     * Obtain the point of closest approach (POCA) of the line to a point. The return value is the distance parameter s,
+     * such that getPointAtDistance(s) is the POCA.
+     * 
+     * @param point Point in space to swim to
+     * @return The length parameter s
+     */
+    public double getTrackLengthToPoint(SpacePoint point) {
+        return findPOCAToPoint(point);
+    }
+
+    /**
+     * Calculates the <em>unit vector</em> of the momentum at a certain distance from the origin.
+     * Since the momentum is constant for a straight line,
+     * @param alpha is ignored
+     * @return The unit direction of the line, since there is now geometric way to obtain the momentum along a straight line.
+     */
+    public SpacePoint getMomentumAtLength(double alpha) {
+        SpacePoint lineDirection = new CartesianPoint(cosLambda * cosPhi, cosLambda * sinPhi, sinLambda);
+        return lineDirection;
+    }
+    
+    /**
+     * Internal utility routine to return the unit vector of the line's direction.
+     */
+    protected Hep3Vector getUnitVector() {
+        Hep3Vector lineDirection = new BasicHep3Vector(cosLambda * cosPhi, cosLambda * sinPhi, sinLambda);
+        return lineDirection;
+    }
+}

lcsim/src/org/lcsim/contrib/JanStrube/tracking
HelixSwimmerTrackConsistencyTest.java added at 1.1
diff -N HelixSwimmerTrackConsistencyTest.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ HelixSwimmerTrackConsistencyTest.java	17 Jul 2006 10:12:39 -0000	1.1
@@ -0,0 +1,91 @@
+/**
+ * @version $Id: HelixSwimmerTrackConsistencyTest.java,v 1.1 2006/07/17 10:12:39 jstrube Exp $
+ */
+package org.lcsim.contrib.JanStrube.tracking;
+
+import java.util.Random;
+
+import org.lcsim.spacegeom.CartesianPoint;
+import org.lcsim.spacegeom.SpacePoint;
+
+import junit.framework.TestCase;
+
+/**
+ * @author jstrube
+ *
+ */
+public class HelixSwimmerTrackConsistencyTest extends TestCase {
+
+    private HelixSwimmer swimmerRaw;
+    private HelixSwimmer swimmerTrack;
+    private NewFastMCTrackFactory factory;
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        super.setUp();
+        swimmerRaw = new HelixSwimmer(5.);
+        factory = new NewFastMCTrackFactory("sidaug05", 5., true);
+        swimmerTrack = new HelixSwimmer(5.);
+    }
+
+    public void testHelix_TrackFactoryConsistency1() {
+        SpacePoint momentum = new CartesianPoint(-2, 2, 4);
+        SpacePoint location = new CartesianPoint(1, 2, 3);
+        int charge = -1;
+        swimmerRaw.setTrack(momentum, location, charge);
+        // get a Track in a way that no swimming is necessary for the reference point
+        // turn off smearing
+        Track t = factory.getTrack(momentum, location, location, charge, new Random(), false);
+        swimmerTrack.setTrack(t);
+        // swim to pocas of several points and compare position and momentum at these points
+        double alpha = swimmerRaw.getDistanceToPoint(location);
+        double beta = swimmerTrack.getDistanceToPoint(location);
+        assertEquals(swimmerRaw.getPointAtDistance(alpha), swimmerTrack.getPointAtDistance(beta), 4e-4);
+        assertEquals(swimmerRaw.getMomentumAtDistance(alpha), swimmerTrack.getMomentumAtDistance(beta), 1e-5);
+        
+        // use the momentum components as another random point to swim to
+        alpha = swimmerRaw.getDistanceToPoint(momentum);
+        beta = swimmerTrack.getDistanceToPoint(momentum);
+        // TODO there are obviously some floating point precision issues, probably related to the trigonometric functions.
+        // Investigation can be put off to a later date
+        assertEquals(swimmerRaw.getPointAtDistance(alpha), swimmerTrack.getPointAtDistance(beta), 4e-4);
+        assertEquals(swimmerRaw.getMomentumAtDistance(alpha), swimmerTrack.getMomentumAtDistance(beta), 4e-4);
+    }
+    
+    public void testHelix_TrackFactoryConsistency2() {
+        SpacePoint momentum = new CartesianPoint(-2, 2, 4);
+        SpacePoint location = new CartesianPoint(1, 2, 3);
+        int charge = -1;
+        swimmerRaw.setTrack(momentum, location, charge);
+        SpacePoint referencePoint = new SpacePoint();
+        // reference Point is (0, 0, 0)
+        Track t = factory.getTrack(momentum, location, referencePoint, charge, new Random(), false);
+        swimmerTrack.setTrack(t);
+
+        double alpha = swimmerRaw.getDistanceToPoint(referencePoint);
+        System.out.println("Raw: Distance to 000 is: " + alpha);
+        double beta = swimmerTrack.getDistanceToPoint(referencePoint);
+        System.out.println("Track: Distance to 000 is: " + beta);
+        assertEquals(beta, 0, 1e-10);
+        System.out.println(swimmerRaw.getPointAtDistance(alpha));
+    }
+    
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    void assertEquals(SpacePoint a, SpacePoint b, double precision) {
+        assertEquals(a.x(), b.x(), precision);
+        assertEquals(a.y(), b.y(), precision);
+        assertEquals(a.z(), b.z(), precision);        
+    }
+    
+    void assertEquals(SpacePoint a, SpacePoint b) {
+        assertEquals(a, b, 1e-10);
+    }
+
+}

lcsim/src/org/lcsim/contrib/JanStrube/tracking
Helix.java added at 1.1
diff -N Helix.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Helix.java	17 Jul 2006 10:12:40 -0000	1.1
@@ -0,0 +1,223 @@
+package org.lcsim.contrib.JanStrube.tracking;
+
+import static java.lang.Math.abs;
+import static java.lang.Math.asin;
+import static java.lang.Math.atan2;
+import static java.lang.Math.cos;
+import static java.lang.Math.signum;
+import static java.lang.Math.sin;
+import static java.lang.Math.sqrt;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+import org.lcsim.spacegeom.CartesianPoint;
+import org.lcsim.spacegeom.SpacePoint;
+
+/**
+ * This class represents a helix with its axis aligned along Z. All quantities in this class are dimensionless. It has
+ * no dependencies except for Hep3Vector (which could easily be removed).
+ * <p>
+ * For more info on swimming see <a href="doc-files/transport.pdf">this paper</a> by Paul Avery.
+ * 
+ * @author tonyj
+ * @version $Id: Helix.java,v 1.1 2006/07/17 10:12:40 jstrube Exp $
+ */
+public class Helix implements Trajectory {
+    private Hep3Vector origin;
+    double xCenter;
+    double yCenter;
+    private double radius;
+    private double sinLambda;
+    private double cosLambda;
+    private double sinPhi;
+    private double cosPhi;
+    private double phi;
+
+    // parameterization in terms of 'momentum'
+    // A helix is a mathematical object and doesn't have "momentum",
+    // but unfortunately some of the used algorithms are expressed in terms of it.
+    // That's OK, it's a private variable.
+    private double px;
+    private double py;
+    private double pz;
+    private double abs_r;
+    private double rho;
+
+    /**
+     * Creates a new instance of Helix. Parameters according to <a href="doc-files/L3_helix.pdf">the L3 conventions</a><br />
+     * Please also have a look at <img src="doc-files/Helix-1.png" alt="Helix-1.png"> <img src="doc-files/Helix-2.png"
+     * alt="Helix-2.png">
+     * 
+     * @param origin A point on the helix
+     * @param radius The <em>signed</em> radius of curvature of the helix. The conventions is such that for
+     *            <em>positive</em> radii, the direction is <em>clockwise</em>.
+     * @param phi The polar angle of the helix <em>momentum</em> in x-y plane w/rt positive x-axis at the origin
+     * @param lambda The dip angle w/rt positive part of the x-y plane
+     */
+    public Helix(SpacePoint org, double r, double Phi, double lambda) {
+        // if (abs(lambda) > PI/2.)
+        // throw new IllegalArgumentException("lambda = " + lambda + " is outside of -PI/2<lambda<PI/2");
+        origin = org;
+        radius = r;
+        phi = Phi;
+
+        // Calculate some useful quantities
+        cosPhi = cos(phi);
+        sinPhi = sin(phi);
+        cosLambda = cos(lambda);
+        sinLambda = sin(lambda);
+        xCenter = origin.x() + radius * sinPhi;
+        yCenter = origin.y() - radius * cosPhi;
+        setSpatialParameters();
+    }
+
+    public SpacePoint getCenterXY() {
+        return new CartesianPoint(xCenter, yCenter, 0);
+    }
+
+    /**
+     * Calculates the distance along the Helix until it hits a cylinder centered along z
+     * 
+     * @param r the radius of the cylinder
+     * @return the distance along the trajectory or Double.NAN if the cylinder can never be hit
+     */
+    public double getDistanceToInfiniteCylinder(double r) {
+        double phiToCenter = atan2(yCenter, xCenter);
+        double radiusOfCenter = sqrt(xCenter * xCenter + yCenter * yCenter);
+        // Negative radius doesn't make sense
+        if (r < 0)
+            throw new IllegalArgumentException("radius " + r + "<0");
+        double darg = r*r / (2. * radius * radiusOfCenter)
+                - radiusOfCenter / (2. * radius)
+                - radius / (2. * radiusOfCenter);
+        double diff = asin(darg) + phi - phiToCenter;
+        double result = (radius / cosLambda) * diff;
+        while (result < 0)
+            result += Math.abs(radius / cosLambda) * 2 * Math.PI;
+        return result;
+    }
+
+    public double getDistanceToZPlane(double z) {
+        return (z - origin.z()) / sinLambda;
+    }
+
+    /**
+     * @param alpha The distance along the trajectory
+     * @return The unit vector of the momentum
+     */
+    public SpacePoint getMomentumAtLength(double alpha) {
+        double angle = phi - alpha / radius;
+        return new CartesianPoint(cos(angle), sin(angle), sinLambda / cosLambda);
+    }
+
+    /**
+     * returns a point on the Helix at a distance alpha from the origin along the trajectory. alpha ==
+     * 2*PI*radius/cos(lambda) is one rotation in the x-y plane
+     */
+    public SpacePoint getPointAtDistance(double alpha) {
+        double angle = phi - alpha * cosLambda / radius;
+        double x = xCenter + radius * sin(angle);
+        double y = yCenter - radius * cos(angle);
+        double z = origin.z() + alpha * sinLambda;
+        return new CartesianPoint(x, y, z);
+    }
+
+    public double getRadius() {
+        return radius;
+    }
+
+    /**
+     * Calculates the <em>signed</em> distance in mm between the Helix and an arbitrary point in Space
+     * 
+     * @param point the point in space to calculate the distance to
+     * @return the distance in mm between the point and the helix at the point of closest approach
+     */
+    public double getSignedClosestDifferenceToPoint(SpacePoint point) {
+        double tanLambda = sinLambda / cosLambda;
+        Hep3Vector pCrossB = new BasicHep3Vector(py, -px, 0);
+        Hep3Vector xDiff = VecOp.sub(origin, point);
+        double pMag = sqrt(px * px + py * py + pz * pz);
+
+        // translate along Z because algorithm can handle only numbers in the
+        // first quadrant
+        double zPos = xDiff.z();
+        // these are two mutually exclusive cases and two while loops
+        // may not be the best way to express this
+        while (zPos > abs(radius * tanLambda * Math.PI / 4)) {
+            zPos -= abs(radius * tanLambda * Math.PI / 4);
+        }
+        while (zPos < -abs(radius * tanLambda * Math.PI / 4)) {
+            zPos += abs(radius * tanLambda * Math.PI / 4);
+        }
+        xDiff = new BasicHep3Vector(xDiff.x(), xDiff.y(), zPos);
+
+        double numerator = (-2 * VecOp.dot(xDiff, pCrossB) 
+                + pMag*rho*(xDiff.magnitudeSquared() - xDiff.z() * xDiff.z()))
+                / radius;
+        double denominator = 1 + sqrt(1- 2*rho*pMag
+                * VecOp.dot(xDiff, pCrossB) / radius / radius
+                + pMag*pMag*rho*rho
+                * (xDiff.magnitudeSquared() - xDiff.z() * xDiff.z()) /radius/radius);
+        return numerator / denominator;
+    }
+
+    // Returns the "momentum" at the length s from the starting point.
+    // This uses the definition in http://www.phys.ufl.edu/~avery/fitting/transport.pdf
+    public SpacePoint getTangentAtDistance(double alpha) {
+        double p0x = px * cos(rho * alpha) - py * sin(rho * alpha);
+        double p0y = py * cos(rho * alpha) + px * sin(rho * alpha);
+        double p0z = pz * cos(rho * alpha) + pz * (1 - cos(rho * alpha));
+        return new CartesianPoint(p0x, p0y, p0z);
+    }
+
+    /**
+     * Swims the helix along its trajectory to the point of closest approach to the given SpacePoint. For more info on
+     * swimming see <a href=doc-files/fitting/transport.pdf> Paul Avery's excellent text</a>
+     * 
+     * @param point Point in Space to swim to.
+     * @return the length Parameter alpha
+     */
+    public double getTrackLengthToPoint(SpacePoint point) {
+        double tanLambda = sinLambda / cosLambda;
+        double pMag = sqrt(px * px + py * py + pz * pz);
+        Hep3Vector p0 = new BasicHep3Vector(px, py, pz);
+        Hep3Vector pCrossB = new BasicHep3Vector(py, -px, 0);
+
+        // first, the point needs to be translated into the first period
+        Hep3Vector xDiff = VecOp.sub(origin, point);
+        double zPos = xDiff.z();
+        int addedQuarterPeriods = 0;
+        // these are two mutually exclusive cases and two while loops
+        // may not be the best way to express this
+
+        while (abs(zPos) > abs(radius * tanLambda * Math.PI / 2)) {
+            zPos -= signum(zPos) * abs(radius * tanLambda * Math.PI / 2);
+            ++addedQuarterPeriods;
+        }
+        // Make sure the helix is in the right quadrant for the atan
+        if (zPos > 0 && addedQuarterPeriods > 0)
+            addedQuarterPeriods *= -1;
+        if (addedQuarterPeriods % 2 != 0)
+            addedQuarterPeriods += signum(addedQuarterPeriods);
+        xDiff = new BasicHep3Vector(xDiff.x(), xDiff.y(), zPos);
+        double factorA1 = pMag - pz * pz / pMag - (VecOp.dot(xDiff, pCrossB)) * rho;
+        double factorA2 = (VecOp.dot(xDiff, p0) - xDiff.z() * pz) * rho;
+        // System.err.print("addedQuarterPeriods: " + addedQuarterPeriods);
+        // System.err.printf("result:%.3f + %.3f\n", addedQuarterPeriods*(radius/cosLambda*Math.PI/2),
+        // Math.atan(factorA2/factorA1) / -rho);
+        return addedQuarterPeriods * abs(radius / cosLambda * Math.PI / 2) + Math.atan(factorA2 / factorA1) / -rho;
+    }
+
+    /**
+     * Sets the parametrization in terms of "momentum" and charge
+     * 
+     */
+    private void setSpatialParameters() {
+        abs_r = abs(radius);
+        px = abs_r * cosPhi;
+        py = abs_r * sinPhi;
+        pz = abs_r * sinLambda / cosLambda;
+        rho = -cosLambda / radius;
+    }
+}

lcsim/src/org/lcsim/contrib/JanStrube/tracking
NewTrackTest.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- NewTrackTest.java	15 Jul 2006 09:12:45 -0000	1.1
+++ NewTrackTest.java	17 Jul 2006 10:12:39 -0000	1.2
@@ -1,8 +1,11 @@
 /**
- * @version $Id: NewTrackTest.java,v 1.1 2006/07/15 09:12:45 jstrube Exp $
+ * @version $Id: NewTrackTest.java,v 1.2 2006/07/17 10:12:39 jstrube Exp $
  */
 package org.lcsim.contrib.JanStrube.tracking;
 
+import org.lcsim.spacegeom.CartesianPoint;
+import org.lcsim.spacegeom.SpacePoint;
+
 import junit.framework.TestCase;
 
 /**
@@ -11,11 +14,17 @@
  */
 public class NewTrackTest extends TestCase {
 
+    private NewFastMCTrackFactory factory;
+    private Track t;
     /* (non-Javadoc)
      * @see junit.framework.TestCase#setUp()
      */
     protected void setUp() throws Exception {
         super.setUp();
+        factory = new NewFastMCTrackFactory("sidaug05", 5., true);
+        SpacePoint momentum = new CartesianPoint(1, 1, 1);
+        SpacePoint location = new CartesianPoint(1, 2, 3);
+        t = factory.getTrack(momentum, location, 1);
     }
 
     /* (non-Javadoc)
@@ -29,42 +38,78 @@
      * Test method for {@link org.lcsim.contrib.JanStrube.tracking.NewTrack#NewTrack(org.lcsim.spacegeom.SpacePoint, org.lcsim.contrib.JanStrube.tracking.EMap, Jama.Matrix, int)}.
      */
     public void testNewTrack() {
-        fail("Not yet implemented");
-    }
-
-    /**
-     * Test method for {@link org.lcsim.contrib.JanStrube.tracking.NewTrack#getParameter(org.lcsim.contrib.JanStrube.tracking.Track.ParameterName)}.
-     */
-    public void testGetParameter() {
-        fail("Not yet implemented");
+        
     }
 
     /**
      * Test method for {@link org.lcsim.contrib.JanStrube.tracking.NewTrack#getPt()}.
+     * Testing equality of pt for different initializations of the track.
+     * Notable is that different values of the charge are tested.
      */
     public void testGetPt() {
-        fail("Not yet implemented");
+        SpacePoint location = new CartesianPoint(0, 0, 0);
+        SpacePoint momentum = new CartesianPoint(1, 1, 1);
+        t = factory.getTrack(momentum, location, 1);
+        assertEquals(t.getPt(), momentum.rxy(), 1e-10);
+
+        location = new CartesianPoint(1, 2, 3);
+        momentum = new CartesianPoint(-1, -1, -1);
+        t = factory.getTrack(momentum, location, 2);
+        assertEquals(t.getPt(), momentum.rxy(), 1e-10);
+
+        location = new CartesianPoint(-1, -2, -3);
+        momentum = new CartesianPoint(-1, -1, -1);
+        t = factory.getTrack(momentum, location, -1);
+        assertEquals(t.getPt(), momentum.rxy(), 1e-10);
+        
+        location = new CartesianPoint(1, 2, 3);
+        momentum = new CartesianPoint(-2, -1, 1);
+        t = factory.getTrack(momentum, location, -2);
+        assertEquals(t.getPt(), momentum.rxy(), 1e-10);
     }
 
     /**
      * Test method for {@link org.lcsim.contrib.JanStrube.tracking.NewTrack#getCharge()}.
      */
     public void testGetCharge() {
-        fail("Not yet implemented");
+        SpacePoint location = new CartesianPoint(0, 0, 0);
+        SpacePoint momentum = new CartesianPoint(1, 1, 1);
+        t = factory.getTrack(momentum, location, -2);
+        assertEquals(t.getCharge(), -2);
+        t = factory.getTrack(momentum, location, -1);
+        assertEquals(t.getCharge(), -1);
+        t = factory.getTrack(momentum, location, 1);
+        assertEquals(t.getCharge(), 1);
+        t = factory.getTrack(momentum, location, 2);
+        assertEquals(t.getCharge(), 2);
     }
 
     /**
      * Test method for {@link org.lcsim.contrib.JanStrube.tracking.NewTrack#getReferencePoint()}.
      */
     public void testGetReferencePoint() {
-        fail("Not yet implemented");
+        SpacePoint location = new CartesianPoint(1, 2, 3);
+        SpacePoint momentum = new CartesianPoint(1, 1, 1);
+        SpacePoint referencePoint = new CartesianPoint(0, 0, 0);
+        t = factory.getTrack(momentum, location, referencePoint, -2);
+        assertEquals(t.getReferencePoint(), referencePoint);
+
+        referencePoint = new CartesianPoint(1, 2, 3);
+        t = factory.getTrack(momentum, location, referencePoint, -2);
+        assertEquals(t.getReferencePoint(), referencePoint);
+        
+        referencePoint = new CartesianPoint(-2, -3, -4);
+        t = factory.getTrack(momentum, location,referencePoint,  -2);
+        assertEquals(t.getReferencePoint(), referencePoint);
+
+        referencePoint = new CartesianPoint(1, 0, 7);
+        t = factory.getTrack(momentum, location, referencePoint, -2);
+        assertEquals(t.getReferencePoint(), referencePoint);
+    }
+    
+    void assertEquals(SpacePoint a, SpacePoint b) {
+        assertEquals(a.x(), b.x(), 1e-10);
+        assertEquals(a.y(), b.y(), 1e-10);
+        assertEquals(a.z(), b.z(), 1e-10);
     }
-
-    /**
-     * Test method for {@link org.lcsim.contrib.JanStrube.tracking.NewTrack#getErrorMatrix()}.
-     */
-    public void testGetErrorMatrix() {
-        fail("Not yet implemented");
-    }
-
 }

lcsim/src/org/lcsim/contrib/JanStrube/tracking
HelixSwimmer.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- HelixSwimmer.java	15 Jul 2006 09:12:45 -0000	1.2
+++ HelixSwimmer.java	17 Jul 2006 10:12:39 -0000	1.3
@@ -1,10 +1,8 @@
 package org.lcsim.contrib.JanStrube.tracking;
 
+import org.lcsim.recon.vertexing.zvtop4.VectorArithmetic;
 import org.lcsim.spacegeom.CartesianPoint;
 import org.lcsim.spacegeom.SpacePoint;
-import org.lcsim.util.swim.Helix;
-import org.lcsim.util.swim.Line;
-import org.lcsim.util.swim.Trajectory;
 
 import static java.lang.Math.abs;
 import static java.lang.Math.sin;
@@ -19,138 +17,137 @@
 import static org.lcsim.contrib.JanStrube.tracking.Track.ParameterName.tanLambda;
 
 /**
- * A simple helix smimmer for use in org.lcsim. Uses standard lcsim units
- * Tesla, mm, GeV. This swimmer works for charged and neutral tracks.
- * <p> 
- * For more info on swimming see <a href="doc-files/transport.pdf">this paper</a>
- * by Paul Avery.
+ * A simple helix smimmer for use in org.lcsim. Uses standard lcsim units Tesla, mm, GeV. This swimmer works for charged
+ * and neutral tracks.
+ * <p>
+ * For more info on swimming see <a href="doc-files/transport.pdf">this paper</a> by Paul Avery.
+ * 
  * @author jstrube
- * @version $Id: HelixSwimmer.java,v 1.2 2006/07/15 09:12:45 jstrube Exp $
+ * @version $Id: HelixSwimmer.java,v 1.3 2006/07/17 10:12:39 jstrube Exp $
  */
-public class HelixSwimmer
-{
-   public class SpatialParameters
-   {
-	   public double px;
-	   public double py;
-	   public double pz;
-	   public int charge;
-	   public boolean isInvalid = true;
-       
-       public String toString() {
-           String result = new String("SpatialParameters\n");
-           result += String.format("\tp_x: %f\n\tp_y: %f\n\tp_z: %f\n\tcharge: %d", px, py, pz, charge);
-           return result;
-       }
-  }
-   private double field;
-   private Trajectory trajectory;
-   private SpatialParameters spatialParms;
-   private org.lcsim.contrib.JanStrube.tracking.Track track;
-   /** Creates a new instance of HelixSwimmer
-    * @param B field strength in Tesla; uniform, solenoidal, directed along z-axis
-    */
-   public HelixSwimmer(double B)
-   {
-      field = B*fieldConversion;
-      spatialParms = new SpatialParameters();
-   }
-   /**
-    * Sets parameters for helix swimmmer.
-    *
-    * @param p 3-momentum (px,py,pz)
-    * @param r0 initial position(x0,y0,z0)
-    * @param iq charge iq = q/|e| = +1/0/-1
-    */
-   public void setTrack(SpacePoint p, SpacePoint r0, int iq)
-   {
-      double tan_lambda = p.z()/p.rxy();
-      double phi = Math.atan2(p.y(),p.x());
-      double lambda = Math.atan(tan_lambda);
-      
-      if (iq != 0 && field != 0)
-      {
-         double radius = p.rxy()/(iq*field);
-         trajectory = new Helix(r0,radius,phi,lambda);
-      }
-      else
-      {
-         trajectory = new Line(r0, phi, lambda);
-      }
-      spatialParms.isInvalid = true;
-   }
-   
-   public void setTrack(Track t)
-   {
-      double o = t.getParameter(omega);
-      double p = t.getParameter(phi0);
-      double lambda = Math.atan(t.getParameter(tanLambda));
-
-      SpacePoint ref = t.getReferencePoint();
-      double x = ref.x() - t.getParameter(d0)*sin(t.getParameter(phi0));
-      double y = ref.y() + t.getParameter(d0)*cos(t.getParameter(phi0));
-      double z = ref.z() + t.getParameter(z0);
-      SpacePoint origin = new CartesianPoint(x, y, z);
-      trajectory = new Helix(origin, 1/o, p, lambda);
-      spatialParms.isInvalid = true;
-      track=t;
-   }
-   
-   public SpacePoint getPointAtDistance(double alpha)
-   {
-      if (trajectory == null)
-          throw new RuntimeException("Trajectory not set");
-      return trajectory.getPointAtDistance(alpha);
-   }
-   
-   public double getDistanceToRadius(double r)
-   {
-      if (trajectory == null) throw new RuntimeException("Trajectory not set");
-      return trajectory.getDistanceToInfiniteCylinder(r);
-   }
-   
-   public double getDistanceToZ(double z)
-   {
-      if (trajectory == null) throw new RuntimeException("Trajectory not set");
-      double result = trajectory.getDistanceToZPlane(z);
-      if (result<0) result = trajectory.getDistanceToZPlane(-z);
-      return result;
-   }
-   
-   public double getDistanceToCylinder(double r,double z)
-   {
-      double x1 = getDistanceToRadius(r);
-      double x2 = getDistanceToZ(z);
-      return Double.isNaN(x1) ? x2 : Math.min(x1,x2);
-   }
-   
-   /**
-    * Returns the distance along the trajectory to get to the point of closest approach 
-    * @param point The point to swim as close as possible to
-    * @return the length parameter by how much the trajectory has to be swum
-    */
-   public double getDistanceToPoint(SpacePoint point) {
-       return trajectory.getDistanceToPoint(point);
-   }
-   
-   /**
-    * Returns the momentum on a point on the track at a distance from the origin
-    * @param alpha The 3D distance from the origin along the track
-    * @return The components of the momentum in a SpacePoint  
-    */
-   public SpacePoint getMomentumAtDistance(double alpha) {
-       double t = track.getParameter(tanLambda);
-       double cosLambda = 1/sqrt(t*t);
-       double o = track.getParameter(omega);
-       double phi = track.getParameter(phi0) + alpha*cosLambda*o;
-       double p_t = field*track.getCharge()/o;
-       double px = p_t * cos(phi);
-       double py = p_t * sin(phi);
-       double pz = p_t*t;
-       return new CartesianPoint(px, py, pz);
-   }
-   
-   public Trajectory getTrajectory() {
-       return trajectory;
-   }
+public class HelixSwimmer {
+    public class SpatialParameters {
+        public double px;
+        public double py;
+        public double pz;
+        public int charge;
+
+        public String toString() {
+            String result = new String("SpatialParameters\n");
+            result += String.format("\tp_x: %f\n\tp_y: %f\n\tp_z: %f\n\tcharge: %d", px, py, pz, charge);
+            return result;
+        }
+    }
+
+    private double field;
+    private Trajectory _trajectory;
+    private SpatialParameters spatialParms;
+
+    /**
+     * Creates a new instance of HelixSwimmer
+     * 
+     * @param B field strength in Tesla; uniform, solenoidal, directed along z-axis
+     */
+    public HelixSwimmer(double B) {
+        field = B * fieldConversion;
+        spatialParms = new SpatialParameters();
+    }
+
+    /**
+     * Sets parameters for helix swimmmer.
+     * 
+     * @param p 3-momentum (px,py,pz)
+     * @param r0 initial position(x0,y0,z0)
+     * @param iq charge iq = q/|e| = +1/0/-1
+     */
+    public void setTrack(SpacePoint p, SpacePoint r0, int iq) {
+        double tan_lambda = p.z() / p.rxy();
+        double phi = Math.atan2(p.y(), p.x());
+        double lambda = Math.atan(tan_lambda);
+
+        if (iq != 0 && field != 0) {
+            double radius = p.rxy() / (iq * field);
+            _trajectory = new Helix(r0, radius, phi, lambda);
+        } else {
+            _trajectory = new Line(r0, phi, lambda);
+        }
+        spatialParms.px = p.x();
+        spatialParms.py = p.y();
+        spatialParms.pz = p.z();
+        spatialParms.charge = iq;
+    }
+
+    public void setTrack(Track t) {
+        double r = 1/t.getParameter(omega);
+        double phi = t.getParameter(phi0);
+        double lambda = Math.atan(t.getParameter(tanLambda));
+
+        SpacePoint ref = t.getReferencePoint();
+        double x = ref.x() - t.getParameter(d0) * sin(t.getParameter(phi0));
+        double y = ref.y() + t.getParameter(d0) * cos(t.getParameter(phi0));
+        double z = ref.z() + t.getParameter(z0);
+        SpacePoint origin = new CartesianPoint(x, y, z);
+        _trajectory = new Helix(origin, r, phi, lambda);
+        
+        double pt = r*t.getCharge()*field;
+        spatialParms.px = pt*cos(phi);
+        spatialParms.py = pt*sin(phi);
+        spatialParms.pz = pt*t.getParameter(tanLambda);
+        spatialParms.charge = t.getCharge();
+//        System.out.println(spatialParms);
+//        System.out.println(origin);
+    }
+
+    public SpacePoint getPointAtDistance(double alpha) {
+        if (_trajectory == null)
+            throw new RuntimeException("Trajectory not set");
+        return _trajectory.getPointAtDistance(alpha);
+    }
+
+    public double getDistanceToRadius(double r) {
+        if (_trajectory == null)
+            throw new RuntimeException("Trajectory not set");
+        return _trajectory.getDistanceToInfiniteCylinder(r);
+    }
+
+    public double getDistanceToZ(double z) {
+        if (_trajectory == null)
+            throw new RuntimeException("Trajectory not set");
+        double result = _trajectory.getDistanceToZPlane(z);
+        if (result < 0)
+            result = _trajectory.getDistanceToZPlane( -z);
+        return result;
+    }
+
+    public double getDistanceToCylinder(double r, double z) {
+        double x1 = getDistanceToRadius(r);
+        double x2 = getDistanceToZ(z);
+        return Double.isNaN(x1) ? x2 : Math.min(x1, x2);
+    }
+
+    /**
+     * Returns the distance along the trajectory to get to the point of closest approach
+     * 
+     * @param point The point to swim as close as possible to
+     * @return the length parameter by how much the trajectory has to be swum
+     */
+    public double getDistanceToPoint(SpacePoint point) {
+        return _trajectory.getTrackLengthToPoint(point);
+    }
+
+    /**
+     * Returns the momentum on a point on the track at a distance from the origin
+     * 
+     * @param alpha The 3D distance from the origin along the track
+     * @return The components of the momentum in a SpacePoint
+     */
+    public SpacePoint getMomentumAtDistance(double alpha) {
+        // the trajectory can only return the unit direction of the momentum
+        SpacePoint unitDirection = _trajectory.getMomentumAtLength(alpha); 
+        return VectorArithmetic.multiply(unitDirection, sqrt(spatialParms.px*spatialParms.px + spatialParms.py*spatialParms.py));
+    }
+
+    public Trajectory getTrajectory() {
+        return _trajectory;
+    }
 }

lcsim/src/org/lcsim/contrib/JanStrube/tracking
NewFastMCTrackFactory.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- NewFastMCTrackFactory.java	15 Jul 2006 09:12:45 -0000	1.2
+++ NewFastMCTrackFactory.java	17 Jul 2006 10:12:39 -0000	1.3
@@ -1,5 +1,5 @@
 /**
- * @version $Id: NewFastMCTrackFactory.java,v 1.2 2006/07/15 09:12:45 jstrube Exp $
+ * @version $Id: NewFastMCTrackFactory.java,v 1.3 2006/07/17 10:12:39 jstrube Exp $
  */
 package org.lcsim.contrib.JanStrube.tracking;
 
@@ -9,12 +9,12 @@
 import static java.lang.Math.cos;
 import static java.lang.Math.sin;
 import static java.lang.Math.sqrt;
+import static org.lcsim.contrib.JanStrube.tracking.Constants.fieldConversion;
 import static org.lcsim.contrib.JanStrube.tracking.Track.ParameterName.d0;
 import static org.lcsim.contrib.JanStrube.tracking.Track.ParameterName.omega;
 import static org.lcsim.contrib.JanStrube.tracking.Track.ParameterName.phi0;
 import static org.lcsim.contrib.JanStrube.tracking.Track.ParameterName.tanLambda;
 import static org.lcsim.contrib.JanStrube.tracking.Track.ParameterName.z0;
-import static org.lcsim.contrib.JanStrube.tracking.Constants.fieldConversion;
 
 import java.io.IOException;
 import java.util.Random;
@@ -22,7 +22,6 @@
 import org.lcsim.conditions.ConditionsManager;
 import org.lcsim.conditions.ConditionsSet;
 import org.lcsim.event.EventHeader;
-import org.lcsim.geometry.Detector;
 import org.lcsim.mc.fast.tracking.ResolutionTable;
 import org.lcsim.mc.fast.tracking.SimpleTables;
 import org.lcsim.mc.fast.tracking.TrackResolutionTables;
@@ -32,10 +31,10 @@
 import Jama.Matrix;
 
 /**
- * @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 the material, it cannot transport its own parameters.
- * Changing the reference point of a track requires swimming; it is therefore done in this class.
+ * @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 the material, it cannot
+ *         transport its own parameters. Changing the reference point of a track requires swimming; it is therefore done
+ *         in this class.
  * 
  */
 public class NewFastMCTrackFactory {
@@ -45,11 +44,24 @@
     private double _Bz;
     private HelixSwimmer _swimmer;
 
+    /**
+     * This constructor obtains the necessary information for construction like the field and the resolution tables from
+     * the event.
+     * 
+     * @param event The current event
+     * @param beamConstraint A switch to obtain the resolution tables with or without beamconstraint
+     */
     public NewFastMCTrackFactory(EventHeader event, boolean beamConstraint) {
-        String detectorName = event.getDetectorName();
-        Detector detector = event.getDetector();
-        // We want always the z component of the field at 0, 0, 0
-        _Bz = detector.getFieldMap().getField(new double[3])[2];
+        this(event.getDetectorName(), event.getDetector().getFieldMap().getField(new double[3])[2], beamConstraint);
+    }
+
+    /**
+     * This constructor is only to be used by unit tests. It will instantiate the Factory with a detector name and a
+     * field.
+     * 
+     */
+    NewFastMCTrackFactory(String detectorName, double field, boolean beamConstraint) {
+        _Bz = field;
         _manager = ConditionsManager.defaultInstance();
         try {
             _manager.setDetector(detectorName, 0);
@@ -62,10 +74,58 @@
             _simpleTables = new SimpleTables(simpleTrack);
         } catch (IOException e) {
         }
-        _swimmer = new HelixSwimmer(_Bz);
+        _swimmer = new HelixSwimmer(field);
     }
 
-    public Track getTrack(SpacePoint momentum, SpacePoint location, SpacePoint referencePoint, int charge, Random random) {
+    /**
+     * Creates a new Track with the given parameters.
+     * See #{@link #getTrack(SpacePoint, SpacePoint, SpacePoint, int, Random)} for details.
+     * @param momentum The momentum at a given location 
+     * @param location The location where the momentum is measured
+     * @param charge The charge of the Particle that created the Track
+     * @return A new NewTrack object with the desired properties
+     */
+    public Track getTrack(SpacePoint momentum, SpacePoint location, int charge) {
+        return getTrack(momentum, location, new SpacePoint(), charge, new Random());
+    }
+
+    /**
+     * Creates a new Track with the given parameters.
+     * See #{@link #getTrack(SpacePoint, SpacePoint, SpacePoint, int, Random)} for details.
+     * @param momentum The momentum at a given location 
+     * @param location The location where the momentum is measured
+     * @param charge The charge of the Particle that created the Track
+     * @param random A random generator instance
+     * @return A new NewTrack object with the desired properties
+     */
+    public Track getTrack(SpacePoint momentum, SpacePoint location, int charge, Random random) {
+        return getTrack(momentum, location, new SpacePoint(), charge, random);
+    }
+
+    /**
+     * Creates a new Track with the given parameters.
+     * See #{@link #getTrack(SpacePoint, SpacePoint, SpacePoint, int, Random)} for details.
+     * @param momentum The momentum at a given location 
+     * @param location The location where the momentum is measured
+     * @param referencePoint The point with respect to which the parameters are measured
+     * @param charge The charge of the Particle that created the Track
+     * @return A new NewTrack object with the desired properties
+     */
+    public Track getTrack(SpacePoint momentum, SpacePoint location, SpacePoint referencePoint, int charge) {
+        return getTrack(momentum, location, referencePoint, charge, new Random());
+    }
+
+    /**
+     * This version is only to be used in unit tests.
+     * @param momentum The momentum at a given location 
+     * @param location The location where the momentum is measured
+     * @param referencePoint The point with respect to which the parameters are measured
+     * @param charge The charge of the Particle that created the Track
+     * @param random A random generator instance
+     * @param shouldISmear This parameter switches smearing on/off. It should always be true except in Unit tests.
+     * @return A new NewTrack object with the desired properties
+     */
+    Track getTrack(SpacePoint momentum, SpacePoint location, SpacePoint referencePoint, int charge, Random random, boolean shouldISmear) {
         _swimmer.setTrack(momentum, location, charge);
         double alpha = _swimmer.getDistanceToPoint(referencePoint);
         SpacePoint poca = _swimmer.getPointAtDistance(alpha);
@@ -78,15 +138,14 @@
                 + (poca.y() - referencePoint.y())
                 * cos(parameters.get(phi0)));
         parameters.set(omega, charge * _Bz * fieldConversion / parameters.pt);
-        parameters.set(tanLambda, momentumAtPoca.z()/parameters.pt);
-        parameters.set(z0, poca.z()-referencePoint.z());
+        parameters.set(tanLambda, momentumAtPoca.z() / parameters.pt);
+        parameters.set(z0, poca.z() - referencePoint.z());
         Matrix errorMatrix = new Matrix(5, 5);
         // this sets the measurement error
         double cosTheta = abs(momentumAtPoca.cosTheta());
         double p_mag = momentumAtPoca.magnitude();
-        ResolutionTable table = cosTheta < _tables.getPolarInner()
-            ? _tables.getBarrelTable() 
-            : _tables.getEndcapTable();
+        ResolutionTable table = cosTheta < _tables.getPolarInner() ? _tables.getBarrelTable() : _tables
+                .getEndcapTable();
         errorMatrix = new Matrix(5, 5);
         for (int i = 0; i < 5; i++ ) {
             for (int j = 0; j <= i; j++ ) {
@@ -97,10 +156,53 @@
                 }
             }
         }
-        smearParameters(parameters, errorMatrix, random);
-        return new NewTrack(referencePoint, parameters, errorMatrix, charge);
+        // it's a bit inefficient to always have this condition here, although it's only used in tests.
+        EMap smearParams = shouldISmear 
+            ? smearParameters(parameters, errorMatrix, random)
+            : parameters;
+            
+        // System.out.println("TrackFactory: POCA " + poca);
+        // System.out.println("TrackFactory: Momentum " + momentumAtPoca);
+        return new NewTrack(referencePoint, smearParams, errorMatrix, charge);
+    }
+    
+    /**
+     * 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
+     * @param momentum The momentum at a given location 
+     * @param location The location where the momentum is measured
+     * @param referencePoint The point with respect to which the parameters are measured
+     * @param charge The charge of the Particle that created the Track
+     * @param random A random generator instance
+     * @return A new NewTrack object with the desired properties
+     */
+    public Track getTrack(SpacePoint momentum, SpacePoint location, SpacePoint referencePoint, int charge, Random random) {
+        return getTrack(momentum, location, referencePoint, charge, random, true);
+    }
+    
+    
+    /**
+     * 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
+     * @param track The track to be swum
+     * @param referencePoint The new reference point for the track to swim to
+     */
+    public void setNewReferencePoint(Track track, SpacePoint referencePoint) {
+        _swimmer.setTrack(track);
+        double alpha = _swimmer.getDistanceToPoint(referencePoint);
+        
+        // TODO this involves transportation of the full covariance matrix.
+        // See Paul Avery's notes for details.
+        throw new RuntimeException("not yet implemented !");
     }
 
+    /**
+     * Smears the measurement matrix with a Gaussian error
+     * @param oldParams The unsmeared Parameters
+     * @param errorMatrix The measurement error matrix
+     * @param random A random generator
+     * @return A new set of smeared parameters
+     */
     private EMap smearParameters(EMap oldParams, Matrix errorMatrix, Random random) {
         EigenvalueDecomposition eigen = errorMatrix.eig();
         double[] realEigen = eigen.getRealEigenvalues();
@@ -132,20 +234,4 @@
         }
         return new EMap(parameters, pt);
     }
-
-    Track getTrack(SpacePoint momentum, SpacePoint location, SpacePoint referencePoint, int charge) {
-        return getTrack(momentum, location, referencePoint, charge, new Random());
-    }
-
-    Track getTrack(SpacePoint momentum, SpacePoint location, int charge, Random random) {
-        return getTrack(momentum, location, new SpacePoint(), charge, random);
-    }
-
-    Track getTrack(SpacePoint momentum, SpacePoint location, int charge) {
-        return getTrack(momentum, location, new SpacePoint(), charge, new Random());
-    }
-
-    public void setNewReferencePoint(Track track, SpacePoint referencePoint) {
-        _swimmer.setTrack(track);
-    }
 }
CVSspam 0.2.8