Skip to content

Commit

Permalink
Add support for m0scan, aslcontext, asllabeling.
Browse files Browse the repository at this point in the history
  • Loading branch information
tsalo committed Jan 24, 2024
1 parent 057456e commit c8201d1
Showing 1 changed file with 94 additions and 62 deletions.
156 changes: 94 additions & 62 deletions cubids/cubids.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ def change_filename(self, filepath, entities):
sub_ses = sub + "_" + ses

if "run" in list(entities.keys()) and "run-0" in filepath:
# XXX: This adds an extra leading zero to run.
entities["run"] = "0" + str(entities["run"])

filename = "_".join([f"{key}-{entities[key]}" for key in entity_file_keys])
Expand All @@ -496,29 +497,32 @@ def change_filename(self, filepath, entities):
if len(filename) > 0:
filename = sub_ses + "_" + filename + "_" + suffix + old_ext
else:
# XXX: Why is filename here if it's an empty string?
filename = sub_ses + filename + "_" + suffix + old_ext

# CHECK TO SEE IF DATATYPE CHANGED
# XXX: Why/how would datatype change?
dtypes = ["anat", "func", "perf", "fmap", "dwi"]
old = ""
dtype_orig = ""
for dtype in dtypes:
if dtype in filepath:
old = dtype
dtype_orig = dtype

if "datatype" in entities.keys():
dtype = entities["datatype"]
if entities["datatype"] != old:
dtype_new = entities["datatype"]
if entities["datatype"] != dtype_orig:
print("WARNING: DATATYPE CHANGE DETECETD")
else:
dtype = old
dtype_new = dtype_orig

new_path = str(self.path) + "/" + sub + "/" + ses + "/" + dtype + "/" + filename
# Construct the new filename
new_path = str(self.path) + "/" + sub + "/" + ses + "/" + dtype_new + "/" + filename

# add the scan path + new path to the lists of old, new filenames
# Add the scan path + new path to the lists of old, new filenames
self.old_filenames.append(filepath)
self.new_filenames.append(new_path)

# NOW NEED TO RENAME ASSOCIATIONS
# NOW NEED TO RENAME ASSOCIATED FILES
# bids_file = self.layout.get_file(filepath)
bids_file = filepath
# associations = bids_file.get_associations()
Expand All @@ -535,34 +539,35 @@ def change_filename(self, filepath, entities):
self.new_filenames.append(new_ext_path)

# MAKE SURE THESE AREN'T COVERED BY get_associations!!!
# Update DWI-specific files
if "/dwi/" in filepath:
# add the bval and bvec if there
if (
Path(img_to_new_ext(filepath, ".bval")).exists()
and img_to_new_ext(filepath, ".bval") not in self.old_filenames
):
self.old_filenames.append(img_to_new_ext(filepath, ".bval"))
self.new_filenames.append(img_to_new_ext(new_path, ".bval"))

if (
Path(img_to_new_ext(filepath, ".bvec")).exists()
and img_to_new_ext(filepath, ".bvec") not in self.old_filenames
):
self.old_filenames.append(img_to_new_ext(filepath, ".bvec"))
self.new_filenames.append(img_to_new_ext(new_path, ".bvec"))

bval_old = img_to_new_ext(filepath, ".bval")
bval_new = img_to_new_ext(new_path, ".bval")
if Path(bval_old).exists() and bval_old not in self.old_filenames:
self.old_filenames.append(bval_old)
self.new_filenames.append(bval_new)

bvec_old = img_to_new_ext(filepath, ".bvec")
bvec_new = img_to_new_ext(new_path, ".bvec")
if Path(bvec_old).exists() and bvec_old not in self.old_filenames:
self.old_filenames.append(bvec_old)
self.new_filenames.append(bvec_new)

# Update func-specific files
# now rename _events and _physio files!
old_suffix = parse_file_entities(filepath)["suffix"]
scan_end = "_" + old_suffix + old_ext

if "_task-" in filepath:
old_events = filepath.replace(scan_end, "_events.tsv")
old_ejson = filepath.replace(scan_end, "_events.json")
if Path(old_events).exists():
self.old_filenames.append(old_events)
new_scan_end = "_" + suffix + old_ext
new_events = new_path.replace(new_scan_end, "_events.tsv")
self.new_filenames.append(new_events)

old_ejson = filepath.replace(scan_end, "_events.json")
if Path(old_ejson).exists():
self.old_filenames.append(old_ejson)
new_scan_end = "_" + suffix + old_ext
Expand All @@ -576,37 +581,63 @@ def change_filename(self, filepath, entities):
new_physio = new_path.replace(new_scan_end, "_physio.tsv.gz")
self.new_filenames.append(new_physio)

# Update ASL-specific files
if "/perf/" in filepath:
old_context = filepath.replace(scan_end, "_aslcontext.tsv")
if Path(old_context).exists():
self.old_filenames.append(old_context)
new_scan_end = "_" + suffix + old_ext
new_context = new_path.replace(new_scan_end, "_aslcontext.tsv")
self.new_filenames.append(new_context)

old_m0scan = filepath.replace(scan_end, "_m0scan.nii.gz")
if Path(old_m0scan).exists():
self.old_filenames.append(old_m0scan)
new_scan_end = "_" + suffix + old_ext
new_m0scan = new_path.replace(new_scan_end, "_m0scan.nii.gz")
self.new_filenames.append(new_m0scan)

old_mjson = filepath.replace(scan_end, "_m0scan.json")
if Path(old_mjson).exists():
self.old_filenames.append(old_mjson)
new_scan_end = "_" + suffix + old_ext
new_mjson = new_path.replace(new_scan_end, "_m0scan.json")
self.new_filenames.append(new_mjson)

old_labeling = filepath.replace(scan_end, "_asllabeling.jpg")
if Path(old_labeling).exists():
self.old_filenames.append(old_labeling)
new_scan_end = "_" + suffix + old_ext
new_labeling = new_path.replace(new_scan_end, "_asllabeling.jpg")
self.new_filenames.append(new_labeling)

# RENAME INTENDED FORS!
ses_path = self.path + "/" + sub + "/" + ses
for path in Path(ses_path).rglob("fmap/*.json"):
self.IF_rename_paths.append(str(path))
# json_file = self.layout.get_file(str(path))
files_with_if = []
files_with_if += Path(ses_path).rglob("fmap/*.json")
files_with_if += Path(ses_path).rglob("perf/*_m0scan.json")
for path_with_if in files_with_if:
filename_with_if = str(path_with_if)
self.IF_rename_paths.append(filename_with_if)
# json_file = self.layout.get_file(filename_with_if)
# data = json_file.get_dict()
data = get_sidecar_metadata(str(path))
data = get_sidecar_metadata(filename_with_if)
if data == "Erroneous sidecar":
print("Error parsing sidecar: ", str(path))
print("Error parsing sidecar: ", filename_with_if)
continue

if "IntendedFor" in data.keys():
# check if IntendedFor field is a str or list
if isinstance(data["IntendedFor"], str):
if data["IntendedFor"] == _get_intended_for_reference(filepath):
# replace old filename with new one (overwrite string)
data["IntendedFor"] = _get_intended_for_reference(new_path)

# update the json with the new data dictionary
_update_json(str(path), data)

if isinstance(data["IntendedFor"], list):
for item in data["IntendedFor"]:
if item in _get_intended_for_reference(filepath):
# remove old filename
data["IntendedFor"].remove(item)
# add new filename
data["IntendedFor"].append(_get_intended_for_reference(new_path))

# update the json with the new data dictionary
_update_json(str(path), data)
# Coerce IntendedFor to a list.
data["IntendedFor"] = listify(data["IntendedFor"])
for item in data["IntendedFor"]:
if item in _get_intended_for_reference(filepath):
# remove old filename
data["IntendedFor"].remove(item)
# add new filename
data["IntendedFor"].append(_get_intended_for_reference(new_path))

# update the json with the new data dictionary
_update_json(filename_with_if, data)

# save IntendedFor purges so that you can datalad run the
# remove association file commands on a clean dataset
Expand All @@ -625,11 +656,11 @@ def copy_exemplars(self, exemplars_dir, exemplars_tsv, min_group_size):
Parameters
----------
exemplars_dir : str
exemplars_dir : :obj:`str`
path to the directory that will contain one subject
from each Acqusition Group (*_AcqGrouping.tsv)
example path: /Users/Covitz/tsvs/CCNP_Acq_Groups/
exemplars_tsv : str
exemplars_tsv : :obj:`str`
path to the .tsv file that lists one subject
from each Acqusition Group (*_AcqGrouping.tsv
from the cubids-group output)
Expand Down Expand Up @@ -710,7 +741,13 @@ def purge(self, scans_txt):
self._purge_associations(scans)

def _purge_associations(self, scans):
"""Purge field map JSONs' IntendedFor references."""
"""Purge field map JSONs' IntendedFor references.
Parameters
----------
scans : :obj:`list` of :obj:`str`
List of file paths to remove from field map JSONs.
"""
# truncate all paths to intendedfor reference format
# sub, ses, modality only (no self.path)
if_scans = []
Expand All @@ -727,20 +764,14 @@ def _purge_associations(self, scans):

# remove scan references in the IntendedFor
if "IntendedFor" in data.keys():
# check if IntendedFor field value is a list or a string
if isinstance(data["IntendedFor"], str):
if data["IntendedFor"] in if_scans:
data["IntendedFor"] = []
# update the json with the new data dictionary
_update_json(str(path), data)
data["IntendedFor"] = listify(data["IntendedFor"])

if isinstance(data["IntendedFor"], list):
for item in data["IntendedFor"]:
if item in if_scans:
data["IntendedFor"].remove(item)
for item in data["IntendedFor"]:
if item in if_scans:
data["IntendedFor"].remove(item)

# update the json with the new data dictionary
_update_json(str(path), data)
# update the json with the new data dictionary
_update_json(str(path), data)

# save IntendedFor purges so that you can datalad run the
# remove association file commands on a clean dataset
Expand Down Expand Up @@ -838,6 +869,7 @@ def get_nifti_associations(self, nifti):
for path in Path(self.path).rglob("sub-*/**/*.*"):
if no_ext_file in str(path) and ".nii.gz" not in str(path):
associations.append(str(path))

return associations

def _cache_fieldmaps(self):
Expand Down

0 comments on commit c8201d1

Please sign in to comment.