2

I'm trying to plot a plane over a plot without having the main plot out of scale or overwritten. Ideally what I want is to aid visualization of a potential barrier in the complex visualization of a wave function, this could be done by somehow creating a shaded volume between the region of the potential... I thought I could make two planes for this purpose but they are plotted taking out of sight my main plot. This are two pictures of my resulting plots without and with the planes that I tried respectively:

Picture without the planes

Picture of the planes

I think I may be overwritting the main plot but I can't find a clear solution to this problem, this is the code I'm using to make the plot and an animation(If needed I can share the whole code):

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.gca(projection='3d')
ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), np.diag([1.5, 0.7, 0.7, 1]))

line,=ax.plot(x,IMAG[0,:],REAL[0,:],"r",linewidth=0.5)

ax.set_xlabel('Posició (nm)')
ax.set_ylabel('$Im[\psi(x,t)]$')
ax.set_zlabel('$Re[\psi(x,t)]$')

#Here are the two planes
yy, zz = np.meshgrid(range(-2,2), range(-2,2))

ax2 = plt.subplot(projection='3d')
ax2.plot_surface(-l, yy, zz,color='b',alpha=0.2)
ax2.plot_surface(l, yy, zz,color='b',alpha=0.2)

def animacio(i):
    ax.collections.clear()
    line.set_data(REAL[i,:],IMAG[i,:])
    line.set_3d_properties(x, 'x')


    return line,
ani=animation.FuncAnimation(fig,animacio,interval=50, frames=Nt,repeat=True)
ani.save(f'Evolució_[{V0},{L},{l},{xi},{sigmax},{T}].mp4', writer="ffmpeg", dpi=300)
plt.show()
William Miller
  • 9,839
  • 3
  • 25
  • 46

1 Answers1

2

You are plotting the planes on a separate subplot from the wave function. Instead of

ax2 = plt.subplot(projection='3d')
ax2.plot_surface(-l, yy, zz,color='b',alpha=0.2)
ax2.plot_surface(l, yy, zz,color='b',alpha=0.2)

Try

ax.plot_surface(-l, yy, zz, color='b', alpha=0.2)
ax.plot_surface(l, yy, zz, color='b', alpha=0.2)

And you should see the planes on the same plot as the wave function. You may also need to remove

ax.collections.clear()

From the animation function, using set_data and set_3d_properties should suffice to animate the wave function without altering the planes.


Edit

To keep the plotting of the planes from affecting the scale of the plot you can set the limits of the plot ahead of time, i.e.

ax.set_xlim([-20, 20])
ax.set_ylim([-0.6, 0.6])
ax.set_zlim([-0.6, 0.6])

Note, however, that the full extent of the planes will be plotted regardless of this - it is necessary to perform the creation properly to account for this. The following should do so

yy, zz = np.meshgrid(np.linspace(-1,1), np.linspace(-1,1))

I have encountered issues with using set_data and set_3d_properties in the past, if those do not work then you must simply clear the axis and replot the wavefunction and bounding planes, along with resetting the limits on each iteration.

Below is a complete example which illustrates the above

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import animation
from mpl_toolkits.mplot3d import Axes3D

n = 200
fig = plt.figure(figsize=(16,6))
ax = fig.add_subplot(111, projection='3d')
yy, zz = np.meshgrid(np.linspace(-1,1), np.linspace(-1,1))

def update(i):
    # Show propagation of demonstration wavefunction in +x direction
    i *= 22
    p = np.zeros((3, n*4))
    p[0,:] = np.linspace(-np.pi*16, np.pi*16, n*4)
    x = p[0,i:i+n*2]
    p[1,i:i+n*2] = np.sin(2*x + np.pi/2) * np.sin(x/16 + np.pi/2)/2
    p[2,i:i+n*2] = np.sin(2*x) * np.cos(x/16)/2
    # Plotting
    plt.cla()
    ax.set_xlim([-np.pi*16, np.pi*16])
    ax.set_ylim([-1,1])
    ax.set_zlim([-1,1])
    ax.plot_surface(np.full_like(yy, -np.pi*16), yy, zz, color='b', alpha=0.2)
    ax.plot_surface(np.full_like(yy, np.pi*16), yy, zz, color='b', alpha=0.2)
    plot, = ax.plot(p[0,:], p[1,:], p[2,:], color='red', lw=1)
    return plot,

anim = animation.FuncAnimation(fig, update, frames=n//10, interval=2000/(n//10))
anim.save('wavefunc.gif', writer='imagemagick')

enter image description here

William Miller
  • 9,839
  • 3
  • 25
  • 46
  • This worked for getting the planes on the same plot, but still depending on what range I choose for the meshgrid the planes change the scale of the wave function plot. Is there a way to plot things without autoadjusting the scale for it? – Isidre Mas Magre Jan 05 '20 at 21:06
  • This solved my problem thank you! However my intended use was as a finite potential barrier/well of width 2l centered in the plot to show tunneling effect, now I'm thinking that maybe two planes are not adecuate enough because the transparencies overlap and it looks weird... They make for good infinite boundaries though! This may be topic for another question, but is there a simple way of plotting a rectangular parallelepiped that does not overlap its faces? – Isidre Mas Magre Jan 06 '20 at 09:48
  • @IsidreMasMagre You could try changing the viewing geometry of the plot using `ax.view_init()` like in [this answer](https://stackoverflow.com/a/12905458/10659910) and [this demo](https://matplotlib.org/gallery/mplot3d/rotate_axes3d.html) – William Miller Jan 06 '20 at 15:44