Source code for niworkflows.utils.testing

from copy import deepcopy
import json
from pathlib import Path
import yaml


[docs] def generate_bids_skeleton(target_path, bids_config): """ Converts a BIDS directory in dictionary form to a file structure. The BIDS configuration can either be a YAML or JSON file, or :obj:dict: object. Parameters ---------- target_path : str Path to generate BIDS directory at (must not exist) bids_config : dict or str Configuration on how to create the BIDS directory. """ if isinstance(bids_config, dict): # ensure dictionary remains unaltered bids_dict = deepcopy(bids_config) elif isinstance(bids_config, str): bids_config = Path(bids_config).read_text() try: bids_dict = json.loads(bids_config) except json.JSONDecodeError: bids_dict = yaml.load(bids_config, Loader=yaml.Loader) _bids_dict = deepcopy(bids_dict) root = Path(target_path).absolute() root.mkdir(parents=True) desc = bids_dict.pop("dataset_description", None) if desc is None: # default description desc = {"Name": "Default", "BIDSVersion": "1.6.0"} to_json(root / "dataset_description.json", desc) cached_subject_data = None for subject, sessions in bids_dict.items(): bids_subject = subject if subject.startswith("sub-") else f"sub-{subject}" subj_path = root / bids_subject subj_path.mkdir(exist_ok=True) if sessions == "*": # special case to copy previous subject data sessions = cached_subject_data.copy() if isinstance(sessions, dict): # single session sessions.update({"session": None}) sessions = [sessions] cached_subject_data = deepcopy(sessions) for session in sessions: ses_name = session.pop("session", None) if ses_name is not None: bids_session = ses_name if ses_name.startswith("ses-") else f"ses-{ses_name}" bids_prefix = f"{bids_subject}_{bids_session}" curr_path = subj_path / bids_session curr_path.mkdir(exist_ok=True) else: bids_prefix = bids_subject curr_path = subj_path # create modalities for modality, files in session.items(): modality_path = curr_path / modality modality_path.mkdir(exist_ok=True) if isinstance(files, dict): # single file / metadata combo files = [files] for bids_file in files: metadata = bids_file.pop("metadata", None) extension = bids_file.pop("extension", ".nii.gz") suffix = bids_file.pop("suffix") entities = combine_entities(**bids_file) data_file = modality_path / f"{bids_prefix}{entities}_{suffix}{extension}" data_file.touch() if metadata is not None: out_metadata = data_file.parent / data_file.name.replace( extension, ".json" ) to_json(out_metadata, metadata) return _bids_dict
[docs] def to_json(filename, data): filename = Path(filename) filename.write_text(json.dumps(data)) return filename
[docs] def combine_entities(**entities): return f"_{'_'.join([f'{lab}-{val}' for lab, val in entities.items()])}" if entities else ""