Skip to content

Commit

Permalink
Recompress files where dcm2niix failed
Browse files Browse the repository at this point in the history
  • Loading branch information
octomike committed Nov 12, 2024
1 parent 900ccdc commit 7aff494
Showing 1 changed file with 46 additions and 0 deletions.
46 changes: 46 additions & 0 deletions heudiconv/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import random
import re
import shutil
import gzip
import sys
from types import ModuleType
from typing import TYPE_CHECKING, Any, List, Optional, cast
Expand Down Expand Up @@ -630,6 +631,19 @@ def convert(
item_dicoms, prefix, with_prov, bids_options, tmpdir, dcmconfig
)

# try to handle compression failures from dcm2niix
if outtype == 'nii.gz':
converted_files = res.outputs.converted_files
if not isinstance(converted_files, list):
converted_files = [converted_files]
uncompressed = [x for x in converted_files if x.endswith('.nii')]
if len(uncompressed) > 0:
lgr.warning("Conversion returned uncompressed nifti (>4GB?) - "

Check warning on line 641 in heudiconv/convert.py

View check run for this annotation

Codecov / codecov/patch

heudiconv/convert.py#L641

Added line #L641 was not covered by tests
"trying to salvage by recompressing ourselves. "
"This might take a while ")
if not recompress_failed(uncompressed):
raise RuntimeError("Error compressing nifti")

Check warning on line 645 in heudiconv/convert.py

View check run for this annotation

Codecov / codecov/patch

heudiconv/convert.py#L644-L645

Added lines #L644 - L645 were not covered by tests

bids_outfiles = save_converted_files(
res,
item_dicoms,
Expand Down Expand Up @@ -1099,3 +1113,35 @@ def bvals_are_zero(bval_file: str | list) -> bool:

bvals_unique = set(float(b) for b in bvals)
return bvals_unique == {0.0} or bvals_unique == {5.0}


def recompress_failed(niftis: list) -> bool:
"""Tries to recompress nifti files with built-in gzip module
Parameters
----------
niftis : list
list of nifti file paths
Returns
-------
True if all nifits were sucessfully compressed. False otherwise.
"""

from nibabel import load as nb_load
from nibabel.filebasedimages import ImageFileError

Check warning on line 1132 in heudiconv/convert.py

View check run for this annotation

Codecov / codecov/patch

heudiconv/convert.py#L1131-L1132

Added lines #L1131 - L1132 were not covered by tests

for nifti in niftis:
try:
img = nb_load(nifti)
_ = img.get_fdata() # read everything to catch truncated/corrupted files
with open(nifti, 'rb') as f_in:
with gzip.open(nifti + '.gz', 'wb', compresslevel=6) as f_out:
shutil.copyfileobj(f_in, f_out)

Check warning on line 1140 in heudiconv/convert.py

View check run for this annotation

Codecov / codecov/patch

heudiconv/convert.py#L1134-L1140

Added lines #L1134 - L1140 were not covered by tests
# nipype results still carry uncompressed file names and they will
# be renamed to '.nii.gz' later
os.rename(nifti + '.gz', nifti)
except (OSError, ImageFileError, gzip.zlib.error):
return False

Check warning on line 1145 in heudiconv/convert.py

View check run for this annotation

Codecov / codecov/patch

heudiconv/convert.py#L1143-L1145

Added lines #L1143 - L1145 were not covered by tests

return True

Check warning on line 1147 in heudiconv/convert.py

View check run for this annotation

Codecov / codecov/patch

heudiconv/convert.py#L1147

Added line #L1147 was not covered by tests

0 comments on commit 7aff494

Please sign in to comment.