Ejemplo n.º 1
0
def _observers_are_equal(obs_1, obs_2):
    # Note that this also lets pass the situation where both observers are None
    if obs_1 == obs_2:
        return True

    # obs_1 != obs_2
    if obs_1 is None:
        raise ConvertError(
            "The source observer is set to None, but the destination observer is "
            f"{obs_2}.")
    if obs_2 is None:
        raise ConvertError(
            "The destination observer is set to None, but the source observer is "
            f"{obs_2}.")
    if isinstance(obs_1, str):
        raise ConvertError(
            "The source observer needs to have `obstime` set because the "
            "destination observer is different.")
    if isinstance(obs_2, str):
        raise ConvertError(
            "The destination observer needs to have `obstime` set because the "
            "source observer is different.")

    return np.atleast_1d(
        (u.allclose(obs_1.lat, obs_2.lat) and u.allclose(obs_1.lon, obs_2.lon)
         and u.allclose(obs_1.radius, obs_2.radius)
         and obs_1.obstime == obs_2.obstime)).all()
Ejemplo n.º 2
0
def _observers_are_equal(obs_1, obs_2):
    # Note that this also lets pass the situation where both observers are None
    if obs_1 is obs_2:
        return True

    # obs_1 != obs_2
    if obs_1 is None:
        raise ConvertError("The source observer is set to None, but the transformation requires "
                           "the source observer to be specified, as the destination observer "
                           f"is set to {obs_2}.")
    if obs_2 is None:
        raise ConvertError("The destination observer is set to None, but the transformation "
                           "requires the destination observer to be specified, as the "
                           f"source observer is set to {obs_1}.")
    if isinstance(obs_1, str):
        if obs_1 == "self":
            return False
        raise ConvertError("The source observer needs to have `obstime` set because the "
                           "destination observer is different.")
    if isinstance(obs_2, str):
        if obs_2 == "self":
            return False
        raise ConvertError("The destination observer needs to have `obstime` set because the "
                           "source observer is different.")

    return np.atleast_1d((u.allclose(obs_1.lat, obs_2.lat) and
                          u.allclose(obs_1.lon, obs_2.lon) and
                          u.allclose(obs_1.radius, obs_2.radius) and
                          _times_are_equal(obs_1.obstime, obs_2.obstime))).all()
Ejemplo n.º 3
0
def hpc_to_hpc(from_coo, to_frame):
    """
    This converts from HPC to HPC, with different observer location parameters.
    It does this by transforming through HGS.
    """
    if _observers_are_equal(from_coo.observer, to_frame.observer, string_ok=True) and \
       np.all(from_coo.obstime == to_frame.obstime):
        return to_frame.realize_frame(from_coo.data)

    if not isinstance(to_frame.observer, BaseCoordinateFrame):
        raise ConvertError(
            "Cannot transform between helioprojective frames "
            "without `obstime` being specified for observer {}.".format(
                to_frame.observer))
    if not isinstance(from_coo.observer, BaseCoordinateFrame):
        raise ConvertError(
            "Cannot transform between helioprojective frames "
            "without `obstime` being specified for observer {}.".format(
                from_coo.observer))

    hgs = from_coo.transform_to(
        HeliographicStonyhurst(obstime=to_frame.obstime))
    hpc = hgs.transform_to(to_frame)

    return hpc
Ejemplo n.º 4
0
def hpc_to_hpc(heliopcoord, heliopframe):
    """
    This converts from HPC to HPC, with different observer location parameters.
    It does this by transforming through HGS.
    """
    if (heliopcoord.observer == heliopframe.observer or
        (u.allclose(heliopcoord.observer.lat, heliopframe.observer.lat)
         and u.allclose(heliopcoord.observer.lon, heliopframe.observer.lon)
         and u.allclose(heliopcoord.observer.radius,
                        heliopframe.observer.radius))):
        return heliopframe.realize_frame(heliopcoord._data)

    if not isinstance(heliopframe.observer, BaseCoordinateFrame):
        raise ConvertError(
            "Cannot transform between helioprojective frames "
            "without `obstime` being specified for observer {}.".format(
                heliopframe.observer))
    if not isinstance(heliopcoord.observer, BaseCoordinateFrame):
        raise ConvertError(
            "Cannot transform between helioprojective frames "
            "without `obstime` being specified for observer {}.".format(
                heliopcoord.observer))

    hgs = heliopcoord.transform_to(HeliographicStonyhurst)
    hgs.observer = heliopframe.observer
    hpc = hgs.transform_to(heliopframe)

    return hpc
