Source code for rubix.telescope.factory

import os
import warnings
from typing import Optional, Union

import numpy as np
from beartype import beartype as typechecker
from jaxtyping import jaxtyped

from rubix.logger import get_logger
from rubix.telescope.apertures import (
    CIRCULAR_APERTURE,
    HEXAGONAL_APERTURE,
    SQUARE_APERTURE,
)
from rubix.telescope.base import BaseTelescope
from rubix.telescope.utils import calculate_wave_edges, calculate_wave_seq
from rubix.utils import read_yaml

PATH = os.path.dirname(os.path.abspath(__file__))
TELESCOPE_CONFIG_PATH = os.path.join(PATH, "telescopes.yaml")


[docs] class TelescopeFactory: @jaxtyped(typechecker=typechecker) def __init__(self, telescopes_config: Optional[Union[dict, str]] = None) -> None: logger = get_logger() if telescopes_config is None: logger.info( "No telescope config provided, falling back to %s", TELESCOPE_CONFIG_PATH, ) warnings.warn( ("No telescope config provided, " "using default stored in {}").format( TELESCOPE_CONFIG_PATH ), UserWarning, ) self.telescopes_config = read_yaml(TELESCOPE_CONFIG_PATH) elif isinstance(telescopes_config, str): self.telescopes_config = read_yaml(telescopes_config) else: self.telescopes_config = telescopes_config
[docs] @jaxtyped(typechecker=typechecker) def create_telescope(self, name: str) -> BaseTelescope: """ Function to create a telescope object from the given configuration. Args: name (str): The name of the telescope to create. Returns: The telescope object as BaseTelescope. Raises: ValueError: If the telescope name is not present in the configuration. Example 1 (Uses the defined telescope configuration) ----------------------------------------------------- >>> from rubix.telescope import TelescopeFactory >>> telescope_config = { ... "MUSE": { ... "fov": 5, ... "spatial_res": 0.2, ... "wave_range": [4700.15, 9351.4], ... "wave_res": 1.25, ... "lsf_fwhm": 2.51, ... "signal_to_noise": None, ... "wave_centre": 6975.775, ... "aperture_type": "square", ... "pixel_type": "square" ... } ... } >>> factory = TelescopeFactory(telescope_config) >>> telescope = factory.create_telescope("MUSE") >>> print(telescope) Example 2 (Uses the default telescope configuration) ----------------------------------------------------- >>> from rubix.telescope import TelescopeFactory >>> factory = TelescopeFactory() >>> telescope = factory.create_telescope("MUSE") >>> print(telescope) """ if name not in self.telescopes_config: raise ValueError(f"Telescope {name} not found in config") config = self.telescopes_config[name] # Get some parameters from the config sbin = np.floor(config["fov"] / config["spatial_res"]).astype(int) aperture_region = self._get_aperture(config["aperture_type"], sbin) wave_seq = calculate_wave_seq(config["wave_range"], config["wave_res"]) wave_edges = calculate_wave_edges(wave_seq, config["wave_res"]) telescope = BaseTelescope( fov=config["fov"], spatial_res=config["spatial_res"], wave_range=config["wave_range"], wave_res=config["wave_res"], lsf_fwhm=config["lsf_fwhm"], signal_to_noise=config["signal_to_noise"], sbin=sbin, aperture_region=aperture_region, pixel_type=config["pixel_type"], wave_seq=wave_seq, wave_edges=wave_edges, ) telescope.__class__.__name__ = name return telescope
def _get_aperture(self, type, size): if type == "square": return SQUARE_APERTURE(size) elif type == "circular": return CIRCULAR_APERTURE(size) elif type == "hexagonal": return HEXAGONAL_APERTURE(size) else: raise ValueError(f"Unknown aperture type: {type}")