-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
ENH, WIP: Add 2-D fitting function for polynomials #14151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
c927096
b7d303e
fcb83ce
9808bf2
99986c5
5267b0d
bd4489e
b09ef70
f9b403c
652cad2
1ea7e7f
b1e0fdb
13674f0
7491559
c4069f6
4cd2c03
2a20790
6250ff8
b79bdd1
eb23787
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1663,6 +1663,129 @@ def chebfit(x, y, deg, rcond=None, full=False, w=None): | |
return pu._fit(chebvander, x, y, deg, rcond, full, w) | ||
|
||
|
||
def chebfit2d(x, y, z, deg, rcond=None, full=False, w=None, max_degree=None): | ||
""" | ||
2d Least squares fit of Chebyshev series to data. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if we should construct this docstring from a template, it irritates me to see such a large docstring for such a small function body. |
||
|
||
Return the coefficients of a Chebyshev series of degree `deg` that is the | ||
least squares fit to the data values `y` given at points `x`. | ||
AWehrhahn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
The fitted polynomial(s) are in the form | ||
|
||
.. math:: p(x, y) = c_00 + c_10 * T_10(x, y) + ... + c_nm * T_nm(x, y), | ||
eric-wieser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
where `n` and `m` are `deg`. | ||
eric-wieser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Parameters | ||
---------- | ||
x : array_like, shape (M,) | ||
x-coordinates of the M sample points ``(x[i], y[i], z[i])``. | ||
y : array_like, shape (M,) | ||
y-coordinates of the M sample points ''(x[i], y[i], z[i])``. | ||
z : array_like, shape (M,) | ||
z-coordinates of the sample points. | ||
deg : int or 1-D array_like | ||
Degree(s) of the fitting polynomials. If `deg` is a single integer | ||
all terms up to and including the `deg`'th term are included in the | ||
fit. Otherwise the first element is the degree in `x` direction | ||
and the second in `y` direction. | ||
rcond : float, optional | ||
Relative condition number of the fit. Singular values smaller than | ||
this relative to the largest singular value will be ignored. The | ||
default value is len(x)*eps, where eps is the relative precision of | ||
the float type, about 2e-16 in most cases. | ||
full : bool, optional | ||
Switch determining nature of return value. When it is False (the | ||
default) just the coefficients are returned, when True diagnostic | ||
information from the singular value decomposition is also returned. | ||
w : array_like, shape (`M`,), optional | ||
Weights. If not None, the contribution of each point | ||
``(x[i],y[i])`` to the fit is weighted by `w[i]`. Ideally the | ||
weights are chosen so that the errors of the products ``w[i]*y[i]`` | ||
all have the same variance. The default value is None. | ||
|
||
.. versionadded:: 1.5.0 | ||
AWehrhahn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
max_degree : int, optional | ||
If given the maximum combined degree of the coefficients is limited | ||
to this value, i.e. all terms with `n` + `m` > max_degree are set to 0. | ||
The default is None. | ||
|
||
Returns | ||
------- | ||
coef : ndarray, shape (`deg` + 1, `deg` + 1) | ||
Polynomial coefficients ordered from low to high. | ||
With coefficients in `x` direction along the first | ||
dimension and in `y` direction along the second dimension. | ||
|
||
[residuals, rank, singular_values, rcond] : list | ||
These values are only returned if `full` = True | ||
|
||
resid -- sum of squared residuals of the least squares fit | ||
rank -- the numerical rank of the scaled Vandermonde matrix | ||
sv -- singular values of the scaled Vandermonde matrix | ||
rcond -- value of `rcond`. | ||
|
||
For more details, see `linalg.lstsq`. | ||
|
||
Warns | ||
----- | ||
RankWarning | ||
The rank of the coefficient matrix in the least-squares fit is | ||
deficient. The warning is only raised if `full` = False. The | ||
warnings can be turned off by | ||
|
||
>>> import warnings | ||
>>> warnings.simplefilter('ignore', np.RankWarning) | ||
|
||
See Also | ||
-------- | ||
polyfit, legfit, lagfit, hermfit, hermefit | ||
chebval : Evaluates a Chebyshev series. | ||
chebvander : Vandermonde matrix of Chebyshev series. | ||
chebweight : Chebyshev weight function. | ||
linalg.lstsq : Computes a least-squares fit from the matrix. | ||
scipy.interpolate.UnivariateSpline : Computes spline fits. | ||
|
||
Notes | ||
----- | ||
The solution is the coefficients of the Chebyshev series `p` that | ||
minimizes the sum of the weighted squared errors | ||
|
||
.. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2, | ||
|
||
where :math:`w_j` are the weights. This problem is solved by setting up | ||
as the (typically) overdetermined matrix equation | ||
|
||
.. math:: V(x) * c = w * y, | ||
|
||
where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the | ||
coefficients to be solved for, `w` are the weights, and `y` are the | ||
observed values. This equation is then solved using the singular value | ||
decomposition of `V`. | ||
|
||
If some of the singular values of `V` are so small that they are | ||
neglected, then a `RankWarning` will be issued. This means that the | ||
coefficient values may be poorly determined. Using a lower order fit | ||
will usually get rid of the warning. The `rcond` parameter can also be | ||
set to a value smaller than its default, but the resulting fit may be | ||
spurious and have large contributions from roundoff error. | ||
|
||
Fits using Chebyshev series are usually better conditioned than fits | ||
using power series, but much can depend on the distribution of the | ||
sample points and the smoothness of the data. If the quality of the fit | ||
is inadequate splines may be a good alternative. | ||
|
||
References | ||
---------- | ||
.. [1] Wikipedia, "Curve fitting", | ||
https://en.wikipedia.org/wiki/Curve_fitting | ||
|
||
Examples | ||
-------- | ||
|
||
""" | ||
return pu._fit2d(chebvander2d, x, y, z, deg, rcond, full, w, max_degree, False) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tempting to pass There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean that is exactly what chebvander2d is doing. No need to repeat that here I think. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason I suggest this is that you if you passed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about:
I.e. allow both? |
||
|
||
|
||
def chebcompanion(c): | ||
"""Return the scaled companion matrix of c. | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason not to immediately go to nd?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function call is slightly different. The 2d version has seperate paramaters for each dimension x and y. While the nd version only has 1 parameter (x, y) with all coordinates in a tuple.
The 2d version is more consistent with the existing functions for e.g polyval2d.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I'd argue that in hindsight the 2d functions were a mistake - we should have gone straight from 1d to nd, rather than blowing up our API with intermediate integers.
Since what you're adding is a new API, what I'm arguing is that we should learn from our mistake, and go straight to writing the nd function (and the slight argument difference this entails).
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you feel strongly about the calling convention, you could use instead:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no particular attachement to the calling convention
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not deprecating all the XXX2d and XXX3d functions (like chebfit2d, chebfit3d, chebval2d, chebval3d, chebgrid2d, chebgrid3d, chebvander2d, chebvander3d, etc.) since they all are obsolete once you have the XXXnd functions (like chebfitnd, chebvalnd, chebgridnd, chebvandernd, ...)?