Ejemplo n.º 5
0
def _check_observer_defined(frame):
    if frame.observer is None:
        raise ConvertError("This transformation cannot be performed because the "
                           f"{frame.__class__.__name__} frame has observer=None.")
    elif isinstance(frame.observer, str):
        raise ConvertError("This transformation cannot be performed because the "
                           f"{frame.__class__.__name__} frame needs a specified obstime "
                           f"to fully resolve observer='{frame.observer}'.")
Ejemplo n.º 6
0
def _check_observer_defined(frame):
    if frame.observer is None:
        raise ConvertError("This transformation cannot be performed because the "
                           f"{frame.__class__.__name__} frame has observer=None.")
    elif isinstance(frame.observer, str):
        if frame.observer != "self":
            raise ConvertError("This transformation cannot be performed because the "
                               f"{frame.__class__.__name__} frame needs a specified obstime "
                               f"to fully resolve observer='{frame.observer}'.")
        elif not isinstance(frame, HeliographicCarrington):
            raise ConvertError(f"The {frame.__class__.__name__} frame has observer='self' "
                               "but this is valid for only HeliographicCarrington frames.")
Ejemplo n.º 7
0
def hgs_to_hcrs(hgscoord, hcrsframe):
    """
    Convert from Heliographic Stonyhurst to HCRS.

    Even though we calculate the parameters for the affine transform, we use
    ``FunctionTransformWithFiniteDifference`` because otherwise there is no way to account for the
    induced angular velocity when transforming a coordinate with velocity information.
    """
    if hgscoord.obstime is None:
        raise ConvertError(
            "To perform this transformation, the HeliographicStonyhurst"
            " frame needs a specified `obstime`.")

    hgscoord = hgscoord.make_3d()

    # Calculate the matrix and offset in the HCRS->HGS direction
    forward_matrix, forward_offset = _affine_params_hcrs_to_hgs(
        hcrsframe.obstime, hgscoord.obstime)

    # Invert the transformation to get the HGS->HCRS transformation
    reverse_matrix = matrix_transpose(forward_matrix)
    reverse_offset = -forward_offset

    return hcrsframe.realize_frame(
        hgscoord.cartesian.transform(reverse_matrix) + reverse_offset)
