0

My question is how to match RGB color with the colorbar. The input data is normalized to put in color.

My project is to represents the local indoor CO2 concentration, so I first made a cube with the help of the site below.

python draw parallelepiped

In sample code, the RGB color corresponds the random sampled coordinates.Later, the concentration is added and normalized to corresponds to color. My terminal goal is to represent cubes like this. enter image description here

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection

def plot_cube(cube_definition):
    cube_definition_array = [
        np.array(list(item))
        for item in cube_definition
    ]

 points = []
    points += cube_definition_array
    vectors = [
        cube_definition_array[1] - cube_definition_array[0],
        cube_definition_array[2] - cube_definition_array[0],
        cube_definition_array[3] - cube_definition_array[0]
    ]

    points += [cube_definition_array[0] + vectors[0] + vectors[1]]
    points += [cube_definition_array[0] + vectors[0] + vectors[2]]
    points += [cube_definition_array[0] + vectors[1] + vectors[2]]
    points += [cube_definition_array[0] + vectors[0] + vectors[1] + vectors[2]]

    points = np.array(points)

    edges = [
        [points[0], points[3], points[5], points[1]],
        [points[1], points[5], points[7], points[4]],
        [points[4], points[2], points[6], points[7]],
        [points[2], points[6], points[3], points[0]],
        [points[0], points[2], points[4], points[1]],
        [points[3], points[6], points[7], points[5]]
    ]
     faces = Poly3DCollection(edges, linewidths=1, edgecolors='k')

    faces.set_facecolor(cube_definition[0])
    ax.add_collection3d(faces)



data_number = 20
pre_data = np.random.random((data_number,3))

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlim(-1,2.2) 
ax.set_ylim(-1,2.2)
ax.set_zlim(-1,2.2)
ax.set_ylabel(r'y')  
ax.set_xlabel(r'x')  
ax.set_zlabel(r'z')
p= ax.scatter(pre_data[:,0], pre_data[:,1], pre_data[:,2] ,s=0, c=pre_data)
fig.colorbar(p)
for i in range(0,data_number):
    data = [pre_data[i],pre_data[i]+(0,1,0),pre_data[i]+(0,0,1),pre_data[i]+(1,0,0)]    
    plot_cube(data)

enter image description here

============================== I did

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
import matplotlib.colorbar as cbar
from matplotlib import cm
from pylab import get_cmap
import matplotlib as mpl

def edges(crd):

delta = 0.5
start_crd= crd - (delta, delta, delta)

cube_definition_array = [
    start_crd,start_crd+(0,delta,0),start_crd+(0,0,delta),start_crd+(delta,0,0)
]

points = []
points += cube_definition_array
vectors = [
    cube_definition_array[1] - cube_definition_array[0],
    cube_definition_array[2] - cube_definition_array[0],
    cube_definition_array[3] - cube_definition_array[0]
]

points += [cube_definition_array[0] + vectors[0] + vectors[1]]
points += [cube_definition_array[0] + vectors[0] + vectors[2]]
points += [cube_definition_array[0] + vectors[1] + vectors[2]]
points += [cube_definition_array[0] + vectors[0] + vectors[1] + vectors[2]]

points = np.array(points)

edges = [
    [points[0], points[3], points[5], points[1]],
    [points[1], points[5], points[7], points[4]],
    [points[4], points[2], points[6], points[7]],
    [points[2], points[6], points[3], points[0]],
    [points[0], points[2], points[4], points[1]],
    [points[3], points[6], points[7], points[5]]
]
return edges

data_number = 20
pre_data = np.random.random((data_number,3)) # coordinate
concentration = np.linspace(0,20, data_number)

def plot_cube(crd, concentration):
    norm = mpl.colors.Normalize(vmin=-1, vmax=1)
    norm_c = norm(concentration)
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    for i in range(0,len(crd)):
        faces = Poly3DCollection(edges(crd[i]), linewidths=1, edgecolors='k', alpha=0.3)
        viridis = cm.get_cmap('viridis')
        color = viridis(np.linspace(0,1,data_number))
        faces.set_facecolor(color[i])
        ax.add_collection3d(faces)
    img = ax.scatter(crd[0:,0], crd[0:,1],crd[0:,2], c=concentration, s=0)
    ax.set_xlim(-2,2) #background range
    ax.set_ylim(-2,2)
    ax.set_zlim(-2,2)
    ax.set_ylabel(r'y')  # background label
    ax.set_xlabel(r'x')  
    ax.set_zlabel(r'z')
    faces.set_clim([min(concentration),max(concentration)])
    fig.colorbar(img)
    plt.show()
Galois
  • 1
  • 2
  • rather than setting the RGB, you probably want to calculate them from a norm + colormap. – Jody Klymak Aug 11 '21 at 05:15
  • @JodyKlymak Yes. However, the input of faces.set_facecolor has 3 variables since this function represents RGB. – Galois Aug 11 '21 at 05:36
  • Then what do you expect the colorbar to show? Colorbars are a 1-D mapping – Jody Klymak Aug 11 '21 at 14:46
  • @JodyKlymak In this code, set_facecolor receives 3D data to present RGB, (but also 4D to present RGBA.). However, colorbar is probably viridis color. I want facecolor be viridis too. 'code' – Galois Aug 12 '21 at 02:23
  • Cmap(norm(data)) returns the rgb values you are after. – Jody Klymak Aug 12 '21 at 03:41
  • @JodyKlymak I did!! I want to write my code here, but I don't know. So, I edited my question. Thank you for attention – Galois Aug 12 '21 at 08:39

0 Answers0