21

I'd like to do a scatter plot with 2 categories of the data, one plotted in yellow and one in blue, and them showing up in green where they overlay (or any other combination). I've found that things are a little more difficult even with transparency. The colour of the graph is influenced by whether the last point plotted in a space was blue or yellow.

For example with the following code:

col1 <- rgb(red = .0, green = 0, blue = 0.8, alpha = 0.8)
col2 <- rgb(red = .8, green = 0.8, blue = 0, alpha = 0.8)
circle <- data.frame(x = c(0.2,0), 
                    y = c(0,0),
                    col = c(col1, col2),
                    stringsAsFactors = F)
orders <- c(1,2)
plot(x = circle$x[orders], y = circle$y[orders],
     col = circle$col[orders], pch = 19, cex = 100, xlab = "", ylab = "")

Depending on how you set the vector orders (which sets up which way round the two large points are drawn) you get different results: enter image description here

And if you swap the order in which you plot the two circles round you get: enter image description here

Either way, I was anticipating mixing the colours to get a green. Is there a way to do this? Thanks!

Edit - the two plots were made using the pdf device. I've also tried running the code through tikzDevice to see if that worked but it didn't.

Community
  • 1
  • 1
Andrew
  • 602
  • 7
  • 10
  • The package `colorspace` has a function `mixcolor` that will calculate the value of such a mixed colour: http://cran.r-project.org/web/packages/colorspace/colorspace.pdf. I don't know of a way of doing this directly - my solutions to this problem has been to find a different way of visualising the data, e.g. with `hexbin`, using `facets` or calculating a net score at each point. – Andrie Nov 25 '11 at 14:21
  • 2
    This is not really an answer, but you could look at http://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending -- I'm assuming that the different devices (PDF, tikzDevice, PNG etc.) are all using variations on this algorithm to determine overlaid colours, and it might help you understand what's going on. – Ben Bolker Nov 25 '11 at 15:27
  • 1
    In particular, I've figured out from poking around with those formulae a bit that alpha-blending is not commutative (in fact, as the article points out, in some cases it's not associative either, although that doesn't matter here because you're only combining two colours) -- which explains your "order matters" results above. – Ben Bolker Nov 25 '11 at 15:54
  • I just tried this to a postscript() device and the circles didn't overlap! That's what you get for using cex and no proper device size... Increasing cex fixes it. Anyway, postscript device cant handle transparency and just overprints. Hmmm. I think not (easily) possible. – Spacedman Nov 25 '11 at 15:59
  • @ Andrie - thanks for the advice re - colorspace. – Andrew Nov 25 '11 at 16:15
  • @Ben - I'll have to think about alpha blending some more. – Andrew Nov 25 '11 at 16:15
  • @spacedman - sorry for not putting in a device size. I agree doesn't seem easy. – Andrew Nov 25 '11 at 16:15
  • 2
    This was also discussed on R-help some time ago, with interesting contributions from R-core members: http://www.mail-archive.com/r-help@r-project.org/msg83970.html – baptiste Nov 25 '11 at 20:35
  • One more comment: following @baptiste's comments, I found Duncan Murdoch suggesting that the alpha-blending was doing *averaging* of *additive* colours. If my logic is right, that means we can **never** get pure green from a mixture of yellow (red/green mixture in additive space) and blue (blue in additive space) -- we can only get something between pure yellow and pure blue that is almost a muddy green in the middle – Ben Bolker Nov 25 '11 at 21:44

1 Answers1

5

The help file for the pdf() device says the default setting for background is "transparent", although that does not seem to be its behavior in practice, perhaps because viewers assume a white background or perhaps because the default for the plot function is "white". The middle section first becomes a color that is an equal blend of white and green, and second second you then add to it the blue. So I'm guessing that the math would predict an rgb value of (0.5, 0.5, (0.5+0.8)/2 ) followed by blending that mixture with the overlayed color And I think the white+col1 gets added in equal proportions to the values from col2 which makes the math non-commutative. At any rate the end result will probably be different if you can force the background to "transparent". The default behavior is more like mixing paints than like shining theater lights.

The PDF color model is described in http://www.adobe.com/devnet/pdf/pdf_reference.html and will determine what you can expect from a pdf device (but not necessarily what a viewer will provide).

I tested my theory that the white background was the problem (and appear to have disproved it) by changing the background to "black" in hopes that there would be no added values to the layered rgb vectors:

pdf("testfil12rev.pdf", bg="black")
 col1 <- rgb(red = .0, green = 0, blue = 1, alpha = 0.5)
 col2 <- rgb(red = 1, green = 0, blue = 0, alpha = 0.5)
 circle <- data.frame(x = c(0.2,0), 
                     y = c(0,0),
                     col = c(col1, col2),
                     stringsAsFactors = F)
 orders <- c(1,2)
plot(x = circle$x[orders], y = circle$y[orders], bg="black",
      col = circle$col[orders], pch = 19, cex = 100, xlab = "", ylab = "")

 dev.off()

Reversing the 'orders' indicator does NOT result in the same blended color with a black background, either.

EDIT: There is a prior SO posting with the rules for blending colors and alphas: How to calculate an RGB colour by specifying an alpha blending amount?

Community
  • 1
  • 1
IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • thanks for the reference. I'll try experimenting with the transparent settings. – Andrew Nov 25 '11 at 16:15
  • I tried transparent settings (`png("tmp.png", bg="transparent")`) and it does change things (and will probably help with any exploration by removing a factor), but the results are still non-commutative and still don't correspond to the naive expectations (blue+yellow=green) as stated above. – Ben Bolker Nov 25 '11 at 17:27