简体   繁体   中英

Extend a 2D plot to 3D

I'm trying to show my 2D data on a 3D space.

Here is my code below:

import numpy as np
import matplotlib.pyplot as plt

i = 60
n = 1000
r = 3.8   
eps = 0.7

y = np.ones((n, i))

# random numbers on the first row of array x
np.random.seed(1)
x = np.ones((n+1, i))
x[0, :] = np.random.random(i)


def logistic(r, x):
    return r * x * (1 - x)

present_indi = np.arange(i)        
next_indi = (present_indi + 1) % i
prev_indi = (present_indi - 1) % i  

for n in range(1000):

    y[n, :] = logistic(r, x[n, :])

    x[n+1, :] = (1-eps)*y[n, present_indi] + 0.5*eps*(y[n, prev_indi] + y[n, next_indi])  
#print(x)

# the above logic generates a 2D array 'x'. with i columns and n rows.    


fig, ax = plt.subplots()
for i in range(60):
       for n in range(1000):
           if n>=900:
                ax.plot(i,x[n,i],'*k',ms=0.9)
plt.xlabel('i')
plt.ylabel('x')
plt.title('test')        
plt.show()

The above code perfectly displays i and x graph. I have plotted all the elements of 1st column of X, then all elements of second column, then the third and so on....., using the nested for loop logic (refer to the code)

Now what I need to do is, extend the plotting to 3D, ie use Xaxis = i, Yaxis= n, Zaxis= array 'x'

I want to plot something like this: 像这样的东西

I know I have to use mplot3D But doing the following won't give me any result:

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for i in range(60):
       for n in range(1000):
           if n>=900:
                ax.plot_wireframe(i,n,x[n,i],rstride=1,cstride=1)

Plotting 3d images in matplotlib is a little tricky. Generally you plot whole surfaces at once instead of plotting one line at a time. You do so by passing three 2d arrays, one for each position dimension (x, y, z). But you can't just pass any old 2d arrays either; the points themselves have to be in a precise order!

Sometimes you can do something that just works, but I find it easier to explicitly parameterize plots using u and v dimensions. Here's what I was able to get working here:

# Abstract u and v parameters describing surface coordinates
u_plt = np.arange(x.shape[1])
v_plt = np.arange(x.shape[0])

# The outer products here produce 2d arrays. We multiply by
# ones in this case for an identity transformation, but in 
# general, you could use any broadcasted operation on `u`
# and `v`.
x_plt = np.outer(np.ones(np.size(v_plt)), u_plt)
y_plt = np.outer(v_plt, np.ones(np.size(u_plt)))

# In this case, our `x` array gives the `z` values directly.
z_plt = x

fig = plt.figure(figsize=(16, 10))
ax = fig.add_subplot(111, projection='3d')

ax.set_zmargin(1)  # Add a bit more space around the plot.
ax.plot_wireframe(x_plt, y_plt, z_plt,
                  rstride=1, cstride=1,  # "Resolution" of the plot
                  color='blue', linewidth=1.0,
                  alpha=0.7, antialiased=True)

# Tilt the view to match the example.
ax.view_init(elev = 45, azim = -45)

plt.xlabel('i')
plt.ylabel('x')
plt.title('test')
plt.show()

And here's the resulting image. I had to reduce n to 80 to make this comprehensible at all, and I have no idea what I am looking at, so I am not sure it's correct. But I think it looks broadly similar to the example you gave.

线框图

Just to illustrate the power of this approach, here's a nautilus shell. It uses a two-stage parameterization, which could be compressed, but which I find conceptually clearer:

n_ticks = 100

# Abstract u and v parameters describing surface coordinates
u_plt = np.arange(n_ticks // 2) * 2
v_plt = np.arange(n_ticks)

# theta is the angle along the leading edge of the shell
# phi is the angle along the spiral of the shell
# r is the distance of the edge from the origin
theta_plt = np.pi * ((u_plt / n_ticks) * 0.99 + 0.005)
phi_plt = np.pi * v_plt / (n_ticks / 5)
r_plt = v_plt / (n_ticks / 5)

# These formulas are based on the formulas for rendering
# a sphere parameterized by theta and phi. The only difference
# is that r is variable here too.
x_plt = r_plt[:, None] * np.cos(phi_plt[:, None]) * np.sin(theta_plt[None, :])
y_plt = r_plt[:, None] * np.sin(phi_plt[:, None]) * np.sin(theta_plt[None, :])
z_plt = r_plt[:, None] * \ 
    (np.ones(np.shape(phi_plt[:, None])) * np.cos(theta_plt[None, :]))

# This varies the color along phi
colors = cm.inferno(1 - (v_plt[:, None] / max(v_plt))) * \
    np.ones(np.shape(u_plt[None, :, None])) 

fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(111, projection='3d')

ax.set_zmargin(1)
ax.plot_surface(x_plt, y_plt, z_plt,
                rstride=1, cstride=1,
                facecolors=colors, linewidth=1.0,
                alpha=0.3, antialiased=True)
ax.view_init(elev = 45, azim = -45)

plt.show()

鹦鹉螺壳图

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM