44import numpy as np
55
66from surfa import Mesh
7+ from surfa import load_volume
8+ from surfa import load_mesh
79from surfa .system import run
810from surfa .system import collect_output
911from surfa .image import cast_image
1214
1315class Freeview :
1416
15- def __init__ (self , title = None , debug = False , use_vglrun = True ):
17+ def __init__ (self , title = None , debug = False , use_vglrun = True , return_edits = False ):
1618 """
1719 A visualization class that wraps the `freeview` command.
1820
@@ -25,6 +27,17 @@ def __init__(self, title=None, debug=False, use_vglrun=True):
2527 fv.add_mesh(mesh, overlay=overlay)
2628 fv.show()
2729
30+ To reload the data visualized inf FreeView after the viewer closes, specify
31+ 'return_edits=True' and assign the return value of fv.show() to be a variable:
32+
33+ fv = Freeview(return_edits=True)
34+ fv.add_image(img)
35+ fv_contents = fv.show()
36+
37+ This will return a tuple of lists, with the first list containing volumes and
38+ the second list containing any data added to the viewer via fv.add_mesh(mesh).
39+ Items will be returned in the order that they are added to FreeView.
40+
2841 For a quicker but more limited way to wrap freeview, see the `fv()` function.
2942 """
3043 self .tempdir = None
@@ -33,6 +46,10 @@ def __init__(self, title=None, debug=False, use_vglrun=True):
3346 self .isshown = False
3447 self .use_vglrun = use_vglrun
3548 self .arguments = []
49+ self ._return_edits = return_edits
50+ self ._vols = []
51+ self ._meshes = []
52+
3653
3754 # first check if freeview is even accessible
3855 self .fvpath = shutil .which ('freeview' )
@@ -77,6 +94,9 @@ def add_image(self, img, **kwargs):
7794 img .save (filename )
7895 if self .debug :
7996 print (f'wrote image to { filename } ' )
97+
98+ # add the path to the temp vol to the internal list of volumes
99+ self ._vols .append (filename )
80100
81101 # configure the corresponding freeview argument
82102 self .arguments .append ('-v ' + filename + _convert_kwargs_to_tags (kwargs ))
@@ -149,6 +169,9 @@ def add_mesh(self, mesh, curvature=None, overlay=None, annot=None, name=None, **
149169
150170 if name is not None :
151171 tags += f':name={ name } '
172+
173+ # add the path to the temp vol to the internal list of volumes
174+ self ._meshes .append (filename )
152175
153176 # configure the corresponding freeview argument
154177 self .arguments .append ('-f ' + mesh_filename + tags + _convert_kwargs_to_tags (kwargs ))
@@ -175,7 +198,9 @@ def show(self, background=True, threads=None):
175198 threads : int
176199 Number of OMP threads available to FreeView.
177200 """
178-
201+ # set background based on _return_edits
202+ background = background if not self ._return_edits else False
203+
179204 # compile the command
180205 command = self .fvpath + ' ' + ' ' .join (self .arguments )
181206
@@ -185,7 +210,9 @@ def show(self, background=True, threads=None):
185210 command = f'{ command } -subtitle "{ title } "'
186211
187212 # be sure to remove the temporary directory (if it exists) after freeview closes
188- command = f'{ command } ; rm -rf { self .tempdir } '
213+ # need the tempdir if saving edits
214+ if not self ._return_edits :
215+ command = f'{ command } ; rm -rf { self .tempdir } '
189216
190217 # freeview can be buggy when run remotely, so let's test if VGL is
191218 # available to wrap the process
@@ -206,7 +233,18 @@ def show(self, background=True, threads=None):
206233 self .isshown = True
207234
208235 # run it
209- run (command , background = background )
236+ ret_code = run (command , background = background )
237+
238+ # reload the vol/mesh data before deleting the tempdir, if necessary
239+ if self ._return_edits :
240+ print ('Reloading temp volumes into surfa' )
241+ vols = [load_volume (x ) for x in self ._vols ]
242+ meshes = [load_mesh (x ) for x in self ._meshes ]
243+
244+ # clean up the tempdir
245+ shutil .rmtree (self .tempdir )
246+
247+ return vols , meshes
210248
211249
212250class FreeviewCurvature :
0 commit comments