How to animate a contour plot produced by a bilinear interpolation? - python

I would like to visualize the magnitude of VM with respect to time t. In the following program, t is set to zero. I would appreciate it if one could tell me how to produce an animation of the bilinear interpolation contour plot. Thank you!
Please here is the code:
import numpy as np
from numpy import cos, sin, pi, exp, sqrt
from matplotlib import pyplot as plt
import matplotlib.cm as cm
nx=30
ny=30
nu=0.0025
p=2*pi
x = np.linspace(0,p,nx)
y = np.linspace(0,p,ny)
fig,ax = plt.subplots(1,1)
ax.set_xlim(0,p)
ax.set_ylim(0,p)
t=0
X,Y = np.meshgrid(x,y)
U=-cos(X)*sin(Y)*exp(-2*nu*t)
V=sin(X)*cos(Y)*exp(-2*nu*t)
VM=sqrt(U**2+V**2)
im = plt.imshow(VM, interpolation='bilinear', origin='lower',
cmap=cm.gray, extent=(0, p, 0, p))
levels = np.arange(-1.2, 1.6, 0.2)
# add a vertical colorbar.
CBI = plt.colorbar(im, orientation='vertical', shrink=0.8)
plt.show()

mostly copied from here. See there for in depth explanations.
import numpy as np
from numpy import cos, sin, pi, exp, sqrt
from matplotlib import pyplot as plt
import matplotlib.cm as cm
from matplotlib import animation
nx=30
ny=30
nu=0.0025
p=2*pi
x = np.linspace(0,p,nx)
y = np.linspace(0,p,ny)
fig,ax = plt.subplots(1,1)
ax.set_xlim(0,p)
ax.set_ylim(0,p)
t=0
X,Y = np.meshgrid(x,y)
U=-cos(X)*sin(Y)*exp(-2*nu*t)
V=sin(X)*cos(Y)*exp(-2*nu*t)
VM=sqrt(U**2+V**2)
im = plt.imshow(VM, interpolation='bilinear', origin='lower',
cmap=cm.gray, extent=(0, p, 0, p))
levels = np.arange(-1.2, 1.6, 0.2)
# add a vertical colorbar.
CBI = plt.colorbar(im, orientation='vertical', shrink=0.8)
def init():
im.set_data((np.empty_like(VM)))
return im,
def animate(t):
U=-cos(X)*sin(Y)*exp(-2*nu*t)
V=sin(X)*cos(Y)*exp(-2*nu*t)
VM=sqrt(U**2+V**2)
im.set_data(VM)
return im,
# # call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=200, interval=20, blit=True)
plt.show()

Related

python - how do I fix interpolate grid origin issues in matplotlib?

I have a data set with a small sample size of data. For example:
My code looks something like this:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.interpolate import Rbf
df=pd.read_csv('test.csv')
df.head()
extent = x_extent = x_min, x_max, y_min, y_max = [df["X"].min()-1000, df["X"].max()+1000, df["Y"].min()-1000, df["Y"].min()+1000]
grid_x, grid_y = np.mgrid[x_min:x_max:100, y_min:y_max:100]
rbfi=Rbf(df["X"], df["Y"], df["Total"])
di=rbfi(grid_x, grid_y)
plt.scatter(grid_x, grid_y, s=10)
plt.figure(figsize=(15,15))
plt.imshow(di.T, origin="lower", extent=extent)
c2 = plt.scatter(df["X"], df["Y"], s=60, c=df["Total"], edgecolor='#ffffff66')
plt.colorbar(c2, shrink=0.6)
plt.show()
the result:
The result is a scatter plot of my points that appear to be in the correct place, but the interpolated grid is not covering the scatter points. So I think this has something to do with my origin not being correct, but I don't know how to fix this.
Two approaches here, one with a Delaunay triangulation, the other using the Radial Basis Function. Snippet and figure below.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.tri import Triangulation
from scipy.interpolate import Rbf
rng = np.random.default_rng()
X = rng.random(size=(15))
Y = rng.random(size=(15))
Total = rng.random(size=(15))
fig, (ax, bx) = plt.subplots(nrows=1, ncols=2, num=0, figsize=(16, 8))
tri = Triangulation(X, Y)
tctrf = ax.tricontourf(tri, Total)
gridY, gridX = np.mgrid[np.amin(Y):np.amax(Y):100 * 1j,
np.amin(X):np.amax(X):100 * 1j]
rbfi = Rbf(X, Y, Total, function='linear')
iTotal = rbfi(gridX, gridY)
bx.contourf(gridX, gridY, iTotal)
scat = ax.scatter(X, Y, s=60, c=Total, edgecolor='black')
fig.colorbar(scat, ax=ax)
scat = bx.scatter(X, Y, s=60, c=Total, edgecolor='black')
fig.colorbar(scat, ax=bx)
ax.set_aspect('equal')
bx.set_aspect('equal')
fig.tight_layout()
fig.savefig('so.png')
plt.show()

