Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

real interpolation in MPL colormaps #36

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

mkomo
Copy link

@mkomo mkomo commented Apr 17, 2021

The four BIDS colormaps [viridis, magma, inferno, plasma] are each defined by arrays of 256 colors.*

These colormaps all have visible color banding (as seen in the images referenced by the d3-scale-chromatic README). By switching to the standard ramp function for each of these scales, banding is significantly decreased:

  • viridis 254 -> 650 distinct colors
    viridis

  • magma 256 -> 717 distinct colors
    magma

  • inferno 256 -> 861 distinct colors
    inferno

  • plasma 256 -> 642 distinct colors
    plasma

*In a 24-bit color space, viridis is actually only 254 colors because two of the colors [#26828e, #20928c] are present twice due to rounding (this is true in the original python as well as in the D3 implementation.)

@mkomo
Copy link
Author

mkomo commented Apr 17, 2021

Differences between existing images and new images

magick compare -metric rmse inferno.png img/inferno.png inferno-difference.png
inferno-difference

magick compare -metric rmse magma.png img/magma.png magma-difference.png
magma-difference

magick compare -metric rmse plasma.png img/plasma.png plasma-difference.png
plasma-difference

magick compare -metric rmse viridis.png img/viridis.png viridis-difference.png
viridis-difference

These differences are due to the new color interpolation.

@mkomo
Copy link
Author

mkomo commented Apr 17, 2021

Test code to determine number of distinct colors in a given chromatic scale:

const getAllScaleColorsBetween = (scale, start=0, end=1) => {
  const s = scale(start),
    e = scale(end);
  if (s == e) {
    return {[s]: start};
  } else if (colorDiff(s, e) == 1 || end - start < Number.EPSILON) {
    return {[s]: start, [e]: end};
  } else {
    const mid = (start + end) / 2;
    return {...getAllScaleColorsBetween(scale, start, mid), ...getAllScaleColorsBetween(scale, mid, end)};
  }
}
const colorDiff = (s, e) => {
  const c1 = d3.color(s), c2 = d3.color(e);
  return Math.abs(c1.r - c2.r) + Math.abs(c1.g - c2.g) + Math.abs(c1.b - c2.b);
}

@Fil
Copy link
Member

Fil commented Apr 17, 2021

built here https://observablehq.com/d/e9aa5c89fc7d6f9c if someone wants to test things (feel free to send suggestions)

On my screen and with my eyes, I don't see any difference, in fact I don't see any banding in the original ramps 👓. So thank you for the code that counts the colors!

@Fil Fil mentioned this pull request Apr 27, 2021
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants