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:
Gilles Sadowski 2011-02-19 00:03:46 +00:00
parent 04bbc3fccf
commit f2e551b8de
4 changed files with 4 additions and 302 deletions

View File

@ -43,7 +43,6 @@ import org.apache.commons.math.exception.NullArgumentException;
* </ul>
*
* @see GaussianDerivativeFunction
* @see ParametricGaussianFunction
* @since 2.2
* @version $Revision$ $Date$
*/

View File

@ -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();
}
}
}

View File

@ -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

View File

@ -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]);
}
}
}