diff --git a/surfa/io/framed.py b/surfa/io/framed.py index fcfbf54..5019a88 100644 --- a/surfa/io/framed.py +++ b/surfa/io/framed.py @@ -158,7 +158,8 @@ def save_framed_array(arr, filename, fmt=None, intent=FramedArrayIntents.mri): iop = protocol.find_protocol_by_name(array_io_protocols, fmt) if iop is None: raise ValueError(f'unknown file format {fmt}') - filename = iop.enforce_extension(filename) + if iop.name != 'curv': + filename = iop.enforce_extension(filename) # pass intent if iop() is an instance of MGHArrayIO if (isinstance(iop(), MGHArrayIO)): diff --git a/surfa/vis/freeview.py b/surfa/vis/freeview.py index 3fe6330..2052073 100644 --- a/surfa/vis/freeview.py +++ b/surfa/vis/freeview.py @@ -80,7 +80,7 @@ def add_image(self, img, **kwargs): # configure the corresponding freeview argument self.arguments.append('-v ' + filename + _convert_kwargs_to_tags(kwargs)) - def add_mesh(self, mesh, overlay=None, annot=None, **kwargs): + def add_mesh(self, mesh, curvature=None, overlay=None, annot=None, name=None, **kwargs): """ Adds an image to the freeview window. Any key/value tags allowed as a `-v` option in the freeview command line can be provided as an additional argument. @@ -113,6 +113,17 @@ def add_mesh(self, mesh, overlay=None, annot=None, **kwargs): # extra tags for the mesh tags = '' + # configure any curvatures + if curvature is not None: + curvature = [curvature] if not isinstance(curvature, (list, tuple)) else curvature + for c in curvature: + c = FreeviewCurvature(c) if not isinstance(c, FreeviewCurvature) else c + filename = _unique_filename(c.name, '.mgz', self.tempdir) + c.arr.save(filename) + if self.debug: + print(f'wrote curvature to {filename}') + tags += f':curvature={filename}' + c.tags() + # configure any overlays if overlay is not None: overlay = [overlay] if not isinstance(overlay, (list, tuple)) else overlay @@ -135,6 +146,9 @@ def add_mesh(self, mesh, overlay=None, annot=None, **kwargs): print(f'wrote annotation to {filename}') tags += f':annot={filename}' + if name is not None: + tags += f':name={name}' + # configure the corresponding freeview argument self.arguments.append('-f ' + mesh_filename + tags + _convert_kwargs_to_tags(kwargs)) @@ -193,9 +207,25 @@ def show(self, background=True, threads=None): run(command, background=background) +class FreeviewCurvature: + + def __init__(self, arr, name='curvature', method='binary'): + """ + Configuration for freeview curvature. + """ + self.arr = cast_overlay(arr, allow_none=False) + self.name = name + self.method = method + + def tags(self): + tags = '' + tags += '' if self.method is None else f':curvature_method={self.method}' + return tags + + class FreeviewOverlay: - def __init__(self, arr, name='overlay', threshold=None, opacity=None): + def __init__(self, arr, name='overlay', threshold=None, opacity=None, color=None, custom=None): """ Configuration for freeview overlays. """ @@ -203,11 +233,15 @@ def __init__(self, arr, name='overlay', threshold=None, opacity=None): self.name = name self.threshold = threshold self.opacity = opacity + self.color = color + self.custom = custom def tags(self): tags = '' - tags += '' if self.threshold is None else f':overlay_threshold=' + ','.join(str(x) for x in config.threshold) + tags += '' if self.threshold is None else f':overlay_threshold=' + ','.join(str(x) for x in self.threshold) tags += '' if self.opacity is None else f':overlay_opacity={self.opacity}' + tags += '' if self.color is None else f':overlay_color={self.color}' + tags += '' if self.custom is None else f':overlay_custom={self.custom}' return tags