Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib: Plot 3D curve on top of 3D surface

I'm trying to plot a 3D curve on top of a 3D surface in Matplotlib, but when the curve is in front of the surface, it is barely visible (the curve is the image of the unit circle): enter image description here There should be a green curve floating one unit above the surface.
If you look at it from the side, you can see the parts of the curve that are not in front of the surface (the small loops on the left and the right of central peak of the surface): enter image description here

Is there any way to get this working? I've tried white surfaces, with and without anti-aliasing, but no avail.

This is the code I'm using:

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

fig = plt.figure()
ax = fig.gca(projection='3d')

N = 5

# Make H surface
X = np.linspace(-1.25, 1.25, 1024)
Y = np.linspace(-1.25, 1.25, 1024)
X, Y = np.meshgrid(X, Y)
Z = 1/N * np.abs(1 - (X + Y*1j)**-N) / np.abs(1 - 1/(X + Y*1j))
Z = 20 * np.log10(Z)

# Make the image of the unit circle
omega = np.linspace(0, 2*np.pi, 2048)
circ_X = np.cos(omega)
circ_Y = np.sin(omega)
circ_Z = 1/N * np.sin(N*omega/2) / np.sin(omega/2)
circ_Z = 10 * np.log10(circ_Z**2) + 1

# Plot the H surface and the unit circle
surf = ax.plot_surface(X, Y, Z, cmap=cm.plasma, linewidth=0, antialiased=True)
circ = ax.plot(circ_X, circ_Y, circ_Z, color='green')

ax.set_zlim(-40, 10)
plt.show()
like image 500
tttapa Avatar asked Oct 15 '22 13:10

tttapa


People also ask

Are 3d graphs possible in matplotlib?

Matplotlib was introduced keeping in mind, only two-dimensional plotting. But at the time when the release of 1.0 occurred, the 3d utilities were developed upon the 2d and thus, we have 3d implementation of data available today! The 3d plots are enabled by importing the mplot3d toolkit.

Why is %Matplotlib inline?

The line magic command %matplotlib inline enables the drawing of matplotlib figures in the IPython environment. Once this command is executed in any cell, then for the rest of the session, the matplotlib plots will appear directly below the cell in which the plot function was called.


1 Answers

To answer my own question, I ended up using Mayavi:

#!/usr/bin/env python3

import mayavi.mlab as mlab
import numpy as np
import os

script_dir = os.path.dirname(os.path.realpath(__file__))

N = 5

max = 15
min = -60

# Make H surface
X = np.linspace(-1.5, 1.5, 1024 * 5)
Y = np.linspace(-1.5, 1.5, 1024 * 5)
X, Y = np.meshgrid(X, Y)
z = X + Y * 1j
Z = 1 / N * np.abs(1 - z**-N) / np.abs(1 - 1 / z)
Z = 20 * np.log10(Z)
Z[np.logical_or(Z > max, Z < min)] = np.nan
Z = Z / 40 + 0.6

# Make the image of the unit circle
omega = np.linspace(2 * np.pi / 2048, 2 * np.pi - 2 * np.pi / 2048, 2047)
circ_X = np.cos(omega)
circ_Y = np.sin(omega)
circ_Z = 1 / N * np.sin(N * omega / 2) / np.sin(omega / 2)
circ_Z = 10 * np.log10(circ_Z**2) + 0.1
circ_Z[np.logical_or(circ_Z > max, circ_Z < min)] = min
circ_Z = circ_Z / 40 + 0.6

# Plot the H surface and the unit circle
mlab.figure(size=(1080 * 2, 720 * 2),
            bgcolor=(1.0, 1.0, 1.0),
            fgcolor=(.6, .1, .1))
mlab.surf(-np.transpose(X),
          np.transpose(Y),
          np.transpose(Z),
          extent=[-1.5, 1.5, -1.5, 1.5, min / 40 + 0.6, max / 40 + 0.6],
          opacity=0.9,
          colormap='ocean')
mlab.plot3d(-circ_X, circ_Y, circ_Z, tube_radius=None)

view = (90.0, 60, 5, (0, 0, 0))
mlab.view(*view, reset_roll=True)

mlab.savefig(
    os.path.join(os.path.dirname(script_dir), f'images/SMA-H-surf-N{N}.png'))

Mayavi plot

like image 63
tttapa Avatar answered Oct 19 '22 01:10

tttapa