コード例 #1
0
    def test_icrsFromObservedExceptions(self):
        """
        Test that _icrsFromObserved raises exceptions when it is supposed to.
        """
        numpy.random.seed(33)
        ra_in = numpy.random.random_sample(10)
        dec_in = numpy.random.random_sample(10)
        with self.assertRaises(RuntimeError) as context:
            ra_out, dec_out = _icrsFromObserved(ra_in, dec_in, epoch=2000.0)
        self.assertEqual(context.exception.args[0],
                         "cannot call icrsFromObserved; obs_metadata is None")

        obs = ObservationMetaData(pointingRA=23.0, pointingDec=-19.0)
        with self.assertRaises(RuntimeError) as context:
            ra_out, dec_out = _icrsFromObserved(ra_in, dec_in, epoch=2000.0, obs_metadata=obs)
        self.assertEqual(context.exception.args[0],
                         "cannot call icrsFromObserved; obs_metadata.mjd is None")

        obs = ObservationMetaData(pointingRA=23.0, pointingDec=-19.0,
                                  mjd=ModifiedJulianDate(TAI=52344.0))
        with self.assertRaises(RuntimeError) as context:
            ra_out, dec_out = _icrsFromObserved(ra_in, dec_in, obs_metadata=obs)
        self.assertEqual(context.exception.args[0],
                         "cannot call icrsFromObserved; you have not specified an epoch")

        with self.assertRaises(RuntimeError) as context:
            ra_out, dec_out = _icrsFromObserved(ra_in[:3], dec_in, obs_metadata=obs, epoch=2000.0)
        self.assertEqual(context.exception.args[0],
                         "You passed 3 RAs but 10 Decs to icrsFromObserved")
コード例 #2
0
def _raDecFromNativeLonLat(lon, lat, obs_metadata):
    """
    Transform a star's position in native longitude and latitude into
    RA and Dec.  See the doc string for _nativeLonLatFromRaDec for definitions
    of native longitude and latitude.

    @param [in] lon is the native longitude in radians

    @param [in] lat is the native latitude in radians

    @param [in] obs_metadata is an ObservationMetaData characterizing the pointing
    of the telescope

    @param [out] raOut is the RA of the star in radians
    (in the International Celestial Reference System)

    @param [in] decOut is the Dec of the star in radians
    (in the International Celestial Reference System)

    Note: Because of its reliance on icrsFromObserved, this
    method is only accurate at angular distances from the sun of greater
    than 45 degrees and zenith distances of less than 75 degrees.
    """

    ra_temp, dec_temp = _observedFromICRS(np.array([obs_metadata._pointingRA]),
                                          np.array([obs_metadata._pointingDec]),
                                          obs_metadata=obs_metadata, epoch=2000.0,
                                          includeRefraction=True)

    raPointing = ra_temp[0]
    decPointing = dec_temp[0]

    raObs, decObs = _lonLatFromNativeLonLat(lon, lat, raPointing, decPointing)


    # convert from observed geocentric coordinates to International Celestial Reference System
    # coordinates

    if hasattr(raObs,'__len__'):
        raOut, decOut = _icrsFromObserved(raObs, decObs, obs_metadata=obs_metadata,
                                          epoch=2000.0, includeRefraction=True)
    else:
        raOut, decOut = _icrsFromObserved(np.array([raObs]), np.array([decObs]),
                                          obs_metadata=obs_metadata,
                                          epoch=2000.0, includeRefraction=True)

    if not hasattr(lon, '__len__'):
        return raOut[0], decOut[0]

    return raOut, decOut
コード例 #3
0
    def testIcrsFromObserved(self):
        obs = ObservationMetaData(pointingRA=35.0,
                                  pointingDec=-45.0,
                                  mjd=43572.0)

        for includeRefraction in [True, False]:

            raRad, decRad = utils._icrsFromObserved(
                self.raList,
                self.decList,
                obs_metadata=obs,
                epoch=2000.0,
                includeRefraction=includeRefraction)

            raDeg, decDeg = utils.icrsFromObserved(
                np.degrees(self.raList),
                np.degrees(self.decList),
                obs_metadata=obs,
                epoch=2000.0,
                includeRefraction=includeRefraction)

            dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg))
            np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9)

            dDec = utils.arcsecFromRadians(decRad - np.radians(decDeg))
            np.testing.assert_array_almost_equal(dDec, np.zeros(self.nStars),
                                                 9)
