glvis icon indicating copy to clipboard operation
glvis copied to clipboard

More color palettes

Open justinlaughlin opened this issue 1 year ago • 6 comments

There is a nice resource from Fabio Crameri that provides a lot of color-vision deficiency friendly and perceptually-uniform color maps [see issue 268, and reference]. This PR adds most of those colormaps into GLVis.

Here is an example of batlow

I wrote a small script to help munge the colormap files into something copy-pasteable. I'm not sure if it's worth adding to the repo but I posted it as a gist. The colormaps added in this PR are listed in the gist:

cmnames = ['batlow', 'batlowW', 'batlowK', 'glasgow', 'lipari', 'navia', # continuous
           'oleron', 'bukavu', 'fes', # multi-sequential
           'hawaii', 'buda', 'imola', # discrete
           'oslo', 'nuuk', 'lajolla', 'bamako', 'davos', # categorical
           'bilbao', 'lapaz', 'acton', 'turku', 'tokyo',
           'broc', 'cork', 'vik', 'lisbon', 'tofino', 'berlin', # diverging
           ]

justinlaughlin avatar Jul 11 '24 00:07 justinlaughlin

It looks like tests 15 and 17 are failing because they cycle color palettes backwards using P, so they get around to the new palettes. Maybe we should restrict palettes that cycle to a subset of the total? Or update tests?

justinlaughlin avatar Jul 11 '24 00:07 justinlaughlin

This seems like going a bit overboard with the palettes. 😁 The size of palettes.cpp is essentially doubled in terms of lines!

v-dobrev avatar Jul 11 '24 03:07 v-dobrev

I started with just a few, but it was taking a while so I wrote a script to help, and then I figured might as well add most 😆. I think we had 43 before and this adds 28? Could pare it down too...

justinlaughlin avatar Jul 11 '24 05:07 justinlaughlin

Some suggestions from gm:

  • Add option for user to point to custom colormap file
  • Keep "cyclable" colormaps the same for backwards compatability

Extra colormaps + user defined ones would still be accessed through F6?

justinlaughlin avatar Jul 15 '24 22:07 justinlaughlin

To clarify

Add option for user to point to custom colormap file

The idea will be to have an optional colormap file (could be configurable at build time, or just "colormaps.dat" in the same directory as the executable) and for glvis to check for that file at startup and if found to add the additional colormaps at the end of the default list.

This way, we preserve the default behavior, while allowing for local customization.

tzanio avatar Jul 17 '24 17:07 tzanio

@justinlaughlin, I think it will be still cool to add an optional input file for this. Happy to chat if you want to give it a try.

tzanio avatar Oct 15 '24 00:10 tzanio

@justinlaughlin, I think it will be still cool to add an optional input file for this. Happy to chat if you want to give it a try.

@tzanio I pushed some changes and updated the PR description. So far it works for me; feel free to give it a try with -p shared/palettes.txt

justinlaughlin avatar Nov 05 '24 22:11 justinlaughlin

Also I would separate the classes from the color palette arrays and split declaration / definition to make the code easier to navigate, so maybe move the classes to a new file or put them to palette.cpp/hpp at least 😉 .

najlkin avatar Nov 07 '24 16:11 najlkin

  • [ ] Please, describe in CHANGELOG

tzanio avatar Nov 10 '24 22:11 tzanio

I noticed that discrete textures don't use RepeatPaletteTimes besides for reversing (so you need to press ! to change to the smooth version), is this intended?

justinlaughlin avatar Nov 14 '24 20:11 justinlaughlin

you need to press ! to change to the smooth version

If I understand correctly, that is intended, so you can get a visualization in several bands:

Screenshot 2024-11-14 at 12 43 41 PM

tzanio avatar Nov 14 '24 20:11 tzanio

I think @justinlaughlin means that the discrete palette does not repeat even when you specify that, while the smooth palette does. That looks inconsistent to me 🤔 .

najlkin avatar Nov 14 '24 20:11 najlkin

If I understand correctly, that is intended, so you can get a visualization in several bands:

