Skip to content

ENH: Add "ExportFile" interface as simple alternative to "DataSink" #3054

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

Merged
merged 25 commits into from
Oct 26, 2019

Conversation

stilley2
Copy link
Contributor

Acknowledgment

  • (Mandatory) I acknowledge that this contribution will be available under the Apache 2 license.

@effigies
Copy link
Member

Hi @stilley2, could you clarify the reasoning here? Is the idea to use this as a kind of cheap DataSink? In general, symlinking should be a safe operation within the workflow.

@stilley2
Copy link
Contributor Author

Hi @effigies , yeah that's exactly what I was thinking. Specifically it could be used when output file name generation is handled by an external program (e.g. pybids). Perhaps a new interface would be clearer than hijacking Rename for this purpose?

@effigies
Copy link
Member

Perhaps a new interface would be clearer than hijacking Rename for this purpose?

I think so. It may be that DataSink will actually be enough if it's a single file, but you could easily write a simple ExportFile (or whatever name seems appropriate) interface that really does just copy one file with a given name.

Given that you're looking at using pybids, you could also check out niworkflows.interfaces.bids.DerivativesDataSink or fitlins.interfaces.bids.BIDSDataSink, to see if those meet your needs. It might be time to consider upstreaming these to nipype, if they're usable outside our specific contexts.

@stilley2 stilley2 changed the title Add "copy" trait to Rename, to allow copying instead of symlink Add "ExportFile" interface as simple alternative to "DataSink" Oct 1, 2019
@stilley2 stilley2 changed the title Add "ExportFile" interface as simple alternative to "DataSink" ENH: Add "ExportFile" interface as simple alternative to "DataSink" Oct 1, 2019
Copy link
Member

@effigies effigies left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this. I've made some suggestions. Another thing you can look into to avoid using _list_outputs in addition to _run_interface is SimpleInterface.

stilley2 and others added 3 commits October 1, 2019 16:21
Co-Authored-By: Chris Markiewicz <effigies@gmail.com>
Co-Authored-By: Chris Markiewicz <effigies@gmail.com>
Co-Authored-By: Chris Markiewicz <effigies@gmail.com>
@codecov
Copy link

codecov bot commented Oct 1, 2019

Codecov Report

Merging #3054 into master will decrease coverage by 3.61%.
The diff coverage is 91.66%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3054      +/-   ##
==========================================
- Coverage   68.19%   64.58%   -3.62%     
==========================================
  Files         297      295       -2     
  Lines       39771    39712      -59     
  Branches     5210     5202       -8     
==========================================
- Hits        27123    25648    -1475     
- Misses      11939    13025    +1086     
- Partials      709     1039     +330
Flag Coverage Δ
#smoketests ?
#unittests 64.58% <91.66%> (-0.86%) ⬇️
Impacted Files Coverage Δ
nipype/utils/filemanip.py 75.38% <100%> (-3.56%) ⬇️
nipype/interfaces/io.py 50.15% <90%> (-9.11%) ⬇️
nipype/interfaces/nilearn.py 40% <0%> (-56.67%) ⬇️
nipype/workflows/__init__.py 47.05% <0%> (-52.95%) ⬇️
nipype/utils/spm_docs.py 25.92% <0%> (-44.45%) ⬇️
nipype/interfaces/freesurfer/base.py 46.61% <0%> (-32.21%) ⬇️
nipype/utils/logger.py 59.7% <0%> (-29.86%) ⬇️
nipype/algorithms/rapidart.py 35% <0%> (-29.42%) ⬇️
nipype/interfaces/spm/base.py 57.94% <0%> (-29.14%) ⬇️
nipype/utils/provenance.py 55.73% <0%> (-28.35%) ⬇️
... and 38 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1725f51...3695d36. Read the comment docs.

stilley2 and others added 2 commits October 1, 2019 16:23
Co-Authored-By: Chris Markiewicz <effigies@gmail.com>
@effigies effigies added this to the 1.3.0 milestone Oct 3, 2019
@effigies
Copy link
Member

effigies commented Oct 7, 2019

Ah, you have a FileExistsError, which didn't exist prior to Python 3.5. If you want to use it, could you add it to utils.filemanip, along with FileNotFoundError?

try:
from builtins import FileNotFoundError
except ImportError: # PY27
class FileNotFoundError(OSError): # noqa
"""Defines the exception for Python 2."""
def __init__(self, path):
"""Initialize the exception."""
super(FileNotFoundError, self).__init__(
2, 'No such file or directory', '%s' % path)

There's also a Python 3.5 issue, which I suspect will be fixed if you merge/rebase master. I would certainly try that before we start digging deeper.

Copy link
Member

@effigies effigies left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will resolve the Python 3.5 issue. I don't think we need to obsess over what happens if people pass pathlib2.Paths as File traits on Python 3.5.

stilley2 and others added 2 commits October 9, 2019 11:14
Co-Authored-By: Chris Markiewicz <effigies@gmail.com>
Co-Authored-By: Chris Markiewicz <effigies@gmail.com>
Copy link
Member

@effigies effigies left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this. Some suggestions. I think the test failure is related to output_folder...

>>> from nipype.interfaces.io import ExportFile
>>> import os.path as op
>>> ef = Node(ExportFile(), "export")
>>> ef.inputs.in_file = "temporary_file.nii.gz"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file needs to exist. By default, all doctests are run in nipype/testing/data, so there are a lot of options to pick from.


A trivial example that copies temporary_file.nii.gz
to sub1_out.nii.gz. (A more realistic example would set
in_file as the output of another Node.)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like an unnecessary qualifier. I think you could probably just skip this text, unless you want to have multiple tests showing off check_extension and clobber. If so, you could say "By default, file extensions need to match, and the output file should not exist:" and something similar above the other examples.

stilley2 and others added 2 commits October 17, 2019 16:45
Co-Authored-By: Chris Markiewicz <effigies@gmail.com>
Co-Authored-By: Chris Markiewicz <effigies@gmail.com>
stilley2 and others added 3 commits October 17, 2019 16:45
Co-Authored-By: Chris Markiewicz <effigies@gmail.com>
Co-Authored-By: Chris Markiewicz <effigies@gmail.com>
@stilley2
Copy link
Contributor Author

Thanks @effigies . Sorry for the delay. Busy week.

@effigies
Copy link
Member

No worries. This looks good. Two minor issues should fix up the tests, I think.

stilley2 and others added 3 commits October 21, 2019 14:27
Co-Authored-By: Chris Markiewicz <effigies@gmail.com>
Co-Authored-By: Chris Markiewicz <effigies@gmail.com>
@effigies
Copy link
Member

Can you run make specs and commit nipype/interfaces/tests/test_auto_ExportFile.py?

@effigies effigies merged commit b4f9131 into nipy:master Oct 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants