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

Incorrect color mapping using categories=True for non-linear categories #5994

Open
user27182 opened this issue Apr 29, 2024 · 0 comments
Open
Labels
bug Uh-oh! Something isn't working as expected.

Comments

@user27182
Copy link
Contributor

user27182 commented Apr 29, 2024

Describe the bug, what's wrong, and what you expected.

When plotting categorical data with a non-linear or non-sequential integer mapping, the categories are not colored correctly.

Edit: For context, this bug means that the use of categories=True should probably be avoided until this is fixed, unless it's certain that the categories in the data being plotted are sequential, contiguous, 0-indexed integers. E.g any examples in the docs which currently use the download_frog_tissue or download_whole_body_ct and plot categorical=True are likely showing the segmentation labels incorrectly.

Steps to reproduce the bug.

E.g. Plot mesh with three categories for cell data: [0, 2, 8]

import pyvista as pv
import numpy as np
sphere = pv.Sphere()
sphere['labels'] = np.zeros(sphere.n_cells)      # category: '0'
sphere['labels'][range(sphere.n_cells//2)] = 2   # category: '2'
sphere['labels'][range(sphere.n_cells//4)] = 8   # category: '8'
sphere.plot(cmap='glasbey', categories=True)

Will produce this, which shows 3 colors in the scalar bar for 3 categories, but visually only colors the mesh with two.
image

Setting categories=False, we can see the "correct" coloring for the sphere (with non-categorical scalar bar). I would have expected this to as the coloring with categories=True, however.
image

I suspect the issue has something to do with this line:

values = cmap(np.linspace(0, 1, n_values)) * 255

which applies a linear mapping for the colors. In this case, the apply_cmap function has limited information about the data, as it only receives an n_values parameter. To resolve this issue, I think apply_cmap needs to know the actual unique values in the data so that it can create a non-linear mapping based on the actual data values, rather than just the number of values in the data.

For reference, the value of n_values which is passed to apply_cmap, is set here when categories=True:

if categories is True:
n_colors = len(np.unique(scalars))

EDIT: A non-linear mapping applied on its own may result in abnormally sized color widths in the scalar bar, e.g. the scalar bar might look like this for the example above [0 0 0 0 0 0 0 0 7 8] with the 0 color being disproportionally wide. In this case, perhaps it's better to keep the linear mapping, but only set each category to a single color value, and set all other values in the lookup table to NaN and use SetNanColor to format the colors for categories not present in range. E.g., format the color bar as [0 nan nan nan nan nan nan 7 8]

System Information

pyvista 0.44.dev0

Screenshots

No response

@user27182 user27182 added the bug Uh-oh! Something isn't working as expected. label Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Uh-oh! Something isn't working as expected.
Projects
None yet
Development

No branches or pull requests

1 participant