I guess what I mean is when I press F6 it asks for

  1. Palette repetition times ($R$)
  2. Palette index
  3. Number of colors ($N$)

If I'm in discrete mode and set $R=3$ and $N=5$ I'd expect to get 15 colors (in same ordering used by the smooth palette) but it is just 5.

Palette is repeated 1 times.
(Negative value means the palette is flipped.)
Enter new value: 3
Palette will be repeated 3 times now.

Choose a palette:
...
 ---> [1]

Palette is using 5 colors.
Enter new value (0 = use original 5 colors): 0
Palette will be using 5 colors now.

Discrete image

Smooth image

justinlaughlin avatar Nov 14 '24 20:11 justinlaughlin

Would it be difficult to fix, @justinlaughlin ? ... if we agree it is to be fixed, but I believe we do 😅

najlkin avatar Nov 14 '24 23:11 najlkin

Would it be difficult to fix, @justinlaughlin ? ... if we agree it is to be fixed, but I believe we do 😅

I changed this and simplified the interpolation logic a bit in the Texture class. As a nice side-effect we can use custom alpha channels (seems to work better with a black background); turns out the multiplication is already happening, I think because of GL_BLEND?

image

justinlaughlin avatar Nov 15 '24 06:11 justinlaughlin

The transparent colormaps are cool! Do they work ok for data on 3D meshes?

tzanio avatar Nov 15 '24 18:11 tzanio

The transparent colormaps are cool! Do they work ok for data on 3D meshes?

image

Doesn't look like it 😞 ; it works on cutting planes though 🤔. I need to dig a bit more to understand what GL is doing.

Forgot to mention that repeating palettes works with discrete textures now.

image

justinlaughlin avatar Nov 15 '24 23:11 justinlaughlin

