Source code for fastar.imf.registry

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Registry for Initial Mass Functions (IMFs).
Provides centralized access to all available IMF parametrizations.
"""

from fastar.imf.named_imf.bimodal import bimodal
from fastar.imf.named_imf.broken_power_law import broken_power_law
from fastar.imf.named_imf.chabrier import chabrier
from fastar.imf.named_imf.flexi import flexi
from fastar.imf.named_imf.kroupa import kroupa
from fastar.imf.named_imf.single_power_law import single_power_law


[docs] class IMFRegistry: """ Registry for Initial Mass Functions (IMFs). This class provides a centralized way to access pre-defined IMF parametrizations by name, and allows registration of custom IMFs. Supports multiple access patterns: - Method: imf_registry.load_by_name('kroupa') - Dict-like: imf_registry['kroupa'] - Attribute: imf_registry.kroupa Examples -------- >>> import jax.numpy as jnp >>> from fastar.imf import imf_registry >>> >>> # Method access >>> imf_func = imf_registry.load_by_name('kroupa') >>> >>> # Dict-like access >>> imf_func = imf_registry['kroupa'] >>> >>> # Attribute access >>> imf_func = imf_registry.kroupa """ def __init__(self): """ Initialize the IMF registry with pre-defined IMFs. """ self._registry = { 'single_power_law': single_power_law, 'broken_power_law': broken_power_law, 'kroupa': kroupa, 'chabrier': chabrier, 'flexi': flexi, 'bimodal': bimodal, }
[docs] def load_by_name(self, name): """ Load an IMF function by name. Parameters ---------- name : str Name of the IMF to load. Available options are: - 'single_power_law' - 'broken_power_law' - 'kroupa' - 'chabrier' - 'flexi' - 'bimodal' Returns ------- callable The IMF function with signature `func(mass, params)`. Raises ------ ValueError If the IMF name is not found in the registry. """ name_lower = name.lower() if name_lower not in self._registry: available = sorted(set(self._registry.keys())) raise ValueError( f"IMF '{name}' not in registry. Available IMFs: {', '.join(available)}" ) return self._registry[name_lower]
def __getitem__(self, name): """ Dictionary-like access to IMFs. Parameters ---------- name : str Name of the IMF to load. Returns ------- callable The IMF function. """ return self.load_by_name(name) def __getattr__(self, name): """ Attribute-like access to IMFs. Parameters ---------- name : str Name of the IMF to load. Returns ------- callable The IMF function. """ if name.startswith('_'): raise AttributeError( f"'{type(self).__name__}' object has no attribute '{name}'" ) try: return self.load_by_name(name) except ValueError as e: raise AttributeError(str(e)) from e
[docs] def register(self, name, imf_func): """ Register a custom IMF function. Parameters ---------- name : str Name to register the IMF under. imf_func : callable IMF function with signature `func(mass, params)`. Raises ------ ValueError If the name already exists and overwrite is False. """ name_lower = name.lower() if name_lower in self._registry: raise ValueError(f"IMF '{name}' already exists in registry. ") self._registry[name_lower] = imf_func
[docs] def list_available(self): """ List all available IMF names in the registry. Returns ------- list of str Sorted list of unique IMF names (excluding aliases). """ return sorted(self._registry.keys())
[docs] def has_imf(self, name): """ Check if an IMF exists in the registry. Parameters ---------- name : str Name of the IMF to check. Returns ------- bool True if the IMF exists, False otherwise. """ return name.lower() in self._registry
def __repr__(self): """String representation of the registry.""" available = self.list_available() return f'IMFRegistry(available={available})' def __len__(self): """Return the number of unique IMFs in the registry.""" return len(set(self._registry.values()))