Ejemplo n.º 8
0
    def make_3d(self):
        """
        This method calculates the third coordinate of the Helioprojective
        frame. It assumes that the coordinate point is on the surface of the Sun.

        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
        distance = self.spherical.distance
        if not (distance.unit is u.one and u.allclose(distance, 1 * u.one)):
            return self

        if not isinstance(self.observer, BaseCoordinateFrame):
            raise ConvertError("Cannot calculate distance to the Sun "
                               f"for observer '{self.observer}' "
                               "without `obstime` being specified.")

        rep = self.represent_as(UnitSphericalRepresentation)
        lat, lon = rep.lat, rep.lon

        # Check for the use of floats with lower precision than the native Python float
        if not set([lon.dtype.type, lat.dtype.type]).issubset(
            [float, np.float64, np.longdouble]):
            raise SunpyUserWarning(
                "The Helioprojective component values appear to be lower "
                "precision than the native Python float: "
                f"Tx is {lon.dtype.name}, and Ty is {lat.dtype.name}. "
                "To minimize precision loss, you may want to cast the values to "
                "`float` or `numpy.float64` via the NumPy method `.astype()`.")

        # Calculate the distance to the surface of the Sun using the law of cosines
        cos_alpha = np.cos(lat) * np.cos(lon)
        c = self.observer.radius**2 - self.rsun**2
        b = -2 * self.observer.radius * cos_alpha
        # Ignore sqrt of NaNs
        with np.errstate(invalid='ignore'):
            d = ((-1 * b) -
                 np.sqrt(b**2 - 4 * c)) / 2  # use the "near" solution

        if self._spherical_screen:
            sphere_center = self._spherical_screen['center'].transform_to(
                self).cartesian
            c = sphere_center.norm()**2 - self._spherical_screen['radius']**2
            b = -2 * sphere_center.dot(rep)
            # Ignore sqrt of NaNs
            with np.errstate(invalid='ignore'):
                dd = ((-1 * b) +
                      np.sqrt(b**2 - 4 * c)) / 2  # use the "far" solution

            d = np.fmin(d,
                        dd) if self._spherical_screen['only_off_disk'] else dd

        return self.realize_frame(
            SphericalRepresentation(lon=lon, lat=lat, distance=d))
Ejemplo n.º 9
0
def hpc_to_hcc(heliopcoord, heliocframe):
    """
    Convert from Helioprojective Cartesian to Heliocentric Cartesian.
    """
    if not isinstance(heliopcoord.observer, BaseCoordinateFrame):
        raise ConvertError("Cannot transform helioprojective coordinates to "
                           "heliocentric coordinates for observer '{}' "
                           "without `obstime` being specified.".format(
                               heliopcoord.observer))

    heliopcoord = heliopcoord.calculate_distance()

    # Permute/swap axes from HPC equivalent Cartesian to HCC
    newrepr = heliopcoord.cartesian.transform(
        matrix_transpose(_matrix_hcc_to_hpc()))

    # Shift the origin from the observer to the Sun
    distance = heliocframe.observer.radius
    newrepr += CartesianRepresentation(0 * u.m, 0 * u.m, distance)

    # Complete the conversion of HPC to HCC at the obstime and observer of the HPC coord
    int_coord = Heliocentric(newrepr,
                             obstime=heliopcoord.obstime,
                             observer=heliopcoord.observer)

    # Loopback transform HCC as needed
    return int_coord.transform_to(heliocframe)
Ejemplo n.º 10
0
def gei_to_hme(geicoord, hmeframe):
    """
    Convert from Geocentric Earth Equatorial to Heliocentric Mean Ecliptic
    """
    if geicoord.obstime is None:
        raise ConvertError("To perform this transformation, the coordinate"
                           " frame needs a specified `obstime`.")

    # Use an intermediate frame of HME at the GEI observation time
    int_frame = HeliocentricMeanEcliptic(obstime=geicoord.obstime, equinox=geicoord.equinox)

    # Get the Sun-Earth vector in the intermediate frame
    sun_earth = HCRS(_sun_earth_icrf(int_frame.obstime), obstime=int_frame.obstime)
    sun_earth_int = sun_earth.transform_to(int_frame).cartesian

    # Rotate from Earth equatorial to ecliptic
    rot_matrix = _rotation_matrix_obliquity(int_frame.equinox)
    earth_object_int = geicoord.cartesian.transform(rot_matrix)

    # Find the Sun-object vector in the intermediate frame
    sun_object_int = sun_earth_int + earth_object_int
    int_coord = int_frame.realize_frame(sun_object_int)

    # Convert to the final frame through HCRS
    return int_coord.transform_to(HCRS(obstime=int_coord.obstime)).transform_to(hmeframe)
Ejemplo n.º 11
0
def hme_to_gei(hmecoord, geiframe):
    """
    Convert from Heliocentric Mean Ecliptic to Geocentric Earth Equatorial
    """
    if geiframe.obstime is None:
        raise ConvertError("To perform this transformation, the coordinate"
                           " frame needs a specified `obstime`.")

    # Use an intermediate frame of HME at the GEI observation time, through HCRS
    int_frame = HeliocentricMeanEcliptic(obstime=geiframe.obstime,
                                         equinox=geiframe.equinox)
    int_coord = hmecoord.transform_to(
        HCRS(obstime=int_frame.obstime)).transform_to(int_frame)

    # Get the Sun-Earth vector in the intermediate frame
    sun_earth = HCRS(_sun_earth_icrf(int_frame.obstime),
                     obstime=int_frame.obstime)
    sun_earth_int = sun_earth.transform_to(int_frame).cartesian

    # Find the Earth-object vector in the intermediate frame
    earth_object_int = int_coord.cartesian - sun_earth_int

    # Rotate from ecliptic to Earth equatorial
    rot_matrix = matrix_transpose(_rotation_matrix_obliquity(
        int_frame.equinox))
    newrepr = earth_object_int.transform(rot_matrix)

    return geiframe.realize_frame(newrepr)
Ejemplo n.º 12
0
def hpc_to_hcc(heliopcoord, heliocframe):
    """
    Convert from Helioprojective Cartesian to Heliocentric Cartesian.
    """
    if not _observers_are_equal(heliopcoord.observer, heliocframe.observer):
        heliocframe_heliopobs = Heliocentric(observer=heliopcoord.observer)
        helioccoord_heliopobs = heliopcoord.transform_to(heliocframe_heliopobs)
        helioccoord = helioccoord_heliopobs.transform_to(heliocframe)
        return helioccoord

    if not isinstance(heliopcoord.observer, BaseCoordinateFrame):
        raise ConvertError("Cannot transform helioprojective coordinates to "
                           "heliocentric coordinates for observer '{}' "
                           "without `obstime` being specified.".format(
                               heliopcoord.observer))

    heliopcoord = heliopcoord.calculate_distance()
    x = np.deg2rad(heliopcoord.Tx)
    y = np.deg2rad(heliopcoord.Ty)

    cosx = np.cos(x)
    sinx = np.sin(x)
    cosy = np.cos(y)
    siny = np.sin(y)

    rx = (heliopcoord.distance.to(u.m)) * cosy * sinx
    ry = (heliopcoord.distance.to(u.m)) * siny
    rz = (heliopcoord.observer.radius.to(
        u.m)) - (heliopcoord.distance.to(u.m)) * cosy * cosx

    representation = CartesianRepresentation(rx.to(u.km), ry.to(u.km),
                                             rz.to(u.km))
    return heliocframe.realize_frame(representation)
Ejemplo n.º 13
0
def hcc_to_hgs(helioccoord, heliogframe):
    """
    Convert from Heliocentric Cartesian to Heliographic Stonyhurst.
    """
    if not isinstance(helioccoord.observer, BaseCoordinateFrame):
        raise ConvertError("Cannot transform heliocentric coordinates to "
                           "heliographic coordinates for observer '{}' "
                           "without `obstime` being specified.".format(
                               helioccoord.observer))

    x = helioccoord.x.to(u.m)
    y = helioccoord.y.to(u.m)
    z = helioccoord.z.to(u.m)

    l0_rad = helioccoord.observer.lon
    b0_deg = helioccoord.observer.lat

    cosb = np.cos(np.deg2rad(b0_deg))
    sinb = np.sin(np.deg2rad(b0_deg))

    hecr = np.sqrt(x**2 + y**2 + z**2)
    hgln = np.arctan2(x, z * cosb - y * sinb) + l0_rad
    hglt = np.arcsin((y * cosb + z * sinb) / hecr)

    representation = SphericalRepresentation(np.rad2deg(hgln),
                                             np.rad2deg(hglt), hecr.to(u.km))
    return heliogframe.realize_frame(representation)
Ejemplo n.º 14
0
    def make_3d(self):
        """
        This method calculates the third coordinate of the Helioprojective
        frame. It assumes that the coordinate point is on the surface of the Sun.

        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
        distance = self.spherical.distance
        if not (distance.unit is u.one and u.allclose(distance, 1 * u.one)):
            return self

        if not isinstance(self.observer, BaseCoordinateFrame):
            raise ConvertError("Cannot calculate distance to the Sun "
                               f"for observer '{self.observer}' "
                               "without `obstime` being specified.")

        rep = self.represent_as(UnitSphericalRepresentation)
        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)
        # Ingore sqrt of NaNs
        with np.errstate(invalid='ignore'):
            d = ((-1 * b) - np.sqrt(b**2 - 4 * c)) / 2

        return self.realize_frame(
            SphericalRepresentation(lon=lon, lat=lat, distance=d))
