Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 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
58 changes: 58 additions & 0 deletions cubids/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,63 @@ def _parse_add_nifti_info():
return parser


def _parse_add_file_collections():
"""Parse command-line arguments for the `cubids add-file-collections` command.

This function sets up an argument parser for the `cubids add-file-collections` command,
which adds file collection metadata to the sidecars of each dataset in a BIDS
directory.

Parameters
----------
bids_dir : str
Absolute path to the root of a BIDS dataset. It should contain sub-X directories
and dataset_description.json.
use_datalad : bool, optional
Ensure that there are no untracked changes before finding groups (default is False).
force_unlock : bool, optional
Unlock dataset before adding file collection metadata (default is False).

Returns
-------
argparse.ArgumentParser
The argument parser with the defined arguments.
"""
parser = argparse.ArgumentParser(
description=(
"cubids add-file-collections: Add file collection metadata to the sidecars "
"of each NIfTI file in the BIDS dataset"
),
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
allow_abbrev=False,
)
PathExists = partial(_path_exists, parser=parser)

parser.add_argument(
"bids_dir",
type=PathExists,
action="store",
help=(
"absolute path to the root of a BIDS dataset. "
"It should contain sub-X directories and "
"dataset_description.json."
),
)
parser.add_argument(
"--use-datalad",
action="store_true",
default=False,
help="ensure that there are no untracked changes before finding groups",
)
parser.add_argument(
"--force-unlock",
action="store_true",
default=False,
help="unlock dataset before adding file collection metadata",
)
return parser


def _enter_add_nifti_info(argv=None):
"""Entry point for the deprecated `cubids-add-nifti-info` command.

Expand Down Expand Up @@ -1345,6 +1402,7 @@ def _enter_print_metadata_fields(argv=None):
("apply", _parse_apply, workflows.apply),
("purge", _parse_purge, workflows.purge),
("add-nifti-info", _parse_add_nifti_info, workflows.add_nifti_info),
("add-file-collections", _parse_add_file_collections, workflows.add_file_collections),
("copy-exemplars", _parse_copy_exemplars, workflows.copy_exemplars),
("undo", _parse_undo, workflows.undo),
("datalad-save", _parse_datalad_save, workflows.datalad_save),
Expand Down
47 changes: 47 additions & 0 deletions cubids/cubids.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,53 @@ def add_nifti_info(self):

self.reset_bids_layout()

def add_file_collections(self):
"""Add file collections to the dataset.

This method processes all files in the BIDS directory specified by `self.path`.
It identifies file collections based on the presence of specific entities in the filenames.

Notes
-----
This method requires that the BIDSLayout has been indexed with metadata.
"""
# check if force_unlock is set
if self.force_unlock:
# CHANGE TO SUBPROCESS.CALL IF NOT BLOCKING
subprocess.run(["datalad", "unlock"], cwd=self.path)

checked_files = []

# loop through all niftis in the bids dir
for bids_file in self.layout.get(extension=[".nii", ".nii.gz"]):
path = bids_file.path

if path in checked_files:
continue

# Add file collection metadata to the sidecar
files, collection_metadata = utils.collect_file_collections(self.layout, path)
filepaths = [f.path for f in files]
checked_files.extend(filepaths)

for collection_path in filepaths:
# Add metadata to the sidecar
sidecar = utils.img_to_new_ext(str(collection_path), ".json")
if Path(sidecar).exists():
with open(sidecar, "r") as f:
data = json.load(f)
else:
data = {}

data.update(collection_metadata)
with open(sidecar, "w") as f:
json.dump(data, f, sort_keys=True, indent=4)

if self.use_datalad:
self.datalad_save(message="Added file collection metadata to sidecars")

self.reset_bids_layout()

def apply_tsv_changes(self, summary_tsv, files_tsv, new_prefix, raise_on_error=True):
"""Apply changes documented in the edited summary tsv and generate the new tsv files.

