Repository: nipy/nipype

Issue:
Dcm2niix interface: Add `mvecs` output
### Summary

`dcm2niix` produces `.mvec` files for Bruker DW images, to indicate that the polarity of those vectors is undefined (see [here](https://github.com/rordenlab/dcm2niix/issues/265#issuecomment-460779952)).

However, the `Dcm2niix` interface does not include those files.

### Actual behavior

When converting a Bruker DW dataset using `dcm2niix`, the output includes `.nii.gz`, `.json`, `.bval` and `.mvec` files. However the interface outputs are:
```
>>> output.outputs
bids = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.json
bvals = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.bval
bvecs = <undefined>
converted_files = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.nii.gz
```

### Expected behavior

either:
```
>>> output.outputs
bids = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.json
bvals = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.bval
bvecs = <undefined>
mvecs = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.mvec
converted_files = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.nii.gz
```
or:
```
>>> output.outputs
bids = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.json
bvals = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.bval
bvecs = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.mvec
converted_files = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.nii.gz
```

I'm more inclined to the first option, to be more explicit, and let the application using the interface handle it (e.g., making `output.outputs.bvecs = output.outputs.mvecs` if that is OK, or otherwise deal with it).

### How to replicate the behavior

```
>>> from nipype.interfaces.dcm2nii import Dcm2niix
>>> root_dir = '/home/pvelasco/data/samples/bruker_dti/'
>>> converter = Dcm2niix()
>>> converter.inputs.source_dir = root_dir + 'dicom/1'
>>> converter.inputs.output_dir = root_dir + 'nifti'
>>> converter.inputs.bids_format = True
>>> output = converter.run()
>>> output.outputs
bids = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.json
bvals = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.bval
bvecs = <undefined>
converted_files = /home/pvelasco/data/samples/bruker_dti/nifti/1_DTI_EPI_seg_30dir_sat_20210928080241_130001.nii.gz

>>> import os
>>> os.listdir(root_dir + 'nifti')
['1_DTI_EPI_seg_30dir_sat_20210928080241_130001.nii.gz', '1_DTI_EPI_seg_30dir_sat_20210928080241_130001.bval', '1_DTI_EPI_seg_30dir_sat_20210928080241_130001.mvec', '1_DTI_EPI_seg_30dir_sat_20210928080241_130001.json']
```

### Script/Workflow details

(see above)

### Platform details:

<!-- Please run the following code from your shell and place the output between the triple ticks, below.
python -c "import nipype; from pprint import pprint; pprint(nipype.get_info())"
-->

```
{'commit_hash': 'cdfe679a4',
 'commit_source': 'repository',
 'networkx_version': '3.0',
 'nibabel_version': '5.0.1',
 'nipype_version': '1.8.6.dev0',
 'numpy_version': '1.24.2',
 'pkg_path': '/home/pvelasco/code/utils/nipype/nipype',
 'scipy_version': '1.10.1',
 'sys_executable': '/home/pvelasco/.pyenv/versions/3.10.4/bin/python',
 'sys_platform': 'linux',
 'sys_version': '3.10.4 (main, Nov 10 2022, 13:47:31) [GCC 7.5.0]',
 'traits_version': '6.3.2'}
```

### Execution environment

Choose one
- My python environment outside container



Discussion:

Resolving patch:
diff --git a/nipype/interfaces/dcm2nii.py b/nipype/interfaces/dcm2nii.py
--- a/nipype/interfaces/dcm2nii.py
+++ b/nipype/interfaces/dcm2nii.py
@@ -380,6 +380,7 @@ class Dcm2niixInputSpec(CommandLineInputSpec):
 class Dcm2niixOutputSpec(TraitedSpec):
     converted_files = OutputMultiPath(File(exists=True))
     bvecs = OutputMultiPath(File(exists=True))
+    mvecs = OutputMultiPath(File(exists=True))
     bvals = OutputMultiPath(File(exists=True))
     bids = OutputMultiPath(File(exists=True))
 
@@ -459,8 +460,8 @@ def _parse_stdout(self, stdout):
         return filenames
 
     def _parse_files(self, filenames):
-        outfiles, bvals, bvecs, bids = [], [], [], []
-        outtypes = [".bval", ".bvec", ".json", ".txt"]
+        outfiles, bvals, bvecs, mvecs, bids = [], [], [], [], []
+        outtypes = [".bval", ".bvec", ".mvec", ".json", ".txt"]
         if self.inputs.to_nrrd:
             outtypes += [".nrrd", ".nhdr", ".raw.gz"]
         else:
@@ -480,10 +481,13 @@ def _parse_files(self, filenames):
                     bvals.append(fl)
                 elif fl.endswith(".bvec"):
                     bvecs.append(fl)
+                elif fl.endswith(".mvec"):
+                    mvecs.append(fl)
                 elif fl.endswith(".json") or fl.endswith(".txt"):
                     bids.append(fl)
         self.output_files = outfiles
         self.bvecs = bvecs
+        self.mvecs = mvecs
         self.bvals = bvals
         self.bids = bids
 
@@ -492,6 +496,7 @@ def _list_outputs(self):
         outputs["converted_files"] = self.output_files
         outputs["bvecs"] = self.bvecs
         outputs["bvals"] = self.bvals
+        outputs["mvecs"] = self.mvecs
         outputs["bids"] = self.bids
         return outputs
 


Test patch:
diff --git a/nipype/interfaces/tests/test_auto_Dcm2niix.py b/nipype/interfaces/tests/test_auto_Dcm2niix.py
--- a/nipype/interfaces/tests/test_auto_Dcm2niix.py
+++ b/nipype/interfaces/tests/test_auto_Dcm2niix.py
@@ -95,6 +95,7 @@ def test_Dcm2niix_outputs():
         bvals=dict(),
         bvecs=dict(),
         converted_files=dict(),
+        mvecs=dict(),
     )
     outputs = Dcm2niix.output_spec()