|
10 | 10 | from typing import TYPE_CHECKING |
11 | 11 |
|
12 | 12 | import nibabel as nib |
13 | | -from niwrap import afni, fsl |
| 13 | +from niwrap import afni |
14 | 14 |
|
15 | 15 | if TYPE_CHECKING: |
16 | 16 | from collections.abc import Sequence |
17 | 17 | from pathlib import Path |
18 | 18 |
|
19 | 19 | from rbc.core.fileops import file_tmp_copy |
| 20 | +from rbc.core.niwrap import generate_exec_folder |
20 | 21 |
|
21 | 22 | __all__ = ["deoblique_and_reorient", "merge_3d_to_4d", "split_4d"] |
22 | 23 |
|
@@ -49,19 +50,24 @@ def deoblique_and_reorient( |
49 | 50 | def split_4d(img_4d: Path) -> list[Path]: |
50 | 51 | """Split a 4D NIfTI timeseries into individual 3D volumes. |
51 | 52 |
|
| 53 | + Volumes are written as uncompressed NIfTI (.nii) to avoid gzip |
| 54 | + overhead on float intermediates that are read back immediately. |
| 55 | +
|
52 | 56 | Args: |
53 | 57 | img_4d: Path to a 4D NIfTI image. |
54 | 58 |
|
55 | 59 | Returns: |
56 | 60 | Sorted list of paths to the individual 3D volume files. |
57 | 61 | """ |
58 | | - split_result = fsl.fslsplit( |
59 | | - infile=img_4d, separation_time=True, output_basename="vol_" |
60 | | - ) |
61 | | - assert split_result.out_files is not None # noqa: S101 |
62 | | - out_files = split_result.out_files |
63 | | - out_dir = out_files[0].parent if isinstance(out_files, list) else out_files.parent |
64 | | - return sorted(out_dir.glob("vol_*.nii.gz")) |
| 62 | + img = nib.nifti1.load(img_4d) |
| 63 | + volumes = nib.four_to_three(img) |
| 64 | + out_dir = generate_exec_folder(suffix="split4d") |
| 65 | + paths: list[Path] = [] |
| 66 | + for idx, vol in enumerate(volumes): |
| 67 | + out_path = out_dir / f"vol_{idx:04d}.nii" |
| 68 | + nib.save(vol, out_path) |
| 69 | + paths.append(out_path) |
| 70 | + return paths |
65 | 71 |
|
66 | 72 |
|
67 | 73 | def merge_3d_to_4d(volumes: Sequence[Path], output: Path) -> Path: |
|
0 commit comments