numpy: Different results between diff and gradient for finite differences - numpy

I want to calculate the numerical derivative of two arrays a and b.
If I do
c = diff(a) / diff(b)
I get what I want, but I loose the edge (the last point) so c.shape ~= a.shape.
If I do
c = gradient(a, b)
then c.shape = a.shape, but I get a completely different result.
I have read how gradient is calculated in numpy and I guess it does a completely different thing, although I dont understand quite well the difference yet. But is there a way or another function to calculate the differential which also gives the values at the edges?
And why is the result so different between gradient and diff?

These functions, although related, do different actions.
np.diff simply takes the differences of matrix slices along a given axis, and used for n-th difference returns a matrix smaller by n along the given axis (what you observed in the n=1 case). Please see: https://docs.scipy.org/doc/numpy/reference/generated/numpy.diff.html
np.gradient produces a set of gradients of an array along all its dimensions while preserving its shape https://docs.scipy.org/doc/numpy/reference/generated/numpy.gradient.html Please also observe that np.gradient should be executed for one input array, your second argument b does not make sense here (was interpreted as first non-keyword argument from *varargs which is meant to describe spacings between the values of the first argument), hence the results that don't match your intuition.
I would simply use c = diff(a) / diff(b) and append values to c if you really need to have c.shape match a.shape. For instance, you might append zeros if you expect the gradient to vanish close to the edges of your window.

Related

Mapping a numerical function with two inputs onto one with one input

I‘m quite bad at programming, so please bear with me. I‘m not even sure what the concept I need right now is called, so i don’t know what to google for or write in the title of this post.
My issue is, I numerically integrated a function on Mathematica and have a function F that depends on 2 inputs X and Y. Those inputs form a 2x2 grid. To visualize my solution, I would need a 3D graph.
Now I want to compare this to my analytical solution (/approximation) A, which I know only depends on one input Z, which is the ratio of X/Y. To visualize it, I only need a 2d Graph.
My issue now is, that I‘m not sure how to effectively filter that part of my numerical solution F so that I only consider the outputs with various ratios X/Y. This way, I could easily compare it to my analytical solution by only using a 2d graph.
I hope some of you understand my gibberish. I apologize for not being able to properly explain what I need in the correct language. I would be glad if some of you might be able to help me. Any help is appreciated.
Is my understanding correct? You have a numerically integrated function, F which maps a pair of numbers to a scalar:
F: (x,y) -> (z)
Then, there's another function, A, which takes a scalar and maps it to another scalar:
A: (b) -> (c)
and b is itself the ratio of x and y from before:
b = x/y
And you'd like to compare the outputs of F and A, i.e. compare z to c, as I've defined them here?
One thing you can do is sample the inputs to F that you already have, and then query A with the ratio of those inputs, and compare the output.
To put it another way, you can say, "for this x and this y, I know the output of F is this. Then, when I divide them and put them into A I get this."
Then, you could make a heatmap, say, where one of the axes is the x-value and the other axis is the y-value, and the color corresponds to F(x, y) - A(x/y)

How to specify the number of knot points when using scipy.splprep

