Example #1
0
def reference_to_skyoffset_matrix(skyoffset_frame):
    """Make rotation matrix from reference frame and a skyoffset frame.

    this function is useful after using astropy to make a rotation matrix
    *modified from reference_to_skyoffset function in astropy

    Parameters
    ----------
    skyoffset_frame : SkyCoord frame
        the rotated frame
        note: SkyCoords are compatible

    Returns
    -------
    R : numpy array
        a 3d rotation matrix

    """
    origin = skyoffset_frame.origin.spherical

    mat1 = rotation_matrix(-skyoffset_frame.rotation, "x")
    mat2 = rotation_matrix(-origin.lat, "y")
    mat3 = rotation_matrix(origin.lon, "z")

    R = matrix_product(mat1, mat2, mat3)
    return R
Example #2
0
def reference_to_greatcircle(reference_frame, greatcircle_frame):
    """Convert a reference coordinate to a great circle frame."""

    # Define rotation matrices along the position angle vector, and
    # relative to the origin.
    pole = greatcircle_frame.pole.transform_to(coord.ICRS)
    ra0 = greatcircle_frame.ra0

    R_rot = rotation_matrix(greatcircle_frame.rotation, 'z')

    if np.isnan(ra0):
        R2 = rotation_matrix(pole.dec, 'y')
        R1 = rotation_matrix(pole.ra, 'z')
        R = matrix_product(R2, R1)

    else:
        xaxis = np.array([np.cos(ra0), np.sin(ra0), 0.])
        zaxis = pole.cartesian.xyz.value
        xaxis[2] = -(zaxis[0] * xaxis[0] +
                     zaxis[1] * xaxis[1]) / zaxis[2]  # what?
        xaxis = xaxis / np.sqrt(np.sum(xaxis**2))
        yaxis = np.cross(zaxis, xaxis)
        R = np.stack((xaxis, yaxis, zaxis))

    return matrix_product(R_rot, R)
Example #3
0
def camera_to_altaz(camera, altaz):
    if camera.pointing_direction is None:
        raise ValueError('Pointing Direction must not be None')

    x = camera.x.copy()
    y = camera.y.copy()

    if camera.rotated is True:
        x, y = y, -x

    z = 1 / np.sqrt(1 + (x / focal_length)**2 + (y / focal_length)**2)
    x *= z / focal_length
    y *= z / focal_length

    cartesian = CartesianRepresentation(x, y, z, copy=False)

    rot_z_az = rotation_matrix(-camera.pointing_direction.az, 'z')
    rot_y_zd = rotation_matrix(-camera.pointing_direction.zen, 'y')

    cartesian = cartesian.transform(rot_y_zd)
    cartesian = cartesian.transform(rot_z_az)

    altitude = 90 * u.deg - np.arccos(cartesian.z)
    azimuth = np.arctan2(cartesian.y, cartesian.x)

    return AltAz(
        alt=altitude,
        az=azimuth,
        location=camera.location,
        obstime=camera.obstime,
    )
Example #4
0
def fk4_to_gal(fk4coords, galframe):
    mat1 = rotation_matrix(180 - Galactic._lon0_B1950.degree, 'z')
    mat2 = rotation_matrix(90 - Galactic._ngp_B1950.dec.degree, 'y')
    mat3 = rotation_matrix(Galactic._ngp_B1950.ra.degree, 'z')
    matprec = fk4coords._precession_matrix(fk4coords.equinox, EQUINOX_B1950)

    return matrix_product(mat1, mat2, mat3, matprec)
Example #5
0
def fk4_to_gal(fk4coords, galframe):
    mat1 = rotation_matrix(180 - Galactic._lon0_B1950.degree, 'z')
    mat2 = rotation_matrix(90 - Galactic._ngp_B1950.dec.degree, 'y')
    mat3 = rotation_matrix(Galactic._ngp_B1950.ra.degree, 'z')
    matprec = fk4coords._precession_matrix(fk4coords.equinox, EQUINOX_B1950)

    return matrix_product(mat1, mat2, mat3, matprec)
Example #6
0
def altaz_to_camera(altaz, camera):
    if camera.pointing_direction is None:
        raise ValueError('Pointing Direction must not be None')

    cartesian = altaz.cartesian

    rot_z_az = rotation_matrix(camera.pointing_direction.az, 'z')
    rot_y_zd = rotation_matrix(camera.pointing_direction.zen, 'y')

    cartesian = cartesian.transform(rot_z_az)
    cartesian = cartesian.transform(rot_y_zd)

    x = (cartesian.x * focal_length / cartesian.z).copy()
    y = (cartesian.y * focal_length / cartesian.z).copy()

    if camera.rotated is True:
        x, y = -y, x

    return CameraFrame(
        x=x,
        y=y,
        pointing_direction=camera.pointing_direction,
        obstime=altaz.obstime,
        location=camera.location,
    )
Example #7
0
    def get_ksi_eta(self, time, star):
        """ Calculates relative position to star in the orthographic projection.

        Parameters:
            time (str, Time): Reference time to calculate the position.
                It can be a string in the format "yyyy-mm-dd hh:mm:ss.s" or an astropy Time object
            star (str, SkyCoord): The coordinate of the star in the same reference frame as the ephemeris.
                It can be a string in the format "hh mm ss.s +dd mm ss.ss"
                or an astropy SkyCoord object.

        Returns:
            ksi, eta (float): on-sky orthographic projection of the observer relative to a star
                Ksi is in the North-South direction (North positive)
                Eta is in the East-West direction (East positive)
        """
        time = test_attr(time, Time, 'time')
        try:
            star = SkyCoord(star, unit=(u.hourangle, u.deg))
        except:
            raise ValueError(
                'star is not an astropy object or a string in the format "hh mm ss.s +dd mm ss.ss"'
            )

        itrs = self.site.get_itrs(obstime=time)
        gcrs = itrs.transform_to(GCRS(obstime=time))
        rz = rotation_matrix(star.ra, 'z')
        ry = rotation_matrix(-star.dec, 'y')

        cp = gcrs.cartesian.transform(rz).transform(ry)
        return cp.y.to(u.km).value, cp.z.to(u.km).value
