5

I'm trying to implement the following formula in python for X and Y points

enter image description here

I have tried following approach

def f(c):
    """This function computes the curvature of the leaf."""
    tt = c
    n = (tt[0]*tt[3] - tt[1]*tt[2])
    d = (tt[0]**2 + tt[1]**2)
    k = n/d
    R = 1/k # Radius of Curvature
    return R

There is something incorrect as it is not giving me correct result. I think I'm making some mistake while computing derivatives in first two lines. How can I fix that?

Here are some of the points which are in a data frame:

pts = pd.DataFrame({'x': x, 'y': y})


           x            y
    0.089631    97.710199
    0.089831    97.904541
    0.090030    98.099313
    0.090229    98.294513
    0.090428    98.490142
    0.090627    98.686200
    0.090827    98.882687
    0.091026    99.079602
    0.091225    99.276947
    0.091424    99.474720
    0.091623    99.672922
    0.091822    99.871553
    0.092022    100.070613
    0.092221    100.270102
    0.092420    100.470020
    0.092619    100.670366
    0.092818    100.871142
    0.093017    101.072346
    0.093217    101.273979
    0.093416    101.476041
    0.093615    101.678532
    0.093814    101.881451
    0.094013    102.084800
    0.094213    102.288577


pts_x = np.gradient(x_c, t)  # first derivatives
pts_y = np.gradient(y_c, t)
pts_xx = np.gradient(pts_x, t)  # second derivatives
pts_yy = np.gradient(pts_y, t)

After getting the derivatives I am putting the derivatives x_prim, x_prim_prim, y_prim, y_prim_prim in another dataframe using the following code:

d = pd.DataFrame({'x_prim': pts_x, 'y_prim': pts_y, 'x_prim_prim': pts_xx, 'y_prim_prim':pts_yy})

after having everything in the data frame I am calling function for each row of the data frame to get curvature at that point using following code:

# Getting the curvature at each point
for i in range(len(d)):
    temp = d.iloc[i]
    c_temp = f(temp)
    curv.append(c_temp)
