/*- * 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.DoubleDataset; /** * Class which expands on the AFunction class to give the properties of a Gaussian. A 1D implementation */ public class Gaussian extends APeak { private static final String NAME = "Gaussian"; private static final String DESC = "A Gaussian or normal distribution." + "\n y(x) = A exp( -(x-posn)^2 / a^2 )" + "\nwhere fwhm = 2*a*sqrt(ln(2)), and area = sqrt(pi) * a * A." + PEAK_DESC; private static final double[] PARAMS = new double[]{0, 0, 0}; public Gaussian() { this(PARAMS); } /** * Constructor which takes the three parameters required, which are * * <pre> * Parameter 1 - Position * Parameter 2 - FWHM (full width at half maximum) * Parameter 3 - Area * </pre> * * @param params */ public Gaussian(double... params) { super(params); } public Gaussian(IParameter... params) { super(params); } public Gaussian(IdentifiedPeak peakParameters) { super(peakParameters); } /** * Constructor which takes more sensible values for the parameters, which also incorporates the limits which they * can be in, reducing the overall complexity of the problem * * @param minPeakPosition * The minimum value the peak position of the Gaussian * @param maxPeakPosition * The maximum value of the peak position * @param maxFWHM * Full width at half maximum * @param maxArea * The maximum area of the peak */ public Gaussian(double minPeakPosition, double maxPeakPosition, double maxFWHM, double maxArea) { super(minPeakPosition, maxPeakPosition, maxFWHM, maxArea); } @Override protected void setNames() { setNames(NAME, DESC, PARAM_NAMES); } private static final double CONST_A = Math.sqrt(4. * Math.log(2.)); private static final double CONST_B = 1.0 / Math.sqrt(Math.PI); private transient double pos, fr; @Override protected void calcCachedParameters() { pos = getParameterValue(POSN); fr = CONST_A / getParameterValue(FWHM); height = fr * CONST_B * getParameterValue(AREA); setDirty(false); } @Override public double val(double... values) { if (isDirty()) { calcCachedParameters(); } final double arg = fr * (values[0] - pos); return height * Math.exp(-(arg * arg)); } @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 arg = fr * (coords[0] - pos); buffer[i++] = height * Math.exp(-(arg * arg)); } } @Override public double partialDeriv(IParameter parameter, double... position) { if (isDirty()) { calcCachedParameters(); } if (isDuplicated(parameter)) { return super.partialDeriv(parameter, position); } int i = indexOfParameter(parameter); final double del = position[0] - pos; final double arg = fr * del; switch (i) { case 0: return 2*height*arg*fr*Math.exp(-(arg * arg)); case 1: final double sqarg = arg * arg; return fr*height*(2*sqarg - 1)*Math.exp(-sqarg)/CONST_A; case 2: return CONST_B * fr * Math.exp(-(arg * arg)); default: return 0; } } @Override public void fillWithPartialDerivativeValues(IParameter parameter, DoubleDataset data, CoordinatesIterator it) { if (isDirty()) { calcCachedParameters(); } if (isDuplicated(parameter)) { super.fillWithPartialDerivativeValues(parameter, data, it); return; } int j = indexOfParameter(parameter); it.reset(); double[] coords = it.getCoordinates(); int i = 0; double[] buffer = data.getData(); switch (j) { case 0: while (it.hasNext()) { final double del = coords[0] - pos; final double arg = fr * del; buffer[i++] = 2*height*arg*fr*Math.exp(-(arg * arg)); } break; case 1: while (it.hasNext()) { final double del = coords[0] - pos; final double arg = fr * del; final double sqarg = arg * arg; buffer[i++] = fr*height*(2*sqarg - 1)*Math.exp(-sqarg)/CONST_A; } break; case 2: while (it.hasNext()) { final double del = coords[0] - pos; final double arg = fr * del; buffer[i++] = CONST_B * fr * Math.exp(-(arg * arg)); } break; default: break; } } }