-
Notifications
You must be signed in to change notification settings - Fork 58
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
Support complex-valued dwidenoising #679
Changes from 26 commits
56772f6
f1bea5f
3d6b10d
3d1ce20
a6bc0a3
970f367
88844cf
a305138
ad1974c
9f06f2a
35df866
0774bc3
b182f12
ddea10e
2aef726
39c50ff
310d9f2
16aeb98
e09cfb5
ae88d98
f155c35
d9c8bdb
2e04518
3d3588f
09394f3
30aab41
ae8acc7
2e983b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
import json | ||
import os.path as op | ||
|
||
import nibabel as nb | ||
import numpy as np | ||
import pandas as pd | ||
from nilearn.image import concat_imgs, index_img, iter_img, load_img, math_img | ||
|
@@ -714,3 +715,77 @@ def create_provenance_dataframe( | |
image_df = pd.concat(series_confounds, axis=0, ignore_index=True) | ||
image_df["original_file"] = bids_sources | ||
return image_df | ||
|
||
|
||
class _PhaseToRadInputSpec(BaseInterfaceInputSpec): | ||
phase_file = File(exists=True, mandatory=True) | ||
|
||
|
||
class _PhaseToRadOutputSpec(TraitedSpec): | ||
phase_file = File(exists=True) | ||
|
||
|
||
class PhaseToRad(SimpleInterface): | ||
"""Convert phase image from arbitrary units (au) to radians. | ||
|
||
This method assumes that the phase image's minimum and maximum values correspond to | ||
-pi and pi, respectively, and scales the image to be between 0 and 2*pi. | ||
|
||
Notes | ||
----- | ||
The code is derived from | ||
https://github.com/nipreps/sdcflows/blob/c6cd42944f4b6d638716ce020ffe51010e9eb58a/\ | ||
sdcflows/utils/phasemanip.py#L26. | ||
|
||
License | ||
------- | ||
Copyright 2021 The NiPreps Developers <[email protected]> | ||
mattcieslak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
|
||
We support and encourage derived works from this project, please read | ||
about our expectations at | ||
|
||
https://www.nipreps.org/community/licensing/ | ||
|
||
""" | ||
|
||
input_spec = _PhaseToRadInputSpec | ||
output_spec = _PhaseToRadOutputSpec | ||
|
||
def _run_interface(self, runtime): | ||
im = nb.load(self.inputs.phase_file) | ||
data = im.get_fdata(caching="unchanged") # Read as float64 for safety | ||
hdr = im.header.copy() | ||
|
||
# Rescale to [0, 2*pi] | ||
data = (data - data.min()) * (2 * np.pi / (data.max() - data.min())) | ||
|
||
# Round to float32 and clip | ||
data = np.clip(np.float32(data), 0.0, 2 * np.pi) | ||
|
||
hdr.set_data_dtype(np.float32) | ||
hdr.set_xyzt_units("mm") | ||
|
||
# Set the output file name | ||
self._results["phase_file"] = fname_presuffix( | ||
self.inputs.phase_file, | ||
suffix="_rad.nii.gz", | ||
newpath=runtime.cwd, | ||
use_ext=False, | ||
) | ||
|
||
# Save the output image | ||
nb.Nifti1Image(data, None, hdr).to_filename(self._results["phase_file"]) | ||
|
||
return runtime |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1365,3 +1365,54 @@ class TransformHeader(CommandLine): | |
input_spec = _TransformHeaderInputSpec | ||
output_spec = _TransformHeaderOutputSpec | ||
_cmd = "mrtransform -strides -1,-2,3" | ||
|
||
|
||
class _PolarToComplexInputSpec(CommandLineInputSpec): | ||
mag_file = traits.File(exists=True, mandatory=True, position=0, argstr="%s") | ||
phase_file = traits.File(exists=True, mandatory=True, position=1, argstr="%s") | ||
out_file = traits.File( | ||
exists=False, | ||
name_source="mag_file", | ||
name_template="%s_complex.nii.gz", | ||
keep_extension=False, | ||
position=-1, | ||
argstr="-polar %s", | ||
) | ||
|
||
|
||
class _PolarToComplexOutputSpec(TraitedSpec): | ||
out_file = File(exists=True) | ||
|
||
|
||
class PolarToComplex(CommandLine): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you remember where you found the mrcalc commands? Was it on the mrtrix forum? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I got it from the docstring of mrcalc: https://mrtrix.readthedocs.io/en/latest/reference/commands/mrcalc.html#complex-numbers |
||
"""Convert a magnitude and phase image pair to a single complex image using mrcalc.""" | ||
|
||
input_spec = _PolarToComplexInputSpec | ||
output_spec = _PolarToComplexOutputSpec | ||
|
||
_cmd = "mrcalc" | ||
|
||
|
||
class _ComplexToMagnitudeInputSpec(CommandLineInputSpec): | ||
complex_file = traits.File(exists=True, mandatory=True, position=0, argstr="%s") | ||
out_file = traits.File( | ||
exists=False, | ||
name_source="complex_file", | ||
name_template="%s_mag.nii.gz", | ||
keep_extension=False, | ||
position=-1, | ||
argstr="-abs %s", | ||
) | ||
|
||
|
||
class _ComplexToMagnitudeOutputSpec(TraitedSpec): | ||
out_file = File(exists=True) | ||
|
||
|
||
class ComplexToMagnitude(CommandLine): | ||
"""Extract the magnitude portion of a complex image using mrcalc.""" | ||
|
||
input_spec = _ComplexToMagnitudeInputSpec | ||
output_spec = _ComplexToMagnitudeOutputSpec | ||
|
||
_cmd = "mrcalc" |
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 is a great idea - it doesn't require a new commandline flag and is easy to understand