Esempio n. 1
0
class CameraFrame(BaseCoordinateFrame):
    '''
    Astropy CoordinateFrame representing coordinates in the CameraPlane

    Attributes
    ----------
    pointing_direction: astropy.coordinates.AltAz
        The pointing direction of the telescope
    obstime: astropy.Time
        The timestamp of the observation, only needed to directly transform
        to Equatorial coordinates, transforming to AltAz does not need this.
    location: astropy.coordinates.EarthLocation
        The location of the observer,  only needed to directly transform
        to Equatorial coordinates, transforming to AltAz does not need this,
        default is FACT's location
    rotated: bool
        True means x points right and y points up when looking on the camera
        from the dish, which is the efinition of FACT-Tools >= 1.0 and Mars.
        False means x points up and y points left,
        which is definition in the original FACTPixelMap file.
    '''
    default_representation = PlanarRepresentation
    pointing_direction = CoordinateAttribute(frame=AltAz, default=None)
    obstime = TimeAttribute(default=None)
    location = EarthLocationAttribute(default=LOCATION)
    rotated = Attribute(default=True)
Esempio n. 2
0
class ReferencePlaneFrame(coord.BaseCoordinateFrame):
    """A coordinate frame aligned with the reference plane coordinates of a
    Kepler orbit, centered on the barycenter or reference point of the orbit.

    See :ref:`celestial-reference-plane` for more information.

    ``ReferencePlaneFrame`` objects always have generic component names for
    spherical coordinates of ``lon``/``lat``, *not* the component names for the
    frame of the ``origin``.

    Parameters
    ----------
    representation : `BaseRepresentation` or None
        A representation object or None to have no data (or use the other
        keywords).
    origin : `SkyCoord` or low-level coordinate object.
        The coordinate which specifies the origin of this frame. This is
        typically a sky position and a distance to the barycenter or reference
        point of the orbit at a particular epoch.

    Notes
    -----
    ``ReferencePlaneFrame`` is a factory class.  That is, the objects that it
    yields are *not* actually objects of class ``ReferencePlaneFrame``.
    Instead, distinct classes are created on-the-fly for whatever the frame
    class is of ``origin``.
    """

    origin = CoordinateAttribute(default=None, frame=None)

    def __new__(cls, *args, **kwargs):
        # We don't want to call this method if we've already set up
        # an skyoffset frame for this class.
        if not (issubclass(cls, ReferencePlaneFrame)
                and cls is not ReferencePlaneFrame):
            # We get the origin argument, and handle it here. Default is ICRS:
            # the user might want to use arbitrary reference plane coordinates
            # without every transforming them
            origin_frame = kwargs.get('origin', ICRS())

            if hasattr(origin_frame, 'frame'):
                origin_frame = origin_frame.frame
            newcls = _make_cls(origin_frame.__class__)
            return newcls.__new__(newcls, *args, **kwargs)

        # http://stackoverflow.com/questions/19277399/why-does-object-new-work-differently-in-these-three-cases
        # See above for why this is necessary. Basically, because some child
        # may override __new__, we must override it here to never pass
        # arguments to the object.__new__ method.
        if super().__new__ is object.__new__:
            return super().__new__(cls)
        return super().__new__(cls, *args, **kwargs)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.origin is not None and not self.origin.has_data:
            raise ValueError('The origin supplied to ReferencePlaneFrame has '
                             'no data.')
        if self.has_data and hasattr(self.data, 'lon'):
            self.data.lon.wrap_angle = 180 * u.deg
