Source code for rubix.telescope.factory
import numpy as np
from rubix.telescope.apertures import (
SQUARE_APERTURE,
CIRCULAR_APERTURE,
HEXAGONAL_APERTURE,
)
from rubix.telescope.base import BaseTelescope
from rubix.telescope.utils import calculate_wave_edges, calculate_wave_seq
from rubix.utils import read_yaml
import os
import warnings
from typing import Optional, Union
from jaxtyping import Float, Array, jaxtyped
from beartype import beartype as typechecker
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:
if telescopes_config is None:
warnings.warn(
"No telescope config provided, using default stored in {}".format(
TELESCOPE_CONFIG_PATH
)
)
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.
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}")