0

I have a problem very similar to this question. The answer works very well for plotting the voxels. However, I need to find a way to colour the voxels according to a colormap (of type 'jet') which is based on the 5x1 array called "variable". I also need to associate a logarithmic colorbar with that 3D plot.

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Leonardo
  • 11
  • 3

1 Answers1

1

I added two changes to the problem conditions:

  1. The voxels are rectangular prisms of custom dimensions (a,b,c) instead of simple cubes.
  2. Instead of "variable", i defined an array called "Ivec", which has more suitable values ​​for displaying the logarithmic colormap.

If one wants to display a linear colormap, he/she can simply uncomment the line commented as "linear scale colormap" and comment/delete the line commented as "log scale colormap"

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

df = pd.DataFrame({"x": [14630, 14630, 14360, 14360, 14360], "y" : [21750, 21770, 21790, 21930, 21950], "z" : [4690, 4690, 4690, 5290, 5270]})
Ivec = np.array([1, 10, 100, 1000, 10000])


def get_cube():   
    phi = np.arange(1,10,2)*np.pi/4
    Phi, Theta = np.meshgrid(phi, phi) 

    x = np.cos(Phi)*np.sin(Theta)
    y = np.sin(Phi)*np.sin(Theta)
    z = np.cos(Theta)/np.sqrt(2)
    return x,y,z


fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
a = 25
b = 8
c = 14

ax.view_init(azim=0, elev=0)
cm = plt.get_cmap('jet')
#cNorm = matplotlib.colors.Normalize(vmin=min(Ivec), vmax=max(Ivec))#linear scale colormap
cNorm = matplotlib.colors.LogNorm(vmin=min(Ivec), vmax=max(Ivec)) #log scale colormap
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cm)
scalarMap.set_array(Ivec)
fig.colorbar(scalarMap, ax=ax)
cmapRgba=scalarMap.to_rgba(Ivec) 

for i in df.index:
    x,y,z = get_cube()
    
    # Change the centroid of the cube from zero to values in data frame
    x = x*a + df.x[i]
    y = y*b + df.y[i]
    z = z*c + df.z[i]
    ax.plot_surface(x, y, z, color = cmapRgba[i]) 
    ax.set_zlabel("z")

plt.xlabel("x")
plt.ylabel("y")
plt.show()

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Leonardo
  • 11
  • 3