Example #8
0
    def reference_plane(self, time):
        """Compute the orbit at specified times in the two-body barycentric
        frame aligned with the reference plane coordinate system (XYZ).

        Parameters
        ----------
        time : array_like, `astropy.time.Time`
            Array of times as barycentric MJD values, or an Astropy
            `~astropy.time.Time` object containing the times to evaluate at.
        """

        xyz = self.orbital_plane(time)
        vxyz = xyz.differentials['s']
        xyz = xyz.without_differentials()

        # Construct rotation matrix to take the orbit from the orbital plane
        # system (xyz) to the reference plane system (XYZ):
        R1 = rotation_matrix(-self.omega, axis='z')
        R2 = rotation_matrix(self.i, axis='x')
        R3 = rotation_matrix(self.Omega, axis='z')
        Rot = matrix_product(R3, R2, R1)

        # Rotate to the reference plane system
        XYZ = coord.CartesianRepresentation(matrix_product(Rot, xyz.xyz))
        VXYZ = coord.CartesianDifferential(matrix_product(Rot, vxyz.d_xyz))
        XYZ = XYZ.with_differentials(VXYZ)

        kw = dict()
        if self.barycenter is not None:
            kw['origin'] = self.barycenter.origin
        return ReferencePlaneFrame(XYZ, **kw)
Example #9
0
def add_detector_on_earth(name,
                          longitude,
                          latitude,
                          yangle=0,
                          xangle=None,
                          height=0):
    """ Add a new detector on the earth

    Parameters
    ----------

    name: str
        two-letter name to identify the detector
    longitude: float
        Longitude in radians using geodetic coordinates of the detector
    latitude: float
        Latitude in radians using geodetic coordinates of the detector
    yangle: float
        Azimuthal angle of the y-arm (angle drawn from pointing north)
    xangle: float
        Azimuthal angle of the x-arm (angle drawn from point north). If not set
        we assume a right angle detector following the right-hand rule.
    height: float
        The height in meters of the detector above the standard
        reference ellipsoidal earth
    """
    if xangle is None:
        # assume right angle detector if no separate xarm direction given
        xangle = yangle + np.pi / 2.0

    # Calculate response in earth centered coordinates
    # by rotation of response in coordinates aligned
    # with the detector arms
    a, b = cos(2 * xangle), sin(2 * xangle)
    xresp = np.array([[-a, b, 0], [b, a, 0], [0, 0, 0]])
    a, b = cos(2 * yangle), sin(2 * yangle)
    yresp = np.array([[-a, b, 0], [b, a, 0], [0, 0, 0]])
    resp = (yresp - xresp) / 4.0

    rm1 = rotation_matrix(longitude * units.rad, 'z')
    rm2 = rotation_matrix((np.pi / 2.0 - latitude) * units.rad, 'y')
    rm = np.matmul(rm2, rm1)

    resp = np.matmul(resp, rm)
    resp = np.matmul(rm.T, resp)

    loc = coordinates.EarthLocation.from_geodetic(longitude * units.rad,
                                                  latitude * units.rad,
                                                  height=height * units.meter)
    loc = np.array([loc.x.value, loc.y.value, loc.z.value])
    _custom_ground_detectors[name] = {
        'location': loc,
        'response': resp,
        'yangle': yangle,
        'xangle': xangle,
        'height': height,
        'xaltitude': 0.0,
        'yaltitude': 0.0,
    }
Example #10
0
def fk5_to_gal(fk5coord, galframe):
    # need precess to J2000 first
    pmat = fk5coord._precession_matrix(fk5coord.equinox, EQUINOX_J2000)
    mat1 = rotation_matrix(180 - Galactic._lon0_J2000.degree, 'z')
    mat2 = rotation_matrix(90 - Galactic._ngp_J2000.dec.degree, 'y')
    mat3 = rotation_matrix(Galactic._ngp_J2000.ra.degree, 'z')

    return matrix_product(mat1, mat2, mat3, pmat)
Example #11
0
def fk5_to_gal(fk5coord, galframe):
    # need precess to J2000 first
    pmat = fk5coord._precession_matrix(fk5coord.equinox, EQUINOX_J2000)
    mat1 = rotation_matrix(180 - Galactic._lon0_J2000.degree, 'z')
    mat2 = rotation_matrix(90 - Galactic._ngp_J2000.dec.degree, 'y')
    mat3 = rotation_matrix(Galactic._ngp_J2000.ra.degree, 'z')

    return matrix_product(mat1, mat2, mat3, pmat)
Example #12
0
def reference_to_skyoffset_matrix(
    lon: T.Union[float, u.Quantity],
    lat: T.Union[float, u.Quantity],
    rotation: T.Union[float, u.Quantity],
) -> T.Sequence:
    """Convert a reference coordinate to an sky offset frame [astropy].

    Cartesian to Cartesian matrix transform.

    Parameters
    ----------
    lon : float or |AngleType| or |Quantity| instance
        For ICRS, the right ascension.
        If float, assumed degrees.
    lat : |AngleType| or |Quantity| instance
        For ICRS, the declination.
        If float, assumed degrees.
    rotation : |AngleType| or |Quantity| instance
        The final rotation of the frame about the ``origin``. The sign of
        the rotation is the left-hand rule.  That is, an object at a
        particular position angle in the un-rotated system will be sent to
        the positive latitude (z) direction in the final frame.
        If float, assumed degrees.

    Returns
    -------
    ndarray
        (3x3) matrix. rotates reference Cartesian to skyoffset Cartesian.

    See Also
    --------
    :func:`~astropy.coordinates.builtin.skyoffset.reference_to_skyoffset`

    References
    ----------
    .. [astropy] Astropy Collaboration, Robitaille, T., Tollerud, E.,
        Greenfield, P., Droettboom, M., Bray, E., Aldcroft, T., Davis,
        M., Ginsburg, A., Price-Whelan, A., Kerzendorf, W., Conley, A.,
        Crighton, N., Barbary, K., Muna, D., Ferguson, H., Grollier, F.,
        Parikh, M., Nair, P., Unther, H., Deil, C., Woillez, J.,
        Conseil, S., Kramer, R., Turner, J., Singer, L., Fox, R.,
        Weaver, B., Zabalza, V., Edwards, Z., Azalee Bostroem, K.,
        Burke, D., Casey, A., Crawford, S., Dencheva, N., Ely, J.,
        Jenness, T., Labrie, K., Lim, P., Pierfederici, F., Pontzen, A.,
        Ptak, A., Refsdal, B., Servillat, M., & Streicher, O. (2013).
        Astropy: A community Python package for astronomy.
        Astronomy and Astrophysics, 558, A33.

    """
    # Define rotation matrices along the position angle vector, and
    # relative to the origin.
    mat1 = rotation_matrix(-rotation, "x")
    mat2 = rotation_matrix(-lat, "y")
    mat3 = rotation_matrix(lon, "z")

    M = matrix_product(mat1, mat2, mat3)

    return M
Example #13
0
def reference_to_skyoffset(reference_frame, telescope_frame):
    '''Convert a reference coordinate to an sky offset frame.'''

    # Define rotation matrices along the position angle vector, and
    # relative to the telescope_pointing.
    telescope_pointing = telescope_frame.telescope_pointing.spherical
    mat1 = rotation_matrix(-telescope_pointing.lat, 'y')
    mat2 = rotation_matrix(telescope_pointing.lon, 'z')
    return matrix_product(mat1, mat2)
Example #14
0
def reference_to_skyoffset(reference_frame, telescope_frame):
    """Convert a reference coordinate to an sky offset frame."""

    # Define rotation matrices along the position angle vector, and
    # relative to the origin.
    origin = telescope_frame.origin.spherical
    mat1 = rotation_matrix(-origin.lat, 'y')
    mat2 = rotation_matrix(origin.lon, 'z')
    return matrix_product(mat1, mat2)
Example #15
0
def reference_to_skyoffset(reference_frame, telescope_frame):
    """Convert a reference coordinate to an sky offset frame."""

    # Define rotation matrices along the position angle vector, and
    # relative to the origin.
    origin = telescope_frame.origin.spherical
    mat1 = rotation_matrix(-origin.lat, "y")
    mat2 = rotation_matrix(origin.lon, "z")
    return matrix_product(mat1, mat2)
Example #16
0
    def reference_to_skyoffset(reference_frame, skyoffset_frame):
        """Convert a reference coordinate to an sky offset frame."""

        # Define rotation matrices along the position angle vector, and
        # relative to the origin.
        origin = skyoffset_frame.origin.spherical
        mat1 = rotation_matrix(-skyoffset_frame.rotation, 'x')
        mat2 = rotation_matrix(-origin.lat, 'y')
        mat3 = rotation_matrix(origin.lon, 'z')
        return matrix_product(mat1, mat2, mat3)
Example #17
0
def cb_crs_to_cb_j2000_eq(cb_crs_coord, _):
    """Conversion from Celestial Reference System of a Central Body
    to its Local Equatorial at J2000 Epoch Reference System."""

    ra, dec, w = celestial_body_rot_params(None, cb_crs_coord.body_name)

    body_crs_to_body_eq = matrix_product(
        rotation_matrix(90 * u.deg - dec, "x"),
        rotation_matrix(90 * u.deg + ra, "z"))

    return body_crs_to_body_eq
Example #18
0
def body_crs_to_body_eq_matrix(obstime, body_name):
    """Computes the rotation matrix from Celestial Body CRS to
    Local Equatorial True-of-Date Reference System."""
    ra, dec, w = celestial_body_rot_params(obstime, body_name)

    body_crs_to_body_eq = matrix_product(
        rotation_matrix(90 * u.deg - dec, "x"),
        rotation_matrix(90 * u.deg + ra, "z"),
    )

    return body_crs_to_body_eq
Example #19
0
def body_crs_to_body_fixed_matrix(obstime, body_name):
    """Computes the rotation matrix from Celestial Body CRS to
    Body Fixed Reference System."""
    ra, dec, w = celestial_body_rot_params(obstime, body_name)

    body_crs_to_body_fixed = matrix_product(
        rotation_matrix(w, "z"),
        rotation_matrix(90 * u.deg - dec, "x"),
        rotation_matrix(90 * u.deg + ra, "z"),
    )

    return body_crs_to_body_fixed
Example #20
0
def test_angle_axis():
    m1 = rotation_matrix(35*u.deg, 'x')
    an1, ax1 = angle_axis(m1)

    assert an1 - 35*u.deg < 1e-10*u.deg
    assert_allclose(ax1, [1, 0, 0])

    m2 = rotation_matrix(-89*u.deg, [1, 1, 0])
    an2, ax2 = angle_axis(m2)

    assert an2 - 89*u.deg < 1e-10*u.deg
    assert_allclose(ax2, [-2**-0.5, -2**-0.5, 0])
Example #21
0
def test_angle_axis():
    m1 = rotation_matrix(35 * u.deg, 'x')
    an1, ax1 = angle_axis(m1)

    assert an1 - 35 * u.deg < 1e-10 * u.deg
    assert_allclose(ax1, [1, 0, 0])

    m2 = rotation_matrix(-89 * u.deg, [1, 1, 0])
    an2, ax2 = angle_axis(m2)

    assert an2 - 89 * u.deg < 1e-10 * u.deg
    assert_allclose(ax2, [-2**-0.5, -2**-0.5, 0])
