Can Plot use two colour scales in the same plot?

I am working with Plot’s raster mark and I would like to show two rasters in the same plot. But I need to use a different colour scheme for each raster. Is there a way of doing this in Plot?

I realise I could use a single custom colour scheme with part of it used for the values in raster 1 and the other part used for raster 2. This would involve transforming the values in raster 2 such that they don’t overlap with those in raster 1. But this feels rather hacky, and I’d hope for a more elegant solution.

What are the semantics of the two color schemes? As in, what are you trying to convey/represent with them?

Plot doesn’t support multiple color scales in the same plot. (Though there’s an open issue regarding this, mostly in the context of dual-axis charts where you might have two y scales.) But you could achieve this by partitioning the domain, or perhaps by using a diverging color scale. And you can always opt out of scales entirely and supplying literal colors directly, typically by setting the color scale type to identity but you can also turn it off for individual channels manually using a scale override or automatically if a channel’s values are all literal colors.

OK - thanks for the confirmation. Yes my ‘hacky’ solution involves partitioning the domain and range as you suggest.

The context is that I am trying to generate some cartographic quality output with Plot where I have a number of ‘layers’ that I’d like to encode with colour independently. I may try exploring identity/null scales and colour literals.

More generally, I think being able to specify some per-mark scales opens up some interesting expressive possibilities in addition to this use case (e.g. overlaying bar charts on maps).

1 Like

Quite pleased with progress so far. This uses the custom diverging colour scheme approach to store both hypsometric colours and shadows in the same colour scale (elevations as positive numbers, shading as negative). Contours calculated via Plot’s contour mark; lakes and rivers as separate geoJSON layers.

I will add an Observable doc on creating topographic map output with Plot soon…

1 Like

Beautiful! Thank you for sharing!

Document explaining the process now up here:

Incredible! Thank you for the write-up!

If you wanted to create the grays directly (as literals), you could write:

      Plot.raster(imhofRelief.values, {
        width: relief.nCols,
        height: relief.nRows,
        fill: d => d3.hcl(0, 0, d * 100).toString(),
        mixBlendMode: "luminosity"
      })

I also wonder how you would compute the eduard values in the notebook :slight_smile:

1 Like

Maybe a nicer way of framing this is by saying:

fill: d3.scaleLinear([0, 1], [“black”, “white”]),

or even simpler (in this simple case):

fill: d3.interpolate(“black”, “white”),

I think it conveys the intention better.

1 Like

Yes, I think your suggested approach of fill colour encoding functions would be a better than the one I originally proposed. I’ll update the topographic map page later. Semantically this makes sense in that the shaded relief component can be thought of as an intensity modifier of the coloured elevation raster.

In fact that would appear to answer my original question directly: You can have multiple colour schemes in the same plot by delegating colour encoding to the fill function with a d3 interpolator rather than rely on a Plot-wide colour scheme. Don’t know if there is a performance hit doing it that way, but it certainly gives more flexiblity.

Given this approach for defining multiple interpolated colour schemes, I’ve created a separate page for experimenting with blending of different colour schemes:

It turns out to be quite expressive, allowing subtle (and not so subtle!) shading schemes.