コード例 #4
0
ファイル: FocalPlaneUtils.py プロジェクト: lsst/sims_utils
def _raDecFromPupilCoords(xPupil, yPupil, obs_metadata=None,
                          includeRefraction=True, epoch=2000.0):
    """
    @param [in] xPupil -- pupil coordinates in radians.
    Can be a numpy array or a number.

    @param [in] yPupil -- pupil coordinates in radians.
    Can be a numpy array or a number.

    @param [in] obs_metadata -- an instantiation of ObservationMetaData characterizing
    the state of the telescope

    @param[in] includeRefraction -- a boolean which controls the effects of refraction
    (refraction is used when finding the observed coordinates of the boresite specified
    by obs_metadata)

    @param [in] epoch -- julian epoch of the mean equinox used for the coordinate
    transformations (in years; defaults to 2000)

    @param [out] a 2-D numpy array in which the first row is RA and the second
    row is Dec (both in radians; both in the International Celestial Reference System)

    WARNING: This method does not account for apparent motion due to parallax.
    This method is only useful for mapping positions on a theoretical focal plane
    to positions on the celestial sphere.
    """

    are_arrays = _validate_inputs([xPupil, yPupil], ['xPupil', 'yPupil'], "raDecFromPupilCoords")

    if obs_metadata is None:
        raise RuntimeError("Cannot call raDecFromPupilCoords without obs_metadata")

    if epoch is None:
        raise RuntimeError("Cannot call raDecFromPupilCoords; epoch is None")

    if obs_metadata.rotSkyPos is None:
        raise RuntimeError("Cannot call raDecFromPupilCoords without rotSkyPos " +
                           "in obs_metadata")

    if obs_metadata.pointingRA is None or obs_metadata.pointingDec is None:
        raise RuntimeError("Cannot call raDecFromPupilCoords " +
                           "without pointingRA, pointingDec in obs_metadata")

    if obs_metadata.mjd is None:
        raise RuntimeError("Cannot calculate RA, Dec without mjd " +
                           "in obs_metadata")

    raObs, decObs = _observedFromPupilCoords(xPupil, yPupil,
                                             obs_metadata=obs_metadata,
                                             epoch=epoch,
                                             includeRefraction=includeRefraction)

    ra_icrs, dec_icrs = _icrsFromObserved(raObs, decObs,
                                          obs_metadata=obs_metadata,
                                          epoch=epoch,
                                          includeRefraction=includeRefraction)

    return np.array([ra_icrs, dec_icrs])
コード例 #5
0
def _raDecFromAltAz(altRad, azRad, obs, includeRefraction=True):
    """
    Convert altitude and azimuth to RA and Dec

    @param [in] altRad is the altitude in radians.  Can be a numpy array or a single value.

    @param [in] azRad is the azimuth in radians.  Cant be a numpy array or a single value.

    @param [in] obs is an ObservationMetaData characterizing
    the site of the telescope and the MJD of the observation

    @param [in] includeRefraction is a boolean that turns refraction on and off
    (default True)

    @param [out] RA in radians (in the International Celestial Reference System)

    @param [out] Dec in radians (in the International Celestial Reference System)

    Note: This method is only accurate to within 0.01 arcsec near azimuth = 0 or pi
    """

    are_arrays = _validate_inputs([altRad, azRad], ['altRad', 'azRad'],
                                  "raDecFromAltAz")

    lst = calcLmstLast(obs.mjd.UT1, obs.site.longitude_rad)
    last = lst[1]
    sinAlt = np.sin(altRad)
    cosLat = np.cos(obs.site.latitude_rad)
    sinLat = np.sin(obs.site.latitude_rad)
    decObs = np.arcsin(sinLat * sinAlt +
                       cosLat * np.cos(altRad) * np.cos(azRad))
    costheta = (sinAlt - np.sin(decObs) * sinLat) / (np.cos(decObs) * cosLat)
    if are_arrays:
        haRad0 = np.arccos(costheta)
        # Make sure there were no NaNs
        nanSpots = np.where(np.isnan(haRad0))[0]
        if np.size(nanSpots) > 0:
            haRad0[nanSpots] = 0.5 * np.pi * \
                (1.0 - np.sign(costheta[nanSpots]))
    else:
        haRad0 = np.arccos(costheta)
        if np.isnan(haRad0):
            if np.sign(costheta) > 0.0:
                haRad0 = 0.0
            else:
                haRad0 = np.pi

    haRad = np.where(np.sin(azRad) >= 0.0, -1.0 * haRad0, haRad0)
    raObs = np.radians(last * 15.) - haRad

    raRad, decRad = _icrsFromObserved(raObs,
                                      decObs,
                                      obs_metadata=obs,
                                      epoch=2000.0,
                                      includeRefraction=includeRefraction)

    return raRad, decRad
