Source code for fastspecfit.singlecopy

"""
fastspecfit.singlecopy
======================

Single-copy (per process) data structures read from files.

"""
import logging
from fastspecfit.cosmo import TabulatedDESI
from fastspecfit.igm import Inoue14
from fastspecfit.photometry import Photometry
from fastspecfit.linetable import LineTable
from fastspecfit.templates import Templates, VDISP_NOMINAL, VDISP_BOUNDS
from fastspecfit.logger import log, DEBUG

[docs] class Singletons(object): """Container for per-process singleton data structures. Holds global shared objects (templates, emission lines, photometry, cosmology, IGM model) that are read from disk once at startup and shared across all worker threads/processes within a single MPI rank. """ def __init__(self): pass
[docs] def initialize(self, emlines_file=None, constraints_file=None, fphotofile=None, fastphot=False, vdisp_nominal=VDISP_NOMINAL, vdisp_bounds=VDISP_BOUNDS, fitstack=False, ignore_photometry=False, template_file=None, template_version=None, template_imf=None, log_verbose=False, ): """Load all singleton data structures from disk. Parameters ---------- emlines_file : :class:`str` or None, optional Path to the emission-line parameter file; uses the bundled default when ``None``. constraints_file : :class:`str` or None, optional Path to the emission-line kinematic constraint YAML file; uses the bundled default when ``None``. A consistency check against ``emlines_file`` is run at startup. fphotofile : :class:`str` or None, optional Path to the photometric configuration YAML file; uses the bundled DR9 default when ``None``. fastphot : :class:`bool`, optional If ``True``, load templates in photometry-only mode. Default is ``False``. vdisp_nominal : :class:`float`, optional Nominal velocity dispersion in km/s used to pre-cache FFTs. vdisp_bounds : tuple of float, optional ``(min, max)`` velocity dispersion bounds in km/s. fitstack : :class:`bool`, optional If ``True``, use the stacked-spectra photometry configuration. Default is ``False``. ignore_photometry : :class:`bool`, optional If ``True``, disable photometric fitting. Default is ``False``. template_file : :class:`str` or None, optional Full path to the SPS template FITS file; auto-detected when ``None``. template_version : :class:`str` or None, optional Template version string; used when ``template_file`` is ``None``. template_imf : :class:`str` or None, optional Initial mass function name for template selection. log_verbose : :class:`bool`, optional If ``True``, set the logger level to ``DEBUG``. Default is ``False``. """ if log_verbose: log.setLevel(DEBUG) key = (emlines_file, constraints_file, fphotofile, fastphot, fitstack, ignore_photometry, template_file, template_version, template_imf, vdisp_nominal, tuple(vdisp_bounds) if vdisp_bounds is not None else None) if getattr(self, '_init_key', None) == key: return self._init_key = key # templates for continuum fitting self.templates = Templates(template_file=template_file, template_version=template_version, imf=template_imf, mintemplatewave=None, maxtemplatewave=40e4, vdisp_nominal=vdisp_nominal, vdisp_bounds=vdisp_bounds, fastphot=fastphot) log.debug(f'Cached stellar templates {self.templates.file}') # emission line table self.emlines = LineTable(emlines_file) log.debug(f'Cached emission-line table {self.emlines.file}') # kinematic constraint file (validated against emlines at startup) from fastspecfit.emlines import EmlineConstraints self.constraints = EmlineConstraints(constraints_file, self.emlines.table) log.debug(f'Cached emission-line constraints {self.constraints.file}') # photometry self.photometry = Photometry(fphotofile, fitstack, ignore_photometry) log.debug(f'Cached photometric filters and parameters {self.photometry.fphotofile}') # fiducial cosmology self.cosmology = TabulatedDESI() log.debug(f'Cached cosmology table {self.cosmology.file}') # IGM model self.igm = Inoue14() log.debug(f'Cached {self.igm.reference} IGM attenuation parameters.')
# global structure with single-copy data, initially empty sc_data = Singletons()
[docs] def _initialize_sc_data(**kwargs): """Pool initializer: initialize the per-process sc_data singleton. This must be a module-level function so that multiprocessing (spawn mode) pickles it by reference rather than by value. A bound method such as ``sc_data.initialize`` would be pickled together with the parent's fully initialized ``sc_data`` object and then called on that pickled copy in the worker, leaving the worker's own module-level ``sc_data`` uninitialized. """ sc_data.initialize(**kwargs)
[docs] def _initialize_sc_data_worker(**kwargs): """Pool initializer for MPI production workers. Like :func:`_initialize_sc_data` but suppresses INFO logging in workers unless ``log_verbose=True`` was requested. This keeps per-object progress messages out of the Slurm log (where output from all MPI ranks is interleaved) while still routing them to the per-healpix log file via the parent process. Interactive ``fastspec``/``fastphot`` runs use :func:`_initialize_sc_data` instead and therefore keep full INFO logging regardless of ``--mp``. """ sc_data.initialize(**kwargs) if not kwargs.get('log_verbose', False): log.setLevel(logging.WARNING)