glvis
glvis copied to clipboard
More color palettes
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
]
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?
This seems like going a bit overboard with the palettes. 😁 The size of palettes.cpp is essentially doubled in terms of lines!
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...
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?
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.
@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.
@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
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 😉 .
- [ ] Please, describe in
CHANGELOG
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?
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:
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 🤔 .
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
- Palette repetition times ($R$)
- Palette index
- 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
Smooth
Would it be difficult to fix, @justinlaughlin ? ... if we agree it is to be fixed, but I believe we do 😅
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?
The transparent colormaps are cool! Do they work ok for data on 3D meshes?
The transparent colormaps are cool! Do they work ok for data on 3D meshes?
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.
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.
Okay, I think this is ready to go
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 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).
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.
Approved modulo the renaming suggestions I put in the comments.
We can also consider adding some additional palettes, e.g.
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?
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.
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 😉
Added some changes based on your feedback. Thanks!
Should this be squashed before merging? There is a lot of commits.