Esempio n. 3
0
class Heliocentric(BaseCoordinateFrame):
    """
    A coordinate or frame in the Heliocentric system.
    This frame may either be specified in Cartesian
    or cylindrical representation.
    Cylindrical representation replaces (x, y) with
    (rho, psi) where rho is the impact parameter and
    psi is the position angle in degrees.

    Parameters
    ----------
    representation: `~astropy.coordinates.BaseRepresentation` or None.
        A representation object. If specified, other parameters must
        be in keyword form and if x, y and z are specified, it must
        be None.
    x: `Quantity` object.
        X-axis coordinate, optional, must be keyword.
    y: `Quantity` object.
        Y-axis coordinate, optional, must be keyword.
    z: `Quantity` object. Shared by both representations.
        Z-axis coordinate, optional, must be keyword.
    D0: `Quantity` object.
        Represents the distance between the observer and the Sun center.
        Defaults to 1AU.

    Examples
    --------
    >>> from astropy.coordinates import SkyCoord, CartesianRepresentation
    >>> import sunpy.coordinates
    >>> import astropy.units as u
    >>> sc = SkyCoord(CartesianRepresentation(10*u.km, 1*u.km, 2*u.km),
    ...               dateobs="2011/01/05T00:00:50", frame="heliocentric")
    >>> sc
    <SkyCoord (HelioCentric): dateobs=2011-01-05 00:00:50, D0=149597870.7 km,
    x=10.0 km, y=1.0 km, z=2.0 km>
    >>> sc = SkyCoord([1,2]*u.km, [3,4]*u.m, [5,6]*u.cm, frame="heliocentric",
    dateobs="2011/01/01T00:00:54")
    >>> sc
    <SkyCoord (HelioCentric): dateobs=2011-01-01 00:00:54, D0=149597870.7 km,
    (x, y, z) in (km, m, cm)
        [(1.0, 3.0, 5.0), (2.0, 4.0, 6.0)]>
    """

    default_representation = CartesianRepresentation

    _frame_specific_representation_info = {
        'cylindrical': [RepresentationMapping('phi', 'psi', u.deg)]
    }

    dateobs = TimeFrameAttributeSunPy()
    observer = CoordinateAttribute(HeliographicStonyhurst,
                                   default=HeliographicStonyhurst(
                                       0 * u.deg, 0 * u.deg, 1 * u.AU))
Esempio n. 4
0
        def __new__(cls, name, bases, members):
            # Only 'origin' is needed here, to set the origin frame properly.
            members['origin'] = CoordinateAttribute(frame=framecls,
                                                    default=None)

            # This has to be done because FrameMeta will set these attributes
            # to the defaults from BaseCoordinateFrame when it creates the base
            # SkyOffsetFrame class initially.
            members[
                '_default_representation'] = framecls._default_representation
            members['_default_differential'] = framecls._default_differential

            newname = name[:-5] if name.endswith('Frame') else name
            newname += framecls.__name__

            return super().__new__(cls, newname, bases, members)
Esempio n. 5
0
class TelescopeFrame(BaseCoordinateFrame):
    """
    Telescope coordinate frame.

    A Frame using a UnitSphericalRepresentation.
    This is basically the same as a HorizonCoordinate, but the
    origin is at the telescope's pointing direction.

    This is used to specify coordinates in the field of view of a
    telescope that is independent of the optical properties of the telescope.

    ``fov_lon`` is aligned with azimuth and ``fov_lat`` is aligned with altitude
    of the horizontal coordinate frame as implemented in ``astropy.coordinates.AltAz``.

    This is what astropy calls a SkyOffsetCoordinate.

    Attributes
    ----------

    telescope_pointing: SkyCoord[AltAz]
        Coordinate of the telescope pointing in AltAz
    obstime: Tiem
        Observation time
    location: EarthLocation
        Location of the telescope
    """

    frame_specific_representation_info = {
        UnitSphericalRepresentation: [
            RepresentationMapping("lon", "fov_lon"),
            RepresentationMapping("lat", "fov_lat"),
        ]
    }
    default_representation = UnitSphericalRepresentation

    telescope_pointing = CoordinateAttribute(default=None, frame=AltAz)

    obstime = TimeAttribute(default=None)
    location = EarthLocationAttribute(default=None)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # make sure telescope coordinate is in range [-180°, 180°]
        if isinstance(self._data, UnitSphericalRepresentation):
            self._data.lon.wrap_angle = Angle(180, unit=u.deg)
Esempio n. 6
0
class TiltedGroundFrame(BaseCoordinateFrame):
    """Tilted ground coordinate frame.  The tilted ground coordinate frame
    is a cartesian system describing the 2 dimensional projected
    positions of objects in a tilted plane described by
    pointing_direction Typically this frame will be used for the
    reconstruction of the shower core position

    Frame attributes:

    * ``pointing_direction``
        Alt,Az direction of the tilted reference plane

    """
    default_representation = PlanarRepresentation
    # Pointing direction of the tilted system (alt,az),
    # could be the telescope pointing direction or the reconstructed shower
    # direction
    pointing_direction = CoordinateAttribute(default=None, frame=AltAz)
Esempio n. 7
0
class NominalFrame(BaseCoordinateFrame):
    """
    Nominal coordinate frame.

    A Frame using a UnitSphericalRepresentation.
    This is basically the same as a HorizonCoordinate, but the
    origin is at an arbitray position in the sky.
    This is what astropy calls a SkyOffsetCoordinate

    If the telescopes are in divergent pointing, this Frame can be
    used to transform to a common system.

    Attributes
    ----------

    origin: SkyCoord[AltAz]
        Origin of this frame as a HorizonCoordinate
    obstime: Tiem
        Observation time
    location: EarthLocation
        Location of the telescope
    """

    frame_specific_representation_info = {
        UnitSphericalRepresentation: [
            RepresentationMapping("lon", "fov_lon"),
            RepresentationMapping("lat", "fov_lat"),
        ]
    }
    default_representation = UnitSphericalRepresentation

    origin = CoordinateAttribute(default=None, frame=AltAz)

    obstime = TimeAttribute(default=None)
    location = EarthLocationAttribute(default=None)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # make sure telescope coordinate is in range [-180°, 180°]
        if isinstance(self._data, UnitSphericalRepresentation):
            self._data.lon.wrap_angle = Angle(180, unit=u.deg)
Esempio n. 8
0
class CameraFrame(BaseCoordinateFrame):
    """
    Camera coordinate frame.

    The camera frame is a 2d cartesian frame,
    describing position of objects in the focal plane of the telescope.

    The frame is defined as in H.E.S.S., starting at the horizon,
    the telescope is pointed to magnetic north in azimuth and then up to zenith.

    Now, x points north and y points west, so in this orientation, the
    camera coordinates line up with the CORSIKA ground coordinate system.

    MAGIC and FACT use a different camera coordinate system:
    Standing at the dish, looking at the camera, x points right, y points up.
    To transform MAGIC/FACT to ctapipe, do x' = -y, y' = -x.

    Attributes
    ----------

    focal_length : u.Quantity[length]
        Focal length of the telescope as a unit quantity (usually meters)
    rotation : u.Quantity[angle]
        Rotation angle of the camera (0 deg in most cases)
    telescope_pointing : SkyCoord[AltAz]
        Pointing direction of the telescope as SkyCoord in AltAz
    obstime : Time
        Observation time
    location : EarthLocation
        location of the telescope
    """

    default_representation = PlanarRepresentation

    focal_length = QuantityAttribute(default=0, unit=u.m)
    rotation = QuantityAttribute(default=0 * u.deg, unit=u.rad)
    telescope_pointing = CoordinateAttribute(frame=AltAz, default=None)

    obstime = TimeAttribute(default=None)
    location = EarthLocationAttribute(default=None)
Esempio n. 9
0
class TelescopeFrame(BaseCoordinateFrame):
    '''
    Telescope coordinate frame.

    A Frame using a UnitSphericalRepresentation.
    This is basically the same as a HorizonCoordinate, but the
    origin is at the telescope's pointing direction.
    This is what astropy calls a SkyOffsetCoordinate

    Attributes
    ----------

    telescope_pointing: SkyCoord[HorizonFrame]
        Coordinate of the telescope pointing in HorizonFrame
    obstime: Tiem
        Observation time
    location: EarthLocation
        Location of the telescope
    '''
    frame_specific_representation_info = {
        UnitSphericalRepresentation: [
            RepresentationMapping('lon', 'delta_az'),
            RepresentationMapping('lat', 'delta_alt'),
        ]
    }
    default_representation = UnitSphericalRepresentation

    telescope_pointing = CoordinateAttribute(default=None, frame=HorizonFrame)

    obstime = TimeAttribute(default=None)
    location = EarthLocationAttribute(default=None)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # make sure telescope coordinate is in range [-180°, 180°]
        if isinstance(self._data, UnitSphericalRepresentation):
            self._data.lon.wrap_angle = Angle(180, unit=u.deg)
Esempio n. 10
0
class Helioprojective(BaseCoordinateFrame):
    """
    A coordinate or frame in the Helioprojective (Cartesian) system.

    This is a projective coordinate system centered around the observer.
    It is a full spherical coordinate system with position given as longitude
    theta_x and latitude theta_y.

    Parameters
    ----------
    representation: `~astropy.coordinates.BaseRepresentation` or None.
        A representation object. If specified, other parameters must
        be in keyword form.
    Tx: `~astropy.coordinates.Angle`  or `~astropy.units.Quantity`
        X-axis coordinate.
    Ty: `~astropy.coordinates.Angle`  or `~astropy.units.Quantity`
        Y-axis coordinate.
    distance: `~astropy.units.Quantity`
        The radial distance from the observer to the coordinate point.
    L0: `~astropy.coordinates.Angle`
        The Heliographic (Stonyhurst) Longitude of the observer.
    B0: `~astropy.coordinates.Angle` or `~astropy.units.Quantity`
        The Heliographic (Stonyhurst) Latitude of the observer.
    D0: `Quantity` object.
        Represents the distance between observer and solar center.
        **Defaults to 1 AU**.

    Examples
    --------
    >>> from astropy.coordinates import SkyCoord
    >>> import sunpy.coordinates
    >>> import astropy.units as u
    >>> sc = SkyCoord(0*u.deg, 0*u.deg, 5*u.km, dateobs="2010/01/01T00:00:00",
    ...               frame="helioprojective")
    >>> sc
    <SkyCoord (HelioProjective): dateobs=2010-01-01 00:00:00, D0=149597870.7 km
    , Tx=0.0 arcsec, Ty=0.0 arcsec, distance=5.0 km>
    >>> sc = SkyCoord(0*u.deg, 0*u.deg, dateobs="2010/01/01T00:00:00",
    frame="helioprojective")
    >>> sc
    <SkyCoord (HelioProjective): dateobs=2010-01-01 00:00:00, D0=149597870.7 km
    , Tx=0.0 arcsec, Ty=0.0 arcsec, distance=149597870.7 km>
    """

    default_representation = SphericalWrap180Representation

    _frame_specific_representation_info = {
        'spherical': [
            RepresentationMapping('lon', 'Tx', u.arcsec),
            RepresentationMapping('lat', 'Ty', u.arcsec),
            RepresentationMapping('distance', 'distance', u.km)
        ],
        'sphericalwrap180': [
            RepresentationMapping('lon', 'Tx', u.arcsec),
            RepresentationMapping('lat', 'Ty', u.arcsec),
            RepresentationMapping('distance', 'distance', u.km)
        ],
        'unitspherical': [
            RepresentationMapping('lon', 'Tx', u.arcsec),
            RepresentationMapping('lat', 'Ty', u.arcsec)
        ],
        'unitsphericalwrap180': [
            RepresentationMapping('lon', 'Tx', u.arcsec),
            RepresentationMapping('lat', 'Ty', u.arcsec)
        ]
    }

    dateobs = TimeFrameAttributeSunPy()
    rsun = FrameAttribute(default=RSUN_METERS.to(u.km))
    observer = CoordinateAttribute(HeliographicStonyhurst,
                                   default=HeliographicStonyhurst(
                                       0 * u.deg, 0 * u.deg, 1 * u.AU))

    def __init__(self, *args, **kwargs):
        _rep_kwarg = kwargs.get('representation', None)

        BaseCoordinateFrame.__init__(self, *args, **kwargs)

        # Convert from Spherical to SphericalWrap180
        # If representation was explicitly passed, do not change the rep.
        if not _rep_kwarg:
            # The base __init__ will make this a UnitSphericalRepresentation
            # This makes it Wrap180 instead
            if isinstance(self._data, UnitSphericalRepresentation):
                self._data = UnitSphericalWrap180Representation(
                    lat=self._data.lat, lon=self._data.lon)
                self.representation = UnitSphericalWrap180Representation
            # Make a Spherical Wrap180 instead
            elif isinstance(self._data, SphericalRepresentation):
                self._data = SphericalWrap180Representation(
                    lat=self._data.lat,
                    lon=self._data.lon,
                    distance=self._data.distance)
                self.representation = SphericalWrap180Representation

    def calculate_distance(self):
        """
        This method calculates the third coordinate of the Helioprojective
        frame. It assumes that the coordinate point is on the disk of the Sun
        at the rsun radius.

        If a point in the frame is off limb then NaN will be returned.

        Returns
        -------
        new_frame : `~sunpy.coordinates.frames.HelioProjective`
            A new frame instance with all the attributes of the original but
            now with a third coordinate.
        """
        # Skip if we already are 3D
        if isinstance(self._data, SphericalRepresentation):
            return self

        rep = self.represent_as(UnitSphericalWrap180Representation)
        lat, lon = rep.lat, rep.lon
        alpha = np.arccos(np.cos(lat) * np.cos(lon)).to(lat.unit)
        c = self.observer.radius**2 - self.rsun**2
        b = -2 * self.observer.radius * np.cos(alpha)
        d = ((-1 * b) - np.sqrt(b**2 - 4 * c)) / 2
        return self.realize_frame(
            SphericalWrap180Representation(lon=lon, lat=lat, distance=d))