I have the following piece of code. It generates the 3-D cubic spline of the given 3-D function given in parametric form. I pretty much adapted this to my case using the online documentation for splprep and splev.
But I have some things I don't understand. Here is the code:
%matplotlib inline
from numpy import arange, cos, linspace, pi, sin, random
from scipy.interpolate import splprep, splev
import matplotlib.pyplot as plt
# make ascending spiral in 3-space
t=linspace(0,1.75*2*pi,100)
x = sin(t)
y = cos(t)
z = t
# spline parameters
s=3.0 # smoothness parameter
k=3 # spline order
nest=-1 # estimate of number of knots needed (-1 = maximal)
# find the knot points
tck,u = splprep([x,y,z],s=s,k=k,nest=-1)
# evaluate spline, including interpolated points
xnew,ynew,znew = splev(linspace(0,1,400),tck)
I have a few questions regarding this implementation.
What exactly does the (t,c,k) tuple return in this case?. I read the documentation and it says it returns the knot points, the coefficients and the degree of the spline. Doesn't knot points have to be coordinates of the form (x, y, z)?. So we have to have "number of knots" such coordinate points. But that's not what gets returned. We simply get returned an array of length 11.
What does u return? (Documentation says it returns the values of the parameter. What does that mean?. The values of the parameter t?
When I use nest = -1 (This is the default) it uses the maximal number of knot points needed (in this case they use 11 knot points). But how do I specify my own number of knot points, let's say 50 or 80 etc?
I am completely misunderstanding the documentation here. Can someone enlighten me may be using examples?
Values of parameter, u
The idea is that your points [x,y,z] are values of some parameterized curve, the original parameter being t in your example. Knowing the values of the parameter t helps in figuring out how to interpolate between these points. For this reason, you are given an option to pass the values of parameter as optional argument u (it would be u=t in this example). But if you choose not to do so, the method will make a guess for the values of the parameter, based on the distances between given points (the parameter interval will be from 0 to 1). This guess is then returned to you as variable u, so you know how the data was interpreted. If you do pass u=t as the argument, the u you get back is exactly the same.
You don't really need this u to use the spline. However, if it is desirable to compare the location of original [x,y,z] points to the values of the spline, then you may want to pass u as an argument to splev. A shorter way to explain the meaning of u is: it's what splev would need to reproduce the [x,y,z] coordinates that you started with, with some deviations due to smoothing.
tck values
The knots of a spline, t, are the points in the parameter interval, not in the 3D space. Since in your example the parameter interval is [0,1], chosen by default, the values of t are in this range. A knot is a place on the parameter interval where some coefficients of the spline change. The endpoints 0 and 1 are technically multiple knots, so they are listed several times.
The 3D nature of the curve is expressed by coefficients c. You may notice it's a list of three arrays, one for each coordinate.
Number of knot points
With this interpolation routine, you have two choices:
tell it exactly what the knot points are (by giving task=-1 and providing t argument with the knots). To avoid confusion: this t is not necessarily the t from which you got the points [x,y,z]. One doesn't necessarily want every sample point to be a knot point.
leave the determination of the knots up to the routine, including their number.
However, the number of knots depends on the value of smoothness parameter s, so it can be influenced indirectly. For example, with your data there are 11 knots with s=3, but 12 knots with s=1 and 14 knots with s=0.1.

Differences between X.ravel() and X.reshape(s0*s1*s2) when number of axes known

Seeing this answer I am wondering if the creation of a flattened view of X are essentially the same, as long as I know that the number of axes in X is 3:
A = X.ravel()
s0, s1, s2 = X.shape
B = X.reshape(s0*s1*s2)
C = X.reshape(-1) # thanks to #hpaulj below
I'm not asking if A and B and C are the same.
I'm wondering if the particular use of ravel and reshape in this situation are essentially the same, or if there are significant differences, advantages, or disadvantages to one or the other, provided that you know the number of axes of X ahead of time.
The second method takes a few microseconds, but that does not seem to be size dependent.
Look at their __array_interface__ and do some timings. The only difference that I can see is that ravel is faster.
.flatten() has a more significant difference - it returns a copy.
A.reshape(-1)
is a simpler way to use reshape.
You could study the respective docs, and see if there is something else. I haven't explored what happens when you specify order.
I would use ravel if I just want it to be 1d. I use .reshape most often to change a 1d (e.g. arange()) to nd.
e.g.
np.arange(10).reshape(2,5).ravel()
Or choose the one that makes your code most readable.
reshape and ravel are defined in numpy C code:
In https://github.com/numpy/numpy/blob/0703f55f4db7a87c5a9e02d5165309994b9b13fd/numpy/core/src/multiarray/shape.c
PyArray_Ravel(PyArrayObject *arr, NPY_ORDER order) requires nearly 100 lines of C code. And it punts to PyArray_Flatten if the order changes.
In the same file, reshape punts to newshape. That in turn returns a view is the shape doesn't actually change, tries _attempt_nocopy_reshape, and as last resort returns a PyArray_NewCopy.
Both make use of PyArray_Newshape and PyArray_NewFromDescr - depending on how shapes and order mix and match.
So identifying where reshape (to 1d) and ravel are different would require careful study.
Another way to do this ravel is to make a new array, with a new shape, but the same data buffer:
np.ndarray((24,),buffer=A.data)
It times the same as reshape. Its __array_interface__ is the same. I don't recommend using this method, but it may clarify what is going on with these reshape/ravel functions. They all make a new array, with new shape, but with share data (if possible). Timing differences are the result of different sequences of function calls - in Python and C - not in different handling of the data.

Fitting curves to a set of points

Basically, I have a set of up to 100 co-ordinates, along with the desired tangents to the curve at the first and last point.
I have looked into various methods of curve-fitting, by which I mean an algorithm with takes the inputted data points and tangents, and outputs the equation of the cure, such as the gaussian method and interpolation, but I really struggled understanding them.
I am not asking for code (If you choose to give it, thats acceptable though :) ), I am simply looking for help into this algorithm. It will eventually be converted to Objective-C for an iPhone app, if that changes anything..
EDIT:
I know the order of all of the points. They are not too close together, so passing through all points is necessary - aka interpolation (unless anyone can suggest something else). And as far as I know, an algebraic curve is what I'm looking for. This is all being done on a 2D plane by the way
I'd recommend to consider cubic splines. There is some explanation and code to calculate them in plain C in Numerical Recipes book (chapter 3.3)
Most interpolation methods originally work with functions: given a set of x and y values, they compute a function which computes a y value for every x value, meeting the specified constraints. As a function can only ever compute a single y value for every x value, such an curve cannot loop back on itself.
To turn this into a real 2D setup, you want two functions which compute x resp. y values based on some parameter that is conventionally called t. So the first step is computing t values for your input data. You can usually get a good approximation by summing over euclidean distances: think about a polyline connecting all your points with straight segments. Then the parameter would be the distance along this line for every input pair.
So now you have two interpolation problem: one to compute x from t and the other y from t. You can formulate this as a spline interpolation, e.g. using cubic splines. That gives you a large system of linear equations which you can solve iteratively up to the desired precision.
The result of a spline interpolation will be a piecewise description of a suitable curve. If you wanted a single equation, then a lagrange interpolation would fit that bill, but the result might have odd twists and turns for many sets of input data.

