Skip to content

Commit

Permalink
MRG, ENH: Allow disabling FXAA (#7877)
Browse files Browse the repository at this point in the history
* ENH: Allow disabling FXAA

* FIX: Global

* DOC: Document correctly

* Fix relative import path

* FIX: Doc [skip travis]

Co-authored-by: Guillaume Favelier <[email protected]>
  • Loading branch information
larsoner and GuillaumeFavelier authored Jun 10, 2020
1 parent 98b0bb3 commit 3fdd502
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 12 deletions.
2 changes: 2 additions & 0 deletions doc/changes/latest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ Changelog

- Add ECoG misc EDF dataset to the :ref:`tut_working_with_ecog` tutorial to show snapshots of time-frequency activity by `Adam Li`_

- Add :func:`mne.viz.set_3d_options` and ``MNE_3D_OPTION_ANTIALIAS`` environment variable to control full-scene antialiasing (FXAA) in 3D functions like :ref:`mne coreg`, :func:`mne.viz.plot_alignment`, and :func:`mne.viz.plot_source_estimates`; this can be useful on systems where FXAA does not work well, such as some with MESA software rendering, by `Eric Larson`_

- Add better support for reading corrupted FIF files in :func:`mne.io.read_raw_fif` by `Eric Larson`_

- BIDS conformity: When saving FIF files to disk and the files are split into parts, the ``split_naming='bids'`` parameter now uses a "_split-%d" naming instead of the previous "_part-%d", by `Stefan Appelhoff`_
Expand Down
11 changes: 11 additions & 0 deletions doc/install/advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,17 @@ to force MESA to use modern OpenGL by using this before executing
Also, it's possible that different software rending backends might perform
better than others, such as using the ``llvmpipe`` backend rather than ``swr``.

MESA also can have trouble with full-screen antialiasing, which you can
disable with:

.. code-block:: console
$ export MNE_3D_OPTION_ANTIALIAS=false
or by doing
:func:`mne.viz.set_3d_options(antialias=False) <mne.viz.set_3d_options>` within
a given Python session.

.. _troubleshoot_3d:

Troubleshooting 3D plots in MNE-Python
Expand Down
1 change: 1 addition & 0 deletions doc/python_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ Visualization
set_3d_backend
get_3d_backend
use_3d_backend
set_3d_options
set_3d_view
set_3d_title
create_3d_figure
Expand Down
3 changes: 2 additions & 1 deletion mne/gui/_coreg_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
rot_to_quat, _angle_between_quats)
from ..coreg import fit_matched_points, scale_mri, _find_fiducials_files
from ..viz.backends._pysurfer_mayavi import _toggle_mlab_render
from ..viz._3d import _get_3d_option
from ..utils import logger, set_config, _pl
from ._fiducials_gui import MRIHeadWithFiducialsModel, FiducialsPanel
from ._file_traits import trans_wildcard, DigSource, SubjectSelectorPanel
Expand Down Expand Up @@ -2028,7 +2029,7 @@ def _on_advanced_rendering_change(self):
renderer.vtk_window.multi_samples = 8
renderer.vtk_window.alpha_bit_planes = 0
if hasattr(renderer, 'use_fxaa'):
self.scene.renderer.use_fxaa = True
self.scene.renderer.use_fxaa = _get_3d_option('antialias')
self.scene.render()

@on_trait_change('lock_fiducials')
Expand Down
1 change: 0 additions & 1 deletion mne/source_estimate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2182,7 +2182,6 @@ def plot(self, subject=None, hemi='lh', colormap='hot', time_label='auto',
colorbar=True, clim='auto', cortex='classic', size=800,
background='black', foreground=None, initial_time=None,
time_unit='s', show_traces='auto', verbose=None): # noqa: D102

