Extracting Line From Scipy Interpolated Data - python

I am trying to plot profiles from an interpolated data. To begin with my data is three columns x,y,c.
First I interpolate the data onto a regular grid using:
xi , yi = np.linspace(np.min(X), np.max(X),300) , np.linspace(np.min(Y), np.max(Y),300)
xi, yi = np.meshgrid(xi, yi)
zi = scipy.interpolate.griddata((X, Y), C , (xi, yi),method='nearest')
now following the thread: How to extract an arbitrary line of values from a numpy array?
I want to plot the values at X = 5 for Y = -4,4
x0, y0 = 5, -4 # These are in _pixel_ coordinates!!
x1, y1 = 5, 4
num = 50
x, y = np.linspace(x0, x1, num), np.linspace(y0, y1, num)
#Getting values at that location
zi2 = scipy.ndimage.map_coordinates(np.transpose(zi), np.vstack((x,y)))
#Plotting
fig, axes = plt.subplots(nrows=2)
axes[0].imshow(zi, vmin=np.min(C), vmax=110, origin='lower',extent= [np.min(X), np.max(X), np.min(Y), np.max(Y)])
axes[0].plot([x0, x1], [y0, y1], 'ro-')
axes[0].axis('image')
axes[1].plot(y,zi2)
plt.show()
I get the following plot which is not looking the same as the way contour is behaving.

Related

3D plot using delauney triangulation using four 1dimensional arrays. First three determine the coordinates while fourth determines the color

I am trying to achieve a plot like the one shown bellow:
The code I am using is the following:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.tri as tri
from matplotlib.colors import Normalize
# Example usage
x = np.linspace(0, 10, 500)
f1 = lambda x: x**2
f2 = lambda x: 3*x**1.4
f3 = lambda x: 2*x**1.2
f4 = lambda x: 2*x**1
X = f1(x)
Y = f2(x)
Z = f3(x)
Z1 = f4(x)
# Find the indices of the non-nan values
valid_indices = np.logical_not(np.logical_or(np.isnan(X), np.logical_or(np.isnan(Y), np.isnan(Z))))
# Use the non-nan indices to index into the arrays
x = X[valid_indices]
y = Y[valid_indices]
z = Z[valid_indices]
z1 = Z1[valid_indices]
# Create grid values first.
ngridx = 300
ngridy = 300
xi = np.linspace(x.min(), x.max(), ngridx)
yi = np.linspace(y.min(), y.max(), ngridy)
# Perform linear interpolation of the data (x,y)
# on a grid defined by (xi,yi)
triang = tri.Triangulation(x, y)
interpolator_z = tri.LinearTriInterpolator(triang, z)
interpolator_z1 = tri.LinearTriInterpolator(triang, z1)
Xi, Yi = np.meshgrid(xi, yi)
zi = interpolator_z(Xi, Yi)
z1i = interpolator_z1(Xi, Yi)
X, Y, Z, Z1 = xi, yi, zi, z1i
fig = plt.gcf()
ax1 = fig.add_subplot(111, projection='3d')
minn, maxx = z1.min(), z1.max()
norm = Normalize()
surf = ax1.plot_surface(X,Y,Z, rstride=1, cstride=1, facecolors=cm.jet(norm(Z1)), vmin=minn, vmax=maxx, shade=False)
#surf =ax.plot_trisurf(X,Y,Z, triangles=tri.triangles, cmap=plt.cm.Spectral)
m = cm.ScalarMappable(cmap=cm.jet)
m.set_array(Z1)
The result I am getting is close but not quite what I want:
I am looking to get something that looks closer to this:
Any ideas on how I could improve my result?

Slices across Contourf plots at different angles to get 2D line plots

