/*- * 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.functions; import org.eclipse.dawnsci.analysis.api.fitting.functions.IParameter; import org.eclipse.january.dataset.Dataset; import org.eclipse.january.dataset.DatasetUtils; import org.eclipse.january.dataset.DoubleDataset; import org.eclipse.january.dataset.Maths; /** * Class that wrappers the equation <br> * y(x) = ax^3 + bx^2 + cx + d */ public class Cubic extends AFunction { private static final String NAME = "Cubic"; private static final String DESC = "A cubic function." + "\n y(x) = a*x^3 + b*x^2 + c*x + d"; private static final String[] PARAM_NAMES = new String[]{"a", "b", "c", "d"}; /** * Basic constructor, not advisable to use */ public Cubic() { super(4); } public Cubic(double[] params) { super(params); } public Cubic(IParameter... params) { super(params); } /** * Constructor that allows for the positioning of all the parameter bounds * * @param minA * minimum boundary for the A parameter * @param maxA * maximum boundary for the A parameter * @param minB * minimum boundary for the B parameter * @param maxB * maximum boundary for the B parameter * @param minC * minimum boundary for the C parameter * @param maxC * maximum boundary for the C parameter * @param minD * minimum boundary for the D parameter * @param maxD * maximum boundary for the D parameter */ public Cubic(double minA, double maxA, double minB, double maxB, double minC, double maxC, double minD, double maxD) { super(4); getParameter(0).setLimits(minA,maxA); getParameter(0).setValue((minA + maxA) / 2.0); getParameter(1).setLimits(minB,maxB); getParameter(1).setValue((minB + maxB) / 2.0); getParameter(2).setLimits(minC,maxC); getParameter(2).setValue((minC + maxC) / 2.0); getParameter(3).setLimits(minD,maxD); getParameter(3).setValue((minD + maxD) / 2.0); } @Override protected void setNames() { setNames(NAME, DESC, PARAM_NAMES); } private transient double a, b, c, d; private void calcCachedParameters() { a = getParameterValue(0); b = getParameterValue(1); c = getParameterValue(2); d = getParameterValue(3); setDirty(false); } @Override public double val(double... values) { if (isDirty()) calcCachedParameters(); double position = values[0]; return a * position * position * position + b * position * position + c * position + d; } @Override public void fillWithValues(DoubleDataset data, CoordinatesIterator it) { if (isDirty()) calcCachedParameters(); it.reset(); double[] coords = it.getCoordinates(); int i = 0; double[] buffer = data.getData(); while (it.hasNext()) { double p = coords[0]; buffer[i++] = a * p * p * p + b * p * p + c * p + d; } } @Override public double partialDeriv(IParameter parameter, double... position) { if (isDuplicated(parameter)) return super.partialDeriv(parameter, position); int i = indexOfParameter(parameter); final double pos = position[0]; switch (i) { case 0: return pos * pos * pos; case 1: return pos * pos; case 2: return pos; case 3: return 1.0; default: return 0; } } @Override public void fillWithPartialDerivativeValues(IParameter parameter, DoubleDataset data, CoordinatesIterator it) { Dataset pos = DatasetUtils.convertToDataset(it.getValues()[0]); int i = indexOfParameter(parameter); switch (i) { case 0: Maths.power(pos, 3, data); break; case 1: Maths.square(pos, data); break; case 2: data.setSlice(pos); break; case 3: data.fill(1); break; default: break; } } }