anndict.AdataDict.fapply

anndict.AdataDict.fapply#

AdataDict.fapply(func, *, use_multithreading=True, num_workers=None, max_retries=0, catch_errors=True, return_as_adata_dict=False, max_depth=None, isolate_rng=True, **kwargs_dicts)[source]#

Applies func to each AnnData in adata_dict, with error handling, retry mechanism, and the option to use either threading or sequential execution. The return behaviour is based on the return behaviour of func.

kwargs can be Any. if a kwarg is a dict with keys that match adata_dict, then values are broadcast to the func call on the corresponding key-value of adata_dict. Otherwise, the kwarg is directly broadcast to all calls of func.

Parameters:
adata_dict AdataDict

An AdataDict.

func callable

Function to apply to each AnnData object in adata_dict.

use_multithreading bool (default: True)

If True, use ThreadPoolExecutor; if False, execute sequentially. Default is True.

num_workers int | None (default: None)

Number of worker threads to use. If None, defaults to the number of CPUs available.

max_retries int (default: 0)

Maximum number of retry attempts after the first failure. (i.e. 0 means no retries, 1 means one retry after the first failure, for a total of 2 attempts)

catch_errors bool (default: True)

If False, raise exceptions instead of catching errors.

return_as_adata_dict bool (default: False)

Whether to return the results as a dict (if False) or AdataDict (if True).

max_depth int | str | list[str] | tuple[str, ...] | None (default: None)

The depth at which to stop recursing and apply func. - None (default): recurse to leaves. - 0: apply to the full input adata_dict. - 1: apply to each top-level value in adata_dict. - int: stop at that integer depth (0-indexed from root). - str / list[str] / tuple[str, ...]: stop at the depth matching the name(s) in adata_dict.hierarchy.

isolate_rng bool (default: True)

If True (default) and use_multithreading is True, each threaded call of func gets its own copy of the process-global random number generators, so results do not depend on thread scheduling. See Notes.

kwargs_dicts Any

Additional keyword arguments to pass to the function.

Return type:

dict | AdataDict | None

Returns:

  • If all results are None: None

  • Otherwise: A dict or AdataDict (based on return_as_adata_dict) containing all results of func applied to each AnnData

Notes

Be careful when setting max_retries != 0. If retries are used, the same function will be called again on whatever the current data is, which may not be the original data. For example, if func log-transform the data, then does something that fails, the second time func is called, the already log-transformed data will have another log transform applied.

With use_multithreading=True and isolate_rng=True, each call of func runs with its own NumPy global RandomState, random generator and igraph generator, which threads started by func share. A func that seeds a global generator (e.g. scanpy.tl.score_genes() with random_state=0) gives the same results as with use_multithreading=False, and unseeded draws are reproducible if numpy.random.seed() and random.seed() were called beforehand. While adata_dict_fapply runs, the global RNG functions are routed process-wide; threads that are not running func use the real generators.

Use use_multithreading=False if func draws random numbers through a reference to a global generator captured before the call (other than scipy.stats distributions), through RNG state inside other compiled code, or in a process pool. Threads that func starts and that outlive it keep using its generators. A custom igraph generator set before the call is replaced by random afterwards. Numba-jitted code (e.g. UMAP) keeps its own per-thread RNG state, so such functions may not be reproducible when threaded.