Ejemplo n.º 15
0
def hcc_to_hpc(helioccoord, heliopframe):
    """
    Convert from Heliocentic Cartesian to Helioprojective Cartesian.
    """
    if not _observers_are_equal(helioccoord.observer, heliopframe.observer):
        raise ConvertError(
            "Cannot directly transform heliocentric coordinates to "
            "helioprojective coordinates for different "
            "observers {} and {}. See discussion in this GH issue: "
            "https://github.com/sunpy/sunpy/issues/2712. Try converting to "
            "an intermediate heliographic Stonyhurst frame.".format(
                helioccoord.observer, heliopframe.observer))

    x = helioccoord.x.to(u.m)
    y = helioccoord.y.to(u.m)
    z = helioccoord.z.to(u.m)

    # d is calculated as the distance between the points
    # (x,y,z) and (0,0,D0).
    distance = np.sqrt(x**2 + y**2 + (helioccoord.observer.radius - z)**2)

    hpcx = np.rad2deg(np.arctan2(x, helioccoord.observer.radius - z))
    hpcy = np.rad2deg(np.arcsin(y / distance))

    representation = SphericalRepresentation(hpcx, hpcy, distance.to(u.km))

    return heliopframe.realize_frame(representation)
Ejemplo n.º 16
0
    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)
                and not (self.distance.unit is u.one
                         and quantity_allclose(self.distance, 1 * u.one))):
            return self

        if not isinstance(self.observer, BaseCoordinateFrame):
            raise ConvertError("Cannot calculate distance to the solar disk "
                               "for observer '{}' "
                               "without `obstime` being specified.".format(
                                   self.observer))

        rep = self.represent_as(UnitSphericalRepresentation)
        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(
            SphericalRepresentation(lon=lon, lat=lat, distance=d))
