-
Notifications
You must be signed in to change notification settings - Fork 127
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
Replace deprecated "_phase" suffix in reproin heuristic with "part-phase" entity #770
Open
tsalo
wants to merge
6
commits into
nipy:master
Choose a base branch
from
tsalo:reproin-part
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 3 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
55f21bb
Work on part.
tsalo b00e41f
Get it working.
tsalo 168e078
Remove perfusion datatype.
tsalo 2c4835e
Generalize change to other suffixes.
tsalo 0ca3021
Fix.
tsalo 59bb2ec
Merge remote-tracking branch 'upstream/master' into reproin-part
tsalo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -402,32 +402,61 @@ def infotodict( | |
run_label: Optional[str] = None # run- | ||
dcm_image_iod_spec: Optional[str] = None | ||
skip_derived = False | ||
for s in seqinfo: | ||
for i_acq, curr_seqinfo in enumerate(seqinfo): | ||
# XXX: skip derived sequences, we don't store them to avoid polluting | ||
# the directory, unless it is the motion corrected ones | ||
# (will get _rec-moco suffix) | ||
if skip_derived and s.is_derived and not s.is_motion_corrected: | ||
skipped.append(s.series_id) | ||
lgr.debug("Ignoring derived data %s", s.series_id) | ||
if ( | ||
skip_derived | ||
and curr_seqinfo.is_derived | ||
and not curr_seqinfo.is_motion_corrected | ||
): | ||
skipped.append(curr_seqinfo.series_id) | ||
lgr.debug("Ignoring derived data %s", curr_seqinfo.series_id) | ||
continue | ||
|
||
if i_acq == 0: | ||
prev_seqinfo = None | ||
prev_dcm_image_iod_spec = None | ||
else: | ||
prev_seqinfo = seqinfo[i_acq - 1] | ||
for f in "series_description", "protocol_name": | ||
prev_seqinfo = prev_seqinfo._replace( | ||
**{f: getattr(prev_seqinfo, f).format(**prev_seqinfo._asdict())} | ||
) | ||
|
||
prev_dcm_image_iod_spec = prev_seqinfo.image_type[2] | ||
|
||
if i_acq == (len(seqinfo) - 1): | ||
next_seqinfo = None | ||
next_dcm_image_iod_spec = None | ||
else: | ||
next_seqinfo = seqinfo[i_acq + 1] | ||
for f in "series_description", "protocol_name": | ||
next_seqinfo = next_seqinfo._replace( | ||
**{f: getattr(next_seqinfo, f).format(**next_seqinfo._asdict())} | ||
) | ||
|
||
next_dcm_image_iod_spec = next_seqinfo.image_type[2] | ||
|
||
# possibly apply present formatting in the series_description or protocol name | ||
for f in "series_description", "protocol_name": | ||
s = s._replace(**{f: getattr(s, f).format(**s._asdict())}) | ||
curr_seqinfo = curr_seqinfo._replace( | ||
**{f: getattr(curr_seqinfo, f).format(**curr_seqinfo._asdict())} | ||
) | ||
|
||
template = None | ||
suffix = "" | ||
# seq = [] | ||
|
||
# figure out type of image from s.image_info -- just for checking ATM | ||
# figure out type of image from curr_seqinfo.image_info -- just for checking ATM | ||
# since we primarily rely on encoded in the protocol name information | ||
prev_dcm_image_iod_spec = dcm_image_iod_spec | ||
if len(s.image_type) > 2: | ||
if len(curr_seqinfo.image_type) > 2: | ||
# https://dicom.innolitics.com/ciods/cr-image/general-image/00080008 | ||
# 0 - ORIGINAL/DERIVED | ||
# 1 - PRIMARY/SECONDARY | ||
# 3 - Image IOD specific specialization (optional) | ||
dcm_image_iod_spec = s.image_type[2] | ||
dcm_image_iod_spec = curr_seqinfo.image_type[2] | ||
image_type_datatype = { | ||
# Note: P and M are too generic to make a decision here, could be | ||
# for different datatypes (bold, fmap, etc) | ||
|
@@ -443,7 +472,7 @@ def infotodict( | |
|
||
series_info = {} # For please lintian and its friends | ||
for sfield in series_spec_fields: | ||
svalue = getattr(s, sfield) | ||
svalue = getattr(curr_seqinfo, sfield) | ||
series_info = parse_series_spec(svalue) | ||
if series_info: # looks like a valid spec - we are done | ||
series_spec = svalue | ||
|
@@ -454,10 +483,10 @@ def infotodict( | |
if not series_info: | ||
series_spec = None # we cannot know better | ||
lgr.warning( | ||
"Could not determine the series name by looking at " "%s fields", | ||
"Could not determine the series name by looking at %s fields", | ||
", ".join(series_spec_fields), | ||
) | ||
skipped_unknown.append(s.series_id) | ||
skipped_unknown.append(curr_seqinfo.series_id) | ||
continue | ||
|
||
if dcm_image_iod_spec and dcm_image_iod_spec.startswith("MIP"): | ||
|
@@ -476,14 +505,14 @@ def infotodict( | |
series_spec, | ||
) | ||
|
||
# if s.is_derived: | ||
# if curr_seqinfo.is_derived: | ||
# # Let's for now stash those close to original images | ||
# # TODO: we might want a separate tree for all of this!? | ||
# # so more of a parameter to the create_key | ||
# #datatype += '/derivative' | ||
# # just keep it lower case and without special characters | ||
# # XXXX what for??? | ||
# #seq.append(s.series_description.lower()) | ||
# #seq.append(curr_seqinfo.series_description.lower()) | ||
# prefix = os.path.join('derivatives', 'scanner') | ||
# else: | ||
# prefix = '' | ||
|
@@ -493,15 +522,30 @@ def infotodict( | |
# Figure out the datatype_suffix (BIDS _suffix) | ||
# | ||
# If none was provided -- let's deduce it from the information we find: | ||
# analyze s.protocol_name (series_id is based on it) for full name mapping etc | ||
# analyze curr_seqinfo.protocol_name (series_id is based on it) for full name mapping etc | ||
if not datatype_suffix: | ||
if datatype == "func": | ||
if "_pace_" in series_spec: | ||
datatype_suffix = "pace" # or should it be part of seq- | ||
elif "P" in s.image_type: | ||
datatype_suffix = "phase" | ||
elif "M" in s.image_type: | ||
elif ( | ||
"P" in curr_seqinfo.image_type | ||
and not curr_seqinfo.series_description.endswith("_SBRef") | ||
): | ||
datatype_suffix = "bold" | ||
series_info["part"] = "phase" | ||
elif "M" in curr_seqinfo.image_type: | ||
datatype_suffix = "bold" | ||
|
||
# if next one is phase fMRI, we should set part to mag | ||
if ( | ||
( | ||
next_seqinfo.series_description | ||
== curr_seqinfo.series_description | ||
) | ||
and (next_dcm_image_iod_spec == "P") | ||
and not curr_seqinfo.series_description.endswith("_SBRef") | ||
): | ||
series_info["part"] = "mag" | ||
tsalo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
else: | ||
# assume bold by default | ||
datatype_suffix = "bold" | ||
|
@@ -526,7 +570,7 @@ def infotodict( | |
# since they are complementary files produced along-side with original | ||
# ones. | ||
# | ||
if s.series_description.endswith("_SBRef"): | ||
if curr_seqinfo.series_description.endswith("_SBRef"): | ||
datatype_suffix = "sbref" | ||
|
||
if not datatype_suffix: | ||
|
@@ -550,7 +594,10 @@ def infotodict( | |
# XXX if we have a known earlier study, we need to always | ||
# increase the run counter for phasediff because magnitudes | ||
# were not acquired | ||
if get_study_hash([s]) == "9d148e2a05f782273f6343507733309d": | ||
if ( | ||
get_study_hash([curr_seqinfo]) | ||
== "9d148e2a05f782273f6343507733309d" | ||
): | ||
current_run += 1 | ||
else: | ||
raise RuntimeError( | ||
|
@@ -583,10 +630,10 @@ def infotodict( | |
run_label = None | ||
|
||
# yoh: had a wrong assumption | ||
# if s.is_motion_corrected: | ||
# assert s.is_derived, "Motion corrected images must be 'derived'" | ||
# if curr_seqinfo.is_motion_corrected: | ||
# assert curr_seqinfo.is_derived, "Motion corrected images must be 'derived'" | ||
|
||
if s.is_motion_corrected and "rec-" in series_info.get("bids", ""): | ||
if curr_seqinfo.is_motion_corrected and "rec-" in series_info.get("bids", ""): | ||
raise NotImplementedError( | ||
"want to add _rec-moco but there is _rec- already" | ||
) | ||
|
@@ -611,17 +658,19 @@ def from_series_info(name: str) -> Optional[str]: | |
from_series_info("acq"), | ||
# But we want to add an indicator in case it was motion corrected | ||
# in the magnet. ref sample /2017/01/03/qa | ||
None if not s.is_motion_corrected else "rec-moco", | ||
None if not curr_seqinfo.is_motion_corrected else "rec-moco", | ||
from_series_info("dir"), | ||
series_info.get("bids"), | ||
run_label, | ||
from_series_info("part"), | ||
datatype_suffix, | ||
] | ||
|
||
# filter those which are None, and join with _ | ||
suffix = "_".join(filter(bool, filename_suffix_parts)) # type: ignore[arg-type] | ||
|
||
# # .series_description in case of | ||
# sdesc = s.study_description | ||
# sdesc = curr_seqinfo.study_description | ||
# # temporary aliases for those phantoms which we already collected | ||
# # so we rename them into this | ||
# #MAPPING | ||
|
@@ -638,13 +687,16 @@ def from_series_info(name: str) -> Optional[str]: | |
# https://github.com/nipy/heudiconv/issues/145 | ||
outtype: tuple[str, ...] | ||
if ( | ||
"_Scout" in s.series_description | ||
"_Scout" in curr_seqinfo.series_description | ||
or ( | ||
datatype == "anat" | ||
and datatype_suffix | ||
and datatype_suffix.startswith("scout") | ||
and filename_suffix_parts[-1] | ||
and filename_suffix_parts[-1].startswith("scout") | ||
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. what does this have to do with phase suffix? nothing in short commit messages hints on possible relation to this change... why is it? |
||
) | ||
or ( | ||
curr_seqinfo.series_description.lower() | ||
== curr_seqinfo.protocol_name.lower() + "_setter" | ||
) | ||
or (s.series_description.lower() == s.protocol_name.lower() + "_setter") | ||
): | ||
outtype = ("dicom",) | ||
else: | ||
|
@@ -654,7 +706,7 @@ def from_series_info(name: str) -> Optional[str]: | |
# we wanted ordered dict for consistent demarcation of dups | ||
if template not in info: | ||
info[template] = [] | ||
info[template].append(s.series_id) | ||
info[template].append(curr_seqinfo.series_id) | ||
|
||
if skipped: | ||
lgr.info("Skipped %d sequences: %s" % (len(skipped), skipped)) | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 duplicates that
_replace
hack 2 more times, causes me duplication-allergy...Since we are to do that anyways, do it once then -- just in a loop before this loop apply the replacements to all first.
Then avoid that
i_acq
- do following 'zip'ing, as chatgpt suggestedwhich would avoid all the if's and else's etc and make code easier to read IMHO.