@@ -1232,3 +1232,217 @@ def _run_interface(self, runtime):
12321232 if runtime .stderr :
12331233 self .raise_exception (runtime )
12341234 return runtime
1235+
1236+
1237+ class EddyQuadInputSpec (FSLCommandInputSpec ):
1238+ base_name = traits .Str (
1239+ 'eddy_corrected' ,
1240+ argstr = '%s' ,
1241+ desc = "Basename (including path) specified when running EDDY" ,
1242+ position = 0 ,
1243+ )
1244+ idx_file = File (
1245+ exists = True ,
1246+ mandatory = True ,
1247+ argstr = "--eddyIdx=%s" ,
1248+ desc = ("File containing indices for all volumes into acquisition "
1249+ "parameters" )
1250+ )
1251+ param_file = File (
1252+ exists = True ,
1253+ mandatory = True ,
1254+ argstr = "--eddyParams=%s" ,
1255+ desc = "File containing acquisition parameters"
1256+ )
1257+ mask_file = File (
1258+ exists = True ,
1259+ mandatory = True ,
1260+ argstr = "--mask=%s" ,
1261+ desc = "Binary mask file"
1262+ )
1263+ bval_file = File (
1264+ exists = True ,
1265+ mandatory = True ,
1266+ argstr = "--bvals=%s" ,
1267+ desc = "b-values file"
1268+ )
1269+ bvec_file = File (
1270+ exists = True ,
1271+ mandatory = False ,
1272+ argstr = "--bvecs=%s" ,
1273+ desc = ("b-vectors file - only used when <base_name>.eddy_residuals "
1274+ "file is present" )
1275+ )
1276+ output_dir = traits .Str (
1277+ 'eddy_corrected.qc' ,
1278+ mandatory = False ,
1279+ argstr = '--output-dir=%s' ,
1280+ desc = "Output directory - default = '<base_name>.qc'" ,
1281+ )
1282+ field = File (
1283+ mandatory = False ,
1284+ argstr = '--field=%s' ,
1285+ desc = "TOPUP estimated field (in Hz)" ,
1286+ )
1287+ slspec = File (
1288+ mandatory = False ,
1289+ argstr = '--slspec=%s' ,
1290+ desc = "Text file specifying slice/group acquisition" ,
1291+ )
1292+ verbose = traits .Bool (
1293+ False ,
1294+ mandatory = False ,
1295+ argstr = '--verbose' ,
1296+ desc = "Display debug messages" ,
1297+ )
1298+
1299+
1300+ class EddyQuadOutputSpec (TraitedSpec ):
1301+ out_qc_json = File (
1302+ exists = True ,
1303+ mandatory = True ,
1304+ desc = ("Single subject database containing quality metrics and data "
1305+ "info." )
1306+ )
1307+ out_qc_pdf = File (
1308+ exists = True ,
1309+ mandatory = True ,
1310+ desc = "Single subject QC report."
1311+ )
1312+ out_avg_b_png = traits .List (
1313+ File (
1314+ exists = True ,
1315+ mandatory = True ,
1316+ desc = ("Image showing mid-sagittal, -coronal and -axial slices of "
1317+ "each averaged b-shell volume." )
1318+ )
1319+ )
1320+ out_avg_b0_png = traits .List (
1321+ File (
1322+ exists = True ,
1323+ mandatory = False ,
1324+ desc = ("Image showing mid-sagittal, -coronal and -axial slices of "
1325+ "each averaged pe-direction b0 volume. Generated when using "
1326+ "the -f option." )
1327+ )
1328+ )
1329+ out_cnr_png = traits .List (
1330+ File (
1331+ exists = True ,
1332+ mandatory = False ,
1333+ desc = ("Image showing mid-sagittal, -coronal and -axial slices of "
1334+ "each b-shell CNR volume. Generated when CNR maps are "
1335+ "available." )
1336+ )
1337+ )
1338+ out_vdm_png = File (
1339+ exists = True ,
1340+ mandatory = False ,
1341+ desc = ("Image showing mid-sagittal, -coronal and -axial slices of "
1342+ "the voxel displacement map. Generated when using the -f "
1343+ "option." )
1344+ )
1345+ out_residuals = File (
1346+ exists = True ,
1347+ mandatory = False ,
1348+ desc = ("Text file containing the volume-wise mask-averaged squared "
1349+ "residuals. Generated when residual maps are available." )
1350+ )
1351+ out_clean_volumes = File (
1352+ exists = True ,
1353+ mandatory = False ,
1354+ desc = ("Text file containing a list of clean volumes, based on "
1355+ "the eddy squared residuals. To generate a version of the "
1356+ "pre-processed dataset without outlier volumes, use: "
1357+ "`fslselectvols -i <eddy_corrected_data> -o "
1358+ "eddy_corrected_data_clean --vols=vols_no_outliers.txt`" )
1359+ )
1360+
1361+
1362+ class EddyQuad (FSLCommand ):
1363+ """
1364+ Interface for FSL eddy_quad, a tool for generating single subject reports
1365+ and storing the quality assessment indices for each subject.
1366+ `User guide <https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/eddyqc/UsersGuide>`_
1367+
1368+ Examples
1369+ --------
1370+
1371+ >>> from nipype.interfaces.fsl import EddyQuad
1372+ >>> quad = EddyQuad()
1373+ >>> quad.inputs.in_file = 'epi.nii'
1374+ >>> quad.inputs.in_mask = 'epi_mask.nii'
1375+ >>> quad.inputs.in_index = 'epi_index.txt'
1376+ >>> quad.inputs.in_acqp = 'epi_acqp.txt'
1377+ >>> quad.inputs.in_bvec = 'bvecs.scheme'
1378+ >>> quad.inputs.in_bval = 'bvals.scheme'
1379+ >>> quad.inputs.use_cuda = True
1380+ >>> quad.cmdline # doctest: +ELLIPSIS
1381+ 'eddy_cuda --ff=10.0 --acqp=epi_acqp.txt --bvals=bvals.scheme \
1382+ --bvecs=bvecs.scheme --imain=epi.nii --index=epi_index.txt \
1383+ --mask=epi_mask.nii --niter=5 --nvoxhp=1000 --out=.../eddy_corrected'
1384+ >>> quad.cmdline # doctest: +ELLIPSIS
1385+ 'eddy_openmp --ff=10.0 --acqp=epi_acqp.txt --bvals=bvals.scheme \
1386+ --bvecs=bvecs.scheme --imain=epi.nii --index=epi_index.txt \
1387+ --mask=epi_mask.nii --niter=5 --nvoxhp=1000 --out=.../eddy_corrected'
1388+ >>> res = quad.run() # doctest: +SKIP
1389+
1390+ """
1391+ _cmd = 'eddy_quad'
1392+ input_spec = EddyQuadInputSpec
1393+ output_spec = EddyQuadOutputSpec
1394+
1395+ def __init__ (self , ** inputs ):
1396+ super (EddyQuad , self ).__init__ (** inputs )
1397+
1398+ def _list_outputs (self ):
1399+ outputs = self .output_spec ().get ()
1400+ out_dir = self .inputs .output_dir
1401+ outputs ['out_qc_json' ] = os .path .abspath (
1402+ os .path .join (self .inputs .output_dir , 'out.json' )
1403+ )
1404+ outputs ['out_qc_json' ] = os .path .abspath (
1405+ os .path .join (self .inputs .output_dir , 'out.json' )
1406+ )
1407+ outputs ['out_parameter' ] = os .path .abspath (
1408+ '%s.eddy_parameters' % self .inputs .out_base )
1409+
1410+ # File generation might depend on the version of EDDY
1411+ out_rotated_bvecs = os .path .abspath (
1412+ '%s.eddy_rotated_bvecs' % self .inputs .out_base )
1413+ out_movement_rms = os .path .abspath (
1414+ '%s.eddy_movement_rms' % self .inputs .out_base )
1415+ out_restricted_movement_rms = os .path .abspath (
1416+ '%s.eddy_restricted_movement_rms' % self .inputs .out_base )
1417+ out_shell_alignment_parameters = os .path .abspath (
1418+ '%s.eddy_post_eddy_shell_alignment_parameters' %
1419+ self .inputs .out_base )
1420+ out_outlier_report = os .path .abspath (
1421+ '%s.eddy_outlier_report' % self .inputs .out_base )
1422+ if isdefined (self .inputs .cnr_maps ) and self .inputs .cnr_maps :
1423+ out_cnr_maps = os .path .abspath (
1424+ '%s.eddy_cnr_maps.nii.gz' % self .inputs .out_base )
1425+ if os .path .exists (out_cnr_maps ):
1426+ outputs ['out_cnr_maps' ] = out_cnr_maps
1427+ if isdefined (self .inputs .residuals ) and self .inputs .residuals :
1428+ out_residuals = os .path .abspath (
1429+ '%s.eddy_residuals.nii.gz' % self .inputs .out_base )
1430+ if os .path .exists (out_residuals ):
1431+ outputs ['out_residuals' ] = out_residuals
1432+
1433+ if os .path .exists (out_rotated_bvecs ):
1434+ outputs ['out_rotated_bvecs' ] = out_rotated_bvecs
1435+ if os .path .exists (out_movement_rms ):
1436+ outputs ['out_movement_rms' ] = out_movement_rms
1437+ if os .path .exists (out_restricted_movement_rms ):
1438+ outputs ['out_restricted_movement_rms' ] = \
1439+ out_restricted_movement_rms
1440+ if os .path .exists (out_shell_alignment_parameters ):
1441+ outputs ['out_shell_alignment_parameters' ] = \
1442+ out_shell_alignment_parameters
1443+ if os .path .exists (out_outlier_report ):
1444+ outputs ['out_outlier_report' ] = out_outlier_report
1445+
1446+ return outputs
1447+
1448+
0 commit comments