Source code for smriprep.interfaces.workbench

from nipype.interfaces.base import CommandLineInputSpec, File, TraitedSpec, traits
from nipype.interfaces.workbench.base import WBCommand


class CreateSignedDistanceVolumeInputSpec(CommandLineInputSpec):
    surf_file = File(
        exists=True,
        mandatory=True,
        argstr='%s',
        position=0,
        desc='Input surface GIFTI file (.surf.gii)',
    )
    ref_file = File(
        exists=True,
        mandatory=True,
        argstr='%s',
        position=1,
        desc='NIfTI volume in the desired output space (dims, spacing, origin)',
    )
    out_file = File(
        name_source=['surf_file'],
        name_template='%s_distvol.nii.gz',
        argstr='%s',
        position=2,
        desc='Name of output volume containing signed distances',
    )
    out_mask = File(
        name_source=['surf_file'],
        name_template='%s_distmask.nii.gz',
        argstr='-roi-out %s',
        desc='Name of file to store a mask where the ``out_file`` has a computed value',
    )
    fill_value = traits.Float(
        0.0,
        mandatory=False,
        usedefault=True,
        argstr='-fill-value %f',
        desc="value to put in all voxels that don't get assigned a distance",
    )
    exact_limit = traits.Float(
        5.0,
        usedefault=True,
        argstr='-exact-limit %f',
        desc='distance for exact output in mm',
    )
    approx_limit = traits.Float(
        20.0,
        usedefault=True,
        argstr='-approx-limit %f',
        desc='distance for approximate output in mm',
    )
    approx_neighborhood = traits.Int(
        2,
        usedefault=True,
        argstr='-approx-neighborhood %d',
        desc='size of neighborhood cube measured from center to face in voxels, default 2 = 5x5x5',
    )
    winding_method = traits.Enum(
        'EVEN_ODD',
        'NEGATIVE',
        'NONZERO',
        'NORMALS',
        argstr='-winding %s',
        usedefault=True,
        desc='winding method for point inside surface test',
    )


class CreateSignedDistanceVolumeOutputSpec(TraitedSpec):
    out_file = File(desc='Name of output volume containing signed distances')
    out_mask = File(
        desc='Name of file to store a mask where the ``out_file`` has a computed value'
    )


