MATH-514
Removed "ParametricGaussianFunction" (superseded by "Gaussian.Parametric" in package "analysis.function"). git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1072207 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
04bbc3fccf
commit
f2e551b8de
|
@ -43,7 +43,6 @@ import org.apache.commons.math.exception.NullArgumentException;
|
|||
* </ul>
|
||||
*
|
||||
* @see GaussianDerivativeFunction
|
||||
* @see ParametricGaussianFunction
|
||||
* @since 2.2
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.commons.math.optimization.fitting;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.math.exception.DimensionMismatchException;
|
||||
import org.apache.commons.math.exception.util.LocalizedFormats;
|
||||
import org.apache.commons.math.exception.ZeroException;
|
||||
import org.apache.commons.math.exception.NullArgumentException;
|
||||
import org.apache.commons.math.analysis.ParametricUnivariateRealFunction;
|
||||
|
||||
/**
|
||||
* A Gaussian function. Specifically:
|
||||
* <p>
|
||||
* {@code f(x) = a + b*exp(-((x - c)^2 / (2*d^2)))}
|
||||
* <p>
|
||||
* The parameters have the following meaning:
|
||||
* <ul>
|
||||
* <li>{@code a} is a constant offset that shifts {@code f(x)} up or down
|
||||
* <li>{@code b} is the height of the peak
|
||||
* <li>{@code c} is the position of the center of the peak
|
||||
* <li>{@code d} is related to the FWHM by {@code FWHM = 2*sqrt(2*ln(2))*d}
|
||||
* </ul>
|
||||
* Notation key:
|
||||
* <ul>
|
||||
* <li>{@code x^n}: {@code x} raised to the power of {@code n}
|
||||
* <li>{@code exp(x)}: e<sup>x</sup>
|
||||
* <li>{@code sqrt(x)}: square root of {@code x}
|
||||
* <li>{@code ln(x)}: natural logarithm of {@code x}
|
||||
* </ul>
|
||||
* References:
|
||||
* <ul>
|
||||
* <li><a href="http://en.wikipedia.org/wiki/Gaussian_function">Wikipedia:
|
||||
* Gaussian function</a>
|
||||
* </ul>
|
||||
*
|
||||
* @since 2.2
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class ParametricGaussianFunction implements ParametricUnivariateRealFunction, Serializable {
|
||||
/** Serializable version Id. */
|
||||
private static final long serialVersionUID = -3875578602503903233L;
|
||||
|
||||
/**
|
||||
* Computes value of function {@code f(x)} for the specified {@code x} and
|
||||
* parameters {@code a}, {@code b}, {@code c}, and {@code d}.
|
||||
*
|
||||
* @param x Value at which to compute the function.
|
||||
* @return {@code f(x)}.
|
||||
* @param parameters Values of {@code a}, {@code b}, {@code c}, and {@code d}.
|
||||
* @throws NullArgumentException if {@code parameters} is {@code null}.
|
||||
* @throws DimensionMismatchException if the size of {@code parameters} is
|
||||
* not 4.
|
||||
* @throws ZeroException if {@code parameters[3]} is 0.
|
||||
*/
|
||||
public double value(double x, double[] parameters) {
|
||||
validateParameters(parameters);
|
||||
final double a = parameters[0];
|
||||
final double b = parameters[1];
|
||||
final double c = parameters[2];
|
||||
final double d = parameters[3];
|
||||
final double xMc = x - c;
|
||||
return a + b * Math.exp(-xMc * xMc / (2.0 * (d * d)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the gradient vector for a four variable version of the function
|
||||
* where the parameters, {@code a}, {@code b}, {@code c}, and {@code d},
|
||||
* are considered the variables, not {@code x}. That is, instead of
|
||||
* computing the gradient vector for the function {@code f(x)} (which would
|
||||
* just be the derivative of {@code f(x)} with respect to {@code x} since
|
||||
* it's a one-dimensional function), computes the gradient vector for the
|
||||
* function {@code f(a, b, c, d) = a + b*exp(-((x - c)^2 / (2*d^2)))}
|
||||
* treating the specified {@code x} as a constant.
|
||||
* <p>
|
||||
* The components of the computed gradient vector are the partial
|
||||
* derivatives of {@code f(a, b, c, d)} with respect to each variable.
|
||||
* That is, the partial derivative of {@code f(a, b, c, d)} with respect to
|
||||
* {@code a}, the partial derivative of {@code f(a, b, c, d)} with respect
|
||||
* to {@code b}, the partial derivative of {@code f(a, b, c, d)} with
|
||||
* respect to {@code c}, and the partial derivative of {@code f(a, b, c,
|
||||
* d)} with respect to {@code d}.
|
||||
*
|
||||
* @param x Value to be used as constant in {@code f(x, a, b, c, d)}.
|
||||
* @param parameters Values of {@code a}, {@code b}, {@code c}, and {@code d}.
|
||||
* @return the gradient vector of {@code f(a, b, c, d)}.
|
||||
* @throws NullArgumentException if {@code parameters} is {@code null}.
|
||||
* @throws DimensionMismatchException if the size of {@code parameters} is
|
||||
* not 4.
|
||||
* @throws ZeroException if {@code parameters[3]} is 0.
|
||||
*/
|
||||
public double[] gradient(double x, double[] parameters) {
|
||||
validateParameters(parameters);
|
||||
final double b = parameters[1];
|
||||
final double c = parameters[2];
|
||||
final double d = parameters[3];
|
||||
|
||||
final double xMc = x - c;
|
||||
final double d2 = d * d;
|
||||
final double exp = Math.exp(-xMc * xMc / (2 * d2));
|
||||
final double f = b * exp * xMc / d2;
|
||||
|
||||
return new double[] { 1.0, exp, f, f * xMc / d };
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates parameters to ensure they are appropriate for the evaluation of
|
||||
* the {@code value} and {@code gradient} methods.
|
||||
*
|
||||
* @param parameters Values of {@code a}, {@code b}, {@code c}, and {@code d}.
|
||||
* @throws NullArgumentException if {@code parameters} is {@code null}.
|
||||
* @throws DimensionMismatchException if the size of {@code parameters} is
|
||||
* not 4.
|
||||
* @throws ZeroException if {@code parameters[3]} is 0.
|
||||
*/
|
||||
private void validateParameters(double[] parameters) {
|
||||
if (parameters == null) {
|
||||
throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
|
||||
}
|
||||
if (parameters.length != 4) {
|
||||
throw new DimensionMismatchException(4, parameters.length);
|
||||
}
|
||||
if (parameters[3] == 0) {
|
||||
throw new ZeroException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -52,6 +52,10 @@ The <action> type attribute can be add,update,fix,remove.
|
|||
If the output is not quite correct, check for invisible trailing spaces!
|
||||
-->
|
||||
<release version="3.0" date="TBD" description="TBD">
|
||||
<action dev="erans" type="fix" issue="MATH-514">
|
||||
Removed "ParametricGaussianFunction" (in package "optimization.fitting");
|
||||
functionality moved to class "Gaussian" (in package "analysis.function").
|
||||
</action>
|
||||
<action dev="erans" type="update" issue="MATH-512" due-to="Ole Ersoy">
|
||||
Refactored "GaussianFitter" (in package "optimization.fitting").
|
||||
The class now really fits a Gaussian function (whereas previously it was
|
||||
|
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.commons.math.optimization.fitting;
|
||||
|
||||
import org.apache.commons.math.exception.MathUserException;
|
||||
import org.apache.commons.math.exception.ZeroException;
|
||||
import org.apache.commons.math.exception.MathIllegalArgumentException;
|
||||
import org.apache.commons.math.optimization.OptimizationException;
|
||||
import org.apache.commons.math.optimization.fitting.CurveFitter;
|
||||
import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Tests {@link ParametricGaussianFunction}.
|
||||
*
|
||||
* @since 2.2
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class ParametricGaussianFunctionTest {
|
||||
/** Dataset 1 used by some test cases. */
|
||||
protected static final double[][] DATASET1 = new double[][] {
|
||||
{4.0254623, 531026.0},
|
||||
{4.02804905, 664002.0},
|
||||
{4.02934242, 787079.0},
|
||||
{4.03128248, 984167.0},
|
||||
{4.03386923, 1294546.0},
|
||||
{4.03580929, 1560230.0},
|
||||
{4.03839603, 1887233.0},
|
||||
{4.0396894, 2113240.0},
|
||||
{4.04162946, 2375211.0},
|
||||
{4.04421621, 2687152.0},
|
||||
{4.04550958, 2862644.0},
|
||||
{4.04744964, 3078898.0},
|
||||
{4.05003639, 3327238.0},
|
||||
{4.05132976, 3461228.0},
|
||||
{4.05326982, 3580526.0},
|
||||
{4.05585657, 3576946.0},
|
||||
{4.05779662, 3439750.0},
|
||||
{4.06038337, 3220296.0},
|
||||
{4.06167674, 3070073.0},
|
||||
{4.0636168, 2877648.0},
|
||||
{4.06620355, 2595848.0},
|
||||
{4.06749692, 2390157.0},
|
||||
{4.06943698, 2175960.0},
|
||||
{4.07202373, 1895104.0},
|
||||
{4.0733171, 1687576.0},
|
||||
{4.07525716, 1447024.0},
|
||||
{4.0778439, 1130879.0},
|
||||
{4.07978396, 904900.0},
|
||||
{4.08237071, 717104.0},
|
||||
{4.08366408, 620014.0}
|
||||
};
|
||||
|
||||
/**
|
||||
* Using not-so-good initial parameters.
|
||||
*
|
||||
* @throws OptimizationException in the event of a test case error
|
||||
* @throws MathUserException in the event of a test case error
|
||||
*/
|
||||
@Test
|
||||
public void testFit01()
|
||||
throws OptimizationException, MathUserException {
|
||||
CurveFitter fitter = new CurveFitter(new LevenbergMarquardtOptimizer());
|
||||
addDatasetToCurveFitter(DATASET1, fitter);
|
||||
double[] parameters = fitter.fit(new ParametricGaussianFunction(),
|
||||
new double[] {8.64753e3, 3.483323e6, 4.06322, 1.946857e-2});
|
||||
assertEquals(99200.94715858076, parameters[0], 1e-4);
|
||||
assertEquals(3410515.221897707, parameters[1], 1e-4);
|
||||
assertEquals(4.054928275257894, parameters[2], 1e-4);
|
||||
assertEquals(0.014609868499860, parameters[3], 1e-4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using eye-balled guesses for initial parameters.
|
||||
*
|
||||
* @throws OptimizationException in the event of a test case error
|
||||
* @throws MathUserException in the event of a test case error
|
||||
*/
|
||||
@Test
|
||||
public void testFit02()
|
||||
throws OptimizationException, MathUserException {
|
||||
CurveFitter fitter = new CurveFitter(new LevenbergMarquardtOptimizer());
|
||||
addDatasetToCurveFitter(DATASET1, fitter);
|
||||
double[] parameters = fitter.fit(new ParametricGaussianFunction(),
|
||||
new double[] {500000.0, 3500000.0, 4.055, 0.025479654});
|
||||
assertEquals(99200.81836264656, parameters[0], 1e-4);
|
||||
assertEquals(3410515.327151986, parameters[1], 1e-4);
|
||||
assertEquals(4.054928275377392, parameters[2], 1e-4);
|
||||
assertEquals(0.014609869119806, parameters[3], 1e-4);
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameters array is null.
|
||||
*
|
||||
* @throws MathUserException in the event of a test case error
|
||||
*/
|
||||
@Test(expected=MathIllegalArgumentException.class)
|
||||
public void testValue01() throws MathUserException {
|
||||
ParametricGaussianFunction f = new ParametricGaussianFunction();
|
||||
f.value(0.0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameters array length is not 4.
|
||||
*
|
||||
* @throws MathUserException in the event of a test case error
|
||||
*/
|
||||
@Test(expected=MathIllegalArgumentException.class)
|
||||
public void testValue02() throws MathUserException {
|
||||
ParametricGaussianFunction f = new ParametricGaussianFunction();
|
||||
f.value(0.0, new double[] {0.0, 1.0});
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameters d is 0.
|
||||
*
|
||||
* @throws MathUserException in the event of a test case error
|
||||
*/
|
||||
@Test(expected=ZeroException.class)
|
||||
public void testValue03() throws MathUserException {
|
||||
ParametricGaussianFunction f = new ParametricGaussianFunction();
|
||||
f.value(0.0, new double[] {0.0, 1.0, 1.0, 0.0});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified points to specified <code>CurveFitter</code> instance.
|
||||
*
|
||||
* @param points data points where first dimension is a point index and
|
||||
* second dimension is an array of length two representing the point
|
||||
* with the first value corresponding to X and the second value
|
||||
* corresponding to Y
|
||||
* @param fitter fitter to which the points in <code>points</code> should be
|
||||
* added as observed points
|
||||
*/
|
||||
protected static void addDatasetToCurveFitter(double[][] points,
|
||||
CurveFitter fitter) {
|
||||
for (int i = 0; i < points.length; i++) {
|
||||
fitter.addObservedPoint(points[i][0], points[i][1]);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue