Print

Print


Commit in lcsim/src/org/lcsim/fit/twopointcircle on MAIN
TwoPointCircleFit.java+79added 1.1
TwoPointCircleFitter.java+254added 1.1
TwoPointLineFit.java+72added 1.1
+405
3 added files
New class to fit a circle to two points and a specified impact parameter.

lcsim/src/org/lcsim/fit/twopointcircle
TwoPointCircleFit.java added at 1.1
diff -N TwoPointCircleFit.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ TwoPointCircleFit.java	29 Oct 2009 19:15:55 -0000	1.1
@@ -0,0 +1,79 @@
+/*
+ * Encapsulate results of a 2 point circle fit
+ */
+
+package org.lcsim.fit.twopointcircle;
+
+/**
+ * @author Richard Partridge
+ */
+public class TwoPointCircleFit {
+
+    private double _xc;
+    private double _yc;
+    private double _rc;
+    private double _s1;
+    private double _s2;
+
+    /**
+     * Fully qualified constructor.
+     *
+     * @param xc x coordinate of circle center
+     * @param yc y coordinate of circle center
+     * @param rc circle radius
+     * @param s1 arc length from the DCA to the first hit
+     * @param s2 arc length from the DCA to the second hit
+     */
+    public TwoPointCircleFit(double xc, double yc, double rc, double s1, double s2) {
+        _xc = xc;
+        _yc = yc;
+        _rc = rc;
+        _s1 = s1;
+        _s2 = s2;
+    }
+
+    /**
+     * Return the x coordinate of the circle center.
+     *
+     * @return x coordinate of the circle center
+     */
+    public double xc() {
+        return _xc;
+    }
+
+    /**
+     * Return the y coordinate of the circle center.
+     *
+     * @return y coordinate of the circle center
+     */
+    public double yc() {
+        return _yc;
+    }
+
+    /**
+     * Return the radius of the circle.
+     *
+     * @return circle radius
+     */
+    public double rc() {
+        return _rc;
+    }
+
+    /**
+     * Return the arc length to the first hit.
+     *
+     * @return arc length to the first hit
+     */
+    public double s1() {
+        return _s1;
+    }
+
+    /**
+     * Return the arc length to the second hit.
+     *
+     * @return arc length to the second hit.
+     */
+    public double s2() {
+        return _s2;
+    }
+}

