From 8ad2fe85ac6ab622c47ada39f9c8c9d2036b8c0f Mon Sep 17 00:00:00 2001 From: Guillaume Favelier Date: Thu, 14 Jan 2021 14:19:53 +0100 Subject: [PATCH 1/9] Work a solution --- mne/viz/backends/renderer.py | 3 ++- tutorials/misc/plot_seeg.py | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/mne/viz/backends/renderer.py b/mne/viz/backends/renderer.py index fad9f882f97..f8446cbbad9 100644 --- a/mne/viz/backends/renderer.py +++ b/mne/viz/backends/renderer.py @@ -242,7 +242,7 @@ def set_3d_title(figure, title, size=40): def create_3d_figure(size, bgcolor=(0, 0, 0), smooth_shading=True, - handle=None, scene=True): + shape=None, handle=None, scene=True): """Return an empty figure based on the current 3d backend. .. warning:: Proceed with caution when the renderer object is @@ -274,6 +274,7 @@ def create_3d_figure(size, bgcolor=(0, 0, 0), smooth_shading=True, fig=handle, size=size, bgcolor=bgcolor, + shape=shape, smooth_shading=smooth_shading, ) if scene: diff --git a/tutorials/misc/plot_seeg.py b/tutorials/misc/plot_seeg.py index b7370f80693..2cef4899f0b 100644 --- a/tutorials/misc/plot_seeg.py +++ b/tutorials/misc/plot_seeg.py @@ -118,9 +118,22 @@ ############################################################################### # Let's check to make sure everything is aligned. -fig = mne.viz.plot_alignment(raw.info, trans, 'fsaverage', - subjects_dir=subjects_dir, show_axes=True, - surfaces=["pial", "head"]) + +def comparative_views(size, func, *args, **kwargs): + fig = mne.viz.create_3d_figure(size=size, shape="1|3") + kwargs["fig"] = fig + func(*args, **kwargs) + fig.plotter.show_axes() + for idx, pos in enumerate(["xz", "yz", "xy"]): + fig.plotter.subplot(idx + 1) + func(*args, **kwargs) + fig.plotter.camera_position = pos + fig.plotter.show_axes() + + +comparative_views((800, 600), mne.viz.plot_alignment, raw.info, trans, + 'fsaverage', subjects_dir=subjects_dir, show_axes=True, + surfaces=["pial", "head"]) ############################################################################### # Next, we'll get the raw data and plot its amplitude over time. From cd096006a8f30e7d6572dedd7c8989228ded8f9b Mon Sep 17 00:00:00 2001 From: Guillaume Favelier Date: Thu, 14 Jan 2021 14:29:33 +0100 Subject: [PATCH 2/9] Fix style --- mne/viz/backends/renderer.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mne/viz/backends/renderer.py b/mne/viz/backends/renderer.py index f8446cbbad9..84447a9f015 100644 --- a/mne/viz/backends/renderer.py +++ b/mne/viz/backends/renderer.py @@ -258,6 +258,10 @@ def create_3d_figure(size, bgcolor=(0, 0, 0), smooth_shading=True, The color of the background. smooth_shading : bool If True, smooth shading is enabled. Defaults to True. + shape : str | list | tuple + Number of sub-render windows inside of the main window. + As string, for example ``"1|3"``, it means 1 plot on + the left and 3 plots on the right. handle : int | None The figure identifier. scene : bool From 05863aceab82e8de68a731336f5a1a6220dacd4f Mon Sep 17 00:00:00 2001 From: Guillaume Favelier Date: Thu, 14 Jan 2021 14:44:29 +0100 Subject: [PATCH 3/9] Change default --- mne/viz/backends/renderer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mne/viz/backends/renderer.py b/mne/viz/backends/renderer.py index 84447a9f015..a257eaf1e0b 100644 --- a/mne/viz/backends/renderer.py +++ b/mne/viz/backends/renderer.py @@ -242,7 +242,7 @@ def set_3d_title(figure, title, size=40): def create_3d_figure(size, bgcolor=(0, 0, 0), smooth_shading=True, - shape=None, handle=None, scene=True): + shape=(1, 1), handle=None, scene=True): """Return an empty figure based on the current 3d backend. .. warning:: Proceed with caution when the renderer object is From fa75019ec9c3dd18e63df3e68ecc42d624264cdd Mon Sep 17 00:00:00 2001 From: Guillaume Favelier Date: Thu, 14 Jan 2021 15:00:10 +0100 Subject: [PATCH 4/9] Finalize plot settings --- tutorials/misc/plot_seeg.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tutorials/misc/plot_seeg.py b/tutorials/misc/plot_seeg.py index 2cef4899f0b..7f701e3625d 100644 --- a/tutorials/misc/plot_seeg.py +++ b/tutorials/misc/plot_seeg.py @@ -129,6 +129,7 @@ def comparative_views(size, func, *args, **kwargs): func(*args, **kwargs) fig.plotter.camera_position = pos fig.plotter.show_axes() + fig.plotter.update() comparative_views((800, 600), mne.viz.plot_alignment, raw.info, trans, From 9f0775c1ad3362c3f30e097602c9f7a6fc756664 Mon Sep 17 00:00:00 2001 From: Guillaume Favelier Date: Mon, 18 Jan 2021 16:46:35 +0100 Subject: [PATCH 5/9] Rollback --- mne/viz/backends/renderer.py | 7 +------ tutorials/misc/plot_seeg.py | 20 +++----------------- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/mne/viz/backends/renderer.py b/mne/viz/backends/renderer.py index a257eaf1e0b..fad9f882f97 100644 --- a/mne/viz/backends/renderer.py +++ b/mne/viz/backends/renderer.py @@ -242,7 +242,7 @@ def set_3d_title(figure, title, size=40): def create_3d_figure(size, bgcolor=(0, 0, 0), smooth_shading=True, - shape=(1, 1), handle=None, scene=True): + handle=None, scene=True): """Return an empty figure based on the current 3d backend. .. warning:: Proceed with caution when the renderer object is @@ -258,10 +258,6 @@ def create_3d_figure(size, bgcolor=(0, 0, 0), smooth_shading=True, The color of the background. smooth_shading : bool If True, smooth shading is enabled. Defaults to True. - shape : str | list | tuple - Number of sub-render windows inside of the main window. - As string, for example ``"1|3"``, it means 1 plot on - the left and 3 plots on the right. handle : int | None The figure identifier. scene : bool @@ -278,7 +274,6 @@ def create_3d_figure(size, bgcolor=(0, 0, 0), smooth_shading=True, fig=handle, size=size, bgcolor=bgcolor, - shape=shape, smooth_shading=smooth_shading, ) if scene: diff --git a/tutorials/misc/plot_seeg.py b/tutorials/misc/plot_seeg.py index 7f701e3625d..b7370f80693 100644 --- a/tutorials/misc/plot_seeg.py +++ b/tutorials/misc/plot_seeg.py @@ -118,23 +118,9 @@ ############################################################################### # Let's check to make sure everything is aligned. - -def comparative_views(size, func, *args, **kwargs): - fig = mne.viz.create_3d_figure(size=size, shape="1|3") - kwargs["fig"] = fig - func(*args, **kwargs) - fig.plotter.show_axes() - for idx, pos in enumerate(["xz", "yz", "xy"]): - fig.plotter.subplot(idx + 1) - func(*args, **kwargs) - fig.plotter.camera_position = pos - fig.plotter.show_axes() - fig.plotter.update() - - -comparative_views((800, 600), mne.viz.plot_alignment, raw.info, trans, - 'fsaverage', subjects_dir=subjects_dir, show_axes=True, - surfaces=["pial", "head"]) +fig = mne.viz.plot_alignment(raw.info, trans, 'fsaverage', + subjects_dir=subjects_dir, show_axes=True, + surfaces=["pial", "head"]) ############################################################################### # Next, we'll get the raw data and plot its amplitude over time. From f5d69bf86ea9546b72f9b9906e5dd52a62eafd97 Mon Sep 17 00:00:00 2001 From: Guillaume Favelier Date: Mon, 18 Jan 2021 17:19:00 +0100 Subject: [PATCH 6/9] Add a silhouette parameter to plot_alignment --- mne/viz/_3d.py | 14 ++++++++++++-- mne/viz/backends/_pyvista.py | 25 +++++++++++++++++++++++-- tutorials/misc/plot_seeg.py | 8 +++++--- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/mne/viz/_3d.py b/mne/viz/_3d.py index 15e87488206..f9bf5752329 100644 --- a/mne/viz/_3d.py +++ b/mne/viz/_3d.py @@ -425,7 +425,7 @@ def plot_alignment(info=None, trans=None, subject=None, subjects_dir=None, meg=None, eeg='original', fwd=None, dig=False, ecog=True, src=None, mri_fiducials=False, bem=None, seeg=True, fnirs=True, show_axes=False, fig=None, - interaction='trackball', verbose=None): + interaction='trackball', silhouette=None, verbose=None): """Plot head, sensor, and source space alignment in 3D. Parameters @@ -520,6 +520,12 @@ def plot_alignment(info=None, trans=None, subject=None, subjects_dir=None, * MEG in blue (if MEG sensors are present). .. versionadded:: 0.16 + silhouette : dict | None + As a dict, it contains the ``color``, ``linewidth`` and ``alpha``opacity + of the brain's silhouette to display, otherwise it is None. + Defauts to None. + + .. versionadded:: 0.22 fig : mayavi.mlab.Figure | None Mayavi Scene in which to plot the alignment. If ``None``, creates a new 600x600 pixel figure with black background. @@ -1029,7 +1035,11 @@ def plot_alignment(info=None, trans=None, subject=None, subjects_dir=None, for key, surf in surfs.items(): renderer.surface(surface=surf, color=colors[key], opacity=alphas[key], - backface_culling=(key != 'helmet')) + backface_culling=(key != 'helmet'), + silhouette=dict( + color=(0, 0, 0), + alpha=1.0, + linewidth=4)) if brain and 'lh' not in surfs: # one layer sphere assert bem['coord_frame'] == FIFF.FIFFV_COORD_HEAD center = bem['r0'].copy() diff --git a/mne/viz/backends/_pyvista.py b/mne/viz/backends/_pyvista.py index 1b340d2a974..8f595b91bde 100644 --- a/mne/viz/backends/_pyvista.py +++ b/mne/viz/backends/_pyvista.py @@ -302,7 +302,7 @@ def polydata(self, mesh, color=None, opacity=1.0, normals=None, backface_culling=False, scalars=None, colormap=None, vmin=None, vmax=None, interpolate_before_map=True, representation='surface', line_width=1., - polygon_offset=None, **kwargs): + polygon_offset=None, silhouette=None, **kwargs): with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=FutureWarning) rgba = False @@ -344,6 +344,25 @@ def polydata(self, mesh, color=None, opacity=1.0, normals=None, mapper.SetRelativeCoincidentTopologyPolygonOffsetParameters( polygon_offset, polygon_offset) + if silhouette is not None: + silhouette_filter = vtk.vtkPolyDataSilhouette() + silhouette_filter.SetInputData(mesh.decimate(0.9)) + silhouette_filter.SetCamera( + self.plotter.renderer.GetActiveCamera()) + silhouette_filter.SetEnableFeatureAngle(0) + silhouette_mapper = vtk.vtkPolyDataMapper() + silhouette_mapper.SetInputConnection( + silhouette_filter.GetOutputPort()) + _, prop = self.plotter.add_actor( + silhouette_mapper, reset_camera=False, name=None, + culling=False, pickable=False) + if "color" in silhouette: + prop.SetColor(silhouette["color"]) + if "alpha" in silhouette: + prop.SetOpacity(silhouette["alpha"]) + if "linewidth" in silhouette: + prop.SetLineWidth(silhouette["linewidth"]) + return actor, mesh def mesh(self, x, y, z, triangles, color, opacity=1.0, shading=False, @@ -408,7 +427,8 @@ def contour(self, surface, scalars, contours, width=1.0, opacity=1.0, def surface(self, surface, color=None, opacity=1.0, vmin=None, vmax=None, colormap=None, normalized_colormap=False, scalars=None, - backface_culling=False, polygon_offset=None): + backface_culling=False, polygon_offset=None, + silhouette=None): with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=FutureWarning) normals = surface.get('nn', None) @@ -430,6 +450,7 @@ def surface(self, surface, color=None, opacity=1.0, vmin=vmin, vmax=vmax, polygon_offset=polygon_offset, + silhouette=silhouette, ) def sphere(self, center, color, scale, opacity=1.0, diff --git a/tutorials/misc/plot_seeg.py b/tutorials/misc/plot_seeg.py index b7370f80693..959b94eca9f 100644 --- a/tutorials/misc/plot_seeg.py +++ b/tutorials/misc/plot_seeg.py @@ -118,9 +118,11 @@ ############################################################################### # Let's check to make sure everything is aligned. -fig = mne.viz.plot_alignment(raw.info, trans, 'fsaverage', - subjects_dir=subjects_dir, show_axes=True, - surfaces=["pial", "head"]) +fig = mne.viz.create_3d_figure() +mne.viz.plot_alignment(raw.info, trans, 'fsaverage', + subjects_dir=subjects_dir, show_axes=True, + surfaces=["pial", "head"], + fig=fig) ############################################################################### # Next, we'll get the raw data and plot its amplitude over time. From 01252fd227279ee9d83d8ac90328d9a785fd4d46 Mon Sep 17 00:00:00 2001 From: Guillaume Favelier Date: Mon, 18 Jan 2021 17:20:16 +0100 Subject: [PATCH 7/9] Fix example --- tutorials/misc/plot_seeg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorials/misc/plot_seeg.py b/tutorials/misc/plot_seeg.py index 959b94eca9f..d2af9a77857 100644 --- a/tutorials/misc/plot_seeg.py +++ b/tutorials/misc/plot_seeg.py @@ -118,7 +118,7 @@ ############################################################################### # Let's check to make sure everything is aligned. -fig = mne.viz.create_3d_figure() +fig = mne.viz.create_3d_figure(800, 600) mne.viz.plot_alignment(raw.info, trans, 'fsaverage', subjects_dir=subjects_dir, show_axes=True, surfaces=["pial", "head"], From 07748b830a1adb2c6d87fbf72f0d30793eeaf7c5 Mon Sep 17 00:00:00 2001 From: Guillaume Favelier Date: Mon, 18 Jan 2021 17:27:19 +0100 Subject: [PATCH 8/9] Fix example --- mne/viz/_3d.py | 5 +---- tutorials/misc/plot_seeg.py | 6 +++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mne/viz/_3d.py b/mne/viz/_3d.py index 5e6af32b17c..d0e4bf94356 100644 --- a/mne/viz/_3d.py +++ b/mne/viz/_3d.py @@ -1038,10 +1038,7 @@ def plot_alignment(info=None, trans=None, subject=None, subjects_dir=None, renderer.surface(surface=surf, color=colors[key], opacity=alphas[key], backface_culling=(key != 'helmet'), - silhouette=dict( - color=(0, 0, 0), - alpha=1.0, - linewidth=4)) + silhouette=silhouette) if brain and 'lh' not in surfs: # one layer sphere assert bem['coord_frame'] == FIFF.FIFFV_COORD_HEAD center = bem['r0'].copy() diff --git a/tutorials/misc/plot_seeg.py b/tutorials/misc/plot_seeg.py index d2af9a77857..832a380cc35 100644 --- a/tutorials/misc/plot_seeg.py +++ b/tutorials/misc/plot_seeg.py @@ -118,10 +118,14 @@ ############################################################################### # Let's check to make sure everything is aligned. -fig = mne.viz.create_3d_figure(800, 600) +fig = mne.viz.create_3d_figure(size=(800, 600)) mne.viz.plot_alignment(raw.info, trans, 'fsaverage', subjects_dir=subjects_dir, show_axes=True, surfaces=["pial", "head"], + silhouette=dict( + color=(0, 0, 0), + alpha=1.0, + linewidth=4), fig=fig) ############################################################################### From 01d440ff7d4cb0711d44a5823a56764dddb4e983 Mon Sep 17 00:00:00 2001 From: Guillaume Favelier Date: Mon, 18 Jan 2021 17:37:05 +0100 Subject: [PATCH 9/9] Fix docstring --- mne/viz/_3d.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mne/viz/_3d.py b/mne/viz/_3d.py index d0e4bf94356..5b7ced94f2b 100644 --- a/mne/viz/_3d.py +++ b/mne/viz/_3d.py @@ -526,7 +526,7 @@ def plot_alignment(info=None, trans=None, subject=None, subjects_dir=None, silhouette : dict | None As a dict, it contains the ``color``, ``linewidth`` and ``alpha``opacity of the brain's silhouette to display, otherwise it is None. - Defauts to None. + Defaults to None. fig : mayavi.mlab.Figure | None Mayavi Scene in which to plot the alignment. If ``None``, creates a new 600x600 pixel figure with black background.