def fk4_to_fk4_no_e(fk4coord, fk4noeframe): # Extract cartesian vector rep = fk4coord.cartesian # Find distance (for re-normalization) d_orig = rep.norm() rep /= d_orig # Apply E-terms of aberration. Note that this depends on the equinox (not # the observing time/epoch) of the coordinates. See issue #1496 for a # discussion of this. eterms_a = CartesianRepresentation( u.Quantity(fk4_e_terms(fk4coord.equinox), u.dimensionless_unscaled, copy=False), copy=False) rep = rep - eterms_a + eterms_a.dot(rep) * rep # Find new distance (for re-normalization) d_new = rep.norm() # Renormalize rep *= d_orig / d_new # now re-cast into an appropriate Representation, and precess if need be if isinstance(fk4coord.data, UnitSphericalRepresentation): rep = rep.represent_as(UnitSphericalRepresentation) # if no obstime was given in the new frame, use the old one for consistency newobstime = fk4coord._obstime if fk4noeframe._obstime is None else fk4noeframe._obstime fk4noe = FK4NoETerms(rep, equinox=fk4coord.equinox, obstime=newobstime) if fk4coord.equinox != fk4noeframe.equinox: # precession fk4noe = fk4noe.transform_to(fk4noeframe) return fk4noe
def _sun_north_angle_to_z(frame): """ Return the angle between solar north and the Z axis of the provided frame's coordinate system and observation time. """ # Find the Sun center in HGS at the frame's observation time(s) sun_center_repr = SphericalRepresentation(0*u.deg, 0*u.deg, 0*u.km) # The representation is repeated for as many times as are in obstime prior to transformation sun_center = SkyCoord(sun_center_repr._apply('repeat', frame.obstime.size), frame=HGS, obstime=frame.obstime) # Find the Sun north in HGS at the frame's observation time(s) # Only a rough value of the solar radius is needed here because, after the cross product, # only the direction from the Sun center to the Sun north pole matters sun_north_repr = SphericalRepresentation(0*u.deg, 90*u.deg, 690000*u.km) # The representation is repeated for as many times as are in obstime prior to transformation sun_north = SkyCoord(sun_north_repr._apply('repeat', frame.obstime.size), frame=HGS, obstime=frame.obstime) # Find the Sun center and Sun north in the frame's coordinate system sky_normal = sun_center.transform_to(frame).data.to_cartesian() sun_north = sun_north.transform_to(frame).data.to_cartesian() # Use cross products to obtain the sky projections of the two vectors (rotated by 90 deg) sun_north_in_sky = sun_north.cross(sky_normal) z_in_sky = CartesianRepresentation(0, 0, 1).cross(sky_normal) # Normalize directional vectors sky_normal /= sky_normal.norm() sun_north_in_sky /= sun_north_in_sky.norm() z_in_sky /= z_in_sky.norm() # Calculate the signed angle between the two projected vectors cos_theta = sun_north_in_sky.dot(z_in_sky) sin_theta = sun_north_in_sky.cross(z_in_sky).dot(sky_normal) angle = np.arctan2(sin_theta, cos_theta).to('deg') # If there is only one time, this function's output should be scalar rather than array if angle.size == 1: angle = angle[0] return Angle(angle)
def _rotation_matrix_hgs_to_hci(obstime): """ Return the rotation matrix from HGS to HCI at the same observation time """ z_axis = CartesianRepresentation(0, 0, 1) * u.m if not obstime.isscalar: z_axis = z_axis._apply('repeat', obstime.size) # Get the ecliptic pole in HGS ecliptic_pole = HeliocentricMeanEcliptic(z_axis, obstime=obstime, equinox=_J2000) ecliptic_pole_hgs = ecliptic_pole.transform_to( HeliographicStonyhurst(obstime=obstime)) # Rotate the ecliptic pole to the -YZ plane, which aligns the solar ascending node with the X # axis rot_matrix = _rotation_matrix_reprs_to_xz_about_z( ecliptic_pole_hgs.cartesian) xz_to_yz_matrix = rotation_matrix(-90 * u.deg, 'z') return xz_to_yz_matrix @ rot_matrix
def altaz_to_enu(altaz_coo, enu_frame): '''Defines the transformation between AltAz and the ENU frame. AltAz usually has units attached but ENU does not require units if it specifies a direction.''' is_directional = (isinstance(altaz_coo.data, UnitSphericalRepresentation) or altaz_coo.cartesian.x.unit == u.one) if is_directional: rep = CartesianRepresentation(x=altaz_coo.cartesian.y, y=altaz_coo.cartesian.x, z=altaz_coo.cartesian.z, copy=False) else: location_altaz = ITRS( *enu_frame.location.to_geocentric()).transform_to( AltAz(location=enu_frame.location, obstime=enu_frame.obstime)) rep = CartesianRepresentation( x=altaz_coo.cartesian.y - location_altaz.cartesian.y, y=altaz_coo.cartesian.x - location_altaz.cartesian.x, z=altaz_coo.cartesian.z - location_altaz.cartesian.z, copy=False) return enu_frame.realize_frame(rep)
def gcrs_to_icrs(gcrs_coo, icrs_frame): srepr = gcrs_coo.represent_as(SphericalRepresentation) gcrs_ra = srepr.lon.to_value(u.radian) gcrs_dec = srepr.lat.to_value(u.radian) # set up the astrometry context for ICRS<->GCRS and then convert to BCRS # coordinate direction obs_pv = pav2pv( gcrs_coo.obsgeoloc.get_xyz(xyz_axis=-1).to_value(u.m), gcrs_coo.obsgeovel.get_xyz(xyz_axis=-1).to_value(u.m / u.s)) jd1, jd2 = get_jd12(gcrs_coo.obstime, 'tdb') earth_pv, earth_heliocentric = prepare_earth_position_vel(gcrs_coo.obstime) astrom = erfa.apcs(jd1, jd2, obs_pv, earth_pv, earth_heliocentric) i_ra, i_dec = aticq(gcrs_ra, gcrs_dec, astrom) if gcrs_coo.data.get_name( ) == 'unitspherical' or gcrs_coo.data.to_cartesian().x.unit == u.one: # if no distance, just use the coordinate direction to yield the # infinite-distance/no parallax answer newrep = UnitSphericalRepresentation(lat=u.Quantity(i_dec, u.radian, copy=False), lon=u.Quantity(i_ra, u.radian, copy=False), copy=False) else: # When there is a distance, apply the parallax/offset to the SSB as the # last step - ensures round-tripping with the icrs_to_gcrs transform # the distance in intermedrep is *not* a real distance as it does not # include the offset back to the SSB intermedrep = SphericalRepresentation(lat=u.Quantity(i_dec, u.radian, copy=False), lon=u.Quantity(i_ra, u.radian, copy=False), distance=srepr.distance, copy=False) astrom_eb = CartesianRepresentation(astrom['eb'], unit=u.au, xyz_axis=-1, copy=False) newrep = intermedrep + astrom_eb return icrs_frame.realize_frame(newrep)
def fk4_no_e_to_fk4(fk4noecoord, fk4frame): # first precess, if necessary if fk4noecoord.equinox != fk4frame.equinox: fk4noe_w_fk4equinox = FK4NoETerms(equinox=fk4frame.equinox, obstime=fk4noecoord.obstime) fk4noecoord = fk4noecoord.transform_to(fk4noe_w_fk4equinox) # Extract cartesian vector rep = fk4noecoord.cartesian # Find distance (for re-normalization) d_orig = rep.norm() rep /= d_orig # Apply E-terms of aberration. Note that this depends on the equinox (not # the observing time/epoch) of the coordinates. See issue #1496 for a # discussion of this. eterms_a = CartesianRepresentation(u.Quantity(fk4_e_terms( fk4noecoord.equinox), u.dimensionless_unscaled, copy=False), copy=False) rep0 = rep.copy() for _ in range(10): rep = (eterms_a + rep0) / (1. + eterms_a.dot(rep)) # Find new distance (for re-normalization) d_new = rep.norm() # Renormalize rep *= d_orig / d_new # now re-cast into an appropriate Representation, and precess if need be if isinstance(fk4noecoord.data, UnitSphericalRepresentation): rep = rep.represent_as(UnitSphericalRepresentation) return fk4frame.realize_frame(rep)
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 ValueError("To perform this transformation the coordinate" " Frame needs an obstime Attribute") # Determine the Sun-Earth vector in ICRS # Since HCRS is ICRS with an origin shift, this is also the Sun-Earth vector in HCRS 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) # Remove the component of the Sun-Earth vector that is parallel to the Sun's north pole # (The additional transpose operations are to handle both scalar and array obstime situations) hgs_x_axis_detilt = CartesianRepresentation((sun_earth_detilt.xyz.T * [1, 1, 0]).T) # The above vector, which is in the Sun's equatorial plane, is also the X axis of HGS x_axis = CartesianRepresentation(1, 0, 0) if hgsframe.obstime.isscalar: rot_matrix = _make_rotation_matrix_from_reprs(hgs_x_axis_detilt, x_axis) else: rot_matrix_list = [_make_rotation_matrix_from_reprs(vect, x_axis) for vect in hgs_x_axis_detilt] rot_matrix = np.stack(rot_matrix_list) return matrix_product(rot_matrix, _SUN_DETILT_MATRIX)
def gse_to_hee(gsecoord, heeframe): """ Convert from Geocentric Solar Ecliptic to Heliocentric Earth Ecliptic """ # First transform the GSE coord to the HEE obstime int_coord = _transform_obstime(gsecoord, heeframe.obstime) if int_coord.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 earth_distance # Find the Sun-object vector in the intermediate frame earth_sun_int = earth_distance(int_coord.obstime) * CartesianRepresentation(1, 0, 0) sun_object_int = int_coord.cartesian - earth_sun_int # Flip the vector in X and Y, but leave Z untouched # (The additional transpose operations are to handle both scalar and array inputs) newrepr = CartesianRepresentation((sun_object_int.xyz.T * [-1, -1, 1]).T) return heeframe._replicate(newrepr, obstime=int_coord.obstime)
def icrs_to_cirs(icrs_coo, cirs_frame): # first set up the astrometry context for ICRS<->CIRS jd1, jd2 = get_jd12(cirs_frame.obstime, 'tt') x, y, s = get_cip(jd1, jd2) earth_pv, earth_heliocentric = prepare_earth_position_vel( cirs_frame.obstime) # erfa.apci requests TDB but TT can be used instead of TDB without any significant impact on accuracy astrom = erfa.apci(jd1, jd2, earth_pv, earth_heliocentric, x, y, s) if icrs_coo.data.get_name( ) == 'unitspherical' or icrs_coo.data.to_cartesian().x.unit == u.one: # if no distance, just do the infinite-distance/no parallax calculation usrepr = icrs_coo.represent_as(UnitSphericalRepresentation) i_ra = usrepr.lon.to_value(u.radian) i_dec = usrepr.lat.to_value(u.radian) cirs_ra, cirs_dec = atciqz(i_ra, i_dec, astrom) newrep = UnitSphericalRepresentation(lat=u.Quantity(cirs_dec, u.radian, copy=False), lon=u.Quantity(cirs_ra, u.radian, copy=False), copy=False) else: # When there is a distance, we first offset for parallax to get the # astrometric coordinate direction and *then* run the ERFA transform for # no parallax/PM. This ensures reversibility and is more sensible for # inside solar system objects astrom_eb = CartesianRepresentation(astrom['eb'], unit=u.au, xyz_axis=-1, copy=False) newcart = icrs_coo.cartesian - astrom_eb srepr = newcart.represent_as(SphericalRepresentation) i_ra = srepr.lon.to_value(u.radian) i_dec = srepr.lat.to_value(u.radian) cirs_ra, cirs_dec = atciqz(i_ra, i_dec, astrom) newrep = SphericalRepresentation(lat=u.Quantity(cirs_dec, u.radian, copy=False), lon=u.Quantity(cirs_ra, u.radian, copy=False), distance=srepr.distance, copy=False) return cirs_frame.realize_frame(newrep)
def observed_to_icrs(observed_coo, icrs_frame): # if the data are UnitSphericalRepresentation, we can skip the distance calculations is_unitspherical = (isinstance(observed_coo.data, UnitSphericalRepresentation) or observed_coo.cartesian.x.unit == u.one) usrepr = observed_coo.represent_as(UnitSphericalRepresentation) lon = usrepr.lon.to_value(u.radian) lat = usrepr.lat.to_value(u.radian) if isinstance(observed_coo, AltAz): # the 'A' indicates zen/az inputs coord_type = 'A' lat = PIOVER2 - lat else: coord_type = 'H' # first set up the astrometry context for ICRS<->CIRS at the observed_coo time astrom = erfa_astrom.get().apco(observed_coo) # Topocentric CIRS cirs_ra, cirs_dec = erfa.atoiq(coord_type, lon, lat, astrom) << u.radian if is_unitspherical: srepr = SphericalRepresentation(cirs_ra, cirs_dec, 1, copy=False) else: srepr = SphericalRepresentation(lon=cirs_ra, lat=cirs_dec, distance=observed_coo.distance, copy=False) # BCRS (Astrometric) direction to source bcrs_ra, bcrs_dec = aticq(srepr, astrom) << u.radian # Correct for parallax to get ICRS representation if is_unitspherical: icrs_srepr = UnitSphericalRepresentation(bcrs_ra, bcrs_dec, copy=False) else: icrs_srepr = SphericalRepresentation(lon=bcrs_ra, lat=bcrs_dec, distance=observed_coo.distance, copy=False) observer_icrs = CartesianRepresentation(astrom['eb'], unit=u.au, xyz_axis=-1, copy=False) newrepr = icrs_srepr.to_cartesian() + observer_icrs icrs_srepr = newrepr.represent_as(SphericalRepresentation) return icrs_frame.realize_frame(icrs_srepr)
def fk4_to_fk4_no_e(fk4coord, fk4noeframe): # Extract cartesian vector rep = fk4coord.cartesian # Find distance (for re-normalization) d_orig = rep.norm() rep /= d_orig # Apply E-terms of aberration. Note that this depends on the equinox (not # the observing time/epoch) of the coordinates. See issue #1496 for a # discussion of this. eterms_a = CartesianRepresentation(u.Quantity(fk4_e_terms( fk4coord.equinox), u.dimensionless_unscaled, copy=False), copy=False) rep = rep - eterms_a + eterms_a.dot(rep) * rep # Find new distance (for re-normalization) d_new = rep.norm() # Renormalize rep *= d_orig / d_new # now re-cast into an appropriate Representation, and precess if need be if isinstance(fk4coord.data, UnitSphericalRepresentation): rep = rep.represent_as(UnitSphericalRepresentation) # if no obstime was given in the new frame, use the old one for consistency newobstime = fk4coord._obstime if fk4noeframe._obstime is None else fk4noeframe._obstime fk4noe = FK4NoETerms(rep, equinox=fk4coord.equinox, obstime=newobstime) if fk4coord.equinox != fk4noeframe.equinox: # precession fk4noe = fk4noe.transform_to(fk4noeframe) return fk4noe
def fk4_no_e_to_fk4(fk4noecoord, fk4frame): # first precess, if necessary if fk4noecoord.equinox != fk4frame.equinox: fk4noe_w_fk4equinox = FK4NoETerms(equinox=fk4frame.equinox, obstime=fk4noecoord.obstime) fk4noecoord = fk4noecoord.transform_to(fk4noe_w_fk4equinox) # Extract cartesian vector rep = fk4noecoord.cartesian # Find distance (for re-normalization) d_orig = rep.norm() rep /= d_orig # Apply E-terms of aberration. Note that this depends on the equinox (not # the observing time/epoch) of the coordinates. See issue #1496 for a # discussion of this. eterms_a = CartesianRepresentation( u.Quantity(fk4_e_terms(fk4noecoord.equinox), u.dimensionless_unscaled, copy=False), copy=False) rep0 = rep.copy() for _ in range(10): rep = (eterms_a + rep0) / (1. + eterms_a.dot(rep)) # Find new distance (for re-normalization) d_new = rep.norm() # Renormalize rep *= d_orig / d_new # now re-cast into an appropriate Representation, and precess if need be if isinstance(fk4noecoord.data, UnitSphericalRepresentation): rep = rep.represent_as(UnitSphericalRepresentation) return fk4frame.realize_frame(rep)
def _rotation_matrix_hme_to_hee(hmeframe): """ Return the rotation matrix from HME to HEE at the same observation time """ # Get the Sun-Earth vector sun_earth = HCRS(_sun_earth_icrf(hmeframe.obstime), obstime=hmeframe.obstime) sun_earth_hme = sun_earth.transform_to(hmeframe).cartesian # 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_hme) # Tilt the rotated Sun-Earth vector so that it is aligned with the X axis tilt_matrix = _rotation_matrix_reprs_to_reprs(sun_earth_hme.transform(rot_matrix), CartesianRepresentation(1, 0, 0)) return matrix_product(tilt_matrix, rot_matrix)
def gcrs_to_hcrs(gcrs_coo, hcrs_frame): if np.any(gcrs_coo.obstime != hcrs_frame.obstime): # if they GCRS obstime and HCRS obstime are not the same, we first # have to move to a GCRS where they are. frameattrs = gcrs_coo.get_frame_attr_names() frameattrs['obstime'] = hcrs_frame.obstime gcrs_coo = gcrs_coo.transform_to(GCRS(**frameattrs)) srepr = gcrs_coo.represent_as(SphericalRepresentation) gcrs_ra = srepr.lon.to_value(u.radian) gcrs_dec = srepr.lat.to_value(u.radian) # set up the astrometry context for ICRS<->GCRS and then convert to ICRS # coordinate direction astrom = erfa_astrom.get().apcs(gcrs_coo) i_ra, i_dec = aticq(gcrs_ra, gcrs_dec, astrom) # convert to Quantity objects i_ra = u.Quantity(i_ra, u.radian, copy=False) i_dec = u.Quantity(i_dec, u.radian, copy=False) if gcrs_coo.data.get_name() == 'unitspherical' or gcrs_coo.data.to_cartesian().x.unit == u.one: # if no distance, just use the coordinate direction to yield the # infinite-distance/no parallax answer newrep = UnitSphericalRepresentation(lat=i_dec, lon=i_ra, copy=False) else: # When there is a distance, apply the parallax/offset to the # Heliocentre as the last step to ensure round-tripping with the # hcrs_to_gcrs transform # Note that the distance in intermedrep is *not* a real distance as it # does not include the offset back to the Heliocentre intermedrep = SphericalRepresentation(lat=i_dec, lon=i_ra, distance=srepr.distance, copy=False) # astrom['eh'] and astrom['em'] contain Sun to observer unit vector, # and distance, respectively. Shapes are (X) and (X,3), where (X) is the # shape resulting from broadcasting the shape of the times object # against the shape of the pv array. # broadcast em to eh and scale eh eh = astrom['eh'] * astrom['em'][..., np.newaxis] eh = CartesianRepresentation(eh, unit=u.au, xyz_axis=-1, copy=False) newrep = intermedrep.to_cartesian() + eh return hcrs_frame.realize_frame(newrep)
def cirs_to_icrs(cirs_coo, icrs_frame): srepr = cirs_coo.represent_as(SphericalRepresentation) cirs_ra = srepr.lon.to_value(u.radian) cirs_dec = srepr.lat.to_value(u.radian) # set up the astrometry context for ICRS<->cirs and then convert to # astrometric coordinate direction jd1, jd2 = get_jd12(cirs_coo.obstime, 'tt') x, y, s = get_cip(jd1, jd2) earth_pv, earth_heliocentric = prepare_earth_position_vel(cirs_coo.obstime) # erfa.apci requests TDB but TT can be used instead of TDB without any significant impact on accuracy astrom = erfa.apci(jd1, jd2, earth_pv, earth_heliocentric, x, y, s) i_ra, i_dec = aticq(cirs_ra, cirs_dec, astrom) if cirs_coo.data.get_name( ) == 'unitspherical' or cirs_coo.data.to_cartesian().x.unit == u.one: # if no distance, just use the coordinate direction to yield the # infinite-distance/no parallax answer newrep = UnitSphericalRepresentation(lat=u.Quantity(i_dec, u.radian, copy=False), lon=u.Quantity(i_ra, u.radian, copy=False), copy=False) else: # When there is a distance, apply the parallax/offset to the SSB as the # last step - ensures round-tripping with the icrs_to_cirs transform # the distance in intermedrep is *not* a real distance as it does not # include the offset back to the SSB intermedrep = SphericalRepresentation(lat=u.Quantity(i_dec, u.radian, copy=False), lon=u.Quantity(i_ra, u.radian, copy=False), distance=srepr.distance, copy=False) astrom_eb = CartesianRepresentation(astrom['eb'], unit=u.au, xyz_axis=-1, copy=False) newrep = intermedrep + astrom_eb return icrs_frame.realize_frame(newrep)
def hcc_to_hpc(helioccoord, heliopframe): """ Convert from Heliocentric Cartesian to Helioprojective Cartesian. """ # Loopback transform HCC coord to obstime and observer of HPC frame int_frame = Heliocentric(obstime=heliopframe.obstime, observer=heliopframe.observer) int_coord = helioccoord.transform_to(int_frame) # Shift the origin from the Sun to the observer distance = int_coord.observer.radius newrepr = int_coord.cartesian - CartesianRepresentation(0*u.m, 0*u.m, distance) # Permute/swap axes from HCC to HPC equivalent Cartesian newrepr = newrepr.transform(_matrix_hcc_to_hpc()) # Explicitly represent as spherical because external code (e.g., wcsaxes) expects it return heliopframe.realize_frame(newrepr.represent_as(SphericalRepresentation))
def icrs_to_gcrs(icrs_coo, gcrs_frame): # first set up the astrometry context for ICRS<->GCRS. There are a few steps... # get the position and velocity arrays for the observatory. Need to # have xyz in last dimension, and pos/vel in one-but-last. # (Note could use np.stack once our minimum numpy version is >=1.10.) obs_pv = erfa.pav2pv( gcrs_frame.obsgeoloc.get_xyz(xyz_axis=-1).to_value(u.m), gcrs_frame.obsgeovel.get_xyz(xyz_axis=-1).to_value(u.m/u.s)) # find the position and velocity of earth jd1, jd2 = get_jd12(gcrs_frame.obstime, 'tdb') earth_pv, earth_heliocentric = prepare_earth_position_vel(gcrs_frame.obstime) # get astrometry context object, astrom. astrom = erfa.apcs(jd1, jd2, obs_pv, earth_pv, earth_heliocentric) if icrs_coo.data.get_name() == 'unitspherical' or icrs_coo.data.to_cartesian().x.unit == u.one: # if no distance, just do the infinite-distance/no parallax calculation usrepr = icrs_coo.represent_as(UnitSphericalRepresentation) i_ra = usrepr.lon.to_value(u.radian) i_dec = usrepr.lat.to_value(u.radian) gcrs_ra, gcrs_dec = atciqz(i_ra, i_dec, astrom) newrep = UnitSphericalRepresentation(lat=u.Quantity(gcrs_dec, u.radian, copy=False), lon=u.Quantity(gcrs_ra, u.radian, copy=False), copy=False) else: # When there is a distance, we first offset for parallax to get the # BCRS coordinate direction and *then* run the ERFA transform for no # parallax/PM. This ensures reversibility and is more sensible for # inside solar system objects astrom_eb = CartesianRepresentation(astrom['eb'], unit=u.au, xyz_axis=-1, copy=False) newcart = icrs_coo.cartesian - astrom_eb srepr = newcart.represent_as(SphericalRepresentation) i_ra = srepr.lon.to_value(u.radian) i_dec = srepr.lat.to_value(u.radian) gcrs_ra, gcrs_dec = atciqz(i_ra, i_dec, astrom) newrep = SphericalRepresentation(lat=u.Quantity(gcrs_dec, u.radian, copy=False), lon=u.Quantity(gcrs_ra, u.radian, copy=False), distance=srepr.distance, copy=False) return gcrs_frame.realize_frame(newrep)
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 test_czml_add_trajectory_raises_error_for_groundtrack_show(): start_epoch = iss.epoch end_epoch = iss.epoch + molniya.period sample_points = 10 x = u.Quantity([1.0, 2.0, 3.0], u.m) y = u.Quantity([4.0, 5.0, 6.0], u.m) z = u.Quantity([7.0, 8.0, 9.0], u.m) positions = CartesianRepresentation(x, y, z) time = ["2010-01-01T05:00:00", "2010-01-01T05:00:30", "2010-01-01T05:01:00"] epochs = Time(time, format="isot") extractor = CZMLExtractor(start_epoch, end_epoch, sample_points) with pytest.raises(NotImplementedError) as excinfo: extractor.add_trajectory(positions, epochs, groundtrack_show=True) assert "Ground tracking for trajectory not implemented yet" in excinfo.exconly()
def test_czml_raises_error_if_length_of_points_and_epochs_not_same(): start_epoch = iss.epoch end_epoch = iss.epoch + molniya.period sample_points = 10 color = [255, 255, 0] x = u.Quantity([1.0, 2.0, 3.0], u.m) y = u.Quantity([4.0, 5.0, 6.0], u.m) z = u.Quantity([7.0, 8.0, 9.0], u.m) positions = CartesianRepresentation(x, y, z) time = ["2010-01-01T05:00:00", "2010-01-01T05:00:30"] epochs = Time(time, format="isot") extractor = CZMLExtractor(start_epoch, end_epoch, sample_points) with pytest.raises(ValueError) as excinfo: extractor.add_trajectory(positions, epochs, label_text="Test", path_color=color) assert "Number of Points and Epochs must be equal." in excinfo.exconly()
def _transform_cartesian(representation, matrix): # Get xyz once since it's an expensive operation xyz = representation.xyz # Since the underlying data can be n-dimensional, reshape to a # 2-dimensional (3, N) array. vec = xyz.reshape((3, xyz.size // 3)) # Do the transformation vec_new = np.dot(np.asarray(matrix), vec) # Reshape to preserve the original shape subshape = xyz.shape[1:] x = vec_new[0].reshape(subshape) y = vec_new[1].reshape(subshape) z = vec_new[2].reshape(subshape) # Make a new representation and return return CartesianRepresentation(x, y, z)
def hee_to_gse(heecoord, gseframe): """ Convert from Heliocentric Earth Ecliptic to Geocentric Solar Ecliptic """ # Use an intermediate frame of HEE at the GSE observation time int_frame = HeliocentricEarthEcliptic(obstime=gseframe.obstime) int_coord = heecoord.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 # Flip the vector in X and Y, but leave Z untouched # (The additional transpose operations are to handle both scalar and array inputs) newrepr = CartesianRepresentation((earth_object_int.xyz.T * [-1, -1, 1]).T) return gseframe.realize_frame(newrepr)
def test_czml_add_trajectory(expected_doc_add_trajectory): start_epoch = iss.epoch end_epoch = iss.epoch + molniya.period sample_points = 10 color = [255, 255, 0] x = u.Quantity([1.0, 2.0, 3.0], u.m) y = u.Quantity([4.0, 5.0, 6.0], u.m) z = u.Quantity([7.0, 8.0, 9.0], u.m) positions = CartesianRepresentation(x, y, z) time = ["2010-01-01T05:00:00", "2010-01-01T05:00:30", "2010-01-01T05:01:00"] epochs = Time(time, format="isot") extractor = CZMLExtractor(start_epoch, end_epoch, sample_points) extractor.add_trajectory(positions, epochs, label_text="Test", path_color=color) assert repr(extractor.packets) == expected_doc_add_trajectory
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)
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 gcrs_to_icrs(gcrs_coo, icrs_frame): # set up the astrometry context for ICRS<->GCRS and then convert to BCRS # coordinate direction astrom = erfa_astrom.get().apcs(gcrs_coo) srepr = gcrs_coo.represent_as(SphericalRepresentation) i_ra, i_dec = aticq(srepr.without_differentials(), astrom) if gcrs_coo.data.get_name( ) == 'unitspherical' or gcrs_coo.data.to_cartesian().x.unit == u.one: # if no distance, just use the coordinate direction to yield the # infinite-distance/no parallax answer newrep = UnitSphericalRepresentation(lat=u.Quantity(i_dec, u.radian, copy=False), lon=u.Quantity(i_ra, u.radian, copy=False), copy=False) else: # When there is a distance, apply the parallax/offset to the SSB as the # last step - ensures round-tripping with the icrs_to_gcrs transform # the distance in intermedrep is *not* a real distance as it does not # include the offset back to the SSB intermedrep = SphericalRepresentation(lat=u.Quantity(i_dec, u.radian, copy=False), lon=u.Quantity(i_ra, u.radian, copy=False), distance=srepr.distance, copy=False) astrom_eb = CartesianRepresentation(astrom['eb'], unit=u.au, xyz_axis=-1, copy=False) newrep = intermedrep + astrom_eb return icrs_frame.realize_frame(newrep)
def icrs_to_gcrs(icrs_coo, gcrs_frame): # first set up the astrometry context for ICRS<->GCRS. astrom = erfa_astrom.get().apcs(gcrs_frame) if icrs_coo.data.get_name( ) == 'unitspherical' or icrs_coo.data.to_cartesian().x.unit == u.one: # if no distance, just do the infinite-distance/no parallax calculation srepr = icrs_coo.represent_as(SphericalRepresentation) gcrs_ra, gcrs_dec = atciqz(srepr.without_differentials(), astrom) newrep = UnitSphericalRepresentation(lat=u.Quantity(gcrs_dec, u.radian, copy=False), lon=u.Quantity(gcrs_ra, u.radian, copy=False), copy=False) else: # When there is a distance, we first offset for parallax to get the # BCRS coordinate direction and *then* run the ERFA transform for no # parallax/PM. This ensures reversibility and is more sensible for # inside solar system objects astrom_eb = CartesianRepresentation(astrom['eb'], unit=u.au, xyz_axis=-1, copy=False) newcart = icrs_coo.cartesian - astrom_eb srepr = newcart.represent_as(SphericalRepresentation) gcrs_ra, gcrs_dec = atciqz(srepr.without_differentials(), astrom) newrep = SphericalRepresentation(lat=u.Quantity(gcrs_dec, u.radian, copy=False), lon=u.Quantity(gcrs_ra, u.radian, copy=False), distance=srepr.distance, copy=False) return gcrs_frame.realize_frame(newrep)
def hpc_to_hcc(heliopcoord, heliocframe): """ Convert from Helioprojective Cartesian to Heliocentric Cartesian. """ 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.D0.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 load(self, filename): super(Solution, self).load(filename) f = h5py.File(filename, 'r') try: obstime = at.Time(f['TCI'].attrs['obstime'], format='gps', scale='tai') fixtime = at.Time(f['TCI'].attrs['fixtime'], format='gps', scale='tai') location = ac.ITRS().realize_frame( CartesianRepresentation(*(f['TCI'].attrs['location'] * au.km))) phase = ac.SkyCoord(*(f['TCI'].attrs['phase'] * au.deg), frame='icrs') pointing_frame = Pointing(location=location, obstime=obstime, phase=phase, fixtime=fixtime) except: pointing_frame = None f.close() self.__init__(pointing_frame=pointing_frame)
def icrs_to_observed(icrs_coo, observed_frame): # if the data are UnitSphericalRepresentation, we can skip the distance calculations is_unitspherical = (isinstance(icrs_coo.data, UnitSphericalRepresentation) or icrs_coo.cartesian.x.unit == u.one) # first set up the astrometry context for ICRS<->observed astrom = erfa_astrom.get().apco(observed_frame) # correct for parallax to find BCRS direction from observer (as in erfa.pmpx) if is_unitspherical: srepr = icrs_coo.spherical else: observer_icrs = CartesianRepresentation(astrom['eb'], unit=u.au, xyz_axis=-1, copy=False) srepr = (icrs_coo.cartesian - observer_icrs).represent_as(SphericalRepresentation) # convert to topocentric CIRS cirs_ra, cirs_dec = atciqz(srepr, astrom) # now perform observed conversion if isinstance(observed_frame, AltAz): lon, zen, _, _, _ = erfa.atioq(cirs_ra, cirs_dec, astrom) lat = PIOVER2 - zen else: _, _, lon, lat, _ = erfa.atioq(cirs_ra, cirs_dec, astrom) if is_unitspherical: obs_srepr = UnitSphericalRepresentation(lon << u.radian, lat << u.radian, copy=False) else: obs_srepr = SphericalRepresentation(lon << u.radian, lat << u.radian, srepr.distance, copy=False) return observed_frame.realize_frame(obs_srepr)
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 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 hpc_to_hcc(heliopcoord, heliocframe): """ Convert from Helioprojective Cartesian to Heliocentric Cartesian. """ _check_observer_defined(heliopcoord) _check_observer_defined(heliocframe) heliopcoord = heliopcoord.make_3d() # Permute/swap axes from HPC equivalent Cartesian to HCC newrepr = heliopcoord.cartesian.transform(matrix_transpose(_matrix_hcc_to_hpc())) # Transform the HPC observer (in HGS) to the HPC obstime in case it's different observer = _transform_obstime(heliopcoord.observer, heliopcoord.obstime) # Shift the origin from the observer to the Sun distance = 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=observer.obstime, observer=observer) # Loopback transform HCC as needed return int_coord.transform_to(heliocframe)