return plot_vector_source_estimates(
self, subject=subject, hemi=hemi, colormap=colormap,
time_label=time_label, smoothing_steps=smoothing_steps,
Expand Down
1 change: 1 addition & 0 deletions mne/utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def set_memmap_min_size(memmap_min_size):

# List the known configuration values
known_config_types = (
'MNE_3D_OPTION_ANTIALIAS',
'MNE_BROWSE_RAW_SIZE',
'MNE_CACHE_DIR',
'MNE_COREG_ADVANCED_RENDERING',
Expand Down
58 changes: 53 additions & 5 deletions mne/viz/_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from scipy import linalg, sparse

from ..defaults import DEFAULTS
from ..fixes import einsum, _crop_colorbar, _get_img_fdata
from ..fixes import einsum, _crop_colorbar, _get_img_fdata, _get_args
from ..io import _loc_to_coil_trans
from ..io.pick import pick_types, _picks_to_idx
from ..io.constants import FIFF
Expand All @@ -38,7 +38,7 @@
invert_transform, Transform,
read_ras_mni_t, _print_coord_trans)
from ..utils import (get_subjects_dir, logger, _check_subject, verbose, warn,
has_nibabel, check_version, fill_doc, _pl,
has_nibabel, check_version, fill_doc, _pl, get_config,
_ensure_int, _validate_type, _check_option)
from .utils import (mne_analyze_colormap, _get_color_list,
plt_show, tight_layout, figure_nobar, _check_time_unit)
Expand Down Expand Up @@ -1631,7 +1631,6 @@ def plot_source_estimates(stc, subject=None, surface='inflated', hemi='lh',
mayavi, but resorts to matplotlib if mayavi is not available.
.. versionadded:: 0.15.0
spacing : str
The spacing to use for the source space. Can be ``'ico#'`` for a
recursively subdivided icosahedron, ``'oct#'`` for a recursively
Expand Down Expand Up @@ -1716,12 +1715,15 @@ def plot_source_estimates(stc, subject=None, surface='inflated', hemi='lh',
"title": title, "cortex": cortex, "size": size,
"background": background, "foreground": foreground,
"figure": figure, "subjects_dir": subjects_dir,
"views": views
"views": views,
}
if _get_3d_backend() == "pyvista":
kwargs["show"] = not time_viewer
else:
kwargs.update(_check_pysurfer_antialias(Brain))
with warnings.catch_warnings(record=True): # traits warnings
brain = Brain(**kwargs)
del kwargs
center = 0. if diverging else None
for hemi in hemis:
hemi_idx = 0 if hemi == 'lh' else 1
Expand Down Expand Up @@ -2216,6 +2218,17 @@ def plot_and_correct(*args, **kwargs):
return fig


def _check_pysurfer_antialias(Brain):
antialias = _get_3d_option('antialias')
kwargs = dict()
if not antialias:
if 'antialias' not in _get_args(Brain):
raise ValueError('To turn off antialiasing, PySurfer needs to be '
'updated to version 0.11+')
kwargs['antialias'] = antialias
return kwargs


@verbose
def plot_vector_source_estimates(stc, subject=None, hemi='lh', colormap='hot',
time_label='auto', smoothing_steps=10,
Expand Down Expand Up @@ -2320,8 +2333,10 @@ def plot_vector_source_estimates(stc, subject=None, hemi='lh', colormap='hot',
if _get_3d_backend() == "mayavi":
from surfer import Brain
from surfer import __version__ as surfer_version
kwargs = _check_pysurfer_antialias(Brain)
else: # PyVista
from ._brain import _Brain as Brain
kwargs = dict()
from ..source_estimate import VectorSourceEstimate

_validate_type(stc, VectorSourceEstimate, "stc", "Vector Source Estimate")
Expand Down Expand Up @@ -2355,7 +2370,7 @@ def plot_vector_source_estimates(stc, subject=None, hemi='lh', colormap='hot',
title=title, cortex=cortex, size=size,
background=background, foreground=foreground,
figure=figure, subjects_dir=subjects_dir,
views=views, alpha=brain_alpha)
views=views, alpha=brain_alpha, **kwargs)
if scale_factor is None:
# Configure the glyphs scale directly
width = np.mean([np.ptp(brain.geo[hemi].coords[:, 1])
Expand Down Expand Up @@ -3123,3 +3138,36 @@ def plot_brain_colorbar(ax, clim, colormap='auto', transparent=True,
'bottom' if orientation == 'vertical' else 'right'):
ax.spines[key].set_visible(False)
return cbar


_3d_options = dict()
_3d_default = dict(antialias='true')


def set_3d_options(antialias=None):
"""Set 3D rendering options.
Parameters
----------
antialias : bool | None
If not None, set the default full-screen anti-aliasing setting.
False is useful when renderers have problems (such as software
MESA renderers). This option can also be controlled using an
environment variable, e.g., ``MNE_3D_OPTION_ANTIALIAS=false``.
Notes
-----
.. versionadded:: 0.21.0
"""
if antialias is not None:
_3d_options['antialias'] = str(bool(antialias)).lower()


def _get_3d_option(key):
try:
opt = _3d_options[key]
except KeyError:
opt = get_config(f'MNE_3D_OPTION_{key.upper()}', _3d_default[key])
opt = opt.lower()
_check_option(f'3D option {key}', opt, ('true', 'false'))
return opt == 'true'
2 changes: 1 addition & 1 deletion mne/viz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
plot_dipole_locations, snapshot_brain_montage,
plot_head_positions, plot_alignment, plot_brain_colorbar,
plot_volume_source_estimates, plot_sensors_connectivity,
link_brains)
link_brains, set_3d_options)
from .misc import (plot_cov, plot_csd, plot_bem, plot_events,
plot_source_spectrogram, _get_presser,
plot_dipole_amplitudes, plot_ideal_filter, plot_filter,
Expand Down
4 changes: 3 additions & 1 deletion mne/viz/backends/_pysurfer_mayavi.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,11 @@ def enable_depth_peeling(self):

def _mlab_figure(**kwargs):
"""Create a Mayavi figure using our defaults."""
from .._3d import _get_3d_option
fig = _import_mlab().figure(**kwargs)
# If using modern VTK/Mayavi, improve rendering with FXAA
if hasattr(getattr(fig.scene, 'renderer', None), 'use_fxaa'):
antialias = _get_3d_option('antialias')
if antialias and hasattr(getattr(fig.scene, 'renderer', None), 'use_fxaa'):
fig.scene.renderer.use_fxaa = True
return fig

Expand Down
8 changes: 5 additions & 3 deletions mne/viz/backends/_pyvista.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,13 @@ class _Renderer(_BaseRenderer):
def __init__(self, fig=None, size=(600, 600), bgcolor='black',
name="PyVista Scene", show=False, shape=(1, 1)):
from .renderer import MNE_3D_BACKEND_TESTING
from .._3d import _get_3d_option
figure = _Figure(show=show, title=name, size=size, shape=shape,
background_color=bgcolor, notebook=None)
self.font_family = "arial"
self.tube_n_sides = 20
antialias = _get_3d_option('antialias')
self.antialias = antialias and not MNE_3D_BACKEND_TESTING
if isinstance(fig, int):
saved_fig = _FIGURES.get(fig)
# Restore only active plotter
Expand Down Expand Up @@ -173,15 +176,14 @@ def __init__(self, fig=None, size=(600, 600), bgcolor='black',
self.plotter.default_camera_tool_bar.close()
if hasattr(self.plotter, "saved_cameras_tool_bar"):
self.plotter.saved_cameras_tool_bar.close()
if not MNE_3D_BACKEND_TESTING:
if self.antialias:
_enable_aa(self.figure, self.plotter)

def subplot(self, x, y):
from .renderer import MNE_3D_BACKEND_TESTING
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=FutureWarning)
self.plotter.subplot(x, y)
if not MNE_3D_BACKEND_TESTING:
if self.antialias:
_enable_aa(self.figure, self.plotter)

def scene(self):
Expand Down

0 comments on commit 3fdd502

Please sign in to comment.