Source code for phasorpy.utils

"""Utility functions.

The ``phasorpy.utils`` module provides auxiliary and convenience functions
that do not naturally fit into other modules.

"""

from __future__ import annotations

__all__ = [
    'logger',
    'number_threads',
    'versions',
]

import logging
import os


[docs] def logger() -> logging.Logger: """Return ``logging.getLogger('phasorpy')``.""" return logging.getLogger('phasorpy')
[docs] def number_threads( num_threads: int | None = None, max_threads: int | None = None, /, ) -> int: """Return number of threads for parallel computations across CPU cores. This function is used to parse ``num_threads`` parameters. Parameters ---------- num_threads : int, optional Number of threads to use for parallel computations on CPU cores. If None (default), return 1, disabling multi-threading. If greater than zero, return value up to `max_threads` if set. If zero, return the value of the ``PHASORPY_NUM_THREADS`` environment variable if set, else half the CPU cores up to `max_threads` or 32. max_threads : int, optional Maximum number of threads to return. Returns ------- int Number of threads for parallel computations. Examples -------- >>> number_threads() 1 >>> number_threads(0) # doctest: +SKIP 8 """ if num_threads is None or num_threads < 0: # disable multi-threading by default return 1 if num_threads == 0: # return default number of threads if max_threads is None: max_threads = 32 else: max_threads = max(max_threads, 1) if 'PHASORPY_NUM_THREADS' in os.environ: return min( max_threads, max(1, int(os.environ['PHASORPY_NUM_THREADS'])) ) cpu_count: int | None if hasattr(os, 'sched_getaffinity'): cpu_count = len(os.sched_getaffinity(0)) else: # sched_getaffinity not available on Windows cpu_count = os.cpu_count() if cpu_count is None: return 1 return min(max_threads, max(1, cpu_count // 2)) # return num_threads up to max_threads if max_threads is None: return num_threads return min(num_threads, max(max_threads, 1))
[docs] def versions( *, sep: str = '\n', dash: str = '-', verbose: bool = False ) -> str: """Return version information for PhasorPy and its dependencies. Parameters ---------- sep : str, optional Separator between version items. Defaults to newline. dash : str, optional Separator between module name and version. Defaults to dash. verbose : bool, optional Include paths to Python interpreter and modules. Returns ------- str Formatted string containing version information. Format: "<package><dash><version>[<space>(<path>)]<sep>" Example ------- >>> print(versions()) Python-3... phasorpy-0... numpy-... ... """ import importlib.metadata import os import sys if verbose: version_strings = [f'Python{dash}{sys.version} ({sys.executable})'] else: version_strings = [f'Python{dash}{sys.version.split()[0]}'] for module in ( 'phasorpy', 'numpy', 'tifffile', 'imagecodecs', 'lfdfiles', 'sdtfile', 'ptufile', 'liffile', 'matplotlib', 'scipy', 'skimage', 'sklearn', 'pandas', 'xarray', 'click', 'pooch', ): try: __import__(module) except ModuleNotFoundError: version_strings.append(f'{module.lower()}{dash}n/a') continue lib = sys.modules[module] try: ver = importlib.metadata.version(module) except importlib.metadata.PackageNotFoundError: ver = getattr(lib, '__version__', 'unknown') ver = f'{module.lower()}{dash}{ver}' if verbose: try: path = getattr(lib, '__file__') except NameError: pass else: ver += f' ({os.path.dirname(path)})' version_strings.append(ver) return sep.join(version_strings)