I need to plot a 2d streamline in 3d view like this. As suggested by the post, I need to extract streamlines and arrows from a 2d plot and then transform it to 3d data. How
this example should get you started:
import matplotlib.pyplot as plt
import numpy as np
fig_tmp, ax_tmp = plt.subplots()
x, y = np.mgrid[0:2.5:1000j, -2.5:2.5:1000j]
vx, vy = np.cos(x - y), np.sin(x - y)
res = ax_tmp.streamplot(x.T, y.T, vx, vy, color='k')
fig_tmp.show()
# extract the lines from the temporary figure
lines = res.lines.get_paths()
#for l in lines:
# plot(l.vertices.T[0],l.vertices.T[1],'k')
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for line in lines:
old_x = line.vertices.T[0]
old_y = line.vertices.T[1]
# apply for 2d to 3d transformation here
new_z = np.exp(-(old_x ** 2 + old_y ** 2) / 4)
new_x = 1.2 * old_x
new_y = 0.8 * old_y
ax.plot(new_x, new_y, new_z, 'k')
this generates an intermediate temporary figure:
from which the lines are extracted. Then you apply your 2d to 3d point transformation of your liking, and plot the same lines in a new 3d figure:
pyplot.streamplot returns "lines" and "arrows".
"Lines" consists of series of pair of interpolated points(in x,y given in streamplot) from streamplot function. One particular streamline starts with a seed point (uniformly distributed I guess) and ends when integrator inside streamline gives same pair of points more than 5 times. Then it choose next seed and repeat the procedure.
"arrows" are actually information about the patch object with edge points measured by the fig(gca) unlike "lines" . That is why if you get res.arrows.get_paths() and plot vertices of it it runs from zero to (figsize[0]-2)*dpi and (figsize[1]-2)*dpi.
In principle one can invert the logic back and get the arrow. But I think that would be tedious. So better way would be, get all the segments of a particular streamline from "lines". Map to 3d and draw 3d-arrow using one or more segments, depending upon the arrow density you want.
Conditions to get individual streamlines from "lines" is. 1. New streamline if all the four points of two consecutive segments differ. 2. End of a streamline if all the four points of two consecutive segments are same for more than 5 consecutive pairs.
A naive solution might be
fig = figure(figsize=(8,6), dpi =160)
ax = fig.add_subplot(111, projection='3d' )
i = 0
for line in lines:
i += 1
old_x = line.vertices.T[0]
old_y = line.vertices.T[1]
# apply for 2d to 3d transformation here
new_z = np.exp(-(old_x ** 2 + old_y ** 2) / 4)
new_x = 1.2 * old_x
new_y = 0.8 * old_y
ax.plot(new_x, new_y, new_z, 'k')
if i%10 ==1:
ax.quiver(new_x[0],new_y[0],new_z[0],new_x[0]-new_x[1],new_y[0]-new_y[1],new_z[0]-new_z[1], length=0.2)