0
votes

I'm having trouble using the scipy interpolation methods to generate a nice smooth curve from the data points given. I've tried using the standard 1D interpolation, the Rbf interpolation with all options (cubic, gaussian, multiquadric etc.)

in the image provided, the blue line is the original data, and I'm looking to first smooth the sharp edges, and then have dynamically editable points from which to recalculate the curve. Each time a single point is edited it should auto calculate a new spline of some sort to smoothly transition between each point. It kind of works when the points are within a particular range of each other as below.

good example of a good result

But if the points end up too far apart, or too close together, I end up with issues like the following.

good example of a bad result

Key points are:

  1. The curve MUST be flat between the first two points
  2. The curve must NOT go below point 1 or 2 (i.e. derivative can't be negative)
  3. ~15 points (not shown) between points 2 and 3 are also editable and the line between is not necessarily linear. Full control over each of these points is a must, as is the curve going through each of them.

I'm happy to break it down into smaller curves that i then join/convolve, but just need to ensure a >0 gradient.

sample data:

x=[0, 37, 50, 105, 115,120]
y=[0.00965, 0.00965, 0.047850827205882, 0.35600416666667, 0.38074375,  0.38074375]

As an example, try moving point 2 (x=37) to an extreme value, say 10 (keep y the same). Just ensure that all points from x=0 to x=10 (or any other variation) have identical y values of 0.00965.

any assistance is greatly appreciated.

UPDATE Attempted pchip method suggested in comments with the results below:

pchip method, better and worse...

1
Thanks @WarrenWeckesser. I had already tried the pchip method, but perhaps it's worth looking at again as some of those solutions look exactly like what I'm after. I'll report back.Fonty
Almost. However the pchip method (which in now recall does have an issue) misbehaves at the top of the curve. But perhaps I just need to add a point or 2 around that to more heavily weight the point. See the new image in the original post.Fonty
Additional points don't seem to avoid the significant 'kink' as the curved section becomes more linear. It seems as though I may need to sample some points from the pchip method, then pass those into the Rbf method. Or find a different solution altogether - one that allows conditions to be set, like derivatives or point weights.Fonty
It appears as though the only 'workable' solution (although the term solution is used lightly) will be to have an additional point mid way between points 2 and 3 with an additional side check on the calculated data which looks at the derivative around the point and throws some error message back to the user if the result goes outside of certain conditions (like no negatives, or it must always be increasing).Fonty

1 Answers

0
votes

Solved!

While I'm not sure that this is exactly true, it is as if the spline tools for creating Bezier curves treat the control points as points the calculated curve must go through - which is not true in my case. I couldn't figure out how to turn this feature off, so I found the cubic formula for a Bezier curve (cubic is what I need) and calculated my own points. I only then had to do a little adjustment to make the points fit the required integer x values - in my case, near enough is good enough. I would otherwise have needed to interpolate linearly between two points either side of the desired x value and determine the exact value.

For those interested, cubic needs 4 points - start, end, and 2 control points. The rule is:

B(t) = (1-t)^3 P0 + 3(1-t)^2 tP1 + 3(1-t)t^2 P2 + t^3 P3

Calculate for x and y separately, using a list of values for t. If you need to gradient match, just make sure that the control points for P1 and P2 are only moved along the same gradient as the preceding/proceeding sections.

Perfect result