Source code for AFQ.definitions.utils

import os.path as op
import logging

from AFQ.utils.path import drop_extension


logger = logging.getLogger('AFQ')


__all__ = ["Definition", "find_file", "name_from_path"]


[docs]class Definition(object): ''' All Definitions should inherit this. For a given subject and session within the API, the definition is used to create a given image or map. Definitions have an init function which the users uses to specify how they want the definition to behave. The find_path function is called by the AFQ API. The api calls find_path to let the definition find relevant files for the given subject and session. ''' def __init__(self): raise NotImplementedError("Please implement an __init__ method")
[docs] def find_path(self, bids_layout, from_path, subject, session, required=True): pass
[docs] def str_for_toml(self): """ Uses __init__ in str_for_toml to make string that will instantiate itself. Assumes object will have attributes of same name as __init__ args. This is important for reading/writing definitions as arguments to config files. """ return type(self).__name__\ + "("\ + _arglist_to_string( self.__init__.__code__.co_varnames, get_attr=self)\ + ')'
def _arglist_to_string(args, get_attr=None): ''' Helper function Takes a list of arguments and unfolds them into a string. If get_attr is not None, it will be used to get the attribute corresponding to each argument instead. ''' to_string = "" for arg in args: if arg == "self": continue if get_attr is not None: arg = getattr(get_attr, arg) if isinstance(arg, Definition): arg = arg.str_for_toml() elif isinstance(arg, str): arg = f"\"{arg}\"" elif isinstance(arg, list): arg = f"[{_arglist_to_string(arg)}]" to_string = to_string + str(arg) + ', ' if to_string[-2:] == ', ': to_string = to_string[:-2] return to_string
[docs]def name_from_path(path): file_name = op.basename(path) # get file name file_name = drop_extension(file_name) # remove extension if "-" in file_name: file_name = file_name.split("-")[-1] # get suffix if exists return file_name
def _ff_helper(required, err_msg): if required: raise ValueError(err_msg) else: logger.warning(err_msg) return None
[docs]def find_file(bids_layout, path, filters, suffix, session, subject, extension=".nii.gz", required=True): """ Helper function Generic calls to get_nearest to find a file """ if "extension" not in filters: filters["extension"] = extension if "suffix" not in filters: filters["suffix"] = suffix # First, try to match the session. nearest = bids_layout.get_nearest( path, **filters, session=session, subject=subject, full_search=True, strict=False, ) # If that fails, loosen session restriction # in order to find scans that are not session specific if nearest is None: nearest = bids_layout.get_nearest( path, **filters, subject=subject, full_search=True, strict=False, ) # Nothing is found if nearest is None: return _ff_helper(required, ( "No file found with these parameters:\n" f"suffix: {suffix},\n" f"session (searched with and without): {session},\n" f"subject: {subject},\n" f"filters: {filters},\n" f"near path: {path},\n")) path_subject = bids_layout.parse_file_entities(path).get( "subject", None ) file_subject = bids_layout.parse_file_entities(nearest).get( "subject", None ) path_session = bids_layout.parse_file_entities(path).get( "session", None ) file_session = bids_layout.parse_file_entities(nearest).get( "session", None ) # found file is wrong subject if path_subject != file_subject: return _ff_helper(required, ( f"Expected subject IDs to match for the retrieved image file " f"and the supplied `from_path` file. Got sub-{file_subject} " f"from image file {nearest} and sub-{path_subject} " f"from `from_path` file {path}.")) # found file is wrong session if (file_session is not None) and (path_session != file_session): return _ff_helper(required, ( f"Expected session IDs to match for the retrieved image file " f"and the supplied `from_path` file. Got ses-{file_session} " f"from image file {nearest} and ses-{path_session} " f"from `from_path` file {path}.")) return nearest