I am trying to generate 2D line plots at different angles or slices of a matplotlib contourf plot.
As an example from the matplotlib contourf demo example below
import numpy as np
import matplotlib.pyplot as plt
origin = 'lower'
delta = 0.025
x = y = np.arange(-3.0, 3.01, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2
nr, nc = Z.shape
fig1, ax2 = plt.subplots(constrained_layout=True)
CS = ax2.contourf(X, Y, Z, 10, cmap=plt.cm.viridis, origin=origin,extend='both')
ax2.set_title('Random Plot')
ax2.set_xlabel('X Axis')
ax2.set_ylabel('Y Axis')
cbar = fig1.colorbar(CS)
Ideally, I want to generate lines at different angles (30,45,60 degrees) across the map (starting at any arbitrary point till the end of existing array) and then plot the Z variations across that line.
I think a simpler problem in principle would be, lines from (X2,Y2) to (X1,Y1) and plot the Z variation for the given contour (which is already interpolated data).
As an example, original problem would be line from (-3,-3) at angle 45 deg across. Analogous problem would be lets say a line from (-3,-3) to (3,3) and plot the Z variation at different locations on that line.
The source contour plot generated is :
Here is a rather inefficient approach, but it does the job. It recalculates the function on a new grid of which it only needs the diagonal.
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import RectBivariateSpline
delta = 0.025
x = y = np.arange(-3.0, 3.01, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X ** 2 - Y ** 2)
Z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2)
Z = (Z1 - Z2) * 2
nr, nc = Z.shape
x1, y1 = -3, -2
x2, y2 = 3, 2
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(15, 5))
CS = ax1.contourf(X, Y, Z, 10, cmap=plt.cm.viridis, origin='lower', extend='both')
ax1.plot([x1, x2], [y1, y2], color='k', ls='--', lw=3, alpha=0.6)
ax1.set_xlabel('X Axis')
ax1.set_ylabel('Y Axis')
cbar = fig.colorbar(CS, ax=ax1)
spline_func = RectBivariateSpline(x, y, Z)
xline = np.linspace(x1, x2, 200)
yline = np.linspace(y1, y2, 200)
zline = spline_func(xline, yline)
ax2.plot(xline, zline.diagonal())
ax2.set_xlabel('X Axis')
ax2.set_ylabel('Z Axis')
plt.show()

How to extract coordinates of points after a fit?

I am using the following code in order to smooth my data
a = get_data()
y, x = a.T
t = np.linspace(0, 1, len(x))
t2 = np.linspace(0, 1, len(x))
x2 = np.interp(t2, t, x)
y2 = np.interp(t2, t, y)
sigma = 50
x3 = gaussian_filter1d(x2, sigma)
y3 = gaussian_filter1d(y2, sigma)
x4 = np.interp(t, t2, x3)
y4 = np.interp(t, t2, y3)
plt.plot(x, y, "o-", lw=2)
plt.plot(x3, y3, "r", lw=2)
plt.plot(x4, y4, "o", lw=2)
plt.show()
I found this code here:
line smoothing algorithm in python?
My problem is that I need to get points from the new fit which are exactly with the same x values as my original x values (the points that I have smoothed).
The fit works well but the x values of the new points are different.
How can I get points from the new fit which has the same x value but with the new fit y values. The x values for the points starts from 0 and the space between each one should be 1800.
I think what is particular to your case is that the data to smooth are like a free line in the plane (x, y) = f(t) rather than a function y = f(x)
Maybe the trick is that the points have to be sorted before the interpolation (see numpy.interp):
# Generate random data:
t = np.linspace(0, 3, 20)
x = np.cos(t) + 0.1*np.random.randn(np.size(t))
y = np.sin(t) + 0.1*np.random.randn(np.size(t))
# Smooth the 2D data:
sigma = 2
x_smooth = gaussian_filter1d(x, sigma)
y_smooth = gaussian_filter1d(y, sigma)
# Sort (see: https://stackoverflow.com/a/1903579/8069403)
permutation = x_smooth.argsort()
x_smooth = x_smooth[permutation]
y_smooth = y_smooth[permutation]
x_new = np.sort(x) # not mandatory
# Interpolation on the original x points:
y_smooth_new = np.interp(x_new, x_smooth, y_smooth)
# Plot:
plt.plot(x, y, label='x, y');
plt.plot(x_smooth, y_smooth, label='x_smooth, y_smooth');
plt.plot(x_new, y_smooth_new, '-ro', label='x_new, Y_smooth_new', alpha=0.7);
plt.legend(); plt.xlabel('x');

How to plot multiple three-dimensional surface plots with matplotlib in the same plane

