/* * Copyright (c) 2012 Diamond Light Source Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package uk.ac.diamond.scisoft.analysis.fitting; import java.util.List; import org.eclipse.dawnsci.analysis.api.fitting.functions.IOperator; import org.eclipse.dawnsci.analysis.api.fitting.functions.IPeak; import org.eclipse.january.dataset.Dataset; import org.eclipse.january.dataset.DoubleDataset; import org.eclipse.january.dataset.IDataset; import org.junit.Assert; import org.junit.Test; import uk.ac.diamond.scisoft.analysis.fitting.functions.Add; import uk.ac.diamond.scisoft.analysis.fitting.functions.Gaussian; import uk.ac.diamond.scisoft.analysis.fitting.functions.IdentifiedPeak; import uk.ac.diamond.scisoft.analysis.fitting.functions.Offset; import uk.ac.diamond.scisoft.analysis.optimize.AbstractOptimizer; import uk.ac.diamond.scisoft.analysis.optimize.ApacheOptimizer; import uk.ac.diamond.scisoft.analysis.optimize.ApacheOptimizer.Optimizer; public class OptimizerTest { static final long SEED = 12357L; public AbstractOptimizer createOptimizer(Optimizer o) { ApacheOptimizer opt = new ApacheOptimizer(o); opt.seed = SEED; return opt; } @Test public void testOptimizer() { DoubleDataset gaussian = Generic1DDatasetCreator.createGaussianDataset(); List<IdentifiedPeak> peaks = Generic1DFitter.parseDataDerivative(Generic1DDatasetCreator.xAxis, gaussian, Generic1DDatasetCreator.smoothing); IdentifiedPeak iniPeak = peaks.get(0); int[] start = { iniPeak .getIndexOfDatasetAtMinPos() }; int[] stop = { iniPeak.getIndexOfDatasetAtMaxPos() + 1 }; int[] step = { 1 }; Dataset y = gaussian.getSlice(start, stop, step); Dataset x = Generic1DDatasetCreator.xAxis.getSlice(start, stop, step); double lowOffset = y.min().doubleValue(); double highOffset = (Double) y.mean(); Offset baseline = new Offset(lowOffset, highOffset); IPeak localPeak = new Gaussian(iniPeak); IOperator comp = new Add(); comp.addFunction(localPeak); comp.addFunction(baseline); AbstractOptimizer opt = createOptimizer(Optimizer.SIMPLEX_MD); try { opt.optimize(new IDataset[] {x}, y, comp); } catch (Exception e) { System.err.println("Problem: " + e); } double[] parameters = opt.getParameterValues(); for (int ind = 0; ind < parameters.length; ind++) { double v = parameters[ind]; double dv = v * 1e-5; double od = evalDiff(parameters, ind, v, dv, opt); double nd = 0; System.err.printf("Difference is %g for %g\n", od, dv); dv *= 0.25; for (int i = 0; i < 20; i++) { // System.err.println(Arrays.toString(parameters)); nd = evalDiff(parameters, ind, v, dv, opt); System.err.printf("Difference is %g for %g\n", nd, dv); if (Math.abs(nd - od) < 1e-15*Math.max(1, Math.abs(od))) { break; } od = nd; dv *= 0.25; } parameters[ind] = v; double pd = opt.calculateResidualDerivative(opt.getParameters().get(ind), parameters); System.err.println(nd + " cf " + pd); Assert.assertEquals(nd, pd, 5e-3*Math.abs(pd)); } } private double evalDiff(double[] parameters, int ind, double v, double dv, AbstractOptimizer opt) { parameters[ind] = v + dv; opt.setParameterValues(parameters); double r = opt.calculateResidual(); parameters[ind] = v - dv; opt.setParameterValues(parameters); r -= opt.calculateResidual(); return (r * 0.5) / dv; } }