Example #22
0
def topo_frame_def(latitude, longitude, moon=True):
    """
    Make a list of strings defining a topocentric frame. This can then be loaded
    with spiceypy.lmpool.
    """

    if moon:
        idnum = 1301000
        station_name = 'LUNAR-TOPO'
        relative = 'MOON_ME'
    else:
        idnum = 1399000
        station_name = 'EARTH-TOPO'
        relative = 'ITRF93'

    # The DSS stations are built into SPICE, and they number up to 66.
    # We will call this station number 98.
    station_num = 98
    idnum += station_num
    fm_center_id = idnum - 1000000

    ecef_to_enu = np.matmul(
        rotation_matrix(-longitude, 'z', unit='deg'), rotation_matrix(latitude, 'y', unit='deg')
    ).T
    # Reorder the axes so that X,Y,Z = E,N,U
    ecef_to_enu = ecef_to_enu[[2, 1, 0]]

    mat = " ".join(map("{:.7f}".format, ecef_to_enu.flatten()))

    fmt_strs = [
        "FRAME_{1}                     = {0}",
        "FRAME_{0}_NAME                = '{1}'",
        "FRAME_{0}_CLASS                   = 4",
        "FRAME_{0}_CLASS_ID                = {0}",
        "FRAME_{0}_CENTER                  = {2}",
        "OBJECT_{2}_FRAME                   = '{1}'",
        "TKFRAME_{0}_RELATIVE          = '{3}'",
        "TKFRAME_{0}_SPEC              = 'MATRIX'",
        "TKFRAME_{0}_MATRIX            = {4}"
    ]

    frame_specs = [s.format(idnum, station_name, fm_center_id, relative, mat) for s in fmt_strs]

    frame_dict = {}

    for spec in frame_specs:
        k, v = map(str.strip, spec.split('='))
        frame_dict[k] = v

    latlon = ["{:.4f}".format(l) for l in [latitude, longitude]]

    return station_name, idnum, frame_dict, latlon
def icrs_to_arbpole(icrs_coord, arbpole_frame):

    roll = arbpole_frame.roll
    pole = arbpole_frame.pole

    # Align z(new) with direction to M31
    mat1 = rotation_matrix(-pole.dec, 'y')
    mat2 = rotation_matrix(pole.ra, 'z')
    mat3 = rotation_matrix(roll, 'z')
    mat4 = rotation_matrix(90 * u.degree, 'y')
    R = matrix_product(mat4, mat1, mat2, mat3)

    return R
Example #24
0
def _get_matrix_vectors(gal_frame, inverse=False):
    """
    Utility function: use the ``inverse`` argument to get the inverse transformation, matrix and
    offsets to go from external galaxy frame to ICRS.
    """
    # this is based on the astropy Galactocentric class code
    # shorthand
    gcf = gal_frame

    # rotation matrix to align x(ICRS) with the vector to the galaxy center
    mat0 = np.array([[0., 1., 0.],
                     [0., 0., 1.],
                     [1., 0., 0.]])   # relabel axes so x points in RA, y in dec, z away from us
    mat1 = rotation_matrix(-gcf.gal_coord.dec, 'y')
    mat2 = rotation_matrix(gcf.gal_coord.ra, 'z')

    # construct transformation matrix and use it
    R = matrix_product(mat0, mat1, mat2)

    # Now define translation by distance to galaxy center - best defined in current sky coord system defined by R
    translation = r.CartesianRepresentation(gcf.gal_distance * [0., 0., 1.])

    # Now rotate galaxy to right orientation
    pa_rot = rotation_matrix(-gcf.PA, 'z')
    inc_rot = rotation_matrix(gcf.inclination, 'y')
    H = matrix_product(inc_rot, pa_rot)

    # compute total matrices
    A = matrix_product(H, R)

    # Now we transform the translation vector between sky-aligned and galaxy-aligned frames
    offset = -translation.transform(H)

    if inverse:
        # the inverse of a rotation matrix is a transpose, which is much faster
        #   and more stable to compute
        A = matrix_transpose(A)
        offset = (-offset).transform(A)
        # galvel is given in sky-aligned coords, need to transform to ICRS, so use R transpose
        R = matrix_transpose(R)
        offset_v = r.CartesianDifferential.from_cartesian(
            (gcf.galvel_heliocentric).to_cartesian().transform(R))
        offset = offset.with_differentials(offset_v)

    else:
        # galvel is given in sky-aligned coords, need to transform to gal frame, so use H
        offset_v = r.CartesianDifferential.from_cartesian(
            (-gcf.galvel_heliocentric).to_cartesian().transform(H))
        offset = offset.with_differentials(offset_v)

    return A, offset
Example #25
0
def get_rot(fr, x0=0.):
    origin = get_origin(fr)
    usph_band = coord.UnitSphericalRepresentation(
        np.random.uniform(0, 360, 10000) * u.deg,
        np.random.uniform(-1, 1, size=10000) * u.deg)
    band_icrs = fr.realize_frame(usph_band).transform_to(coord.ICRS)

    R1 = rotation_matrix(origin.ra, 'z')
    R2 = rotation_matrix(-origin.dec, 'y')
    Rtmp = R2 @ R1

    roll = get_roll(band_icrs, Rtmp, x0)

    return [origin.ra.degree, origin.dec.degree, roll.degree]
Example #26
0
def _rotation_matrix_hcc_to_hgs(longitude, latitude):
    # Returns the rotation matrix from HCC to HGS based on the observer longitude and latitude

    # Permute the axes of HCC to match HGS Cartesian equivalent
    #   HGS_X = HCC_Z
    #   HGS_Y = HCC_X
    #   HGS_Z = HCC_Y
    axes_matrix = np.array([[0, 0, 1], [1, 0, 0], [0, 1, 0]])

    # Rotate in latitude and longitude (sign difference because of direction difference)
    lat_matrix = rotation_matrix(latitude, 'y')
    lon_matrix = rotation_matrix(-longitude, 'z')

    return lon_matrix @ lat_matrix @ axes_matrix