[docs] class CreateSignedDistanceVolume(WBCommand): """Create signed distance volume from surface Computes the signed distance function of the surface. Exact distance is calculated by finding the closest point on any surface triangle to the center of the voxel. Approximate distance is calculated starting with these distances, using dijkstra's method with a neighborhood of voxels. Specifying too small of an exact distance may produce unexpected results. The NORMALS winding method uses the normals of triangles and edges, or the closest triangle hit by a ray from the point. This method may be slightly faster, but is only reliable for a closed surface that does not cross through itself. All other methods count entry (positive) and exit (negative) crossings of a vertical ray from the point, then counts as inside if the total is odd, negative, or nonzero, respectively. Command help string:: CREATE SIGNED DISTANCE VOLUME FROM SURFACE wb_command -create-signed-distance-volume <surface> - the input surface <refspace> - a volume in the desired output space (dims, spacing, origin) <outvol> - output - the output volume [-roi-out] - output an roi volume of where the output has a computed value <roi-vol> - output - the output roi volume [-fill-value] - specify a value to put in all voxels that don't get assigned a distance <value> - value to fill with (default 0) [-exact-limit] - specify distance for exact output <dist> - distance in mm (default 5) [-approx-limit] - specify distance for approximate output <dist> - distance in mm (default 20) [-approx-neighborhood] - voxel neighborhood for approximate calculation <num> - size of neighborhood cube measured from center to face, in voxels (default 2 = 5x5x5) [-winding] - winding method for point inside surface test <method> - name of the method (default EVEN_ODD) Computes the signed distance function of the surface. Exact distance is calculated by finding the closest point on any surface triangle to the center of the voxel. Approximate distance is calculated starting with these distances, using dijkstra's method with a neighborhood of voxels. Specifying too small of an exact distance may produce unexpected results. Valid specifiers for winding methods are as follows: EVEN_ODD (default) NEGATIVE NONZERO NORMALS The NORMALS method uses the normals of triangles and edges, or the closest triangle hit by a ray from the point. This method may be slightly faster, but is only reliable for a closed surface that does not cross through itself. All other methods count entry (positive) and exit (negative) crossings of a vertical ray from the point, then counts as inside if the total is odd, negative, or nonzero, respectively. """ input_spec = CreateSignedDistanceVolumeInputSpec output_spec = CreateSignedDistanceVolumeOutputSpec _cmd = 'wb_command -create-signed-distance-volume'
class SurfaceAffineRegressionInputSpec(CommandLineInputSpec): in_surface = File( exists=True, mandatory=True, argstr='%s', position=0, desc='Surface to warp', ) target_surface = File( exists=True, mandatory=True, argstr='%s', position=1, desc='Surface to match the coordinates of', ) out_affine = File( name_template='%s_xfm', name_source=['in_surface'], argstr='%s', position=2, desc='the output affine file', ) class SurfaceAffineRegressionOutputSpec(TraitedSpec): out_affine = File(desc='The output affine file')
[docs] class SurfaceAffineRegression(WBCommand): """REGRESS THE AFFINE TRANSFORM BETWEEN SURFACES ON THE SAME MESH wb_command -surface-affine-regression <source> - the surface to warp <target> - the surface to match the coordinates of <affine-out> - output - the output affine file Use linear regression to compute an affine that minimizes the sum of squares of the coordinate differences between the target surface and the warped source surface. Note that this has a bias to shrink the surface that is being warped. The output is written as a NIFTI 'world' matrix, see -convert-affine to convert it for use in other software. >>> sar = SurfaceAffineRegression() >>> sar.inputs.in_surface = 'sub-01_hemi-L_sulc.shape.gii' >>> sar.inputs.target_surface = 'tpl-fsaverage_hemi-L_den-164k_sulc.shape.gii' >>> sar.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE 'wb_command -surface-affine-regression \ sub-01_hemi-L_sulc.shape.gii \ tpl-fsaverage_hemi-L_den-164k_sulc.shape.gii \ sub-01_hemi-L_sulc.shape_xfm' """ input_spec = SurfaceAffineRegressionInputSpec output_spec = SurfaceAffineRegressionOutputSpec _cmd = 'wb_command -surface-affine-regression'
class SurfaceApplyAffineInputSpec(CommandLineInputSpec): in_surface = File( exists=True, mandatory=True, argstr='%s', position=0, desc='the surface to transform', ) in_affine = File( exists=True, mandatory=True, argstr='%s', position=1, desc='the affine file', ) out_surface = File( name_template='%s_xformed.surf.gii', name_source=['in_surface'], argstr='%s', position=2, desc='the output transformed surface', ) flirt_source = File( exists=True, requires=['flirt_target'], argstr='-flirt %s', position=3, desc='Source volume (must be used if affine is a flirt affine)', ) flirt_target = File( exists=True, requires=['flirt_source'], argstr='%s', position=4, desc='Target volume (must be used if affine is a flirt affine)', ) class SurfaceApplyAffineOutputSpec(TraitedSpec): out_surface = File(desc='the output transformed surface')
[docs] class SurfaceApplyAffine(WBCommand): """APPLY AFFINE TRANSFORM TO SURFACE FILE wb_command -surface-apply-affine <in-surf> - the surface to transform <affine> - the affine file <out-surf> - output - the output transformed surface [-flirt] - MUST be used if affine is a flirt affine <source-volume> - the source volume used when generating the affine <target-volume> - the target volume used when generating the affine For flirt matrices, you must use the -flirt option, because flirt matrices are not a complete description of the coordinate transform they represent. If the -flirt option is not present, the affine must be a nifti 'world' affine, which can be obtained with the -convert-affine command, or aff_conv from the 4dfp suite. .. testsetup:: >>> np.savetxt('affine.txt', np.eye(4), delimiter='\t') .. doctest:: >>> saa = SurfaceApplyAffine() >>> saa.inputs.in_surface = 'sub-01_hemi-L_sphere.surf.gii' >>> saa.inputs.in_affine = 'affine.txt' >>> saa.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE 'wb_command -surface-apply-affine \ sub-01_hemi-L_sphere.surf.gii \ affine.txt \ sub-01_hemi-L_sphere.surf_xformed.surf.gii' .. testcleanup:: >>> os.unlink('affine.txt') """ input_spec = SurfaceApplyAffineInputSpec output_spec = SurfaceApplyAffineOutputSpec _cmd = 'wb_command -surface-apply-affine'
class SurfaceApplyWarpfieldInputSpec(CommandLineInputSpec): in_surface = File( exists=True, mandatory=True, argstr='%s', position=0, desc='the surface to transform', ) warpfield = File( exists=True, mandatory=True, argstr='%s', position=1, desc='the INVERSE warpfield', ) out_surface = File( name_template='%s_warped.surf.gii', name_source=['in_surface'], argstr='%s', position=2, desc='the output transformed surface', ) fnirt_forward_warp = File( exists=True, argstr='-fnirt %s', position=3, desc='the forward warpfield (must be used if fnirt warpfield)', ) class SurfaceApplyWarpfieldOutputSpec(TraitedSpec): out_surface = File(desc='the output transformed surface')
[docs] class SurfaceApplyWarpfield(WBCommand): """APPLY WARPFIELD TO SURFACE FILE wb_command -surface-apply-warpfield <in-surf> - the surface to transform <warpfield> - the INVERSE warpfield <out-surf> - output - the output transformed surface [-fnirt] - MUST be used if using a fnirt warpfield <forward-warp> - the forward warpfield NOTE: warping a surface requires the INVERSE of the warpfield used to warp the volume it lines up with. The header of the forward warp is needed by the -fnirt option in order to correctly interpret the displacements in the fnirt warpfield. If the -fnirt option is not present, the warpfield must be a nifti 'world' warpfield, which can be obtained with the -convert-warpfield command. >>> saw = SurfaceApplyWarpfield() >>> saw.inputs.in_surface = 'sub-01_hemi-L_sphere.surf.gii' >>> saw.inputs.warpfield = 'sub-01_desc-warped_T1w.nii.gz' >>> saw.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE 'wb_command -surface-apply-warpfield \ sub-01_hemi-L_sphere.surf.gii \ sub-01_desc-warped_T1w.nii.gz \ sub-01_hemi-L_sphere.surf_warped.surf.gii' """ input_spec = SurfaceApplyWarpfieldInputSpec output_spec = SurfaceApplyWarpfieldOutputSpec _cmd = 'wb_command -surface-apply-warpfield'
class SurfaceModifySphereInputSpec(CommandLineInputSpec): in_surface = File( exists=True, mandatory=True, position=0, argstr='%s', desc='the sphere to modify', ) radius = traits.Int( mandatory=True, position=1, argstr='%d', desc='the radius the output sphere should have' ) out_surface = File( name_template='%s_mod.surf.gii', name_source='in_surface', position=2, argstr='%s', desc='the modified sphere', ) recenter = traits.Bool( False, position=3, argstr='-recenter', desc='recenter the sphere by means of the bounding box', ) class SurfaceModifySphereOutputSpec(TraitedSpec): out_surface = File(desc='the modified sphere')
[docs] class SurfaceModifySphere(WBCommand): """CHANGE RADIUS AND OPTIONALLY RECENTER A SPHERE wb_command -surface-modify-sphere <sphere-in> - the sphere to modify <radius> - the radius the output sphere should have <sphere-out> - output - the output sphere [-recenter] - recenter the sphere by means of the bounding box This command may be useful if you have used -surface-resample to resample a sphere, which can suffer from problems generally not present in -surface-sphere-project-unproject. If the sphere should already be centered around the origin, using -recenter may still shift it slightly before changing the radius, which is likely to be undesirable. If <sphere-in> is not close to spherical, or not centered around the origin and -recenter is not used, a warning is printed. >>> sms = SurfaceModifySphere() >>> sms.inputs.in_surface = 'sub-01_hemi-L_sphere.surf.gii' >>> sms.inputs.radius = 100 >>> sms.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE 'wb_command -surface-modify-sphere \ sub-01_hemi-L_sphere.surf.gii 100 sub-01_hemi-L_sphere.surf_mod.surf.gii' """ input_spec = SurfaceModifySphereInputSpec output_spec = SurfaceModifySphereOutputSpec _cmd = 'wb_command -surface-modify-sphere'
class SurfaceSphereProjectUnprojectInputSpec(TraitedSpec): """COPY REGISTRATION DEFORMATIONS TO DIFFERENT SPHERE. wb_command -surface-sphere-project-unproject <sphere-in> - a sphere with the desired output mesh <sphere-project-to> - a sphere that aligns with sphere-in <sphere-unproject-from> - <sphere-project-to> deformed to the desired output space <sphere-out> - output - the output sphere Background: A surface registration starts with an input sphere, and moves its vertices around on the sphere until it matches the template data. This means that the registration deformation is actually represented as the difference between two separate files - the starting sphere, and the registered sphere. Since the starting sphere of the registration may not have vertex correspondence to any other sphere (often, it is a native sphere), it can be inconvenient to manipulate or compare these deformations across subjects, etc. The purpose of this command is to be able to apply these deformations onto a new sphere of the user's choice, to make it easier to compare or manipulate them. Common uses are to concatenate two successive separate registrations (e.g. Human to Chimpanzee, and then Chimpanzee to Macaque) or inversion (for dedrifting or symmetric registration schemes). <sphere-in> must already be considered to be in alignment with one of the two ends of the registration (if your registration is Human to Chimpanzee, <sphere-in> must be in register with either Human or Chimpanzee). The 'project-to' sphere must be the side of the registration that is aligned with <sphere-in> (if your registration is Human to Chimpanzee, and <sphere-in> is aligned with Human, then 'project-to' should be the original Human sphere). The 'unproject-from' sphere must be the remaining sphere of the registration (original vs deformed/registered). The output is as if you had run the same registration with <sphere-in> as the starting sphere, in the direction of deforming the 'project-to' sphere to create the 'unproject-from' sphere. Note that this command cannot check for you what spheres are aligned with other spheres, and using the wrong spheres or in the incorrect order will not necessarily cause an error message. In some cases, it may be useful to use a new, arbitrary sphere as the input, which can be created with the -surface-create-sphere command. Example 1: You have a Human to Chimpanzee registration, and a Chimpanzee to Macaque registration, and want to combine them. If you use the Human sphere registered to Chimpanzee as sphere-in, the Chimpanzee standard sphere as project-to, and the Chimpanzee sphere registered to Macaque as unproject-from, the output will be the Human sphere in register with the Macaque. Example 2: You have a Human to Chimpanzee registration, but what you really want is the inverse, that is, the sphere as if you had run the registration from Chimpanzee to Human. If you use the Chimpanzee standard sphere as sphere-in, the Human sphere registered to Chimpanzee as project-to, and the standard Human sphere as unproject-from, the output will be the Chimpanzee sphere in register with the Human. Technical details: Each vertex of <sphere-in> is projected to a triangle of <sphere-project-to>, and its new position is determined by the position of the corresponding triangle in <sphere-unproject-from>. The output is a sphere with the topology of <sphere-in>, but coordinates shifted by the deformation from <sphere-project-to> to <sphere-unproject-from>. <sphere-project-to> and <sphere-unproject-from> must have the same topology as each other, but <sphere-in> may have any topology.""" sphere_in = File( desc='a sphere with the desired output mesh', exists=True, mandatory=True, argstr='%s', position=0, ) sphere_project_to = File( desc='a sphere that aligns with sphere-in', exists=True, mandatory=True, argstr='%s', position=1, ) sphere_unproject_from = File( desc='<sphere-project-to> deformed to the desired output space', exists=True, mandatory=True, argstr='%s', position=2, ) sphere_out = traits.File( name_template='%s_unprojected.surf.gii', name_source=['sphere_in'], desc='the output sphere', argstr='%s', position=3, ) class SurfaceSphereProjectUnprojectOutputSpec(TraitedSpec): sphere_out = File(desc='the output sphere')
[docs] class SurfaceSphereProjectUnproject(WBCommand): """COPY REGISTRATION DEFORMATIONS TO DIFFERENT SPHERE. Example ------- >>> from smriprep.interfaces.workbench import SurfaceSphereProjectUnproject >>> sphere_project = SurfaceSphereProjectUnproject() >>> sphere_project.inputs.sphere_in = 'sub-01_hemi-L_sphere.surf.gii' >>> sphere_project.inputs.sphere_project_to = 'tpl-fsLR_hemi-L_den-32k_sphere.surf.gii' >>> sphere_project.inputs.sphere_unproject_from = 'lh.sphere.reg.surf.gii' >>> sphere_project.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE 'wb_command -surface-sphere-project-unproject sub-01_hemi-L_sphere.surf.gii \ tpl-fsLR_hemi-L_den-32k_sphere.surf.gii lh.sphere.reg.surf.gii \ sub-01_hemi-L_sphere.surf_unprojected.surf.gii' """ input_spec = SurfaceSphereProjectUnprojectInputSpec output_spec = SurfaceSphereProjectUnprojectOutputSpec _cmd = 'wb_command -surface-sphere-project-unproject'
class SurfaceResampleInputSpec(TraitedSpec): """RESAMPLE A SURFACE TO A DIFFERENT MESH wb_command -surface-resample <surface-in> - the surface file to resample <current-sphere> - a sphere surface with the mesh that the input surface is currently on <new-sphere> - a sphere surface that is in register with <current-sphere> and has the desired output mesh <method> - the method name <surface-out> - output - the output surface file [-area-surfs] - specify surfaces to do vertex area correction based on <current-area> - a relevant surface with <current-sphere> mesh <new-area> - a relevant surface with <new-sphere> mesh [-area-metrics] - specify vertex area metrics to do area correction based on <current-area> - a metric file with vertex areas for <current-sphere> mesh <new-area> - a metric file with vertex areas for <new-sphere> mesh Resamples a surface file, given two spherical surfaces that are in register. If ADAP_BARY_AREA is used, exactly one of -area-surfs or -area-metrics must be specified. This method is not generally recommended for surface resampling, but is provided for completeness. The BARYCENTRIC method is generally recommended for anatomical surfaces, in order to minimize smoothing. For cut surfaces (including flatmaps), use -surface-cut-resample. Instead of resampling a spherical surface, the -surface-sphere-project-unproject command is recommended. The <method> argument must be one of the following: ADAP_BARY_AREA BARYCENTRIC """ surface_in = File( desc='the surface file to resample', exists=True, mandatory=True, argstr='%s', position=0, ) current_sphere = File( desc='a sphere surface with the mesh that the input surface is currently on', exists=True, mandatory=True, argstr='%s', position=1, ) new_sphere = File( desc='a sphere surface that is in register with <current-sphere> and has the ' 'desired output mesh', exists=True, mandatory=True, argstr='%s', position=2, ) method = traits.Enum( 'ADAP_BARY_AREA', 'BARYCENTRIC', desc='the method name', mandatory=True, argstr='%s', position=3, ) surface_out = traits.File( name_template='%s_resampled.surf.gii', name_source=['surface_in'], keep_extension=False, desc='the output surface file', argstr='%s', position=4, ) correction_source = traits.Enum( 'area_surfs', 'area_metrics', desc='specify surfaces or vertex area metrics to do vertex area correction based on', argstr='-%s', position=5, ) current_area = File( desc='a relevant surface with <current-sphere> mesh', exists=True, argstr='%s', position=6, requires=['correction_source'], ) new_area = File( desc='a relevant surface with <new-sphere> mesh', exists=True, argstr='%s', position=7, requires=['correction_source'], ) class SurfaceResampleOutputSpec(TraitedSpec): surface_out = File(desc='the output surface file')
[docs] class SurfaceResample(WBCommand): """RESAMPLE A SURFACE TO A DIFFERENT MESH. Example ------- >>> from smriprep.interfaces.workbench import SurfaceResample >>> surface_resample = SurfaceResample() >>> surface_resample.inputs.surface_in = 'sub-01_hemi-L_midthickness.surf.gii' >>> surface_resample.inputs.current_sphere = 'sub-01_hemi-L_sphere.surf.gii' >>> surface_resample.inputs.new_sphere = 'tpl-fsLR_hemi-L_den-32k_sphere.surf.gii' >>> surface_resample.inputs.method = 'BARYCENTRIC' >>> surface_resample.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE 'wb_command -surface-resample sub-01_hemi-L_midthickness.surf.gii \ sub-01_hemi-L_sphere.surf.gii tpl-fsLR_hemi-L_den-32k_sphere.surf.gii \ BARYCENTRIC sub-01_hemi-L_midthickness.surf_resampled.surf.gii' """ input_spec = SurfaceResampleInputSpec output_spec = SurfaceResampleOutputSpec _cmd = 'wb_command -surface-resample'