def pixelCoordinatesFromRaDec(self, ra, dec):
        """
        Convert RA, Dec into pixel coordinates on this detector

        @param [in] ra is a numpy array or a float indicating RA in radians

        @param [in] dec is a numpy array or a float indicating Dec in radians

        @param [out] xPix is a numpy array indicating the x pixel coordinate

        @param [out] yPix is a numpy array indicating the y pixel coordinate
        """

        nameList = [self.name]
        if type(ra) is numpy.ndarray:
            nameList = nameList*len(ra)
            raLocal=ra
            decLocal=dec
        else:
            raLocal = numpy.array([ra])
            decLocal = numpy.array([dec])

        xPix, yPix = _pixelCoordsFromRaDec(raLocal, decLocal, chipNames=nameList,
                                           obs_metadata=self._obs_metadata,
                                           epoch=self._epoch,
                                           camera=self._afwCamera)

        return xPix, yPix
    def pixelCoordinatesFromRaDec(self, ra, dec):
        """
        Convert RA, Dec into pixel coordinates on this detector

        @param [in] ra is a numpy array or a float indicating RA in radians

        @param [in] dec is a numpy array or a float indicating Dec in radians

        @param [out] xPix is a numpy array indicating the x pixel coordinate

        @param [out] yPix is a numpy array indicating the y pixel coordinate
        """

        nameList = [self.name]
        if type(ra) is np.ndarray:
            nameList = nameList * len(ra)
            raLocal = ra
            decLocal = dec
        else:
            raLocal = np.array([ra])
            decLocal = np.array([dec])

        xPix, yPix = _pixelCoordsFromRaDec(raLocal,
                                           decLocal,
                                           chipName=nameList,
                                           obs_metadata=self._obs_metadata,
                                           epoch=self._epoch,
                                           camera=self._afwCamera)

        return xPix, yPix
    def _xy(self, ra, dec):
        """
        This is a method required by the GalSim WCS API

        Convert ra, dec in radians into x, y in pixel space with crpix subtracted.
        """

        chipNameList = [self.afwDetector.getName()]

        if type(ra) is np.ndarray:
            chipNameList = chipNameList * len(ra)

        xx, yy = _pixelCoordsFromRaDec(ra=ra,
                                       dec=dec,
                                       chipName=chipNameList,
                                       obs_metadata=self.obs_metadata,
                                       epoch=self.epoch,
                                       camera=self.afwCamera)

        if type(ra) is np.ndarray:
            return (xx - self.crpix1, yy - self.crpix2)
        else:
            return (xx[0] - self.crpix1, yy - self.crpix2)
Exemple #4
0
    def _pixelCoordsFromRaDec(self,
                              ra,
                              dec,
                              pm_ra=None,
                              pm_dec=None,
                              parallax=None,
                              v_rad=None,
                              obs_metadata=None,
                              chipName=None,
                              epoch=2000.0,
                              includeDistortion=True):
        """
        Get the pixel positions (or nan if not on a chip) for objects based
        on their RA, and Dec (in radians)

        Parameters
        ----------
        ra is in radians in the International Celestial Reference System.
        Can be either a float or a numpy array.

        dec is in radians in the International Celestial Reference System.
        Can be either a float or a numpy array.

        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).

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

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

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

        obs_metadata is an ObservationMetaData characterizing the telescope
        pointing.

        epoch is the epoch in Julian years of the equinox against which
        RA is measured.  Default is 2000.

        chipName designates the names of the chips on which the pixel
        coordinates will be reckoned.  Can be either single value, an array, or None.
        If an array, there must be as many chipNames as there are (RA, Dec) pairs.
        If a single value, all of the pixel coordinates will be reckoned on the same
        chip.  If None, this method will calculate which chip each(RA, Dec) pair actually
        falls on, and return pixel coordinates for each (RA, Dec) pair on the appropriate
        chip.  Default is None.

        includeDistortion is a boolean.  If True (default), then this method will
        return the true pixel coordinates with optical distortion included.  If False, this
        method will return TAN_PIXEL coordinates, which are the pixel coordinates with
        estimated optical distortion removed.  See the documentation in afw.cameraGeom for more
        details.

        Returns
        -------
        a 2-D numpy array in which the first row is the x pixel coordinate
        and the second row is the y pixel coordinate
        """

        return coordUtils._pixelCoordsFromRaDec(
            ra,
            dec,
            pm_ra=pm_ra,
            pm_dec=pm_dec,
            parallax=parallax,
            v_rad=v_rad,
            obs_metadata=obs_metadata,
            chipName=chipName,
            camera=self._camera,
            epoch=epoch,
            includeDistortion=includeDistortion)