Example #27
0
    def rotate(self, axis_angle=None, rotmat=None, L_coords=None):
        """
        Rotate the source.

        The arguments correspond to different rotation types. If supplied
        together in one function call, they are applied in order: axis_angle,
        then rotmat, then L_coords.

        Parameters
        ----------
        axis_angle : 2-tuple
            First element one of 'x', 'y', 'z' for the axis to rotate about,
            second element an astropy.units.Quantity with dimensions of angle,
            indicating the angle to rotate through.
        rotmat : (3, 3) array-like
            Rotation matrix.
        L_coords : 2-tuple
            First element containing an inclination and second element an
            azimuthal angle (both astropy.units.Quantity instances with
            dimensions of angle). The routine will first attempt to identify
            a preferred plane based on the angular momenta of the central 1/3
            of particles in the source. This plane will then be rotated to lie
            in the 'y-z' plane, followed by a rotation by the azimuthal angle
            about its angular momentum pole (rotation about 'x'), and finally
            inclined (rotation about 'y').
        """

        do_rot = np.eye(3)

        if axis_angle is not None:
            do_rot = rotation_matrix(axis_angle[1],
                                     axis=axis_angle[0]).dot(do_rot)

        if rotmat is not None:
            do_rot = rotmat.dot(do_rot)

        if L_coords is not None:
            incl, az_rot = L_coords
            do_rot = L_align(self.coordinates_g.get_xyz(),
                             self.coordinates_g.differentials['s'].get_d_xyz(),
                             self.mHI_g,
                             frac=.3,
                             Laxis='x').dot(do_rot)
            do_rot = rotation_matrix(az_rot, axis='x').dot(do_rot)
            do_rot = rotation_matrix(incl, axis='y').dot(do_rot)

        self.current_rotation = do_rot.dot(self.current_rotation)
        self.coordinates_g = self.coordinates_g.transform(do_rot)
        return
Example #28
0
def _icrs_to_fk5_matrix():
    """
    B-matrix from USNO circular 179.  Used by the ICRS->FK5 transformation
    functions.
    """

    eta0 = -19.9 / 3600000.
    xi0 = 9.1 / 3600000.
    da0 = -22.9 / 3600000.

    m1 = rotation_matrix(-eta0, 'x')
    m2 = rotation_matrix(xi0, 'y')
    m3 = rotation_matrix(da0, 'z')

    return matrix_product(m1, m2, m3)
Example #29
0
def tip_axis(coord: UnitSphericalRepresentation, axis_lon: Angle,
             rot_angle: Angle) -> UnitSphericalRepresentation:
    """Perform a rotation about an axis perpendicular to the Z-axis.

    The purpose of this rotation is to move the pole of the coordinate system from one place to
    another. For example, transforming from a coordinate system where the pole is aligned with the
    physical pole of a mount to a topocentric coordinate system where the pole is aligned with
    zenith.

    Note that this is a true rotation, and the same rotation is applied to all coordinates in the
    originating coordinate system equally. It is not equivalent to using SkyCoord
    directional_offset_by() with a fixed position angle and separation since the direction and
    magnitude of the offset depend on the value of coord.

    Args:
        coord: Coordinate to be transformed.
        axis_lon: Longitude angle of the axis of rotation.
        rot_angle: Angle of rotation.

    Returns:
        Coordinate after transformation.
    """
    rot = rotation_matrix(rot_angle,
                          axis=SkyCoord(axis_lon, 0 *
                                        u.deg).represent_as('cartesian').xyz)
    coord_cart = coord.represent_as(CartesianRepresentation)
    coord_rot_cart = coord_cart.transform(rot)
    return coord_rot_cart.represent_as(UnitSphericalRepresentation)
Example #30
0
def wcs(target, xobj, yobj, pattern, a = 0, p = 0.25):
    from astropy.wcs import WCS
    from astropy.coordinates.matrix_utilities import rotation_matrix
    from astropy import units as u
    from astropy.coordinates import SkyCoord
    header = get_header(pattern)
    
    for filename in pattern:
        angle = a * u.deg
        plate = p * header['CCDXBIN']*u.arcsec
        rot_matrix = plate.to(u.deg) * rotation_matrix(angle)[:-1,:-1]
        #questa matrice orienta l'immagine in modo diverso!
        #mi pare che, per essere "in linea" con il catalogo, debba ruotare attorno all'asse x
        w = WCS(header)
        
        if 'CTYPE' in header and 'CRVAL' in header and 'CRPIX' in header and 'CD1_1 CD1_2' in header and 'CD2_1 CD2_2' in header and 'NAXIS' in header: #cerco WCS in header 
            pass
        else:
            w.wcs.ctype = ["RA---TAN", "DEC--TAN"]
            w.wcs.cd = w.wcs.cd = [[0, 0.00013888888888888889], [0.00013888888888888889, 0]]

            if 'RA' in header and 'DEC' in header:
                c = SkyCoord(header['RA'], header['DEC'], unit=(u.hourangle, u.deg),equinox="J2019.9")
                w.wcs.crval = [c.ra.degree, c.dec.degree]
                w.wcs.crpix = [header['NAXIS1']/2, header['NAXIS2']/2]
            else:
                o = get_obj(target, xobj, yobj, pattern)
                c = SkyCoord.from_name(o['obj'],equinox="J2019.9")
                w.wcs.crval = [c.ra.degree, c.dec.degree]
                w.wcs.crpix = [header['NAXIS1']/2, header['NAXIS2']/2] #o, in alternativa, xobj e yobj date in input
          
        header.extend(w.to_header(), update=True)
        return(w)
