Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions src/rbc/core/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
from typing import TYPE_CHECKING

import nibabel as nib
from niwrap import afni, fsl
from niwrap import afni

if TYPE_CHECKING:
from collections.abc import Sequence
from pathlib import Path

from rbc.core.fileops import file_tmp_copy
from rbc.core.niwrap import generate_exec_folder

__all__ = ["deoblique_and_reorient", "merge_3d_to_4d", "split_4d"]

Expand Down Expand Up @@ -49,19 +50,24 @@ def deoblique_and_reorient(
def split_4d(img_4d: Path) -> list[Path]:
"""Split a 4D NIfTI timeseries into individual 3D volumes.

Volumes are written as uncompressed NIfTI (.nii) to avoid gzip
overhead on float intermediates that are read back immediately.

Args:
img_4d: Path to a 4D NIfTI image.

Returns:
Sorted list of paths to the individual 3D volume files.
"""
split_result = fsl.fslsplit(
infile=img_4d, separation_time=True, output_basename="vol_"
)
assert split_result.out_files is not None # noqa: S101
out_files = split_result.out_files
out_dir = out_files[0].parent if isinstance(out_files, list) else out_files.parent
return sorted(out_dir.glob("vol_*.nii.gz"))
img = nib.nifti1.load(img_4d)
volumes = nib.four_to_three(img)
out_dir = generate_exec_folder(suffix="split4d")
paths: list[Path] = []
for idx, vol in enumerate(volumes):
out_path = out_dir / f"vol_{idx:04d}.nii"
nib.save(vol, out_path)
paths.append(out_path)
return paths


def merge_3d_to_4d(volumes: Sequence[Path], output: Path) -> Path:
Expand Down
4 changes: 2 additions & 2 deletions src/rbc/core/functional/distortion.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ def correct_distortion_phasediff(
diff_img = nib.Nifti1Image(
diff_data, affine=p1_img.affine, header=p1_img.header
)
phasediff = out_dir / "phasediff.nii.gz"
phasediff = out_dir / "phasediff.nii"
nib.save(diff_img, phasediff)

# 4. Prepare fieldmap (rad/s)
Expand Down Expand Up @@ -454,7 +454,7 @@ def correct_distortion_pepolar(
# 2. Merge forward/reverse into 4D
merged_path = merge_3d_to_4d(
volumes=[epi_forward, epi_reverse],
output=out_dir / "merged_epi.nii.gz",
output=out_dir / "merged_epi.nii",
)

# 3. Estimate field with TOPUP
Expand Down
8 changes: 4 additions & 4 deletions src/rbc/core/functional/masking.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def bold_masking(
warped_probseg = ants.ants_apply_transforms(
reference_image=bold_ref,
output=ants.ants_apply_transforms_warped_output(
warped_output_file_name="probseg_transform.nii.gz"
warped_output_file_name="probseg_transform.nii"
),
default_value=0,
float_=True,
Expand Down Expand Up @@ -222,7 +222,7 @@ def bold_masking(
# mismatches before N4 correction.
bold_ref_dir_corrected = ants.set_direction_by_matrix(
infile=bold_ref,
outfile="bold_ref_dir_corrected.nii.gz",
outfile="bold_ref_dir_corrected.nii",
direction_matrix=parse_direction_matrix_from_header(
dilated_binary_mask.output_file
),
Expand All @@ -233,7 +233,7 @@ def bold_masking(
n4_bias_correction = ants.n4_bias_field_correction(
input_image=bold_ref_dir_corrected.outfile,
output=ants.n4_bias_field_correction_corrected_output(
corrected_output_file_name="ref_bold_corrected.nii.gz"
corrected_output_file_name="ref_bold_corrected.nii"
),
image_dimensionality=3,
bspline_fitting=ants.n4_bias_field_correction_bspline_fitting(
Expand Down Expand Up @@ -286,7 +286,7 @@ def bold_masking(
in_file=masked_bold.output_file,
cl_frac=0.2,
rbt=[18.3, 65, 90],
prefix="uni.nii.gz",
prefix="uni.nii",
t2=True,
)

Expand Down
2 changes: 1 addition & 1 deletion src/rbc/core/functional/motion.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def extract_motion_reference(in_file: Path) -> Path:
header=ref_im.header,
)

temp_slice_file = generate_exec_folder(suffix="motion_ref_input") / "slice.nii.gz"
temp_slice_file = generate_exec_folder(suffix="motion_ref_input") / "slice.nii"
ref_im.to_filename(temp_slice_file)

mc_output_prefix = f"{_MC_PREFIX}_volreg.nii.gz"
Expand Down
4 changes: 2 additions & 2 deletions src/rbc/core/functional/resampling.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def apply_motion_transforms(
default_value=0,
dimensionality=3,
output=ants.ants_apply_transforms_warped_output(
f"vol_{idx:04d}_motion.nii.gz"
f"vol_{idx:04d}_motion.nii"
),
)
transformed_vols.append(result.output.output_image_outfile)
Expand Down Expand Up @@ -193,7 +193,7 @@ def resample_bold_to_template(
default_value=0,
dimensionality=3,
output=ants.ants_apply_transforms_warped_output(
f"vol_{idx:04d}_template.nii.gz"
f"vol_{idx:04d}_template.nii"
),
)
transformed_vols.append(result.output.output_image_outfile)
Expand Down
2 changes: 1 addition & 1 deletion src/rbc/core/longitudinal/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def _transform_4d_chunked(in_file: Path, template: Path, xfm: Path) -> Path:
dimensionality=3,
interpolation=ants.ants_apply_transforms_linear(),
output=ants.ants_apply_transforms_warped_output(
f"vol_{idx:04d}_template.nii.gz"
f"vol_{idx:04d}_template.nii"
),
)
transformed_vols.append(result.output.output_image_outfile)
Expand Down