Source code for extraction.core.functions.loaders

import typing as t
from types import FunctionType
from inspect import getfullargspec, getmembers, isfunction, isbuiltin

import bottleneck as bn

from extraction.core.functions import cell, trap
from extraction.core.functions.custom import localisation
from extraction.core.functions.distributors import trap_apply
from extraction.core.functions.math_utils import div0

"""
Load functions for analysing cells and their background.
Note that inspect.getmembers returns a list of function names and functions,
and inspect.getfullargspec returns a function's arguments.
"""


[docs]def load_cellfuns_core(): """Load functions from the cell module and return as a dict.""" return { f[0]: f[1] for f in getmembers(cell) if isfunction(f[1]) and f[1].__module__.startswith("extraction.core.functions") }
[docs]def load_custom_args() -> t.Tuple[ (t.Dict[str, t.Callable], t.Dict[str, t.List[str]]) ]: """ Load custom functions from the localisation module. Return the functions and any additional arguments other than cell_mask and trap_image as dictionaries. """ # load functions from module funs = { f[0]: f[1] for f in getmembers(localisation) if isfunction(f[1]) and f[1].__module__.startswith("extraction.core.functions") } # load additional arguments if cell_mask and trap_image are arguments args = { k: getfullargspec(v).args[2:] for k, v in funs.items() if set(["cell_mask", "trap_image"]).intersection( getfullargspec(v).args ) } # return dictionaries of functions and of arguments return ( {k: funs[k] for k in args.keys()}, {k: v for k, v in args.items() if v}, )
[docs]def load_cellfuns(): """ Create a dict of core functions for use on cell_masks. The core functions only work on a single mask. """ # create dict of the core functions from cell.py - these functions apply to a single mask cell_funs = load_cellfuns_core() # create a dict of functions that apply the core functions to an array of cell_masks CELLFUNS = {} for f_name, f in cell_funs.items(): if isfunction(f): def tmp(f): args = getfullargspec(f).args if len(args) == 1: # function that applies f to m, an array of masks return lambda m, _: trap_apply(f, m) else: # function that applies f to m and img, the trap_image return lambda m, img: trap_apply(f, m, img) CELLFUNS[f_name] = tmp(f) return CELLFUNS
[docs]def load_trapfuns(): """Load functions that are applied to an entire tile.""" TRAPFUNS = { f[0]: f[1] for f in getmembers(trap) if isfunction(f[1]) and f[1].__module__.startswith("extraction.core.functions") } return TRAPFUNS
[docs]def load_funs(): """Combine all automatically loaded functions.""" CELLFUNS = load_cellfuns() TRAPFUNS = load_trapfuns() # return dict of cell funs, dict of trap funs, and dict of both return CELLFUNS, TRAPFUNS, {**TRAPFUNS, **CELLFUNS}
[docs]def load_redfuns( additional_reducers: t.Optional[ t.Union[t.Dict[str, t.Callable], t.Callable] ] = None, ) -> t.Dict[str, t.Callable]: """ Load functions to reduce a multidimensional image by one dimension. Parameters ---------- additional_reducers: function or a dict of functions (optional) Functions to perform the reduction. """ RED_FUNS = { "max": bn.nanmax, "mean": bn.nanmean, "median": bn.nanmedian, "div0": div0, "add": bn.nansum, "None": None, } if additional_reducers is not None: if isinstance(additional_reducers, FunctionType): additional_reducers = [ (additional_reducers.__name__, additional_reducers) ] RED_FUNS.update(additional_reducers) return RED_FUNS