5 added + 3 modified, total 8 files
lcsim/src/org/lcsim/contrib/JanStrube/tracking
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
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
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
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
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
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
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
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