Upriser
  • 418
  • 2
  • 7
  • 23
  • Did you try looking at what you get for pts_x, pts_y, pts_xx and pts_yy and see whether those are being calculated approximately correctly? Also, I don't see anything corresponding to the notion of "absolute value" here... your n could turn out negative. – Patrick87 Apr 16 '19 at 17:12
  • @Patrick87 I just checked that that is somewhere it is getting fuzzy. If I compute all the derivatives separately then it should solve the problem. Let me try that. – Upriser Apr 16 '19 at 17:14
  • Do those primes mean "derivative" to you? – duffymo Apr 16 '19 at 17:14
  • The root of the sum of squares is positive-definite, so no concerns about complex values here. – duffymo Apr 16 '19 at 17:15
  • @duffymo yes. pts_x is first derivative and pts_xx is second derivative. – Upriser Apr 16 '19 at 17:15
  • Is there a summation in here somewhere? Either you've left off a summation to give you a constant value k OR k is really a function. Which is it? What are you expecting? Are you supposed to be multiplying values at a point? Or is that a dot product of two vectors that evaluates to a scalar? You need to understand the formula before you can code it. I can't say that I do from what you've posted. – duffymo Apr 16 '19 at 17:21
  • @duffymo It is formula for the curvature that I found on https://www.math24.net/curvature-plane-curves/ link in the section for getting the curvature when the coordinates x(t) and y(t) of a curve are given parametrically. – Upriser Apr 16 '19 at 17:24
  • The curvature varies at every point. The key bit from the np.gradient documentation: "The returned gradient hence has the same shape as the input array." Those are arrays. When you multiply one array by another, what do you expect to get? – duffymo Apr 16 '19 at 17:30
  • I need to get |k| which is shown on the blog for which I shared link with you. – Upriser Apr 16 '19 at 17:31
  • Got it here: https://en.wikipedia.org/wiki/Curvature. It's the curvature of a curve defined by two vectors of points x and y. I'd assume that x is in sorted order. There is a different value of k at each point x of the curve. I'd recommend that you reconsider your programming. It's not correct. – duffymo Apr 16 '19 at 17:33
  • @duffymo Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/191933/discussion-between-upriser-and-duffymo). – Upriser Apr 16 '19 at 17:35
  • No chat for me. Sorry. – duffymo Apr 16 '19 at 17:38
  • @duffymo I'll update you when I implement this. – Upriser Apr 16 '19 at 17:39
  • Please *always* use the generic [python] tag for all python related questions. Only use a version specific tag if you think it's important. – juanpa.arrivillaga Apr 16 '19 at 18:07
  • As I wrote in another comment, please show how you call your function, especially showing the value of the `pts` array. Without that, we are just guessing about your problem. – Rory Daulton Apr 16 '19 at 19:15
  • Your edit is not sufficient to clarify just what `pts` is. Are the numbers in the first column starting with `450` part of the `pts` array? Is it an array or a dataset? If an array, what is its shape? And so on--the details matter for a problem like this. Please read and follow [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – Rory Daulton Apr 16 '19 at 20:44
  • @RoryDaulton the numbers from the 450 in the first column are just indices. I'll edit my question sorry for that. – Upriser Apr 16 '19 at 20:46
  • Doesn't your data allow for the simplified formula in case of the [curvature of the graph of a function](https://en.wikipedia.org/wiki/Curvature#Curvature_of_the_graph_of_a_function)? You might also think about using `scipy.interpolate.splev` as this provides the possibility to get derivatives. In any case it does not make sense to get the curvature on edge points...or it is at least questionable. – mikuszefski Apr 17 '19 at 07:22

2 Answers2

3

You do not specify exactly what the structure of the parameter pts is. But it seems that it is a two-dimensional array where each row has two values x and y and the rows are the points in your curve. That itself is problematic, since the documentation is not quite clear on what exactly is returned in such a case.

But you clearly are not getting the derivatives of x or y. If you supply only one array to np.gradient then numpy assumes that the points are evenly spaced with a distance of one. But that is probably not the case. The meaning of x' in your formula is the derivative of x with respect to t, the parameter variable for the curve (which is separate from the parameters to the computer functions). But you never supply the values of t to numpy. The values of t must be the second parameter passed to the gradient function.

So to get your derivatives, split the x, y, and t values into separate one-dimensional arrays--lets call them x and y and t. Then get your first and second derivatives with

pts_x = np.gradient(x, t)  # first derivatives
pts_y = np.gradient(y, t)
pts_xx = np.gradient(pts_x, t)  # second derivatives
pts_yy = np.gradient(pts_y, t)

Then continue from there. You no longer need the t values to calculate the curvatures, which is the point of the formula you are using. Note that gradient is not really designed to calculate the second derivatives, and it absolutely should not be used to calculate third or higher-order derivatives. More complex formulas are needed for those. Numpy's gradient uses "second order accurate central differences" which are pretty good for the first derivative, poor for the second derivative, and worthless for higher-order derivatives.

Rory Daulton
  • 21,934
  • 6
  • 42
  • 50
  • Is it possible for you to give example what t array would look like. x and y arrays that I have are floating point values. – Upriser Apr 16 '19 at 18:38
  • I'm busy right now but will try to respond later. It would help if you show an example of your `pts` data--that would make your code snippet more complete, according to [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – Rory Daulton Apr 16 '19 at 18:43
  • @RonyDaulton Hello Rony, should I consider x = t in my case or it is different. – Upriser Apr 22 '19 at 16:14
  • @Upriser: I do not mean to be rude, but I will not do any more work on your question or my answer until you actually [create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). What *exactly* is `pts`? Showing a text representation is not enough--show its data structure in Python in executable code. A reduced version is fine if it shows your problem. And just how is your code "not giving me correct result"? What do you get, what do you expect, and how are they different? – Rory Daulton Apr 22 '19 at 16:47
  • @RonyDaulton I added the approach that I tried, and this is pretty much everything I have. I hope this works. – Upriser Apr 22 '19 at 17:11
0

I think your problem is that x and y are arrays of double values.

The array x is the independent variable; I'd expect it to be sorted into ascending order. If I evaluate y[i], I expect to get the value of the curve at x[i].

When you call that numpy function you get an array of derivative values that are the same shape as the (x, y) arrays. If there are n pairs from (x, y), then

y'[i] gives the value of the first derivative of y w.r.t. x at x[i]; 

y''[i] gives the value of the second derivative of y w.r.t. x at x[i].

The curvature k will also be an array with n points:

k[i] = abs(x'[i]*y''[i] -y'[i]*x''[i])/(x'[i]**2 + y'[i]**2)**1.5

Think of x and y as both being functions of a parameter t. x' = dx/dt, etc. This means curvature k is also a function of that parameter t.

I like to have a well understood closed form solution available when I program a solution.

y(x) = sin(x) for 0 <= x <= pi
y'(x) = cos(x)
y''(x) = -sin(x)
k = sin(x)/(1+(cos(x))**2)**1.5

Now you have a nice formula for curvature as a function of x.

If you want to parameterize it, use

x(t) = pi*t for 0 <= t <= 1
x'(t) = pi
x''(t) = 0

See if you can plot those and make your Python solution match it.

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • Is this implementation same as you suggested from the wiki blog. – Upriser Apr 16 '19 at 17:50
  • I'm suggesting that the wiki entry is describing your problem. Try my idea about implementation and see if your results make more sense. Do it for a curve that you know the answer to, like y = sin(x) for 0 <= x <= pi. You can evaluate that analytically and check your programming solution against it. – duffymo Apr 16 '19 at 17:51
  • I tried for the sin curve but this approach is not giving correct result. I need to go by different approach probably the wiki blog approach as the blog that I found math24.net/curvature-plane-curves I think it is misleading or it is not what I'm looking for. – Upriser Apr 16 '19 at 17:57
  • No. You need to understand the problem. My source and yours are describing the same problem. I don't know what "tried" looks like; I don't know what result you got or expected. I don't think you understand your problem. – duffymo Apr 16 '19 at 18:01
  • I mean I tried to get the curvature of the sine curve but it is not giving the correct answer I referred another blog which was doing simulation for the curvature of the sine curve and the values are not matching I generated the sine curve with the same parameter as described in blog. I think the dx/dy that I'm taking is making something wierd I need to check documentation again if it is giving dy/dx or dx/dy the order of the parameters x and y. – Upriser Apr 16 '19 at 18:12
  • The code that you suggested is working. I just tried it. In my code I forgot to consider pi (it's a silly mistake that I made.) – Upriser Apr 16 '19 at 19:51