update curve_fit function - still is not usable

This commit is contained in:
wyq 2022-07-31 10:42:00 +08:00
parent 40a4939f28
commit 09ac878bcc
12 changed files with 167 additions and 226 deletions

View File

@ -1,34 +1,34 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="milconfig.xml" Type="configurefile">
<Path OpenPath="D:\Temp\HYSPLIT">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\grads"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite\himawari"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\LaSW"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\meteo\wrf"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\meteo"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\meteo\calc"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\traj"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\traj\TrajStat"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\micaps"/>
<Path OpenPath="D:\Working\MIScript\Jython\mis\plot_types\contour">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\plot"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\no_opengl"/>
<RecentFolder Folder="D:\Temp\HYSPLIT"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\gui"/>
<RecentFolder Folder="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\fitting"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\optimize"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\particles"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\contour"/>
</Path>
<File>
<OpenedFiles>
<OpenedFile File="D:\Working\MIScript\Jython\mis\LaSW\typhoon_map_slice.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\micaps\micaps_4_8.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\plot\plot3_multi_color_1.py"/>
<OpenedFile File="D:\Temp\HYSPLIT\hys_lekima.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\mainGUI.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\common_math\optimize\curve_fit_2.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\contour\conout_negtive_value.py"/>
</OpenedFiles>
<RecentFiles>
<RecentFile File="D:\Working\MIScript\Jython\mis\LaSW\typhoon_map_slice.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\micaps\micaps_4_8.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\plot\plot3_multi_color_1.py"/>
<RecentFile File="D:\Temp\HYSPLIT\hys_lekima.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\mainGUI.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\common_math\optimize\curve_fit_2.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\contour\conout_negtive_value.py"/>
</RecentFiles>
</File>
<Font>
@ -36,5 +36,5 @@
</Font>
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
<Figure DoubleBuffering="true"/>
<Startup MainFormLocation="-7,0" MainFormSize="1342,730"/>
<Startup MainFormLocation="-7,-7" MainFormSize="1293,685"/>
</MeteoInfo>

View File

@ -6,5 +6,6 @@ sys.path.append(toolbox_path)
sys.path.append(os.path.join(toolbox_path, 'miml_dev'))
sys.path.append(os.path.join(toolbox_path, 'EMIPS'))
sys.path.append(os.path.join(toolbox_path, 'IMEP'))
sys.path.append(os.path.join(toolbox_path, 'meteoview3d'))
mipylib.migl.mifolder = 'D:/MyProgram/Distribution/Java/MeteoInfo/MeteoInfo'

View File

@ -1,4 +1,4 @@
from .minpack import *
#from ._lsq import *
from ._lsq import *
__all__ = [s for s in dir() if not s.startswith('_')]

View File

@ -1,3 +1,3 @@
from .least_squares import least_squares
__all__ = ['least_squares', 'lsq_linear']
__all__ = ['least_squares']

View File