Example #31
0
def test_varying_transform_pc():
    varying_matrix_lt = [
        rotation_matrix(a)[:2, :2] for a in np.linspace(0, 90, 10)
    ] * u.arcsec

    vct = VaryingCelestialTransform(crpix=(5, 5) * u.pix,
                                    cdelt=(1, 1) * u.arcsec / u.pix,
                                    crval_table=(0, 0) * u.arcsec,
                                    pc_table=varying_matrix_lt,
                                    lon_pole=180 * u.deg)

    trans5 = vct.transform_at_index(5)
    assert isinstance(trans5, CompoundModel)

    # Verify that we have the 5th matrix in the series
    affine = trans5.left.left.right
    assert isinstance(affine, m.AffineTransformation2D)
    assert u.allclose(affine.matrix, varying_matrix_lt[5])
    # x.shape=(1,), y.shape=(1,), z.shape=(1,)
    pixel = (0 * u.pix, 0 * u.pix, 5 * u.pix)
    world = vct(*pixel)
    assert np.array(world[0]).shape == ()
    assert u.allclose(world, (359.99804329 * u.deg, 0.00017119 * u.deg))
    assert u.allclose(vct.inverse(*world, 5 * u.pix),
                      pixel[:2],
                      atol=0.01 * u.pix)
Example #32
0
def test_vct_shape_errors():
    pc_table = [rotation_matrix(a)[:2, :2]
                for a in np.linspace(0, 90, 15)] * u.arcsec
    pc_table = pc_table.reshape((5, 3, 2, 2))

    crval_table = list(zip(np.arange(1, 16), np.arange(16, 31))) * u.arcsec
    crval_table = crval_table.reshape((5, 3, 2))

    kwargs = dict(crpix=(5, 5) * u.pix,
                  cdelt=(1, 1) * u.arcsec / u.pix,
                  lon_pole=180 * u.deg)

    with pytest.raises(ValueError,
                       match="only be constructed with a one dimensional"):
        VaryingCelestialTransform(crval_table=crval_table,
                                  pc_table=pc_table,
                                  **kwargs)

    with pytest.raises(ValueError,
                       match="only be constructed with a one dimensional"):
        VaryingCelestialTransformSlit(crval_table=crval_table,
                                      pc_table=pc_table,
                                      **kwargs)

    with pytest.raises(ValueError,
                       match="only be constructed with a two dimensional"):
        VaryingCelestialTransform2D(crval_table=crval_table[0],
                                    pc_table=pc_table[0],
                                    **kwargs)

    with pytest.raises(ValueError,
                       match="only be constructed with a two dimensional"):
        VaryingCelestialTransformSlit2D(crval_table=crval_table[0],
                                        pc_table=pc_table[0],
                                        **kwargs)
Example #33
0
def test_vct_dispatch():
    varying_matrix_lt = [
        rotation_matrix(a)[:2, :2] for a in np.linspace(0, 90, 15)
    ] * u.arcsec
    varying_matrix_lt = varying_matrix_lt.reshape((5, 3, 2, 2))

    crval_table = list(zip(np.arange(1, 16), np.arange(16, 31))) * u.arcsec
    crval_table = crval_table.reshape((5, 3, 2))

    kwargs = dict(crpix=(5, 5) * u.pix,
                  cdelt=(1, 1) * u.arcsec / u.pix,
                  lon_pole=180 * u.deg)

    vct_3d = varying_celestial_transform_from_tables(
        pc_table=varying_matrix_lt[0], crval_table=crval_table[0], **kwargs)

    assert isinstance(vct_3d, VaryingCelestialTransform)

    vct_2d = varying_celestial_transform_from_tables(
        pc_table=varying_matrix_lt, crval_table=crval_table, **kwargs)

    assert isinstance(vct_2d, VaryingCelestialTransform2D)

    with pytest.raises(
            ValueError,
            match="Only one or two dimensional lookup tables are supported"):
        varying_celestial_transform_from_tables(
            pc_table=varying_matrix_lt[1:].reshape((3, 2, 2, 2, 2)),
            crval_table=crval_table[1:].reshape((3, 2, 2, 2)),
            **kwargs)
Example #34
0
    def from_equatorial(equatorial_coo, fixed_frame):
        # TODO replace w/ something smart (Sun/Earth special cased)
        if fixed_frame.body == Sun:
            assert type(equatorial_coo) == HCRS
        else:
            assert equatorial_coo.body == fixed_frame.body

        r = equatorial_coo.cartesian

        ra, dec, W = fixed_frame.rot_elements_at_epoch(fixed_frame.obstime)

        r_trans2 = r.transform(rotation_matrix(90 * u.deg + ra, "z"))
        r_f = r_trans2.transform(rotation_matrix(90 * u.deg - dec, "x"))
        r_f = r_f.transform(rotation_matrix(W, "z"))

        return fixed_frame.realize_frame(r_f)
Example #35
0
def test_static_matrix_combine_paths():
    """
    Check that combined staticmatrixtransform matrices provide the same
    transformation as using an intermediate transformation.

    This is somewhat of a regression test for #7706
    """
    from astropy.coordinates.baseframe import BaseCoordinateFrame
    from astropy.coordinates.matrix_utilities import rotation_matrix

    class AFrame(BaseCoordinateFrame):
        default_representation = r.SphericalRepresentation
        default_differential = r.SphericalCosLatDifferential

    t1 = t.StaticMatrixTransform(rotation_matrix(30.*u.deg, 'z'),
                                 ICRS, AFrame)
    t1.register(frame_transform_graph)
    t2 = t.StaticMatrixTransform(rotation_matrix(30.*u.deg, 'z').T,
                                 AFrame, ICRS)
    t2.register(frame_transform_graph)

    class BFrame(BaseCoordinateFrame):
        default_representation = r.SphericalRepresentation
        default_differential = r.SphericalCosLatDifferential

    t3 = t.StaticMatrixTransform(rotation_matrix(30.*u.deg, 'x'),
                                 ICRS, BFrame)
    t3.register(frame_transform_graph)
    t4 = t.StaticMatrixTransform(rotation_matrix(30.*u.deg, 'x').T,
                                 BFrame, ICRS)
    t4.register(frame_transform_graph)

    c = Galactic(123*u.deg, 45*u.deg)
    c1 = c.transform_to(BFrame) # direct
    c2 = c.transform_to(AFrame).transform_to(BFrame) # thru A
    c3 = c.transform_to(ICRS).transform_to(BFrame) # thru ICRS

    assert quantity_allclose(c1.lon, c2.lon)
    assert quantity_allclose(c1.lat, c2.lat)

    assert quantity_allclose(c1.lon, c3.lon)
    assert quantity_allclose(c1.lat, c3.lat)

    for t_ in [t1, t2, t3, t4]:
        t_.unregister(frame_transform_graph)
