简体   繁体   中英

Python - 2/3D scatter plot with surface plot from that data

Using: [python] [numpy] [matplotlib] So I have a 3D array to create a scatter plot making an * n * n cube. Those points have different values of potential represented by colors. 您可以在此处查看结果。

size = 11
z = y = x = size
potential = np.zeros((z, y, x))                                                
Positive = 10
Negative = -10

""" ------- Positive Polo --------- """                                        
polox = poloy = poloz = [1,2]
polos=[polox,poloy,poloz]
polop = [list(x) for x in np.stack(np.meshgrid(*polos)).T.reshape(-1,len(polos))] # Positive polos list

for coord in polop:
    potential[coord] = Positive

""" ------- Negative Polo --------- """                                        
polo2x = polo2y = polo2z = [size-3,size-2]
polos2=[polo2x,polo2y,polo2z]
polon = [list(x) for x in np.stack(np.meshgrid(*polos2)).T.reshape(-1,len(polos2))] # Negative polos list

for coord in polon:
    potential[coord] = Negative

I have 2 polos of values -10 and 10 at the start and the rest of the points are calculated like this: (the mean of the surrounding points, no diagonals):

for z in range(1,size):
    for y in range(1,size):
        for x in range(1,size):
            if [z,y,x] in polop:
                potential[z,y,x] = Positive                                # If positive polo, keeps potential
            elif [z,y,x] in polon:
                potential[z,y,x] = Negative                                # If negative polo, keeps potential
            elif z!=size-1 and y!=size-1 and x!=size-1:                    # Sets the potential to the mean potential of neighbors
                potential[z][y][x] = (potential[z][y][x+1] + potential[z][y][x-1] + potential[z][y+1][x] + potential[z][y-1][x] + potential[z+1][y][x] + potential[z-1][y][x]) / 6

And for the outer cells:

for z in range(0,size):
        for y in range(0,size):
            for x in range(0,size):
                potential[z,y,0] = potential[z,y,2]
                potential[z,0,x] = potential[z,2,x]
                potential[0,y,x] = potential[2,y,x]
                if z == size-1:
                    potential[size-1,y,x] = potential[size-3,y,x]
                elif y == size-1:
                    potential[z,size-1,x] = potential[z,size-3,x]
                elif x == size-1:
                    potential[z,y,size-1] = potential[z,y,size-3]

What I need is to show a surface connecting the points that have the same value interval 'same colors' (like from 0 to 2.5).

I know that there are a lot of questions like this, but I can't adapt to my code, it either doesn't show (such as this ) or it's not the same problem or it's not with python (as this one ), that's why I'm asking again. It can also be shown as a lot of subplots each with a surface.

Note: My 3D array is such that if I type print(potential[1,1,1]) it shows the value of that cell that, as you can see in the image below, is 10. And that's what I use to show the colors.

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
z,y,x = potential.nonzero()
cube = ax.scatter(x, y, z, zdir='z', c=potential[z,y,x], cmap=plt.cm.rainbow)  # Plot the cube
cbar = fig.colorbar(cube, shrink=0.6, aspect=5)                                # Add a color bar which maps values to colors.

It would be beneficial for you to create a Minimum, Complete and Verifiable Example to make assistance easier.

It's still not clear to me how you mean to calculate your potential, nor how you mean to generate your surface, so I have included trivial functions.

The code below will generate a 3D Scatterplot of coloured points and a Surface with the average value of the colour.

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

def fn(x, y):
    """Custom fuction to determine the colour (potential?) of the point"""
    return (x + y) / 2  # use average as a placeholder

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

size = 11  # range 0 to 10
# Make the 3D grid
X, Y, Z = np.meshgrid(np.arange(0, size, 1),
                      np.arange(0, size, 1),
                      np.arange(0, size, 1))

# calculate a colour for point(x,y,z)
zs = np.array([fn(x, y) for x, y in zip(np.ravel(X), np.ravel(Y))])
ZZ = zs.reshape(X.shape)  # this is used below

# create the surface
xx, yy = np.meshgrid(np.arange(0, size, 1), np.arange(0, size, 1))
# Calcule the surface Z value, e.g. average of  the colours calculated above
zzs = np.array([np.average(ZZ[x][y]) for x, y in zip(np.ravel(xx), np.ravel(yy))])
zz= zzs.reshape(xx.shape)

cube = ax.scatter(X, Y, Z, zdir='z', c=zs, cmap=plt.cm.rainbow)
surf = ax.plot_surface(xx, yy, zz, cmap=plt.cm.rainbow) 
cbar = fig.colorbar(cube, shrink=0.6, aspect=5) # Add a color bar

plt.show()

The image generated will look something like this: 3D散射和表面

EDIT: With your additional code, I'm able to replicate your cube.

Then use the following code to generate a surface:

xx, yy = np.meshgrid(np.arange(0, size, 1), np.arange(0, size, 1))
#define potential range
min_p = 1.0
max_p = 4.0

zz = np.zeros((size, size))
for i in range(size):  # X
    for j in range(size):  # Y
        for k in range(size):  # Z
            p = potential[k,j,i]
            if min_p < p < max_p:
                zz[j][i] = p # stop at the first element to meet the conditions
                break # break to use the first value in range

Then to plot this surface:

surf = ax.plot_surface(xx, yy, zz, cmap=plt.cm.rainbow) 

Note: include vmin and vmax keyword args to keep the same scale, I've left those out so the surface deviations are more visible. I also set the alpha on the cube to 0.2 to make it easier to see the surface.

具有Surface Take 2的多维数据集图

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