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()
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()
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
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
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}'.")
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.")
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)
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))
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)
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)
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)
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)
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)
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))
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)
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))
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
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)
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)
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))
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)
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)
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)
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)
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)
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)
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)
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')
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)
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)