Fitting a closed curve to a set of points - python

I have a set of points pts which form a loop and it looks like this:
This is somewhat similar to 31243002, but instead of putting points in between pairs of points, I would like to fit a smooth curve through the points (coordinates are given at the end of the question), so I tried something similar to scipy documentation on Interpolation:
values = pts
tck = interpolate.splrep(values[:,0], values[:,1], s=1)
xnew = np.arange(2,7,0.01)
ynew = interpolate.splev(xnew, tck, der=0)
but I get this error:
ValueError: Error on input data
Is there any way to find such a fit?
Coordinates of the points:
pts = array([[ 6.55525 , 3.05472 ],
[ 6.17284 , 2.802609],
[ 5.53946 , 2.649209],
[ 4.93053 , 2.444444],
[ 4.32544 , 2.318749],
[ 3.90982 , 2.2875 ],
[ 3.51294 , 2.221875],
[ 3.09107 , 2.29375 ],
[ 2.64013 , 2.4375 ],
[ 2.275444, 2.653124],
[ 2.137945, 3.26562 ],
[ 2.15982 , 3.84375 ],
[ 2.20982 , 4.31562 ],
[ 2.334704, 4.87873 ],
[ 2.314264, 5.5047 ],
[ 2.311709, 5.9135 ],
[ 2.29638 , 6.42961 ],
[ 2.619374, 6.75021 ],
[ 3.32448 , 6.66353 ],
[ 3.31582 , 5.68866 ],
[ 3.35159 , 5.17255 ],
[ 3.48482 , 4.73125 ],
[ 3.70669 , 4.51875 ],
[ 4.23639 , 4.58968 ],
[ 4.39592 , 4.94615 ],
[ 4.33527 , 5.33862 ],
[ 3.95968 , 5.61967 ],
[ 3.56366 , 5.73976 ],
[ 3.78818 , 6.55292 ],
[ 4.27712 , 6.8283 ],
[ 4.89532 , 6.78615 ],
[ 5.35334 , 6.72433 ],
[ 5.71583 , 6.54449 ],
[ 6.13452 , 6.46019 ],
[ 6.54478 , 6.26068 ],
[ 6.7873 , 5.74615 ],
[ 6.64086 , 5.25269 ],
[ 6.45649 , 4.86206 ],
[ 6.41586 , 4.46519 ],
[ 5.44711 , 4.26519 ],
[ 5.04087 , 4.10581 ],
[ 4.70013 , 3.67405 ],
[ 4.83482 , 3.4375 ],
[ 5.34086 , 3.43394 ],
[ 5.76392 , 3.55156 ],
[ 6.37056 , 3.8778 ],
[ 6.53116 , 3.47228 ]])

Actually, you were not far from the solution in your question.
Using scipy.interpolate.splprep for parametric B-spline interpolation would be the simplest approach. It also natively supports closed curves, if you provide the per=1 parameter,
import numpy as np
from scipy.interpolate import splprep, splev
import matplotlib.pyplot as plt
# define pts from the question
tck, u = splprep(pts.T, u=None, s=0.0, per=1)
u_new = np.linspace(u.min(), u.max(), 1000)
x_new, y_new = splev(u_new, tck, der=0)
plt.plot(pts[:,0], pts[:,1], 'ro')
plt.plot(x_new, y_new, 'b--')
plt.show()
Fundamentally, this approach not very different from the one in #Joe Kington's answer. Although, it will probably be a bit more robust, because the equivalent of the i vector is chosen, by default, based on the distances between points and not simply their index (see splprep documentation for the u parameter).

