@@ -534,7 +534,12 @@ def write_vtk(tria: "TriaMesh", filename: str) -> None:
534534 f .close ()
535535
536536
537- def write_fssurf (tria : "TriaMesh" , filename : str , image : Optional [object ] = None ) -> None :
537+ def write_fssurf (
538+ tria : "TriaMesh" ,
539+ filename : str ,
540+ image : Optional [object ] = None ,
541+ coords_are_voxels : Optional [bool ] = None ,
542+ ) -> None :
538543 """Save Freesurfer Surface Geometry file (wrap Nibabel).
539544
540545 Parameters
@@ -544,13 +549,23 @@ def write_fssurf(tria: "TriaMesh", filename: str, image: Optional[object] = None
544549 filename : str
545550 Filename to save to.
546551 image : str, object, or None, default=None
547- Path to image, nibabel image object, or image header. If specified, the vertices
548- are assumed to be in voxel coordinates and are converted to surface RAS (tkr)
549- coordinates before saving. The expected order of coordinates is (x, y, z)
550- matching the image voxel indices in nibabel.
552+ Path to image, nibabel image object, or image header. If specified, volume_info
553+ will be extracted from the image header, and by default, vertices are assumed to
554+ be in voxel coordinates and will be converted to surface RAS (tkr) before saving.
555+ The expected order of coordinates is (x, y, z) matching the image voxel indices
556+ in nibabel.
557+ coords_are_voxels : bool or None, default=None
558+ Specifies whether vertices are in voxel coordinates. If None (default), the
559+ behavior is inferred: when image is provided, vertices are assumed to be in
560+ voxel space and converted to surface RAS; when image is not provided, vertices
561+ are assumed to already be in surface RAS. Set explicitly to True to force
562+ conversion (requires image), or False to skip conversion even when image is
563+ provided (only extracts volume_info).
551564
552565 Raises
553566 ------
567+ ValueError
568+ If coords_are_voxels is explicitly True but image is None.
554569 OSError
555570 If file is not writable.
556571 TypeError
@@ -562,6 +577,17 @@ def write_fssurf(tria: "TriaMesh", filename: str, image: Optional[object] = None
562577 ``get_vox2ras_tkr()`` (e.g., ``MGHHeader``). For other header types (NIfTI1/2,
563578 Analyze/SPM, etc.), we attempt conversion via ``MGHHeader.from_header``.
564579 """
580+ # Infer coords_are_voxels if not explicitly set
581+ if coords_are_voxels is None :
582+ coords_are_voxels = image is not None
583+
584+ # Validate parameters
585+ if coords_are_voxels and image is None :
586+ raise ValueError (
587+ "coords_are_voxels=True requires an image to be provided for voxel-to-surface-RAS "
588+ "coordinate conversion. Either provide an image or set coords_are_voxels=False."
589+ )
590+
565591 # open file
566592 try :
567593 from nibabel .freesurfer .io import write_geometry
@@ -594,7 +620,9 @@ def write_fssurf(tria: "TriaMesh", filename: str, image: Optional[object] = None
594620 "via MGHHeader.from_header)."
595621 ) from e
596622
597- v = apply_affine (header .get_vox2ras_tkr (), v )
623+ # Convert from voxel to surface RAS coordinates if requested
624+ if coords_are_voxels :
625+ v = apply_affine (header .get_vox2ras_tkr (), v )
598626
599627 # create volume_info from header
600628 affine = header .get_best_affine ()
0 commit comments