-
Notifications
You must be signed in to change notification settings - Fork 533
ENH: Add FSL eddy_quad
interface
#2825
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
Conversation
Hmm, the travis PR checks failed, but only for Python 3.4 because |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution! Overall, this looks great.
I have a few suggestions/comments/questions.
And don't worry about the Python 3.4 tests. I made an issue in #2826.
nipype/interfaces/fsl/epi.py
Outdated
os.path.join(out_dir, 'vdm.png') | ||
) | ||
|
||
if os.path.exists(vdm): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These checks are a little bit worrisome. Is there no way you can predict whether it should exist from the inputs
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. In 8bac064, I inspect the qc.json
file to see if those files should exist.
nipype/interfaces/fsl/epi.py
Outdated
) | ||
|
||
outputs['out_avg_b0_png'] = glob(os.path.abspath( | ||
os.path.join(out_dir, 'avg_b0_pe*.png') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the use of glob
here a time saver, or is the number of outputs unknown until after it's been run? If the former, it would be better to actually predict the outputs. If the latter, then this is fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. In 8bac064, I now inspect the qc.json
which has flags that indicate the presence of certain output files and the number of expected files for each type.
nipype/interfaces/fsl/epi.py
Outdated
base_name = traits.Str( | ||
'eddy_corrected', | ||
argstr='%s', | ||
desc="Basename (including path) specified when running EDDY", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a non-EDDY user, this means little to me. Will the intent here be obvious to EDDY users?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I improved the description in 8bac064. I think it should be clear to EDDY users. But honestly, I'm no EDDY expert myself.
nipype/interfaces/fsl/epi.py
Outdated
"file is present") | ||
) | ||
output_dir = traits.Str( | ||
'eddy_corrected.qc', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'eddy_corrected.qc', | |
name_template='%s.qc', | |
name_source=['base_name'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I think I resolved this in 8bac064. Is that correct?
- Remove redundant `__init__` method in `EddyQuad` class. - Use `os.path.abspath()` earlier in order to remove from later statements. - Improve `EddyQuad`'s `base_name` input description. - Remove unnecessary `mandatory=False` params. - Rename `slspec` to `slice_spec`. - Use default for `EddyQuad`'s `base_name` input. - Use a name template for `EddyQuad`'s `output_dir` input.
Codecov Report
@@ Coverage Diff @@
## master #2825 +/- ##
==========================================
- Coverage 67.39% 67.38% -0.02%
==========================================
Files 341 341
Lines 43428 43474 +46
Branches 5396 5401 +5
==========================================
+ Hits 29270 29294 +24
- Misses 13461 13474 +13
- Partials 697 706 +9
Continue to review full report at Codecov.
|
Thanks for your review @effigies. I responded inline to your reviews and closed the ones that I felt were trivially resolved, leaving the more involved ones to you to review and close if you agree that I've addressed them. Thanks again for your help! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for making the changes. Sorry to do this to you, but I've got another round of comments, and some of them are to undo some of what you've done... Thanks for your patience.
.zenodo.json
Outdated
"affiliation": "University of Washington", | ||
"name": "Richie-Halford, Adam", | ||
"orcid": "0000-0001-9276-9084" | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
}, | |
} |
nipype/interfaces/fsl/epi.py
Outdated
class EddyQuadOutputSpec(TraitedSpec): | ||
out_qc_json = File( | ||
exists=True, | ||
mandatory=True, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mandatory=True, |
nipype/interfaces/fsl/epi.py
Outdated
|
||
out_qc_pdf = File( | ||
exists=True, | ||
mandatory=True, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mandatory=True, |
nipype/interfaces/fsl/epi.py
Outdated
) | ||
|
||
out_avg_b_png = traits.List( | ||
File( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File( | |
File(exists=True), |
nipype/interfaces/fsl/epi.py
Outdated
exists=True, | ||
mandatory=True, | ||
desc=("Image showing mid-sagittal, -coronal and -axial slices of " | ||
"each averaged b-shell volume.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
desc
should be a parameter to List
, not File
, and you can drop mandatory
. I've suggested removing it from the other output spec files... I don't think it's enforced, but if it is, it will cause problems if you have the remove_unnecessary_outputs
config option set, and no node takes those files as inputs.
nipype/interfaces/fsl/epi.py
Outdated
mandatory=False, | ||
desc=("Image showing mid-sagittal, -coronal and -axial slices of " | ||
"each b-shell CNR volume. Generated when CNR maps are " | ||
"available.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again.
nipype/interfaces/fsl/epi.py
Outdated
|
||
out_vdm_png = File( | ||
exists=True, | ||
mandatory=False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mandatory=False, |
nipype/interfaces/fsl/epi.py
Outdated
|
||
out_residuals = File( | ||
exists=True, | ||
mandatory=False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mandatory=False, |
nipype/interfaces/fsl/epi.py
Outdated
|
||
out_clean_volumes = File( | ||
exists=True, | ||
mandatory=False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mandatory=False, |
nipype/interfaces/fsl/epi.py
Outdated
outputs['out_qc_pdf'] = os.path.join(out_dir, 'qc.pdf') | ||
|
||
with open(outputs['out_qc_json']) as fp: | ||
qc = json.load(fp) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, we'd prefer glob
to this. The reason is that _list_outputs()
should be runnable without having already run the interface. With glob
you'll just get an empty list, while attempting to read a JSON file will actually fail.
If there's no way to predict the outputs entirely without running, that's fine. I was just suggesting that, if you could, that's a little nicer. But we should only depend on self.inputs
to determine the expected outputs. And I can't remember whether you used sorted(glob(...))
before, but I would recommend sorting the list so it's consistent across runs. (glob
does not have to return sorted lists.)
Hi, just a reminder that the 1.1.8 release is targeted for January 28. Please let us know if you'd like to try to finish this up for that release. |
Yes. Sorry for the delay and thanks for the nudge. I'll try to get this done in the next week. |
@effigies I think this is ready for review. I changed back to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome. Looks good. A few minor touchups and suggestions, and I think this is good to go. Feel free to push back if I'm getting too nit-picky, by the way.
# If the output directory isn't defined, the interface seems to use | ||
# the default but not set its value in `self.inputs.output_dir` | ||
if not isdefined(self.inputs.output_dir): | ||
out_dir = os.path.abspath(os.path.basename(self.inputs.base_name) + '.qc.nii.gz') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default output is a directory named eddy_corrected.qc.nii.gz/
? This looks weird, so just want to check there isn't a typo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@akeshavan, we tested this on your system. I think this is correct but it is very weird. Could you confirm? (I don't want to take the hours needed to build the docker image on my laptop. 😏)
Oh, can you please merge |
@akeshavan Feel free to merge if you're happy with this. |
- Remove redundant `__init__` method in `EddyQuad` class. - Use `os.path.abspath()` earlier in order to remove from later statements. - Improve `EddyQuad`'s `base_name` input description. - Remove unnecessary `mandatory=False` params. - Rename `slspec` to `slice_spec`. - Use default for `EddyQuad`'s `base_name` input. - Use a name template for `EddyQuad`'s `output_dir` input.
Co-Authored-By: richford <richford@users.noreply.github.com>
2fe91b9
to
41d82ad
Compare
Just rebased onto master (with a force push for the change in history). |
I think we can take your word on the default |
* origin/master: (63 commits) Update nipype/interfaces/dipy/tracks.py Update nipype/interfaces/dipy/reconstruction.py MNT: Install numpy!=1.16.0 from conda in Docker Add FSL auto test remake specs Update nipype/interfaces/io.py Remove return type named tuple Update nipype/info.py STY: Whitespace, line length Remove out_ prefix from EddyQuad outputs Apply minor edits from code review Use os.path.basename for the fallback output_dir in EddyQuad._list_outputs() Add output_dir check to EddyQuad._list_outputs() Remove redundant out_avg_b_png lines Add glob stuff back in Edit in response to @effigies comments on PR nipy#2825 Fix tests for EddyQuad in interfaces/fsl/epi.py Add name to .zenodo.json Add doctest for EddyQuad fix: made the outputdir be mandatory and use the default val ...
1.1.8 (January 28, 2019) * FIX: ANTS LaplacianThickness cmdline opts fixed up (nipy#2846) * FIX: Resolve LinAlgError during SVD (nipy#2838) * ENH: Add interfaces wrapping DIPY worflows (nipy#2830) * ENH: Update BIDSDataGrabber for pybids 0.7 (nipy#2737) * ENH: Add FSL `eddy_quad` interface (nipy#2825) * ENH: Support tckgen -select in MRtrix3 v3+ (nipy#2823) * ENH: Support for BIDS event files (nipy#2845) * ENH: CompositeTransformUtil, new ANTs interface (nipy#2785) * RF: Move pytest and pytest-xdist from general requirement into tests_required (nipy#2850) * DOC: Add S3DataGrabber example (nipy#2849) * DOC: Skip conftest module in API generation (nipy#2852) * DOC: Hyperlink DOIs to preferred resolver (nipy#2833) * MAINT: Install numpy!=1.16.0 from conda in Docker (nipy#2862) * MAINT: Drop pytest-xdist requirement, minimum pytest version (nipy#2856) * MAINT: Disable numpy 1.16.0 for Py2.7 (nipy#2855) * tag '1.1.8': (79 commits) MNT: Add @feilong to .zenodo, update ordering MNT: Update .mailmap MNT: Update .zenodo ordering Accept invitation as Zenodo release co-author (see nipy#2864) MAINT: Update .mailmap BF: allowing bids_event_file as alternate input MNT: Update .zenodo ordering MNT: Version 1.1.8 DOC: 1.1.8 changelog Update nipype/interfaces/dipy/tracks.py Update nipype/interfaces/dipy/reconstruction.py MNT: Install numpy!=1.16.0 from conda in Docker Add FSL auto test remake specs Update nipype/interfaces/io.py Remove return type named tuple Update nipype/info.py STY: Whitespace, line length Remove out_ prefix from EddyQuad outputs Apply minor edits from code review ...
Summary
This PR adds an interface to
eddy_quad
, one of two tools in the EDDY QC framework.See the EDDY QC documentation for further details. Thanks to @akeshavan for help with my first nipype PR.
List of changes proposed in this PR (pull-request)
EddyQuadInputSpec
classEddyQuadOutputSpec
classEddyQuad
class with doctestAcknowledgment