Example #36
0
 def _create_matrix(self, phi, theta, psi, axes_order):
     matrices = []
     for angle, axis in zip([phi, theta, psi], axes_order):
         if isinstance(angle, u.Quantity):
             angle = angle.value
         angle = angle.item()
         matrices.append(rotation_matrix(angle, axis, unit=u.rad))
     result = matrix_product(*matrices[::-1])
     return result
Example #37
0
def get_matrix_vectors(galactocentric_frame, inverse=False):
    """
    Use the ``inverse`` argument to get the inverse transformation, matrix and
    offsets to go from Galactocentric to ICRS.
    """
    # shorthand
    gcf = galactocentric_frame

    # rotation matrix to align x(ICRS) with the vector to the Galactic center
    mat1 = rotation_matrix(-gcf.galcen_coord.dec, 'y')
    mat2 = rotation_matrix(gcf.galcen_coord.ra, 'z')
    # extra roll away from the Galactic x-z plane
    mat0 = rotation_matrix(gcf.get_roll0() - gcf.roll, 'x')

    # construct transformation matrix and use it
    R = matrix_product(mat0, mat1, mat2)

    # Now need to translate by Sun-Galactic center distance around x' and
    # rotate about y' to account for tilt due to Sun's height above the plane
    translation = r.CartesianRepresentation(gcf.galcen_distance * [1., 0., 0.])
    z_d = gcf.z_sun / gcf.galcen_distance
    H = rotation_matrix(-np.arcsin(z_d), 'y')

    # compute total matrices
    A = matrix_product(H, R)

    # Now we re-align the translation vector to account for the Sun's height
    # above the midplane
    offset = -translation.transform(H)

    if inverse:
        # the inverse of a rotation matrix is a transpose, which is much faster
        #   and more stable to compute
        A = matrix_transpose(A)
        offset = (-offset).transform(A)
        offset_v = r.CartesianDifferential.from_cartesian(
            (-gcf.galcen_v_sun).to_cartesian().transform(A))
        offset = offset.with_differentials(offset_v)

    else:
        offset = offset.with_differentials(gcf.galcen_v_sun)

    return A, offset
Example #38
0
def _ecliptic_rotation_matrix(equinox):
    # This code calls pmat06 from ERFA, which retrieves the precession
    # matrix (including frame bias) according to the IAU 2006 model, but
    # leaves out the nutation. This matches what ERFA does in the ecm06
    # function and also brings the results closer to what other libraries
    # give (see https://github.com/astropy/astropy/pull/6508). However,
    # notice that this makes the name "TrueEcliptic" misleading, and might
    # be changed in the future (discussion in the same pull request)
    jd1, jd2 = get_jd12(equinox, 'tt')
    rbp = erfa.pmat06(jd1, jd2)
    obl = erfa.obl06(jd1, jd2)*u.radian
    return matrix_product(rotation_matrix(obl, 'x'), rbp)
Example #39
0
def _make_rotation_matrix_from_reprs(start_representation, end_representation):
    """
    Return the matrix for the direct rotation from one representation to a second representation.
    The representations need not be normalized first.
    """
    A = start_representation.to_cartesian()
    B = end_representation.to_cartesian()
    rotation_axis = A.cross(B)
    rotation_angle = -np.arccos(A.dot(B) / (A.norm() * B.norm()))  # negation is required

    # This line works around some input/output quirks of Astropy's rotation_matrix()
    matrix = np.array(rotation_matrix(rotation_angle, rotation_axis.xyz.value.tolist()))
    return matrix
Example #40
0
def _rotate_polygon(lon, lat, lon0, lat0):
    """
    Given a polygon with vertices defined by (lon, lat), rotate the polygon
    such that the North pole of the spherical coordinates is now at (lon0,
    lat0). Therefore, to end up with a polygon centered on (lon0, lat0), the
    polygon should initially be drawn around the North pole.
    """

    # Create a representation object
    polygon = UnitSphericalRepresentation(lon=lon, lat=lat)

    # Determine rotation matrix to make it so that the circle is centered
    # on the correct longitude/latitude.
    m1 = rotation_matrix(-(0.5 * np.pi * u.radian - lat0), axis='y')
    m2 = rotation_matrix(-lon0, axis='z')
    transform_matrix = matrix_product(m2, m1)

    # Apply 3D rotation
    polygon = polygon.to_cartesian()
    polygon = polygon.transform(transform_matrix)
    polygon = UnitSphericalRepresentation.from_cartesian(polygon)

    return polygon.lon, polygon.lat
Example #41
0
def test_rotation_matrix():
    assert_array_equal(rotation_matrix(0*u.deg, 'x'), np.eye(3))

    assert_allclose(rotation_matrix(90*u.deg, 'y'), [[0, 0, -1],
                                                     [0, 1, 0],
                                                     [1, 0, 0]], atol=1e-12)

    assert_allclose(rotation_matrix(-90*u.deg, 'z'), [[0, -1, 0],
                                                      [1, 0, 0],
                                                      [0, 0, 1]], atol=1e-12)

    assert_allclose(rotation_matrix(45*u.deg, 'x'),
                    rotation_matrix(45*u.deg, [1, 0, 0]))
    assert_allclose(rotation_matrix(125*u.deg, 'y'),
                    rotation_matrix(125*u.deg, [0, 1, 0]))
    assert_allclose(rotation_matrix(-30*u.deg, 'z'),
                    rotation_matrix(-30*u.deg, [0, 0, 1]))

    assert_allclose(np.dot(rotation_matrix(180*u.deg, [1, 1, 0]), [1, 0, 0]),
                    [0, 1, 0], atol=1e-12)

    # make sure it also works for very small angles
    assert_allclose(rotation_matrix(0.000001*u.deg, 'x'),
                    rotation_matrix(0.000001*u.deg, [1, 0, 0]))