Expand Down
114 changes: 114 additions & 0 deletions cubids/data/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,25 @@ derived_params:
tolerance: 0.001
precision: 3
suggest_variant_rename: yes
# Array of echo times across file collection
EchoTimes:
tolerance: 0.001
precision: 3
suggest_variant_rename: yes
# Array of flip angles across file collection
FlipAngles:
suggest_variant_rename: yes
# Array of inversion times across file collection
InversionTimes:
tolerance: 0.001
precision: 5
suggest_variant_rename: yes
# Array of magnetization transfer states across file collection
MTStates:
suggest_variant_rename: yes
# Array of parts across file collection
Parts:
suggest_variant_rename: yes
dwi:
Dim1Size:
suggest_variant_rename: yes
Expand Down Expand Up @@ -64,6 +83,25 @@ derived_params:
suggest_variant_rename: yes
ImageOrientation:
suggest_variant_rename: yes
# Array of echo times across file collection
EchoTimes:
tolerance: 0.001
precision: 3
suggest_variant_rename: yes
# Array of flip angles across file collection
FlipAngles:
suggest_variant_rename: yes
# Array of inversion times across file collection
InversionTimes:
tolerance: 0.001
precision: 5
suggest_variant_rename: yes
# Array of magnetization transfer states across file collection
MTStates:
suggest_variant_rename: yes
# Array of parts across file collection
Parts:
suggest_variant_rename: yes
fmap:
Dim1Size:
suggest_variant_rename: yes
Expand All @@ -90,6 +128,25 @@ derived_params:
suggest_variant_rename: yes
ImageOrientation:
suggest_variant_rename: yes
# Array of echo times across file collection
EchoTimes:
tolerance: 0.001
precision: 3
suggest_variant_rename: yes
# Array of flip angles across file collection
FlipAngles:
suggest_variant_rename: yes
# Array of inversion times across file collection
InversionTimes:
tolerance: 0.001
precision: 5
suggest_variant_rename: yes
# Array of magnetization transfer states across file collection
MTStates:
suggest_variant_rename: yes
# Array of parts across file collection
Parts:
suggest_variant_rename: yes
func:
Dim1Size:
suggest_variant_rename: yes
Expand Down Expand Up @@ -117,6 +174,25 @@ derived_params:
suggest_variant_rename: yes
ImageOrientation:
suggest_variant_rename: yes
# Array of echo times across file collection
EchoTimes:
tolerance: 0.001
precision: 3
suggest_variant_rename: yes
# Array of flip angles across file collection
FlipAngles:
suggest_variant_rename: yes
# Array of inversion times across file collection
InversionTimes:
tolerance: 0.001
precision: 5
suggest_variant_rename: yes
# Array of magnetization transfer states across file collection
MTStates:
suggest_variant_rename: yes
# Array of parts across file collection
Parts:
suggest_variant_rename: yes
perf:
Dim1Size:
suggest_variant_rename: yes
Expand Down Expand Up @@ -144,6 +220,25 @@ derived_params:
suggest_variant_rename: yes
ImageOrientation:
suggest_variant_rename: yes
# Array of echo times across file collection
EchoTimes:
tolerance: 0.001
precision: 3
suggest_variant_rename: yes
# Array of flip angles across file collection
FlipAngles:
suggest_variant_rename: yes
# Array of inversion times across file collection
InversionTimes:
tolerance: 0.001
precision: 5
suggest_variant_rename: yes
# Array of magnetization transfer states across file collection
MTStates:
suggest_variant_rename: yes
# Array of parts across file collection
Parts:
suggest_variant_rename: yes
other:
Dim1Size:
suggest_variant_rename: yes
Expand Down Expand Up @@ -171,6 +266,25 @@ derived_params:
suggest_variant_rename: yes
ImageOrientation:
suggest_variant_rename: yes
# Array of echo times across file collection
EchoTimes:
tolerance: 0.001
precision: 3
suggest_variant_rename: yes
# Array of flip angles across file collection
FlipAngles:
suggest_variant_rename: yes
# Array of inversion times across file collection
InversionTimes:
tolerance: 0.001
precision: 5
suggest_variant_rename: yes
# Array of magnetization transfer states across file collection
MTStates:
suggest_variant_rename: yes
# Array of parts across file collection
Parts:
suggest_variant_rename: yes
# These fields reflect relationships between images.
# Not modality specific
relational_params:
Expand Down
Loading