uk.ac.diamond.scisoft.analysis.fitting.EllipseFitterTest.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.diamond.scisoft.analysis.fitting.EllipseFitterTest.java

Source

/*
 * Copyright 2011 Diamond Light Source Ltd.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package uk.ac.diamond.scisoft.analysis.fitting;

import java.util.Arrays;

import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.MaxIterationsExceededException;
import org.apache.commons.math.analysis.solvers.BrentSolver;
import org.junit.Assert;
import org.junit.Test;

import uk.ac.diamond.scisoft.analysis.dataset.AbstractDataset;
import uk.ac.diamond.scisoft.analysis.dataset.DoubleDataset;
import uk.ac.diamond.scisoft.analysis.dataset.Maths;
import uk.ac.diamond.scisoft.analysis.dataset.Random;

public class EllipseFitterTest {

    @Test
    public void testOrthoDist() {

        AngleDerivativeFunction angleDerivative = new AngleDerivativeFunction();
        BrentSolver solver = new BrentSolver(BrentSolver.DEFAULT_ABSOLUTE_ACCURACY);
        double a = 10.2;
        double b = 3.1;
        final double twopi = 2 * Math.PI;
        double alpha = twopi * 10. / 360; // 0 to 2 pi
        angleDerivative.setRadii(a, b);
        angleDerivative.setAngle(alpha);

        //      final double ca = 0;
        //      final double cb = b-0.5;
        final double Xc = -5.; // Math.cos(alpha)*ca + Math.sin(alpha)*cb;
        final double Yc = 5.5; //Math.sin(alpha)*ca + Math.cos(alpha)*cb;

        angleDerivative.setCoordinate(Xc, Yc);
        try {
            // find quadrant to use
            double p = Math.atan2(Yc, Xc);
            if (p < 0)
                p += twopi;
            p -= alpha;
            final double end;
            final double halfpi = 0.5 * Math.PI;
            p /= halfpi;
            end = Math.ceil(p) * halfpi;
            final double angle = solver.solve(BrentSolver.DEFAULT_MAXIMUM_ITERATIONS, angleDerivative, end - halfpi,
                    end);
            //         final double cos = Math.cos(angle);
            //         final double sin = Math.sin(angle);

            Assert.assertEquals("Angle found is not close enough", 1.930, angle, 0.001);
            //         double dx = a*cos + Xc;
            //         double dy = b*sin + Yc;
            //
            //         System.out.println("Bracket angle = " + Math.ceil(p));
            //         System.out.println("Delta angle = " + 180.*angle/Math.PI);
            //         System.out.println(dx + ", " + dy);
        } catch (MaxIterationsExceededException e) {
            // TODO
            System.err.println(e);
        } catch (FunctionEvaluationException e) {
            // TODO
            System.err.println(e);
        }

    }

    @Test
    public void testQuickEllipse() {
        double[] original = new double[] { 344.2, 243.2, Math.PI * 0.23, 0.2, -12.3 };

        DoubleDataset theta;
        //      theta = new DoubleDataset(new double[] {0.1, 0.2, 0.25, 0.33, 0.35, 0.37, 0.43, });
        Random.seed(1277);
        theta = Random.rand(0, 2 * Math.PI, 10);

        AbstractDataset[] coords = EllipseFitter.generateCoordinates(theta, original);

        AbstractDataset x;
        AbstractDataset y;
        //      x = new DoubleDataset(new double[] {242.34, 188.08, 300.04, 188.90, 300.97, 103.80, 157.67, 141.81, 302.64, 266.58});
        //      y = new DoubleDataset(new double[] {-262.478, 147.192, -107.673, 136.293, -118.735, 217.387, 166.996, 192.521, -55.201, 17.826});
        x = Maths.add(coords[0], Random.randn(0.0, 10.2, theta.getShape()));
        y = Maths.add(coords[1], Random.randn(0.0, 10.2, theta.getShape()));
        System.err.println(x);
        System.err.println(y);

        EllipseFitter fitter = new EllipseFitter();

        fitter.algebraicFit(x, y);
        double[] result = fitter.getParameters();

        double[] tols = new double[] { 8e-2, 5e-2, 1e-1, 6, -2e-1 };
        for (int i = 0; i < original.length; i++) {
            Assert.assertEquals("Algebraic fit: " + i, original[i], result[i], original[i] * tols[i]);
        }
        System.err.println(Arrays.toString(original));
        System.err.println(Arrays.toString(result));

        fitter.geometricFit(x, y, result);
        result = fitter.getParameters();
        System.err.println(Arrays.toString(result));
        for (int i = 0; i < original.length; i++) {
            Assert.assertEquals("Geometric fit: " + i, original[i], result[i], original[i] * tols[i]);
        }
    }

}