What's the meaning of the partial derivatives of B-spline as given by scipy.interpolate.bisplev?

I have a mesh generated from cloudpoint, which could be described as z = f(x,y), so I'm using scipy.interpolate.bisplrep and bisplev, with good results.
bisplev can be used with parameters dx=n and/or dy=n so that the results are derivatives of order n at the evaluated points. I plan to use this to calculate mean and gaussian curvatures (called surfature in Matlab), and that should involve getting the second-order partial derivatives of the survace
The results using one of the partial derivatives at a time, say dx are great, clearly representing the gradient as a "shading" effect, as seen in this image from a human back (code first):
self.spline = inter.bisplrep(self.pointlist[:,1],
self.pointlist[:,0],
self.pointlist[:,2], s=smoothing_factor)
self.mesh_shadow = inter.bisplev(yy.flat, xx.flat, self.spline, dy=1)
So far, so good. The problem is: I can't understand (and can't find any explanation) what's the meaning of the result when I ask for both partial derivatives at the same time, since there isn't any obvious numeric or visual meaning. For example, if I use dx AND dy:
self.mesh_shadow = inter.bisplev(yy.flat, xx.flat, self.spline, dx=1, dy=1)
I get this:
So, I wonder:
What's the mathematical/geometrical meaning of the simultaneous result of first-order partial derivatives of a surface as given by bislplev(..., dx=1, dy=1), if any?
Would there be a way to get the maximum slope (in any direction) from bislplev(..., dx=1, dy=1)?
Are both partial derivatives supposed to be called together, in the first place? I see I can use, say, (..., dx=1, dy=2) and the function seems to produce "valid" results, but would that make any sense?
Every time, the returned value is a (Y,X)-shaped array of single float values (Z or one of its derivative-related values).
Any help?
Thanks for reading
The partial derivative you get with dx=n, dy=m is the mathematical object (or rather, its numerical approximation)
(d/dx)^n (d/dy)^m f(x,y)
You cannot compute the Gaussian curvature just from dx=2,dy=0 and dx=0,dy=2 --- you in general also need also the cross-derivative dx=1,dy=1.
Partial derivatives (d/dx)^n (d/dy)^m f(x,y) are mathematically well-defined. With splines, if you go to too high orders, you should start getting zeros or discontinuities.