Ejemplo n.º 17
0
def hcrs_to_hgs(hcrscoord, hgsframe):
    """
    Convert from HCRS to Heliographic Stonyhurst (HGS).

    HGS shares the same origin (the Sun) as HCRS, but has its Z axis aligned with the Sun's
    rotation axis and its X axis aligned with the projection of the Sun-Earth vector onto the Sun's
    equatorial plane (i.e., the component of the Sun-Earth vector perpendicular to the Z axis).
    Thus, the transformation matrix is the product of the matrix to align the Z axis (by de-tilting
    the Sun's rotation axis) and the matrix to align the X axis.  The first matrix is independent
    of time and is pre-computed, while the second matrix depends on the time-varying Sun-Earth
    vector.
    """
    if hgsframe.obstime is None:
        raise ConvertError("To perform this transformation, the coordinate"
                           " frame needs a specified `obstime`.")

    # Check whether differentials are involved on either end
    has_differentials = (
        (hcrscoord._data is not None and hcrscoord.data.differentials)
        or (hgsframe._data is not None and hgsframe.data.differentials))

    # Determine the Sun-Earth vector in ICRS
    # Since HCRS is ICRS with an origin shift, this is also the Sun-Earth vector in HCRS
    # If differentials exist, also obtain Sun and Earth velocities
    if has_differentials:
        sun_pos_icrs, sun_vel = get_body_barycentric_posvel(
            'sun', hgsframe.obstime)
        earth_pos_icrs, earth_vel = get_body_barycentric_posvel(
            'earth', hgsframe.obstime)
    else:
        sun_pos_icrs = get_body_barycentric('sun', hgsframe.obstime)
        earth_pos_icrs = get_body_barycentric('earth', hgsframe.obstime)
    sun_earth = earth_pos_icrs - sun_pos_icrs

    # De-tilt the Sun-Earth vector to the frame with the Sun's rotation axis parallel to the Z axis
    sun_earth_detilt = sun_earth.transform(_SUN_DETILT_MATRIX)

    # Rotate the Sun-Earth vector about the Z axis so that it lies in the XZ plane
    rot_matrix = _rotation_matrix_reprs_to_xz_about_z(sun_earth_detilt)

    total_matrix = rot_matrix @ _SUN_DETILT_MATRIX

    # All of the above is calculated for the HGS observation time
    # If the HCRS observation time is different, calculate the translation in origin
    if not _ignore_sun_motion and np.any(
            hcrscoord.obstime != hgsframe.obstime):
        sun_pos_old_icrs = get_body_barycentric('sun', hcrscoord.obstime)
        offset_icrf = sun_pos_icrs - sun_pos_old_icrs
    else:
        offset_icrf = sun_pos_icrs * 0  # preserves obstime shape

    # Add velocity if needed (at the HGS observation time)
    if has_differentials:
        vel_icrf = (sun_vel - earth_vel).represent_as(CartesianDifferential)
        offset_icrf = offset_icrf.with_differentials(vel_icrf)

    offset = offset_icrf.transform(total_matrix)
    return total_matrix, offset
Ejemplo n.º 18
0
def hpc_to_hcc(heliopcoord, heliocframe):
    """
    Convert from Helioprojective Cartesian to Heliocentric Cartesian.
    """
    if not _observers_are_equal(heliopcoord.observer, heliocframe.observer):
        raise ConvertError(
            "Cannot directly transform helioprojective coordinates to "
            "heliocentric coordinates for different "
            "observers {} and {}. See discussion in this GH issue: "
            "https://github.com/sunpy/sunpy/issues/2712. Try converting to "
            "an intermediate heliographic Stonyhurst frame.".format(
                heliopcoord.observer, heliocframe.observer))

    if not isinstance(heliopcoord.observer, BaseCoordinateFrame):
        raise ConvertError("Cannot transform helioprojective coordinates to "
                           "heliocentric coordinates for observer '{}' "
                           "without `obstime` being specified.".format(
                               heliopcoord.observer))

    heliopcoord = heliopcoord.calculate_distance()
    x = np.deg2rad(heliopcoord.Tx)
    y = np.deg2rad(heliopcoord.Ty)

    cosx = np.cos(x)
    sinx = np.sin(x)
    cosy = np.cos(y)
    siny = np.sin(y)

    rx = (heliopcoord.distance.to(u.m)) * cosy * sinx
    ry = (heliopcoord.distance.to(u.m)) * siny
    rz = (heliopcoord.observer.radius.to(
        u.m)) - (heliopcoord.distance.to(u.m)) * cosy * cosx

    representation = CartesianRepresentation(rx.to(u.km), ry.to(u.km),
                                             rz.to(u.km))
    return heliocframe.realize_frame(representation)