Example #42
0
def gal_to_mag():
    mat1 = rotation_matrix(57.275785782128686*u.deg, 'z')
    mat2 = rotation_matrix(90*u.deg - MagellanicStreamNidever08._ngp.b, 'y')
    mat3 = rotation_matrix(MagellanicStreamNidever08._ngp.l, 'z')

    return matrix_product(mat1, mat2, mat3)
Example #43
0
File: orphan.py Project: adrn/gala
    # TODO: remove this. This is a hack required as of astropy v3.1 in order
    # to have the longitude components wrap at the desired angle
    def represent_as(self, base, s='base', in_frame_units=False):
        r = super().represent_as(base, s=s, in_frame_units=in_frame_units)
        r.lon.wrap_angle = self._default_wrap_angle
        return r
    represent_as.__doc__ = coord.BaseCoordinateFrame.represent_as.__doc__


# Define the Euler angles
phi = 128.79 * u.degree
theta = 54.39 * u.degree
psi = 90.70 * u.degree

# Generate the rotation matrix using the x-convention (see Goldstein)
D = rotation_matrix(phi, "z")
C = rotation_matrix(theta, "x")
B = rotation_matrix(psi, "z")
R = matrix_product(B, C, D)

@frame_transform_graph.transform(coord.StaticMatrixTransform, coord.Galactic,
                                 OrphanNewberg10)
def galactic_to_orp():
    """ Compute the transformation from Galactic spherical to
        heliocentric Orphan coordinates.
    """
    return R

# Oph to Galactic coordinates
@frame_transform_graph.transform(coord.StaticMatrixTransform, OrphanNewberg10,
                                 coord.Galactic)
# In this case we override the names in the spherical representations but don't
# do anything with other representations like cartesian or cylindrical.
#
# Next we have to define the transformation from this coordinate system to some
# other built-in coordinate system; we will use Galactic coordinates. We can do
# this by defining functions that return transformation matrices, or by simply
# defining a function that accepts a coordinate and returns a new coordinate in
# the new system. We'll start by constructing the rotation matrix, using the
# ``rotation_matrix`` helper function:

SGR_PHI = np.radians(180+3.75) # Euler angles (from Law & Majewski 2010)
SGR_THETA = np.radians(90-13.46)
SGR_PSI = np.radians(180+14.111534)

# Generate the rotation matrix using the x-convention (see Goldstein)
D = rotation_matrix(SGR_PHI, "z", unit=u.radian)
C = rotation_matrix(SGR_THETA, "x", unit=u.radian)
B = rotation_matrix(SGR_PSI, "z", unit=u.radian)
SGR_MATRIX = np.array(B.dot(C).dot(D))

##############################################################################
# This is done at the module level, since it will be used by both the
# transformation from Sgr to Galactic as well as the inverse from Galactic to
# Sgr. Now we can define our first transformation function:

@frame_transform_graph.transform(coord.FunctionTransform, coord.Galactic, Sagittarius)
def galactic_to_sgr(gal_coord, sgr_frame):
    """ Compute the transformation from Galactic spherical to
        heliocentric Sgr coordinates.
    """
Example #45
0
def _ecliptic_rotation_matrix():
    jd1, jd2 = get_jd12(J2000, J2000.scale)
    obl = erfa.obl80(jd1, jd2) * u.radian
    assert obl.to(u.arcsec).value == 84381.448
    return rotation_matrix(obl, "x")
def gal_to_supergal():
    mat1 = rotation_matrix(90, 'z')
    mat2 = rotation_matrix(90 - Supergalactic._nsgp_gal.b.degree, 'y')
    mat3 = rotation_matrix(Supergalactic._nsgp_gal.l.degree, 'z')
    return matrix_product(mat1, mat2, mat3)
# Next we have to define the transformation from this coordinate system to some
# other built-in coordinate system; we will use Galactic coordinates. We can do
# this by defining functions that return transformation matrices, or by simply
# defining a function that accepts a coordinate and returns a new coordinate in
# the new system. Because the transformation to the Sagittarius coordinate
# system is just a spherical rotation from Galactic coordinates, we'll just
# define a function that returns this matrix. We'll start by constructing the
# transformation matrix using pre-deteremined Euler angles and the
# ``rotation_matrix`` helper function:

SGR_PHI = (180 + 3.75) * u.degree # Euler angles (from Law & Majewski 2010)
SGR_THETA = (90 - 13.46) * u.degree
SGR_PSI = (180 + 14.111534) * u.degree

# Generate the rotation matrix using the x-convention (see Goldstein)
D = rotation_matrix(SGR_PHI, "z")
C = rotation_matrix(SGR_THETA, "x")
B = rotation_matrix(SGR_PSI, "z")
A = np.diag([1.,1.,-1.])
SGR_MATRIX = matrix_product(A, B, C, D)

##############################################################################
# Since we already constructed the transformation (rotation) matrix above, and
# the inverse of a rotation matrix is just its transpose, the required
# transformation functions are very simple:

@frame_transform_graph.transform(coord.StaticMatrixTransform, coord.Galactic, Sagittarius)
def galactic_to_sgr():
    """ Compute the transformation matrix from Galactic spherical to
        heliocentric Sgr coordinates.
    """
Example #48
0
def _ecliptic_rotation_matrix_pulsar(obl):
    """Here we only do the obliquity angle rotation. Astropy will add the
    precession-nutation correction.
    """
    return rotation_matrix(obl, 'x')