-
Notifications
You must be signed in to change notification settings - Fork 12
ENH: Add option to exclude projecting high variance voxels to surface #235
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
…ing Workbench interfaces
…pler option (to be continued in a separate branch)
…urfaces for test sub)
Codecov ReportBase: 30.70% // Head: 31.52% // Increases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## master #235 +/- ##
==========================================
+ Coverage 30.70% 31.52% +0.81%
==========================================
Files 43 49 +6
Lines 3696 4634 +938
==========================================
+ Hits 1135 1461 +326
- Misses 2561 3173 +612
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
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.
Hey Thomas, thank you for the PR! I've gone through a first pass and left some comments.
Regarding some of the style changes - nibabies leverages pre-commit
to run styling hooks automatically when committing. To get this, first install it (pip install pre-commit
) and then run pre-commit install
in the root. This will trigger some automatic checks when attempting to git commit
. You may have to run black
and isort
manually to fix the previous commits. I'm just realizing we don't really have a nibabies-specific contributor's guideline, so will work on adding one.
nibabies/interfaces/volume.py
Outdated
def _list_outputs(self): | ||
outputs = super(CreateSignedDistanceVolume, self)._list_outputs() | ||
return outputs |
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.
No need for this since it's just calling the inherited method
def _list_outputs(self): | |
outputs = super(CreateSignedDistanceVolume, self)._list_outputs() | |
return outputs |
@@ -135,48 +199,422 @@ def select_target(subject_id, space): | |||
name="outputnode", | |||
) | |||
|
|||
# fmt: off | |||
# 0, 1 = wm; 2, 3 = pial; 6, 7 = mid |
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.
Since this is such a large addition, I think it would make more sense to make this a subworkflow, and call it within init_bold_surf_wf
so we don't clutter the connections.
mem_gb=DEFAULT_MEMORY_MIN_GB, | ||
) |
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.
Generally, we can run most nipype utility interfaces on the master process since they are not intense operations - no need to potentially submit to a job queue.
mem_gb=DEFAULT_MEMORY_MIN_GB, | |
) | |
mem_gb=DEFAULT_MEMORY_MIN_GB, | |
run_without_submitting=True, | |
) |
mem_gb=DEFAULT_MEMORY_MIN_GB, | ||
) |
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.
mem_gb=DEFAULT_MEMORY_MIN_GB, | |
) | |
mem_gb=DEFAULT_MEMORY_MIN_GB, | |
run_without_submitting=True, | |
) |
select_midthick = pe.Node( | ||
niu.Select(index=[6, 7]), | ||
name="select_midthick", | ||
mem_gb=DEFAULT_MEMORY_MIN_GB, |
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.
mem_gb=DEFAULT_MEMORY_MIN_GB, | |
mem_gb=DEFAULT_MEMORY_MIN_GB, | |
run_without_submitting=True, |
nibabies/interfaces/volume.py
Outdated
surface = File( | ||
exists=True, | ||
mandatory=True, | ||
argstr="%s ", |
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 don't think you need to add a trailing space for these
argstr="%s ", | |
argstr="%s", |
) | ||
|
||
cov_ribbon_mean = pe.Node( | ||
fsl.ImageStats(op_string='-M '), |
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.
Trailing spaces again.
fsl.ImageStats(op_string='-M '), | |
fsl.ImageStats(op_string='-M'), |
Ah, sorry, I hadn't noticed you'd started a review over here. Looks like we at least were thinking in the same direction where we overlapped. |
Removed duplicate code by abstracting it into functions, clarifying the goodvoxels logic
- Implemented the formatting suggestions by Mathias at the URLs below: - nipreps#235 - nipreps/fmriprep#2855 - Split the 3 workflow-connect blocks in the project-goodvoxels section of resampling.py into 3 different functions: ribbon, outliers, and vol-to-surf - Incomplete comments in resampling.py
Reorganized/cleaned goodvoxels resampling.py
… into madisoth-goodvoxels
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.
Hi @GregConan - thanks for contributing and pushing on this! I started going through and leaving some comments - let me know if anything doesn't make sense, or if you would like to schedule a call to go over some things.
nibabies/interfaces/volume.py
Outdated
@@ -0,0 +1,133 @@ | |||
# -*- coding: utf-8 -*- |
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 think this would be better suited to go in the workbench
module https://github.com/nipreps/nibabies/blob/master/nibabies/interfaces/workbench.py
nibabies/workflows/bold/base.py
Outdated
@@ -321,6 +321,7 @@ def init_func_preproc_wf(bold_file, has_fieldmap=False, existing_derivatives=Non | |||
"anat2std_xfm", | |||
"std2anat_xfm", | |||
"template", | |||
"anat_giftis", |
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.
This should probably be anat_surfaces
to avoid confusion, now that morphometric files (which are also giftis) are available
"subjects_dir", | ||
"t1w2fsnative_xfm", | ||
"anat_giftis", | ||
"t1w_mask", |
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.
Not sure if this is T1w specific, but one goal for down the line is to allow T1/T2 only processing, so to future-proof may want to rename this to anat_mask
if project_goodvoxels: | ||
workflow.__desc__ += """\ | ||
Before resampling, a "goodvoxels" mask [@hcppipelines] was applied, | ||
excluding voxels whose time-series have a locally high coetfficient of |
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.
excluding voxels whose time-series have a locally high coetfficient of | |
excluding voxels whose time-series have a locally high coefficient of |
|
||
from niworkflows.interfaces.freesurfer import MedialNaNs | ||
def make_ribbon_file(workflow, mem_gb, inputnode): |
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.
This seems like an anatomical workflow, so it should go in the https://github.com/nipreps/nibabies/tree/master/nibabies/workflows/anatomical module.
Also, to stay consistent with nipreps best practices, let's rename/restructure this as a separate workflow.
def make_ribbon_file(workflow, mem_gb, inputnode): | |
def init_ribbon_volume_wf(mem_gb, name='ribbon_volume_wf'): |
|
||
|
||
def apply_med_surf_nans_if( | ||
medial_surface_nan, workflow, inputnode, sampler, update_metadata, medial_nans |
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.
We generally stay away from passing workflows / inputs / nodes as parameters, as that greatly complicates the logic / testing.
These connections can be applied within the init_
workflow function
return workflow | ||
|
||
|
||
def connect_bold_surf_wf( |
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.
Same as above
FIX: Minor anat wf & workbench.py fixes (+5 squashed commit) Squashed commit: [e995ec4] RF: Moved ribbon wf (from bold to anat) and reformatted [9676f14] Updated Docker version tag [532875e] STY: black and isort [946dc7e] Formatting fixes and resampling.py modularization - Implemented the formatting suggestions by Mathias at the URLs below: - nipreps#235 - nipreps/fmriprep#2855 - Split the 3 workflow-connect blocks in the project-goodvoxels section of resampling.py into 3 different functions: ribbon, outliers, and vol-to-surf - Incomplete comments in resampling.py [114f982] Modularized goodvoxels code in resampling.py Removed duplicate code by abstracting it into functions, clarifying the goodvoxels logic
ENH: Add option to exclude projecting high variance voxels to surface (update of #235)
Adds option
--project-goodvoxels
.If enabled, voxels whose timeseries have locally high coefficient of variation, or which lie outside the cortex (based on signed distance volumes generated from the WM and pial surfaces), are excluded from volume-to-surface sampling of BOLD timeseries.
Note that unlike HCP / ciftify, no dilation or spatial smoothing is applied to the surface-resampled BOLD timeseries