コード例 #6
0
def _raDecFromAltAz(altRad, azRad, obs, includeRefraction=True):
    """
    Convert altitude and azimuth to RA and Dec

    @param [in] altRad is the altitude in radians.  Can be a numpy array or a single value.

    @param [in] azRad is the azimuth in radians.  Cant be a numpy array or a single value.

    @param [in] obs is an ObservationMetaData characterizing
    the site of the telescope and the MJD of the observation

    @param [in] includeRefraction is a boolean that turns refraction on and off
    (default True)

    @param [out] RA in radians (in the International Celestial Reference System)

    @param [out] Dec in radians (in the International Celestial Reference System)

    Note: This method is only accurate to within 0.01 arcsec near azimuth = 0 or pi
    """

    with np.errstate(invalid='ignore', divide='ignore'):
        are_arrays = _validate_inputs(
            [altRad, azRad], ['altRad', 'azRad'], "raDecFromAltAz")

        lst = calcLmstLast(obs.mjd.UT1, obs.site.longitude_rad)
        last = lst[1]
        sinAlt = np.sin(altRad)
        cosLat = np.cos(obs.site.latitude_rad)
        sinLat = np.sin(obs.site.latitude_rad)
        decObs = np.arcsin(sinLat * sinAlt + cosLat *
                           np.cos(altRad) * np.cos(azRad))
        costheta = (sinAlt - np.sin(decObs) * sinLat) / (np.cos(decObs) * cosLat)
        if are_arrays:
            haRad0 = np.arccos(costheta)
            # Make sure there were no NaNs
            nanSpots = np.where(np.isnan(haRad0))[0]
            if np.size(nanSpots) > 0:
                haRad0[nanSpots] = 0.5 * np.pi * \
                    (1.0 - np.sign(costheta[nanSpots]))
        else:
            haRad0 = np.arccos(costheta)
            if np.isnan(haRad0):
                if np.sign(costheta) > 0.0:
                    haRad0 = 0.0
                else:
                    haRad0 = np.pi

        haRad = np.where(np.sin(azRad) >= 0.0, -1.0 * haRad0, haRad0)
        raObs = np.radians(last * 15.) - haRad

        raRad, decRad = _icrsFromObserved(raObs, decObs,
                                          obs_metadata=obs, epoch=2000.0,
                                          includeRefraction=includeRefraction)

    return raRad, decRad
コード例 #7
0
def fovCorners(obs, side_length):
    """
    obs is an ObservationMetaData
    side_length in arcminutes
    """

    # find the center of the field of view and convert it into "Observed RA, Dec"
    pointing_lon, pointing_lat = _observedFromICRS(np.array([obs._pointingRA]),
                                                   np.array([obs._pointingDec
                                                             ]),
                                                   obs_metadata=obs,
                                                   epoch=2000.0)

    # figure out the length of the diagonal of your square field of view
    hypotenuse = np.sqrt(2.0 * (side_length / 60.0)**2)
    half_length = np.radians(0.5 * hypotenuse)

    # Create a fiducial field of view cetnered on the north pole.
    # We will take this field of viewand rotate it so that it has
    # the correct orientation, then translate it down the celestial
    # sphere to the actual position of your telescope pointing.
    native_lon_list = np.array([0.0, np.pi / 2.0, np.pi, 1.5 * np.pi])
    native_lat_list = np.array([0.5 * np.pi - half_length] * 4)

    # rotate your field of view to account for the rotation of the sky

    rot_angle = -1.0 * obs._rotSkyPos + 0.25 * np.pi  # the extra 0.25 pi is to align our field
    # of view so that rotSkyPos=0 puts the
    # northern edge vertically up (when we
    # created the field of view, one of the
    # corners was vertically up)
    cosRot = np.cos(rot_angle)
    sinRot = np.sin(rot_angle)

    rotz = np.array([[cosRot, sinRot, 0.0], [-sinRot, cosRot, 0.0],
                     [0.0, 0.0, 1.0]])

    xyz = cartesianFromSpherical(native_lon_list, native_lat_list)

    rot_xyz = []

    for vec in xyz:
        new_xyz = np.dot(rotz, vec)
        rot_xyz.append(new_xyz)

    rot_xyz = np.array(rot_xyz)

    rot_lon, rot_lat = sphericalFromCartesian(rot_xyz)

    # translate the field of view down to the actual telescope pointing
    ra_obs, dec_obs = _lonLatFromNativeLonLat(rot_lon, rot_lat,
                                              pointing_lon[0], pointing_lat[0])

    return np.degrees(
        _icrsFromObserved(ra_obs, dec_obs, obs_metadata=obs, epoch=2000.0))
