@@ -137,6 +137,8 @@ class Brain:
137137 Add support for non-string arguments.
138138 alpha : float in [0, 1]
139139 Alpha level to control opacity of the cortical surface.
140+
141+ See :meth:`set_cortex_alpha` to change this after creation.
140142 size : int | array-like, shape (2,)
141143 The size of the window, in pixels. can be one number to specify
142144 a square window, or a length-2 sequence to specify (width, height).
@@ -182,6 +184,9 @@ class Brain:
182184
183185 .. versionchanged:: 1.13
184186 The default ``decimate`` value changed from ``0.9`` to ``"ico5"``.
187+
188+ See :meth:`set_silhouette_line_width` to change the line width (or
189+ show/hide the silhouette) after creation.
185190 %(theme_3d)s
186191 show : bool
187192 Display the window as soon as it is ready. Defaults to True.
@@ -399,6 +404,7 @@ def __init__(
399404 self .silhouette = True
400405 else :
401406 self .silhouette = silhouette
407+ self ._silhouette_actors = []
402408 self ._scalar_bar = None
403409 self ._scalar_bar_ticks = None
404410 # for now only one time label can be added
@@ -474,35 +480,11 @@ def __init__(
474480 else :
475481 actor = self .layered_meshes [h ]._actor
476482 self ._renderer .plotter .add_actor (actor , render = False )
477- if self .silhouette :
478- mesh = self .layered_meshes [h ]
479- decimate = self ._silhouette ["decimate" ]
480- if isinstance (decimate , str ):
481- import pyvista as pv
482-
483- vertno , tris = _decimate_surface_ico_oct (
484- self ._subject ,
485- self ._subjects_dir ,
486- h ,
487- self .geo [h ].surf ,
488- decimate ,
489- )
490- sil_mesh = pv .PolyData (
491- self .geo [h ].coords [vertno ],
492- np .c_ [np .full (len (tris ), 3 ), tris ],
493- )
494- decimate = None # already decimated
495- else :
496- sil_mesh = mesh ._polydata
497- self ._renderer ._silhouette (
498- mesh = sil_mesh ,
499- color = self ._silhouette ["color" ],
500- line_width = self ._silhouette ["line_width" ],
501- alpha = self ._silhouette ["alpha" ],
502- decimate = decimate ,
503- )
504483 self ._set_camera (** views_dicts [h ][v ])
505484
485+ if self .silhouette :
486+ self ._add_silhouette ()
487+
506488 self .interaction = interaction
507489 self ._closed = False
508490 if show :
@@ -658,6 +640,9 @@ def _clean(self):
658640 # clear init actors
659641 for hemi in self .layered_meshes :
660642 self .layered_meshes [hemi ]._clean ()
643+ for actor in getattr (self , "_silhouette_actors" , None ) or ():
644+ self .plotter .remove_actor (actor )
645+ self ._silhouette_actors = None
661646 self ._clear_callbacks ()
662647 self ._clear_widgets ()
663648 if getattr (self , "mpl_canvas" , None ) is not None :
@@ -820,7 +805,7 @@ def current_time_func():
820805 del current_time
821806
822807 def _configure_dock_orientation_widget (self , name ):
823- layout = self ._renderer ._dock_add_group_box (name )
808+ layout = self ._renderer ._dock_add_group_box (name , collapse = True )
824809 # Renderer widget
825810 rends = [str (i ) for i in range (len (self ._renderer ._all_renderers ))]
826811 if len (rends ) > 1 :
@@ -876,13 +861,31 @@ def set_orientation(value, orientation_data=orientation_data):
876861 layout = layout ,
877862 )
878863
864+ def _configure_dock_surface_widget (self , name ):
865+ layout = self ._renderer ._dock_add_group_box (name , collapse = True )
866+ self .widgets ["cortex_alpha" ] = self ._renderer ._dock_add_slider (
867+ name = "Alpha" ,
868+ value = self ._alpha ,
869+ rng = [0.0 , 1.0 ],
870+ callback = self .set_cortex_alpha ,
871+ double = True ,
872+ layout = layout ,
873+ )
874+ self .widgets ["silhouette" ] = self ._renderer ._dock_add_spin_box (
875+ name = "Silhouette" ,
876+ value = self ._silhouette ["line_width" ] if self .silhouette else 0.0 ,
877+ rng = [0.0 , 10.0 ],
878+ callback = self .set_silhouette_line_width ,
879+ layout = layout ,
880+ )
881+
879882 def _configure_dock_colormap_widget (self , name ):
880883 self ._active_data_key = next (iter (self ._all_data ))
881884 fmax , fscale , fscale_power = _get_range (self )
882885 rng = [0 , fmax * fscale ]
883886 self ._data ["fscale" ] = fscale
884887
885- layout = self ._renderer ._dock_add_group_box (name )
888+ layout = self ._renderer ._dock_add_group_box (name , collapse = False )
886889
887890 @_auto_weakref
888891 def select_data_key (value ):
@@ -969,6 +972,16 @@ def fplus():
969972 style = "toolbutton" ,
970973 )
971974 self ._renderer ._layout_add_widget (layout , hlayout )
975+
976+ self .widgets ["smoothing" ] = self ._renderer ._dock_add_spin_box (
977+ name = "Smoothing" ,
978+ value = self ._data ["smoothing_steps" ],
979+ rng = self .default_smoothing_range ,
980+ callback = self .set_data_smoothing ,
981+ double = False ,
982+ layout = layout ,
983+ )
984+
972985 self ._update_colormap_range ()
973986
974987 def _refresh_colormap_widgets (self ):
@@ -1006,7 +1019,7 @@ def _configure_dock_trace_widget(self, name):
10061019 self ._configure_vertex_time_course ()
10071020 return
10081021
1009- layout = self ._renderer ._dock_add_group_box (name )
1022+ layout = self ._renderer ._dock_add_group_box (name , collapse = True )
10101023
10111024 # setup candidate annots
10121025 @_auto_weakref
@@ -1078,19 +1091,10 @@ def _set_label_mode(mode):
10781091 def _configure_dock (self ):
10791092 self ._renderer ._dock_initialize ()
10801093 self ._configure_dock_playback_widget (name = "Playback" )
1081- self ._configure_dock_orientation_widget (name = "Orientation" )
10821094 self ._configure_dock_colormap_widget (name = "Color Limits" )
1095+ self ._configure_dock_orientation_widget (name = "Orientation" )
1096+ self ._configure_dock_surface_widget (name = "Surface" )
10831097 self ._configure_dock_trace_widget (name = "Trace" )
1084-
1085- # Smoothing widget
1086- self .widgets ["smoothing" ] = self ._renderer ._dock_add_spin_box (
1087- name = "Smoothing" ,
1088- value = self ._data ["smoothing_steps" ],
1089- rng = self .default_smoothing_range ,
1090- callback = self .set_data_smoothing ,
1091- double = False ,
1092- )
1093-
10941098 self ._renderer ._dock_finalize ()
10951099
10961100 def _configure_mplcanvas (self ):
@@ -3746,6 +3750,72 @@ def screenshot(self, mode="rgb", time_viewer=False):
37463750 )
37473751 return img
37483752
3753+ def set_cortex_alpha (self , alpha ):
3754+ """Set the opacity of the cortical surface.
3755+
3756+ Parameters
3757+ ----------
3758+ alpha : float
3759+ The opacity of the cortical surface, between 0 and 1.
3760+ """
3761+ self ._alpha = float (alpha )
3762+ for hemi in self ._hemis :
3763+ self .layered_meshes [hemi ].update_overlay ("curv" , opacity = self ._alpha )
3764+ self ._renderer ._update ()
3765+
3766+ def _add_silhouette (self ):
3767+ self ._silhouette_actors = []
3768+ for h in self ._hemis :
3769+ mesh = self .layered_meshes [h ]
3770+ for _ , _ , v in self ._iter_views (h ):
3771+ self ._set_camera (** views_dicts [h ][v ])
3772+ decimate = self ._silhouette ["decimate" ]
3773+ if isinstance (decimate , str ):
3774+ import pyvista as pv
3775+
3776+ vertno , tris = _decimate_surface_ico_oct (
3777+ self ._subject , self ._subjects_dir , h , self .geo [h ].surf , decimate
3778+ )
3779+ sil_mesh = pv .PolyData (
3780+ self .geo [h ].coords [vertno ],
3781+ np .c_ [np .full (len (tris ), 3 ), tris ],
3782+ )
3783+ decimate = None # already decimated
3784+ else :
3785+ sil_mesh = mesh ._polydata
3786+ actor = self ._renderer ._silhouette (
3787+ mesh = sil_mesh ,
3788+ color = self ._silhouette ["color" ],
3789+ line_width = self ._silhouette ["line_width" ],
3790+ alpha = self ._silhouette ["alpha" ],
3791+ decimate = decimate ,
3792+ )
3793+ self ._silhouette_actors .append (actor )
3794+
3795+ def set_silhouette_line_width (self , line_width ):
3796+ """Set the width of the cortical surface silhouette outline.
3797+
3798+ Parameters
3799+ ----------
3800+ line_width : float
3801+ The silhouette line width. A value of ``0`` hides the
3802+ silhouette entirely.
3803+ """
3804+ line_width = float (line_width )
3805+ self ._silhouette ["line_width" ] = line_width
3806+ if line_width <= 0 :
3807+ self .silhouette = False
3808+ for actor in self ._silhouette_actors :
3809+ actor .SetVisibility (False )
3810+ else :
3811+ self .silhouette = True
3812+ if not self ._silhouette_actors :
3813+ self ._add_silhouette ()
3814+ for actor in self ._silhouette_actors :
3815+ actor .GetProperty ().SetLineWidth (line_width )
3816+ actor .SetVisibility (True )
3817+ self ._renderer ._update ()
3818+
37493819 @fill_doc
37503820 def update_lut (self , fmin = None , fmid = None , fmax = None , alpha = None ):
37513821 """Update the range of the color map.
0 commit comments