openmc-dev / openmc

OpenMC Monte Carlo Code
https://docs.openmc.org
Other
769 stars 495 forks source link

Smart Color Palette Generation with Plot.colorize() #2827

Open tjlaboss opened 9 months ago

tjlaboss commented 9 months ago

Description

Plot.colorize() is a neat little function that assigns reproducible random colors to each cell or material domain in the geometry. The catch is that these colors are not always unique.

Checking that a color's RGB is unique is trivial (see "Alternatives"). However, that doesn't always mean that the difference will be distinguished by the human eye (haha). One strategy could be to count the number of domains and generate an evenly-spaced color series, possibly rejecting those that are close to user-assigned colors. Another could be to use predefined color palettes for plots up to a certain number of domains, which will make it easier to produce colorblind-accessible plots.

Alternatives

Alternatively, a set of RGB tuples could be created in Plot.colorize(). It would be initialized with whatever colors the user defined via the Plot.colors attribute. If PR #2826 is accepted, a loop would be added to first populate it with cell/material colors, converting any named SVG_COLORS to RGB. Then another loop would generate the random colors. While the generated color is already in the set, a new random color would be generated. This doesn't guarantee that the difference will be visible to a human, but it would be sufficient for a bitmap. (Unless you're trying to plot more than 16,777,216 cells.)

Compatibility

Change to existing API: new keyword argument to Plot.colorize() and Plots.colorize() for a color palette or color generation mode.

gridley commented 9 months ago

I really like the idea of a predefined color palette, similar to what matplotlib does. In fact, since the matplotlib color sequences are already professionally defined, we could just rely on those. These are made for lines and not shaded areas though, so it'd be cool to find some research that looks specifically at that.

print(plt.rcParams['axes.prop_cycle'].by_key()['color'])

which is:

image