diff --git a/.gitignore b/.gitignore index 95f82a103..336385a09 100644 --- a/.gitignore +++ b/.gitignore @@ -136,4 +136,5 @@ data/* .DS_Store notebooks/testdata .vscode/settings.json -notebooks/test1 \ No newline at end of file +notebooks/test1 +docs/generated \ No newline at end of file diff --git a/cubids/__about__.py b/cubids/__about__.py index d4341aebe..bb727e533 100644 --- a/cubids/__about__.py +++ b/cubids/__about__.py @@ -1,6 +1,25 @@ # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- # vi: set ft=python sts=4 ts=4 sw=4 et: -"""Base module variables.""" +"""Base module variables for CuBIDS. + +This module defines the base variables for the CuBIDS package, including version, +package name, copyright, credits, and URLs. + +Attributes +---------- +__version__ : str + The version of the CuBIDS package. +__packagename__ : str + The name of the CuBIDS package. +__copyright__ : str + The copyright information for the CuBIDS package. +__credits__ : str + The credits for the CuBIDS package. +__url__ : str + The URL for the CuBIDS package repository. +DOWNLOAD_URL : str + The URL to download the CuBIDS package. +""" try: from cubids._version import __version__ except ImportError: diff --git a/cubids/__init__.py b/cubids/__init__.py index ff9b1d3d5..92fffc3fa 100644 --- a/cubids/__init__.py +++ b/cubids/__init__.py @@ -1,4 +1,37 @@ -"""Top-level package for CuBIDS.""" +"""Top-level package for CuBIDS. + +This module initializes the CuBIDS package and imports its main submodules and attributes. + +Submodules +---------- +cli : module + Command-line interface for CuBIDS. +config : module + Configuration utilities for CuBIDS. +constants : module + Constants used throughout the CuBIDS package. +cubids : module + Core functionalities of the CuBIDS package. +metadata_merge : module + Utilities for merging metadata in CuBIDS. +utils : module + Utility functions for CuBIDS. +validator : module + Validation utilities for CuBIDS. +workflows : module + Workflows for CuBIDS operations. + +Attributes +---------- +__version__ : str + The version of the CuBIDS package. +__packagename__ : str + The name of the CuBIDS package. +__copyright__ : str + The copyright information for the CuBIDS package. +__credits__ : str + The credits for the CuBIDS package. +""" from cubids import ( cli, diff --git a/cubids/cli.py b/cubids/cli.py index c17b610ec..846b401f6 100644 --- a/cubids/cli.py +++ b/cubids/cli.py @@ -1,4 +1,15 @@ -"""Console script for cubids.""" +"""Console script for cubids. + +This module provides command-line interface (CLI) tools for CuBIDS, a BIDS dataset +validation and manipulation toolkit. The CLI tools include functionalities for +validating BIDS datasets, merging sidecar JSON files, grouping acquisition parameters, +applying changes, purging associations, adding NIfTI information, copying exemplar +subjects, undoing changes, saving with DataLad, and managing metadata fields. + +Each function that serves as an entry point for a CLI command in the format of `cubids-function` +is marked as deprecated and will be removed in the future. Users are advised to use the +corresponding `cubids function` commands instead. +""" import argparse import logging @@ -21,15 +32,20 @@ def _path_exists(path, parser): Parameters ---------- - path : str - Path to check for existence. + path : str or None + The path to check for existence. If None or the path does not exist, an error is raised. parser : argparse.ArgumentParser - Argument parser object. + The argument parser instance used to raise an error if the path does not exist. Returns ------- pathlib.Path - Absolute path to the given location. + The absolute path if it exists. + + Raises + ------ + argparse.ArgumentError + If the path does not exist or is None. """ if path is not None: path = Path(path) @@ -44,15 +60,20 @@ def _is_file(path, parser): Parameters ---------- - path : str - Path to check for existence. + path : str or Path + The path to check. parser : argparse.ArgumentParser - Argument parser object. + The argument parser instance to use for error reporting. Returns ------- - pathlib.Path - Absolute path to the given location. + Path + The validated path as a Path object. + + Raises + ------ + argparse.ArgumentError + If the path does not exist or is not a file. """ path = _path_exists(path, parser) if not path.is_file(): @@ -63,16 +84,41 @@ def _is_file(path, parser): def _parse_validate(): - """Create the parser for the "cubids validate" command. + """Create and configure the argument parser for the `cubids validate` command. + + This function sets up an argument parser with various options for running + the BIDS validator, including specifying the BIDS dataset directory, output + file prefix, and additional validation options. - Returns: + Parameters + ---------- + None + + Returns ------- - parser : argparse.ArgumentParser - The parser object for the "cubids validate" command. + argparse.ArgumentParser + Configured argument parser for the `cubids validate` command. + + Notes + ----- + The following arguments are added to the parser: + + - bids_dir: The root of a BIDS dataset. It should contain sub-X directories + and dataset_description.json. + - output_prefix: File prefix to which tabulated validator output is written. + If a filename prefix is provided, the output will be placed in + bids_dir/code/CuBIDS. If a full path is provided, the output files will + go to the specified location. + - --sequential: Run the BIDS validator sequentially on each subject. + - --container: Docker image tag or Singularity image file. + - --ignore-nifti-headers: Disregard NIfTI header content during validation. + - --sequential-subjects: Filter the sequential run to only include the + listed subjects. """ parser = argparse.ArgumentParser( - description="cubids-validate: Wrapper around the official BIDS Validator", + description="cubids validate: Wrapper around the official BIDS Validator", formatter_class=argparse.ArgumentDefaultsHelpFormatter, + allow_abbrev=False, ) PathExists = partial(_path_exists, parser=parser) @@ -141,6 +187,26 @@ def _parse_validate(): def _enter_validate(argv=None): + """Entry point for the `cubids-validate` command. + + This function is deprecated and will be removed in the future. + Please use 'cubids validate' instead. + + Parameters + ---------- + argv : list, optional + List of command-line arguments. If None, defaults to sys.argv. + + Warns + ----- + DeprecationWarning + Indicates that this function is deprecated. + + Notes + ----- + This function parses the command-line arguments and calls the + `workflows.validate` function with the parsed arguments. + """ warnings.warn( "cubids-validate is deprecated and will be removed in the future. " "Please use cubids validate.", @@ -153,9 +219,34 @@ def _enter_validate(argv=None): def _parse_bids_version(): + """Parse command-line arguments for the `cubids bids-version` command. + + This function sets up an argument parser for the `cubids bids-version` command, + which retrieves the BIDS Validator and Schema version for a given BIDS dataset. + + Parameters + ---------- + None + + Returns + ------- + argparse.ArgumentParser + The argument parser configured for the `cubids bids-version` command. + + Notes + ----- + The parser includes the following arguments: + + - `bids_dir`: The root directory of a BIDS dataset, which should contain + sub-X directories and a dataset_description.json file. + - `--write`: A flag to save the validator and schema version to + 'dataset_description.json'. If not provided, the versions are printed + to the terminal. + """ parser = argparse.ArgumentParser( description="cubids bids-version: Get BIDS Validator and Schema version", formatter_class=argparse.ArgumentDefaultsHelpFormatter, + allow_abbrev=False, ) PathExists = partial(_path_exists, parser=parser) @@ -182,15 +273,64 @@ def _parse_bids_version(): def _enter_bids_version(argv=None): + """Entry point for the deprecated `cubids-bids-version`. + + This function serves as the entry point for the BIDS version command-line + functionality. It parses command-line arguments, issues a deprecation + warning, and invokes the corresponding workflow. + + Parameters + ---------- + argv : list, optional + List of command-line arguments. If None, defaults to `sys.argv`. + + Returns + ------- + None + + Warns + ----- + DeprecationWarning + Indicates that the `cubids-bids-version` command is deprecated and + will be removed in the future. + """ + warnings.warn( + "cubids-bids-version is deprecated and will be removed in the future. " + "Please use cubids bids-version.", + DeprecationWarning, + stacklevel=2, + ) options = _parse_bids_version().parse_args(argv) args = vars(options).copy() workflows.bids_version(**args) def _parse_bids_sidecar_merge(): + """Create an argument parser for the `cubids bids-sidecar-merge` command. + + This function sets up an argument parser for the `cubids bids-sidecar-merge` command-line tool, + which merges critical keys from one BIDS sidecar JSON file into another. + + Parameters + ---------- + from_json : str + Source JSON file path. This file contains the data to be copied. + to_json : str + Destination JSON file path. This file will have data from `from_json` copied into it. + + Returns + ------- + argparse.ArgumentParser + The argument parser with the necessary arguments configured. + + Notes + ----- + The `IsFile` partial function is used to validate that the provided file paths exist. + """ parser = argparse.ArgumentParser( description=("bids-sidecar-merge: merge critical keys from one sidecar to another"), formatter_class=argparse.ArgumentDefaultsHelpFormatter, + allow_abbrev=False, ) IsFile = partial(_is_file, parser=parser) @@ -210,6 +350,23 @@ def _parse_bids_sidecar_merge(): def _enter_bids_sidecar_merge(argv=None): + """Entry point for the deprecated `cubids-bids-sidecar-merge command`. + + This function serves as the entry point for the `cubids-bids-sidecar-merge`. + It parses command-line arguments, issues a deprecation + warning, and invokes the corresponding workflow. + + Parameters + ---------- + argv : list, optional + List of command-line arguments. If None, defaults to `sys.argv`. + + Warns + ----- + DeprecationWarning + Indicates that the `bids-sidecar-merge` command is deprecated and + will be removed in the future. + """ warnings.warn( "bids-sidecar-merge is deprecated and will be removed in the future. " "Please use cubids bids-sidecar-merge.", @@ -222,9 +379,43 @@ def _enter_bids_sidecar_merge(argv=None): def _parse_group(): + """Parse command-line arguments for the `cubids group` command. + + This function sets up an argument parser for the `cubids group` command, + which is used to find key and parameter groups in a BIDS dataset. + + Parameters + ---------- + None + + Returns + ------- + argparse.ArgumentParser + The argument parser with the defined arguments. + + Arguments + --------- + bids_dir : str + The root of a BIDS dataset. It should contain sub-X directories and + dataset_description.json. + output_prefix : str + File prefix to which a _summary.tsv, _files.tsv, _AcqGrouping.tsv, and + _AcqGroupInfo.txt are written. If a filename prefix is provided (e.g., V1), + the outputs will be placed in bids_dir/code/CuBIDS. If a path is specified + (e.g., /Users/scovitz/BIDS/V1), the output files will go to the specified location. + --container : str, optional + Docker image tag or Singularity image file. + --acq-group-level : {'subject', 'session'}, optional + Level at which acquisition groups are created. Options are 'subject' or 'session'. + Default is 'subject'. + --config : str, optional + Path to a config file for grouping. If not provided, the default config file from + CuBIDS will be used. + """ parser = argparse.ArgumentParser( - description="cubids-group: find key and parameter groups in BIDS", + description="cubids group: find key and parameter groups in BIDS", formatter_class=argparse.ArgumentDefaultsHelpFormatter, + allow_abbrev=False, ) PathExists = partial(_path_exists, parser=parser) @@ -277,6 +468,28 @@ def _parse_group(): def _enter_group(argv=None): + """Entry point for the deprecated `cubids-group` command. + + This function issues a deprecation warning indicating that `cubids-group` + is deprecated and will be removed in the future. It then parses the + command-line arguments and invokes the `group` workflow with the parsed + arguments. + + Parameters + ---------- + argv : list, optional + List of command-line arguments. If None, defaults to sys.argv. + + Warns + ----- + DeprecationWarning + Indicates that 'cubids-group' is deprecated and will be removed in + the future. + + Returns + ------- + None + """ warnings.warn( "cubids-group is deprecated and will be removed in the future. Please use cubids group.", DeprecationWarning, @@ -288,9 +501,44 @@ def _enter_group(argv=None): def _parse_apply(): + """Parse command-line arguments for the `cubids apply` command. + + This function sets up an argument parser for the `cubids apply` command, + which applies changes specified in a TSV file to a BIDS directory. + + Parameters + ---------- + bids_dir : str + The root of a BIDS dataset. It should contain sub-X directories and + dataset_description.json. + edited_summary_tsv : str + Path to the _summary.tsv that has been edited in the MergeInto and + RenameEntitySet columns. + files_tsv : str + Path to the _files.tsv that has been edited in the MergeInto and + RenameEntitySet columns. + new_tsv_prefix : str + File prefix for writing the post-apply grouping outputs. + --use-datalad : bool, optional + Ensure that there are no untracked changes before finding groups + (default is False). + --container : str, optional + Docker image tag or Singularity image file. + --acq-group-level : {'subject', 'session'}, optional + Level at which acquisition groups are created (default is 'subject'). + --config : str, optional + Path to a config file for grouping. If not provided, the default config + file from CuBIDS will be used. + + Returns + ------- + argparse.ArgumentParser + The argument parser with the defined arguments. + """ parser = argparse.ArgumentParser( - description=("cubids-apply: apply the changes specified in a tsv to a BIDS directory"), + description=("cubids apply: apply the changes specified in a tsv to a BIDS directory"), formatter_class=argparse.ArgumentDefaultsHelpFormatter, + allow_abbrev=False, ) PathExists = partial(_path_exists, parser=parser) IsFile = partial(_is_file, parser=parser) @@ -306,7 +554,7 @@ def _parse_apply(): ) parser.add_argument( "edited_summary_tsv", - type=IsFile, + type=Path, action="store", help=( "path to the _summary.tsv that has been edited " @@ -318,7 +566,7 @@ def _parse_apply(): ) parser.add_argument( "files_tsv", - type=IsFile, + type=Path, action="store", help=( "path to the _files.tsv that has been edited " @@ -374,6 +622,22 @@ def _parse_apply(): def _enter_apply(argv=None): + """Entry point for the deprecated `cubids-apply` command. + + This function serves as a wrapper for the `cubids-apply` command and issues a + deprecation warning. It parses the command-line arguments and invokes the + `apply` workflow with the parsed arguments. + + Parameters + ---------- + argv : list, optional + List of command-line arguments. If None, the arguments will be taken from `sys.argv`. + + Warns + ----- + DeprecationWarning + Indicates that `cubids-apply` is deprecated and will be removed in the future. + """ warnings.warn( "cubids-apply is deprecated and will be removed in the future. Please use cubids apply.", DeprecationWarning, @@ -385,9 +649,32 @@ def _enter_apply(argv=None): def _parse_datalad_save(): + """Create an argument parser for the `cubids datalad-save` command. + + This function sets up an argument parser for performing a DataLad save on a BIDS directory. + It includes arguments for specifying the BIDS directory, a commit message, and an optional + container image. + + Parameters + ---------- + None + + Returns + ------- + argparse.ArgumentParser + The configured argument parser. + + Notes + ----- + The `bids_dir` argument is required and should point to the root of a BIDS dataset, which + must contain sub-X directories and a dataset_description.json file. The `-m` argument is + used to provide a commit message, and the `--container` argument allows specifying a Docker + image tag or Singularity image file. + """ parser = argparse.ArgumentParser( - description=("cubids-datalad-save: perform a DataLad save on a BIDS directory"), + description=("cubids datalad-save: perform a DataLad save on a BIDS directory"), formatter_class=argparse.ArgumentDefaultsHelpFormatter, + allow_abbrev=False, ) PathExists = partial(_path_exists, parser=parser) @@ -415,6 +702,28 @@ def _parse_datalad_save(): def _enter_datalad_save(argv=None): + """Entry point for the deprecated `cubids-datalad-save` command. + + This function serves as a warning that the `cubids-datalad-save` command is deprecated + and will be removed in the future. It parses the command-line arguments and calls + the `datalad_save` workflow with the parsed arguments. + + Parameters + ---------- + argv : list, optional + List of command-line arguments. If not provided, defaults to None. + + Warns + ----- + DeprecationWarning + Indicates that the `cubids-datalad-save` command is deprecated and + will be removed in the future. + + See Also + -------- + _parse_datalad_save : Function to parse command-line arguments for the datalad save operation. + workflows.datalad_save : Function to perform the datalad save operation. + """ warnings.warn( "cubids-datalad-save is deprecated and will be removed in the future. " "Please use cubids datalad-save.", @@ -427,9 +736,33 @@ def _enter_datalad_save(argv=None): def _parse_undo(): + """Create an argument parser for the `cubids undo` command. + + This function sets up an argument parser for the `cubids undo` command, + which is used to revert the most recent commit in a BIDS dataset. It + defines the required and optional arguments for the command. + + Parameters + ---------- + None + + Returns + ------- + argparse.ArgumentParser + The argument parser for the `cubids undo` command. + + Notes + ----- + The parser includes the following arguments: + + - bids_dir: The root of a BIDS dataset, which should contain sub-X directories + and dataset_description.json. + - container: Docker image tag or Singularity image file. + """ parser = argparse.ArgumentParser( - description="cubids-undo: revert most recent commit", + description="cubids undo: revert most recent commit", formatter_class=argparse.ArgumentDefaultsHelpFormatter, + allow_abbrev=False, ) PathExists = partial(_path_exists, parser=parser) @@ -452,6 +785,28 @@ def _parse_undo(): def _enter_undo(argv=None): + """Entry point for the deprecated `cubids-undo` command. + + This function is called when the `cubids-undo` command is executed. + It displays a deprecation warning and then parses the command-line + arguments to execute the undo workflow. + + Parameters + ---------- + argv : list, optional + List of command-line arguments. If None, the arguments from + sys.argv are used. + + Warns + ----- + DeprecationWarning + Indicates that `cubids-undo` is deprecated and will be removed + in the future. Users should use `cubids undo` instead. + + Returns + ------- + None + """ warnings.warn( "cubids-undo is deprecated and will be removed in the future. Please use cubids undo.", DeprecationWarning, @@ -463,15 +818,51 @@ def _enter_undo(argv=None): def _parse_copy_exemplars(): + """Parse command-line arguments for the `cubids copy-exemplars` script. + + This function sets up an argument parser for the `cubids copy-exemplars` script, + which creates and saves a directory with one subject from each Acquisition Group + in the BIDS dataset. + + Parameters + ---------- + bids_dir : str + Path to the root of a BIDS dataset. It should contain sub-X directories and + dataset_description.json. + exemplars_dir : str + Name of the directory to create where to store the exemplar dataset. It will + include one subject from each Acquisition Group. It should contain sub-X + directories and dataset_description.json. + exemplars_tsv : str + Path to the .tsv file that lists one subject from each Acquisition Group + (*_AcqGrouping.tsv from the cubids-group output). If the file is located in + the code/CuBIDS directory, then users can just pass the .tsv filename instead + of the full path. + use_datalad : bool, optional + Check exemplar dataset into DataLad (default is False). + min_group_size : int, optional + Minimum number of subjects an Acquisition Group must have in order to be + included in the exemplar dataset (default is 1). + container : str, optional + Docker image tag or Singularity image file. + force_unlock : bool, optional + Unlock dataset before adding nifti info (default is False). + + Returns + ------- + argparse.ArgumentParser + The argument parser with the defined arguments. + """ parser = argparse.ArgumentParser( description=( - "cubids-copy-exemplars: create and save a directory with " + "cubids copy-exemplars: create and save a directory with " "one subject from each Acquisition Group in the BIDS dataset" ), formatter_class=argparse.ArgumentDefaultsHelpFormatter, + allow_abbrev=False, ) PathExists = partial(_path_exists, parser=parser) - IsFile = partial(_is_file, parser=parser) + # IsFile = partial(_is_file, parser=parser) parser.add_argument( "bids_dir", @@ -485,7 +876,7 @@ def _parse_copy_exemplars(): ) parser.add_argument( "exemplars_dir", - type=PathExists, + type=Path, action="store", help=( "name of the directory to create where to store exemplar dataset. " @@ -496,7 +887,7 @@ def _parse_copy_exemplars(): ) parser.add_argument( "exemplars_tsv", - type=IsFile, + type=Path, action="store", help=( "path to the .tsv that lists one " @@ -547,6 +938,22 @@ def _parse_copy_exemplars(): def _enter_copy_exemplars(argv=None): + """Entry point for the deprecated `cubids-copy-exemplars` command. + + This function is deprecated and will be removed in the future. + It parses command-line arguments and invokes the `copy_exemplars` + workflow with the parsed arguments. + + Parameters + ---------- + argv : list, optional + List of command-line arguments. If None, defaults to `sys.argv`. + + Warns + ----- + DeprecationWarning + Indicates that this function is deprecated and will be removed in the future. + """ warnings.warn( "cubids-copy-exemplars is deprecated and will be removed in the future. " "Please use cubids copy-exemplars.", @@ -559,12 +966,36 @@ def _enter_copy_exemplars(argv=None): def _parse_add_nifti_info(): + """Parse command-line arguments for the `cubids add-nifti-info` command. + + This function sets up an argument parser for the `cubids add-nifti-info` command, + which adds information from NIfTI files 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 NIfTI info (default is False). + container : str, optional + Docker image tag or Singularity image file. + + Returns + ------- + argparse.ArgumentParser + The argument parser with the defined arguments. + """ parser = argparse.ArgumentParser( description=( - "cubids-add-nifti-info: Add information from nifti" + "cubids add-nifti-info: Add information from nifti" "files to the sidecars of each dataset" ), formatter_class=argparse.ArgumentDefaultsHelpFormatter, + allow_abbrev=False, ) PathExists = partial(_path_exists, parser=parser) @@ -599,6 +1030,26 @@ def _parse_add_nifti_info(): def _enter_add_nifti_info(argv=None): + """Entry point for the deprecated `cubids-add-nifti-info` command. + + This function is deprecated and will be removed in the future. + Please use `cubids add-nifti-info` instead. + + Parameters + ---------- + argv : list, optional + List of command line arguments. If None, defaults to `sys.argv`. + + Warns + ----- + DeprecationWarning + Indicates that this function is deprecated. + + Notes + ----- + This function parses command line arguments and invokes the + `add_nifti_info` workflow with the parsed arguments. + """ warnings.warn( "cubids-add-nifti-info is deprecated and will be removed in the future. " "Please use cubids add-nifti-info.", @@ -611,9 +1062,35 @@ def _enter_add_nifti_info(argv=None): def _parse_purge(): + """Parse command-line arguments for the `cubids purge` command. + + This function sets up an argument parser for the `cubids purge` command, + which is used to purge associations from a BIDS dataset. It defines the + required arguments and options for the command. + + Parameters + ---------- + None + + Returns + ------- + argparse.ArgumentParser + The argument parser with the defined arguments and options. + + Notes + ----- + The following arguments are defined: + + - `bids_dir`: The root of a BIDS dataset. It should contain sub-X directories + and dataset_description.json. + - `scans`: Path to the txt file of scans whose associations should be purged. + - `--use-datalad`: Ensure that there are no untracked changes before finding groups. + - `--container`: Docker image tag or Singularity image file. + """ parser = argparse.ArgumentParser( - description="cubids-purge: purge associations from the dataset", + description="cubids purge: purge associations from the dataset", formatter_class=argparse.ArgumentDefaultsHelpFormatter, + allow_abbrev=False, ) PathExists = partial(_path_exists, parser=parser) IsFile = partial(_is_file, parser=parser) @@ -654,6 +1131,26 @@ def _parse_purge(): def _enter_purge(argv=None): + """Entry point for the deprecated `cubids-purge` command. + + This function is deprecated and will be removed in the future. + Please use `cubids purge` instead. + + Parameters + ---------- + argv : list, optional + List of command-line arguments. If None, defaults to sys.argv. + + Warns + ----- + DeprecationWarning + Indicates that this function is deprecated. + + Notes + ----- + This function parses the command-line arguments and calls the + `workflows.purge` function with the parsed arguments. + """ warnings.warn( "cubids-purge is deprecated and will be removed in the future. Please use cubids purge.", DeprecationWarning, @@ -665,9 +1162,37 @@ def _enter_purge(argv=None): def _parse_remove_metadata_fields(): + """Create an argument parser for the `cubids remove-metadata-fields` command. + + This function sets up an argument parser for the command-line interface (CLI) + tool `cubids remove-metadata-fields`, which is used to delete specified fields + from the metadata of a BIDS dataset. + + Parameters + ---------- + None + + Returns + ------- + argparse.ArgumentParser + The argument parser configured for the `cubids remove-metadata-fields` CLI tool. + + Notes + --------- + The parser includes the following arguments: + + bids_dir : str + The root directory of a BIDS dataset. It should contain sub-X directories and + a dataset_description.json file. + --fields : list of str, optional + A space-separated list of metadata fields to remove. Defaults to an empty list. + --container : str, optional + Docker image tag or Singularity image file. + """ parser = argparse.ArgumentParser( - description="cubids-remove-metadata-fields: delete fields from metadata", + description="cubids remove-metadata-fields: delete fields from metadata", formatter_class=argparse.ArgumentDefaultsHelpFormatter, + allow_abbrev=False, ) PathExists = partial(_path_exists, parser=parser) @@ -697,7 +1222,30 @@ def _parse_remove_metadata_fields(): def _enter_remove_metadata_fields(argv=None): - """Set entrypoint for "cubids-remove-metadata-fields" CLI.""" + """Entry point for the deprecated `cubids-remove-metadata-fields` command. + + This function serves as the entry point for the deprecated + `cubids-remove-metadata-fields` command-line interface (CLI). It issues a + deprecation warning and then parses the provided arguments to execute the + `remove_metadata_fields` workflow. + + Parameters + ---------- + argv : list, optional + List of command-line arguments. If None, the default arguments will be used. + + Warns + ----- + DeprecationWarning + Indicates that the `cubids-remove-metadata-fields` CLI is deprecated and + will be removed in the future. Users are advised to use + `cubids remove-metadata-fields` instead. + + See Also + -------- + _parse_remove_metadata_fields : Function to parse the command-line arguments. + workflows.remove_metadata_fields : Workflow to remove metadata fields. + """ warnings.warn( "cubids-remove-metadata-fields is deprecated and will be removed in the future. " "Please use cubids remove-metadata-fields.", @@ -710,10 +1258,34 @@ def _enter_remove_metadata_fields(argv=None): def _parse_print_metadata_fields(): - """Create the parser for the "cubids print-metadata-fields" command.""" + """Create the parser for the `cubids print-metadata-fields` command. + + This function sets up an argument parser for the command that prints all + unique metadata fields in a BIDS dataset. It defines the required arguments + and their types, as well as optional arguments. + + Parameters + ---------- + None + + Returns + ------- + argparse.ArgumentParser + The argument parser for the `cubids print-metadata-fields` command. + + Notes + ----- + The parser includes the following arguments: + + - bids_dir: The root of a BIDS dataset, which should contain sub-X directories + and dataset_description.json. + - container: An optional argument specifying a Docker image tag or Singularity + image file. + """ parser = argparse.ArgumentParser( - description="cubids-print-metadata-fields: print all unique metadata fields", + description="cubids print-metadata-fields: print all unique metadata fields", formatter_class=argparse.ArgumentDefaultsHelpFormatter, + allow_abbrev=False, ) PathExists = partial(_path_exists, parser=parser) @@ -736,6 +1308,28 @@ def _parse_print_metadata_fields(): def _enter_print_metadata_fields(argv=None): + """Entry point for the deprecated `cubids-print-metadata-fields` command. + + This function parses the command-line arguments for `cubids-print-metadata-fields`, + issues a deprecation warning, and then calls the `print_metadata_fields` + function from the `workflows` module with the parsed arguments. + + Parameters + ---------- + argv : list, optional + List of command-line arguments. If None, the arguments will be taken from + `sys.argv`. + + Warns + ----- + DeprecationWarning + Indicates that the `cubids-print-metadata-fields` command is deprecated + and will be removed in the future. + + See Also + -------- + workflows.print_metadata_fields : Function that prints metadata fields. + """ options = _parse_print_metadata_fields().parse_args(argv) args = vars(options).copy() warnings.warn( @@ -764,10 +1358,20 @@ def _enter_print_metadata_fields(argv=None): def _get_parser(): - """Create the general "cubids" parser object.""" + """Create the general `cubids` parser object. + + This function sets up the argument parser for the `cubids` command-line interface. + It includes a version argument and dynamically adds subparsers for each command + defined in the COMMANDS list. + + Returns + ------- + argparse.ArgumentParser + The argument parser for the "cubids" CLI. + """ from cubids import __version__ - parser = argparse.ArgumentParser(prog="cubids") + parser = argparse.ArgumentParser(prog="cubids", allow_abbrev=False) parser.add_argument("-v", "--version", action="version", version=__version__) subparsers = parser.add_subparsers(help="CuBIDS commands") @@ -779,13 +1383,24 @@ def _get_parser(): parents=[subparser], help=subparser.description, add_help=False, + allow_abbrev=False, ) return parser def _main(argv=None): - """Set entrypoint for "cubids" CLI.""" + """Entry point for `cubids` CLI. + + Parameters + ---------- + argv : list, optional + List of command-line arguments. If None, defaults to `sys.argv`. + + Returns + ------- + None + """ options = _get_parser().parse_args(argv) args = vars(options).copy() args.pop("func") diff --git a/cubids/constants.py b/cubids/constants.py index dfbc2072b..54fdf451e 100644 --- a/cubids/constants.py +++ b/cubids/constants.py @@ -1,14 +1,21 @@ -"""Constants for CuBIDS.""" +"""Constants for CuBIDS. + +This module defines various constants used throughout the CuBIDS package. + +Attributes +---------- +ID_VARS : set of str + Names of identifier variables. Used to place EntitySet and ParamGroup at + the beginning of a dataframe but both are hardcoded in the relevant function. +NON_KEY_ENTITIES : set of str + Entities that should not be used to group parameter sets. +IMAGING_PARAMS : set of str + List of metadata fields merged in `metadata_merge.py`. +""" -# Names of identifier variables. -# Used to place EntitySet and ParamGroup at the beginning of a dataframe, -# but both are hardcoded in the relevant function. ID_VARS = set(["EntitySet", "ParamGroup", "FilePath"]) -# Entities that should not be used to group parameter sets NON_KEY_ENTITIES = set(["subject", "session", "extension"]) # Multi-dimensional keys SliceTiming XXX: what is this line about? -# List of metadata fields and parameters (calculated by CuBIDS) -# Not sure what this specific list is used for. IMAGING_PARAMS = set( [ "ParallelReductionFactorInPlane", diff --git a/cubids/tests/test_apply.py b/cubids/tests/test_apply.py index 469a4b5dc..ebe67818b 100644 --- a/cubids/tests/test_apply.py +++ b/cubids/tests/test_apply.py @@ -146,7 +146,13 @@ @pytest.fixture(scope="module") def files_data(): - """A dictionary describing a CuBIDS files tsv file for testing.""" + """A dictionary describing a CuBIDS files tsv file for testing. + + Returns + ------- + dict + A dictionary containing file data for longitudinal and cross-sectional datasets. + """ dict_ = { "longitudinal": { "ParamGroup": [1, 1, 1, 1], @@ -196,7 +202,13 @@ def files_data(): @pytest.fixture(scope="module") def summary_data(): - """A dictionary describing a CuBIDS summary tsv file for testing.""" + """A dictionary describing a CuBIDS summary tsv file for testing. + + Returns + ------- + dict + A dictionary containing summary data for CuBIDS. + """ dict_ = { "RenameEntitySet": [ None, @@ -267,7 +279,30 @@ def test_cubids_apply_intendedfor( is_longitudinal, expected, ): - """Test cubids apply with different IntendedFor types.""" + """Test cubids apply with different IntendedFor types. + + Parameters + ---------- + tmpdir : LocalPath + Temporary directory for the test. + summary_data : dict + Summary data fixture. + files_data : dict + Files data fixture. + name : str + Name of the test case. + skeleton : dict + BIDS skeleton structure. + intended_for : str + IntendedFor field value. + expected : str or Exception + Expected result or exception. + + Raises + ------ + ValueError + If the test case is expected to raise an error. + """ import json from cubids.workflows import apply diff --git a/cubids/tests/test_bond.py b/cubids/tests/test_bond.py index 82dc3adcb..4fb90b9d2 100644 --- a/cubids/tests/test_bond.py +++ b/cubids/tests/test_bond.py @@ -45,7 +45,13 @@ def test_ok_json_merge(tmp_path): - """Test ok_json_merge.""" + """Test that a successful merge can happen. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) # Test that a successful merge can happen @@ -73,7 +79,13 @@ def test_ok_json_merge(tmp_path): def test_ok_json_merge_cli(tmp_path): - """Test ok_json_merge_cli.""" + """Test that a successful merge can happen using the CLI. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) # Test that a successful merge can happen @@ -103,7 +115,13 @@ def test_ok_json_merge_cli(tmp_path): def test_get_param_groups(tmp_path): - """Test get_param_groups.""" + """Test the retrieval of parameter groups. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) bod = CuBIDS(data_root / "inconsistent", use_datalad=True) entity_sets = bod.get_entity_sets() @@ -115,7 +133,13 @@ def test_get_param_groups(tmp_path): def test_copy_exemplars(tmp_path): - """Test copy_exemplars.""" + """Test the copying of exemplars. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) bod = CuBIDS(data_root / "complete", use_datalad=True) tsv_prefix = str(tmp_path / "tsvs") @@ -139,7 +163,13 @@ def test_copy_exemplars(tmp_path): def test_purge_no_datalad(tmp_path): - """Test purge_no_datalad.""" + """Test the purge operation without using DataLad. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) scans = [] scan_name = "sub-03/ses-phdiff/func/sub-03_ses-phdiff_task-rest_bold.nii.gz" @@ -203,7 +233,13 @@ def test_purge_no_datalad(tmp_path): def test_purge(tmp_path): - """Test purge.""" + """Test the purge operation using DataLad. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) scans = [] scan_name = "sub-03/ses-phdiff/func/sub-03_ses-phdiff_task-rest_bold.nii.gz" @@ -236,7 +272,13 @@ def test_purge(tmp_path): def test_bad_json_merge(tmp_path): - """Test bad_json_merge.""" + """Test that an unsuccessful merge returns an error. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) # Test that a successful merge can happen @@ -263,7 +305,13 @@ def test_bad_json_merge(tmp_path): def test_bad_json_merge_cli(tmp_path): - """Test bade_json_merge_cli.""" + """Test that an unsuccessful merge returns an error using the CLI. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) # Test that a successful merge can happen @@ -291,7 +339,13 @@ def test_bad_json_merge_cli(tmp_path): def test_add_nifti_info_datalad(tmp_path): - """Test add_nifti_info_datalad.""" + """Test adding NIfTI info to sidecars using DataLad. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) bod = CuBIDS(data_root / "complete", use_datalad=True, force_unlock=True) tsv_prefix = str(tmp_path / "tsvs") @@ -326,7 +380,13 @@ def test_add_nifti_info_datalad(tmp_path): def test_add_nifti_info_no_datalad(tmp_path): - """Test add_nifti_info_no_datalad.""" + """Test adding NIfTI info to sidecars without using DataLad. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) bod = CuBIDS(data_root / "complete", use_datalad=False, force_unlock=False) bod.add_nifti_info() @@ -354,7 +414,13 @@ def test_add_nifti_info_no_datalad(tmp_path): def test_tsv_merge_no_datalad(tmp_path): - """Test tsv_merge_no_datalad.""" + """Test merging TSV files without using DataLad. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) bod = CuBIDS(data_root / "inconsistent", use_datalad=False) @@ -415,7 +481,13 @@ def test_tsv_merge_no_datalad(tmp_path): def test_tsv_merge_changes(tmp_path): - """Test tsv_merge_changes.""" + """Test merging TSV files with changes. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) bod = CuBIDS(data_root / "inconsistent", use_datalad=True, is_longitudinal=True) bod.datalad_save() @@ -545,7 +617,10 @@ def test_tsv_merge_changes(tmp_path): def test_merge_without_overwrite(): - """Test merge_without_overwrite.""" + """Test merge_without_overwrite. + + Test that metadata fields are merged without overwriting existing values. + """ meta1 = { "ManualCheck": 1.0, "RenameEntitySet": np.nan, @@ -612,7 +687,13 @@ def test_merge_without_overwrite(): def test_entitysets(tmp_path): - """Test entitysets.""" + """Test entitysets. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) # Test the complete data @@ -636,7 +717,13 @@ def test_entitysets(tmp_path): def test_tsv_creation(tmp_path): - """Test the Entity Set and Parameter Group creation on sample data.""" + """Test the Entity Set and Parameter Group creation on sample data. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) # Test the complete data @@ -713,7 +800,13 @@ def test_tsv_creation(tmp_path): def test_apply_tsv_changes(tmp_path): - """Test apply_tsv_changes.""" + """Test apply_tsv_changes. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ # set up like narrative of user using this # similar to test tsv creation # open the tsv, rename a entity set @@ -836,7 +929,13 @@ def test_apply_tsv_changes(tmp_path): def test_session_apply(tmp_path): - """Test session_apply.""" + """Test session_apply. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ # set up like narrative of user using this # similar to test tsv creation # open the tsv, rename a entity set @@ -872,7 +971,13 @@ def test_session_apply(tmp_path): def test_remove_fields(tmp_path): - """Test that we metadata fields are detected and removed.""" + """Test that we metadata fields are detected and removed. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) bod = CuBIDS(data_root, use_datalad=False) @@ -896,7 +1001,13 @@ def test_remove_fields(tmp_path): def test_datalad_integration(tmp_path): - """Test that datalad works for basic file modification operations.""" + """Test that datalad works for basic file modification operations. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) # Test that an uninitialized CuBIDS raises exceptions @@ -991,7 +1102,13 @@ def test_datalad_integration(tmp_path): def test_validator(tmp_path): - """Test validator.""" + """Test validator. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) # test the validator in valid dataset @@ -1039,7 +1156,13 @@ def test_validator(tmp_path): def test_bids_version(tmp_path): - """Test workflows.bids_version.""" + """Test workflows.bids_version. + + Parameters + ---------- + tmp_path : pathlib.Path + The temporary path where the test data will be copied. + """ data_root = get_data(tmp_path) bids_dir = Path(data_root) / "complete" @@ -1070,7 +1193,6 @@ def test_bids_version(tmp_path): schema_version >= min_schema_version ), f"Schema version {schema_version} is less than minimum {min_schema_version}" - # def test_image(image='pennlinc/bond:latest'): # """Check whether image is present on local system.""" # ret = subprocess.run(['docker', 'images', '-q', image], diff --git a/cubids/tests/test_cli.py b/cubids/tests/test_cli.py index d45c8dc8c..06b9603d4 100644 --- a/cubids/tests/test_cli.py +++ b/cubids/tests/test_cli.py @@ -17,7 +17,18 @@ def test_path_exists(tmp_path): - """Test whether a given path exists or not.""" + """Test whether a given path exists or not. + + Parameters + ---------- + tmp_path : pathlib.Path + Temporary directory path provided by pytest. + + Raises + ------ + SystemExit + If the path does not exist. + """ parser = argparse.ArgumentParser() # Test with an existing path @@ -60,7 +71,18 @@ def test_path_exists(tmp_path): def test_is_file(tmp_path): - """Test whether a given path exists or not.""" + """Test whether a given path is a file or not. + + Parameters + ---------- + tmp_path : pathlib.Path + Temporary directory path provided by pytest. + + Raises + ------ + SystemExit + If the path does not exist or is not a file. + """ parser = argparse.ArgumentParser() # Test with an existing path diff --git a/cubids/tests/test_cubids.py b/cubids/tests/test_cubids.py index 2839e7875..b3fa498bf 100644 --- a/cubids/tests/test_cubids.py +++ b/cubids/tests/test_cubids.py @@ -1,4 +1,4 @@ -"""This file contains unit tests for the CuBIDS class in the CuBIDS package.""" +"""Unit tests for the CuBIDS class in the CuBIDS package.""" import pandas as pd import pytest @@ -8,11 +8,25 @@ @pytest.fixture def cubids_instance(): + """Fixture for creating a CuBIDS instance. + + Returns + ------- + CuBIDS + An instance of the CuBIDS class. + """ data_root = "/path/to/bids/dataset" return CuBIDS(data_root) def _test_init_cubids(cubids_instance): + """Test the initialization of CuBIDS. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ assert cubids_instance.path == "/path/to/bids/dataset" assert cubids_instance.use_datalad is False assert cubids_instance.acq_group_level == "subject" @@ -21,41 +35,97 @@ def _test_init_cubids(cubids_instance): def _test_reset_bids_layout(cubids_instance): + """Test the reset of BIDS layout. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ cubids_instance.reset_bids_layout() assert cubids_instance.layout is not None def _test_create_cubids_code_dir(cubids_instance): + """Test the creation of CuBIDS code directory. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ cubids_instance.create_cubids_code_dir() assert cubids_instance.cubids_code_dir is True def _test_init_datalad(cubids_instance): + """Test the initialization of DataLad. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ cubids_instance.init_datalad() assert cubids_instance.datalad_ready is True assert cubids_instance.datalad_handle is not None def _test_add_nifti_info(cubids_instance): + """Test adding NIfTI information. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ cubids_instance.add_nifti_info() # Add assertions here def _test_datalad_save(cubids_instance): + """Test saving with DataLad. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ cubids_instance.datalad_save() # Add assertions here def _test_is_datalad_clean(cubids_instance): + """Test if DataLad repository is clean. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ assert cubids_instance.is_datalad_clean() is True def _test_datalad_undo_last_commit(cubids_instance): + """Test undoing the last DataLad commit. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ cubids_instance.datalad_undo_last_commit() # Add assertions here def _test_apply_tsv_changes(cubids_instance): + """Test applying TSV changes. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ summary_tsv = "/path/to/summary.tsv" files_tsv = "/path/to/files.tsv" new_prefix = "new_prefix" @@ -64,6 +134,13 @@ def _test_apply_tsv_changes(cubids_instance): def _test_change_filename(cubids_instance): + """Test changing filename. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ filepath = "/path/to/file.nii.gz" entities = {"subject": "sub-01", "session": "ses-01"} cubids_instance.change_filename(filepath, entities) @@ -71,6 +148,13 @@ def _test_change_filename(cubids_instance): def _test_copy_exemplars(cubids_instance): + """Test copying exemplars. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ exemplars_dir = "/path/to/exemplars" exemplars_tsv = "/path/to/exemplars.tsv" min_group_size = 2 @@ -79,62 +163,139 @@ def _test_copy_exemplars(cubids_instance): def _test_purge(cubids_instance): + """Test purging scans. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ scans_txt = "/path/to/scans.txt" cubids_instance.purge(scans_txt) # Add assertions here def _test__purge_associations(cubids_instance): + """Test purging associations. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ scans = ["scan-01", "scan-02"] cubids_instance._purge_associations(scans) # Add assertions here def _test_get_nifti_associations(cubids_instance): + """Test getting NIfTI associations. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ nifti = "/path/to/file.nii.gz" associations = cubids_instance.get_nifti_associations(nifti) # Add assertions here def _test__cache_fieldmaps(cubids_instance): + """Test caching fieldmaps. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ cubids_instance._cache_fieldmaps() # Add assertions here def _test_get_param_groups_from_entity_set(cubids_instance): + """Test getting parameter groups from entity set. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ entity_set = "group-01" param_groups = cubids_instance.get_param_groups_from_entity_set(entity_set) # Add assertions here def _test_create_data_dictionary(cubids_instance): + """Test creating data dictionary. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ cubids_instance.create_data_dictionary() # Add assertions here def _test_get_data_dictionary(cubids_instance): + """Test getting data dictionary. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ df = pd.DataFrame({"subject": ["sub-01", "sub-02"], "age": [25, 30]}) data_dict = cubids_instance.get_data_dictionary(df) # Add assertions here def _test_get_param_groups_dataframes(cubids_instance): + """Test getting parameter groups dataframes. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ param_groups_dataframes = cubids_instance.get_param_groups_dataframes() # Add assertions here def _test_get_tsvs(cubids_instance): + """Test getting TSV files. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ path_prefix = "/path/to/tsvs" tsvs = cubids_instance.get_tsvs(path_prefix) # Add assertions here def _test_get_entity_sets(cubids_instance): + """Test getting entity sets. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ entity_sets = cubids_instance.get_entity_sets() # Add assertions here def _test_change_metadata(cubids_instance): + """Test changing metadata. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ filters = {"subject": "sub-01"} metadata = {"age": 25} cubids_instance.change_metadata(filters, metadata) @@ -142,37 +303,86 @@ def _test_change_metadata(cubids_instance): def _test_get_all_metadata_fields(cubids_instance): + """Test getting all metadata fields. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ metadata_fields = cubids_instance.get_all_metadata_fields() # Add assertions here def _test_remove_metadata_fields(cubids_instance): + """Test removing metadata fields. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ fields_to_remove = ["age", "sex"] cubids_instance.remove_metadata_fields(fields_to_remove) # Add assertions here def _test_get_filenames(cubids_instance): + """Test getting filenames. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ filenames = cubids_instance.get_filenames() # Add assertions here def _test_get_fieldmap_lookup(cubids_instance): + """Test getting fieldmap lookup. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ fieldmap_lookup = cubids_instance.get_fieldmap_lookup() # Add assertions here def _test_get_layout(cubids_instance): + """Test getting layout. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ layout = cubids_instance.get_layout() # Add assertions here def _test__validate_json(cubids_instance): + """Test validating JSON. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ cubids_instance._validate_json() # Add assertions here def _test__update_json(cubids_instance): + """Test updating JSON. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ json_file = "/path/to/file.json" metadata = {"age": 25} cubids_instance._update_json(json_file, metadata) @@ -180,30 +390,65 @@ def _test__update_json(cubids_instance): def _test__entity_set_to_entities(cubids_instance): + """Test converting entity set to entities. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ entity_set = "group-01" entities = cubids_instance._entity_set_to_entities(entity_set) # Add assertions here def _test__entities_to_entity_set(cubids_instance): + """Test converting entities to entity set. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ entities = {"subject": "sub-01", "session": "ses-01"} entity_set = cubids_instance._entities_to_entity_set(entities) # Add assertions here def _test__file_to_entity_set(cubids_instance): + """Test converting file to entity set. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ filename = "sub-01_ses-01_task-rest_bold.nii.gz" entity_set = cubids_instance._file_to_entity_set(filename) # Add assertions here def _test__get_intended_for_reference(cubids_instance): + """Test getting intended for reference. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ scan = "sub-01_ses-01_task-rest_bold.nii.gz" reference = cubids_instance._get_intended_for_reference(scan) # Add assertions here def _test__get_param_groups(cubids_instance): + """Test getting parameter groups. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ files = ["sub-01_ses-01_task-rest_bold.nii.gz", "sub-02_ses-01_task-rest_bold.nii.gz"] fieldmap_lookup = {"sub-01_ses-01_task-rest_bold.nii.gz": "fieldmap.nii.gz"} entity_set_name = "group-01" @@ -217,6 +462,13 @@ def _test__get_param_groups(cubids_instance): def _test_round_params(cubids_instance): + """Test rounding parameters. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ param_group_df = pd.DataFrame({"param": [0.123456789]}) config = {"param": {"round": 3}} modality = "bold" @@ -225,12 +477,26 @@ def _test_round_params(cubids_instance): def _test_get_sidecar_metadata(cubids_instance): + """Test getting sidecar metadata. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ json_file = "/path/to/file.json" metadata = cubids_instance.get_sidecar_metadata(json_file) # Add assertions here def _test_format_params(cubids_instance): + """Test formatting parameters. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ param_group_df = pd.DataFrame({"param": [0.123456789]}) config = {"param": {"format": "{:.2f}"}} modality = "bold" @@ -239,12 +505,26 @@ def _test_format_params(cubids_instance): def _test__order_columns(cubids_instance): + """Test ordering columns. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ df = pd.DataFrame({"b": [2], "a": [1]}) ordered_df = cubids_instance._order_columns(df) # Add assertions here def _test_img_to_new_ext(cubids_instance): + """Test converting image to new extension. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ img_path = "/path/to/image.nii.gz" new_ext = ".nii" new_img_path = cubids_instance.img_to_new_ext(img_path, new_ext) @@ -252,6 +532,13 @@ def _test_img_to_new_ext(cubids_instance): def _test_get_entity_value(cubids_instance): + """Test getting key name. + + Parameters + ---------- + cubids_instance : CuBIDS + An instance of the CuBIDS class. + """ path = "/path/to/file.nii.gz" key = "subject" key_name = cubids_instance.get_entity_value(path, key) diff --git a/cubids/utils.py b/cubids/utils.py index 09c02e349..c4cdb457f 100644 --- a/cubids/utils.py +++ b/cubids/utils.py @@ -1,4 +1,7 @@ -"""Miscellaneous utility functions for CuBIDS.""" +"""Miscellaneous utility functions for CuBIDS. + +This module provides various utility functions used throughout the CuBIDS package. +""" import re from pathlib import Path diff --git a/cubids/workflows.py b/cubids/workflows.py index 5fd615e82..07d03bfe9 100644 --- a/cubids/workflows.py +++ b/cubids/workflows.py @@ -695,7 +695,7 @@ def copy_exemplars( """ # Run directly from python using if container is None: - bod = CuBIDS(data_root=str(bids_dir), use_datalad=use_datalad) + bod = CuBIDS(data_root=str(bids_dir), use_datalad=use_datalad, force_unlock=force_unlock) if use_datalad: if not bod.is_datalad_clean(): raise Exception( diff --git a/docs/conf.py b/docs/conf.py index ae90cf8ce..04eeea0ae 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -259,3 +259,10 @@ "term", "footcite", ] + +# ----------------------------------------------------------------------------- +# sphinx_copybutton +# ----------------------------------------------------------------------------- +# Configuration for sphinx_copybutton to remove shell prompts, i.e. $ +copybutton_prompt_text = "$ " +copybutton_only_copy_prompt_lines = False # ensures all lines are copied, even those without a prompt \ No newline at end of file