# Define RGB values for heatmap

Hi,

I would like to specify RGB values per each data point in a heatmap. Any hints on how this could be done?

The normal behaviour is that value of `z` (real numbers) is used to colour the pixel according to the specified `colormap`. What I’d ideally want is to be able to use 3-tuple (instead of a single number) to define the colour channels (i.e. override any colormap).

Use case: I have high dimensional data set on which I run Principal Component Analysis to get 3 primary components. These components will form my RGB values.

Hi @tracek, you can use the image trace for this, either with `go.Image` or with the plotly express function `px.imshow`. Please see the tutorial on image data, and if your values come from a home-made computation rather than an image file don’t forget to set the `zmin` and `zmax` parameters.

Hi @tracek

For me it’s not clear how do you intend to associate a heatmap to a 3d-space or an image following Emmanuelle’s suggestion.
You can associate r, g, b, values to each point, but how do you specify its position in a 2d array to define the image?

I can suggest the following path to using r,g, b for each projected point:
If u1, u2, u3 are the principal directions, represented by three unit vectors,
and each point `p` in your high dimensional space is projected orthogonally onto
the subspace generated by these vectors, then its projection is
`p' = x u1 +y u2 +z u3`.

Define the intervals:

`[a, b]=[min(x), max(x)], [c, e]=[min(y), max(y)], [e, f]=[min(z), max(z)]`
where x,y, respectively z run over all x, y, z coordinates of the projected points.
Then map each such interval onto the interval `[0, 255]`, by:

``````def mapping_interval(v, a, b):
if a >= b:
raise ValueError(f'a={a} must be less than b={b}')
if  v < a or v > b:
raise VallueError('...')
return int(255*(v-a)/(b-a)+0.5)
``````

In this way you can associate r, g, b values to each projected point, i.e. a color code.
Denoting by prx, pry, prz the lists of `p'` - point coordinates,
you can test this method with this example:

``````import numpy as np
import plotly.graph_objects as go

a, b = -20, 31
c, d = -16, 27
e, f = -24, 35

def mapping_interval(v, a, b):
if a >= b:
raise ValueError(f'a={a} must be less than b={b}')
if  v < a or v > b:
raise VallueError('...')
return int(255*(v-a)/(b-a)+0.5)

prx = np.random.randint(a, b, 25)
pry = np.random.randint(c, d, 25)
prz = np.random.randint(e, f, 25)
color = [f'rgb({mapping_interval(x, a, b)}, {mapping_interval(y, c, d)}, {mapping_interval(z, e, f)})'
for x,y,z in zip(prx, pry,prz)]
fig= go.Figure(go.Scatter3d(x=prx,
y=pry,
z=prz,
mode = 'markers',
marker_color =color,
marker_size=5,
hovertemplate ='x: %{x}<br>y: %{y}<br>z: %{z}<br>color: %{marker.color}'))
fig.update_layout(width=600, height=600)
``````

Here the position is given by the three coordinates with respect to u1, u2, u3. How do associate to each point a position in an image? Only the color is already assigned.

Thanks @Emmanuelle and @empet for the suggestions!

First, to answer your question: I know the position on the graph thanks to the ordering in the sequence. Essentially, each data point is a point in time. On the `heatmap`, I’d like to to display time of the day on the `x` axis and date on `y` axis. The 3 principal components calculated per point are then my RGB values.

Why `heatmap` specifically? It solves a lot of problems for me out of the box. I am grateful for suggesting how it could work on a scatter plot, but in my case it’d be rather meaningless. Going with `imshow` absolutely works, it’s just I need to spend much more time to make it behave like `heatmap`.

Thanks!
Lukasz