Exemple #5
0
    def testUtilityMethods(self):
        """
        Generate a catalog using the methods from AstrometryUtils.py and CameraUtils.py.
        Read that data in, and then recalculate the values 'by hand' to make sure
        that they are consistent.
        """

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

        if os.path.exists(catName):
            os.unlink(catName)

        self.cat.write_catalog(catName)

        dtype = [('id', int),
                 ('raICRS', float), ('decICRS', float),
                 ('parallax', float), ('radial_velocity', float),
                 ('x_pupil', float), ('y_pupil', float), ('chipName', str, 11),
                 ('xPix', float), ('yPix', float),
                 ('xFocalPlane', float), ('yFocalPlane', float)]

        baselineData = np.genfromtxt(catName, dtype=dtype, delimiter=';')

        self.assertGreater(len(baselineData), 0)

        pupilTest = _pupilCoordsFromRaDec(baselineData['raICRS'],
                                          baselineData['decICRS'],
                                          parallax=baselineData['parallax'],
                                          v_rad=baselineData['radial_velocity'],
                                          obs_metadata=self.obs_metadata,
                                          epoch=2000.0)

        for (xxtest, yytest, xx, yy) in \
                zip(pupilTest[0], pupilTest[1], baselineData['x_pupil'], baselineData['y_pupil']):
            self.assertAlmostEqual(xxtest, xx, 6)
            self.assertAlmostEqual(yytest, yy, 6)

        focalTest = focalPlaneCoordsFromPupilCoords(pupilTest[0], pupilTest[1], camera=self.cat.camera)

        focalRa = _focalPlaneCoordsFromRaDec(baselineData['raICRS'], baselineData['decICRS'],
                                             parallax=baselineData['parallax'],
                                             v_rad=baselineData['radial_velocity'],
                                             epoch=self.cat.db_obj.epoch, obs_metadata=self.cat.obs_metadata,
                                             camera=self.cat.camera)

        for (xxtest, yytest, xxra, yyra, xx, yy) in \
                zip(focalTest[0], focalTest[1], focalRa[0], focalRa[1],
                    baselineData['xFocalPlane'], baselineData['yFocalPlane']):

            self.assertAlmostEqual(xxtest, xx, 6)
            self.assertAlmostEqual(yytest, yy, 6)
            self.assertAlmostEqual(xxra, xx, 6)
            self.assertAlmostEqual(yyra, yy, 6)

        pixTest = pixelCoordsFromPupilCoords(pupilTest[0], pupilTest[1], camera=self.cat.camera)

        pixTestRaDec = _pixelCoordsFromRaDec(baselineData['raICRS'], baselineData['decICRS'],
                                             parallax=baselineData['parallax'],
                                             v_rad=baselineData['radial_velocity'],
                                             epoch=self.cat.db_obj.epoch,
                                             obs_metadata=self.cat.obs_metadata,
                                             camera=self.cat.camera)

        for (xxtest, yytest, xxra, yyra, xx, yy) in \
                zip(pixTest[0], pixTest[1], pixTestRaDec[0], pixTestRaDec[1],
                    baselineData['xPix'], baselineData['yPix']):

            if not np.isnan(xx) and not np.isnan(yy):
                self.assertAlmostEqual(xxtest, xx, 5)
                self.assertAlmostEqual(yytest, yy, 5)
                self.assertAlmostEqual(xxra, xx, 5)
                self.assertAlmostEqual(yyra, yy, 5)
            else:
                np.testing.assert_equal(xx, np.NaN)
                np.testing.assert_equal(yy, np.NaN)
                np.testing.assert_equal(xxra, np.NaN)
                np.testing.assert_equal(yyra, np.NaN)
                np.testing.assert_equal(xxtest, np.NaN)
                np.testing.assert_equal(yytest, np.NaN)

        nameTest = chipNameFromPupilCoords(pupilTest[0], pupilTest[1],
                                           camera=self.cat.camera)

        nameRA = _chipNameFromRaDec(baselineData['raICRS'], baselineData['decICRS'],
                                    epoch=self.cat.db_obj.epoch, obs_metadata=self.cat.obs_metadata,
                                    camera=self.cat.camera)

        is_none = 0
        for (ntest, nra, ncontrol) in zip(nameTest, nameRA, baselineData['chipName']):
            if ncontrol != 'None':
                self.assertEqual(ntest, ncontrol)
                self.assertEqual(nra, ncontrol)
            else:
                is_none += 1
                self.assertIsNone(ntest)
                self.assertIsNone(nra)

        self.assertGreater(is_none, 0)
        self.assertLess(is_none, len(baselineData))

        if os.path.exists(catName):
            os.unlink(catName)
    def test_pixel_coords_from_ra_dec_radians(self):
        """
        Test that _pixelCoordsFromRaDec and _pixelCoordsFromRaDecLSST agree
        """
        raP = 74.2
        decP = 13.0
        obs = ObservationMetaData(pointingRA=raP,
                                  pointingDec=decP,
                                  rotSkyPos=13.0,
                                  mjd=43441.0)

        n_obj = 1000
        rng = np.random.RandomState(83241)
        rr = rng.random_sample(n_obj) * 1.75
        theta = rng.random_sample(n_obj) * 2.0 * np.pi
        ra_list = np.radians(raP + rr * np.cos(theta))
        dec_list = np.radians(decP + rr * np.sin(theta))
        x_pix, y_pix = _pixelCoordsFromRaDec(ra_list,
                                             dec_list,
                                             obs_metadata=obs,
                                             camera=self.camera)
        self.assertLessEqual(len(np.where(np.isnan(x_pix))[0]), n_obj / 10)
        self.assertLessEqual(len(np.where(np.isnan(y_pix))[0]), n_obj / 10)

        x_pix_test, y_pix_test = _pixelCoordsFromRaDecLSST(ra_list,
                                                           dec_list,
                                                           obs_metadata=obs)
        np.testing.assert_array_equal(x_pix, x_pix_test)
        np.testing.assert_array_equal(y_pix, y_pix_test)

        # test when we force a chipName
        x_pix, y_pix = _pixelCoordsFromRaDec(ra_list,
                                             dec_list,
                                             chipName=['R:2,2 S:1,1'],
                                             obs_metadata=obs,
                                             camera=self.camera)
        self.assertLessEqual(len(np.where(np.isnan(x_pix))[0]), n_obj / 10)
        self.assertLessEqual(len(np.where(np.isnan(y_pix))[0]), n_obj / 10)

        x_pix_test, y_pix_test = _pixelCoordsFromRaDecLSST(
            ra_list, dec_list, chipName=['R:2,2 S:1,1'], obs_metadata=obs)
        np.testing.assert_array_equal(x_pix, x_pix_test)
        np.testing.assert_array_equal(y_pix, y_pix_test)

        # test without distortion
        x_pix, y_pix = _pixelCoordsFromRaDec(ra_list,
                                             dec_list,
                                             obs_metadata=obs,
                                             camera=self.camera,
                                             includeDistortion=False)
        self.assertLessEqual(len(np.where(np.isnan(x_pix))[0]), n_obj / 10)
        self.assertLessEqual(len(np.where(np.isnan(y_pix))[0]), n_obj / 10)

        x_pix_test, y_pix_test = _pixelCoordsFromRaDecLSST(
            ra_list, dec_list, obs_metadata=obs, includeDistortion=False)
        np.testing.assert_array_equal(x_pix, x_pix_test)
        np.testing.assert_array_equal(y_pix, y_pix_test)

        # test that exceptions are raised when incomplete ObservationMetaData are used
        obs = ObservationMetaData(pointingRA=raP,
                                  pointingDec=decP,
                                  mjd=59580.0)
        with self.assertRaises(RuntimeError) as context:
            _pixelCoordsFromRaDecLSST(ra_list, dec_list, obs_metadata=obs)
        self.assertIn("rotSkyPos", context.exception.args[0])

        obs = ObservationMetaData(pointingRA=raP,
                                  pointingDec=decP,
                                  rotSkyPos=35.0)
        with self.assertRaises(RuntimeError) as context:
            _pixelCoordsFromRaDecLSST(ra_list, dec_list, obs_metadata=obs)
        self.assertIn("mjd", context.exception.args[0])

        with self.assertRaises(RuntimeError) as context:
            _pixelCoordsFromRaDecLSST(ra_list, dec_list)
        self.assertIn("ObservationMetaData", context.exception.args[0])

        # check that exceptions are raised when ra_list, dec_list are of the wrong shape
        obs = ObservationMetaData(pointingRA=raP,
                                  pointingDec=decP,
                                  rotSkyPos=24.0,
                                  mjd=43000.0)
        with self.assertRaises(RuntimeError) as context:
            _pixelCoordsFromRaDecLSST(ra_list, dec_list[:5], obs_metadata=obs)
        self.assertIn("pixelCoordsFromRaDecLSST", context.exception.args[0])