コード例 #8
0
    def _icrsFromPhoSim(self, raPhoSim, decPhoSim, obs_metadata):
        """
        This method will convert from the 'deprecessed' coordinates expected by
        PhoSim to ICRS coordinates

        Parameters
        ----------
        raPhoSim is the PhoSim RA-like coordinate (in radians)

        decPhoSim is the PhoSim Dec-like coordinate (in radians)

        obs_metadata is an ObservationMetaData characterizing the
        telescope pointing

        Returns
        -------
        raICRS in radians

        decICRS in radians
        """

        # Calculate the rotation matrix to go from the ICRS bore site to the
        # precessed bore site
        xyz_bore = cartesianFromSpherical(np.array([obs_metadata._pointingRA]),
                                          np.array([obs_metadata._pointingDec]))

        precessedRA, precessedDec = _observedFromICRS(np.array([obs_metadata._pointingRA]),
                                                      np.array([obs_metadata._pointingDec]),
                                                      obs_metadata=obs_metadata, epoch=2000.0,
                                                      includeRefraction=False)

        xyz_precessed = cartesianFromSpherical(precessedRA, precessedDec)

        rotMat = rotationMatrixFromVectors(xyz_bore[0], xyz_precessed[0])

        # apply this rotation matrix to the PhoSim RA, Dec-like coordinates,
        # transforming back to "Observed" RA and Dec
        xyz_list = cartesianFromSpherical(raPhoSim, decPhoSim)
        xyz_obs = np.array([np.dot(rotMat, xx) for xx in xyz_list])
        ra_obs, dec_obs = sphericalFromCartesian(xyz_obs)

        # convert to ICRS coordinates
        return _icrsFromObserved(ra_obs, dec_obs, obs_metadata=obs_metadata,
                                 epoch=2000.0, includeRefraction=False)
コード例 #9
0
    def testIcrsFromObserved(self):
        obs = ObservationMetaData(pointingRA=35.0, pointingDec=-45.0,
                                  mjd=43572.0)

        for includeRefraction in [True, False]:

            raRad, decRad = utils._icrsFromObserved(self.raList, self.decList,
                                                         obs_metadata=obs, epoch=2000.0,
                                                         includeRefraction=includeRefraction)

            raDeg, decDeg = utils.icrsFromObserved(np.degrees(self.raList), np.degrees(self.decList),
                                                        obs_metadata=obs, epoch=2000.0,
                                                        includeRefraction=includeRefraction)

            dRa = utils.arcsecFromRadians(raRad-np.radians(raDeg))
            np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9)

            dDec = utils.arcsecFromRadians(decRad-np.radians(decDeg))
            np.testing.assert_array_almost_equal(dDec, np.zeros(self.nStars), 9)
コード例 #10
0
def _raDecFromNativeLonLat(lon, lat, obs_metadata):
    """
    Transform a star's position in native longitude and latitude into
    RA and Dec.  See the doc string for _nativeLonLatFromRaDec for definitions
    of native longitude and latitude.

    @param [in] lon is the native longitude in radians

    @param [in] lat is the native latitude in radians

    @param [in] obs_metadata is an ObservationMetaData characterizing the pointing
    of the telescope

    @param [out] raOut is the RA of the star in radians
    (in the International Celestial Reference System)

    @param [in] decOut is the Dec of the star in radians
    (in the International Celestial Reference System)

    Note: Because of its reliance on icrsFromObserved, this
    method is only accurate at angular distances from the sun of greater
    than 45 degrees and zenith distances of less than 75 degrees.
    """

    raPointing, decPointing = _observedFromICRS(obs_metadata._pointingRA,
                                                obs_metadata._pointingDec,
                                                obs_metadata=obs_metadata,
                                                epoch=2000.0,
                                                includeRefraction=True)

    raObs, decObs = _lonLatFromNativeLonLat(lon, lat, raPointing, decPointing)

    # convert from observed geocentric coordinates to International Celestial Reference System
    # coordinates

    raOut, decOut = _icrsFromObserved(raObs,
                                      decObs,
                                      obs_metadata=obs_metadata,
                                      epoch=2000.0,
                                      includeRefraction=True)

    return raOut, decOut
