diff --git a/mne/gui/__init__.py b/mne/gui/__init__.py index 92d9c78a743..ba9a1b00ce0 100644 --- a/mne/gui/__init__.py +++ b/mne/gui/__init__.py @@ -130,7 +130,6 @@ def coregistration(tabbed=False, split=True, width=None, inst=None, 'scrollable': (scrollable, True), 'head_inside': (head_inside, True), 'guess_mri_subject': guess_mri_subject, - 'head_opacity': head_opacity, 'scale': scale, 'advanced_rendering': advanced_rendering, } @@ -152,7 +151,7 @@ def coregistration(tabbed=False, split=True, width=None, inst=None, advanced_rendering = \ config.get('MNE_COREG_ADVANCED_RENDERING', 'true') == 'true' if head_opacity is None: - head_opacity = config.get('MNE_COREG_HEAD_OPACITY', 1.) + head_opacity = config.get('MNE_COREG_HEAD_OPACITY', 0.8) if head_inside is None: head_inside = \ config.get('MNE_COREG_HEAD_INSIDE', 'true').lower() == 'true' @@ -191,11 +190,11 @@ def coregistration(tabbed=False, split=True, width=None, inst=None, block = not MNE_3D_BACKEND_TESTING return CoregistrationUI( info_file=inst, subject=subject, subjects_dir=subjects_dir, - head_resolution=head_high_res, orient_glyphs=orient_to_surface, - scale_by_distance=scale_by_distance, project_eeg=project_eeg, - mark_inside=mark_inside, trans=trans, size=(width, height), - show=show, block=block, interaction=interaction, - verbose=verbose + head_resolution=head_high_res, head_opacity=head_opacity, + orient_glyphs=orient_to_surface, scale_by_distance=scale_by_distance, + project_eeg=project_eeg,mark_inside=mark_inside, trans=trans, + size=(width, height), show=show, block=block, + interaction=interaction, verbose=verbose ) diff --git a/mne/gui/_coreg.py b/mne/gui/_coreg.py index 5e19617dfe6..1502db998fe 100644 --- a/mne/gui/_coreg.py +++ b/mne/gui/_coreg.py @@ -44,8 +44,8 @@ class CoregistrationUI(HasTraits): %(fiducials)s head_resolution : bool If True, use a high-resolution head surface. Defaults to False. - head_transparency : bool - If True, display the head surface with transparency. Defaults to False. + head_opacity : float + The opacity of the head surface. Defaults to 0.8. hpi_coils : bool If True, display the HPI coils. Defaults to True. head_shape_points : bool @@ -99,7 +99,7 @@ class CoregistrationUI(HasTraits): _head_shape_points = Bool() _eeg_channels = Bool() _head_resolution = Bool() - _head_transparency = Bool() + _head_opacity = Float() _helmet = Bool() _grow_hair = Float() _subject_to = Unicode() @@ -113,12 +113,12 @@ class CoregistrationUI(HasTraits): @verbose def __init__(self, info_file, subject=None, subjects_dir=None, fiducials='auto', head_resolution=None, - head_transparency=None, hpi_coils=None, + head_opacity=None, hpi_coils=None, head_shape_points=None, eeg_channels=None, orient_glyphs=None, scale_by_distance=None, project_eeg=None, mark_inside=None, sensor_opacity=None, trans=None, size=None, bgcolor=None, show=True, block=False, interaction='terrain', *, - standalone=None, + head_transparency=None, standalone=None, verbose=None): if standalone is not None: depr_message = ('standalone is deprecated and will be replaced by ' @@ -130,6 +130,17 @@ def __init__(self, info_file, subject=None, subjects_dir=None, warn(depr_message + ' Since you passed values for both ' 'standalone and block, standalone will be ignored.', DeprecationWarning) + if head_transparency is not None: + depr_message = ('head_transparency is deprecated and will be' + ' replaced by head_opacity in 1.1.') + if head_opacity is None: + head_opacity = 0.8 if head_transparency else 1.0 + warn(depr_message, DeprecationWarning) + else: + warn(depr_message + ' Since you passed values for both ' + 'head_transparency and head_opacity, ' + 'head_transparency will be ignored.', + DeprecationWarning) from ..viz.backends.renderer import _get_renderer from ..viz.backends._utils import _qt_app_exec @@ -151,7 +162,6 @@ def _get_default(var, val): self._mouse_no_mvt = -1 self._to_cf_t = None self._omit_hsp_distance = 0.0 - self._head_opacity = 1.0 self._fid_colors = tuple( DEFAULTS['coreg'][f'{key}_color'] for key in ('lpa', 'nasion', 'rpa')) @@ -166,9 +176,8 @@ def _get_default(var, val): head_shape_points=_get_default(head_shape_points, True), eeg_channels=_get_default(eeg_channels, True), head_resolution=_get_default(head_resolution, True), - head_transparency=_get_default(head_transparency, False), + head_opacity=_get_default(head_opacity, 0.8), helmet=False, - head_opacity=0.5, sensor_opacity=_get_default(sensor_opacity, 1.0), fiducials=("LPA", "Nasion", "RPA"), fiducial="LPA", @@ -205,6 +214,7 @@ def _get_default(var, val): # setup the window self._renderer = _get_renderer( size=self._defaults["size"], bgcolor=self._defaults["bgcolor"]) + self._renderer.enable_depth_peeling() self._renderer._window_close_connect(self._clean) self._renderer.set_interaction(interaction) self._renderer._status_bar_initialize() @@ -234,7 +244,8 @@ def _get_default(var, val): self._set_head_shape_points(self._defaults["head_shape_points"]) self._set_eeg_channels(self._defaults["eeg_channels"]) self._set_head_resolution(self._defaults["head_resolution"]) - self._set_head_transparency(self._defaults["head_transparency"]) + self._set_head_opacity(self._defaults["head_opacity"]) + self._old_head_opacity = self._head_opacity self._set_helmet(self._defaults["helmet"]) self._set_grow_hair(self._defaults["grow_hair"]) self._set_skip_fiducials(self._defaults["skip_fiducials"]) @@ -352,8 +363,8 @@ def _set_eeg_channels(self, state): def _set_head_resolution(self, state): self._head_resolution = bool(state) - def _set_head_transparency(self, state): - self._head_transparency = bool(state) + def _set_head_opacity(self, value): + self._head_opacity = value def _set_helmet(self, state): self._helmet = bool(state) @@ -458,13 +469,15 @@ def _lock_fids_changed(self, change=None): "fit_fiducials", "fit_icp"] fits_widgets = ["fits_fiducials", "fits_icp"] fid_widgets = ["fid_X", "fid_Y", "fid_Z", "fids_file", "fids"] - self._set_head_transparency(self._lock_fids) if self._lock_fids: + self._head_opacity = self._old_head_opacity self._forward_widget_command(locked_widgets, "set_enabled", True) self._scale_mode_changed() self._display_message() self._update_distance_estimation() else: + self._old_head_opacity = self._head_opacity + self._head_opacity = 1.0 self._forward_widget_command(locked_widgets, "set_enabled", False) self._forward_widget_command(fits_widgets, "set_enabled", False) self._display_message("Placing MRI fiducials - " @@ -542,12 +555,11 @@ def _eeg_channels_changed(self, change=None): def _head_resolution_changed(self, change=None): self._update_plot(["head"]) - @observe("_head_transparency") - def _head_transparency_changed(self, change=None): - self._head_opacity = self._defaults["head_opacity"] \ - if self._head_transparency else 1.0 - self._actors["head"].GetProperty().SetOpacity(self._head_opacity) - self._renderer._update() + @observe("_head_opacity") + def _head_opacity_changed(self, change=None): + if "head" in self._actors: + self._actors["head"].GetProperty().SetOpacity(self._head_opacity) + self._renderer._update() @observe("_helmet") def _helmet_changed(self, change=None): @@ -1238,6 +1250,15 @@ def _configure_dock(self): tooltip="Enable/Disable helmet", layout=view_options_layout, ) + self._widgets["head_opacity"] = self._renderer._dock_add_slider( + name="Head opacity", + value=self._head_opacity, + rng=[0.25, 1.0], + callback=self._set_head_opacity, + compact=True, + double=True, + layout=view_options_layout, + ) self._renderer._dock_add_stretch() self._renderer._dock_initialize( diff --git a/mne/gui/tests/test_coreg_gui.py b/mne/gui/tests/test_coreg_gui.py index 53874a28a84..386f7f979a9 100644 --- a/mne/gui/tests/test_coreg_gui.py +++ b/mne/gui/tests/test_coreg_gui.py @@ -105,6 +105,10 @@ def test_coreg_gui_pyvista(tmp_path, renderer_interactive_pyvistaqt): with pytest.warns(DeprecationWarning, match='standalone is deprecated'): CoregistrationUI(info_file=None, subject='sample', subjects_dir=subjects_dir, standalone=False) + with pytest.warns(DeprecationWarning, match='head_transparency ' + 'is deprecated'): + CoregistrationUI(info_file=None, subject='sample', + subjects_dir=subjects_dir, head_transparency=False) config = get_config(home_dir=os.environ.get('_MNE_FAKE_HOME_DIR')) tmp_trans = tmp_path / 'tmp-trans.fif' @@ -153,10 +157,8 @@ def test_coreg_gui_pyvista(tmp_path, renderer_interactive_pyvistaqt): coreg._on_pick(vtk_picker, None) # also pick when locked # lock fiducials - assert not coreg._head_transparency coreg._set_lock_fids(True) assert coreg._lock_fids - assert coreg._head_transparency # fitting (no scaling) assert coreg._nasion_weight == 10. @@ -181,6 +183,9 @@ def test_coreg_gui_pyvista(tmp_path, renderer_interactive_pyvistaqt): assert coreg._orient_glyphs assert coreg._scale_by_distance assert coreg._mark_inside + assert_allclose( + coreg._head_opacity, + float(config.get('MNE_COREG_HEAD_OPACITY', '0.8'))) assert coreg._project_eeg == \ (config.get('MNE_COREG_PROJECT_EEG', '') == 'true') assert coreg._hpi_coils