Source code for ctapipe.instrument.telescope
"""
Classes pertaining to the description of a Cherenkov Telescope
Todo:
-----
- add more info in OpticsDescription (mirror area, facets, etc). How to guess
  this?
- add ability to write to/from tables (like that written by
  ctapipe-dump-instrument)
- add ability to construct by names TelescopeDescription.from_name(
  camera='LSTCam', optics=('SST','1M')) (which would create a very unbalanced
  telescope :-))
"""
from ..coordinates import CameraFrame
from .camera import CameraDescription
from .guess import guess_telescope, unknown_telescope
from .optics import OpticsDescription
from .warnings import warn_from_name
__all__ = ["TelescopeDescription"]
[docs]
class TelescopeDescription:
    """
    Describes a Cherenkov Telescope and its associated
    `~ctapipe.instrument.OpticsDescription` and `~ctapipe.instrument.CameraDescription`
    Attributes
    ----------
    name: str
        Telescope name
    tel_type: str
        Telescope type
    optics: OpticsDescription
       the optics associated with this telescope
    camera: CameraDescription
       the camera associated with this telescope
    """
    __slots__ = (
        "name",
        "optics",
        "camera",
    )
    def __init__(
        self,
        name: str,
        optics: OpticsDescription,
        camera: CameraDescription,
    ):
        if not isinstance(name, str):
            raise TypeError("`name` must be a str")
        if not isinstance(optics, OpticsDescription):
            raise TypeError("`optics` must be an instance of `OpticsDescription`")
        if not isinstance(camera, CameraDescription):
            raise TypeError("`camera` must be an instance of `CameraDescription`")
        self.name = name
        self.optics = optics
        self.camera = camera
    def __hash__(self):
        """Make this hashable, so it can be used as dict keys or in sets"""
        return hash((self.optics, self.camera))
    def __eq__(self, other):
        return self.optics == other.optics and self.camera == other.camera
[docs]
    @classmethod
    def from_name(cls, optics_name, camera_name):
        """
        construct a TelescopeDescription from a name (telescope description
        string)
        Parameters
        ----------
        camera_name : str
           camera name
        optics_name : str
           optics name (e.g. LST, or SST-ASTRI), also called
           telescope_description
        Notes
        -----
        Warning: This method loads a pre-generated ``TelescopeDescription`` and is
        thus not guaranteed to be the same pixel ordering or even positions that
        correspond with event data! Therefore if you are analysing data, you
        should not rely on this method, but rather open the data with an
        ``EventSource`` and use the ``TelescopeDescription`` that is provided by
        ``source.subarray.tel[i]`` or by
        ``source.subarray.telescope_types[type_name]``. This will guarantee that
        the pixels in the event data correspond with the ``TelescopeDescription``
        Returns
        -------
        TelescopeDescription
        """
        warn_from_name()
        camera = CameraDescription.from_name(camera_name)
        optics = OpticsDescription.from_name(optics_name)
        camera.geometry.frame = CameraFrame(focal_length=optics.equivalent_focal_length)
        try:
            result = guess_telescope(
                camera.geometry.n_pixels, optics.equivalent_focal_length
            )
        except ValueError:
            result = unknown_telescope(optics.mirror_area, camera.geometry.n_pixels)
        return cls(name=result.name, optics=optics, camera=camera) 
    @property
    def camera_name(self):
        """Name of the camera"""
        return self.camera.name
    @property
    def optics_name(self):
        """Name of the optics"""
        return self.optics.name
    @property
    def type(self):
        """Size classification"""
        return self.optics.size_type
    def __str__(self):
        return f"{self.type}_{self.optics_name}_{self.camera_name}"
    def __repr__(self):
        return (
            f"{self.__class__.__name__}("
            f"type={self.type.value!r}"
            f", optics_name={self.optics_name!r}"
            f", camera_name={self.camera_name!r}"
            ")"
        )