Creating a graph with 2 planes and colormaps via Python

I have two 2D arrays and I want to use to produce an image similar to the one that fallows, just with different limits on the axis.
Here is my attempt so far:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlim(-2.01, 2.01)
ax.set_ylim(-2.01, 2.01)
ax.set_zlim(-2.01, 2.01)
cmap = plt.cm.gray
im = ax.imshow(np.asarray(array1), cmap=cmap)
im.remove()
fig.colorbar(im)
plt.show()
The arrays I have, (array1 and array2) are two dimensional with sizes n by n. Any help or a point in the right direction will be greatly appreciated!
With help of Matplotlib - Plot a plane and points in 3D simultaneously, I am able to achieve this:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
ax.set_xticks([0, 0.2, 0.4, 0.6, 0.8, 1])
ax.set_yticks([0, 0.5, 1])
ax.set_zticks([0, 0.2, 0.4, 0.6, 0.8, 1])
cmap = plt.cm.gray
#plot vertical surface
y = 0.5
xx, zz = np.meshgrid(np.linspace(0,1,10), np.linspace(0,1,10))
p = ax.plot_surface(xx, y, zz, cmap=cmap, alpha=0.5)
x = 0.2
yy, zz = np.meshgrid(np.linspace(0,1,10), np.linspace(0,1,10))
p = ax.plot_surface(x, yy, zz, cmap=cmap, alpha=0.5)
fig.colorbar(p)
plt.show()
Note that I didn't use normal or dot just as another question do, because here you want to plot vertical planes.
Here's what I got(I'm working on the right occlusion):

How do you scale a polygon patch in matplotlib?

In the example below, I create a rectangular patch using matplotlib.patches.Polygon. Is there a way to scale the patch before adding it to the plot?
I've tried using matplotlib.transforms.Affine2D in a variety of ways with no success. As usual, the matplotlib documentation on transformations is woefully insufficient.
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot([-3,3],[-3,3])
x = [-1,0,1,1,0,-1]
y = [1,1,1,-1,-1,-1]
poly = Polygon( zip(x,y), facecolor='red', edgecolor='red', alpha=0.5)
ax.add_patch(poly)
plt.show()
If by scale you mean multiplication by a factor, you can easily do this via numpy.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot([-3,3],[-3,3])
x = [-1,0,1,1,0,-1]
y = [1,1,1,-1,-1,-1]
scale = 2
poly = Polygon( np.c_[x,y]*scale, facecolor='red', edgecolor='red', alpha=0.5)
ax.add_patch(poly)
plt.show()
The same can be achieved with a matplotlib.transforms.Affine2D() transform.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
import matplotlib.transforms as transforms
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot([-3,3],[-3,3])
x = [-1,0,1,1,0,-1]
y = [1,1,1,-1,-1,-1]
trans = transforms.Affine2D().scale(2) + ax.transData
poly = Polygon( np.c_[x,y], facecolor='red', edgecolor='red', alpha=0.5,
transform=trans)
ax.add_patch(poly)
plt.show()
Although it seems a bit overkill for a simple scaling like this.

3D animation using matplotlib

