"""Shared utilities for IO, plotting, logging, and runtime helpers.
The ``common`` package contains cross-cutting infrastructure used by all major
subpackages, including directory management, plotting, HDF5 helpers, timers,
and low-level binary utilities.
Input/output contracts
----------------------
Utilities are intentionally lightweight: they accept standard Python objects or
NumPy-compatible arrays and return plain Python or NumPy outputs where possible.
Plotting helpers expect Matplotlib-compatible inputs.
Determinism and stability
-------------------------
Most helpers are deterministic for fixed inputs. Logging or timing output may
vary with runtime scheduling. Binary helper functions operate on integer bit
patterns and are deterministic by construction.
Submodules are loaded lazily on first access to reduce import overhead.
"""
import importlib
from typing import TYPE_CHECKING
# For static type checking (IDE support) without runtime import
if TYPE_CHECKING:
from .directories import Directories
from .plot import (
Plotter, PlotterSave, MatrixPrinter,
colorsCycle, colorsCycleBright, colorsCycleDark, colorsList,
linestylesCycle, linestylesCycleExtended, linestylesList,
markersCycle, markersList
)
from .datah import DataHandler
from .binary import (
ctz64, popcount64,
mask_from_indices, indices_from_mask,
complement_mask, complement_indices
)
from .hdf5man import HDF5Manager
from .lazy_entry import (
LazyDataEntry, LazyHDF5Entry,
LazyNpzEntry, LazyPickleEntry, LazyJsonEntry
)
from .plotters.data_loader import load_results, filter_results, ResultSet, PlotData
from .flog import Logger, get_global_logger
from .memory import log_memory_status, check_memory_for_operation
from .timer import Timer
[docs]
def dtype_to_name(dtype):
"""
Normalize dtype-like objects to the canonical QES dtype name.
"""
if isinstance(dtype, str):
return dtype
try:
import numpy as np
dtype_obj = np.dtype(dtype)
except Exception:
dtype_obj = dtype
try:
from QES.Algebra.backends import get_dtype_map
dtype_name = get_dtype_map().get(dtype)
if dtype_name is None:
dtype_name = get_dtype_map().get(dtype_obj)
if dtype_name is not None:
return dtype_name
except Exception:
pass
try:
import numpy as np
return np.dtype(dtype).name
except Exception:
return str(dtype)
# Lazy loading registry
_LAZY_IMPORTS = {
# directories
'Directories' : ('.directories', 'Directories'),
# plot
'Plotter' : ('.plot', 'Plotter'),
'PlotterSave' : ('.plot', 'PlotterSave'),
'MatrixPrinter' : ('.plot', 'MatrixPrinter'),
'colorsCycle' : ('.plot', 'colorsCycle'),
'colorsCycleBright' : ('.plot', 'colorsCycleBright'),
'colorsCycleDark' : ('.plot', 'colorsCycleDark'),
'colorsList' : ('.plot', 'colorsList'),
'linestylesCycle' : ('.plot', 'linestylesCycle'),
'linestylesCycleExtended' : ('.plot', 'linestylesCycleExtended'),
'linestylesList' : ('.plot', 'linestylesList'),
'markersCycle' : ('.plot', 'markersCycle'),
'markersList' : ('.plot', 'markersList'),
# datah
'DataHandler' : ('.datah', 'DataHandler'),
# binary - Numba-safe bit operations
'ctz64' : ('.binary', 'ctz64'),
'popcount64' : ('.binary', 'popcount64'),
'mask_from_indices' : ('.binary', 'mask_from_indices'),
'indices_from_mask' : ('.binary', 'indices_from_mask'),
'complement_mask' : ('.binary', 'complement_mask'),
'complement_indices' : ('.binary', 'complement_indices'), # alias
# hdf5
'HDF5Manager' : ('.hdf5man', 'HDF5Manager'),
# lazy entries
'LazyDataEntry' : ('.lazy_entry', 'LazyDataEntry'),
'LazyHDF5Entry' : ('.lazy_entry', 'LazyHDF5Entry'),
'LazyNpzEntry' : ('.lazy_entry', 'LazyNpzEntry'),
'LazyPickleEntry' : ('.lazy_entry', 'LazyPickleEntry'),
'LazyJsonEntry' : ('.lazy_entry', 'LazyJsonEntry'),
# data loaders
'load_results' : ('.plotters.data_loader', 'load_results'),
'filter_results' : ('.plotters.data_loader', 'filter_results'),
'ResultSet' : ('.plotters.data_loader', 'ResultSet'),
'PlotData' : ('.plotters.data_loader', 'PlotData'),
# logging
'Logger' : ('.flog', 'Logger'),
'get_global_logger' : ('.flog', 'get_global_logger'),
# memory
'log_memory_status' : ('.memory', 'log_memory_status'),
'check_memory_for_operation': ('.memory', 'check_memory_for_operation'),
# timer
'Timer' : ('.timer', 'Timer'),
}
# Cache for loaded modules
_LOADED = {}
def __getattr__(name: str):
"""Lazy import handler - loads modules only when accessed."""
if name in _LAZY_IMPORTS:
if name not in _LOADED:
module_path, attr_name = _LAZY_IMPORTS[name]
module = importlib.import_module(module_path, package=__name__)
_LOADED[name] = getattr(module, attr_name)
return _LOADED[name]
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
def __dir__():
"""List available attributes for autocompletion."""
return list(_LAZY_IMPORTS.keys()) + ['dtype_to_name', 'get_module_description', 'list_available_modules']
####################################################################################################
[docs]
def get_module_description(module_name):
"""
Get the description of a specific module in the common package.
Parameters:
- module_name (str): The name of the module.
Returns:
- str: The description of the module.
"""
descriptions = {
"binary" : "Handles binary data operations.",
"directories" : "Provides the Directories class for managing directory structures.",
"plot" : "Provides visualization utilities (Plotter, PlotterSave, MatrixPrinter).",
"datah" : "Handles various data operations and transformations.",
"hdf5man" : "Manages reading and writing HDF5 files.",
"lazy_entry" : "Lazy data-entry wrappers for HDF5/NPZ/Pickle/JSON files.",
"plotters" : "Plot-related data loaders and plotting utilities.",
"flog" : "Provides logging functionalities for structured output.",
"memory" : "Memory monitoring and management utilities.",
"timer" : "Context manager and utilities for performance timing."
}
return descriptions.get(module_name, "Module not found.")
[docs]
def list_available_modules():
"""
List all available modules in the common package.
Returns:
- list: A list of available module names.
"""
return ["binary", "directories", "plot", "datah", "hdf5man", "lazy_entry", "plotters", "flog", "memory", "timer"]
# Expose all lazy-loadable names for `from common import *`
__all__ = list(_LAZY_IMPORTS.keys()) + ['dtype_to_name', 'get_module_description', 'list_available_modules']
####################################################################################################
#! EOF
####################################################################################################