-
Notifications
You must be signed in to change notification settings - Fork 54
ENH: Add smooth
input to RegridToZooms
#549
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
ENH: Add smooth
input to RegridToZooms
#549
Conversation
Best reviewed: commit by commit
Optimal code review plan (2 commits squashed)
|
Codecov Report
@@ Coverage Diff @@
## master #549 +/- ##
==========================================
- Coverage 64.65% 59.80% -4.86%
==========================================
Files 44 43 -1
Lines 5396 5386 -10
Branches 791 789 -2
==========================================
- Hits 3489 3221 -268
- Misses 1747 2028 +281
+ Partials 160 137 -23
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
niworkflows/utils/images.py
Outdated
data = gaussian_filter(in_file.get_fdata(), | ||
2 if smooth is True else smooth).astype(dtype) |
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.
Should we default to something besides 2? Scikit-image uses (max downsampling factor - 1) / 2.
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.
minor comments
niworkflows/utils/images.py
Outdated
@@ -195,6 +194,13 @@ def resample_by_spacing(in_file, zooms, order=3, clip=True): | |||
new_card.dot(np.vstack((new_grid, np.ones((1, new_grid.shape[1]))))) | |||
) | |||
|
|||
if smooth: | |||
from scipy.ndimage import gaussian_filter | |||
data = gaussian_filter(in_file.get_fdata(), |
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.
why the difference of in_file.get_fdata()
and in_file.dataobj
?
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.
gaussian_filter
wants float, and nibabel does it conveniently. Please note the astype
in the next line
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.
You'll probably want to round if re-casting to int, otherwise you truncate 2.9 to 2.
Resampling (up- or down-) typically requires a gussian smoothing to be run before, so that outliers are not introduced (esp. when downsampling). This PR adds this option, relying on scipy.
26b788b
to
e7fdd57
Compare
Scaling factors are based on zooms, not dimensions. And I don't understand why you're using get_data_dtype to determine the type of the interpreted data. |
Right, thanks for catching this.
TBH, because I thought that is the correct way of doing it. Please suggest what would be best. |
e7fdd57
to
f803bdd
Compare
What's the goal of manually setting the dtype? Is there a case where you want to clip your data to integers? |
The output image should be of the same dtype of the input - so I guess this is correct? |
What should be correct? I'm having trouble following the conversation. Can you provide a concrete case where setting the dtype might help? |
let ``map_coordinates`` do the trick.
I have removed the casting in the latest commit. After thinking about it, there's no need to re-cast the data because Please note that we still need to interrogate the data type on disk because the output of this function should not modify the datatype. Is there any automated operation on the dtype by nibabel? (either casting the data array to the dtype stated on the header or vice-versa, changing the nifti header to reflect the datatype of the data array. |
The data will be cast to the dtype set in the header. If scale factors are needed to make it work, they will be set. The only time you determine the on-disk dtype from the data object is if you don't pass in a header. |
Co-authored-by: Chris Markiewicz <[email protected]>
Got it
Does this mean the cast does not round? I'm not sure we don't want to round in this case. |
It will round to the precision of your output type. Basically what you get is: def rescale_data(data, dtype):
# assume dtype is int
dinfo = np.iinfo(dtype)
# Slope matches change in data range, so we get fixed precision
slope = (data.max() - data.min()) / (dinfo.max - dinfo.min)
# We want inter such that orig_min = new_min * slope + inter
inter = data.min() - dinfo.min * slope
# And generally, orig_data = new_data * slope + inter
new_data = (data - data.min()) / slope + dinfo.min
# Round and truncate to precision of the target data type
return np.round(new_data).astype(dtype), slope, inter
def reconstruct_data(data, slope, inter):
return data * slope + inter
data = np.random.default_rng().normal(1000, 200, size=(5,5,5))
new_data, slope, inter = rescale_data(data, 'int16')
reconstructed = reconstruct_data(new_data, slope, inter)
np.abs(reconstructed - data).max()
Round to what? |
if issubclass(input_nii.header.get_data_dtype(), numbers.Integer) and not issubclass(data.dtype, numbers.Integer):
data = np.round(data).astype(input_nii.header.get_data_dtype()) |
That's done implicitly. |
First release in the 1.3.x series. This release includes enhancements and bug-fixes towards the release of the first LTS version of fMRIPrep. PyBIDS has been revised to use more recent versions, a series of ANTs' interfaces have been deemed ready to upstream into Nipype, and several improvements regarding multi-echo EPI are included. With thanks to Basile Pinsard for contributions. * FIX: Patch ``ApplyTransforms`` spec to permit identity in a chain (#554) * FIX: Add dots to extensions in PyBIDS' config file (#548) * FIX: Segmentation plots aligned with cardinal axes (#544) * FIX: Skip T1w file existence check if ``anat_derivatives`` are provided (#545) * FIX: Avoid diverting CIFTI dtype from original BOLD (#532) * ENH: Add ``smooth`` input to ``RegridToZooms`` (#549) * ENH: Enable ``DerivativesDataSink`` to take multiple source files to derive entities (#547) * ENH: Allow ``bold_reference_wf`` to accept multiple EPIs/SBRefs (#408) * ENH: Numerical stability of EPI brain-masks using probabilistic prior (#485) * ENH: Add a pure-Python interface to resample to specific resolutions (#511) * MAINT: Finalize upstreaming of ANTs' interfaces to Nipype (#550) * MAINT: Update to Python +3.6 (#541)
1.3.0rc3 First release in the 1.3.x series. This release includes enhancements and bug-fixes towards the release of the first LTS version of fMRIPrep. PyBIDS has been revised to use more recent versions, a series of ANTs' interfaces have been deemed ready to upstream into Nipype, and several improvements regarding multi-echo EPI are included. With thanks to Basile Pinsard for contributions. * FIX: Patch ``ApplyTransforms`` spec to permit identity in a chain (nipreps#554) * FIX: Add dots to extensions in PyBIDS' config file (nipreps#548) * FIX: Segmentation plots aligned with cardinal axes (nipreps#544) * FIX: Skip T1w file existence check if ``anat_derivatives`` are provided (nipreps#545) * FIX: Avoid diverting CIFTI dtype from original BOLD (nipreps#532) * ENH: Add ``smooth`` input to ``RegridToZooms`` (nipreps#549) * ENH: Enable ``DerivativesDataSink`` to take multiple source files to derive entities (nipreps#547) * ENH: Allow ``bold_reference_wf`` to accept multiple EPIs/SBRefs (nipreps#408) * ENH: Numerical stability of EPI brain-masks using probabilistic prior (nipreps#485) * ENH: Add a pure-Python interface to resample to specific resolutions (nipreps#511) * MAINT: Finalize upstreaming of ANTs' interfaces to Nipype (nipreps#550) * MAINT: Update to Python +3.6 (nipreps#541)
1.3.0 First release in the 1.3.x series. This release includes enhancements and bug-fixes towards the release of the first LTS (*long-term support*) version of *fMRIPrep*. *PyBIDS* has been revised to use more recent versions, a series of ANTs' interfaces have been deemed ready to upstream into *Nipype*, and several improvements regarding multi-echo EPI are included. With thanks to Basile Pinsard for contributions. * FIX: Patch ``ApplyTransforms`` spec to permit identity in a chain (nipreps#554) * FIX: Add dots to extensions in PyBIDS' config file (nipreps#548) * FIX: Segmentation plots aligned with cardinal axes (nipreps#544) * FIX: Skip T1w file existence check if ``anat_derivatives`` are provided (nipreps#545) * FIX: Avoid diverting CIFTI dtype from original BOLD (nipreps#532) * ENH: Add ``smooth`` input to ``RegridToZooms`` (nipreps#549) * ENH: Enable ``DerivativesDataSink`` to take multiple source files to derive entities (nipreps#547) * ENH: Allow ``bold_reference_wf`` to accept multiple EPIs/SBRefs (nipreps#408) * ENH: Numerical stability of EPI brain-masks using probabilistic prior (nipreps#485) * ENH: Add a pure-Python interface to resample to specific resolutions (nipreps#511) * MAINT: Upstream all bug-fixes in the 1.2.9 release * MAINT: Finalize upstreaming of ANTs' interfaces to Nipype (nipreps#550) * MAINT: Update to Python +3.6 (nipreps#541)
Resampling (up- or down-) typically requires a gussian smoothing to be
run before, so that outliers are not introduced (esp. when
downsampling).
This PR adds this option, relying on scipy.
This is the first element of a series of PRs deconstructing #506 into digestible, independent bits.