I want to make 3D animation with matplotlib, but I don't know how to. Here is my non-working code.
from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import animation
from math import *
fig = plt.figure()
ax = fig.add_subplot(111) #, projection='3d'
#setting
ax.set_xlim(-5,5)
ax.set_ylim(-5,5)
#ax.set_zlim(-5,5)
ax.set_xlabel('x')
ax.set_ylabel('y')
#ax.set_zlabel('z')
ax.grid()
f1, = ax.plot([], [], "r-", lw=1) #plot1
def gen():
for phi in np.linspace(0,2*pi,100):
yield np.cos(phi), np.sin(phi), phi
def update(data):
p1, q1, psi = data
f1.set_data(p1,q1)
#f1.set_3d_properties(psi)
ani = animation.FuncAnimation(fig, update, gen, blit=False, interval=100, repeat=True)
#ani.save('matplot003.gif', writer='imagemagick')
plt.show()
I used this example http://matplotlib.org/1.4.1/examples/animation/simple_3danim.html
and modified your code:
from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import animation
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
def gen(n):
phi = 0
while phi < 2*np.pi:
yield np.array([np.cos(phi), np.sin(phi), phi])
phi += 2*np.pi/n
def update(num, data, line):
line.set_data(data[:2, :num])
line.set_3d_properties(data[2, :num])
N = 100
data = np.array(list(gen(N))).T
line, = ax.plot(data[0, 0:1], data[1, 0:1], data[2, 0:1])
# Setting the axes properties
ax.set_xlim3d([-1.0, 1.0])
ax.set_xlabel('X')
ax.set_ylim3d([-1.0, 1.0])
ax.set_ylabel('Y')
ax.set_zlim3d([0.0, 10.0])
ax.set_zlabel('Z')
ani = animation.FuncAnimation(fig, update, N, fargs=(data, line), interval=10000/N, blit=False)
#ani.save('matplot003.gif', writer='imagemagick')
plt.show()
Here is the following code for a sphere moving to the right and off the screen.
You will have to run this code in a folder for tidiness, as it generates 26 .png images (and a .gif image):
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
from numpy import sin, cos, pi, outer, ones, size, linspace
# Define x, y, z lists for sphere
a = linspace(0, 2 * pi)
b = linspace(0, pi)
x = 10 * outer(cos(a), sin(b))
y = 10 * outer(sin(a), sin(b))
z = 10 * outer(ones(size(a)), cos(b))
# The amount of frames in the animation
frames = 26
# Generate each frame
for n in range(frames):
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(x, y, z, color=('b'))
ax.set_xticks([])
ax.set_yticks([])
ax.set_zticks([])
ax.set_xlim(-8,8)
ax.set_xlim(-8,8)
ax.set_xlim(-8,8)
plt.savefig(f"{n}.png")
plt.close()
# Add 1 to the x so the sphere moves right by 1
x += 1
# Use pillow to save all frames as an animation in a gif file
from PIL import Image
images = [Image.open(f"{n}.png") for n in range(frames)]
images[0].save('ball.gif', save_all=True, append_images=images[1:], duration=100, loop=0)
Output:

End ticks in colorbar - matplotlib

I am trying to plot a colorbar in Python using the matplotlib libraries. The plot works well, but the color bar wont show the end ticks on the color bar.
Using the following command plots the colorbar properly, but I only have ticks ranging from -1.6 to +1.6 ( the top and bottom ticks are absent). The range of my data is from -2 to +2.
fig.colorbar(surf, shrink=1, aspect=12)
This is seen in the following figure:
I tried using the command:
cbar.set_ticks([-2,-1,0,1,2]);
But that also failed to get the correct result.
UPDATE:
I tried using the ticks=[-2,0,2] parameter, but that did not work as well. This is a snippet of my plotting code:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
CHI = np.linspace(-45, 45, 35);
M = np.linspace(0, 1, 35)
CHI, M = np.meshgrid(CHI, M)
R = 2*M*np.sin( 2 * np.deg2rad(CHI) )
surf = ax.plot_surface(CHI, M, R, rstride=1, cstride=1, cmap=cm.hsv,linewidth=0, antialiased=False)
ax.set_xlim(-45,45)
cbar = plt.colorbar(surf, shrink=1, aspect=12, ticks=[-2,-1,0,1,2])
plt.show()
This produces the following plot:
As seen, the colorbar lacks the end ticks, viz. -2 and 2
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
CHI = np.linspace(-45, 45, 35);
M = np.linspace(0, 1, 35)
CHI, M = np.meshgrid(CHI, M)
R = 2*M*np.sin( 2 * np.deg2rad(CHI) )
surf = ax.plot_surface(CHI, M, R, rstride=1, cstride=1, cmap=cm.hsv,linewidth=0, antialiased=False)
surf.set_clim([-2, 2]) # <- this is the important line
ax.set_xlim(-45,45)
cbar = plt.colorbar(surf, shrink=1, aspect=12, ticks=[-2,-1,0,1,2])
plt.show()
Something is going wrong with the auto-scaling (I would guess issues with floating point equality tests), if you explicitly set the clim to [-2, 2] it works.
You should be able to set the ticks parameter when calling plt.colorbar:
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
cmap = plt.get_cmap('jet')
data = np.random.randint(-2,3, size=(10,10))
im = ax.imshow(data, interpolation='nearest', cmap=cmap)
cbar = plt.colorbar(im, ticks=[-2,-1,0,1,2])
plt.show()

Categories

Resources