@@ -120,8 +120,6 @@ class _Brain(object):
120
120
+---------------------------+--------------+-----------------------+
121
121
| labels_dict | ✓ | |
122
122
+---------------------------+--------------+-----------------------+
123
- | overlays | ✓ | - |
124
- +---------------------------+--------------+-----------------------+
125
123
| remove_data | ✓ | |
126
124
+---------------------------+--------------+-----------------------+
127
125
| remove_foci | ✓ | |
@@ -134,6 +132,8 @@ class _Brain(object):
134
132
+---------------------------+--------------+-----------------------+
135
133
| show_view | ✓ | - |
136
134
+---------------------------+--------------+-----------------------+
135
+ | TimeViewer | ✓ | ✓ |
136
+ +---------------------------+--------------+-----------------------+
137
137
138
138
"""
139
139
@@ -181,7 +181,6 @@ def __init__(self, subject_id, hemi, surf, title=None,
181
181
self ._subjects_dir = subjects_dir
182
182
self ._views = views
183
183
self ._n_times = None
184
- self ._scalarbar = False
185
184
# for now only one color bar can be added
186
185
# since it is the same for all figures
187
186
self ._colorbar_added = False
@@ -336,6 +335,7 @@ def add_data(self, array, fmin=None, fmid=None, fmax=None,
336
335
337
336
hemi = self ._check_hemi (hemi )
338
337
array = np .asarray (array )
338
+ self ._data ['array' ] = array
339
339
340
340
# Create time array and add label if > 1D
341
341
if array .ndim <= 1 :
@@ -393,8 +393,10 @@ def time_label(x):
393
393
self ._data ['initial_time' ] = initial_time
394
394
self ._data ['time_label' ] = time_label
395
395
self ._data ['time_idx' ] = time_idx
396
+ self ._data ['transparent' ] = transparent
396
397
# data specific for a hemi
397
398
self ._data [hemi + '_array' ] = array
399
+ self ._data [hemi + '_vertices' ] = vertices
398
400
399
401
self ._data ['alpha' ] = alpha
400
402
self ._data ['colormap' ] = colormap
@@ -419,7 +421,7 @@ def time_label(x):
419
421
dt_max = fmax
420
422
dt_min = fmin if center is None else - 1 * fmax
421
423
422
- ctable = self .update_lut (transparent = transparent )
424
+ ctable = self .update_lut ()
423
425
424
426
for ri , v in enumerate (self ._views ):
425
427
views_dict = lh_views_dict if hemi == 'lh' else rh_views_dict
@@ -428,22 +430,33 @@ def time_label(x):
428
430
else :
429
431
ci = 0 if hemi == 'lh' else 1
430
432
self ._renderer .subplot (ri , ci )
431
- mesh = self ._renderer .mesh (x = self .geo [hemi ].coords [:, 0 ],
432
- y = self .geo [hemi ].coords [:, 1 ],
433
- z = self .geo [hemi ].coords [:, 2 ],
434
- triangles = self .geo [hemi ].faces ,
435
- color = None ,
436
- colormap = ctable ,
437
- vmin = dt_min ,
438
- vmax = dt_max ,
439
- scalars = act_data )
433
+ mesh_data = self ._renderer .mesh (
434
+ x = self .geo [hemi ].coords [:, 0 ],
435
+ y = self .geo [hemi ].coords [:, 1 ],
436
+ z = self .geo [hemi ].coords [:, 2 ],
437
+ triangles = self .geo [hemi ].faces ,
438
+ color = None ,
439
+ colormap = ctable ,
440
+ vmin = dt_min ,
441
+ vmax = dt_max ,
442
+ scalars = act_data
443
+ )
444
+ if isinstance (mesh_data , tuple ):
445
+ actor , mesh = mesh_data
446
+ else :
447
+ actor , mesh = mesh_data , None
448
+ self ._data [hemi + '_actor' ] = actor
449
+ self ._data [hemi + '_mesh' ] = mesh
440
450
if array .ndim >= 2 and callable (time_label ):
441
- self ._renderer .text2d (x_window = 0.95 , y_window = y_txt ,
442
- size = time_label_size ,
443
- text = time_label (time [time_idx ]),
444
- justification = 'right' )
451
+ time_actor = self ._renderer .text2d (
452
+ x_window = 0.95 , y_window = y_txt ,
453
+ size = time_label_size ,
454
+ text = time_label (time [time_idx ]),
455
+ justification = 'right'
456
+ )
457
+ self ._data [hemi + '_time_actor' ] = time_actor
445
458
if colorbar and not self ._colorbar_added :
446
- self ._renderer .scalarbar (source = mesh , n_labels = 8 ,
459
+ self ._renderer .scalarbar (source = actor , n_labels = 8 ,
447
460
bgcolor = (0.5 , 0.5 , 0.5 ))
448
461
self ._colorbar_added = True
449
462
self ._renderer .set_camera (azimuth = views_dict [v ].azim ,
@@ -763,7 +776,7 @@ def screenshot(self, mode='rgb'):
763
776
"""
764
777
return self ._renderer .screenshot (mode )
765
778
766
- def update_lut (self , fmin = None , fmid = None , fmax = None , transparent = True ):
779
+ def update_lut (self , fmin = None , fmid = None , fmax = None ):
767
780
u"""Update color map.
768
781
769
782
Parameters
@@ -779,6 +792,7 @@ def update_lut(self, fmin=None, fmid=None, fmax=None, transparent=True):
779
792
alpha = self ._data ['alpha' ]
780
793
center = self ._data ['center' ]
781
794
colormap = self ._data ['colormap' ]
795
+ transparent = self ._data ['transparent' ]
782
796
fmin = self ._data ['fmin' ] if fmin is None else fmin
783
797
fmid = self ._data ['fmid' ] if fmid is None else fmid
784
798
fmax = self ._data ['fmax' ] if fmax is None else fmax
@@ -789,9 +803,146 @@ def update_lut(self, fmin=None, fmid=None, fmax=None, transparent=True):
789
803
790
804
return self ._data ['ctable' ]
791
805
792
- @property
793
- def overlays (self ):
794
- return self ._overlays
806
+ def set_data_smoothing (self , n_steps ):
807
+ """Set the number of smoothing steps.
808
+
809
+ Parameters
810
+ ----------
811
+ n_steps : int
812
+ Number of smoothing steps
813
+ """
814
+ from ..backends ._pyvista import _set_mesh_scalars
815
+ for hemi in ['lh' , 'rh' ]:
816
+ pd = self ._data .get (hemi + '_mesh' )
817
+ if pd is not None :
818
+ array = self ._data [hemi + '_array' ]
819
+ vertices = self ._data [hemi + '_vertices' ]
820
+ if pd is not None :
821
+ time_idx = self ._data ['time_idx' ]
822
+ if self ._data ['array' ].ndim == 1 :
823
+ act_data = array
824
+ elif self ._data ['array' ].ndim == 2 :
825
+ act_data = array [:, time_idx ]
826
+
827
+ adj_mat = mesh_edges (self .geo [hemi ].faces )
828
+ smooth_mat = smoothing_matrix (vertices ,
829
+ adj_mat , int (n_steps ),
830
+ verbose = False )
831
+ act_data = smooth_mat .dot (act_data )
832
+ _set_mesh_scalars (pd , act_data , 'Data' )
833
+ self ._data [hemi + '_smooth_mat' ] = smooth_mat
834
+
835
+ def set_time_point (self , time_idx ):
836
+ """Set the time point shown."""
837
+ from ..backends ._pyvista import _set_mesh_scalars
838
+ time_idx = int (time_idx )
839
+ for hemi in ['lh' , 'rh' ]:
840
+ pd = self ._data .get (hemi + '_mesh' )
841
+ if pd is not None :
842
+ array = self ._data [hemi + '_array' ]
843
+ time = self ._data ['time' ]
844
+ time_label = self ._data ['time_label' ]
845
+ time_actor = self ._data .get (hemi + '_time_actor' )
846
+ if array .ndim == 1 :
847
+ continue # skip data without time axis
848
+ # interpolation
849
+ if array .ndim == 2 :
850
+ act_data = array
851
+
852
+ if isinstance (time_idx , int ):
853
+ act_data = act_data [:, time_idx ]
854
+
855
+ smooth_mat = self ._data [hemi + '_smooth_mat' ]
856
+ if smooth_mat is not None :
857
+ act_data = smooth_mat .dot (act_data )
858
+ _set_mesh_scalars (pd , act_data , 'Data' )
859
+ if callable (time_label ) and time_actor is not None :
860
+ time_actor .SetInput (time_label (time [time_idx ]))
861
+ self ._data ['time_idx' ] = time_idx
862
+
863
+ def update_fmax (self , fmax ):
864
+ """Set the colorbar max point."""
865
+ from ..backends ._pyvista import _set_colormap_range
866
+ if fmax > self ._data ['fmid' ]:
867
+ ctable = self .update_lut (fmax = fmax )
868
+ ctable = (ctable * 255 ).astype (np .uint8 )
869
+ center = self ._data ['center' ]
870
+ for hemi in ['lh' , 'rh' ]:
871
+ actor = self ._data .get (hemi + '_actor' )
872
+ if actor is not None :
873
+ fmin = self ._data ['fmin' ]
874
+ center = self ._data ['center' ]
875
+ dt_max = fmax
876
+ dt_min = fmin if center is None else - 1 * fmax
877
+ rng = [dt_min , dt_max ]
878
+ if self ._colorbar_added :
879
+ scalar_bar = self ._renderer .plotter .scalar_bar
880
+ else :
881
+ scalar_bar = None
882
+ _set_colormap_range (actor , ctable , scalar_bar , rng )
883
+ self ._data ['fmax' ] = fmax
884
+ self ._data ['ctable' ] = ctable
885
+
886
+ def update_fmid (self , fmid ):
887
+ """Set the colorbar mid point."""
888
+ from ..backends ._pyvista import _set_colormap_range
889
+ if self ._data ['fmin' ] < fmid < self ._data ['fmax' ]:
890
+ ctable = self .update_lut (fmid = fmid )
891
+ ctable = (ctable * 255 ).astype (np .uint8 )
892
+ for hemi in ['lh' , 'rh' ]:
893
+ actor = self ._data .get (hemi + '_actor' )
894
+ if actor is not None :
895
+ if self ._colorbar_added :
896
+ scalar_bar = self ._renderer .plotter .scalar_bar
897
+ else :
898
+ scalar_bar = None
899
+ _set_colormap_range (actor , ctable , scalar_bar )
900
+ self ._data ['fmid' ] = fmid
901
+ self ._data ['ctable' ] = ctable
902
+
903
+ def update_fmin (self , fmin ):
904
+ """Set the colorbar min point."""
905
+ from ..backends ._pyvista import _set_colormap_range
906
+ if fmin < self ._data ['fmid' ]:
907
+ ctable = self .update_lut (fmin = fmin )
908
+ ctable = (ctable * 255 ).astype (np .uint8 )
909
+ for hemi in ['lh' , 'rh' ]:
910
+ actor = self ._data .get (hemi + '_actor' )
911
+ if actor is not None :
912
+ fmax = self ._data ['fmax' ]
913
+ center = self ._data ['center' ]
914
+ dt_max = fmax
915
+ dt_min = fmin if center is None else - 1 * fmax
916
+ rng = [dt_min , dt_max ]
917
+ if self ._colorbar_added :
918
+ scalar_bar = self ._renderer .plotter .scalar_bar
919
+ else :
920
+ scalar_bar = None
921
+ _set_colormap_range (actor , ctable , scalar_bar , rng )
922
+ self ._data ['fmin' ] = fmin
923
+ self ._data ['ctable' ] = ctable
924
+
925
+ def update_fscale (self , fscale ):
926
+ """Scale the colorbar points."""
927
+ from ..backends ._pyvista import _set_colormap_range
928
+ fmin = self ._data ['fmin' ] * fscale
929
+ fmid = self ._data ['fmid' ] * fscale
930
+ fmax = self ._data ['fmax' ] * fscale
931
+ ctable = self .update_lut (fmin = fmin , fmid = fmid , fmax = fmax )
932
+ ctable = (ctable * 255 ).astype (np .uint8 )
933
+ for hemi in ['lh' , 'rh' ]:
934
+ actor = self ._data .get (hemi + '_actor' )
935
+ if actor is not None :
936
+ center = self ._data ['center' ]
937
+ dt_max = fmax
938
+ dt_min = fmin if center is None else - 1 * fmax
939
+ rng = [dt_min , dt_max ]
940
+ if self ._colorbar_added :
941
+ scalar_bar = self ._renderer .plotter .scalar_bar
942
+ else :
943
+ scalar_bar = None
944
+ _set_colormap_range (actor , ctable , scalar_bar , rng )
945
+ self ._data ['ctable' ] = ctable
795
946
796
947
@property
797
948
def data (self ):
0 commit comments