[SciPy-Dev] [Numpy]: making np.gradient support unevenly spaced data

josef.pktd at gmail.com josef.pktd at gmail.com
Mon Jan 23 14:54:59 EST 2017


On Mon, Jan 23, 2017 at 1:56 PM, alebarde at gmail.com <alebarde at gmail.com>
wrote:

>
>
> 2017-01-20 16:20 GMT+01:00 <josef.pktd at gmail.com>:
>
>>
>>
>> On Fri, Jan 20, 2017 at 9:09 AM, alebarde at gmail.com <alebarde at gmail.com>
>> wrote:
>>
>>> 2017-01-20 14:44 GMT+01:00 <josef.pktd at gmail.com>:
>>>
>>>>
>>>>
>>>> On Fri, Jan 20, 2017 at 5:21 AM, alebarde at gmail.com <alebarde at gmail.com
>>>> > wrote:
>>>>
>>>>> Hi all,
>>>>>
>>>>> current version of numpy gradient supports only data with uniform
>>>>> spacing. I have implemented a proposed enhancement for the np.gradient
>>>>> function that allows to compute the gradient on non uniform grids. (PR:
>>>>> https://github.com/numpy/numpy/pull/8446)
>>>>> Since it may be of interest also for the scipy user/developers and it
>>>>> may be useful also for scipy.diff
>>>>> <https://github.com/scipy/scipy/wiki/Proposal:-add-finite-difference-numerical-derivatives-as-scipy.diff>
>>>>> I am posting here too.
>>>>>
>>>>> The proposed implementation has a behaviour/signature is similar to
>>>>> that of Matlab/Octave. As argument it can take:
>>>>> 1. A single scalar to specify a sample distance for all dimensions.
>>>>> 2. N scalars to specify a constant sample distance for each dimension.
>>>>>    i.e. `dx`, `dy`, `dz`, ...
>>>>> 3. N arrays to specify the coordinates of the values along each
>>>>>    dimension of F. The length of the array must match the size of
>>>>>    the corresponding dimension
>>>>> 4. Any combination of N scalars/arrays with the meaning of 2. and 3.
>>>>>
>>>>> e.g., you can do the following:
>>>>>
>>>>>     >>> f = np.array([[1, 2, 6], [3, 4, 5]], dtype=np.float)
>>>>>     >>> dx = 2.
>>>>>     >>> y = [1., 1.5, 3.5]
>>>>>     >>> np.gradient(f, dx, y)
>>>>>     [array([[ 1. ,  1. , -0.5], [ 1. ,  1. , -0.5]]),
>>>>>      array([[ 2. ,  2. ,  2. ], [ 2. ,  1.7,  0.5]])]
>>>>>
>>>>> It should not break any existing code since as of 1.12 only scalars or
>>>>> list of scalars are allowed.
>>>>> A possible alternative API could be pass arrays of sampling steps
>>>>> instead of the coordinates.
>>>>> On the one hand, this would have the advantage of having "differences"
>>>>> both in the scalar case and in the array case.
>>>>> On the other hand, if you are dealing with non uniformly-spaced data
>>>>> (e.g, data is mapped on a grid or it is a time-series), in most cases you
>>>>> already have the coordinates/timestamps. Therefore, in the case of
>>>>> difference as argument, you would almost always have a call np.diff before
>>>>> np.gradient.
>>>>>
>>>>> In the end, I would rather prefer the coordinates option since IMHO it
>>>>> is more handy, I don't think that would be too much "surprising" and it is
>>>>> what Matlab already does. Also, it could not easily lead to "silly"
>>>>> mistakes since the length have to match the size of the corresponding
>>>>> dimension.
>>>>>
>>>>> What do you think?
>>>>>
>>>>
>>>> In general I also like specifying x better than dx.
>>>>
>>>> I looked at np.gradient two days ago to see if it does what I need. But
>>>> it was missing the unequal spacing, and it is missing the second derivative.
>>>>
>>>
>>> Yes, and I believe it is quite a useful feature. that's why I have
>>> implemented it. On the other hand I don't think that `gradient` should also
>>> be able to compute the second or kth derivative. In that case a more
>>> general function called `differentiate` would probably be better.
>>>
>>>
>>>>
>>>> more general question: I found the dimension story with dx, dy, dz, ...
>>>> confusing. Isn't this just applying gradient with respect to each axis
>>>> separately?
>>>>
>>>
>>> Yes it is just a way to pass the sampling step in each direction (and
>>> actually they are not keywords). I have kept the original documentation on
>>> this but it is probably better to change into h1,h2,h3.
>>>
>>>
>>>>
>>>>
>>>> (aside: If I read your link in the PR http://websrv.cs.umt.edu/isis/
>>>> index.php/Finite_differencing:_Introduction correctly, then I might
>>>> have just implemented a rescaled version of second (kth) order differencing
>>>> with unequal spaced x using sparse linear algebra. I didn't see anything
>>>> premade in numpy or scipy for it.)
>>>>
>>>
>>> what do you mean with "rescaled version"? and you meant second order or
>>> second derivative? in the first case I think that would be equivalent to
>>> what my PR does. In the latter, I confirm that there is currently no
>>> implementation of a second derivative.
>>>
>>
>> I think it's k-th derivative. Rescaled means that I don't actually
>> compute the derivative, I want to get a nonparametric estimate of the
>> residual which assumes, I think, that the underlying function for the
>> non-noise version has approximately constant k-th derivative (e.g. k-th
>> order polynomial, or (k+1)-th).
>> The sum of squared window coefficients is normalized to 1.
>> I didn't try to understand the math, but the kernels or windows in the
>> equal spaced case are
>>
>> >>> _diff_kernel(0)
>> array([ 1.])
>> >>> _diff_kernel(1)
>> array([ 0.70710678, -0.70710678])
>> >>> _diff_kernel(2)
>> array([ 0.40824829, -0.81649658,  0.40824829])
>> >>> _diff_kernel(2) / _diff_kernel(2)[1]
>> array([-0.5,  1. , -0.5])
>>
>> >>> _diff_kernel(3)
>> array([ 0.2236068 , -0.67082039,  0.67082039, -0.2236068 ])
>> >>> _diff_kernel(4)
>> array([ 0.11952286, -0.47809144,  0.71713717, -0.47809144,  0.11952286])
>> >>> (_diff_kernel(4)**2).sum()
>> 0.99999999999999989
>>
>> Yes, if I am not wrong you are getting the coefficient of the 1st order
> k-th derivative of the forward/backard approximation (
> https://en.wikipedia.org/wiki/Finite_difference_coefficient#Forward_and_
> backward_finite_difference)
> Fornberg (http://www.ams.org/journals/mcom/1988-51-184/S0025-5718-
> 1988-0935077-0/S0025-5718-1988-0935077-0.pdf) proposed an algorithm to
> get the coefficients for a general N-order K-th derivative but I don't know
> how efficient it is.
>

Thanks for the links.

My underlying story ended up being close to savitzky-golay

e.g. central differences with increasing accuracy

>>> signal.savgol_coeffs(3, 2, deriv=1)
array([  5.00000000e-01,  -4.53646149e-17,  -5.00000000e-01])

>>> signal.savgol_coeffs(5, 4, deriv=1)
array([ -8.33333333e-02,   6.66666667e-01,   1.31151738e-15,
        -6.66666667e-01,   8.33333333e-02])

In the simple differencing appoach window length is tied to the number of
derivatives/differencing. But with local polynomials like savitzky-golay
the window length (and order of approximation) can be separated from the
derivative order.

This works with equal spaced points, but I gave up for now going beyond
simple differencing for unequal spaced points, because I don't see a fast
way to create the windows for general local polynomial regression.

(In case anyone is interested:
https://github.com/statsmodels/statsmodels/pull/3380 where it took me a
while to figure out the relationship to savitzky-golay)



> Also, I am not sure if it applies to your case but mind that when going to
> higher order strange effects happens unless "nodes" are properly chosen see
> e.g., figures last page of (https://www.rsmas.miami.edu/
> users/miskandarani/Courses/MSC321/lectfiniteDifference.pdf)
>

In my experience this is more of a problem for interpolation than for lower
order smoothing, but it's not ruled out. It should be even less of a
problem with local, usually low order polynomials as in savitzky-golay.

Josef



> --
> --------------------------------------------------------------------------
> NOTICE: Dlgs 196/2003 this e-mail and any attachments thereto may contain
> confidential information and are intended for the sole use of the
> recipient(s) named above. If you are not the intended recipient of this
> message you are hereby notified that any dissemination or copying of this
> message is strictly prohibited. If you have received this e-mail in error,
> please notify the sender either by telephone or by e-mail and delete the
> material from any computer. Thank you.
> --------------------------------------------------------------------------
>
> _______________________________________________
> SciPy-Dev mailing list
> SciPy-Dev at scipy.org
> https://mail.scipy.org/mailman/listinfo/scipy-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/scipy-dev/attachments/20170123/f21406cf/attachment.html>


More information about the SciPy-Dev mailing list