Skip to content

MCFLIRT naming error with FSL 6.0.7.13 #3684

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
b1060t opened this issue Sep 28, 2024 · 3 comments
Open

MCFLIRT naming error with FSL 6.0.7.13 #3684

b1060t opened this issue Sep 28, 2024 · 3 comments
Labels

Comments

@b1060t
Copy link

b1060t commented Sep 28, 2024

Summary

I'm walking through miykael's tutorial and found the output of mcflirt could not be correctly recognized:

FileNotFoundError: No such file or directory '/xxx/working_dir/preprocWF/mcflirt/sub-01_ses-test_task-fingerfootlips_bold_mcf_mean_reg.nii.gz' for output 'mean_img' of a MCFLIRT interface

and the real output name of mcflirt was sub-01_ses-test_task-fingerfootlips_bold_mcf.nii.gz_mean_reg.nii.gz.
I think this issue should have been resolved after referring to a previous commit.

By simply replacing this line with the hardcoded path of the output file, the workflow finished without any error.

I don't know if this pattern of filename (.nii.gz_mean_reg.nii.gz) shouldn't appear in FLS 6, or there's something wrong on nipype side?

Platform details:

{'commit_hash': '62fc392',
 'commit_source': 'repository',
 'networkx_version': '3.3',
 'nibabel_version': '5.2.1',
 'nipype_version': '1.8.6',
 'numpy_version': '1.26.3',
 'pkg_path': '/xxx/.pyenv/versions/3.11.10/lib/python3.11/site-packages/nipype',
 'scipy_version': '1.14.1',
 'sys_executable': '/xxx/.pyenv/versions/3.11.10/bin/python',
 'sys_platform': 'linux',
 'sys_version': '3.11.10 (main, Sep 23 2024, 14:48:25) [GCC 7.5.0]',
 'traits_version': '6.3.2'}

Execution environment

FSL: 6.0.7.13

@effigies
Copy link
Member

I'm not sure. If you're able to describe an environment and minimal reproducible example, we could definitely debug this.

@effigies effigies added the bug label Nov 18, 2024
@b1060t
Copy link
Author

b1060t commented May 8, 2025

I'm just refering to the nipype tutorial:

from nipype import SelectFiles, Node
from os.path import abspath
templates={'func': '{subject}/{session}/func/{subject}_{session}_task-fingerfootlips_bold.nii.gz'}
sf = Node(SelectFiles(templates),
          name='selectfiles')
sf.inputs.base_directory = abspath('../data/ds000114')
sf.inputs.subject = 'sub-01'
sf.inputs.session = 'ses-test'
from nipype.interfaces.fsl import MCFLIRT, IsotropicSmooth
mcflirt = Node(MCFLIRT(mean_vol=True,
                       save_plots=True),
               name='mcflirt')
smooth = Node(IsotropicSmooth(fwhm=4),
              name='smooth')
from nipype import Workflow
wf = Workflow(name="preprocWF")
wf.base_dir = 'output/working_dir'
wf.connect([(sf, mcflirt, [("func", "in_file")]),
            #(mcflirt, smooth, [("out_file", "in_file")])
            ])
wf.run()

@44REAM
Copy link

44REAM commented Jun 3, 2025

Hi, I noticed an issue when running mcflirt from the command line using:

mcflirt -in name.nii -meanvol -out outname.nii

This produces an output file named outname.nii.nii, which causes a naming error. The same behavior occurs when using Nipype unless you explicitly specify the output filename without the .nii extension. In my Python code, I work around this by setting out_file='outname':

mcflirt = Node(MCFLIRT(mean_vol=True,
                       save_plots=True),
               name='mcflirt', out_file='outname')

Then modify nipype MCFLIRT class

class MCFLIRT(FSLCommand):

    def _list_outputs(self):
        outputs = self._outputs().get()

        outputs["out_file"] = self._gen_outfilename()
        output_dir = os.path.dirname(outputs["out_file"])

        if isdefined(self.inputs.stats_imgs) and self.inputs.stats_imgs:
            if LooseVersion(Info.version()) < LooseVersion("6.0.0"):
                # FSL <6.0 outputs have .nii.gz_variance.nii.gz as extension
                outputs["variance_img"] = self._gen_fname(
                    outputs["out_file"] + "_variance.ext", cwd=output_dir
                )
                outputs["std_img"] = self._gen_fname(
                    outputs["out_file"] + "_sigma.ext", cwd=output_dir
                )
            else:
                outputs["variance_img"] = self._gen_fname(
                    outputs["out_file"], suffix="_variance", cwd=output_dir
                )
                outputs["std_img"] = self._gen_fname(
                    outputs["out_file"], suffix="_sigma", cwd=output_dir
                )

        # The mean image created if -stats option is specified ('meanvol')
        # is missing the top and bottom slices. Therefore we only expose the
        # mean image created by -meanvol option ('mean_reg') which isn't
        # corrupted.
        # Note that the same problem holds for the std and variance image.

        if isdefined(self.inputs.mean_vol) and self.inputs.mean_vol:
            if LooseVersion(Info.version()) < LooseVersion("6.0.0"):
                # FSL <6.0 outputs have .nii.gz_mean_img.nii.gz as extension
                outputs["mean_img"] = self._gen_fname(
                    outputs["out_file"] + "_mean_reg.ext", cwd=output_dir
                )
            else:
                outputs["mean_img"] = self._gen_fname(
                    outputs["out_file"], suffix="_mean_reg", cwd=output_dir
                )


        if isdefined(self.inputs.save_mats) and self.inputs.save_mats:
            _, filename = os.path.split(outputs["out_file"])
            matpathname = os.path.join(output_dir, filename + ".mat")
            _, _, _, timepoints = load(self.inputs.in_file).shape
            outputs["mat_file"] = []
            for t in range(timepoints):
                outputs["mat_file"].append(os.path.join(matpathname, "MAT_%04d" % t))
        if isdefined(self.inputs.save_plots) and self.inputs.save_plots:
            # Note - if e.g. out_file has .nii.gz, you get .nii.gz.par,
            # which is what mcflirt does!
            outputs["par_file"] = outputs["out_file"] + ".par"
        if isdefined(self.inputs.save_rms) and self.inputs.save_rms:
            outfile = outputs["out_file"]
            outputs["rms_files"] = [outfile + "_abs.rms", outfile + "_rel.rms"]

        #! add this line ************************************
        outputs["out_file"] = outputs["out_file"] + ".nii" # .nii or .nii.gz depend on your output
        #! end of add

        return outputs

Hope this help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants