Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R plot with color gradient

Tags:

r

3d

Below is a 3D curve using the R function persp3d and specifying the colors.

library(rgl)

y = seq(-5,25,by=0.1)
x = seq(5,20,by=0.2)

NAs <- rep(NA, length(x)*length(y))
z <- matrix(NAs, length(x), byrow = T)
for(i in seq(1,length(x))) {
    for(j in seq(1,length(y))) {
        val = x[i] * y[j]
        z[i,j] = val
        if(z[i,j] < 0.02) {
            z[i,j] = NA
        }

    }
}

col <- rainbow(length(x))[rank(x)]

open3d()
persp3d(x,y,z,color=col,xlim=c(5,20),ylim=c(5,10),axes=T,box=F,xlab="X Axis",ylab="Y Axis",zlab="Z Axis")

And it produces this image:

enter image description here

In the current version, for an x value of 15, the color is blue regardless of the z value. But I'd like it so that high z values are dark blue whereas low z values are light blue, if that makes sense. How can I do something like this, so that color not only distinguishes x values but also z values?

like image 657
CodeGuy Avatar asked Dec 06 '25 08:12

CodeGuy


1 Answers

You will have to play around with colors in HSV format rather than RGB format for this. It's easier that way I think.

See my sample code below.

library(rgl)

y = seq(-5,25,by=0.1)
x = seq(5,20,by=0.2)

NAs <- rep(NA, length(x)*length(y))
z <- matrix(NAs, length(x), byrow = T)
for(i in seq(1,length(x))) {
  for(j in seq(1,length(y))) {
    val = x[i] * y[j]
    z[i,j] = val
    if(z[i,j] < 0.02) {
      z[i,j] = NA
    }

  }
}

Create unique color for each value of x.

col <- rainbow(length(x))[rank(x)]

Create grid of colors by repeating col length(y) times

col2 <- matrix(rep(col,length(y)), length(x))
for(k in 1:nrow(z)) {

  row <- z[k,]
  rowCol <- col2[k,]  
  rowRGB <- col2rgb(rowCol) #convert hex colors to RGB values
  rowHSV <- rgb2hsv(rowRGB) #convert RGB values to HSV values

  row[is.na(row)] <- 0
  v <- scale(row,center=min(row), scale=max(row)-min(row)) # scale z values to 0-1

  rowHSV['s',] <- v #update s or v values by our scaled values above
  # rowHSV['v',] <- v  # try changing either saturation or value i.e. either s or v

  newRowCol <- hsv(rowHSV['h',], rowHSV['s',], rowHSV['v', ]) #convert back to hex color codes
  col2[k,] <- newRowCol #Replace back in original color grid
}

open3d()
persp3d(x,y,z,color=col2,xlim=c(5,20),ylim=c(5,10),axes=T,box=F,xlab="X Axis",ylab="Y Axis",zlab="Z Axis")

This should give following. You can play around scaling of saturation or value of colors to get desired "lightness" or "darkness" of shades.

enter image description here

like image 192
CHP Avatar answered Dec 08 '25 20:12

CHP