Your problem is because you're trying to work with x and y directly. The interpolation function you're calling assumes that the x-values are in sorted order and that each x value will have a unique y-value.
Instead, you'll need to make a parameterized coordinate system (e.g. the index of your vertices) and interpolate x and y separately using it.
To start with, consider the following:
import numpy as np
from scipy.interpolate import interp1d # Different interface to the same function
import matplotlib.pyplot as plt
#pts = np.array([...]) # Your points
x, y = pts.T
i = np.arange(len(pts))
# 5x the original number of points
interp_i = np.linspace(0, i.max(), 5 * i.max())
xi = interp1d(i, x, kind='cubic')(interp_i)
yi = interp1d(i, y, kind='cubic')(interp_i)
fig, ax = plt.subplots()
ax.plot(xi, yi)
ax.plot(x, y, 'ko')
plt.show()
I didn't close the polygon. If you'd like, you can add the first point to the end of the array (e.g. pts = np.vstack([pts, pts[0]])
If you do that, you'll notice that there's a discontinuity where the polygon closes.
This is because our parameterization doesn't take into account the closing of the polgyon. A quick fix is to pad the array with the "reflected" points:
import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt
#pts = np.array([...]) # Your points
pad = 3
pts = np.pad(pts, [(pad,pad), (0,0)], mode='wrap')
x, y = pts.T
i = np.arange(0, len(pts))
interp_i = np.linspace(pad, i.max() - pad + 1, 5 * (i.size - 2*pad))
xi = interp1d(i, x, kind='cubic')(interp_i)
yi = interp1d(i, y, kind='cubic')(interp_i)
fig, ax = plt.subplots()
ax.plot(xi, yi)
ax.plot(x, y, 'ko')
plt.show()
Alternately, you can use a specialized curve-smoothing algorithm such as PEAK or a corner-cutting algorithm.

Using the ROOT Framework and the pyroot interface I was able to generate the following image
With the following code(I converted your data to a CSV called data.csv so reading it into ROOT would be easier and gave the columns titles of xp,yp)
from ROOT import TTree, TGraph, TCanvas, TH2F
c1 = TCanvas( 'c1', 'Drawing Example', 200, 10, 700, 500 )
t=TTree('TP','Data Points')
t.ReadFile('./data.csv')
t.SetMarkerStyle(8)
t.Draw("yp:xp","","ACP")
c1.Print('pydraw.png')

To fit a smooth closed curve through N points you can use line segments with the following constraints:
Each line segment has to touch its two end points (2 conditions per line segment)
For each point the left and right line segment have to have the same derivative (2 conditions per point == 2 conditions per line segment)
To be able to have enough freedom for in total 4 conditions per line segment the equation of each line segment should be y = ax^3 + bx^2 + cx + d. (so the derivative is y' = 3ax^2 + 2bx + c)
Setting the conditions as suggested would give you N * 4 linear equations for N * 4 unknowns (a1..aN, b1..bN, c1..cN, d1..dN) solvable by matrix inversion (numpy).
If the points are on the same vertical line special (but simple) handling is required since the derivative will be "infinite".

Related

sorting a complicated collection of 2d euclidian points in in clockwise/counterclockwise fashion to form a closed ring

This looks like a repeated question but I tried the solution that already exists and none seems to work so far for me. .
this solution gives a hint but it works only for a regular geometry. I have a rather complicated geometry from which I extract boundary points which are unsorted.
Below is a picture of the geometry and of the boundary vertices that I extract from the geometry.
The (x,y) coordinates of points as in the image are :
import numpy as np
pts = np.array([[ 30. , -6.25 ],
[ 30. , -8.10127917],
[ 0. , -6.25 ],
[ 34.14082772, -6.75584268],
[ 36.49784598, -10. ],
[ 44.43561524, -10. ],
[ 100. , -10. ],
[ 100. , 10. ],
[ 84.1244615 , -10. ],
[ 84.1244615 , 10. ],
[ 36.49784598, 10. ],
[ 34.14082772, 6.75584268],
[ 44.43561524, 10. ],
[ 30. , 8.10127917],
[ 30. , 6.25 ],
[ 0. , 6.25 ],
[ -30. , 6.25 ],
[ -30. , 8.10127917],
[ -32.92183092, 9.05063958],
[ -35.84366185, 10. ],
[ -51.88274638, 10. ],
[-100. , 10. ],
[-100. , -10. ],
[ -83.96091546, 10. ],
[ -83.96091546, -10. ],
[ -35.84366185, -10. ],
[ -51.88274638, -10. ],
[ -32.92183092, -9.05063958],
[ -30. , -8.10127917],
[ -30. , -6.25 ],
[ -67.92183092, 10. ],
[ -67.92183092, -10. ],
[ 68.24892299, 10. ],
[ 52.37338449, 10. ],
[ 68.24892299, -10. ],
[ 52.37338449, -10. ]])
In the boundary vertex data, we can see that the points are unordered. Is there a way the points could be ordered clockwise/counter clockwise so that these points form a closed ring when connected successively?
My goal is to create a polygon or a linear ring as described here and later find if an arbitrary euclidean point lies inside the polyogn/ring
Update: the approach of computing angle between centroid of the pts and the individual euclidean point in pts also doesn't work. Here is a sample code of what I tried :
def sort_circular(pts):
cent = coords.mean(axis=0)
idx = list(np.arange(0, len(pts)+1, dtype=int))
angle = []
for i, cc in enumerate(coords):
dx,dy = cc[0] - center[0], cc[1]-center[1]
angle.append(math.degrees(math.atan2(float(dy), float(dx))))
#simultaneously sort angle and indices
_, idx_sorted = (list(t) for t in zip(*sorted(zip(angle, idx))))
pts_sorted = pts[idx_sorted]
return pts_sorted
The result from this is still not the way i expect it to be (image below):
Method 1:
Define a center point, compute the angle between every coordinate and the center point, then order them by angle:
import pandas as pd
# Define function to compute angle between vectors
import math
def clockwiseangle_and_distance(point, origin = [0,0], refvec = [1,0]):
# Vector between point and the origin: v = p - o
vector = [point[0]-origin[0], point[1]-origin[1]]
# Length of vector: ||v||
lenvector = math.hypot(vector[0], vector[1])
# If length is zero there is no angle
if lenvector == 0:
return -math.pi, 0
# Normalize vector: v/||v||
normalized = [vector[0]/lenvector, vector[1]/lenvector]
dotprod = normalized[0]*refvec[0] + normalized[1]*refvec[1] # x1*x2 + y1*y2
diffprod = refvec[1]*normalized[0] - refvec[0]*normalized[1] # x1*y2 - y1*x2
angle = math.atan2(diffprod, dotprod)
# Negative angles represent counter-clockwise angles so we need to subtract them
# from 2*pi (360 degrees)
if angle < 0:
return 2*math.pi+angle, lenvector
# I return first the angle because that's the primary sorting criterium
# but if two vectors have the same angle then the shorter distance should come first.
return angle, lenvector
import pandas as pd
# Compute the center point
center = pts.mean(axis=0)
angle = []
for i in range(len(pts)):
ang, dist = clockwiseangle_and_distance(pts[i,:] - center, origin=[0,0], refvec=[1,0])
angle.append(ang)
df = pd.DataFrame(pts)
df['angle'] = np.degrees(angle)
df = df.sort_values(by='angle')
df['clockwise_order'] = np.arange(len(df))
import matplotlib.pyplot as plt
# Create plot to show the ordering of the points
plt.figure()
df.plot(kind='scatter', x=0, y=1, s=100, alpha=0.5)
plt.title('Points by clockwise order')
for idx, row in df.iterrows():
plt.gca().annotate('{:.0f}'.format(row['clockwise_order']), (row[0], row[1]),
ha='center', va='center_baseline', fontsize=6, color='k', fontweight='bold')
plt.gca().annotate('Center', center,
ha='center', va='center')
If this clockwise ordering doesn't give you what you want, try Method 2.
Method 2:
To sort the points for the given geometry in clockwise order such that they form a closed ring, you can do the following:
Divide the data set in quadrants
Choose a center point such that the remaining points of the quadrant lie on about the arc of a circle centered at the center point
Order each quadrant by clockwise angle
Place each quadrant in clockwise order
# Compute the center point
center = pts.mean(axis=0)
df = pd.DataFrame(pts)
# Group points into quadrants
df['quadrant'] = 0
df.loc[(df[0] > center[0]) & (df[1] > center[1]), 'quadrant'] = 0
df.loc[(df[0] > center[0]) & (df[1] < center[1]), 'quadrant'] = 1
df.loc[(df[0] < center[0]) & (df[1] < center[1]), 'quadrant'] = 2
df.loc[(df[0] < center[0]) & (df[1] > center[1]), 'quadrant'] = 3
quadrant = {}
for i in range(4):
quadrant[i] = df[df.quadrant == i]
# Intelligently choose the quadrant centers
x = 35
y = 5
subcenter = [[ x, y],
[ x, -y],
[-x, -y],
[-x, y]]
# Compute the angle between each quadrant and respective center point
angle = {}
points = {}
df_sub = {}
for j in range(len(quadrant)):
angle[j] = []
points[j] = quadrant[j][[0,1]]
for i in range(len(points[j])):
ang, dist = clockwiseangle_and_distance(points[j].values[i,:] - subcenter[j], origin=[0,0], refvec=[1,0])
angle[j].append(ang)
df_sub[j] = quadrant[j]
df_sub[j]['angle'] = np.degrees(angle[j])
df_sub[j] = df_sub[j].sort_values(by='angle')
# Combine the data frames
df = pd.concat(df_sub)
df['clockwise_order'] = np.arange(len(df))
# Plot the points by clockwise order
import matplotlib.pyplot as plt
# Create plot to show the ordering of the points
fig, axis = plt.subplots()
df[[0,1]].plot(x=0, y=1, ax=axis, c='lightblue', legend=False, clip_on=False)
df.plot(kind='scatter', x=0, y=1, s=100, ax=axis, c='lightblue', clip_on=False)
plt.title('Points by quadrant in clockwise order')
plt.axis('off')
for idx, row in df.iterrows():
plt.gca().annotate('{:.0f}'.format(row['clockwise_order']), (row[0], row[1]),
ha='center', va='center_baseline', fontsize=6, color='k', fontweight='bold')
plt.gca().annotate('Center', center,
ha='center', va='center')
for i in range(len(subcenter)):
plt.scatter(subcenter[i][0], subcenter[i][1], alpha=0.5, s=80, marker='s')
plt.gca().annotate('Quadrant \n'+str(i)+'\n', subcenter[i],
ha='center', va='center_baseline', color='k', fontsize=8)
# Plot with axis equally-spaced
df2 = df[[0,1]].reset_index(drop=True)
df2.loc[len(df2),:] = df2.loc[0,:]
df2.plot(x=0, y=1, c='k', legend=False, clip_on=False)
plt.axis('equal')
plt.axis('off')
If this doesn't give you what you want, you may have to order the coordinates by hand.

Plotting contour in python

I have an np array of shape (15,2)
When I meshgrid first and second dimension of this array and write a function of this array, and then plot using contour, the output is blank. I don't understand what's wrong. Please guide me.
The code is:
M=[[12.647,4.2439],[13.744,8.9295],[13.93,9.191 ],[16.223,12.452 ],
[16.475 , 12.784 ],
[16.535 , 12.813 ],
[16.774 , 13.377 ],
[16.949 , 13.465 ],
[17.295 , 13.494 ],
[17.329 , 13.613 ],
[18.183 , 14.683 ],
[19.055 , 14.871 ],
[19.098 , 15.487 ],
[21.798 , 16.23 ],
[22.241 , 16.411 ]]
x1,y1=np.meshgrid(M[:,0],M[:,1])
F=np.sqrt(x1**2 + y1**2)
plt.contour(x1,y1,F)
Here M is a np array of (15,2). Is the problem with the values of M?
This is what i get when i run
import numpy as np
import matplotlib.pyplot as plt
M = np.array([[12.647, 4.2439],
[13.744, 8.9295],
[13.93, 9.191],
[16.223, 12.452],
[16.475, 12.784],
[16.535, 12.813],
[16.774, 13.377],
[16.949, 13.465],
[17.295, 13.494],
[17.329, 13.613],
[18.183, 14.683],
[19.055, 14.871],
[19.098, 15.487],
[21.798, 16.23],
[22.241, 16.411]])
x1, y1 = np.meshgrid(M[:, 0], M[:, 1])
f = np.sqrt(x1 ** 2 + y1 ** 2)
plt.contour(x1, y1, f)
plt.show()
Is this what you want? If not, please explain in detail what you would expect to see.

Generating a spline using scipy from a numpy array containing x and y coordinates [duplicate]

I have a set of points pts which form a loop and it looks like this:
This is somewhat similar to 31243002, but instead of putting points in between pairs of points, I would like to fit a smooth curve through the points (coordinates are given at the end of the question), so I tried something similar to scipy documentation on Interpolation:
values = pts
tck = interpolate.splrep(values[:,0], values[:,1], s=1)
xnew = np.arange(2,7,0.01)
ynew = interpolate.splev(xnew, tck, der=0)
but I get this error:
ValueError: Error on input data
Is there any way to find such a fit?
Coordinates of the points:
pts = array([[ 6.55525 , 3.05472 ],
[ 6.17284 , 2.802609],
[ 5.53946 , 2.649209],
[ 4.93053 , 2.444444],
[ 4.32544 , 2.318749],
[ 3.90982 , 2.2875 ],
[ 3.51294 , 2.221875],
[ 3.09107 , 2.29375 ],
[ 2.64013 , 2.4375 ],
[ 2.275444, 2.653124],
[ 2.137945, 3.26562 ],
[ 2.15982 , 3.84375 ],
[ 2.20982 , 4.31562 ],
[ 2.334704, 4.87873 ],
[ 2.314264, 5.5047 ],
[ 2.311709, 5.9135 ],
[ 2.29638 , 6.42961 ],
[ 2.619374, 6.75021 ],
[ 3.32448 , 6.66353 ],
[ 3.31582 , 5.68866 ],
[ 3.35159 , 5.17255 ],
[ 3.48482 , 4.73125 ],
[ 3.70669 , 4.51875 ],
[ 4.23639 , 4.58968 ],
[ 4.39592 , 4.94615 ],
[ 4.33527 , 5.33862 ],
[ 3.95968 , 5.61967 ],
[ 3.56366 , 5.73976 ],
[ 3.78818 , 6.55292 ],
[ 4.27712 , 6.8283 ],
[ 4.89532 , 6.78615 ],
[ 5.35334 , 6.72433 ],
[ 5.71583 , 6.54449 ],
[ 6.13452 , 6.46019 ],
[ 6.54478 , 6.26068 ],
[ 6.7873 , 5.74615 ],
[ 6.64086 , 5.25269 ],
[ 6.45649 , 4.86206 ],
[ 6.41586 , 4.46519 ],
[ 5.44711 , 4.26519 ],
[ 5.04087 , 4.10581 ],
[ 4.70013 , 3.67405 ],
[ 4.83482 , 3.4375 ],
[ 5.34086 , 3.43394 ],
[ 5.76392 , 3.55156 ],
[ 6.37056 , 3.8778 ],
[ 6.53116 , 3.47228 ]])
Actually, you were not far from the solution in your question.
Using scipy.interpolate.splprep for parametric B-spline interpolation would be the simplest approach. It also natively supports closed curves, if you provide the per=1 parameter,
import numpy as np
from scipy.interpolate import splprep, splev
import matplotlib.pyplot as plt
# define pts from the question
tck, u = splprep(pts.T, u=None, s=0.0, per=1)
u_new = np.linspace(u.min(), u.max(), 1000)
x_new, y_new = splev(u_new, tck, der=0)
plt.plot(pts[:,0], pts[:,1], 'ro')
plt.plot(x_new, y_new, 'b--')
plt.show()
Fundamentally, this approach not very different from the one in #Joe Kington's answer. Although, it will probably be a bit more robust, because the equivalent of the i vector is chosen, by default, based on the distances between points and not simply their index (see splprep documentation for the u parameter).
Your problem is because you're trying to work with x and y directly. The interpolation function you're calling assumes that the x-values are in sorted order and that each x value will have a unique y-value.
Instead, you'll need to make a parameterized coordinate system (e.g. the index of your vertices) and interpolate x and y separately using it.
To start with, consider the following:
import numpy as np
from scipy.interpolate import interp1d # Different interface to the same function
import matplotlib.pyplot as plt
#pts = np.array([...]) # Your points
x, y = pts.T
i = np.arange(len(pts))
# 5x the original number of points
interp_i = np.linspace(0, i.max(), 5 * i.max())
xi = interp1d(i, x, kind='cubic')(interp_i)
yi = interp1d(i, y, kind='cubic')(interp_i)
fig, ax = plt.subplots()
ax.plot(xi, yi)
ax.plot(x, y, 'ko')
plt.show()
I didn't close the polygon. If you'd like, you can add the first point to the end of the array (e.g. pts = np.vstack([pts, pts[0]])
If you do that, you'll notice that there's a discontinuity where the polygon closes.
This is because our parameterization doesn't take into account the closing of the polgyon. A quick fix is to pad the array with the "reflected" points:
import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt
#pts = np.array([...]) # Your points
pad = 3
pts = np.pad(pts, [(pad,pad), (0,0)], mode='wrap')
x, y = pts.T
i = np.arange(0, len(pts))
interp_i = np.linspace(pad, i.max() - pad + 1, 5 * (i.size - 2*pad))
xi = interp1d(i, x, kind='cubic')(interp_i)
yi = interp1d(i, y, kind='cubic')(interp_i)
fig, ax = plt.subplots()
ax.plot(xi, yi)
ax.plot(x, y, 'ko')
plt.show()
Alternately, you can use a specialized curve-smoothing algorithm such as PEAK or a corner-cutting algorithm.
Using the ROOT Framework and the pyroot interface I was able to generate the following image
With the following code(I converted your data to a CSV called data.csv so reading it into ROOT would be easier and gave the columns titles of xp,yp)
from ROOT import TTree, TGraph, TCanvas, TH2F
c1 = TCanvas( 'c1', 'Drawing Example', 200, 10, 700, 500 )
t=TTree('TP','Data Points')
t.ReadFile('./data.csv')
t.SetMarkerStyle(8)
t.Draw("yp:xp","","ACP")
c1.Print('pydraw.png')
To fit a smooth closed curve through N points you can use line segments with the following constraints:
Each line segment has to touch its two end points (2 conditions per line segment)
For each point the left and right line segment have to have the same derivative (2 conditions per point == 2 conditions per line segment)
To be able to have enough freedom for in total 4 conditions per line segment the equation of each line segment should be y = ax^3 + bx^2 + cx + d. (so the derivative is y' = 3ax^2 + 2bx + c)
Setting the conditions as suggested would give you N * 4 linear equations for N * 4 unknowns (a1..aN, b1..bN, c1..cN, d1..dN) solvable by matrix inversion (numpy).
If the points are on the same vertical line special (but simple) handling is required since the derivative will be "infinite".

Plot a smooth curve for an array and a normal one for another - Python

I have the following to plot, two arrays of shapes (120,) and (120,). For the second array, I am trying to get a smooth plot, but unable to do so.
The following plots a normal plot:
add_z = array([ 22.39409055, 20.91765398, 19.80805759, 19.14836638, 23.54310977, 19.68638808, 21.25143616, 21.32550146, 18.80392599, 17.37016759, 19.21143494, 18.27464661, 21.25150385, 20.61853909 ])
dataNew = array([[ 26.69], [ 24.94], [ 22.37], [ 23.5 ], [ 22.69], [ 22.62], [ 18.5 ], [ 20.87], [ 19. ], [ 19.75], [ 20.72], [ 19.78], [ 20.38], [ 22.06]])
import matplotlib.pyplot as plt
plt.figure(figsize = (10,5))
plt.plot(dataNew[:],'g')
plt.plot(add_z[:],'b');
I tried using scipy's interpolation methods but, I am really not familiar with splines. I am trying to get dataNew as a normal plot and add_z as a smooth curve to go along in the same plot window. Both are numpy arrays.
This is just patching on another stackoverflow answer which I have embarassingly misplaced:
import matplotlib.pyplot as plt
import numpy as np
add_z = np.array([ 22.39409055, 20.91765398, 19.80805759, 19.14836638, 23.54310977, 19.68638808, 21.25143616, 21.32550146, 18.80392599, 17.37016759, 19.21143494, 18.27464661, 21.25150385, 20.61853909, 22.89028155, 22.3965408 ])
dataNew = np.array([[ 26.69], [ 24.94], [ 22.37], [ 23.5 ], [ 22.69], [ 22.62], [ 18.5 ], [ 20.87], [ 19. ], [ 19.75], [ 20.72], [ 19.78], [ 20.38], [ 22.06]])
plt.figure(figsize = (10,5))
plt.plot(dataNew[:],'g')
plt.plot(add_z[:],'b');
from scipy import interpolate
f = interpolate.interp1d(np.arange(len(add_z)), add_z, kind='cubic')
xnew = np.arange(0, len(add_z)-1, 0.1)
ynew = f(xnew)
plt.plot(xnew, ynew, 'b:')

Using Pylab to create a plot of a line and then getting the rasterized data from the line

I am trying to get the rasterized line data from a pylab plot function. My code is like so:
fitfunc = lambda p, x: p[0] + p[1] * sin(2 * pi * x / data[head[0]].size + p[2])
errfunc = lambda p, x, y: fitfunc(p, x) - y
data = np.genfromtxt(dataFileName, dtype=None, delimiter='\t', names=True)
xAxisSeries =linspace(0., data[head[0]].max(), data[head[0]].size)
p0 = [489., 1000., 9000.] # Initial guess for the parameters
p1, success = optimize.leastsq(errfunc, p0[:], args=(xAxisSeries, data[head[1]]))
time = linspace(xAxisSeries.min(), xAxisSeries.max(), 1000)
plotinfo = plot(time, fitfunc(p1, time), 'r-')
I want to get the x and y line data from plotinfo. When I use "type(plotinfo)," plotinfo is a list, but when using "print plotinfo," it is a 2dlist object.
import numpy as np
import matplotlib.pyplot as plt
N=4
x=np.linspace(0, 10, N)
y=np.cumsum(np.random.random(N) - 0.5)
line=plt.plot(x,y)[0]
path=line._path
These are the original (x,y) data points:
print(path.vertices)
# [[ 0. 0.08426592]
# [ 3.33333333 0.14204252]
# [ 6.66666667 0.41860647]
# [ 10. 0.22516175]]
Here we (linearly) interpolate to find additional points. You can increase the argument to path.interpolated to find more interpolated points between the original points.
path2=path.interpolated(2)
print(path2.vertices)
# [[ 0. 0.08426592]
# [ 1.66666667 0.11315422]
# [ 3.33333333 0.14204252]
# [ 5. 0.2803245 ]
# [ 6.66666667 0.41860647]
# [ 8.33333333 0.32188411]
# [ 10. 0.22516175]]

Categories