コード例 #11
0
def _raDecFromPupilCoords(xPupil, yPupil, obs_metadata=None, epoch=2000.0):
    """
    @param [in] xPupil -- pupil coordinates in radians.
    Can be a numpy array or a number.

    @param [in] yPupil -- pupil coordinates in radians.
    Can be a numpy array or a number.

    @param [in] obs_metadata -- an instantiation of ObservationMetaData characterizing
    the state of the telescope

    @param [in] epoch -- julian epoch of the mean equinox used for the coordinate
    transformations (in years; defaults to 2000)

    @param [out] a 2-D numpy array in which the first row is RA and the second
    row is Dec (both in radians; both in the International Celestial Reference System)

    WARNING: This method does not account for apparent motion due to parallax.
    This method is only useful for mapping positions on a theoretical focal plane
    to positions on the celestial sphere.
    """

    are_arrays = _validate_inputs([xPupil, yPupil], ['xPupil', 'yPupil'],
                                  "raDecFromPupilCoords")

    if obs_metadata is None:
        raise RuntimeError(
            "Cannot call raDecFromPupilCoords without obs_metadata")

    if epoch is None:
        raise RuntimeError("Cannot call raDecFromPupilCoords; epoch is None")

    if obs_metadata.rotSkyPos is None:
        raise RuntimeError(
            "Cannot call raDecFromPupilCoords without rotSkyPos " +
            "in obs_metadata")

    if obs_metadata.pointingRA is None or obs_metadata.pointingDec is None:
        raise RuntimeError("Cannot call raDecFromPupilCoords " +
                           "without pointingRA, pointingDec in obs_metadata")

    if obs_metadata.mjd is None:
        raise RuntimeError("Cannot calculate x_pupil, y_pupil without mjd " +
                           "in obs_metadata")

    ra_pointing, dec_pointing = _observedFromICRS(obs_metadata._pointingRA,
                                                  obs_metadata._pointingDec,
                                                  obs_metadata=obs_metadata,
                                                  epoch=epoch,
                                                  includeRefraction=True)

    # This is the same as theta in pupilCoordsFromRaDec, except without the minus sign.
    # This is because we will be reversing the rotation performed in that other method.
    theta = -1.0 * obs_metadata._rotSkyPos

    x_g = xPupil * np.cos(theta) - yPupil * np.sin(theta)
    y_g = xPupil * np.sin(theta) + yPupil * np.cos(theta)

    x_g *= -1.0

    # x_g and y_g are now the x and y coordinates
    # can now use the PALPY method palDtp2s to convert to RA, Dec.

    if are_arrays:
        raObs, decObs = palpy.dtp2sVector(x_g, y_g, ra_pointing, dec_pointing)
    else:
        raObs, decObs = palpy.dtp2s(x_g, y_g, ra_pointing, dec_pointing)

    ra_icrs, dec_icrs = _icrsFromObserved(raObs,
                                          decObs,
                                          obs_metadata=obs_metadata,
                                          epoch=epoch,
                                          includeRefraction=True)

    return np.array([ra_icrs, dec_icrs])
コード例 #12
0
    def test_icrsFromObserved(self):
        """
        Test that _icrsFromObserved really inverts _observedFromAppGeo.

        In this case, the method is only reliable at distances of more than
        45 degrees from the sun and at zenith distances less than 70 degrees.
        """

        numpy.random.seed(412)
        nSamples = 100

        mjd2000 = pal.epb(2000.0) # convert epoch to mjd

        site = Site(name='LSST')

        for mjd in (53000.0, 53241.6, 58504.6):
            for includeRefraction in (True, False):
                for raPointing in (23.5, 256.9, 100.0):
                    for decPointing in (-12.0, 45.0, 66.8):

                        obs = ObservationMetaData(mjd=mjd, site=site)

                        raZenith, decZenith = _raDecFromAltAz(0.5*numpy.pi, 0.0, obs)

                        obs = ObservationMetaData(pointingRA=raPointing, pointingDec=decPointing,
                                                  mjd=mjd, site=site)

                        rr = numpy.random.random_sample(nSamples)*numpy.radians(50.0)
                        theta = numpy.random.random_sample(nSamples)*2.0*numpy.pi

                        ra_in = raZenith + rr*numpy.cos(theta)
                        dec_in = decZenith + rr*numpy.sin(theta)

                        # test a round-trip between observedFromICRS and icrsFromObserved
                        ra_obs, dec_obs = _observedFromICRS(ra_in, dec_in, obs_metadata=obs,
                                                            includeRefraction=includeRefraction,
                                                            epoch=2000.0)

                        ra_icrs, dec_icrs = _icrsFromObserved(ra_obs, dec_obs, obs_metadata=obs,
                                                              includeRefraction=includeRefraction,
                                                              epoch=2000.0)

                        valid_pts = numpy.where(_distanceToSun(ra_in, dec_in, mjd)>0.25*numpy.pi)[0]

                        self.assertGreater(len(valid_pts), 0)

                        distance = arcsecFromRadians(pal.dsepVector(ra_in[valid_pts], dec_in[valid_pts],
                                                     ra_icrs[valid_pts], dec_icrs[valid_pts]))

                        self.assertLess(distance.max(), 0.01)


                        # test a round-trip between observedFromAppGeo and appGeoFromObserved
                        ra_obs, dec_obs = _observedFromAppGeo(ra_in, dec_in, obs_metadata=obs,
                                                              includeRefraction=includeRefraction)
                        ra_app, dec_app = _appGeoFromObserved(ra_obs, dec_obs, obs_metadata=obs,
                                                                includeRefraction=includeRefraction)

                        distance = arcsecFromRadians(pal.dsepVector(ra_in[valid_pts], dec_in[valid_pts],
                                                     ra_app[valid_pts], dec_app[valid_pts]))

                        self.assertLess(distance.max(), 0.01)