@ -132,19 +132,62 @@ def curve_fit(f, xdata, ydata, p0=None, sigma=None, absolute_sigma=False,
n = p0.size
func = UniFunc(f)
jac_func = OptimizeUtil.getJacobianFunction(func, xdata.asarray(), func.order, 5, 0.1)
problem = LeastSquaresBuilder().start(p0.tojarray('double')). \
model(jac_func). \
target(ydata.tojarray('double')). \
lazyEvaluation(False). \
maxEvaluations(1000). \
maxIterations(1000). \
build()
optimum = LevenbergMarquardtOptimizer().optimize(problem)
r = tuple(optimum.getPoint().toArray())
best = OptimizeUtil.curveFit(func, xdata.asarray(), ydata.asarray(), 5, 0.1, p0.tojarray('double'))
r = tuple(best)
return r
# def curve_fit(f, xdata, ydata, p0=None, sigma=None, absolute_sigma=False,
# check_finite=True, bounds=(-np.inf, np.inf), method=None,
# jac=None, **kwargs):
# """
# Use non-linear least squares to fit a function, f, to data.
#
# Assumes ``ydata = f(xdata, *params) + eps``
#
# :param f: callable
# The model function, f(x, ...). It must take the independent
# variable as the first argument and the parameters to fit as
# separate remaining arguments.
# :param xdata: array_like or object
# The independent variable where the data is measured.
# Should usually be an M-length sequence or an (k,M)-shaped array for
# functions with k predictors, but can actually be any object.
# :param ydata: array_like
# The dependent data, a length M array - nominally ``f(xdata, ...)``.
# :param p0: array_like, optional
# Initial guess for the parameters (length N). If None, then the
# initial values will all be 1 (if the number of parameters for the
# function can be determined using introspection, otherwise a
# ValueError is raised).
# :return:
# """
# if p0 is None:
# # determine number of parameters by inspecting the function
# from ..lib._util import getargspec_no_self as _getargspec
# args, varargs, varkw, defaults = _getargspec(f)
# if len(args) < 2:
# raise ValueError("Unable to determine number of fit parameters.")
# n = len(args) - 1
# p0 = np.ones(n)
# else:
# p0 = np.atleast_1d(p0)
# n = p0.size
#
# func = UniFunc(f)
# jac_func = OptimizeUtil.getJacobianFunction(func, xdata.asarray(), func.order, 5, 0.1)
# problem = LeastSquaresBuilder().start(p0.tojarray('double')). \
# model(jac_func). \
# target(ydata.tojarray('double')). \
# lazyEvaluation(False). \
# maxEvaluations(1000). \
# maxIterations(1000). \
# build()
# optimum = LevenbergMarquardtOptimizer().optimize(problem)
# r = tuple(optimum.getPoint().toArray())
#
# return r
def _del2(p0, p1, d):
return p0 - np.square(p1 - p0) / d

View File

@ -810,59 +810,7 @@ class Axes3DGL(Axes3D):
:param cmap: (*string*) Color map string.
:return:
"""
warnings.warn("plot_slice is deprecated", DeprecationWarning)
if len(args) <= 3:
x = args[0].dimvalue(2)
y = args[0].dimvalue(1)
z = args[0].dimvalue(0)
data = args[0]
args = args[1:]
else:
x = args[0]
y = args[1]
z = args[2]
data = args[3]
args = args[4:]
if x.ndim == 3:
x = x[0,0]
if y.ndim == 3:
y = y[0,:,0]
if z.ndim == 3:
z = z[:,0,0]
cmap = plotutil.getcolormap(**kwargs)
if len(args) > 0:
level_arg = args[0]
if isinstance(level_arg, int):
cn = level_arg
ls = LegendManage.createLegendScheme(data.min(), data.max(), cn, cmap)
else:
if isinstance(level_arg, NDArray):
level_arg = level_arg.aslist()
ls = LegendManage.createLegendScheme(data.min(), data.max(), level_arg, cmap)
else:
ls = LegendManage.createLegendScheme(data.min(), data.max(), cmap)
ls = ls.convertTo(ShapeTypes.POLYGON)
edge = kwargs.pop('edge', True)
kwargs['edge'] = edge
plotutil.setlegendscheme(ls, **kwargs)
xslice = kwargs.pop('xslice', [])
if isinstance(xslice, numbers.Number):
xslice = [xslice]
yslice = kwargs.pop('yslice', [])
if isinstance(yslice, numbers.Number):
yslice = [yslice]
zslice = kwargs.pop('zslice', [])
if isinstance(zslice, numbers.Number):
zslice = [zslice]
graphics = JOGLUtil.slice(data.asarray(), x.asarray(), y.asarray(), z.asarray(), xslice, \
yslice, zslice, ls)
visible = kwargs.pop('visible', True)
if visible:
for gg in graphics:
self.add_graphic(gg)
return graphics
return self.slice(*args, **kwargs)
def contourslice(self, *args, **kwargs):
"""
@ -1218,54 +1166,7 @@ class Axes3DGL(Axes3D):
:returns: Legend
"""
warnings.warn("plot_surface is deprecated", DeprecationWarning)
if len(args) <= 2:
x = args[0].dimvalue(1)
y = args[0].dimvalue(0)
x, y = np.meshgrid(x, y)
z = args[0]
args = args[1:]
else:
x = args[0]
y = args[1]
z = args[2]
args = args[3:]
if kwargs.has_key('colors'):
cn = len(kwargs['colors'])
else:
cn = None
cmap = plotutil.getcolormap(**kwargs)
if len(args) > 0:
level_arg = args[0]
if isinstance(level_arg, int):
cn = level_arg
ls = LegendManage.createLegendScheme(z.min(), z.max(), cn, cmap)
else:
if isinstance(level_arg, NDArray):
level_arg = level_arg.aslist()
ls = LegendManage.createLegendScheme(z.min(), z.max(), level_arg, cmap)
else:
if cn is None:
ls = LegendManage.createLegendScheme(z.min(), z.max(), cmap)
else:
ls = LegendManage.createLegendScheme(z.min(), z.max(), cn, cmap)
ls = ls.convertTo(ShapeTypes.POLYGON)
facecolor = kwargs.pop('facecolor', None)
face_interp = None
if not facecolor is None:
face_interp = (facecolor == 'interp')
if not face_interp:
if not facecolor in ['flat','texturemap','none']:
kwargs['facecolor'] = facecolor
plotutil.setlegendscheme(ls, **kwargs)
graphics = JOGLUtil.surface(x.asarray(), y.asarray(), z.asarray(), ls)
if face_interp:
graphics.setFaceInterp(face_interp)
visible = kwargs.pop('visible', True)
if visible:
self.add_graphic(graphics)
return graphics
return self.surf(*args, **kwargs)
def isosurface(self, *args, **kwargs):
"""
@ -1343,54 +1244,7 @@ class Axes3DGL(Axes3D):
:returns: Legend
"""
warnings.warn("plot_isosurface is deprecated", DeprecationWarning)
if len(args) <= 3:
x = args[0].dimvalue(2)
y = args[0].dimvalue(1)
z = args[0].dimvalue(0)
data = args[0]
isovalue = args[1]
args = args[2:]
else:
x = args[0]
y = args[1]
z = args[2]
data = args[3]
isovalue = args[4]
args = args[5:]
cmap = plotutil.getcolormap(**kwargs)
cvalue = kwargs.pop('cvalue', None)
if not cvalue is None:
if len(args) > 0:
level_arg = args[0]
if isinstance(level_arg, int):
cn = level_arg
ls = LegendManage.createLegendScheme(data.min(), data.max(), cn, cmap)
else:
if isinstance(level_arg, NDArray):
level_arg = level_arg.aslist()
ls = LegendManage.createLegendScheme(data.min(), data.max(), level_arg, cmap)
else:
ls = LegendManage.createLegendScheme(data.min(), data.max(), cmap)
ls = ls.convertTo(ShapeTypes.POLYGON)
edge = kwargs.pop('edge', True)
kwargs['edge'] = edge
plotutil.setlegendscheme(ls, **kwargs)
else:
ls = plotutil.getlegendbreak('polygon', **kwargs)[0]
nthread = kwargs.pop('nthread', None)
if nthread is None:
graphics = JOGLUtil.isosurface(data.asarray(), x.asarray(), y.asarray(), z.asarray(), isovalue, ls)
else:
data = data.asarray().copyIfView()
x = x.asarray().copyIfView()
y = y.asarray().copyIfView()
z = z.asarray().copyIfView()
graphics = JOGLUtil.isosurface(data, x, y, z, isovalue, ls, nthread)
visible = kwargs.pop('visible', True)
if visible:
self.add_graphic(graphics)
return graphics
return self.isosurface(*args, **kwargs)
def particles(self, *args, **kwargs):
"""
@ -1473,51 +1327,7 @@ class Axes3DGL(Axes3D):
:returns: Legend
"""
warnings.warn("plot_particles is deprecated", DeprecationWarning)
if len(args) <= 3:
x = args[0].dimvalue(2)
y = args[0].dimvalue(1)
z = args[0].dimvalue(0)
data = args[0]
args = args[1:]
else:
x = args[0]
y = args[1]
z = args[2]
data = args[3]
args = args[4:]
cmap = plotutil.getcolormap(**kwargs)
vmin = kwargs.pop('vmin', data.min())
vmax = kwargs.pop('vmax', data.max())
if vmin >= vmax:
raise ValueError("Minimum value larger than maximum value")
if len(args) > 0:
level_arg = args[0]
if isinstance(level_arg, int):
cn = level_arg
ls = LegendManage.createLegendScheme(vmin, vmax, cn, cmap)
else:
if isinstance(level_arg, NDArray):
level_arg = level_arg.aslist()
ls = LegendManage.createLegendScheme(vmin, vmax, level_arg, cmap)
else:
ls = LegendManage.createLegendScheme(vmin, vmax, cmap)
plotutil.setlegendscheme(ls, **kwargs)
alpha_min = kwargs.pop('alpha_min', 0.1)
alpha_max = kwargs.pop('alpha_max', 0.6)
density = kwargs.pop('density', 2)
graphics = JOGLUtil.particles(data.asarray(), x.asarray(), y.asarray(), z.asarray(), ls, \
alpha_min, alpha_max, density)
s = kwargs.pop('s', None)
if s is None:
s = kwargs.pop('size', None)
if not s is None:
graphics.setPointSize(s)
visible = kwargs.pop('visible', True)
if visible:
self.add_graphic(graphics)
return graphics
return self.particles(*args, **kwargs)
def volumeplot(self, *args, **kwargs):
"""

View File

@ -0,0 +1,57 @@
package org.meteoinfo.math.optimize;
import org.apache.commons.math3.analysis.ParametricUnivariateFunction;
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math3.analysis.differentiation.FiniteDifferencesDifferentiator;
import org.apache.commons.math3.analysis.differentiation.UnivariateDifferentiableFunction;
public class MyParametricUnivariateFunction implements ParametricUnivariateFunction {
private ParamUnivariateFunction function;
private int nbPoints;
private double stepSize;
/**
* Constructor
* @param function ParamUnivariateFunction
* @param nbPoints Number of points for difference calculation
* @param stepSize Step size for difference calculation
*/
public MyParametricUnivariateFunction(ParamUnivariateFunction function, int nbPoints, double stepSize) {
this.function = function;
this.nbPoints = nbPoints;
this.stepSize = stepSize;
}
@Override
public double value(double v, double... parameters) {
function.setParameters(parameters);
return function.value(v);
}
@Override
public double[] gradient(double v, double... parameters) {
function.setParameters(parameters);
// create a differentiator
FiniteDifferencesDifferentiator differentiator =
new FiniteDifferencesDifferentiator(nbPoints, stepSize);
// create a new function that computes both the value and the derivatives
// using DerivativeStructure
UnivariateDifferentiableFunction diffFunc = differentiator.differentiate(function);
double y = function.value(v);
int n = parameters.length;
double[] gradients = new double[n];
for (int i = 0; i < n; i++) {
DerivativeStructure xDS = new DerivativeStructure(n, 1, i, parameters[i]);
DerivativeStructure yDS = diffFunc.value(xDS);
int[] idx = new int[n];
idx[i] = 1;
gradients[i] = yDS.getPartialDerivative(idx);
}
return gradients;
}
}

View File

@ -1,9 +1,12 @@
package org.meteoinfo.math.optimize;
import org.apache.commons.math3.analysis.ParametricUnivariateFunction;
import org.apache.commons.math3.analysis.UnivariateFunction;
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math3.analysis.differentiation.FiniteDifferencesDifferentiator;
import org.apache.commons.math3.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math3.fitting.SimpleCurveFitter;
import org.apache.commons.math3.fitting.WeightedObservedPoints;
import org.apache.commons.math3.fitting.leastsquares.MultivariateJacobianFunction;
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.ArrayRealVector;
@ -104,4 +107,31 @@ public class OptimizeUtil {
return jacobianFunc;
}
/**
* Get curve fitting parameters.
* @param func The uni-variate function
* @param x X values
* @param y Y values
* @param nbPoints Number of points for difference calculation
* @param stepSize Step size for difference calculation
* @param guess Guess values
* @return Curve fitting parameters
*/
public static double[] curveFit(ParamUnivariateFunction func, Array x, Array y,
int nbPoints, double stepSize, double[] guess) {
ParametricUnivariateFunction function = new MyParametricUnivariateFunction(func, nbPoints, stepSize);
SimpleCurveFitter curveFitter = SimpleCurveFitter.create(function, guess);
IndexIterator xIter = x.getIndexIterator();
IndexIterator yIter = y.getIndexIterator();
WeightedObservedPoints observedPoints = new WeightedObservedPoints();
while (xIter.hasNext()){
observedPoints.add(xIter.getDoubleNext(), yIter.getDoubleNext());
}
double[] best = curveFitter.fit(observedPoints.toList());
return best;
}
}