Turns out, it does actually work on 3d meshes (I don't think we have internal boundaries? so just the external mesh). The example palettes I used just happened to have $\alpha=0$ at the lowest end of the scale, and I was testing it on mfem ex1 solutions using zero dirichlet bcs 😅.

In the future, a volume rendering mode would be very nice.

justinlaughlin avatar Nov 16 '24 05:11 justinlaughlin

Okay, I think this is ready to go

justinlaughlin avatar Nov 16 '24 05:11 justinlaughlin

I have a point for discussion here. Alpha channel is now supported by palettes technically, but except two special external palettes there is no way how to use this feature. So how about adding some option to add alpha channel to existing palettes? For example, there could be an extra option after pressing F6, which would add a simple gradient from 0 to 1 to your selected palette and you could optionally set the repetition/reversion in a similar way to the (non-alpha) color palette? 🤔 That would work nicely in most cases without the need to have special palettes for that 😉 . Technically, we could have two classes for palettes with one base, where one would be for RGB only palettes and the second one for RGBA palettes instead of defaulting the alpha channel during loading. This extra option would be offered only for the former one.

najlkin avatar Nov 17 '24 19:11 najlkin

I have a point for discussion here. Alpha channel is now supported by palettes technically, but except two special external palettes there is no way how to use this feature. So how about adding some option to add alpha channel to existing palettes? For example, there could be an extra option after pressing F6, which would add a simple gradient from 0 to 1 to your selected palette and you could optionally set the repetition/reversion in a similar way to the (non-alpha) color palette? 🤔 That would work nicely in most cases without the need to have special palettes for that 😉 . Technically, we could have two classes for palettes with one base, where one would be for RGB only palettes and the second one for RGBA palettes instead of defaulting the alpha channel during loading. This extra option would be offered only for the former one.

I like your suggestion - but I think it would make more sense as an extension of the existing "global" alpha modifier (ie the modifier changed byk, K, ,, <) rather than the palette alpha channel itself. Palette repetition/reversion is already a global state (represented in PaletteState; all Textures are regenerated when palette repetition/reversion is changed).

IMO the main use for custom alpha maps is to highlight certain parts of the data (kind of like more customizable level sets), especially when there is lots of occlusion eg in volumetric rendering. The NVIDIA IndeX plugin has some nice examples. But, in order to do that you need a more sophisticated alpha editor (paraview lets you define it as a piecewise linear function). I think what you want to highlight is often pretty specific to the data/palette.

TBH I think the global modifier is already good as-is; it could get kind of complicated if we add too many features (what if you reverse the palette, but don't want the alpha channel reversed too?). I think some useful directions for the future may be 1) more formats to load from (paraview exports palettes as a json iirc), 2) a piecewise editor, 3) support in pyglvis (it would be quite easy to modify your palette as a numpy array).

justinlaughlin avatar Nov 17 '24 23:11 justinlaughlin

Sure, some easier ways how to define palettes would be nice and may include that alphas 😉 . But I was thinking of something basic at the level of the default palettes, where you also cannot specify any levels you want highlight, but still most of the people are fine with that. Most of the palettes are linear, highlighting one end of the scale, so that would match the 0 to 1 gradient, or they have uniformly distributed levels, which can be achieved by repetition of the alpha gradient. I agree that the global solution makes more sense, I just mean that I would not try to mix it with the alpha channel of the palette and only add that when it is absent, so the logic may stay relatively simple.

najlkin avatar Nov 18 '24 00:11 najlkin

Approved modulo the renaming suggestions I put in the comments.

We can also consider adding some additional palettes, e.g.

  • The ColorCET perceptually uniform colour maps from here.
  • The VisIt's colortables from here.
  • The MatPlotLib colormaps, see here.

I added the cet maps share/palettes-cet.txt.

For VisIT maybe in a future PR we should add a loader for their .ct specification? Looking at it briefly it looks like they allow for custom spacing of points and also different versions of the spec. If we need to parse it we might as well integrate that into GLVis.

I'd need to dig a bit more on matplotlib's license (they say it is a mixture of the licenses of each contributor?); they do have a nice list of externally maintained colormaps that maybe we can consider adding from in the future?

justinlaughlin avatar Nov 18 '24 00:11 justinlaughlin

Technically, we could have two classes for palettes with one base, where one would be for RGB only palettes and the second one for RGBA palettes instead of defaulting the alpha channel during loading.

We could also use the check Palette::IsTranslucent() which checks if any alpha != 1.0.

Most of the palettes are linear, highlighting one end of the scale, so that would match the 0 to 1 gradient, or they have uniformly distributed levels, which can be achieved by repetition of the alpha gradient.

Now that I think about it more, I'd prefer a less context dependent solution. What if a user uploads a palette with no alpha but wants to add a linear mask? I think the issue is that F6 already asks for a lot of information at once as is; I'd personally prefer if we implemented something like https://github.com/GLVis/glvis/issues/287 first, and then add this alpha adjustment idea as a command.

I suggest we separate this into a different PR. Many GLVis commands are already kind of confusing (IMO 🫣) and I think this would add more confusion. E.g. k, K sets one kind of alpha mask (I assumed it was uniform, but once I read the source I realized its a two-sided exponential curve (see plot); with a peak shifted by , and <). If F6 is (sometimes) used to set a linear mask (and another key else for uniform? something else for piecewise linear?) that is too many different keys + context to keep track of.

image

justinlaughlin avatar Nov 18 '24 19:11 justinlaughlin

Wow 😳 , I ...and probably all other users 😄 ... did not know it is complicated like that 🙃 . But when you look at that, it is actually close to what I was proposing with the linear gradient. So definitely I would not add another layer of logic to the alpha channel, but it is another reason to implement the logic in palettes to unify the whole thing. Also incorporating the settings to the F6 menu would give better control over it to the user. Anyway, we may defer it to another PR, this is good as it is 😉

najlkin avatar Nov 19 '24 22:11 najlkin

Added some changes based on your feedback. Thanks!

justinlaughlin avatar Dec 10 '24 01:12 justinlaughlin

Should this be squashed before merging? There is a lot of commits.

justinlaughlin avatar Dec 10 '24 20:12 justinlaughlin