Summary
When setting the nan_color attribute in Mayavi visualizations (e.g., contour3d, surface, volume), the alpha channel of nan_color incorrectly affects the transparency of active (non-NaN) cells, even when the dataset contains no NaN values. This occurs despite explicitly setting the opacity of the visualization to 1.0, leading to unintended transparency in the rendered output.
Steps to Reproduce
- Create a 3D dataset with no NaN values. For example:
import numpy as np
from mayavi import mlab
def create_sample_data(nx=25, ny=25, nz=15):
data = np.zeros((nx, ny, nz))
k_vals = np.linspace(0, 1, nz)
data[:, :, :] = k_vals[None, None, :]
return data
data = create_sample_data(10, 10, 5)
- Create two Mayavi figures to visualize the data using isosurfaces (or other methods like
surface or volume):
- In the first figure, set
nan_color to (0, 0, 0, 0) (fully transparent).
- In the second figure, set
nan_color to (0, 0, 0, 1) (fully opaque).
- Ensure the visualization’s
opacity is set to 1.0.
# First figure (NaN color = transparent)
mlab.figure(1, bgcolor=(1, 1, 1), size=(400, 600))
vmin, vmax = np.nanmin(data), np.nanmax(data)
contours = list(np.linspace(vmin, vmax, 4))
src1 = mlab.contour3d(data, contours=contours, opacity=1.0, extent=[0, 25, 0, 25, 0, 15*2])
src1.module_manager.scalar_lut_manager.lut.nan_color = 0, 0, 0, 0.9 # Nearly transparent
src1.module_manager.scalar_lut_manager.lut_mode = 'blue-red'
src1.module_manager.scalar_lut_manager.show_scalar_bar = True
mlab.orientation_axes()
# Second figure (NaN color = opaque)
mlab.figure(2, bgcolor=(1, 1, 1), size=(400, 600))
src2 = mlab.contour3d(data, contours=contours, opacity=1.0, extent=[0, 25, 0, 25, 0, 15*2])
src2.module_manager.scalar_lut_manager.lut.nan_color = 0, 0, 0, 1 # Opaque
src2.module_manager.scalar_lut_manager.lut_mode = 'blue-red'
src2.module_manager.scalar_lut_manager.show_scalar_bar = True
mlab.orientation_axes()
mlab.show()
- Observe the rendered output in both figures.
Observed Behavior
- In the first figure (with
nan_color = (0, 0, 0, 0.9) or (0, 0, 0, 0)), the entire visualization (active cells) becomes transparent or nearly transparent, despite the dataset containing no NaN values and the opacity being set to 1.0.
- In the second figure (with
nan_color = (0, 0, 0, 1)), the visualization renders correctly with full opacity.
- The issue is not limited to
contour3d (isosurfaces). It also occurs with other visualization methods, such as:
surface: surface = mlab.pipeline.surface(src, opacity=1.0)
volume: vol = mlab.volume(x, y, z, masked_data)
Expected Behavior
- The
nan_color setting should only affect the rendering of NaN values in the dataset.
- When the dataset contains no NaN values, the
nan_color alpha channel should have no effect on the visualization.
- The
opacity setting (e.g., opacity=1.0) should control the transparency of active (non-NaN) cells, ensuring they render as fully opaque when set to 1.0, regardless of the nan_color alpha value.
Environment
- Mayavi Versions Tested: 4.8.2 and 4.8.3
- VTK Version: 9.2.6 and 9.4.2
- Python Version: 3.11 and 3.12
- Operating System: Windows 11 and RHEL 8.10.
Additional Information
- The issue was initially noticed when rendering surfaces with
mlab.pipeline.surface and was reproduced with both isosurfaces (contour3d) and volume rendering (volume).
- A screenshot demonstrating the defect with
contour3d is attached (Scene 1 with nan_color=(0, 0, 0, 0.9) shows unintended transparency, while Scene 2 with nan_color=(0, 0, 0, 1) renders correctly).
- This defect impacts any visualization where
nan_color is adjusted, making it difficult to control transparency correctly when NaN values are absent.
Suggested Fix
Investigate the lookup table (LUT) manager’s handling of nan_color in Mayavi. It’s possible that the alpha channel of nan_color is being applied globally to the LUT or shader, affecting all data points instead of only NaN values. A potential fix could involve ensuring that the nan_color alpha only applies to NaN-mapped indices in the LUT, leaving non-NaN data to respect the opacity setting.
Summary
When setting the
nan_colorattribute in Mayavi visualizations (e.g.,contour3d,surface,volume), the alpha channel ofnan_colorincorrectly affects the transparency of active (non-NaN) cells, even when the dataset contains no NaN values. This occurs despite explicitly setting theopacityof the visualization to 1.0, leading to unintended transparency in the rendered output.Steps to Reproduce
surfaceorvolume):nan_colorto(0, 0, 0, 0)(fully transparent).nan_colorto(0, 0, 0, 1)(fully opaque).opacityis set to 1.0.Observed Behavior
nan_color = (0, 0, 0, 0.9)or(0, 0, 0, 0)), the entire visualization (active cells) becomes transparent or nearly transparent, despite the dataset containing no NaN values and theopacitybeing set to 1.0.nan_color = (0, 0, 0, 1)), the visualization renders correctly with full opacity.contour3d(isosurfaces). It also occurs with other visualization methods, such as:surface:surface = mlab.pipeline.surface(src, opacity=1.0)volume:vol = mlab.volume(x, y, z, masked_data)Expected Behavior
nan_colorsetting should only affect the rendering of NaN values in the dataset.nan_coloralpha channel should have no effect on the visualization.opacitysetting (e.g.,opacity=1.0) should control the transparency of active (non-NaN) cells, ensuring they render as fully opaque when set to 1.0, regardless of thenan_coloralpha value.Environment
Additional Information
mlab.pipeline.surfaceand was reproduced with both isosurfaces (contour3d) and volume rendering (volume).contour3dis attached (Scene 1 withnan_color=(0, 0, 0, 0.9)shows unintended transparency, while Scene 2 withnan_color=(0, 0, 0, 1)renders correctly).nan_coloris adjusted, making it difficult to control transparency correctly when NaN values are absent.Suggested Fix
Investigate the lookup table (LUT) manager’s handling of
nan_colorin Mayavi. It’s possible that the alpha channel ofnan_coloris being applied globally to the LUT or shader, affecting all data points instead of only NaN values. A potential fix could involve ensuring that thenan_coloralpha only applies to NaN-mapped indices in the LUT, leaving non-NaN data to respect theopacitysetting.