Ejemplo n.º 19
0
def hcrs_to_hgs(hcrscoord, hgsframe):
    """
    Convert from HCRS to Heliographic Stonyhurst (HGS).

    Even though we calculate the parameters for the affine transform, we use
    ``FunctionTransformWithFiniteDifference`` because otherwise there is no way to account for the
    induced angular velocity when transforming a coordinate with velocity information.
    """
    if hgsframe.obstime is None:
        raise ConvertError("To perform this transformation, the HeliographicStonyhurst"
                           " frame needs a specified `obstime`.")

    rot_matrix, offset = _affine_params_hcrs_to_hgs(hcrscoord.obstime, hgsframe.obstime)

    return hgsframe.realize_frame(hcrscoord.cartesian.transform(rot_matrix) + offset)
Ejemplo n.º 20
0
    def make_3d(self):
        """
        This method calculates the third coordinate of the Helioprojective
        frame. It assumes that the coordinate point is on the surface of the Sun.

        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
        distance = self.spherical.distance
        if not (distance.unit is u.one and u.allclose(distance, 1 * u.one)):
            return self

        if not isinstance(self.observer, BaseCoordinateFrame):
            raise ConvertError("Cannot calculate distance to the Sun "
                               f"for observer '{self.observer}' "
                               "without `obstime` being specified.")

        rep = self.represent_as(UnitSphericalRepresentation)
        lat, lon = rep.lat, rep.lon
        cos_alpha = np.cos(lat) * np.cos(lon)
        c = self.observer.radius**2 - self.rsun**2
        b = -2 * self.observer.radius * cos_alpha
        # Ignore sqrt of NaNs
        with np.errstate(invalid='ignore'):
            d = ((-1 * b) -
                 np.sqrt(b**2 - 4 * c)) / 2  # use the "near" solution

        if self._spherical_screen:
            sphere_center = self._spherical_screen['center'].transform_to(
                self).cartesian
            c = sphere_center.norm()**2 - self._spherical_screen['radius']**2
            b = -2 * sphere_center.dot(rep)
            # Ignore sqrt of NaNs
            with np.errstate(invalid='ignore'):
                dd = ((-1 * b) +
                      np.sqrt(b**2 - 4 * c)) / 2  # use the "far" solution

            d = np.fmin(d,
                        dd) if self._spherical_screen['only_off_disk'] else dd

        return self.realize_frame(
            SphericalRepresentation(lon=lon, lat=lat, distance=d))
Ejemplo n.º 21
0
def hci_to_hgs(hcicoord, hgsframe):
    """
    Convert from Heliocentric Inertial to Heliographic Stonyhurst
    """
    # First transform the HCI coord to the HGS obstime
    int_coord = _transform_obstime(hcicoord, hgsframe.obstime)

    if int_coord.obstime is None:
        raise ConvertError("To perform this transformation, the coordinate"
                           " frame needs a specified `obstime`.")

    # Rotate from HCI to HGS
    total_matrix = matrix_transpose(_rotation_matrix_hgs_to_hci(int_coord.obstime))
    newrepr = int_coord.cartesian.transform(total_matrix)

    return hgsframe._replicate(newrepr, obstime=int_coord.obstime)
Ejemplo n.º 22
0
def hme_to_hee(hmecoord, heeframe):
    """
    Convert from Heliocentric Mean Ecliptic to Heliocentric Earth Ecliptic
    """
    if heeframe.obstime is None:
        raise ConvertError("To perform this transformation, the coordinate"
                           " frame needs a specified `obstime`.")

    # Convert to the HME frame with mean equinox of date at the HEE obstime, through HCRS
    int_frame = HeliocentricMeanEcliptic(obstime=heeframe.obstime, equinox=heeframe.obstime)
    int_coord = hmecoord.transform_to(HCRS(obstime=hmecoord.obstime)).transform_to(int_frame)

    # Rotate the intermediate coord to the HEE frame
    total_matrix = _rotation_matrix_hme_to_hee(int_frame)
    newrepr = int_coord.cartesian.transform(total_matrix)

    return heeframe.realize_frame(newrepr)
Ejemplo n.º 23
0
def hee_to_hme(heecoord, hmeframe):
    """
    Convert from Heliocentric Earth Ecliptic to Heliocentric Mean Ecliptic
    """
    if heecoord.obstime is None:
        raise ConvertError("To perform this transformation, the coordinate"
                           " frame needs a specified `obstime`.")

    int_frame = HeliocentricMeanEcliptic(obstime=heecoord.obstime, equinox=heecoord.obstime)

    # Rotate the HEE coord to the intermediate frame
    total_matrix = matrix_transpose(_rotation_matrix_hme_to_hee(int_frame))
    int_repr = heecoord.cartesian.transform(total_matrix)
    int_coord = int_frame.realize_frame(int_repr)

    # Convert to the HME frame through HCRS
    return int_coord.transform_to(HCRS(obstime=int_coord.obstime)).transform_to(hmeframe)
Ejemplo n.º 24
0
def hcc_to_hgs(helioccoord, heliogframe):
    """
    Convert from Heliocentric Cartesian to Heliographic Stonyhurst.
    """
    if not isinstance(helioccoord.observer, BaseCoordinateFrame):
        raise ConvertError("Cannot transform heliocentric coordinates to "
                           "heliographic coordinates for observer '{}' "
                           "without `obstime` being specified.".format(helioccoord.observer))

    total_matrix = _rotation_matrix_hcc_to_hgs(helioccoord.observer.lon, helioccoord.observer.lat)

    # Transform from HCC to HGS at the HCC obstime
    newrepr = helioccoord.cartesian.transform(total_matrix)
    int_coord = HeliographicStonyhurst(newrepr, obstime=helioccoord.obstime)

    # Loopback transform HGS if there is a change in obstime
    return _transform_obstime(int_coord, heliogframe.obstime)
Ejemplo n.º 25
0
def hgs_to_hcc(heliogcoord, heliocframe):
    """
    Convert from Heliographic Stonyhurst to Heliocentric Cartesian.
    """
    if not isinstance(heliocframe.observer, BaseCoordinateFrame):
        raise ConvertError("Cannot transform heliographic coordinates to "
                           "heliocentric coordinates for observer '{}' "
                           "without `obstime` being specified.".format(heliocframe.observer))

    # Loopback transform HGS if there is a change in obstime
    int_coord = _transform_obstime(heliogcoord, heliocframe.obstime)

    total_matrix = matrix_transpose(_rotation_matrix_hcc_to_hgs(heliocframe.observer.lon,
                                                                heliocframe.observer.lat))

    # Transform from HGS to HCC at the same obstime
    newrepr = int_coord.cartesian.transform(total_matrix)
    return heliocframe.realize_frame(newrepr)
Ejemplo n.º 26
0
def hgs_to_hcc(heliogcoord, heliocframe):
    """
    Convert from Heliographic Stonyhurst to Heliocentric Cartesian.
    """
    # Import moved here from top of file to lessen the impact of issue #2580
    # TODO: Revert this.
    from astropy.tests.helper import quantity_allclose
    hglon = heliogcoord.lon
    hglat = heliogcoord.lat
    r = heliogcoord.radius
    if r.unit is u.one and quantity_allclose(r, 1 * u.one):
        r = np.ones_like(r)
        r *= RSUN_METERS

    if not isinstance(heliocframe.observer, BaseCoordinateFrame):
        raise ConvertError("Cannot transform heliographic coordinates to "
                           "heliocentric coordinates for observer '{}' "
                           "without `obstime` being specified.".format(
                               heliocframe.observer))

    l0_rad = heliocframe.observer.lon.to(u.rad)
    b0_deg = heliocframe.observer.lat

    lon = np.deg2rad(hglon)
    lat = np.deg2rad(hglat)

    cosb = np.cos(b0_deg.to(u.rad))
    sinb = np.sin(b0_deg.to(u.rad))

    lon = lon - l0_rad

    cosx = np.cos(lon)
    sinx = np.sin(lon)
    cosy = np.cos(lat)
    siny = np.sin(lat)

    x = r * cosy * sinx
    y = r * (siny * cosb - cosy * cosx * sinb)
    zz = r * (siny * sinb + cosy * cosx * cosb)

    representation = CartesianRepresentation(x.to(u.km), y.to(u.km),
                                             zz.to(u.km))

    return heliocframe.realize_frame(representation)
Ejemplo n.º 27
0
def hgs_to_hci(hgscoord, hciframe):
    """
    Convert from Heliographic Stonyhurst to Heliocentric Inertial
    """

    hgscoord = hgscoord.make_3d()

    # First transform the HGS coord to the HCI obstime
    int_coord = _transform_obstime(hgscoord, hciframe.obstime)

    if int_coord.obstime is None:
        raise ConvertError("To perform this transformation, the coordinate"
                           " frame needs a specified `obstime`.")

    # Rotate from HGS to HCI
    total_matrix = _rotation_matrix_hgs_to_hci(int_coord.obstime)
    newrepr = int_coord.cartesian.transform(total_matrix)

    return hciframe._replicate(newrepr, obstime=int_coord.obstime)
Ejemplo n.º 28
0
def _rotation_matrix_hgs_to_hgc(obstime, observer_distance_from_sun):
    """
    Return the rotation matrix from HGS to HGC at the same observation time
    """
    if obstime is None:
        raise ConvertError("To perform this transformation, the coordinate"
                           " frame needs a specified `obstime`.")

    # Import here to avoid a circular import
    from .sun import L0, earth_distance

    # Calculate the difference in light travel time if the observer is at a different distance from
    # the Sun than the Earth is
    delta_time = (observer_distance_from_sun - earth_distance(obstime)) / speed_of_light

    # Calculate the corresponding difference in apparent longitude
    delta_lon = delta_time * constants.sidereal_rotation_rate

    # Rotation is only in longitude, so only around the Z axis
    return rotation_matrix(-(L0(obstime) + delta_lon), 'z')
Ejemplo n.º 29
0
def hgs_to_hcc(heliogcoord, heliocframe):
    """
    Convert from Heliographic Stonyhurst to Heliograpic Carrington.
    """
    hglon = heliogcoord.lon
    hglat = heliogcoord.lat
    r = heliogcoord.radius.to(u.m)

    if heliocframe.obstime is None:
        heliocframe._obstime = heliogcoord.obstime

    if not isinstance(heliocframe.observer, BaseCoordinateFrame):
        raise ConvertError("Cannot transform heliographic coordinates to "
                           "heliocentric coordinates for observer '{}' "
                           "without `obstime` being specified.".format(
                               heliocframe.observer))

    l0_rad = heliocframe.observer.lon.to(u.rad)
    b0_deg = heliocframe.observer.lat

    lon = np.deg2rad(hglon)
    lat = np.deg2rad(hglat)

    cosb = np.cos(b0_deg.to(u.rad))
    sinb = np.sin(b0_deg.to(u.rad))

    lon = lon - l0_rad

    cosx = np.cos(lon)
    sinx = np.sin(lon)
    cosy = np.cos(lat)
    siny = np.sin(lat)

    x = r * cosy * sinx
    y = r * (siny * cosb - cosy * cosx * sinb)
    zz = r * (siny * sinb + cosy * cosx * cosb)

    representation = CartesianRepresentation(x.to(u.km), y.to(u.km),
                                             zz.to(u.km))

    return heliocframe.realize_frame(representation)
Ejemplo n.º 30
0
def hgs_to_hcc(heliogcoord, heliocframe):
    """
    Convert from Heliographic Stonyhurst to Heliocentric Cartesian.
    """
    hglon = heliogcoord.spherical.lon
    hglat = heliogcoord.spherical.lat
    r = heliogcoord.spherical.distance
    if r.unit is u.one and u.allclose(r, 1 * u.one):
        r = np.ones_like(r)
        r *= RSUN_METERS

    if not isinstance(heliocframe.observer, BaseCoordinateFrame):
        raise ConvertError("Cannot transform heliographic coordinates to "
                           "heliocentric coordinates for observer '{}' "
                           "without `obstime` being specified.".format(
                               heliocframe.observer))

    l0_rad = heliocframe.observer.lon.to(u.rad)
    b0_deg = heliocframe.observer.lat

    lon = np.deg2rad(hglon)
    lat = np.deg2rad(hglat)

    cosb = np.cos(b0_deg.to(u.rad))
    sinb = np.sin(b0_deg.to(u.rad))

    lon = lon - l0_rad

    cosx = np.cos(lon)
    sinx = np.sin(lon)
    cosy = np.cos(lat)
    siny = np.sin(lat)

    x = r * cosy * sinx
    y = r * (siny * cosb - cosy * cosx * sinb)
    zz = r * (siny * sinb + cosy * cosx * cosb)

    representation = CartesianRepresentation(x.to(u.km), y.to(u.km),
                                             zz.to(u.km))

    return heliocframe.realize_frame(representation)