/*-
* 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.dawnsci.analysis.api.fitting.functions.IPeak;
/**
* A peak function is determined at least three parameters:
* position, full width at half-maximum, area
* <p>
* If height of peak can be calculated then set height in the overriding
* calcCachedParameters method.
*/
public abstract class APeak extends AFunction implements IPeak {
protected static final String[] PARAM_NAMES = new String[]{"posn", "fwhm", "area"};
protected static final String PEAK_DESC = "\nA peak function is described by"
+ "\n 'posn' is the position of maximum of the peak,"
+ "\n 'fwhm' is the full-width at half-maximum value of the peak,"
+ "\n 'area' is the area of the peak.";
protected static final int POSN = 0;
protected static final int FWHM = 1;
protected static final int AREA = 2;
protected double height; // height of peak
public APeak(int n) {
super(n);
}
/**
* Constructor which takes the three properties required, which are
*
* <pre>
* Parameter 1 - Position
* Parameter 2 - FWHM (full width at half maximum)
* Parameter 3 - Area
* </pre>
*
* @param params
*/
public APeak(double... params) {
super(3);
if (params.length != 3) {
throw new IllegalArgumentException("A peak requires 3 parameters, and it has been given " + params.length);
}
setParameterValues(params);
setNames();
getParameter(FWHM).setLowerLimit(0.0);
}
/**
* Constructor which takes the three properties required, which are
*
* <pre>
* Parameter 1 - Position
* Parameter 2 - FWHM (full width at half maximum)
* Parameter 3 - Area
* </pre>
*
* @param params
*/
public APeak(IParameter... params) {
super(3);
if (params.length != 3) {
throw new IllegalArgumentException("A peak requires 3 parameters, and it has been given " + params.length);
}
setParameters(params);
setNames();
getParameter(FWHM).setLowerLimit(0.0);
}
public APeak(IdentifiedPeak peakParameters) {
super(3);
setParameters(peakParameters);
setNames();
}
protected void setParameters(IdentifiedPeak peakParameters) {
double range = peakParameters.getMaxXVal() - peakParameters.getMinXVal();
double maxArea = peakParameters.getHeight() * range * 4;
IParameter p;
p = getParameter(POSN);
p.setValue(peakParameters.getPos());
p.setLimits(peakParameters.getMinXVal(), peakParameters.getMaxXVal());
p = getParameter(FWHM);
p.setLimits(0, range*2);
p.setValue(peakParameters.getFWHM() / 2);
p = getParameter(AREA);
p.setLimits(-maxArea, maxArea);
p.setValue(peakParameters.getArea() / 2); // area better fitting is generally found if sigma expands into the peak.
}
/**
* 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 of the peak position
* @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 APeak(double minPeakPosition, double maxPeakPosition, double maxFWHM, double maxArea) {
super(3);
setNames();
internalSetPeakParameters(minPeakPosition, maxPeakPosition, maxFWHM, maxArea);
}
protected void internalSetPeakParameters(double minPeakPosition, double maxPeakPosition, double maxFWHM, double maxArea) {
IParameter p;
p = getParameter(POSN);
p.setValue((maxPeakPosition + minPeakPosition) / 2.0);
p.setLimits(minPeakPosition, maxPeakPosition);
p = getParameter(FWHM);
p.setLimits(0.0, maxFWHM);
p.setValue(maxFWHM / 5.0);
p = getParameter(AREA);
p.setLimits(-maxArea, maxArea);
p.setValue(maxArea / 2.0); // better fitting is generally found if sigma expands into the peak.
}
@Override
public double getPosition() {
return getParameterValue(POSN);
}
@Override
public double getFWHM() {
return getParameterValue(FWHM);
}
@Override
public double getArea() {
return getParameterValue(AREA);
}
@Override
public double getHeight() {
if (isDirty())
calcCachedParameters();
return height;
}
/**
* Implement this to set height and any other internally-used values
*/
abstract protected void calcCachedParameters();
}