Exemple #7
0
    def check_placement(self, imageName, raList, decList, fwhmList,
                        countList, gain,
                        detector, camera, obs, epoch=2000.0):
        """
        Read in a FITS image and a list of objects meant to be on that
        image.  Verify that the objects were placed at the correct pixel
        by counting up all of the flux within 2 fwhm of each object's
        expected location and verifying it with the counts expected for
        that object.

        @param [in] imageName is the name of the FITS file to be read in

        @param [in] raList is a numpy array of the RA coordinates of the objects
        in the image (in radians)

        @param [in] decList is a numpy array of the Dec coordinates of the objects
        in the image (in radians)

        @param [in] fwhmList is a list of the Full Width at Half Maximum of
        each object in arcseconds

        @param [in] countList is a list of the counts expected for each object

        @param [in] gain is the gain of the detector (electrons per ADU)

        @param [in] detector is an instantiation of the afw.cameraGeom Detector
        class characterizing the detector corresponding to this image

        @param [in] camera is an instantiation of the afw.cameraGeom Camera class
        characterizing the camera to which detector belongs

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

        @param [in] epoch is the epoch in Julian years of the equinox against which
        RA and Dec are measured.

        Raises an exception of the counts detected for each object differs from
        the expected amount by more than 3 sigma.
        """

        im = afwImage.ImageF(imageName).getArray()
        activePixels = np.where(im > 1.0e-10)

        # I know this seems backwards, but the way numpy handles arrays,
        # the first index is the row (i.e. the y coordinate)
        imXList = activePixels[1]
        imYList = activePixels[0]

        nameList = [detector.getName()]*len(raList)
        xPixList, yPixList = _pixelCoordsFromRaDec(raList, decList,
                                                   chipName=nameList,
                                                   camera=camera,
                                                   obs_metadata=obs,
                                                   epoch=epoch)

        for rr, dd, xx, yy, fwhm, cc in \
        zip(raList, decList, xPixList, yPixList, fwhmList, countList):

            countSigma = np.sqrt(cc/gain)

            imNameList = [detector.getName()]*len(imXList)
            raImList, decImList = _raDecFromPixelCoords(imXList, imYList,
                                                        imNameList,
                                                        camera=camera,
                                                        obs_metadata=obs,
                                                        epoch=epoch)

            distanceList = arcsecFromRadians(haversine(raImList, decImList, rr, dd))

            fluxArray = np.array([im[imYList[ix]][imXList[ix]]
                                  for ix in range(len(distanceList))
                                  if distanceList[ix] < 2.0*fwhm])

            totalFlux = fluxArray.sum()
            msg = 'totalFlux %e should be %e diff/sigma %e' \
                  % (totalFlux, cc, np.abs(totalFlux-cc)/countSigma)

            self.assertLess(np.abs(totalFlux-cc), 3.0*countSigma, msg=msg)
    def test_generic_camera_wrapper(self):
        """
        Test that GalSimCameraWrapper wraps its methods as expected.
        This is mostly to catch changes in afw API.
        """
        camera = camTestUtils.CameraWrapper().camera
        camera_wrapper = GalSimCameraWrapper(camera)

        obs_mjd = ObservationMetaData(mjd=60000.0)
        ra, dec = raDecFromAltAz(35.0, 112.0, obs_mjd)
        obs = ObservationMetaData(pointingRA=ra,
                                  pointingDec=dec,
                                  mjd=obs_mjd.mjd,
                                  rotSkyPos=22.4)

        rng = np.random.RandomState(8124)

        for detector in camera:
            name = detector.getName()
            bbox = camera[name].getBBox()
            bbox_wrapper = camera_wrapper.getBBox(name)
            self.assertEqual(bbox.getMinX(), bbox_wrapper.getMinX())
            self.assertEqual(bbox.getMaxX(), bbox_wrapper.getMaxX())
            self.assertEqual(bbox.getMinY(), bbox_wrapper.getMinY())
            self.assertEqual(bbox.getMaxY(), bbox_wrapper.getMaxY())

            center_point = camera[name].getCenter(FOCAL_PLANE)
            pixel_system = camera[name].makeCameraSys(PIXELS)
            center_pix = camera.transform(center_point, FOCAL_PLANE,
                                          pixel_system)
            center_pix_wrapper = camera_wrapper.getCenterPixel(name)
            self.assertEqual(center_pix.getX(), center_pix_wrapper.getX())
            self.assertEqual(center_pix.getY(), center_pix_wrapper.getY())

            pupil_system = camera[name].makeCameraSys(FIELD_ANGLE)
            center_pupil = camera.transform(center_point, FOCAL_PLANE,
                                            pupil_system)
            center_pupil_wrapper = camera_wrapper.getCenterPupil(name)
            self.assertEqual(center_pupil.getX(), center_pupil_wrapper.getX())
            self.assertEqual(center_pupil.getY(), center_pupil_wrapper.getY())

            corner_pupil_wrapper = camera_wrapper.getCornerPupilList(name)
            corner_point_list = camera[name].getCorners(FOCAL_PLANE)
            for point in corner_point_list:
                point_pupil = camera.transform(point, FOCAL_PLANE,
                                               pupil_system)
                dd_min = 1.0e10
                for wrapper_point in corner_pupil_wrapper:
                    dd = np.sqrt(
                        (point_pupil.getX() - wrapper_point.getX())**2 +
                        (point_pupil.getY() - wrapper_point.getY())**2)

                    if dd < dd_min:
                        dd_min = dd
                self.assertLess(dd_min, 1.0e-20)

            xpix_min = None
            xpix_max = None
            ypix_min = None
            ypix_max = None
            focal_to_tan_pix = camera[name].getTransform(
                FOCAL_PLANE, TAN_PIXELS)
            for point in corner_point_list:
                pixel_point = focal_to_tan_pix.applyForward(point)
                xx = pixel_point.getX()
                yy = pixel_point.getY()
                if xpix_min is None or xx < xpix_min:
                    xpix_min = xx
                if ypix_min is None or yy < ypix_min:
                    ypix_min = yy
                if xpix_max is None or xx > xpix_max:
                    xpix_max = xx
                if ypix_max is None or yy > ypix_max:
                    ypix_max = yy

            pix_bounds_wrapper = camera_wrapper.getTanPixelBounds(name)
            self.assertEqual(pix_bounds_wrapper[0], xpix_min)
            self.assertEqual(pix_bounds_wrapper[1], xpix_max)
            self.assertEqual(pix_bounds_wrapper[2], ypix_min)
            self.assertEqual(pix_bounds_wrapper[3], ypix_max)

            x_pup = rng.random_sample(10) * 0.005 - 0.01
            y_pup = rng.random_sample(10) * 0.005 - 0.01
            x_pix, y_pix = pixelCoordsFromPupilCoords(x_pup,
                                                      y_pup,
                                                      chipName=name,
                                                      camera=camera)

            (x_pix_wrapper,
             y_pix_wrapper) = camera_wrapper.pixelCoordsFromPupilCoords(
                 x_pup, y_pup, name, obs)

            nan_x = np.where(np.isnan(x_pix))
            self.assertEqual(len(nan_x[0]), 0)
            np.testing.assert_array_equal(x_pix, x_pix_wrapper)
            np.testing.assert_array_equal(y_pix, y_pix_wrapper)

            x_pix = rng.random_sample(10) * 100.0 - 200.0
            y_pix = rng.random_sample(10) * 100.0 - 200.0
            x_pup, y_pup = pupilCoordsFromPixelCoords(x_pix,
                                                      y_pix,
                                                      chipName=name,
                                                      camera=camera)

            (x_pup_wrapper,
             y_pup_wrapper) = camera_wrapper.pupilCoordsFromPixelCoords(
                 x_pix, y_pix, name, obs)

            nan_x = np.where(np.isnan(x_pup))
            self.assertEqual(len(nan_x[0]), 0)
            np.testing.assert_array_equal(x_pup, x_pup_wrapper)
            np.testing.assert_array_equal(y_pup, y_pup_wrapper)

            ra, dec = raDecFromPixelCoords(x_pix,
                                           y_pix,
                                           name,
                                           camera=camera,
                                           obs_metadata=obs)

            (ra_wrapper, dec_wrapper) = camera_wrapper.raDecFromPixelCoords(
                x_pix, y_pix, name, obs)

            nan_ra = np.where(np.isnan(ra))
            self.assertEqual(len(nan_ra[0]), 0)
            np.testing.assert_array_equal(ra, ra_wrapper)
            np.testing.assert_array_equal(dec, dec_wrapper)

            ra, dec = _raDecFromPixelCoords(x_pix,
                                            y_pix,
                                            name,
                                            camera=camera,
                                            obs_metadata=obs)

            (ra_wrapper, dec_wrapper) = camera_wrapper._raDecFromPixelCoords(
                x_pix, y_pix, name, obs)

            nan_ra = np.where(np.isnan(ra))
            self.assertEqual(len(nan_ra[0]), 0)
            np.testing.assert_array_equal(ra, ra_wrapper)
            np.testing.assert_array_equal(dec, dec_wrapper)

            ra = obs.pointingRA + (rng.random_sample(10) * 150.0 -
                                   100.0) / 160.0
            dec = obs.pointingDec + (rng.random_sample(10) * 150.0 -
                                     100.0) / 160.0

            x_pix, y_pix = pixelCoordsFromRaDec(ra,
                                                dec,
                                                chipName=name,
                                                camera=camera,
                                                obs_metadata=obs)

            (x_pix_wrapper,
             y_pix_wrapper) = camera_wrapper.pixelCoordsFromRaDec(
                 ra, dec, chipName=name, obs_metadata=obs)

            nan_x = np.where(np.isnan(x_pix))
            self.assertEqual(len(nan_x[0]), 0)
            np.testing.assert_array_equal(x_pix, x_pix_wrapper)
            np.testing.assert_array_equal(y_pix, y_pix_wrapper)

            ra = np.radians(ra)
            dec = np.radians(dec)

            x_pix, y_pix = _pixelCoordsFromRaDec(ra,
                                                 dec,
                                                 chipName=name,
                                                 camera=camera,
                                                 obs_metadata=obs)

            (x_pix_wrapper,
             y_pix_wrapper) = camera_wrapper._pixelCoordsFromRaDec(
                 ra, dec, chipName=name, obs_metadata=obs)

            nan_x = np.where(np.isnan(x_pix))
            self.assertEqual(len(nan_x[0]), 0)
            np.testing.assert_array_equal(x_pix, x_pix_wrapper)
            np.testing.assert_array_equal(y_pix, y_pix_wrapper)

        del camera
    def check_placement(self, imageName, raList, decList, fwhmList,
                        countList, gain,
                        detector, camera, obs, epoch=2000.0):
        """
        Read in a FITS image and a list of objects meant to be on that
        image.  Verify that the objects were placed at the correct pixel
        by counting up all of the flux within 2 fwhm of each object's
        expected location and verifying it with the counts expected for
        that object.

        @param [in] imageName is the name of the FITS file to be read in

        @param [in] raList is a numpy array of the RA coordinates of the objects
        in the image (in radians)

        @param [in] decList is a numpy array of the Dec coordinates of the objects
        in the image (in radians)

        @param [in] fwhmList is a list of the Full Width at Half Maximum of
        each object in arcseconds

        @param [in] countList is a list of the counts expected for each object

        @param [in] gain is the gain of the detector (electrons per ADU)

        @param [in] detector is an instantiation of the afw.cameraGeom Detector
        class characterizing the detector corresponding to this image

        @param [in] camera is an instantiation of the afw.cameraGeom Camera class
        characterizing the camera to which detector belongs

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

        @param [in] epoch is the epoch in Julian years of the equinox against which
        RA and Dec are measured.

        Raises an exception of the counts detected for each object differs from
        the expected amount by more than 3 sigma.
        """


        im = afwImage.ImageF(imageName).getArray()
        activePixels = numpy.where(im>1.0e-10)

        # I know this seems backwards, but the way numpy handles arrays,
        # the first index is the row (i.e. the y coordinate)
        imXList = activePixels[1]
        imYList = activePixels[0]

        nameList = [detector.getName()]*len(raList)
        xPixList, yPixList = _pixelCoordsFromRaDec(raList, decList,
                                                   chipNames=nameList,
                                                   camera=camera,
                                                   obs_metadata=obs,
                                                   epoch=epoch)

        for rr, dd, xx, yy, fwhm, cc in \
        zip(raList, decList, xPixList, yPixList, fwhmList, countList):
            countSigma = numpy.sqrt(cc/gain)

            imNameList = [detector.getName()]*len(imXList)
            raImList, decImList = _raDecFromPixelCoords(imXList, imYList,
                                                        imNameList,
                                                        camera=camera,
                                                        obs_metadata=obs,
                                                        epoch=epoch)

            distanceList = arcsecFromRadians(haversine(raImList, decImList, rr, dd))

            fluxArray = numpy.array(
                                  [im[imYList[ix]][imXList[ix]] \
                                   for ix in range(len(distanceList)) \
                                   if distanceList[ix]<2.0*fwhm]
                                  )

            totalFlux = fluxArray.sum()
            self.assertTrue(numpy.abs(totalFlux-cc)<3.0*countSigma)
    def testUtilityMethods(self):
        """
        Generate a catalog using the methods from AstrometryUtils.py and CameraUtils.py.
        Read that data in, and then recalculate the values 'by hand' to make sure
        that they are consistent.
        """

        self.cat.write_catalog("AstrometryTestCatalog.txt")

        dtype = [('id',int),
                 ('raPhoSim',float), ('decPhoSim',float),
                 ('raObserved',float), ('decObserved',float),
                 ('x_pupil',float), ('y_pupil',float), ('chipName',str,11),
                 ('xPix',float), ('yPix',float),
                 ('xFocalPlane',float), ('yFocalPlane',float)]

        baselineData = numpy.loadtxt('AstrometryTestCatalog.txt', dtype=dtype, delimiter=';')

        pupilTest = _pupilCoordsFromRaDec(baselineData['raObserved'],
                                              baselineData['decObserved'],
                                              obs_metadata=self.obs_metadata,
                                              epoch=2000.0)

        for (xxtest, yytest, xx, yy) in \
                zip(pupilTest[0], pupilTest[1], baselineData['x_pupil'], baselineData['y_pupil']):
            self.assertAlmostEqual(xxtest,xx,6)
            self.assertAlmostEqual(yytest,yy,6)

        focalTest = focalPlaneCoordsFromPupilCoords(pupilTest[0], pupilTest[1], camera=self.cat.camera)

        focalRa = _focalPlaneCoordsFromRaDec(baselineData['raObserved'], baselineData['decObserved'],
                                             epoch=self.cat.db_obj.epoch, obs_metadata=self.cat.obs_metadata,
                                             camera=self.cat.camera)

        for (xxtest, yytest, xxra, yyra, xx, yy) in \
                zip(focalTest[0], focalTest[1], focalRa[0], focalRa[1],
                        baselineData['xFocalPlane'], baselineData['yFocalPlane']):

            self.assertAlmostEqual(xxtest,xx,6)
            self.assertAlmostEqual(yytest,yy,6)
            self.assertAlmostEqual(xxra,xx,6)
            self.assertAlmostEqual(yyra,yy,6)

        pixTest = pixelCoordsFromPupilCoords(pupilTest[0], pupilTest[1], camera=self.cat.camera)

        pixTestRaDec = _pixelCoordsFromRaDec(baselineData['raObserved'], baselineData['decObserved'],
                                             epoch=self.cat.db_obj.epoch,
                                             obs_metadata=self.cat.obs_metadata,
                                             camera=self.cat.camera)

        for (xxtest, yytest, xxra, yyra, xx, yy) in \
                zip(pixTest[0], pixTest[1], pixTestRaDec[0], pixTestRaDec[1],
                           baselineData['xPix'], baselineData['yPix']):

            if not numpy.isnan(xx) and not numpy.isnan(yy):
                self.assertAlmostEqual(xxtest,xx,5)
                self.assertAlmostEqual(yytest,yy,5)
                self.assertAlmostEqual(xxra,xx,5)
                self.assertAlmostEqual(yyra,yy,5)
            else:
                self.assertTrue(numpy.isnan(xx))
                self.assertTrue(numpy.isnan(yy))
                self.assertTrue(numpy.isnan(xxra))
                self.assertTrue(numpy.isnan(yyra))
                self.assertTrue(numpy.isnan(xxtest))
                self.assertTrue(numpy.isnan(yytest))


        nameTest = chipNameFromPupilCoords(pupilTest[0], pupilTest[1],
                                           camera=self.cat.camera)

        nameRA = _chipNameFromRaDec(baselineData['raObserved'], baselineData['decObserved'],
                                    epoch=self.cat.db_obj.epoch, obs_metadata=self.cat.obs_metadata,
                                    camera=self.cat.camera)

        for (ntest, nra, ncontrol) in zip(nameTest, nameRA, baselineData['chipName']):
            if ncontrol != 'None':
                self.assertEqual(ntest,ncontrol)
                self.assertEqual(nra,ncontrol)
            else:
                self.assertTrue(ntest is None)
                self.assertTrue(nra is None)

        if os.path.exists("AstrometryTestCatalog.txt"):
            os.unlink("AstrometryTestCatalog.txt")
