|
| 1 | +from pathlib import Path |
| 2 | + |
| 3 | +from nipype.interfaces.base import ( |
| 4 | + CommandLine, |
| 5 | + CommandLineInputSpec, |
| 6 | + File, |
| 7 | + TraitedSpec, |
| 8 | + traits, |
| 9 | +) |
| 10 | + |
| 11 | + |
| 12 | +class MSMInputSpec(CommandLineInputSpec): |
| 13 | + in_mesh = File( |
| 14 | + exists=True, |
| 15 | + mandatory=True, |
| 16 | + argstr="--inmesh=%s", |
| 17 | + desc="input mesh (available formats: VTK, ASCII, GIFTI). Needs to be a sphere", |
| 18 | + ) |
| 19 | + out_base = File( |
| 20 | + name_source=["in_mesh"], |
| 21 | + name_template="%s_msm", |
| 22 | + argstr="--out=%s", |
| 23 | + desc="output basename", |
| 24 | + ) |
| 25 | + reference_mesh = File( |
| 26 | + exists=True, |
| 27 | + argstr="--refmesh=%s", |
| 28 | + desc="reference mesh (available formats: VTK, ASCII, GIFTI). Needs to be a sphere." |
| 29 | + "If not included algorithm assumes reference mesh is equivalent input", |
| 30 | + ) |
| 31 | + in_data = File( |
| 32 | + exists=True, |
| 33 | + argstr="--indata=%s", |
| 34 | + desc="scalar or multivariate data for input - can be ASCII (.asc,.dpv,.txt) " |
| 35 | + "or GIFTI (.func.gii or .shape.gii)", |
| 36 | + ) |
| 37 | + reference_data = File( |
| 38 | + exists=True, |
| 39 | + argstr="--refdata=%s", |
| 40 | + desc="scalar or multivariate data for reference - can be ASCII (.asc,.dpv,.txt) " |
| 41 | + "or GIFTI (.func.gii or .shape.gii)", |
| 42 | + ) |
| 43 | + transformed_mesh = File( |
| 44 | + exists=True, |
| 45 | + argstr="--trans=%s", |
| 46 | + desc="Transformed source mesh (output of a previous registration). " |
| 47 | + "Use this to initiliase the current registration.", |
| 48 | + ) |
| 49 | + in_register = File( |
| 50 | + exists=True, |
| 51 | + argstr="--in_register=%s", |
| 52 | + desc="Input mesh at data resolution. Used to resample data onto input mesh if data " |
| 53 | + "is supplied at a different resolution. Note this mesh HAS to be in alignment with " |
| 54 | + "either the input_mesh of (if supplied) the transformed source mesh. " |
| 55 | + "Use with supreme caution.", |
| 56 | + ) |
| 57 | + in_weight = File( |
| 58 | + exists=True, |
| 59 | + argstr="--inweight=%s", |
| 60 | + desc="cost function weighting for input - weights data in these vertices when calculating " |
| 61 | + "similarity (ASCII or GIFTI). Can be multivariate provided dimension equals that of data", |
| 62 | + ) |
| 63 | + reference_weight = File( |
| 64 | + exists=True, |
| 65 | + argstr="--refweight=%s", |
| 66 | + desc="cost function weighting for reference - weights data in these vertices when " |
| 67 | + "calculating similarity (ASCII or GIFTI). Can be multivariate provided dimension " |
| 68 | + "equals that of data", |
| 69 | + ) |
| 70 | + output_format = traits.Enum( |
| 71 | + "GIFTI", |
| 72 | + "VTK", |
| 73 | + "ASCII", |
| 74 | + "ASCII_MAT", |
| 75 | + argstr="--format=%s", |
| 76 | + desc="format of output files", |
| 77 | + ) |
| 78 | + config_file = File( |
| 79 | + exists=True, |
| 80 | + argstr="--conf=%s", |
| 81 | + desc="configuration file", |
| 82 | + ) |
| 83 | + levels = traits.Int( |
| 84 | + argstr="--levels=%d", |
| 85 | + desc="number of resolution levels (default = number of resolution levels specified " |
| 86 | + "by --opt in config file)", |
| 87 | + ) |
| 88 | + smooth_output_sigma = traits.Int( |
| 89 | + argstr="--smoothout=%d", |
| 90 | + desc="smooth tranformed output with this sigma (default=0)", |
| 91 | + ) |
| 92 | + verbose = traits.Bool( |
| 93 | + argstr="--verbose", |
| 94 | + desc="switch on diagnostic messages", |
| 95 | + ) |
| 96 | + |
| 97 | + |
| 98 | +class MSMOutputSpec(TraitedSpec): |
| 99 | + warped_mesh = File( |
| 100 | + desc="the warped input mesh (i.e., new vertex locations - this capture the warp field, " |
| 101 | + "much like a _warp.nii.gz file would for volumetric warps created by FNIRT)." |
| 102 | + ) |
| 103 | + downsampled_warped_mesh = File( |
| 104 | + desc="a downsampled version of the warped_mesh where the resolution of this mesh will " |
| 105 | + "be equivalent to the resolution of the final datamesh" |
| 106 | + ) |
| 107 | + warped_data = File( |
| 108 | + desc="the input data passed through the MSM warp and projected onto the target surface" |
| 109 | + ) |
| 110 | + |
| 111 | + |
| 112 | +class MSM(CommandLine): |
| 113 | + """ |
| 114 | + MSM (Multimodal Surface Matching) is a tool for registering cortical surfaces. |
| 115 | + The tool has been developed and tested using FreeSurfer extracted surfaces. |
| 116 | + However, in principle the tool with work with any cortical surface extraction method provided |
| 117 | + the surfaces can be mapped to the sphere. |
| 118 | + The key advantage of the method is that alignment may be driven using a wide variety of |
| 119 | + univariate (sulcal depth, curvature, myelin), multivariate (Task fMRI, or Resting State |
| 120 | + Networks) or multimodal (combinations of folding, myelin and fMRI) feature sets. |
| 121 | +
|
| 122 | + The main MSM tool is currently run from the command line using the program ``msm``. |
| 123 | + This enables fast alignment of spherical cortical surfaces by utilising a fast discrete |
| 124 | + optimisation framework (FastPD Komodakis 2007), which significantly reduces the search |
| 125 | + space of possible deformations for each vertex, and allows flexibility with regards to the |
| 126 | + choice of similarity metric used to match the images. |
| 127 | +
|
| 128 | + >>> msm = MSM( |
| 129 | + ... config_file=load('msm/MSMSulcStrainFinalconf'), |
| 130 | + ... in_mesh='sub-01_hemi-L_sphere.surf.gii', |
| 131 | + ... reference_mesh='tpl-fsaverage_hemi-L_den-164k_desc-std_sphere.surf.gii', |
| 132 | + ... in_data='sub-01_hemi-L_sulc.shape.gii', |
| 133 | + ... reference_data='tpl-fsaverage_hemi-L_den-164k_sulc.shape.gii', |
| 134 | + ... out_base='L.', |
| 135 | + ... ) |
| 136 | + >>> msm.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE |
| 137 | + 'msm --conf=.../MSMSulcStrainFinalconf \ |
| 138 | + --indata=sub-01_hemi-L_sulc.shape.gii \ |
| 139 | + --inmesh=sub-01_hemi-L_sphere.surf.gii \ |
| 140 | + --out=L. \ |
| 141 | + --refdata=tpl-fsaverage_hemi-L_den-164k_sulc.shape.gii \ |
| 142 | + --refmesh=tpl-fsaverage_hemi-L_den-164k_desc-std_sphere.surf.gii' |
| 143 | +
|
| 144 | + """ |
| 145 | + |
| 146 | + input_spec = MSMInputSpec |
| 147 | + output_spec = MSMOutputSpec |
| 148 | + _cmd = "msm" |
| 149 | + |
| 150 | + def _list_outputs(self): |
| 151 | + from nipype.utils.filemanip import split_filename |
| 152 | + |
| 153 | + outputs = self._outputs().get() |
| 154 | + out_base = self.inputs.out_base or split_filename(self.inputs.in_mesh)[1] |
| 155 | + cwd = Path.cwd() |
| 156 | + outputs['warped_mesh'] = str(cwd / (out_base + 'sphere.reg.surf.gii')) |
| 157 | + outputs['downsampled_warped_mesh'] = str(cwd / (out_base + 'sphere.LR.reg.surf.gii')) |
| 158 | + outputs['warped_data'] = str(cwd / (out_base + 'transformed_and_reprojected.func.gii')) |
| 159 | + return outputs |
0 commit comments