Sigbert Klinke
2023-Feb-23 09:36 UTC
[R] Palettes {grDevices} - wrong number of colors returned?
Hi, I would have expected that I get always 3 colors as result which is not true: hcl.colors(3, alpha=c(0, 0.5, 1)) # 3 colors rainbow(3, alpha=c(0, 0.5, 1)) # 3 colors heat.colors(3, alpha=c(0, 0.5, 1)) # 3 colors terrain.colors(3, alpha=c(0, 0.5, 1)) # 6 colors cm.colors(3, alpha=c(0, 0.5, 1)) # 6 colors topo.colors(3, alpha=c(0, 0.5, 1)) # 9 colors R-Version and platform: R version 4.2.2 Patched (2022-11-10 r83330) -- "Innocent and Trusting" Copyright (C) 2022 The R Foundation for Statistical Computing Platform: x86_64-pc-linux-gnu (64-bit) Bug or feature? Sigbert -- https://hu.berlin/sk https://www.stat.de/faqs https://hu.berlin/mmstat https://hu.berlin/mmstat-ar
Duncan Murdoch
2023-Feb-23 11:04 UTC
[R] Palettes {grDevices} - wrong number of colors returned?
On 23/02/2023 4:36 a.m., Sigbert Klinke wrote:> Hi, > > I would have expected that I get always 3 colors as result which is not > true: > > hcl.colors(3, alpha=c(0, 0.5, 1)) # 3 colors > > rainbow(3, alpha=c(0, 0.5, 1)) # 3 colors > > heat.colors(3, alpha=c(0, 0.5, 1)) # 3 colors > > terrain.colors(3, alpha=c(0, 0.5, 1)) # 6 colors > > cm.colors(3, alpha=c(0, 0.5, 1)) # 6 colors > > topo.colors(3, alpha=c(0, 0.5, 1)) # 9 colors > > R-Version and platform: > R version 4.2.2 Patched (2022-11-10 r83330) -- "Innocent and Trusting" > > Copyright (C) 2022 The R Foundation for Statistical Computing > > Platform: x86_64-pc-linux-gnu (64-bit) > > Bug or feature?Looks like a bug to me, they should all be length 3. The reason it happens in terrain.colors (I didn't look at the others) is that it breaks the range into two parts, and relies on the number of values of the parameters in each part to get the length, but passes the full alpha vector in: terrain.colors <- function (n, alpha, rev = FALSE) { if ((n <- as.integer(n[1L])) > 0) { k <- n%/%2 h <- c(4/12, 2/12, 0/12) s <- c(1, 1, 0) v <- c(0.65, 0.9, 0.95) cols <- c(hsv(h = seq.int(h[1L], h[2L], length.out = k), s = seq.int(s[1L], s[2L], length.out = k), v = seq.int(v[1L], v[2L], length.out = k), alpha = alpha), hsv(h = seq.int(h[2L], h[3L], length.out = n - k + 1)[-1L], s = seq.int(s[2L], s[3L], length.out = n - k + 1)[-1L], v = seq.int(v[2L], v[3L], length.out = n - k + 1)[-1L], alpha = alpha)) if(rev) rev(cols) else cols } else character() } A bug fix would be to recycle alpha to the right length and only pass in portions of it, e.g. terrain.colors <- function (n, alpha, rev = FALSE) { if ((n <- as.integer(n[1L])) > 0) { alpha <- rep_len(alpha, length.out = n) k <- n%/%2 h <- c(4/12, 2/12, 0/12) s <- c(1, 1, 0) v <- c(0.65, 0.9, 0.95) cols <- c(hsv(h = seq.int(h[1L], h[2L], length.out = k), s = seq.int(s[1L], s[2L], length.out = k), v = seq.int(v[1L], v[2L], length.out = k), alpha = alpha[seq_len(k)]), hsv(h = seq.int(h[2L], h[3L], length.out = n - k + 1)[-1L], s = seq.int(s[2L], s[3L], length.out = n - k + 1)[-1L], v = seq.int(v[2L], v[3L], length.out = n - k + 1)[-1L], alpha = alpha[seq_len(n - k) + k])) if(rev) rev(cols) else cols } else character() } I'd guess the same sort of approach would fix cm.colors and topo.colors. Duncan Murdoch
Achim Zeileis
2023-Feb-23 11:06 UTC
[R] Palettes {grDevices} - wrong number of colors returned?
Thanks, Sigbert, good catch. The reason that this happens is the following: rainbow(), heat.colors(), terrain.colors(), cm.colors(), and topo.colors() are all just front-ends to calls to hsv() for Hue-Saturation-Value colors. (BTW: This is also the main reason why they yield palettes with rather poor perceptual properties.) All of the palette functions just pass on the alpha argument to all hsv(..., alpha=alpha) calls. And in each case if the length of alpha and the number of colors does not match the shorter element is recycled to the length of the longer one. Thus, if n == length(alpha), as in your example, then those functions that can generate all colors with a single call of hsv() do the right thing (rainbow and heat.colors). Those, that need two hsv() calls yield 2 * n colors (cm.colors and terrain.colors). And in topo.colors() where three hsv() calls are used we get 3 * n colors. My suggested solution would be to do something like alpha <- rep_len(alpha, n) early on in the palette functions and then assure that the correct elements of alpha are passed to hsv(). The same should be done in those functions that work correctly for n = length(alpha) because it will assure that we always get n colors and not more. For example, the case with n < length(alpha) is also unexpected: hcl.colors(2, alpha = c(0, 0.25, 0.5, 0.75, 1)) ## [1] "#4B005500" "#FDE33340" "#4B005580" "#FDE333BF" "#4B0055FF" Or even worse: gray.colors(2, alpha = c(0, 0.25, 0.5, 0.75, 1)) ## Error in gray(seq.int(from = start^gamma, to = end^gamma, length.out = n)^(1/gamma), : ## attempt to set index 2/2 in SET_STRING_ELT If someone from R Core thinks that my proposed strategy is a good way forward, I'm happy to work on a patch. Sigbert, if you are looking for a solution: (1) Don't use heat.colors, terrain.colors, topo.colors, cm.colors, they are all quite terribel ;-) (2) If you really want to use them, put on the alpha afterwards, e.g., using colorspace::adjust_transparency: colorspace::adjust_transparency(topo.colors(3), alpha = c(0, 0.5, 1)) ## [1] "#4C00FF00" "#00FF4D80" "#FFFF00FF" hth, Achim On Thu, 23 Feb 2023, Sigbert Klinke wrote:> Hi, > > I would have expected that I get always 3 colors as result which is not true: > > hcl.colors(3, alpha=c(0, 0.5, 1)) # 3 colors > > rainbow(3, alpha=c(0, 0.5, 1)) # 3 colors > > heat.colors(3, alpha=c(0, 0.5, 1)) # 3 colors > > terrain.colors(3, alpha=c(0, 0.5, 1)) # 6 colors > > cm.colors(3, alpha=c(0, 0.5, 1)) # 6 colors > > topo.colors(3, alpha=c(0, 0.5, 1)) # 9 colors > > R-Version and platform: > R version 4.2.2 Patched (2022-11-10 r83330) -- "Innocent and Trusting" > > Copyright (C) 2022 The R Foundation for Statistical Computing > > Platform: x86_64-pc-linux-gnu (64-bit) > > Bug or feature? > > Sigbert > > -- > https://hu.berlin/sk > https://www.stat.de/faqs > https://hu.berlin/mmstat > https://hu.berlin/mmstat-ar > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >
Possibly Parallel Threads
- Palettes {grDevices} - wrong number of colors returned?
- Palettes {grDevices} - wrong number of colors returned?
- Palettes {grDevices} - wrong number of colors returned?
- legend: interplay between title and y.intersp
- Palettes {grDevices} - wrong number of colors returned?