Print

Print


Commit in lcsim/test/org/lcsim/fit/twopointcircle on MAIN
TwoPointCircleFitterTest.java+160added 1.1
New test case for the TwoPointCircleFitter

lcsim/test/org/lcsim/fit/twopointcircle
TwoPointCircleFitterTest.java added at 1.1
diff -N TwoPointCircleFitterTest.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ TwoPointCircleFitterTest.java	3 Nov 2009 23:53:40 -0000	1.1
@@ -0,0 +1,160 @@
+/*
+ * Test case for the TwoPointCircleFitter.
+ */
+
+package org.lcsim.fit.twopointcircle;
+
+import java.util.List;
+import java.util.Random;
+import junit.framework.TestCase;
+
+/**
+ * @author Richard Partridge
+ */
+public class TwoPointCircleFitterTest extends TestCase {
+
+    public void testTwoPointCircleFitter() {
+        TwoPointCircleFitter fitter = new TwoPointCircleFitter();
+        fitter.setDebug(true);
+        double epsilon = 1.0e-6;
+        Random r = new Random();
+        // generate a set of random circles
+        double xmax = 1000.;
+        double ymax = 1000.;
+        double dmax = 10.;
+        for(int i=0; i<1000000; ++i)
+        {
+            //  Pick the center of the circle and the impact parameter
+            double xc = (2 * r.nextDouble() - 1.) * xmax;
+            double yc = (2 * r.nextDouble() - 1.) * ymax;
+            double d0 = r.nextDouble()*dmax;
+
+            //  If the center of the circle is inside the impact parameter, skip
+            double rcent = Math.sqrt(xc*xc + yc*yc);
+            if (rcent <= d0) continue;
+
+            //  Loop over the two possible circle radii for this test
+            for (int j=0; j<2; j++) {
+                double radius = rcent + (2*j - 1) * d0;
+
+                //  Generate the two hits
+                double [] hit1 = nextPoint(xc, yc, radius, d0);
+                double [] hit2 = nextPoint(xc, yc, radius, d0);
+
+                //  Set the minimum radius
+                double rmin = 0.;
+                if (r.nextBoolean()) rmin = xmax * r.nextDouble();
+                fitter.setRMin(rmin);
+
+                //  Do the fit
+                boolean success = fitter.FitCircle(hit1[0], hit1[1], hit2[0], hit2[1], d0);
+
+                //  If the circle radius is larger than the min radius, we should have found a solution
+                if (radius >= rmin) assertTrue(success);
+
+                //  Check the circle fits go through hits 1 & 2
+                List<TwoPointCircleFit> cfits = fitter.getCircleFits();
+                for (TwoPointCircleFit fit : cfits) {
+
+                    //  Calculate the locations of hits 1 & 2 from the circle parameters
+                    double rcfit = fit.rc();
+                    double xcfit = fit.xc();
+                    double ycfit = fit.yc();
+                    double phi0 = Math.atan2(-ycfit, -xcfit);
+                    double dphi1 = fit.s1() / rcfit;
+                    double dphi2 = fit.s2() / rcfit;
+                    double phi1;
+                    double phi2;
+                    if (fit.cw()) {
+                        phi1 = phi0 - dphi1;
+                        phi2 = phi0 - dphi2;
+                    } else {
+                        phi1 = phi0 + dphi1;
+                        phi2 = phi0 + dphi2;
+                    }
+                    double x1 = xcfit + rcfit * Math.cos(phi1);
+                    double y1 = ycfit + rcfit * Math.sin(phi1);
+                    double x2 = xcfit + rcfit * Math.cos(phi2);
+                    double y2 = ycfit + rcfit * Math.sin(phi2);
+
+                    //  Check that the hit positions match
+                    assertEquals(x1, hit1[0], epsilon);
+                    assertEquals(y1, hit1[1], epsilon);
+                    assertEquals(x2, hit2[0], epsilon);
+                    assertEquals(y2, hit2[1], epsilon);
+
+                    //  Check that the circle radius exceeds the minimum value
+                    assertTrue(rcfit+epsilon >= rmin);
+
+                    //  Check that the IP matches the specified value if the circle radius is above the minimum
+                    if (rcfit > rmin) {
+                       double dcent = Math.sqrt(xcfit*xcfit + ycfit*ycfit);
+                       assertEquals(Math.abs(dcent - rcfit), d0, epsilon);
+                    }
+                }
+
+                //  If we have a line fit, make sure it goes through the hits
+                TwoPointLineFit lfit = fitter.getLineFit();
+                if (lfit != null) {
+
+                    //  Calculate the hit positions
+                    double x0fit = lfit.x0();
+                    double y0fit = lfit.y0();
+                    double phi0fit = lfit.phi0();
+                    double x1fit = x0fit + lfit.s1() * Math.cos(phi0fit);
+                    double y1fit = y0fit + lfit.s1() * Math.sin(phi0fit);
+                    double x2fit = x0fit + lfit.s2() * Math.cos(phi0fit);
+                    double y2fit = y0fit + lfit.s2() * Math.sin(phi0fit);
+
+                    //  Check that the hit positions match
+                    assertEquals(x1fit, hit1[0], epsilon);
+                    assertEquals(y1fit, hit1[1], epsilon);
+                    assertEquals(x2fit, hit2[0], epsilon);
+                    assertEquals(y2fit, hit2[1], epsilon);
+                }
+
+                //  If we have a line fit with two circle fits, check that the circle fits have opposite sign
+                if (cfits.size() == 2 && lfit != null) {
+                    assertEquals(cfits.get(0).cw(), !cfits.get(1).cw());
+                }
+
+                //  If the generate circle has a radius above the minimum, check that one
+                //  of the two solutions matches the generated circle
+                if (radius > rmin) {
+
+                    //  Find the best match to the generated circle center
+                    double dbest = 1.0e99;
+                    TwoPointCircleFit bestfit = null;
+                    for (TwoPointCircleFit fit : fitter.getCircleFits()) {
+                        double xcfit = fit.xc();
+                        double ycfit = fit.yc();
+                        double dist = (xcfit - xc)*(xcfit - xc) + (ycfit - yc)*(ycfit - yc);
+                        if (dist < dbest) {
+                            bestfit = fit;
+                            dbest = dist;
+                        }
+                    }
+
+                    //  Check that the best fit matches the generated circle
+                    assertEquals(bestfit.xc(), xc, epsilon);
+                    assertEquals(bestfit.yc(), yc, epsilon);
+                    assertEquals(bestfit.rc(), radius, epsilon);
+                }
+            }
+        }
+    }
+    private double[] nextPoint( double xc, double yc, double rc, double d0)
+    {
+        Random rn = new Random();
+        double[] p = new double[2];
+        double r = -1.;
+        while (r < d0) {
+            double phi = rn.nextDouble()*2.*Math.PI;
+            p[0] = rc*Math.cos(phi)+xc;
+            p[1] = rc*Math.sin(phi)+yc;
+            r = Math.sqrt(p[0]*p[0]+p[1]*p[1]);
+        }
+        return p;
+    }
+
+}
CVSspam 0.2.8