Ejemplo n.º 1
0
def _nativeLonLatFromRaDec(ra_in, dec_in, obs_metadata):
    """
    Convert the RA and Dec of a star into `native' longitude and latitude.

    Native longitude and latitude are defined as what RA and Dec would be
    if the celestial pole were at the location where the telescope is pointing.
    The transformation is achieved by rotating the vector pointing to the RA
    and Dec being transformed once about the x axis and once about the z axis.
    These are the Euler rotations referred to in Section 2.3 of

    Calabretta and Greisen (2002), A&A 395, p. 1077

    Note: RA, and Dec are assumed to be in the International Celestial Reference
    System.  Before calculating native longitude and latitude, this method will
    convert RA and Dec to observed geocentric coordinates.

    @param [in] ra is the RA of the star being transformed in radians
    (in the International Celestial Reference System)

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

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

    @param [out] lonOut is the native longitude in radians

    @param [out] latOut is the native latitude in radians
    """

    if not hasattr(ra_in, '__len__'):
        ra_temp, dec_temp = _observedFromICRS(np.array([ra_in]), np.array([dec_in]),
                                              obs_metadata=obs_metadata, epoch=2000.0,
                                              includeRefraction=True)

        ra = ra_temp[0]
        dec = dec_temp[0]
    else:
        ra, dec = _observedFromICRS(ra_in, dec_in,
                                    obs_metadata=obs_metadata, epoch=2000.0,
                                    includeRefraction=True)

    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]

    return _nativeLonLatFromPointing(ra, dec, raPointing, decPointing)
Ejemplo n.º 2
0
def controlAltAzFromRaDec(raRad_in, decRad_in, longRad, latRad, mjd):
    """
    Converts RA and Dec to altitude and azimuth

    @param [in] raRad is the RA in radians
    (observed geocentric)

    @param [in] decRad is the Dec in radians
    (observed geocentric)

    @param [in] longRad is the longitude of the observer in radians
    (positive east of the prime meridian)

    @param [in[ latRad is the latitude of the observer in radians
    (positive north of the equator)

    @param [in] mjd is the universal time expressed as an MJD

    @param [out] altitude in radians

    @param [out[ azimuth in radians

    see: http://www.stargazing.net/kepler/altaz.html#twig04
    """
    obs = utils.ObservationMetaData(mjd=utils.ModifiedJulianDate(UTC=mjd),
                                    site=utils.Site(longitude=np.degrees(longRad),
                                                    latitude=np.degrees(latRad),
                                                    name='LSST'))

    if hasattr(raRad_in, '__len__'):
        raRad, decRad = utils._observedFromICRS(raRad_in, decRad_in, obs_metadata=obs,
                                                epoch=2000.0, includeRefraction=True)
    else:
        raRad, decRad = utils._observedFromICRS(raRad_in, decRad_in,
                                                obs_metadata=obs, epoch=2000.0, includeRefraction=True)

    lst = utils.calcLmstLast(obs.mjd.UT1, longRad)
    last = lst[1]
    haRad = np.radians(last * 15.) - raRad

    sinDec = np.sin(decRad)
    cosLat = np.cos(latRad)
    sinLat = np.sin(latRad)
    sinAlt = sinDec*sinLat + np.cos(decRad)*cosLat*np.cos(haRad)
    altRad = np.arcsin(sinAlt)
    azRad = np.arccos((sinDec - sinAlt*sinLat) / (np.cos(altRad)*cosLat))
    azRadOut = np.where(np.sin(haRad) >= 0.0, 2.0 * np.pi - azRad, azRad)
    if isinstance(altRad, float):
        return altRad, float(azRadOut)
    return altRad, azRadOut
    def testObservedFromICRS(self):
        obs = ObservationMetaData(pointingRA=35.0, pointingDec=-45.0,
                                  mjd=43572.0)
        for pmRaList in [self.pm_raList, None]:
            for pmDecList in [self.pm_decList, None]:
                for pxList in [self.pxList, None]:
                    for vRadList in [self.v_radList, None]:
                        for includeRefraction in [True, False]:


                            raRad, decRad = utils._observedFromICRS(self.raList, self.decList,
                                                                         pm_ra=pmRaList, pm_dec=pmDecList,
                                                                         parallax=pxList, v_rad=vRadList,
                                                                         obs_metadata=obs, epoch=2000.0,
                                                                         includeRefraction=includeRefraction)

                            raDeg, decDeg = utils.observedFromICRS(np.degrees(self.raList), np.degrees(self.decList),
                                                                         pm_ra=utils.arcsecFromRadians(pmRaList),
                                                                         pm_dec=utils.arcsecFromRadians(pmDecList),
                                                                         parallax=utils.arcsecFromRadians(pxList),
                                                                         v_rad=vRadList,
                                                                         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)
Ejemplo n.º 4
0
 def get_phoSimCoordinates(self):
     ff = self.column_by_name('fitsFiles') # to force the catalog to draw the GalSim images
     ra = self.column_by_name('raJ2000')
     dec = self.column_by_name('decJ2000')
     raObs, decObs =  _observedFromICRS(ra, dec, includeRefraction = False, obs_metadata=self.obs_metadata,
                                        epoch=self.db_obj.epoch)
     return self._dePrecess(raObs, decObs, self.obs_metadata)
Ejemplo n.º 5
0
    def testObservedFromPupil(self):
        """
        Test conversion from pupil coordinates to observed coordinates
        """

        mjd = ModifiedJulianDate(TAI=53000.0)
        solarRA, solarDec = solarRaDec(mjd)

        # to make sure that we are more than 45 degrees from the Sun as required
        # for _icrsFromObserved to be at all accurate
        raCenter = solarRA + 100.0
        decCenter = solarDec - 30.0

        obs = ObservationMetaData(pointingRA=raCenter,
                                  pointingDec=decCenter,
                                  boundType='circle',
                                  boundLength=0.1,
                                  rotSkyPos=23.0,
                                  mjd=mjd)

        nSamples = 1000
        rng = np.random.RandomState(4453)
        ra = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(raCenter)
        dec = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(decCenter)
        xp, yp = _pupilCoordsFromRaDec(ra, dec, obs_metadata=obs, epoch=2000.0,
                                       includeRefraction=True)

        raObs, decObs = _observedFromICRS(ra, dec, obs_metadata=obs, epoch=2000.0,
                                          includeRefraction=True)

        raObs_test, decObs_test = _observedFromPupilCoords(xp, yp, obs_metadata=obs,
                                                           epoch=2000.0,
                                                           includeRefraction=True)

        dist = arcsecFromRadians(haversine(raObs, decObs, raObs_test, decObs_test))
        self.assertLess(dist.max(), 1.0e-6)

        # test output in degrees
        raObs_deg, decObs_deg = observedFromPupilCoords(xp, yp, obs_metadata=obs,
                                                        epoch=2000.0,
                                                        includeRefraction=True)

        np.testing.assert_array_almost_equal(raObs_deg, np.degrees(raObs_test), decimal=16)
        np.testing.assert_array_almost_equal(decObs_deg, np.degrees(decObs_test), decimal=16)

        # test one-at-a-time input
        for ii in range(len(raObs)):
            rr, dd = _observedFromPupilCoords(xp[ii], yp[ii],
                                              obs_metadata=obs,
                                              epoch=2000.0,
                                              includeRefraction=True)
            self.assertAlmostEqual(rr, raObs_test[ii], 16)
            self.assertAlmostEqual(dd, decObs_test[ii], 16)

            rr, dd = observedFromPupilCoords(xp[ii], yp[ii],
                                             obs_metadata=obs,
                                             epoch=2000.0,
                                             includeRefraction=True)
            self.assertAlmostEqual(rr, raObs_deg[ii], 16)
            self.assertAlmostEqual(dd, decObs_deg[ii], 16)
 def get_phoSimCoordinates(self):
     ff = self.column_by_name('fitsFiles') # to force the catalog to draw the GalSim images
     ra = self.column_by_name('raJ2000')
     dec = self.column_by_name('decJ2000')
     raObs, decObs =  _observedFromICRS(ra, dec, includeRefraction = False, obs_metadata=self.obs_metadata,
                                        epoch=self.db_obj.epoch)
     return self._dePrecess(raObs, decObs, self.obs_metadata)
Ejemplo n.º 7
0
    def testObservedRaDec(self):
        """
        Test that the mixins provided in Astrometry SSM really do convert ICRS RA, Dec
        into observed RA, Dec
        """

        dtype = np.dtype([('id', np.int),
                          ('raObserved', np.float), ('decObserved', np.float)])

        controlData = np.genfromtxt(self.dbFile, dtype=self.dtype)

        rng = np.random.RandomState(42)
        nTests = 5
        raList = rng.random_sample(nTests)*2.0*np.pi
        decList = (rng.random_sample(nTests)-0.5)*np.pi
        mjdList = rng.random_sample(nTests)*5000.0 + 53850.0
        for raPointing, decPointing, mjd in zip(raList, decList, mjdList):
            obs = ObservationMetaData(pointingRA=raPointing, pointingDec=decPointing, mjd=mjd)

            cat = SSM_astrometryCat(self.astDB, obs_metadata=obs)
            with lsst.utils.tests.getTempFilePath('.txt') as catName:
                cat.write_catalog(catName)

                testData = np.genfromtxt(catName, dtype=dtype, delimiter=',')
            self.assertGreater(len(testData), 0)

            raObservedControl, decObservedControl = _observedFromICRS(controlData['raJ2000'],
                                                                      controlData['decJ2000'],
                                                                      obs_metadata=obs, epoch=2000.0,
                                                                      includeRefraction=True)

            np.testing.assert_array_almost_equal(raObservedControl, testData['raObserved'], 10)
            np.testing.assert_array_almost_equal(decObservedControl, testData['decObserved'], 10)
Ejemplo n.º 8
0
    def observedStellarCoordinates(self, includeRefraction=True):
        """
        Getter which converts mean coordinates in the International Celestial
        Reference Frame to observed coordinates.
        """

        # TODO
        # are we going to store proper motion in raw radians per year
        # or in sky motion = cos(dec) * (radians per year)
        # PAL asks for radians per year inputs

        pr = self.column_by_name('properMotionRa')  # in radians per year
        pd = self.column_by_name('properMotionDec')  # in radians per year
        px = self.column_by_name('parallax')  # in radians
        rv = self.column_by_name(
            'radialVelocity')  # in km/s; positive if receding
        ra = self.column_by_name('raJ2000')
        dec = self.column_by_name('decJ2000')

        return _observedFromICRS(ra,
                                 dec,
                                 pm_ra=pr,
                                 pm_dec=pd,
                                 parallax=px,
                                 v_rad=rv,
                                 includeRefraction=includeRefraction,
                                 obs_metadata=self.obs_metadata,
                                 epoch=self.db_obj.epoch)
Ejemplo n.º 9
0
def _nativeLonLatFromRaDec(ra_in, dec_in, obs_metadata):
    """
    Convert the RA and Dec of a star into `native' longitude and latitude.

    Native longitude and latitude are defined as what RA and Dec would be
    if the celestial pole were at the location where the telescope is pointing.
    The transformation is achieved by rotating the vector pointing to the RA
    and Dec being transformed once about the x axis and once about the z axis.
    These are the Euler rotations referred to in Section 2.3 of

    Calabretta and Greisen (2002), A&A 395, p. 1077

    Note: RA, and Dec are assumed to be in the International Celestial Reference
    System.  Before calculating native longitude and latitude, this method will
    convert RA and Dec to observed geocentric coordinates.

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

    @param [in] ra is the RA of the star being transformed in radians
    (in the International Celestial Reference System)

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

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

    @param [out] lonOut is the native longitude in radians

    @param [out] latOut is the native latitude in radians
    """

    ra, dec = _observedFromICRS(ra_in,
                                dec_in,
                                obs_metadata=obs_metadata,
                                epoch=2000.0,
                                includeRefraction=True)

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

    return _nativeLonLatFromPointing(ra, dec, raPointing, decPointing)
Ejemplo n.º 10
0
    def testAltAzFromRaDec(self):
        """
        Test conversion from RA, Dec to Alt, Az
        """

        nSamples = 100
        ra = self.rng.random_sample(nSamples)*2.0*np.pi
        dec = (self.rng.random_sample(nSamples)-0.5)*np.pi
        lon_rad = 1.467
        lat_rad = -0.234
        controlAlt, controlAz = controlAltAzFromRaDec(ra, dec,
                                                      lon_rad, lat_rad,
                                                      self.mjd)

        obs = utils.ObservationMetaData(mjd=utils.ModifiedJulianDate(UTC=self.mjd),
                                        site=utils.Site(longitude=np.degrees(lon_rad),
                                                        latitude=np.degrees(lat_rad),
                                                        name='LSST'))

        # verify parallactic angle against an expression from
        # http://www.astro.washington.edu/groups/APO/Mirror.Motions/Feb.2000.Image.Jumps/report.html#Image%20motion%20directions
        #
        ra_obs, dec_obs = utils._observedFromICRS(ra, dec, obs_metadata=obs, epoch=2000.0,
                                                  includeRefraction=True)

        lmst, last = utils.calcLmstLast(obs.mjd.UT1, lon_rad)
        hourAngle = np.radians(last * 15.0) - ra_obs
        controlSinPa = np.sin(hourAngle) * np.cos(lat_rad) / np.cos(controlAlt)

        testAlt, testAz, testPa = utils._altAzPaFromRaDec(ra, dec, obs)

        distance = utils.arcsecFromRadians(utils.haversine(controlAz, controlAlt, testAz, testAlt))
        self.assertLess(distance.max(), 0.0001)
        self.assertLess(np.abs(np.sin(testPa) - controlSinPa).max(), self.tolerance)

        # test non-vectorized version
        for r, d in zip(ra, dec):
            controlAlt, controlAz = controlAltAzFromRaDec(r, d, lon_rad, lat_rad, self.mjd)
            testAlt, testAz, testPa = utils._altAzPaFromRaDec(r, d, obs)
            lmst, last = utils.calcLmstLast(obs.mjd.UT1, lon_rad)
            r_obs, dec_obs = utils._observedFromICRS(r, d, obs_metadata=obs,
                                                     epoch=2000.0, includeRefraction=True)
            hourAngle = np.radians(last * 15.0) - r_obs
            controlSinPa = np.sin(hourAngle) * np.cos(lat_rad) / np.cos(controlAlt)
            distance = utils.arcsecFromRadians(utils.haversine(controlAz, controlAlt, testAz, testAlt))
            self.assertLess(distance, 0.0001)
            self.assertLess(np.abs(np.sin(testPa) - controlSinPa), self.tolerance)
Ejemplo n.º 11
0
    def test_de_precession(self):
        """
        test de-precession by de-precessing a list of RA, Dec
        and verifying that the distance between the de-precessed
        points is the same as the distance between the input points.

        Also verify that the observed boresite gets de-precessed correctly
        """
        rng = np.random.RandomState(12)
        n_samples = 5
        pra = 34.0
        pdec = 65.0
        obs = ObservationMetaData(pointingRA=pra,
                                  pointingDec=pdec,
                                  mjd=58324.1)

        raObs, decObs = _observedFromICRS(np.array([np.radians(pra)]),
                                          np.array([np.radians(pdec)]),
                                          obs_metadata=obs,
                                          epoch=2000.0,
                                          includeRefraction=False)

        ra_list = []
        dec_list = []
        ra_list.append(raObs[0])
        dec_list.append(decObs[0])
        for rr, dd in zip(
                rng.random_sample(n_samples) * 2.0 * np.pi,
            (rng.random_sample(n_samples) - 0.5) * np.pi):

            ra_list.append(rr)
            dec_list.append(dd)

        ra_list = np.array(ra_list)
        dec_list = np.array(dec_list)

        raDecTransformed = PhoSimAstrometryBase()._dePrecess(
            ra_list, dec_list, obs)
        dd = arcsecFromRadians(
            haversine(np.radians(pra), np.radians(pdec),
                      raDecTransformed[0][0], raDecTransformed[1][0]))
        self.assertLess(dd, 1.0e-6)
        dd0 = arcsecFromRadians(
            haversine(raObs[0], decObs[0], np.radians(pra), np.radians(pdec)))
        self.assertLess(dd, dd0)

        for ix in range(n_samples + 1):
            for iy in range(n_samples + 1):
                if ix != iy:
                    dd1 = arcsecFromRadians(
                        haversine(ra_list[ix], dec_list[ix], ra_list[iy],
                                  dec_list[iy]))
                    dd2 = arcsecFromRadians(
                        haversine(raDecTransformed[0][ix],
                                  raDecTransformed[1][ix],
                                  raDecTransformed[0][iy],
                                  raDecTransformed[1][iy]))

                    self.assertAlmostEqual(dd1, dd2, delta=6)
Ejemplo n.º 12
0
    def _dePrecess(self, ra_in, dec_in, obs):
        """
        Transform a set of RA, Dec pairs by subtracting out a rotation
        which represents the effects of precession, nutation, and aberration.

        Specifically:

        Calculate the displacement between the boresite and the boresite
        corrected for precession, nutation, and aberration (not refraction).

        Convert boresite and corrected boresite to Cartesian coordinates.

        Calculate the rotation matrix to go between those Cartesian vectors.

        Convert [ra_in, dec_in] into Cartesian coordinates.

        Apply the rotation vector to those Cartesian coordinates.

        Convert back to ra, dec-like coordinates

        @param [in] ra_in is a numpy array of RA in radians

        @param [in] dec_in is a numpy array of Dec in radians

        @param [in] obs is an ObservationMetaData

        @param [out] ra_out is a numpy array of de-precessed RA in radians

        @param [out] dec_out is a numpy array of de-precessed Dec in radians
        """

        if len(ra_in) == 0:
            return np.array([[], []])

        precessedRA, precessedDec = _observedFromICRS(obs._pointingRA,
                                                      obs._pointingDec,
                                                      obs_metadata=obs,
                                                      epoch=2000.0,
                                                      includeRefraction=False)

        if (not hasattr(self, '_icrs_to_phosim_rotator') or arcsecFromRadians(
                _angularSeparation(obs._pointingRA, obs._pointingDec,
                                   self._icrs_to_phosim_rotator._ra1,
                                   self._icrs_to_phosim_rotator._dec1)) >
                1.0e-6 or arcsecFromRadians(
                    _angularSeparation(precessedRA, precessedDec,
                                       self._icrs_to_phosim_rotator._ra0,
                                       self._icrs_to_phosim_rotator._dec0)) >
                1.0e-6):

            self._icrs_to_phosim_rotator = _FieldRotator(
                precessedRA, precessedDec, obs._pointingRA, obs._pointingDec)

        ra_deprecessed, dec_deprecessed = self._icrs_to_phosim_rotator.transform(
            ra_in, dec_in)

        return np.array([ra_deprecessed, dec_deprecessed])
Ejemplo n.º 13
0
    def get_phosim_coords(self, ra, dec, obs_metadata):

        raObs, decObs = _observedFromICRS(ra,
                                          dec,
                                          includeRefraction=False,
                                          obs_metadata=obs_metadata,
                                          epoch=2000.0)

        return self._dePrecess(raObs, decObs, obs_metadata)
Ejemplo n.º 14
0
 def get_observedCoordinates(self):
     """Getter for observed RA, Dec (i.e. RA and Dec with all effects due to the motion
     of the Earth and refraction by the atmosphere applied)"""
     ra = self.column_by_name('raJ2000')
     dec = self.column_by_name('decJ2000')
     return _observedFromICRS(ra,
                              dec,
                              obs_metadata=self.obs_metadata,
                              epoch=self.db_obj.epoch)
Ejemplo n.º 15
0
    def observedSSMCoordinates(self, includeRefraction = True):
        """
        Reads in ICRS coordinates from the database.  Returns observed coordinates
        with refraction toggled on or off based on the input boolean includeRefraction
        """
        ra = self.column_by_name('raJ2000')  # in radians
        dec = self.column_by_name('decJ2000')  # in radians

        return _observedFromICRS(ra, dec, includeRefraction=includeRefraction,
                                 obs_metadata=self.obs_metadata, epoch=self.db_obj.epoch)
Ejemplo n.º 16
0
    def observedSSMCoordinates(self, includeRefraction = True):
        """
        Reads in ICRS coordinates from the database.  Returns observed coordinates
        with refraction toggled on or off based on the input boolean includeRefraction
        """
        ra = self.column_by_name('raJ2000')  # in radians
        dec = self.column_by_name('decJ2000')  # in radians

        return _observedFromICRS(ra, dec, includeRefraction=includeRefraction,
                                 obs_metadata=self.obs_metadata, epoch=self.db_obj.epoch)
Ejemplo n.º 17
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))
Ejemplo n.º 18
0
    def _dePrecess(self, ra_in, dec_in, obs):
        """
        Transform a set of RA, Dec pairs by subtracting out a rotation
        which represents the effects of precession, nutation, and aberration.

        Specifically:

        Calculate the displacement between the boresite and the boresite
        corrected for precession, nutation, and aberration (not refraction).

        Convert boresite and corrected boresite to Cartesian coordinates.

        Calculate the rotation matrix to go between those Cartesian vectors.

        Convert [ra_in, dec_in] into Cartesian coordinates.

        Apply the rotation vector to those Cartesian coordinates.

        Convert back to ra, dec-like coordinates

        @param [in] ra_in is a numpy array of RA in radians

        @param [in] dec_in is a numpy array of Dec in radians

        @param [in] obs is an ObservationMetaData

        @param [out] ra_out is a numpy array of de-precessed RA in radians

        @param [out] dec_out is a numpy array of de-precessed Dec in radians
        """

        if len(ra_in) == 0:
            return np.array([[], []])


        precessedRA, precessedDec = _observedFromICRS(obs._pointingRA,obs._pointingDec,
                                                      obs_metadata=obs, epoch=2000.0,
                                                      includeRefraction=False)

        if (not hasattr(self, '_icrs_to_phosim_rotator') or
            arcsecFromRadians(_angularSeparation(obs._pointingRA, obs._pointingDec,
                                                 self._icrs_to_phosim_rotator._ra1,
                                                 self._icrs_to_phosim_rotator._dec1))>1.0e-6 or
            arcsecFromRadians(_angularSeparation(precessedRA, precessedDec,
                                                 self._icrs_to_phosim_rotator._ra0,
                                                 self._icrs_to_phosim_rotator._dec0))>1.0e-6):

            self._icrs_to_phosim_rotator = _FieldRotator(precessedRA, precessedDec,
                                                         obs._pointingRA, obs._pointingDec)

        ra_deprecessed, dec_deprecessed = self._icrs_to_phosim_rotator.transform(ra_in, dec_in)

        return np.array([ra_deprecessed, dec_deprecessed])
Ejemplo n.º 19
0
    def _dePrecess(self, ra_in, dec_in, obs_metadata):
        """
        Transform a set of RA, Dec pairs by subtracting out a rotation
        which represents the effects of precession, nutation, and aberration.

        Specifically:

        Calculate the displacement between the boresite and the boresite
        corrected for precession, nutation, and aberration (not refraction).

        Convert boresite and corrected boresite to Cartesian coordinates.

        Calculate the rotation matrix to go between those Cartesian vectors.

        Convert [ra_in, dec_in] into Cartesian coordinates.

        Apply the rotation vector to those Cartesian coordinates.

        Convert back to ra, dec-like coordinates

        @param [in] ra_in is a numpy array of RA in radians

        @param [in] dec_in is a numpy array of Dec in radians

        @param [in] obs_metadata is an ObservationMetaData

        @param [out] ra_out is a numpy array of de-precessed RA in radians

        @param [out] dec_out is a numpy array of de-precessed Dec in radians
        """

        if len(ra_in) == 0:
            return np.array([[], []])

        # Calculate the rotation matrix to go from the precessed bore site
        # to the ICRS 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_precessed[0], xyz_bore[0])

        xyz_list = cartesianFromSpherical(ra_in, dec_in)

        xyz_de_precessed = np.array([np.dot(rotMat, xx) for xx in xyz_list])
        ra_deprecessed, dec_deprecessed = sphericalFromCartesian(xyz_de_precessed)
        return np.array([ra_deprecessed, dec_deprecessed])
Ejemplo n.º 20
0
def _altAzPaFromRaDec(raRad, decRad, obs, includeRefraction=True):
    """
    Convert RA, Dec, longitude, latitude and MJD into altitude, azimuth
    and parallactic angle using PALPY

    @param [in] raRad is RA in radians.  Can be a numpy array or a single value.
    Assumed to be in the International Celestial Reference System.

    @param [in] decRad is Dec in radians.  Can be a numpy array or a single value.
    Assumed to be in the International Celestial Reference System.

    @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] altitude in radians

    @param [out] azimuth in radians

    @param [out] parallactic angle in radians

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

    are_arrays = _validate_inputs([raRad, decRad], ['ra', 'dec'],
                                  "altAzPaFromRaDec")

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

    lst = calcLmstLast(obs.mjd.UT1, obs.site.longitude_rad)
    last = lst[1]
    haRad = np.radians(last * 15.0) - raObs

    if are_arrays:
        az, azd, azdd, \
            alt, altd, altdd, \
            pa, pad, padd = palpy.altazVector(
                haRad, decObs, obs.site.latitude_rad)
    else:
        az, azd, azdd, \
            alt, altd, altdd, \
            pa, pad, padd = palpy.altaz(haRad, decObs, obs.site.latitude_rad)

    return alt, az, pa
def _altAzPaFromRaDec(raRad, decRad, obs, includeRefraction=True):
    """
    Convert RA, Dec, longitude, latitude and MJD into altitude, azimuth
    and parallactic angle using PALPY

    @param [in] raRad is RA in radians.  Can be a numpy array or a single value.
    Assumed to be in the International Celestial Reference System.

    @param [in] decRad is Dec in radians.  Can be a numpy array or a single value.
    Assumed to be in the International Celestial Reference System.

    @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] altitude in radians

    @param [out] azimuth in radians

    @param [out] parallactic angle in radians

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

    are_arrays = _validate_inputs([raRad, decRad], ['ra', 'dec'],
                                  "altAzPaFromRaDec")

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

    lst = calcLmstLast(obs.mjd.UT1, obs.site.longitude_rad)
    last = lst[1]
    haRad = np.radians(last * 15.0) - raObs

    if are_arrays:
        az, azd, azdd, \
            alt, altd, altdd, \
            pa, pad, padd = palpy.altazVector(
                haRad, decObs, obs.site.latitude_rad)
    else:
        az, azd, azdd, \
            alt, altd, altdd, \
            pa, pad, padd = palpy.altaz(haRad, decObs, obs.site.latitude_rad)

    return alt, az, pa
Ejemplo n.º 22
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
Ejemplo n.º 23
0
    def test_de_precession(self):
        """
        test de-precession by de-precessing a list of RA, Dec
        and verifying that the distance between the de-precessed
        points is the same as the distance between the input points.

        Also verify that the observed boresite gets de-precessed correctly
        """
        rng = np.random.RandomState(12)
        n_samples = 5
        pra = 34.0
        pdec = 65.0
        obs = ObservationMetaData(pointingRA=pra,
                                  pointingDec=pdec,
                                  mjd=58324.1)

        raObs, decObs = _observedFromICRS(np.array([np.radians(pra)]),
                                          np.array([np.radians(pdec)]),
                                          obs_metadata=obs, epoch=2000.0,
                                          includeRefraction=False)

        ra_list = []
        dec_list = []
        ra_list.append(raObs[0])
        dec_list.append(decObs[0])
        for rr, dd in zip(rng.random_sample(n_samples)*2.0*np.pi,
                          (rng.random_sample(n_samples)-0.5)*np.pi):

            ra_list.append(rr)
            dec_list.append(dd)

        ra_list = np.array(ra_list)
        dec_list = np.array(dec_list)

        raDecTransformed = PhoSimAstrometryBase()._dePrecess(ra_list, dec_list, obs)
        dd = arcsecFromRadians(haversine(np.radians(pra), np.radians(pdec),
                               raDecTransformed[0][0], raDecTransformed[1][0]))
        self.assertLess(dd, 1.0e-6)
        dd0 = arcsecFromRadians(haversine(raObs[0], decObs[0], np.radians(pra), np.radians(pdec)))
        self.assertLess(dd, dd0)

        for ix in range(n_samples+1):
            for iy in range(n_samples+1):
                if ix != iy:
                    dd1 = arcsecFromRadians(haversine(ra_list[ix], dec_list[ix], ra_list[iy], dec_list[iy]))
                    dd2 = arcsecFromRadians(haversine(raDecTransformed[0][ix], raDecTransformed[1][ix],
                                                      raDecTransformed[0][iy], raDecTransformed[1][iy]))

                    self.assertAlmostEqual(dd1, dd2, delta=6)
    def get_phoSimCoordinates(self):
        """Getter for RA, Dec coordinates expected by PhoSim.

        These are observed RA, Dec coordinates with the effects of nutation, aberration,
        and precession subtracted out by the PhosimInputBase._dePrecess() method.
        This preserves the relative effects of nutation, aberration, and precession while
        re-aligning the catalog with the boresite RA, Dec so that astrometric solutions
        make sense."""

        ra = self.column_by_name('raJ2000')
        dec = self.column_by_name('decJ2000')
        raObs, decObs = _observedFromICRS(ra, dec, includeRefraction = False, obs_metadata=self.obs_metadata,
                                          epoch=self.db_obj.epoch)

        return self._dePrecess(raObs, decObs, self.obs_metadata)
Ejemplo n.º 25
0
    def get_phoSimCoordinates(self):
        """Getter for RA, Dec coordinates expected by PhoSim.

        These are observed RA, Dec coordinates with the effects of nutation, aberration,
        and precession subtracted out by the PhosimInputBase._dePrecess() method.
        This preserves the relative effects of nutation, aberration, and precession while
        re-aligning the catalog with the boresite RA, Dec so that astrometric solutions
        make sense."""

        ra = self.column_by_name('raJ2000')
        dec = self.column_by_name('decJ2000')
        raObs, decObs = _observedFromICRS(ra, dec, includeRefraction = False, obs_metadata=self.obs_metadata,
                                          epoch=self.db_obj.epoch)

        return self._dePrecess(raObs, decObs, self.obs_metadata)
Ejemplo n.º 26
0
    def _appGeoFromPhoSim(self, raPhoSim, decPhoSim, obs):
        """
        This method will convert from the 'deprecessed' coordinates expected by
        PhoSim to apparent geocentric coordinates

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

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

        obs is an ObservationMetaData characterizing the
        telescope pointing

        Returns
        -------
        apparent geocentric RA in radians

        apparent geocentric Dec in radians
        """
        precessedRA, precessedDec = _observedFromICRS(obs._pointingRA,
                                                      obs._pointingDec,
                                                      obs_metadata=obs,
                                                      epoch=2000.0,
                                                      includeRefraction=False)

        if (not hasattr(self, '_phosim_to_icrs_rotator') or arcsecFromRadians(
                _angularSeparation(obs._pointingRA, obs._pointingDec,
                                   self._phosim_to_icrs_rotator._ra0,
                                   self._phosim_to_icrs_rotator._dec0)) >
                1.0e-6 or arcsecFromRadians(
                    _angularSeparation(precessedRA, precessedDec,
                                       self._phosim_to_icrs_rotator._ra1,
                                       self._phosim_to_icrs_rotator._dec1)) >
                1.0e-6):

            self._phosim_to_icrs_rotator = _FieldRotator(
                obs._pointingRA, obs._pointingDec, precessedRA, precessedDec)

        ra_obs, dec_obs = self._phosim_to_icrs_rotator.transform(
            raPhoSim, decPhoSim)

        return _appGeoFromObserved(ra_obs,
                                   dec_obs,
                                   includeRefraction=False,
                                   obs_metadata=obs)
Ejemplo n.º 27
0
    def testObservedRaDec(self):
        """
        Test that the mixins provided in Astrometry SSM really do convert ICRS RA, Dec
        into observed RA, Dec
        """

        catName = os.path.join(getPackageDir('sims_catUtils'), 'tests',
                               'scratchSpace', 'ssmAstrometryCat.txt')

        dtype = np.dtype([('id', np.int), ('raObserved', np.float),
                          ('decObserved', np.float)])

        controlData = np.genfromtxt(self.dbFile, dtype=self.dtype)

        rng = np.random.RandomState(42)
        nTests = 5
        raList = rng.random_sample(nTests) * 2.0 * np.pi
        decList = (rng.random_sample(nTests) - 0.5) * np.pi
        mjdList = rng.random_sample(nTests) * 5000.0 + 53850.0
        for raPointing, decPointing, mjd in zip(raList, decList, mjdList):
            obs = ObservationMetaData(pointingRA=raPointing,
                                      pointingDec=decPointing,
                                      mjd=mjd)

            cat = SSM_astrometryCat(self.astDB, obs_metadata=obs)
            cat.write_catalog(catName)

            testData = np.genfromtxt(catName, dtype=dtype, delimiter=',')
            self.assertGreater(len(testData), 0)

            raObservedControl, decObservedControl = _observedFromICRS(
                controlData['raJ2000'],
                controlData['decJ2000'],
                obs_metadata=obs,
                epoch=2000.0,
                includeRefraction=True)

            np.testing.assert_array_almost_equal(raObservedControl,
                                                 testData['raObserved'], 10)
            np.testing.assert_array_almost_equal(decObservedControl,
                                                 testData['decObserved'], 10)

            if os.path.exists(catName):
                os.unlink(catName)
Ejemplo n.º 28
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)
Ejemplo n.º 29
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
Ejemplo n.º 30
0
    def testObservedFromICRS(self):
        obs = ObservationMetaData(pointingRA=35.0,
                                  pointingDec=-45.0,
                                  mjd=43572.0)
        for pmRaList in [self.pm_raList, None]:
            for pmDecList in [self.pm_decList, None]:
                for pxList in [self.pxList, None]:
                    for vRadList in [self.v_radList, None]:
                        for includeRefraction in [True, False]:

                            raRad, decRad = utils._observedFromICRS(
                                self.raList,
                                self.decList,
                                pm_ra=pmRaList,
                                pm_dec=pmDecList,
                                parallax=pxList,
                                v_rad=vRadList,
                                obs_metadata=obs,
                                epoch=2000.0,
                                includeRefraction=includeRefraction)

                            raDeg, decDeg = utils.observedFromICRS(
                                np.degrees(self.raList),
                                np.degrees(self.decList),
                                pm_ra=utils.arcsecFromRadians(pmRaList),
                                pm_dec=utils.arcsecFromRadians(pmDecList),
                                parallax=utils.arcsecFromRadians(pxList),
                                v_rad=vRadList,
                                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)
Ejemplo n.º 31
0
    def test_stellar_observed_radians(self):
        """
        Test ability to go all the way to observed RA, Dec
        from PhoSim (this is necessary for the ImSim software
        that DESC is working on)
        """
        db = testStarsDBObj(driver='sqlite', database=self.db_name)
        cat = StarTestCatalog(db, obs_metadata=self.obs)
        with lsst.utils.tests.getTempFilePath('.txt') as cat_name:
            cat.write_catalog(cat_name)
            dtype = np.dtype([('raICRS', float), ('decICRS', float),
                             ('raPhoSim', float), ('decPhoSim', float),
                             ('raJ2000', float), ('decJ2000', float),
                             ('pmRA', float), ('pmDec', float),
                             ('parallax', float), ('vRad', float)])
            data = np.genfromtxt(cat_name, dtype=dtype)
        self.assertGreater(len(data), 100)

        (ra_obs,
         dec_obs) = _observedFromICRS(data['raJ2000'],
                                      data['decJ2000'],
                                      obs_metadata=self.obs,
                                      pm_ra=data['pmRA'],
                                      pm_dec=data['pmDec'],
                                      parallax=data['parallax'],
                                      v_rad=data['vRad'],
                                      includeRefraction=True,
                                      epoch=2000.0)

        (ra_appGeo,
         dec_appGeo) = PhoSimAstrometryBase._appGeoFromPhoSim(np.radians(data['raPhoSim']),
                                                              np.radians(data['decPhoSim']),
                                                              self.obs)

        (ra_obs_2,
         dec_obs_2) = _observedFromAppGeo(ra_appGeo, dec_appGeo,
                                          obs_metadata=self.obs,
                                          includeRefraction=True)

        dd = arcsecFromRadians(_angularSeparation(ra_obs, dec_obs, ra_obs_2, dec_obs_2))
        self.assertLess(dd.max(), 1.0e-5)
Ejemplo n.º 32
0
    def observedStellarCoordinates(self, includeRefraction = True):
        """
        Getter which converts mean coordinates in the International Celestial
        Reference Frame to observed coordinates.
        """

        # TODO
        # are we going to store proper motion in raw radians per year
        # or in sky motion = cos(dec) * (radians per year)
        # PAL asks for radians per year inputs

        pr = self.column_by_name('properMotionRa')  # in radians per year
        pd = self.column_by_name('properMotionDec')  # in radians per year
        px = self.column_by_name('parallax')  # in radians
        rv = self.column_by_name('radialVelocity')  # in km/s; positive if receding
        ra = self.column_by_name('raJ2000')
        dec = self.column_by_name('decJ2000')

        return _observedFromICRS(ra, dec, pm_ra = pr, pm_dec = pd, parallax = px, v_rad = rv,
                                 includeRefraction = includeRefraction, obs_metadata=self.obs_metadata,
                                 epoch=self.db_obj.epoch)
Ejemplo n.º 33
0
    def test_stellar_observed_radians(self):
        """
        Test ability to go all the way to observed RA, Dec
        from PhoSim (this is necessary for the ImSim software
        that DESC is working on)
        """
        db = testStarsDBObj(driver='sqlite', database=self.db_name)
        cat = StarTestCatalog(db, obs_metadata=self.obs)
        with lsst.utils.tests.getTempFilePath('.txt') as cat_name:
            cat.write_catalog(cat_name)
            dtype = np.dtype([('raICRS', float), ('decICRS', float),
                              ('raPhoSim', float), ('decPhoSim', float),
                              ('raJ2000', float), ('decJ2000', float),
                              ('pmRA', float), ('pmDec', float),
                              ('parallax', float), ('vRad', float)])
            data = np.genfromtxt(cat_name, dtype=dtype)
        self.assertGreater(len(data), 100)

        (ra_obs, dec_obs) = _observedFromICRS(data['raJ2000'],
                                              data['decJ2000'],
                                              obs_metadata=self.obs,
                                              pm_ra=data['pmRA'],
                                              pm_dec=data['pmDec'],
                                              parallax=data['parallax'],
                                              v_rad=data['vRad'],
                                              includeRefraction=True,
                                              epoch=2000.0)

        (ra_appGeo, dec_appGeo) = PhoSimAstrometryBase._appGeoFromPhoSim(
            np.radians(data['raPhoSim']), np.radians(data['decPhoSim']),
            self.obs)

        (ra_obs_2, dec_obs_2) = _observedFromAppGeo(ra_appGeo,
                                                    dec_appGeo,
                                                    obs_metadata=self.obs,
                                                    includeRefraction=True)

        dd = arcsecFromRadians(
            _angularSeparation(ra_obs, dec_obs, ra_obs_2, dec_obs_2))
        self.assertLess(dd.max(), 1.0e-5)
Ejemplo n.º 34
0
    def _appGeoFromPhoSim(self, raPhoSim, decPhoSim, obs):
        """
        This method will convert from the 'deprecessed' coordinates expected by
        PhoSim to apparent geocentric coordinates

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

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

        obs is an ObservationMetaData characterizing the
        telescope pointing

        Returns
        -------
        apparent geocentric RA in radians

        apparent geocentric Dec in radians
        """
        precessedRA, precessedDec = _observedFromICRS(obs._pointingRA,obs._pointingDec,
                                                      obs_metadata=obs, epoch=2000.0,
                                                      includeRefraction=False)

        if (not hasattr(self, '_phosim_to_icrs_rotator') or
            arcsecFromRadians(_angularSeparation(obs._pointingRA, obs._pointingDec,
                                                 self._phosim_to_icrs_rotator._ra0,
                                                 self._phosim_to_icrs_rotator._dec0))>1.0e-6 or
            arcsecFromRadians(_angularSeparation(precessedRA, precessedDec,
                                                 self._phosim_to_icrs_rotator._ra1,
                                                 self._phosim_to_icrs_rotator._dec1))>1.0e-6):

            self._phosim_to_icrs_rotator = _FieldRotator(obs._pointingRA, obs._pointingDec,
                                                         precessedRA, precessedDec)

        ra_obs, dec_obs = self._phosim_to_icrs_rotator.transform(raPhoSim, decPhoSim)

        return _appGeoFromObserved(ra_obs, dec_obs, includeRefraction=False,
                                   obs_metadata=obs)
    def testObservedRaDec(self):
        """
        Test that the mixins provided in Astrometry SSM really do convert ICRS RA, Dec
        into observed RA, Dec
        """

        catName = os.path.join(getPackageDir('sims_catUtils'), 'tests', 'scratchSpace', 'ssmAstrometryCat.txt')

        dtype = np.dtype([('id', np.int),
                          ('raObserved', np.float), ('decObserved', np.float)])

        controlData = np.genfromtxt(self.dbFile, dtype=self.dtype)

        np.random.seed(42)
        nTests = 5
        raList = np.random.random_sample(nTests)*2.0*np.pi
        decList = (np.random.random_sample(nTests)-0.5)*np.pi
        mjdList = np.random.random_sample(nTests)*5000.0 + 53850.0
        for raPointing, decPointing, mjd in zip(raList, decList, mjdList):
            obs = ObservationMetaData(pointingRA=raPointing, pointingDec=decPointing, mjd=mjd)

            cat = SSM_astrometryCat(self.astDB, obs_metadata=obs)
            cat.write_catalog(catName)

            testData = np.genfromtxt(catName, dtype=dtype, delimiter=',')
            self.assertGreater(len(testData), 0)

            raObservedControl, decObservedControl = _observedFromICRS(controlData['raJ2000'], controlData['decJ2000'],
                                                                      obs_metadata=obs, epoch=2000.0,
                                                                      includeRefraction=True)

            np.testing.assert_array_almost_equal(raObservedControl, testData['raObserved'], 10)
            np.testing.assert_array_almost_equal(decObservedControl, testData['decObserved'], 10)

            if os.path.exists(catName):
                os.unlink(catName)
def _altAzPaFromRaDec(raRad, decRad, obs):
    """
    Convert RA, Dec, longitude, latitude and MJD into altitude, azimuth
    and parallactic angle using PALPY

    @param [in] raRad is RA in radians.  Can be a numpy array or a single value.
    Assumed to be in the International Celestial Reference System.

    @param [in] decRad is Dec in radians.  Can be a numpy array or a single value.
    Assumed to be in the International Celestial Reference System.

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

    @param [out] altitude in radians

    @param [out] azimuth in radians

    @param [out] parallactic angle in radians
    """

    raIsArray = False
    decIsArray = False
    if isinstance(raRad, np.ndarray):
        raIsArray = True

    if isinstance(decRad, np.ndarray):
        decIsArray = True

    if raIsArray and not decIsArray:
        raise RuntimeError('passed numpy array of RA to altAzPaFromRaDec; but only one Dec')

    if decIsArray and not raIsArray:
        raise RuntimeError('passed numpy array of Dec to altAzPaFromRaDec; but only one RA')

    if raIsArray and decIsArray and len(raRad) != len(decRad):
        raise RuntimeError('in altAzPaFromRaDec length of RA numpy array does not match length of Dec numpy array')


    if not hasattr(raRad, '__len__'):
        raObs_temp, decObs_temp = _observedFromICRS(np.array([raRad]), np.array([decRad]), obs_metadata=obs,
                                                      includeRefraction=True, epoch=2000.0)

        raObs = raObs_temp[0]
        decObs = decObs_temp[0]


    else:
        raObs, decObs = _observedFromICRS(raRad, decRad, obs_metadata=obs, epoch=2000.0, includeRefraction=True)

    lst = calcLmstLast(obs.mjd.UT1, obs.site.longitude_rad)
    last = lst[1]
    haRad = np.radians(last*15.0) - raObs

    if isinstance(haRad, np.ndarray):
        az, azd, azdd, \
        alt, altd, altdd, \
        pa, pad, padd = palpy.altazVector(haRad, decObs, obs.site.latitude_rad)
    else:
        az, azd, azdd, \
        alt, altd, altdd, \
        pa, pad, padd = palpy.altaz(haRad, decObs, obs.site.latitude_rad)

    return alt, az, pa
Ejemplo n.º 37
0
def _observedFromPupilCoords(xPupil, yPupil, obs_metadata=None,
                             includeRefraction=True,
                             epoch=2000.0):
    """
    Convert pupil coordinates into observed (RA, Dec)

    @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[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 [out] a 2-D numpy array in which the first row is observed RA and the second
    row is observed Dec (both in radians).  Note: these are not ICRS coordinates.
    These are RA and Dec-like coordinates resulting from applying precession, nutation,
    diurnal aberration and annual aberration on top of ICRS coordinates.

    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'],
                                  "observedFromPupilCoords")

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

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

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

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

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

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

    # 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 = 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 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)

    return raObs, decObs
Ejemplo n.º 38
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)
Ejemplo n.º 39
0
def _pupilCoordsFromRaDec(ra_in,
                          dec_in,
                          pm_ra=None,
                          pm_dec=None,
                          parallax=None,
                          v_rad=None,
                          includeRefraction=True,
                          obs_metadata=None,
                          epoch=2000.0):
    """
    Take an input RA and dec from the sky and convert it to coordinates
    on the focal plane.

    This uses PAL's gnomonic projection routine which assumes that the focal
    plane is perfectly flat.  The output is in Cartesian coordinates, assuming
    that the Celestial Sphere is a unit sphere.

    The RA, Dec accepted by this method are in the International Celestial
    Reference System.  Before applying the gnomonic projection, this method
    transforms those RA, Dec into observed geocentric coordinates, applying
    the effects of precession, nutation, aberration, parallax and refraction.
    This is done, because the gnomonic projection ought to be applied to what
    observers actually see, rather than the idealized, above-the-atmosphere
    coordinates represented by the ICRS.

    @param [in] ra_in is in radians (ICRS).  Can be either a numpy array or a number.

    @param [in] dec_in is in radians (ICRS).  Can be either a numpy array or a number.

    @param [in] pm_ra is proper motion in RA multiplied by cos(Dec) (radians/yr)
    Can be a numpy array or a number or None (default=None).

    @param [in] pm_dec is proper motion in dec (radians/yr)
    Can be a numpy array or a number or None (default=None).

    @param [in] parallax is parallax in radians
    Can be a numpy array or a number or None (default=None).

    @param [in] v_rad is radial velocity (km/s)
    Can be a numpy array or a number or None (default=None).

    @param [in] includeRefraction is a boolean controlling the application of refraction.

    @param [in] obs_metadata is an ObservationMetaData instantiation characterizing the
    telescope location and pointing.

    @param [in] epoch is the epoch of mean ra and dec in julian years (default=2000.0)

    @param [out] returns a numpy array whose first row is the x coordinate on the pupil in
    radians and whose second row is the y coordinate in radians
    """

    are_arrays = _validate_inputs([ra_in, dec_in], ['ra_in', 'dec_in'],
                                  "pupilCoordsFromRaDec")

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

    if obs_metadata.mjd is None:
        raise RuntimeError(
            "Cannot call pupilCoordsFromRaDec; obs_metadata.mjd is None")

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

    if obs_metadata.rotSkyPos is None:
        # there is no observation meta data on which to base astrometry
        raise RuntimeError(
            "Cannot calculate [x,y]_focal_nominal without obs_metadata.rotSkyPos"
        )

    if obs_metadata.pointingRA is None or obs_metadata.pointingDec is None:
        raise RuntimeError(
            "Cannot calculate [x,y]_focal_nominal without pointingRA and Dec in obs_metadata"
        )

    ra_obs, dec_obs = _observedFromICRS(ra_in,
                                        dec_in,
                                        pm_ra=pm_ra,
                                        pm_dec=pm_dec,
                                        parallax=parallax,
                                        v_rad=v_rad,
                                        obs_metadata=obs_metadata,
                                        epoch=epoch,
                                        includeRefraction=includeRefraction)

    return _pupilCoordsFromObserved(ra_obs,
                                    dec_obs,
                                    obs_metadata,
                                    epoch=epoch,
                                    includeRefraction=includeRefraction)
Ejemplo n.º 40
0
def _pupilCoordsFromObserved(ra_obs,
                             dec_obs,
                             obs_metadata,
                             epoch=2000.0,
                             includeRefraction=True):
    """
    Convert Observed RA, Dec into pupil coordinates

    Parameters
    ----------
    ra_obs is the observed RA in radians

    dec_obs is the observed Dec in radians

    obs_metadata is an ObservationMetaData characterizing the telescope location and pointing

    epoch is the epoch of the mean RA and Dec in julian years (default=2000.0)

    includeRefraction is a boolean controlling the application of refraction.

    Returns
    --------
    A numpy array whose first row is the x coordinate on the pupil in
    radians and whose second row is the y coordinate in radians
    """

    are_arrays = _validate_inputs([ra_obs, dec_obs], ['ra_obs', 'dec_obs'],
                                  "pupilCoordsFromObserved")

    if obs_metadata.rotSkyPos is None:
        raise RuntimeError("Cannot call pupilCoordsFromObserved; "
                           "rotSkyPos is None")

    theta = obs_metadata._rotSkyPos

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

    # palpy.ds2tp performs the gnomonic projection on ra_in and dec_in
    # with a tangent point at (pointingRA, pointingDec)
    #
    if not are_arrays:
        try:
            x, y = palpy.ds2tp(ra_obs, dec_obs, ra_pointing, dec_pointing)
        except:
            x = np.NaN
            y = np.NaN
    else:
        try:
            x, y = palpy.ds2tpVector(ra_obs, dec_obs, ra_pointing,
                                     dec_pointing)
        except:
            # apparently, one of your ra/dec values was improper; we will have to do this
            # element-wise, putting NaN in the place of the bad values
            x = []
            y = []
            for rr, dd in zip(ra_obs, dec_obs):
                try:
                    xx, yy = palpy.ds2tp(rr, dd, ra_pointing, dec_pointing)
                except:
                    xx = np.NaN
                    yy = np.NaN
                x.append(xx)
                y.append(yy)
            x = np.array(x)
            y = np.array(y)

    # The extra negative sign on x_out comes from the following:
    # The Gnomonic projection as calculated by palpy is such that,
    # if north is in the +y direction, then west is in the -x direction,
    # which is the opposite of the behavior we want (I do not know how to
    # express this analytically; I have just confirmed it numerically)
    x *= -1.0

    # rotate the result by rotskypos (rotskypos being "the angle of the sky relative to
    # camera coordinates" according to phoSim documentation) to account for
    # the rotation of the focal plane about the telescope pointing

    x_out = x * np.cos(theta) - y * np.sin(theta)
    y_out = x * np.sin(theta) + y * np.cos(theta)

    return np.array([x_out, y_out])
    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)
Ejemplo n.º 42
0
 def get_observedCoordinates(self):
     """Getter for observed RA, Dec (i.e. RA and Dec with all effects due to the motion
     of the Earth and refraction by the atmosphere applied)"""
     ra = self.column_by_name('raJ2000')
     dec = self.column_by_name('decJ2000')
     return _observedFromICRS(ra, dec, obs_metadata=self.obs_metadata, epoch=self.db_obj.epoch)
    def testAstrometryExceptions(self):
        """
        Test to make sure that stand-alone astrometry methods raise an exception when they are called without
        the necessary arguments
        """
        obs_metadata = makeObservationMetaData()
        ra, dec, pm_ra, pm_dec, parallax, v_rad = makeRandomSample()

        raShort = numpy.array([1.0])
        decShort = numpy.array([1.0])


        ##########test refractionCoefficients
        self.assertRaises(RuntimeError, refractionCoefficients)
        site = obs_metadata.site
        x, y = refractionCoefficients(site=site)

        ##########test applyRefraction
        zd = 0.1
        rzd = applyRefraction(zd, x, y)

        zd = [0.1, 0.2]
        self.assertRaises(RuntimeError, applyRefraction, zd, x, y)

        zd = numpy.array([0.1, 0.2])
        rzd = applyRefraction(zd, x, y)

        ##########test _applyPrecession
        #test without mjd
        self.assertRaises(RuntimeError, _applyPrecession, ra, dec)

        #test mismatches
        self.assertRaises(RuntimeError, _applyPrecession, raShort, dec,
                          mjd=ModifiedJulianDate(TAI=52000.0))
        self.assertRaises(RuntimeError, _applyPrecession, ra, decShort,
                          mjd=ModifiedJulianDate(TAI=52000.0))

        #test that it runs
        _applyPrecession(ra, dec, mjd=ModifiedJulianDate(TAI=52000.0))

        ##########test _applyProperMotion
        raList = list(ra)
        decList = list(dec)
        pm_raList = list(pm_ra)
        pm_decList = list(pm_dec)
        parallaxList = list(parallax)
        v_radList = list(v_rad)

        pm_raShort = numpy.array([pm_ra[0]])
        pm_decShort = numpy.array([pm_dec[0]])
        parallaxShort = numpy.array([parallax[0]])
        v_radShort = numpy.array([v_rad[0]])

        #test without mjd
        self.assertRaises(RuntimeError, _applyProperMotion,
                          ra, dec, pm_ra, pm_dec, parallax, v_rad)

        #test passing lists
        self.assertRaises(RuntimeError, _applyProperMotion,
                          raList, dec, pm_ra, pm_dec, parallax, v_rad,
                          mjd=ModifiedJulianDate(TAI=52000.0))
        self.assertRaises(RuntimeError, _applyProperMotion,
                          ra, decList, pm_ra, pm_dec, parallax, v_rad,
                          mjd=ModifiedJulianDate(TAI=52000.0))
        self.assertRaises(RuntimeError, _applyProperMotion,
                          ra, dec, pm_raList, pm_dec, parallax, v_rad,
                          mjd=ModifiedJulianDate(TAI=52000.0))
        self.assertRaises(RuntimeError, _applyProperMotion,
                          ra, dec, pm_ra, pm_decList, parallax, v_rad,
                          mjd=ModifiedJulianDate(TAI=52000.0))
        self.assertRaises(RuntimeError, _applyProperMotion,
                          ra, dec, pm_ra, pm_dec, parallaxList, v_rad,
                          mjd=ModifiedJulianDate(TAI=52000.0))
        self.assertRaises(RuntimeError, _applyProperMotion,
                          ra, dec, pm_ra, pm_dec, parallax, v_radList,
                          mjd=ModifiedJulianDate(TAI=52000.0))

        #test mismatches
        self.assertRaises(RuntimeError, _applyProperMotion,
                          raShort, dec, pm_ra, pm_dec, parallax, v_rad,
                          mjd=ModifiedJulianDate(TAI=52000.0))
        self.assertRaises(RuntimeError, _applyProperMotion,
                          ra, decShort, pm_ra, pm_dec, parallax, v_rad,
                          mjd=ModifiedJulianDate(TAI=52000.0))
        self.assertRaises(RuntimeError, _applyProperMotion,
                          ra, dec, pm_raShort, pm_dec, parallax, v_rad,
                          mjd=ModifiedJulianDate(TAI=52000.0))
        self.assertRaises(RuntimeError, _applyProperMotion,
                          ra, dec, pm_ra, pm_decShort, parallax, v_rad,
                          mjd=ModifiedJulianDate(TAI=52000.0))
        self.assertRaises(RuntimeError, _applyProperMotion,
                          ra, dec, pm_ra, pm_dec, parallaxShort, v_rad,
                          mjd=ModifiedJulianDate(TAI=52000.0))
        self.assertRaises(RuntimeError, _applyProperMotion,
                          ra, dec, pm_ra, pm_dec, parallax, v_radShort,
                          mjd=ModifiedJulianDate(TAI=52000.0))

        #test that it actually runs
        _applyProperMotion(ra, dec, pm_ra, pm_dec, parallax, v_rad,
                           mjd=ModifiedJulianDate(TAI=52000.0))
        _applyProperMotion(ra[0], dec[0], pm_ra[0], pm_dec[0], parallax[0], v_rad[0],
                          mjd=ModifiedJulianDate(TAI=52000.0))

        ##########test _appGeoFromICRS
        #test without mjd
        self.assertRaises(RuntimeError, _appGeoFromICRS, ra, dec)

        #test with mismatched ra, dec
        self.assertRaises(RuntimeError, _appGeoFromICRS, ra, decShort,
                          mjd=ModifiedJulianDate(TAI=52000.0))
        self.assertRaises(RuntimeError, _appGeoFromICRS, raShort, dec,
                          mjd=ModifiedJulianDate(TAI=52000.0))

        #test that it actually urns
        test=_appGeoFromICRS(ra, dec, mjd=obs_metadata.mjd)

        ##########test _observedFromAppGeo
        #test without obs_metadata
        self.assertRaises(RuntimeError, _observedFromAppGeo, ra, dec)

        #test without site
        dummy=ObservationMetaData(pointingRA=obs_metadata.pointingRA,
                                  pointingDec=obs_metadata.pointingDec,
                                  mjd=obs_metadata.mjd,
                                  site=None)
        self.assertRaises(RuntimeError, _observedFromAppGeo, ra, dec, obs_metadata=dummy)

        #test without mjd
        dummy=ObservationMetaData(pointingRA=obs_metadata.pointingRA,
                                  pointingDec=obs_metadata.pointingDec,
                                  site=Site(name='LSST'))
        self.assertRaises(RuntimeError, _observedFromAppGeo, ra, dec, obs_metadata=dummy)

        #test mismatches
        dummy=ObservationMetaData(pointingRA=obs_metadata.pointingRA,
                                  pointingDec=obs_metadata.pointingDec,
                                  mjd=obs_metadata.mjd,
                                  site=Site(name='LSST'))

        self.assertRaises(RuntimeError, _observedFromAppGeo, ra, decShort, obs_metadata=dummy)
        self.assertRaises(RuntimeError, _observedFromAppGeo, raShort, dec, obs_metadata=dummy)

        #test that it actually runs
        test = _observedFromAppGeo(ra, dec, obs_metadata=dummy)

        ##########test _observedFromICRS
        #test without epoch
        self.assertRaises(RuntimeError, _observedFromICRS, ra, dec, obs_metadata=obs_metadata)

        #test without obs_metadata
        self.assertRaises(RuntimeError, _observedFromICRS, ra, dec, epoch=2000.0)

        #test without mjd
        dummy=ObservationMetaData(pointingRA=obs_metadata.pointingRA,
                                  pointingDec=obs_metadata.pointingDec,
                                  site=obs_metadata.site)
        self.assertRaises(RuntimeError, _observedFromICRS, ra, dec, epoch=2000.0, obs_metadata=dummy)

        #test that it actually runs
        dummy=ObservationMetaData(pointingRA=obs_metadata.pointingRA,
                                  pointingDec=obs_metadata.pointingDec,
                                  site=obs_metadata.site,
                                  mjd=obs_metadata.mjd)

        #test mismatches
        self.assertRaises(RuntimeError, _observedFromICRS, ra, decShort, epoch=2000.0, obs_metadata=dummy)
        self.assertRaises(RuntimeError, _observedFromICRS, raShort, dec, epoch=2000.0, obs_metadata=dummy)

        #test that it actually runs
        test = _observedFromICRS(ra, dec, obs_metadata=dummy, epoch=2000.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])
Ejemplo n.º 45
0
def _pupilCoordsFromRaDec(ra_in, dec_in,
                          pm_ra=None, pm_dec=None,
                          parallax=None, v_rad=None,
                          includeRefraction=True,
                          obs_metadata=None, epoch=2000.0):
    """
    Take an input RA and dec from the sky and convert it to coordinates
    on the focal plane.

    This uses PAL's gnomonic projection routine which assumes that the focal
    plane is perfectly flat.  The output is in Cartesian coordinates, assuming
    that the Celestial Sphere is a unit sphere.

    The RA, Dec accepted by this method are in the International Celestial
    Reference System.  Before applying the gnomonic projection, this method
    transforms those RA, Dec into observed geocentric coordinates, applying
    the effects of precession, nutation, aberration, parallax and refraction.
    This is done, because the gnomonic projection ought to be applied to what
    observers actually see, rather than the idealized, above-the-atmosphere
    coordinates represented by the ICRS.

    @param [in] ra_in is in radians (ICRS).  Can be either a numpy array or a number.

    @param [in] dec_in is in radians (ICRS).  Can be either a numpy array or a number.

    @param [in] pm_ra is proper motion in RA multiplied by cos(Dec) (radians/yr)
    Can be a numpy array or a number or None (default=None).

    @param [in] pm_dec is proper motion in dec (radians/yr)
    Can be a numpy array or a number or None (default=None).

    @param [in] parallax is parallax in radians
    Can be a numpy array or a number or None (default=None).

    @param [in] v_rad is radial velocity (km/s)
    Can be a numpy array or a number or None (default=None).

    @param [in] includeRefraction is a boolean controlling the application of refraction.

    @param [in] obs_metadata is an ObservationMetaData instantiation characterizing the
    telescope location and pointing.

    @param [in] epoch is the epoch of mean ra and dec in julian years (default=2000.0)

    @param [out] returns a numpy array whose first row is the x coordinate on the pupil in
    radians and whose second row is the y coordinate in radians
    """

    are_arrays = _validate_inputs([ra_in, dec_in], ['ra_in', 'dec_in'],
                                  "pupilCoordsFromRaDec")

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

    if obs_metadata.mjd is None:
        raise RuntimeError("Cannot call pupilCoordsFromRaDec; obs_metadata.mjd is None")

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

    if obs_metadata.rotSkyPos is None:
        # there is no observation meta data on which to base astrometry
        raise RuntimeError("Cannot calculate [x,y]_focal_nominal without obs_metadata.rotSkyPos")

    if obs_metadata.pointingRA is None or obs_metadata.pointingDec is None:
        raise RuntimeError("Cannot calculate [x,y]_focal_nominal without pointingRA and Dec in obs_metadata")

    ra_obs, dec_obs = _observedFromICRS(ra_in, dec_in,
                                        pm_ra=pm_ra, pm_dec=pm_dec,
                                        parallax=parallax, v_rad=v_rad,
                                        obs_metadata=obs_metadata,
                                        epoch=epoch,
                                        includeRefraction=includeRefraction)

    return _pupilCoordsFromObserved(ra_obs, dec_obs, obs_metadata,
                                    epoch=epoch, includeRefraction=includeRefraction)
def _pupilCoordsFromRaDec(ra_in, dec_in, obs_metadata=None, epoch=None):
    """
    Take an input RA and dec from the sky and convert it to coordinates
    on the focal plane.

    This uses PAL's gnomonic projection routine which assumes that the focal
    plane is perfectly flat.  The output is in Cartesian coordinates, assuming
    that the Celestial Sphere is a unit sphere.

    The RA, Dec accepted by this method are in the International Celestial
    Reference System.  Before applying the gnomonic projection, this method
    transforms those RA, Dec into observed geocentric coordinates, applying
    the effects of precession, nutation, aberration, parallax and refraction.
    This is done, because the gnomonic projection ought to be applied to what
    observers actually see, rather than the idealized, above-the-atmosphere
    coordinates represented by the ICRS.

    @param [in] ra_in is a numpy array of RAs in radians
    (in the International Celestial Reference System)

    @param [in] dec_in is a numpy array of Decs in radians
    (in the International Celestial Reference System)

    @param [in] obs_metadata is an ObservationMetaData instantiation characterizing the
    telescope location and pointing.

    @param [in] epoch is the epoch of mean ra and dec in julian years (optional; if not
    provided, this method will try to get it from the db_obj member variable, assuming this
    method is part of an InstanceCatalog)

    @param [out] returns a numpy array whose first row is the x coordinate on the pupil in
    radians and whose second row is the y coordinate in radians
    """

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

    if obs_metadata.mjd is None:
        raise RuntimeError("Cannot call pupilCoordsFromRaDec; obs_metadata.mjd is None")

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

    if len(ra_in)!=len(dec_in):
        raise RuntimeError("You passed %d RAs but %d Decs to pupilCoordsFromRaDec" % (len(ra_in), len(dec_in)))

    if obs_metadata.rotSkyPos is None:
        #there is no observation meta data on which to base astrometry
        raise RuntimeError("Cannot calculate [x,y]_focal_nominal without obs_metadata.rotSkyPos")

    if obs_metadata.pointingRA is None or obs_metadata.pointingDec is None:
        raise RuntimeError("Cannot calculate [x,y]_focal_nominal without pointingRA and Dec in obs_metadata")

    theta = obs_metadata._rotSkyPos

    ra_obs, dec_obs = _observedFromICRS(ra_in, dec_in, obs_metadata=obs_metadata,
                                        epoch=2000.0, includeRefraction=True)

    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]

    #palpy.ds2tp performs the gnomonic projection on ra_in and dec_in
    #with a tangent point at (pointingRA, pointingDec)
    #
    try:
        x, y = palpy.ds2tpVector(ra_obs, dec_obs, ra_pointing, dec_pointing)
    except:
        # apparently, one of your ra/dec values was improper; we will have to do this
        # element-wise, putting NaN in the place of the bad values
        x = []
        y = []
        for rr, dd in zip(ra_obs, dec_obs):
            try:
                xx, yy = palpy.ds2tp(rr, dd, ra_pointing, dec_pointing)
            except:
                xx = np.NaN
                yy = np.NaN
            x.append(xx)
            y.append(yy)
        x = np.array(x)
        y = np.array(y)

    # The extra negative sign on x_out comes from the following:
    # The Gnomonic projection as calculated by palpy is such that,
    # if north is in the +y direction, then west is in the -x direction,
    # which is the opposite of the behavior we want (I do not know how to
    # express this analytically; I have just confirmed it numerically)
    x *= -1.0

    # rotate the result by rotskypos (rotskypos being "the angle of the sky relative to
    # camera coordinates" according to phoSim documentation) to account for
    # the rotation of the focal plane about the telescope pointing

    x_out = x*np.cos(theta) - y*np.sin(theta)
    y_out = x*np.sin(theta) + y*np.cos(theta)

    return np.array([x_out, y_out])
Ejemplo n.º 47
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])
Ejemplo n.º 48
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)
Ejemplo n.º 49
0
def _pupilCoordsFromObserved(ra_obs, dec_obs, obs_metadata, epoch=2000.0, includeRefraction=True):
    """
    Convert Observed RA, Dec into pupil coordinates

    Parameters
    ----------
    ra_obs is the observed RA in radians

    dec_obs is the observed Dec in radians

    obs_metadata is an ObservationMetaData characterizing the telescope location and pointing

    epoch is the epoch of the mean RA and Dec in julian years (default=2000.0)

    includeRefraction is a boolean controlling the application of refraction.

    Returns
    --------
    A numpy array whose first row is the x coordinate on the pupil in
    radians and whose second row is the y coordinate in radians
    """

    are_arrays = _validate_inputs([ra_obs, dec_obs], ['ra_obs', 'dec_obs'],
                                  "pupilCoordsFromObserved")

    if obs_metadata.rotSkyPos is None:
        raise RuntimeError("Cannot call pupilCoordsFromObserved; "
                           "rotSkyPos is None")

    theta = -1.0*obs_metadata._rotSkyPos

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

    # palpy.ds2tp performs the gnomonic projection on ra_in and dec_in
    # with a tangent point at (pointingRA, pointingDec)
    #
    if not are_arrays:
        try:
            x, y = palpy.ds2tp(ra_obs, dec_obs, ra_pointing, dec_pointing)
        except:
            x = np.NaN
            y = np.NaN
    else:
        try:
            x, y = palpy.ds2tpVector(ra_obs, dec_obs, ra_pointing, dec_pointing)
        except:
            # apparently, one of your ra/dec values was improper; we will have to do this
            # element-wise, putting NaN in the place of the bad values
            x = []
            y = []
            for rr, dd in zip(ra_obs, dec_obs):
                try:
                    xx, yy = palpy.ds2tp(rr, dd, ra_pointing, dec_pointing)
                except:
                    xx = np.NaN
                    yy = np.NaN
                x.append(xx)
                y.append(yy)
            x = np.array(x)
            y = np.array(y)

    # rotate the result by rotskypos (rotskypos being "the angle of the sky relative to
    # camera coordinates" according to phoSim documentation) to account for
    # the rotation of the focal plane about the telescope pointing

    x_out = x*np.cos(theta) - y*np.sin(theta)
    y_out = x*np.sin(theta) + y*np.cos(theta)

    return np.array([x_out, y_out])
Ejemplo n.º 50
0
    def testObservedFromPupil_noRefraction(self):
        """
        Test conversion from pupil coordinates to observed coordinates
        when includeRefraction=False
        """

        mjd = ModifiedJulianDate(TAI=53000.0)
        solarRA, solarDec = solarRaDec(mjd)

        # to make sure that we are more than 45 degrees from the Sun as required
        # for _icrsFromObserved to be at all accurate
        raCenter = solarRA + 100.0
        decCenter = solarDec - 30.0

        obs = ObservationMetaData(pointingRA=raCenter,
                                  pointingDec=decCenter,
                                  boundType='circle',
                                  boundLength=0.1,
                                  rotSkyPos=23.0,
                                  mjd=mjd)

        nSamples = 1000
        rng = np.random.RandomState(4453)
        ra = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(raCenter)
        dec = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(decCenter)
        xp, yp = _pupilCoordsFromRaDec(ra,
                                       dec,
                                       obs_metadata=obs,
                                       epoch=2000.0,
                                       includeRefraction=False)

        raObs, decObs = _observedFromICRS(ra,
                                          dec,
                                          obs_metadata=obs,
                                          epoch=2000.0,
                                          includeRefraction=False)

        raObs_test, decObs_test = _observedFromPupilCoords(
            xp, yp, obs_metadata=obs, epoch=2000.0, includeRefraction=False)

        dist = arcsecFromRadians(
            haversine(raObs, decObs, raObs_test, decObs_test))
        self.assertLess(dist.max(), 1.0e-6)

        # test output in degrees
        raObs_deg, decObs_deg = observedFromPupilCoords(
            xp, yp, obs_metadata=obs, epoch=2000.0, includeRefraction=False)

        np.testing.assert_array_almost_equal(raObs_deg,
                                             np.degrees(raObs_test),
                                             decimal=16)
        np.testing.assert_array_almost_equal(decObs_deg,
                                             np.degrees(decObs_test),
                                             decimal=16)

        # test one-at-a-time input
        for ii in range(len(raObs)):
            rr, dd = _observedFromPupilCoords(xp[ii],
                                              yp[ii],
                                              obs_metadata=obs,
                                              epoch=2000.0,
                                              includeRefraction=False)
            self.assertAlmostEqual(rr, raObs_test[ii], 16)
            self.assertAlmostEqual(dd, decObs_test[ii], 16)

            rr, dd = observedFromPupilCoords(xp[ii],
                                             yp[ii],
                                             obs_metadata=obs,
                                             epoch=2000.0,
                                             includeRefraction=False)
            self.assertAlmostEqual(rr, raObs_deg[ii], 16)
            self.assertAlmostEqual(dd, decObs_deg[ii], 16)