def _raDecFromAltAz(altRad, azRad, obs):
    """
    Convert altitude and azimuth to RA and Dec

    @param [in] altRad is the altitude in radians.  Can be a numpy array or a single value.

    @param [in] azRad is the azimuth in radians.  Cant be a numpy array or a single value.

    @param [in] obs is an ObservationMetaData characterizing
    the site of the telescope and the MJD of the observation

    @param [out] RA in radians (in the International Celestial Reference System)

    @param [out] Dec in radians (in the International Celestial Reference System)

    Note: This method is only accurate to within 0.01 arcsec near azimuth = 0 or pi
    """

    altIsArray = False
    azIsArray = False

    if isinstance(altRad, np.ndarray):
        altIsArray = True

    if isinstance(azRad, np.ndarray):
        azIsArray = True

    if altIsArray and not azIsArray:
        raise RuntimeError('passed a numpy array of alt to raDecFromAltAz, but only one az')

    if azIsArray and not altIsArray:
        raise RuntimeError('passed a numpy array of az to raDecFromAltAz, but only one alt')

    if azIsArray and altIsArray and len(altRad)!=len(azRad):
        raise RuntimeError('in raDecFromAltAz, length of alt numpy array does not match length of az numpy array')

    lst = calcLmstLast(obs.mjd.UT1, obs.site.longitude_rad)
    last = lst[1]
    sinAlt = np.sin(altRad)
    cosLat = np.cos(obs.site.latitude_rad)
    sinLat = np.sin(obs.site.latitude_rad)
    decObs = np.arcsin(sinLat*sinAlt+ cosLat*np.cos(altRad)*np.cos(azRad))
    costheta = (sinAlt - np.sin(decObs)*sinLat)/(np.cos(decObs)*cosLat)
    if altIsArray:
        haRad0 =  np.arccos(costheta)
        # Make sure there were no NaNs
        nanSpots = np.where(np.isnan(haRad0))[0]
        if np.size(nanSpots) > 0:
            haRad0[nanSpots] = 0.5*np.pi*(1.0-np.sign(costheta[nanSpots]))
    else:
        haRad0 = np.arccos(costheta)
        if np.isnan(haRad0):
            if np.sign(costheta)>0.0:
                haRad0 = 0.0
            else:
                haRad0 = np.pi

    haRad = np.where(np.sin(azRad)>=0.0, -1.0*haRad0, haRad0)
    raObs = np.radians(last*15.) - haRad

    if not hasattr(raObs, '__len__'):
        raRad, decRad = _icrsFromObserved(np.array([raObs]), np.array([decObs]),
                                          obs_metadata=obs, epoch=2000.0,
                                          includeRefraction=True)

        return raRad[0], decRad[0]


    raRad, decRad = _icrsFromObserved(raObs, decObs,
                                      obs_metadata=obs, epoch=2000.0,
                                      includeRefraction=True)

    return raRad, decRad
コード例 #14
0
    def testCardinalDirections(self):
        """
        This unit test verifies that the following conventions hold:

        if rotSkyPos = 0, then north is +y the camera and east is +x

        if rotSkyPos = -90, then north is -x on the camera and east is +y

        if rotSkyPos = 90, then north is +x on the camera and east is -y

        if rotSkyPos = 180, then north is -y on the camera and east is -x

        This is consistent with rotSkyPos = rotTelPos - parallacticAngle

        parallacticAngle is negative when the pointing is east of the meridian.
        http://www.petermeadows.com/html/parallactic.html

        rotTelPos is the angle between up on the telescope and up on
        the camera, where positive rotTelPos goes from north to west
        (from an email sent to me by LynneJones)

        I have verified that OpSim follows the rotSkyPos = rotTelPos - paralacticAngle
        convention.

        I have verified that altAzPaFromRaDec follows the convention that objects
        east of the meridian have a negative parallactic angle.  (altAzPaFromRaDec
        uses PALPY under the hood, so it can probably be taken as correct)

        It will verify this convention for multiple random pointings.
        """

        epoch = 2000.0
        mjd = 42350.0
        rng = np.random.RandomState(42)
        raList = rng.random_sample(10) * 360.0
        decList = rng.random_sample(10) * 180.0 - 90.0

        for rotSkyPos in np.arange(-90.0, 181.0, 90.0):
            for ra, dec in zip(raList, decList):
                obs = ObservationMetaData(pointingRA=ra,
                                          pointingDec=dec,
                                          mjd=mjd,
                                          rotSkyPos=rotSkyPos)

                ra_obs, dec_obs = _observedFromICRS(np.radians([ra]), np.radians([dec]),
                                                    obs_metadata=obs, epoch=2000.0,
                                                    includeRefraction=True)

                # test points that are displaced just to the (E, W, N, S) of the pointing
                # in observed geocentric RA, Dec; verify that the pupil coordinates
                # change as expected
                raTest_obs = ra_obs[0] + np.array([0.01, -0.01, 0.0, 0.0])
                decTest_obs = dec_obs[0] + np.array([0.0, 0.0, 0.01, -0.01])
                raTest, decTest = _icrsFromObserved(raTest_obs, decTest_obs, obs_metadata=obs,
                                                    epoch=2000.0, includeRefraction=True)

                x, y = _pupilCoordsFromRaDec(raTest, decTest, obs_metadata=obs, epoch=epoch)

                lon, lat = _nativeLonLatFromRaDec(raTest, decTest, obs)
                rr = np.abs(np.cos(lat) / np.sin(lat))

                if np.abs(rotSkyPos) < 0.01:  # rotSkyPos == 0
                    control_x = np.array([1.0 * rr[0], -1.0 * rr[1], 0.0, 0.0])
                    control_y = np.array([0.0, 0.0, 1.0 * rr[2], -1.0 * rr[3]])
                elif np.abs(rotSkyPos + 90.0) < 0.01:  # rotSkyPos == -90
                    control_x = np.array([0.0, 0.0, -1.0 * rr[2], 1.0 * rr[3]])
                    control_y = np.array([1.0 * rr[0], -1.0 * rr[1], 0.0, 0.0])
                elif np.abs(rotSkyPos - 90.0) < 0.01:  # rotSkyPos == 90
                    control_x = np.array([0.0, 0.0, 1.0 * rr[2], -1.0 * rr[3]])
                    control_y = np.array([-1.0 * rr[0], +1.0 * rr[1], 0.0, 0.0])
                elif np.abs(rotSkyPos - 180.0) < 0.01:  # rotSkyPos == 180
                    control_x = np.array([-1.0 * rr[0], +1.0 * rr[1], 0.0, 0.0])
                    control_y = np.array([0.0, 0.0, -1.0 * rr[2], 1.0 * rr[3]])

                msg = 'failed on rotSkyPos == %e\n' % rotSkyPos
                msg += 'control_x %s\n' % str(control_x)
                msg += 'test_x %s\n' % str(x)
                msg += 'control_y %s\n' % str(control_y)
                msg += 'test_y %s\n' % str(y)

                dx = np.array([xx / cc if np.abs(cc) > 1.0e-10 else 1.0 - xx for xx, cc in zip(x, control_x)])
                dy = np.array([yy / cc if np.abs(cc) > 1.0e-10 else 1.0 - yy for yy, cc in zip(y, control_y)])
                self.assertLess(np.abs(dx-np.ones(4)).max(), 0.001, msg=msg)
                self.assertLess(np.abs(dy-np.ones(4)).max(), 0.001, msg=msg)
コード例 #15
0
def _raDecFromPupilCoords(xPupil, yPupil, obs_metadata=None, epoch=None):
    """
    @param [in] xPupil -- pupil coordinates in radians

    @param [in] yPupil -- pupil coordinates in radians

    @param [in] obs_metadata -- an instantiation of ObservationMetaData characterizing
    the state of the telescope

    @param [in] epoch -- julian epoch of the mean equinox used for the coordinate
    transformations (in years)

    @param [out] a 2-D numpy array in which the first row is RA and the second
    row is Dec (both in radians; both in the International Celestial Reference System)
    """

    if obs_metadata is None:
        raise RuntimeError("Cannot call raDecFromPupilCoords without obs_metadata")

    if epoch is None:
        raise RuntimeError("Cannot call raDecFromPupilCoords; epoch is None")

    if obs_metadata.rotSkyPos is None:
        raise RuntimeError("Cannot call raDecFromPupilCoords without rotSkyPos " + \
                           "in obs_metadata")

    if obs_metadata.pointingRA is None or obs_metadata.pointingDec is None:
        raise RuntimeError("Cannot call raDecFromPupilCoords "+ \
                          "without pointingRA, pointingDec in obs_metadata")

    if obs_metadata.mjd is None:
        raise RuntimeError("Cannot calculate x_pupil, y_pupil without mjd " + \
                           "in obs_metadata")

    if len(xPupil)!=len(yPupil):
        raise RuntimeError("You passed %d RAs but %d Decs into raDecFromPupilCoords" % \
                           (len(raObj), len(decObj)))

    ra_pointing_temp, dec_pointing_temp = _observedFromICRS(np.array([obs_metadata._pointingRA]),
                                                            np.array([obs_metadata._pointingDec]),
                                                            obs_metadata=obs_metadata,
                                                            epoch=2000.0, includeRefraction=True)

    ra_pointing = ra_pointing_temp[0]
    dec_pointing = dec_pointing_temp[0]

    #This is the same as theta in pupilCoordsFromRaDec, except without the minus sign.
    #This is because we will be reversing the rotation performed in that other method.
    theta = -1.0*obs_metadata._rotSkyPos

    x_g = xPupil*np.cos(theta) - yPupil*np.sin(theta)
    y_g = xPupil*np.sin(theta) + yPupil*np.cos(theta)

    x_g *= -1.0

    # x_g and y_g are now the x and y coordinates
    # can now use the PALPY method palDtp2s to convert to RA, Dec.

    raObs, decObs = palpy.dtp2sVector(x_g, y_g, ra_pointing, dec_pointing)

    ra_icrs, dec_icrs = _icrsFromObserved(raObs, decObs,
                                          obs_metadata=obs_metadata, epoch=2000.0, includeRefraction=True)

    return np.array([ra_icrs, dec_icrs])
コード例 #16
0
    def testCardinalDirections(self):
        """
        This unit test verifies that the following conventions hold:

        if rotSkyPos = 0, then north is +y the camera and east is +x

        if rotSkyPos = -90, then north is -x on the camera and east is +y

        if rotSkyPos = 90, then north is +x on the camera and east is -y

        if rotSkyPos = 180, then north is -y on the camera and east is -x

        This is consistent with rotSkyPos = rotTelPos - parallacticAngle

        parallacticAngle is negative when the pointing is east of the meridian.
        http://www.petermeadows.com/html/parallactic.html

        rotTelPos is the angle between up on the telescope and up on
        the camera, where positive rotTelPos goes from north to west
        (from an email sent to me by LynneJones)

        I have verified that OpSim follows the rotSkyPos = rotTelPos - paralacticAngle
        convention.

        I have verified that altAzPaFromRaDec follows the convention that objects
        east of the meridian have a negative parallactic angle.  (altAzPaFromRaDec
        uses PALPY under the hood, so it can probably be taken as correct)

        It will verify this convention for multiple random pointings.
        """

        epoch = 2000.0
        mjd = 42350.0
        rng = np.random.RandomState(42)
        raList = rng.random_sample(10) * 360.0
        decList = rng.random_sample(10) * 180.0 - 90.0

        for rotSkyPos in np.arange(-90.0, 181.0, 90.0):
            for ra, dec in zip(raList, decList):
                obs = ObservationMetaData(pointingRA=ra,
                                          pointingDec=dec,
                                          mjd=mjd,
                                          rotSkyPos=rotSkyPos)

                ra_obs, dec_obs = _observedFromICRS(np.radians([ra]),
                                                    np.radians([dec]),
                                                    obs_metadata=obs,
                                                    epoch=2000.0,
                                                    includeRefraction=True)

                # test points that are displaced just to the (E, W, N, S) of the pointing
                # in observed geocentric RA, Dec; verify that the pupil coordinates
                # change as expected
                raTest_obs = ra_obs[0] + np.array([0.01, -0.01, 0.0, 0.0])
                decTest_obs = dec_obs[0] + np.array([0.0, 0.0, 0.01, -0.01])
                raTest, decTest = _icrsFromObserved(raTest_obs,
                                                    decTest_obs,
                                                    obs_metadata=obs,
                                                    epoch=2000.0,
                                                    includeRefraction=True)

                x, y = _pupilCoordsFromRaDec(raTest,
                                             decTest,
                                             obs_metadata=obs,
                                             epoch=epoch)

                lon, lat = _nativeLonLatFromRaDec(raTest, decTest, obs)
                rr = np.abs(np.cos(lat) / np.sin(lat))

                if np.abs(rotSkyPos) < 0.01:  # rotSkyPos == 0
                    control_x = np.array([1.0 * rr[0], -1.0 * rr[1], 0.0, 0.0])
                    control_y = np.array([0.0, 0.0, 1.0 * rr[2], -1.0 * rr[3]])
                elif np.abs(rotSkyPos + 90.0) < 0.01:  # rotSkyPos == -90
                    control_x = np.array([0.0, 0.0, -1.0 * rr[2], 1.0 * rr[3]])
                    control_y = np.array([1.0 * rr[0], -1.0 * rr[1], 0.0, 0.0])
                elif np.abs(rotSkyPos - 90.0) < 0.01:  # rotSkyPos == 90
                    control_x = np.array([0.0, 0.0, 1.0 * rr[2], -1.0 * rr[3]])
                    control_y = np.array(
                        [-1.0 * rr[0], +1.0 * rr[1], 0.0, 0.0])
                elif np.abs(rotSkyPos - 180.0) < 0.01:  # rotSkyPos == 180
                    control_x = np.array(
                        [-1.0 * rr[0], +1.0 * rr[1], 0.0, 0.0])
                    control_y = np.array([0.0, 0.0, -1.0 * rr[2], 1.0 * rr[3]])

                msg = 'failed on rotSkyPos == %e\n' % rotSkyPos
                msg += 'control_x %s\n' % str(control_x)
                msg += 'test_x %s\n' % str(x)
                msg += 'control_y %s\n' % str(control_y)
                msg += 'test_y %s\n' % str(y)

                dx = np.array([
                    xx / cc if np.abs(cc) > 1.0e-10 else 1.0 - xx
                    for xx, cc in zip(x, control_x)
                ])
                dy = np.array([
                    yy / cc if np.abs(cc) > 1.0e-10 else 1.0 - yy
                    for yy, cc in zip(y, control_y)
                ])
                self.assertLess(np.abs(dx - np.ones(4)).max(), 0.001, msg=msg)
                self.assertLess(np.abs(dy - np.ones(4)).max(), 0.001, msg=msg)