Exemple #11
0
def tanWcsFromDetector(afwDetector, afwCamera, obs_metadata, epoch):
    """
    Take an afw.cameraGeom detector and return a WCS which approximates
    the focal plane as perfectly flat (i.e. it ignores optical distortions
    that the telescope may impose on the image)

    @param [in] afwDetector is an instantiation of afw.cameraGeom's Detector
    class which characterizes the detector for which you wish to return th
    WCS

    @param [in] afwCamera is an instantiation of afw.cameraGeom's Camera
    class which characterizes the camera containing afwDetector

    @param [in] obs_metadata is an instantiation of ObservationMetaData
    characterizing the telescope's current pointing

    @param [in] epoch is the epoch in Julian years of the equinox against
    which RA and Dec are measured

    @param [out] tanWcs is an instantiation of afw.image's TanWcs class
    representing the WCS of the detector as if there were no optical
    distortions imposed by the telescope.
    """

    xTanPixMin, xTanPixMax, \
    yTanPixMin, yTanPixMax = _getTanPixelBounds(afwDetector, afwCamera)

    xPixList = []
    yPixList = []
    nameList = []

    # dx and dy are set somewhat heuristically
    # setting them eqal to 0.1(max-min) lead to errors
    # on the order of 0.7 arcsec in the WCS

    dx = 0.5*(xTanPixMax-xTanPixMin)
    dy = 0.5*(yTanPixMax-yTanPixMin)

    for xx in np.arange(xTanPixMin, xTanPixMax+0.5*dx, dx):
        for yy in np.arange(yTanPixMin, yTanPixMax+0.5*dy, dy):
            xPixList.append(xx)
            yPixList.append(yy)
            nameList.append(afwDetector.getName())

    raList, decList = _raDecFromPixelCoords(np.array(xPixList),
                                            np.array(yPixList),
                                            nameList,
                                            camera=afwCamera,
                                            obs_metadata=obs_metadata,
                                            epoch=epoch,
                                            includeDistortion=False)

    crPix1, crPix2 = _pixelCoordsFromRaDec(obs_metadata._pointingRA,
                                           obs_metadata._pointingDec,
                                           chipName=afwDetector.getName(), camera=afwCamera,
                                           obs_metadata=obs_metadata, epoch=epoch,
                                           includeDistortion=False)

    lonList, latList = _nativeLonLatFromPointing(raList, decList,
                                                 obs_metadata._pointingRA,
                                                 obs_metadata._pointingDec)

    # convert from native longitude and latitude to intermediate world coordinates
    # according to equations (12), (13), (54) and (55) of
    #
    # Calabretta and Greisen (2002), A&A 395, p. 1077
    #
    radiusList = 180.0/(np.tan(latList)*np.pi)
    uList = radiusList*np.sin(lonList)
    vList = -radiusList*np.cos(lonList)

    delta_xList = xPixList - crPix1
    delta_yList = yPixList - crPix2

    bVector = np.array([
                       (delta_xList*uList).sum(),
                       (delta_yList*uList).sum(),
                       (delta_xList*vList).sum(),
                       (delta_yList*vList).sum()
                       ])

    offDiag = (delta_yList*delta_xList).sum()
    xsq = np.power(delta_xList, 2).sum()
    ysq = np.power(delta_yList, 2).sum()

    aMatrix = np.array([
                       [xsq, offDiag, 0.0, 0.0],
                       [offDiag, ysq, 0.0, 0.0],
                       [0.0, 0.0, xsq, offDiag],
                       [0.0, 0.0, offDiag, ysq]
                       ])

    coeffs = np.linalg.solve(aMatrix, bVector)

    fitsHeader = dafBase.PropertyList()
    fitsHeader.set("RADESYS", "ICRS")
    fitsHeader.set("EQUINOX", epoch)
    fitsHeader.set("CRVAL1", obs_metadata.pointingRA)
    fitsHeader.set("CRVAL2", obs_metadata.pointingDec)
    fitsHeader.set("CRPIX1", crPix1+1)  # the +1 is because LSST uses 0-indexed images
    fitsHeader.set("CRPIX2", crPix2+1)  # FITS files use 1-indexed images
    fitsHeader.set("CTYPE1", "RA---TAN")
    fitsHeader.set("CTYPE2", "DEC--TAN")
    fitsHeader.setDouble("CD1_1", coeffs[0])
    fitsHeader.setDouble("CD1_2", coeffs[1])
    fitsHeader.setDouble("CD2_1", coeffs[2])
    fitsHeader.setDouble("CD2_2", coeffs[3])
    tanWcs = afwImage.cast_TanWcs(afwImage.makeWcs(fitsHeader))

    return tanWcs
    def testUtilityMethods(self):
        """
        Generate a catalog using the methods from AstrometryUtils.py and CameraUtils.py.
        Read that data in, and then recalculate the values 'by hand' to make sure
        that they are consistent.
        """

        with lsst.utils.tests.getTempFilePath('.txt') as catName:
            self.cat.write_catalog(catName)

            dtype = [('id', int),
                     ('raICRS', float), ('decICRS', float),
                     ('parallax', float), ('radial_velocity', float),
                     ('x_pupil', float), ('y_pupil', float), ('chipName', str, 11),
                     ('xPix', float), ('yPix', float),
                     ('xFocalPlane', float), ('yFocalPlane', float)]

            baselineData = np.genfromtxt(catName, dtype=dtype, delimiter=';')

        self.assertGreater(len(baselineData), 0)

        pupilTest = _pupilCoordsFromRaDec(baselineData['raICRS'],
                                          baselineData['decICRS'],
                                          parallax=baselineData['parallax'],
                                          v_rad=baselineData['radial_velocity'],
                                          obs_metadata=self.obs_metadata,
                                          epoch=2000.0)

        for (xxtest, yytest, xx, yy) in \
                zip(pupilTest[0], pupilTest[1], baselineData['x_pupil'], baselineData['y_pupil']):
            self.assertAlmostEqual(xxtest, xx, 6)
            self.assertAlmostEqual(yytest, yy, 6)

        focalTest = focalPlaneCoordsFromPupilCoords(pupilTest[0], pupilTest[1], camera=self.cat.camera)

        focalRa = _focalPlaneCoordsFromRaDec(baselineData['raICRS'], baselineData['decICRS'],
                                             parallax=baselineData['parallax'],
                                             v_rad=baselineData['radial_velocity'],
                                             epoch=self.cat.db_obj.epoch, obs_metadata=self.cat.obs_metadata,
                                             camera=self.cat.camera)

        for (xxtest, yytest, xxra, yyra, xx, yy) in \
                zip(focalTest[0], focalTest[1], focalRa[0], focalRa[1],
                    baselineData['xFocalPlane'], baselineData['yFocalPlane']):

            self.assertAlmostEqual(xxtest, xx, 6)
            self.assertAlmostEqual(yytest, yy, 6)
            self.assertAlmostEqual(xxra, xx, 6)
            self.assertAlmostEqual(yyra, yy, 6)

        pixTest = pixelCoordsFromPupilCoords(pupilTest[0], pupilTest[1], camera=self.cat.camera)

        pixTestRaDec = _pixelCoordsFromRaDec(baselineData['raICRS'], baselineData['decICRS'],
                                             parallax=baselineData['parallax'],
                                             v_rad=baselineData['radial_velocity'],
                                             epoch=self.cat.db_obj.epoch,
                                             obs_metadata=self.cat.obs_metadata,
                                             camera=self.cat.camera)

        for (xxtest, yytest, xxra, yyra, xx, yy) in \
                zip(pixTest[0], pixTest[1], pixTestRaDec[0], pixTestRaDec[1],
                    baselineData['xPix'], baselineData['yPix']):

            if not np.isnan(xx) and not np.isnan(yy):
                self.assertAlmostEqual(xxtest, xx, 5)
                self.assertAlmostEqual(yytest, yy, 5)
                self.assertAlmostEqual(xxra, xx, 5)
                self.assertAlmostEqual(yyra, yy, 5)
            else:
                np.testing.assert_equal(xx, np.NaN)
                np.testing.assert_equal(yy, np.NaN)
                np.testing.assert_equal(xxra, np.NaN)
                np.testing.assert_equal(yyra, np.NaN)
                np.testing.assert_equal(xxtest, np.NaN)
                np.testing.assert_equal(yytest, np.NaN)

        nameTest = chipNameFromPupilCoords(pupilTest[0], pupilTest[1],
                                           camera=self.cat.camera)

        nameRA = _chipNameFromRaDec(baselineData['raICRS'], baselineData['decICRS'],
                                    epoch=self.cat.db_obj.epoch, obs_metadata=self.cat.obs_metadata,
                                    camera=self.cat.camera)

        is_none = 0
        for (ntest, nra, ncontrol) in zip(nameTest, nameRA, baselineData['chipName']):
            if ncontrol != 'None':
                self.assertEqual(ntest, ncontrol)
                self.assertEqual(nra, ncontrol)
            else:
                is_none += 1
                self.assertIsNone(ntest)
                self.assertIsNone(nra)

        self.assertGreater(is_none, 0)
        self.assertLess(is_none, len(baselineData))
def tanWcsFromDetector(afwDetector, afwCamera, obs_metadata, epoch):
    """
    Take an afw.cameraGeom detector and return a WCS which approximates
    the focal plane as perfectly flat (i.e. it ignores optical distortions
    that the telescope may impose on the image)

    @param [in] afwDetector is an instantiation of afw.cameraGeom's Detector
    class which characterizes the detector for which you wish to return th
    WCS

    @param [in] afwCamera is an instantiation of afw.cameraGeom's Camera
    class which characterizes the camera containing afwDetector

    @param [in] obs_metadata is an instantiation of ObservationMetaData
    characterizing the telescope's current pointing

    @param [in] epoch is the epoch in Julian years of the equinox against
    which RA and Dec are measured

    @param [out] tanWcs is an instantiation of afw.image's TanWcs class
    representing the WCS of the detector as if there were no optical
    distortions imposed by the telescope.
    """

    xTanPixMin, xTanPixMax, \
    yTanPixMin, yTanPixMax = _getTanPixelBounds(afwDetector, afwCamera)

    xPixList = []
    yPixList = []
    nameList = []

    # dx and dy are set somewhat heuristically
    # setting them eqal to 0.1(max-min) lead to errors
    # on the order of 0.7 arcsec in the WCS

    dx = 0.5 * (xTanPixMax - xTanPixMin)
    dy = 0.5 * (yTanPixMax - yTanPixMin)

    for xx in np.arange(xTanPixMin, xTanPixMax + 0.5 * dx, dx):
        for yy in np.arange(yTanPixMin, yTanPixMax + 0.5 * dy, dy):
            xPixList.append(xx)
            yPixList.append(yy)
            nameList.append(afwDetector.getName())

    raList, decList = _raDecFromPixelCoords(np.array(xPixList),
                                            np.array(yPixList),
                                            nameList,
                                            camera=afwCamera,
                                            obs_metadata=obs_metadata,
                                            epoch=epoch,
                                            includeDistortion=False)

    crPix1, crPix2 = _pixelCoordsFromRaDec(obs_metadata._pointingRA,
                                           obs_metadata._pointingDec,
                                           chipName=afwDetector.getName(),
                                           camera=afwCamera,
                                           obs_metadata=obs_metadata,
                                           epoch=epoch,
                                           includeDistortion=False)

    lonList, latList = _nativeLonLatFromPointing(raList, decList,
                                                 obs_metadata._pointingRA,
                                                 obs_metadata._pointingDec)

    # convert from native longitude and latitude to intermediate world coordinates
    # according to equations (12), (13), (54) and (55) of
    #
    # Calabretta and Greisen (2002), A&A 395, p. 1077
    #
    radiusList = 180.0 / (np.tan(latList) * np.pi)
    uList = radiusList * np.sin(lonList)
    vList = -radiusList * np.cos(lonList)

    delta_xList = xPixList - crPix1
    delta_yList = yPixList - crPix2

    bVector = np.array([
        (delta_xList * uList).sum(), (delta_yList * uList).sum(),
        (delta_xList * vList).sum(), (delta_yList * vList).sum()
    ])

    offDiag = (delta_yList * delta_xList).sum()
    xsq = np.power(delta_xList, 2).sum()
    ysq = np.power(delta_yList, 2).sum()

    aMatrix = np.array([[xsq, offDiag, 0.0, 0.0], [offDiag, ysq, 0.0, 0.0],
                        [0.0, 0.0, xsq, offDiag], [0.0, 0.0, offDiag, ysq]])

    coeffs = np.linalg.solve(aMatrix, bVector)

    fitsHeader = dafBase.PropertyList()
    fitsHeader.set("RADESYS", "ICRS")
    fitsHeader.set("EQUINOX", epoch)
    fitsHeader.set("CRVAL1", obs_metadata.pointingRA)
    fitsHeader.set("CRVAL2", obs_metadata.pointingDec)
    fitsHeader.set("CRPIX1",
                   crPix1 + 1)  # the +1 is because LSST uses 0-indexed images
    fitsHeader.set("CRPIX2", crPix2 + 1)  # FITS files use 1-indexed images
    fitsHeader.set("CTYPE1", "RA---TAN")
    fitsHeader.set("CTYPE2", "DEC--TAN")
    fitsHeader.setDouble("CD1_1", coeffs[0])
    fitsHeader.setDouble("CD1_2", coeffs[1])
    fitsHeader.setDouble("CD2_1", coeffs[2])
    fitsHeader.setDouble("CD2_2", coeffs[3])

    # 20 March 2017
    # the 'try' block is required by the SWIG stack;
    # the 'except' block is required by the pybind11 stack.
    try:
        tanWcs = afwImage.cast_TanWcs(afwImage.makeWcs(fitsHeader))
    except AttributeError:
        tanWcs = afwImage.makeWcs(fitsHeader)

    return tanWcs
    def test_pixel_coords_from_ra_dec_radians(self):
        """
        Test that _pixelCoordsFromRaDec and _pixelCoordsFromRaDecLSST agree
        """
        raP = 74.2
        decP = 13.0
        obs = ObservationMetaData(pointingRA=raP, pointingDec=decP,
                                  rotSkyPos=13.0, mjd=43441.0)

        n_obj = 1000
        rng = np.random.RandomState(83241)
        rr = rng.random_sample(n_obj)*1.75
        theta = rng.random_sample(n_obj)*2.0*np.pi
        ra_list = np.radians(raP + rr*np.cos(theta))
        dec_list = np.radians(decP + rr*np.sin(theta))

        x_pix, y_pix = _pixelCoordsFromRaDec(ra_list, dec_list, obs_metadata=obs, camera=self.camera,
                                             includeDistortion=False)
        self.assertLessEqual(len(np.where(np.isnan(x_pix))[0]), n_obj/10)
        self.assertLessEqual(len(np.where(np.isnan(y_pix))[0]), n_obj/10)

        x_pix_test, y_pix_test = _pixelCoordsFromRaDecLSST(ra_list, dec_list, obs_metadata=obs,
                                                           includeDistortion=False)

        try:
            np.testing.assert_array_equal(x_pix, x_pix_test)
            np.testing.assert_array_equal(y_pix, y_pix_test)
        except AssertionError:
            n_problematic = 0
            for xx, yy, xt, yt in zip(x_pix, y_pix, x_pix_test, y_pix_test):
                if xx!=xt or yy!=yt:
                    if (not np.isnan(xx) and not np.isnan(xt) and
                        not np.isnan(yy) and not np.isnan(yt)):
                        print(xx,yy,xt,yt)

                        n_problematic += 1
            if n_problematic>0:
                raise

        # test when we force a chipName
        x_pix, y_pix = _pixelCoordsFromRaDec(ra_list, dec_list, chipName=['R:2,2 S:1,1'],
                                             obs_metadata=obs, camera=self.camera,
                                             includeDistortion=False)
        self.assertLessEqual(len(np.where(np.isnan(x_pix))[0]), n_obj/10)
        self.assertLessEqual(len(np.where(np.isnan(y_pix))[0]), n_obj/10)

        x_pix_test, y_pix_test = _pixelCoordsFromRaDecLSST(ra_list, dec_list, chipName=['R:2,2 S:1,1'],
                                                           obs_metadata=obs,
                                                           includeDistortion=False)
        np.testing.assert_array_equal(x_pix, x_pix_test)
        np.testing.assert_array_equal(y_pix, y_pix_test)

        # test without distortion
        x_pix, y_pix = _pixelCoordsFromRaDec(ra_list, dec_list, obs_metadata=obs, camera=self.camera,
                                             includeDistortion=False)
        self.assertLessEqual(len(np.where(np.isnan(x_pix))[0]), n_obj/10)
        self.assertLessEqual(len(np.where(np.isnan(y_pix))[0]), n_obj/10)

        x_pix_test, y_pix_test = _pixelCoordsFromRaDecLSST(ra_list, dec_list, obs_metadata=obs,
                                                           includeDistortion=False)
        try:
            np.testing.assert_array_equal(x_pix, x_pix_test)
            np.testing.assert_array_equal(y_pix, y_pix_test)
        except AssertionError:
            n_problematic = 0
            for xx, yy, xt, yt in zip(x_pix, y_pix, x_pix_test, y_pix_test):
                if xx!=xt or yy!=yt:
                    if (not np.isnan(xx) and not np.isnan(xt) and
                        not np.isnan(yy) and not np.isnan(yt)):
                        print(xx,yy,xt,yt)

                        n_problematic += 1
            if n_problematic>0:
                raise


        # test that exceptions are raised when incomplete ObservationMetaData are used
        obs = ObservationMetaData(pointingRA=raP, pointingDec=decP, mjd=59580.0)
        with self.assertRaises(RuntimeError) as context:
            _pixelCoordsFromRaDecLSST(ra_list, dec_list, obs_metadata=obs)
        self.assertIn("rotSkyPos", context.exception.args[0])

        obs = ObservationMetaData(pointingRA=raP, pointingDec=decP, rotSkyPos=35.0)
        with self.assertRaises(RuntimeError) as context:
            _pixelCoordsFromRaDecLSST(ra_list, dec_list, obs_metadata=obs)
        self.assertIn("mjd", context.exception.args[0])

        with self.assertRaises(RuntimeError) as context:
            _pixelCoordsFromRaDecLSST(ra_list, dec_list)
        self.assertIn("ObservationMetaData", context.exception.args[0])

        # check that exceptions are raised when ra_list, dec_list are of the wrong shape
        obs = ObservationMetaData(pointingRA=raP, pointingDec=decP, rotSkyPos=24.0, mjd=43000.0)
        with self.assertRaises(RuntimeError) as context:
            _pixelCoordsFromRaDecLSST(ra_list, dec_list[:5], obs_metadata=obs)
        self.assertIn("same length", context.exception.args[0])