My goal is to plot the probability distribution functions (pdfs) of two classes. Each class has Gaussian likelihood and equivalent covariance matrices, but different mean vectors. I want both pdfs on the same plane in the z-axis, with the x and y axes containing the projections of the pdfs.
The following code (mostly borrowed from here) plots one of the pdfs:
# Our 2-dimensional distribution will be over variables X and Y
N = 100
X = np.linspace(-10, 15, N)
Y = np.linspace(-10, 15, N)
X, Y = np.meshgrid(X, Y)
# Mean vector and covariance matrix
mu1 = np.array([8, 2])
mu2 = np.array([2,8])
Sigma1 = Sigma2 = np.array([[4.1,0],[0,2.8]])
# Pack X and Y into a single 3-dimensional array
pos = np.empty(X.shape + (2,))
pos[:, :, 0] = X
pos[:, :, 1] = Y
F1 = multivariate_normal(mu1, Sigma1)
F2 = multivariate_normal(mu2, Sigma2)
Z1 = F1.pdf(pos)
Z2 = F2.pdf(pos)
# Create a surface plot and projected filled contour plot under it.
fig1 = plt.figure(figsize=[10,10])
ax1 = fig1.gca(projection='3d')
ax1.plot_surface(X, Y, Z1, rstride=3, cstride=3, linewidth=1,
antialiased=True,cmap=cm.inferno)
cset = ax1.contourf(X, Y, Z1, zdir='z', offset=-0.15, cmap=cm.inferno)
# Adjust the limits, ticks and view angle
ax1.set_zlim(-0.15,0.2)
ax1.set_zticks(np.linspace(0,0.2,5))
ax1.view_init(27, -21)
plt.show()
This is the plot that results from the above code: plot_surfaces for plotting bivariate pdf. However, I need to plot both Z1 and Z2 on the same plane. If I try creating two plots, they overlap and the Z2 pdf cannot be seen. Tweaking the code slightly, I get roughly what I want:
ax1 = fig1.gca(projection='3d')
ax2 = fig1.gca(projection='3d')
ax1.plot_wireframe(X, Y, Z1, rstride=3, cstride=3, linewidth=1,
antialiased=True,cmap=cm.inferno)
ax2.plot_wireframe(X,Y,Z2,rstride=3, cstride=3, linewidth=1,
antialiased=True,cmap=cm.inferno)
the resulting plot of which can be found here: wireframe method to plot 2 bivariate pdfs. But these plots are still overlapping. How can I get around this issue? I want the result to be styled as the first plot, with the surface_plot method and projections on the x-y plane.
You can play with alpha:
ax1.plot_surface(X, Y, Z1, rstride=3, cstride=3, linewidth=1,
antialiased=True,cmap=cm.inferno, alpha = 0.5)
ax1.plot_surface(X, Y, Z2, rstride=3, cstride=3, linewidth=1,
antialiased=True,cmap=cm.inferno, alpha = 1)
cset = ax1.contourf(X, Y, Z1, zdir='z', offset=-0.15, cmap=cm.inferno, alpha=1)
cset = ax1.contourf(X, Y, Z2, zdir='z', offset=-0.15, cmap=cm.inferno, alpha=0.5)
But in some cases you can get the same results by just summing your pdf's
ax1.plot_surface(X, Y, Z1 + Z2, rstride=3, cstride=3, linewidth=1, antialiased=True,cmap=cm.inferno)
cset = ax1.contourf(X, Y, Z1 + Z2, zdir='z', offset=-0.15, cmap=cm.inferno)

Obtain the surfaces curves in a figure with python

I have a set of data for that I need identify patterns, so I tried to use plt.contours and plt.contourf for that task and it works well, now I can plot contours and show graphically the overdensity among the data. In this step, I tried to get the information of the surface contours (I mean, save the values that define the contour in a variable to use it later.) without success: Is there a way to do this?
Also, I have doubts of what does the values in the color bar means, I know that is the level of overdensity of the data, but if someone could tell me more details, would be great.
I attach the code that I'm using so far (I generate the data in this case), and a plot of the code.
import scipy.interpolate
import numpy as np
import scipy.stats as st
import matplotlib.pyplot as plt
np.random.seed(20)
data = np.random.rand(400,2)
x = data[:,0]
y = data[:,1]
plt.figure(figsize=(12,7))
# Set up a regular grid of points
xi, yi = np.linspace(x.min(), x.max(), 100), np.linspace(y.min(), y.max(), 100)
xi, yi = np.meshgrid(xi, yi)
#contours:
n_contours = 6
positions = np.vstack([xi.ravel(), yi.ravel()])
values = np.vstack([x, y])
kernel = st.gaussian_kde(values)
f = np.reshape(kernel(positions).T, xi.shape)
cfset = plt.contourf(xi, yi, f,n_contours, cmap='Greens')
cset = plt.contour(xi, yi, f,n_contours, colors='k')
#For the points data:
positions = np.vstack([x.ravel(), y.ravel()])
values = np.vstack([x, y])
kernel = st.gaussian_kde(values)
z = np.reshape(kernel(positions).T, x.shape)
#plot:
plt.scatter(x, y, c=z)
plt.colorbar(cfset)
plt.show()
thanks!
EDIT:
I founded a way to do this, using the get_paths() feature, so basically, you need to choose the contour, and then the number of the segment that you need to get the values (x,y), for example:
#contour 3, section 0
p = cset.collections[3].get_paths()[0]
v = p.vertices
x0 = v[:,0]
y0 = v[:,1]
#contour 3, section 1
p = cset.collections[3].get_paths()[1]
v = p.vertices
x1 = v[:,0]
y1 = v[:,1]
#contour 3, section 2
p = cset.collections[3].get_paths()[2]
v = p.vertices
x2 = v[:,0]
y2 = v[:,1]
plt.plot(x0,y0,'-',x1,y1,'-',x2,y2,'-')
With this, you get:

Categories

Resources