lcsim/src/org/lcsim/fit/twopointcircle
TwoPointCircleFitter.java added at 1.1
diff -N TwoPointCircleFitter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ TwoPointCircleFitter.java	29 Oct 2009 19:15:55 -0000	1.1
@@ -0,0 +1,254 @@
+/*
+ * Find the circle passing through two points and a fixed impact parameter.
+ * Typically, there are two circles that satisfy these criteria.  The exception
+ * is when a straight line connecting the two points has the specified impact
+ * parameter, where there is only one solution.
+ * 
+ * Optionally, you can provide a minimum circle radius.  If neither circle
+ * satisfies the minimum circle radius cut, the fit fails.  If one circle
+ * satisfies the minimum radius cut, but the other solution does not, then a
+ * second solution is found by setting the radius to the minimum radius and
+ * allowing the impact parameter to be smaller than the specified value.
+ *
+ * This class is used by the seedtracker track finding algorithm to check if
+ * a two hit trial seed satisfies the specified pT and impact parameter cuts.
+ * The two solutions found will generally correspond to the minimum and maximum
+ * radius circles given the two hits and the impact parameter cut.  However,
+ * if the two hits are consistent with a straight-line with an impact parameter
+ * less than or equal to the specified value, there is no upper limit on the
+ * circle radius.  A method is provided to check for this special case and
+ * return the straight-line parameters.
+ */
+
+package org.lcsim.fit.twopointcircle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lcsim.event.TrackerHit;
+
+/**
+ * @author Richard Partridge
+ */
+public class TwoPointCircleFitter {
+    private double _rmin;
+    private double _eps = 1e-6;
+    private List<TwoPointCircleFit> _circlefits;
+    private TwoPointLineFit _linefit;
+    private boolean _debug = true;
+
+    /**
+     * Constructor specifying a minimum radius.  If the minimum radius is >0,
+     * the algorithm will enforce this constraint even if it means having a
+     * smaller impact parameter or fewer / no successful fits.
+     *
+     * @param rmin minimum circle radius
+     */
+    public TwoPointCircleFitter(double rmin) {
+        _rmin = rmin;
+        _circlefits = new ArrayList<TwoPointCircleFit>();
+    }
+
+    /**
+     * Constructor with no minimum radius.
+     */
+    public TwoPointCircleFitter() {
+        this(0.);
+    }
+
+    /**
+     * Fit a circle given two TrackerHits and the impact parameter.
+     *
+     * @param hit1 hit #1
+     * @param hit2 hit #2
+     * @param dmax impact parameter
+     * @return fit status - true if at least one circle fit is found
+     */
+    public boolean FitCircle(TrackerHit hit1, TrackerHit hit2, double dmax) {
+        double[] pos1 = hit1.getPosition();
+        double[] pos2 = hit2.getPosition();
+        return FitCircle(pos1[0], pos1[1], pos2[0], pos2[1], dmax);
+    }
+
+    /**
+     * Fit a circle given coordinates for two points and the impact parameter.
+     *
+     * @param x1 x coordinate of first point
+     * @param y1 y coordinate of first point
+     * @param x2 x coordinate of second point
+     * @param y2 y coordinate of second point
+     * @param dmax impact parameter
+     * @return fit status - true if at least one circle fit is found
+     */
+    public boolean FitCircle(double x1, double y1, double x2, double y2, double dmax) {
+
+        //  Clear the list of fits from the previous time the method was called
+        _circlefits.clear();
+        _linefit = null;
+
+        //  Calculate some useful quantities
+        double r1sq = x1*x1 + y1*y1;
+        double r2sq = x2*x2 + y2*y2;
+        double dmaxsq = dmax*dmax;
+
+        //  If either point is inside maximum IP cut, throw an exception since
+        //  we are under-constrained.
+        if (r1sq < dmaxsq || r2sq < dmaxsq)
+            throw new RuntimeException("Cannot handle case where hit is inside maximum impact parameter cut");
+
+        //  Get the u = (r2 - r1)/|r2 - r1| unit vector
+        double ux = x2 - x1;
+        double uy = y2 - y1;
+        double u = Math.sqrt(ux*ux + uy*uy);
+        ux = ux / u;
+        uy = uy / u;
+        if (u < _eps) throw new RuntimeException("Hits have identical x-y coordinates");
+
+        //  get the midpoint vector
+        double mx = 0.5 * (x1 + x2);
+        double my = 0.5 * (y1 + y2);
+        double msq = mx*mx + my*my;
+
+        //  Get the unit vector normal to u
+        double vx = uy;
+        double vy = -ux;
+
+        //  Get the impact parameter for an infinite momentum track with hits 1 & 2
+        double ipinf = (x1*y2 - y1*x2) / u;
+
+        //  Create an array to hold alpha, the distance of the circle center from the midpoint between hits 1 and 2
+        int nalpha = 2;
+        double alpha[] = new double[nalpha];
+
+        //  First calculate the denominator used in the calculation of alpha
+        double denom = 2. * (ipinf*ipinf - dmaxsq);
+
+        //  Check if we are consistent with a straight-line track
+        boolean sltrack = denom < _eps;
+
+        //  Check for the singular case that occurs when a straight-line track going through the two hits
+        //  is tangent to a circle of radius _dMax
+        if (Math.abs(denom) < _eps) {
+
+            //  Singular case - only one finite momentum solution
+            double beta = msq - 0.25 * u*u - dmaxsq;
+            nalpha = 1;
+            alpha[0] = (u*u * dmaxsq - beta*beta) / (4. * beta * ipinf);
+
+        } else {
+
+            //  Non-singular case - find the two solutions for alpha
+            double r1dotr2 = x1*x2 + y1*y2;
+            double term1 = -ipinf * (r1dotr2 - dmaxsq) / denom;
+            double term2 = Math.abs(dmax * Math.sqrt((r1sq - dmaxsq) * (r2sq - dmaxsq)) / denom);
+            alpha[0] = term1 + term2;
+            alpha[1] = term1 - term2;
+        }
+
+        //  Loop over the two solutions
+        for (int i = 0; i<nalpha; i++) {
+
+            //  Find the circle radius and check if it exceeds the minimum value
+            double rcurv = Math.sqrt(alpha[i]*alpha[i] + 0.25 * u*u);
+            if (rcurv < _rmin) {
+
+                //  The first iteration has the largest circle radius - if it doesn't pass the cut and the track
+                //  isn't consistent with a straight-line track, we can't form a circle that passes the pT cut
+                if (i == 0 && !sltrack) return false;
+
+                //  If we get here, either the first solution passed the pT cut or we are consistent with a
+                //  straight-line track.  Find the circle with the minimum radius
+                rcurv = _rmin;
+                double newalpha = Math.sqrt(_rmin*_rmin - 0.25 * u*u);
+                if (alpha[i] > 0) alpha[i] = newalpha;
+                else alpha[i] = -newalpha;
+            }
+
+            //  Find the center of the circle
+            double xc = mx + alpha[i] * vx;
+            double yc = my + alpha[i] * vy;
+            double rc = Math.sqrt(xc*xc + yc*yc);
+
+            //  Find the point of closest approach
+            double x0 = xc * (1. - rcurv / rc);
+            double y0 = yc * (1. - rcurv / rc);
+
+            //  Make some checks if we have debugging turned on
+            if (_debug) {
+                double c1 = Math.sqrt((x1-xc)*(x1-xc)+(y1-yc)*(y1-yc));
+                if (Math.abs(c1-rcurv) > _eps * c1) throw new RuntimeException("Error in circle finding - c1 = "+c1+" rcurv = "+rcurv);
+                double c2 = Math.sqrt((x2-xc)*(x2-xc)+(y2-yc)*(y2-yc));
+                if (Math.abs(c2-rcurv) > _eps * c2) throw new RuntimeException("Error in circle finding - c2 = "+c2+" rcurv = "+rcurv);
+                double c3 = Math.sqrt((x0-xc)*(x0-xc)+(y0-yc)*(y0-yc));
+                if (Math.abs(c3-rcurv) > _eps * c3) throw new RuntimeException("Error in circle finding - c3 = "+c3+" rcurv = "+rcurv);
+                double r0 = Math.sqrt(x0*x0 + y0*y0);
+                if (r0 > dmax+100*_eps) throw new RuntimeException("Invalid DCA point for solution "+i+" r0: "+r0+" dmax: "+dmax);
+                if (rcurv < _rmin) throw new RuntimeException("Invalid circle radius for solution "+i+" rcurv: "+rcurv+" rmin: "+_rmin);
+            }
+
+            //  Find the x-y arc lengths to hits 1 and 2
+            double d1 = Math.sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
+            double s1 = Math.asin(0.5 * d1 / rcurv);
+            double d2 = Math.sqrt((x2-x0)*(x2-x0) + (y2-y0)*(y2-y0));
+            double s2 = Math.asin(0.5 * d2 / rcurv);
+
+            _circlefits.add(new TwoPointCircleFit(xc, yc, rcurv, s1, s2));
+        }
+
+        //  If we are consistent with a straight-line track, calculate the straight-line
+        //  distances to the hits
+        if (sltrack) {
+
+            //  Find the distances from the straight-line DCA to the hits
+            double s1 = (x1*ux + y1*uy);
+            double s2 = (x2*ux + y2*uy);
+            double phi = Math.atan2(y2-y1, x2-x1);
+
+            _linefit = new TwoPointLineFit(phi, ipinf, s1, s2);
+
+            //  We should always find a valid circle above for this case - check to make sure
+            if (_debug & _circlefits.size() == 0) throw new RuntimeException("No circle found for hits consistent with infinite momentum");
+        }
+
+        return _circlefits.size() > 0;
+    }
+
+    /**
+     * Get the list of TwoPointCircleFits that are found.
+     *
+     * @return list of circle fits
+     */
+    public List<TwoPointCircleFit> getCircleFits() {
+        return _circlefits;
+    }
+
+    /**
+     * Get the TwoPointLineFit if the two hits are consistent with a straight-line
+     * track that passes within the circle defined by the impact parameter cut.
+     * If the line connecting the two hits has a larger impact parameter, then
+     * a null pointer is returned.
+     *
+     * @return pointer to line fit (null if no line fit is found)
+     */
+    public TwoPointLineFit getLineFit() {
+        return _linefit;
+    }
+
+    /**
+     * Set the minimum circle radius.
+     *
+     * @param rmin minimum radius
+     */
+    public void setRMin(double rmin) {
+        _rmin = rmin;
+    }
+
+    /**
+     * Turn on/off the debugging checks.
+     *
+     * @param debug state of debug flag
+     */
+    public void setDebug(boolean debug) {
+        _debug = debug;
+    }
+}
\ No newline at end of file

