Black Lives Matter. Please consider donating to Black Girls Code today.
Learn how to use COVID-19 data in open source Dash apps. Register for the Sept 23rd webinar with IQT!

Surface plot with hex- or rgb-specified colors

I am trying to produce a 3D surface plot with colours specified for each z point. I have x, y and z specified as 100x100 arrays, and I also have a 100x100 array of colours in hex format (hexcols) that I would like to use.

p<- plotly(x = x, y = y, z = z, surfacecolor = hexcols, type=“surface”)

does not work (it produces a surface in a uniform colour).
I can produce a greyscale version of what I want with:

greycols <- array(rowSums(t(col2rgb(hexcols)[,1:3]), dim=dim(x)) / 3
p <- plotly(x = x, y = y, z = z, surfacecolor = greycols, type="surface")

but I really need it to be in full colour. The surface represents output from an optical model that simulates ocean colour (as true colour) mapped onto a 3D surface that represents the surface elevation of the water. Any help gratefully accepted!

Update: For my second attempt, I thought it might help to define my own colour scale with a hex value assigned to each unique colour that I need. Because using the full 0…255 colour scales causes me to run out of memory, I started by reducing the palette to a 0…16 scale for each colour. Thus:

red <- col2rgb(hexcol)[1,]
green <- col2rgb(hexcol)[2,]
blue <- col2rgb(hexcol)[3,]
col16 <- round(red/16)*10000 + round(green/16)*100 + round(blue/16)
col16 <- array(col16, dim=dim(hexcol))

Then set up the new colorscale:

count <- 0
for (i in seq(0,16,length.out=17)) {
    for (j in seq(0,16,length.out=17)) { 
         for (k in seq(0,16,length.out=17)) {
 	     count <- count+1
 	     cscale[[count]] <- c(i*10000+j*100+k, rgb(i,j,k,maxColorValue=16))
 	 }
   }
 }

Finally:

plot_ly(x = x, y = y, z = z, 
            surfacecolor = col16,
            colorscale = cscale,
            type = "surface")

Sadly, this still gives me only a greyscale image! Again, any tips would be much appreciated!
My only other idea at this stage feels rather desperate: produce separate red, green and blue plots in plotly, save them all as PNGs, load them back into R as raster images, and combine the images to produce a new (non-interactive) colour plot.

Usually a surface of equation z=f(x,y) is colored according to its z-values. When you want to change this rule, you should set the surfacecolor key. In your case the surfacecolor should be a 100x100 array , S, of numerical values (not color codes). The corresponding surface is then colored with a colorscale, according to the values in S. A Plotly surface cannot be colored when you give the color code for each point, as you did.

It should be clear from my first greyscale example that I had already figured out how to use surfacecolor using numerical values, but that this does not produce the truecolor plot that I need. So your answer is simply “you cannot do what you want to do in plotly.” Is this official, or an opinion?

I’m not working with R, hence I understood only your problem, not your posted code. And yes, I stress again: