Skip to content
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] update_complex_name to handle real+imaginary complex data #761

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
42 changes: 29 additions & 13 deletions heudiconv/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,20 @@
)


IMAGETYPE_TO_PARTS = {
"M": "mag",
"MAGNITUDE": "mag",
"P": "phase",
"PHASE": "phase",
"REAL": "real",
"IMAGINARY": "imag",
}


def update_complex_name(metadata: dict[str, Any], filename: str) -> str:
"""
Insert `_part-<mag|phase>` entity into filename if data are from a
sequence with magnitude/phase part.
Insert `_part-<mag|phase|real|imag>` entity into filename if data are from a
sequence with magnitude/phase/real/imaginary part.

Parameters
----------
Expand Down Expand Up @@ -330,20 +340,27 @@
if any(ut in filename for ut in unsupported_types):
return filename

# Check to see if it is magnitude or phase part:
img_type = cast(List[str], metadata.get("ImageType", []))
if "M" in img_type:
mag_or_phase = "mag"
elif "P" in img_type:
mag_or_phase = "phase"

present_parts = set(
IMAGETYPE_TO_PARTS[tp] for tp in img_type if tp in IMAGETYPE_TO_PARTS
)
if not present_parts:
raise RuntimeError(
f"Data type could not be inferred from the ImageType={img_type}. Known types are: {sorted(IMAGETYPE_TO_PARTS)}"
)
elif len(present_parts) == 1:
part = present_parts.pop()
else:
raise RuntimeError("Data type could not be inferred from the metadata.")
raise RuntimeError(

Check warning on line 355 in heudiconv/convert.py

View check run for this annotation

Codecov / codecov/patch

heudiconv/convert.py#L355

Added line #L355 was not covered by tests
f"Data type could not be inferred from the ImageType={img_type}. Multiple BIDS parts matched: {present_parts}"
)

# Determine scan suffix
filetype = "_" + filename.split("_")[-1]

# Insert part label
if not ("_part-%s" % mag_or_phase) in filename:
if not ("_part-%s" % part) in filename:
# If "_part-" is specified, prepend the 'mag_or_phase' value.
if "_part-" in filename:
raise BIDSError(
Expand All @@ -368,7 +385,7 @@
]
for label in entities_after_part:
if (label == filetype) or (label in filename):
filename = filename.replace(label, "_part-%s%s" % (mag_or_phase, label))
filename = filename.replace(label, "_part-%s%s" % (part, label))
break

return filename
Expand Down Expand Up @@ -984,9 +1001,8 @@
is_uncombined = (
len(set(filter(bool, channel_names))) > 1
) # Check for uncombined data
is_complex = (
"M" in image_types and "P" in image_types
) # Determine if data are complex (magnitude + phase)
# Determine if data are complex (magnitude + phase or real + imag or all-4)
is_complex = len(set(IMAGETYPE_TO_PARTS.keys()).intersection(image_types))
echo_times_lst = sorted(echo_times) # also converts to list
channel_names_lst = sorted(channel_names) # also converts to list

Expand Down
9 changes: 9 additions & 0 deletions heudiconv/dicoms.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@
else:
sequence_name = ""

# GE data
# see https://github.com/rordenlab/dcm2niix/tree/master/GE#complex-image-component
if dcminfo.get([0x43, 0x102F]):
GE_CPLX_CODING = ["MAGNITUDE", "PHASE", "REAL", "IMAGINARY"]
cplx_idx = int(dcminfo.get([0x43, 0x102F]).value)
part = GE_CPLX_CODING[cplx_idx]
if part not in image_type:
image_type = image_type + (part,)

Check warning on line 121 in heudiconv/dicoms.py

View check run for this annotation

Codecov / codecov/patch

heudiconv/dicoms.py#L117-L121

Added lines #L117 - L121 were not covered by tests

# initialized in `group_dicoms_to_seqinfos`
global total_files
total_files += len(series_files)
Expand Down