lcsim/src/org/lcsim/fit/twopointcircle
TwoPointLineFit.java added at 1.1
diff -N TwoPointLineFit.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ TwoPointLineFit.java	29 Oct 2009 19:15:55 -0000	1.1
@@ -0,0 +1,72 @@
+/*
+ * Encapsulate parameters for a straight line through two hits.  The straight line
+ * is parameterized as an azimuthal angle and an impact parameter, where the angle
+ * defines the direction travelling from point 1 to point 2, the impact parameter
+ * is positive if r1 x r2 is in the z direction, and s1 and s2 are the distances
+ * to points 1 and 2 from the point of closest approach.
+ */
+
+package org.lcsim.fit.twopointcircle;
+
+/**
+ * @author richp
+ */
+public class TwoPointLineFit {
+    private double _phi0;
+    private double _d0;
+    private double _s1;
+    private double _s2;
+
+    /**
+     * Fully qualified constructor.
+     *
+     * @param phi0 angle of line segment
+     * @param d0 distance of closest approach
+     * @param s1 distance to point 1
+     * @param s2 distance to point 2
+     */
+    public TwoPointLineFit(double phi0, double d0, double s1, double s2) {
+
+        _phi0 = phi0;
+        _d0 = d0;
+        _s1 = s1;
+        _s2 = s2;
+    }
+
+    /**
+     * Return the azimuthal angle of the line segment going from point 1 to point 2
+     *
+     * @return azimuthal angle
+     */
+    public double phi0() {
+        return _phi0;
+    }
+
+    /**
+     * Return the distance of closest approach for the line containing the two
+     * points.  The DCA is positive if r1 x r2 points in the +z direction.
+     *
+     * @return distance of closest approach
+     */
+    public double d0() {
+        return _d0;
+    }
+
+    /**
+     * Return the distance from the point of closest approach to the first point
+     *
+     * @return distance to point 1
+     */
+    public double s1() {
+        return _s1;
+    }
+
+    /**
+     * Return the distance from the point of closest approach to the second point
+     *
+     * @return distance to point 2
+     */
+    public double s2() {
+        return _s2;
+    }
+}
\ No newline at end of file
CVSspam 0.2.8