@@ -1232,3 +1232,217 @@ def _run_interface(self, runtime):
1232
1232
if runtime .stderr :
1233
1233
self .raise_exception (runtime )
1234
1234
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