def test_pixel_coords(self):
        """
        Test that pixelCoordsFromRaDecLSST with non-zero proper motion etc.
        agrees with pixelCoordsFromPupilCoords when pupilCoords are
        calculated with the same proper motion, etc.
        """
        (obs, ra_list, dec_list, pm_ra_list, pm_dec_list, parallax_list,
         v_rad_list) = self.set_data(26)

        for is_none in ('pm_ra', 'pm_dec', 'parallax', 'v_rad'):
            pm_ra = pm_ra_list
            pm_dec = pm_dec_list
            parallax = parallax_list
            v_rad = v_rad_list

            if is_none == 'pm_ra':
                pm_ra = None
            elif is_none == 'pm_dec':
                pm_dec = None
            elif is_none == 'parallax':
                parallax = None
            elif is_none == 'v_rad':
                v_rad = None

            xp, yp = pupilCoordsFromRaDec(ra_list,
                                          dec_list,
                                          pm_ra=pm_ra,
                                          pm_dec=pm_dec,
                                          parallax=parallax,
                                          v_rad=v_rad,
                                          obs_metadata=obs)

            xpx_control, ypx_control = pixelCoordsFromPupilCoords(
                xp, yp, camera=self.camera)

            xpx_test, ypx_test = pixelCoordsFromRaDecLSST(ra_list,
                                                          dec_list,
                                                          pm_ra=pm_ra,
                                                          pm_dec=pm_dec,
                                                          parallax=parallax,
                                                          v_rad=v_rad,
                                                          obs_metadata=obs)

            xpx_radians, ypx_radians = _pixelCoordsFromRaDecLSST(
                np.radians(ra_list),
                np.radians(dec_list),
                pm_ra=radiansFromArcsec(pm_ra),
                pm_dec=radiansFromArcsec(pm_dec),
                parallax=radiansFromArcsec(parallax),
                v_rad=v_rad,
                obs_metadata=obs)

            np.testing.assert_array_equal(xpx_control, xpx_test)
            np.testing.assert_array_equal(ypx_control, ypx_test)
            np.testing.assert_array_equal(xpx_control, xpx_radians)
            np.testing.assert_array_equal(ypx_control, ypx_radians)
            self.assertLess(len(np.where(np.isnan(xpx_control))[0]),
                            len(xpx_test) / 4)
            self.assertLess(len(np.where(np.isnan(ypx_control))[0]),
                            len(ypx_test) / 4)
    def test_chip_name_from_ra_dec_degrees(self):
        """
        test that chipNameFromRaDecLSST agrees with chipNameFromRaDec
        """

        n_obj = 1000
        raP = 112.1
        decP = -34.1
        obs = ObservationMetaData(pointingRA=raP, pointingDec=decP,
                                  rotSkyPos=45.0, mjd=43000.0)

        rng = np.random.RandomState(8731)
        rr = rng.random_sample(n_obj)*1.75
        theta = rng.random_sample(n_obj)*2.0*np.pi
        ra_list = raP + rr*np.cos(theta)
        dec_list = decP + rr*np.sin(theta)
        control_name_list = chipNameFromRaDec(ra_list, dec_list,
                                              obs_metadata=obs,
                                              camera=self.camera)

        test_name_list = chipNameFromRaDecLSST(ra_list, dec_list,
                                               obs_metadata=obs)

        try:
            np.testing.assert_array_equal(control_name_list.astype(str),
                                          test_name_list.astype(str))
        except AssertionError:
            n_problematic = 0
            for ii, (c_n, t_n) in enumerate(zip(control_name_list.astype(str), test_name_list.astype(str))):
                if c_n != t_n:
                    x_pix, y_pix = pixelCoordsFromRaDecLSST(ra_list[ii], dec_list[ii], obs_metadata=obs)
                    if c_n != 'None':
                        n_problematic += 1
            if n_problematic > 0:
                raise

        self.assertLessEqual(len(np.where(np.char.rfind(test_name_list.astype(str), 'None') >= 0)[0]),
                             n_obj/10)

        # 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:
            chipNameFromRaDecLSST(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:
            chipNameFromRaDecLSST(ra_list, dec_list, obs_metadata=obs)
        self.assertIn("mjd", context.exception.args[0])

        with self.assertRaises(RuntimeError) as context:
            chipNameFromRaDecLSST(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:
            chipNameFromRaDecLSST(ra_list, dec_list[:5], obs_metadata=obs)
        self.assertIn("chipNameFromRaDecLSST", context.exception.args[0])
    def test_pixel_coords(self):
        """
        Test that pixelCoordsFromRaDecLSST with non-zero proper motion etc.
        agrees with pixelCoordsFromPupilCoords when pupilCoords are
        calculated with the same proper motion, etc.
        """
        (obs, ra_list, dec_list,
         pm_ra_list, pm_dec_list,
         parallax_list, v_rad_list) = self.set_data(26)

        for is_none in ('pm_ra', 'pm_dec', 'parallax', 'v_rad'):
            pm_ra = pm_ra_list
            pm_dec = pm_dec_list
            parallax = parallax_list
            v_rad = v_rad_list

            if is_none == 'pm_ra':
                pm_ra = None
            elif is_none == 'pm_dec':
                pm_dec = None
            elif is_none == 'parallax':
                parallax = None
            elif is_none == 'v_rad':
                v_rad = None

            xp, yp = pupilCoordsFromRaDec(ra_list, dec_list,
                                          pm_ra=pm_ra, pm_dec=pm_dec,
                                          parallax=parallax, v_rad=v_rad,
                                          obs_metadata=obs)

            xpx_control, ypx_control = pixelCoordsFromPupilCoords(xp, yp, camera=self.camera,
                                                                  includeDistortion=False)

            xpx_test, ypx_test = pixelCoordsFromRaDecLSST(ra_list, dec_list,
                                                          pm_ra=pm_ra, pm_dec=pm_dec,
                                                          parallax=parallax, v_rad=v_rad,
                                                          obs_metadata=obs,
                                                          includeDistortion=False)

            xpx_radians, ypx_radians = _pixelCoordsFromRaDecLSST(np.radians(ra_list), np.radians(dec_list),
                                                                 pm_ra=radiansFromArcsec(pm_ra),
                                                                 pm_dec=radiansFromArcsec(pm_dec),
                                                                 parallax=radiansFromArcsec(parallax),
                                                                 v_rad=v_rad, obs_metadata=obs,
                                                                 includeDistortion=False)

            np.testing.assert_array_equal(xpx_control, xpx_test)
            np.testing.assert_array_equal(ypx_control, ypx_test)
            np.testing.assert_array_equal(xpx_control, xpx_radians)
            np.testing.assert_array_equal(ypx_control, ypx_radians)
            self.assertLess(len(np.where(np.isnan(xpx_control))[0]), len(xpx_test)/4)
            self.assertLess(len(np.where(np.isnan(ypx_control))[0]), len(ypx_test)/4)
    def testObjectPlacement(self):
        """
        Test that GalSim places objects on the correct pixel by drawing
        images containing single objects and no background, reading those
        images back in, and comparing the flux-averaged centroids of the
        images with the expected pixel positions of the input objects.
        """
        scratchDir = tempfile.mkdtemp(dir=ROOT, prefix='testLSSTObjectPlacement-')
        if os.path.exists(scratchDir):
            shutil.rmtree(scratchDir)
        os.mkdir(scratchDir)

        detector = lsst_camera()['R:0,3 S:2,2']
        det_name = 'R03_S22'

        magNorm = 19.0

        pixel_transformer = DMtoCameraPixelTransformer()

        for band in 'ugrizy':
            obs = self.obs_dict[band]

            catName = os.path.join(scratchDir, 'placementCatalog.dat')
            imageRoot = os.path.join(scratchDir, 'placementImage')
            dbFileName = os.path.join(scratchDir, 'placementInputCatalog.dat')


            imageName = '%s_%s_%s.fits' % (imageRoot, det_name, obs.bandpass)

            ra_c, dec_c = raDecFromPixelCoordsLSST(2000.0, 2000.0,
                                                   detector.getName(),
                                                   band=obs.bandpass,
                                                   obs_metadata=obs)

            nSamples = 30
            rng = np.random.RandomState(42)
            fwhm = 0.12

            for iteration in range(nSamples):
                if os.path.exists(dbFileName):
                    os.unlink(dbFileName)

                ra_obj = ra_c + rng.random_sample()*0.2 - 0.1
                dec_obj = dec_c + rng.random_sample()*0.2 - 0.1

                dmx_wrong, dmy_wrong = pixelCoordsFromRaDec(ra_obj, dec_obj,
                                                            chipName=detector.getName(),
                                                            obs_metadata=obs,
                                                            camera=lsst_camera())

                dmx_pix, dmy_pix = pixelCoordsFromRaDecLSST(ra_obj, dec_obj,
                                                            chipName=detector.getName(),
                                                            obs_metadata=obs,
                                                            band=obs.bandpass)

                x_pix, y_pix = pixel_transformer.cameraPixFromDMPix(dmx_pix, dmy_pix,
                                                                    detector.getName())

                x_pix_wrong, y_pix_wrong = pixel_transformer.cameraPixFromDMPix(dmx_wrong, dmy_wrong,
                                                                                detector.getName())

                d_ra = 360.0*(ra_obj - obs.pointingRA)  # in arcseconds
                d_dec = 360.0*(dec_obj - obs.pointingDec)

                create_text_catalog(obs, dbFileName,
                                    np.array([d_ra]), np.array([d_dec]),
                                    mag_norm=[magNorm])

                db = LSSTPlacementFileDBObj(dbFileName, runtable='test')
                cat = LSSTPlacementCatalog(db, obs_metadata=obs)
                cat.camera_wrapper = LSSTCameraWrapper()
                psf = SNRdocumentPSF(fwhm=fwhm)
                cat.setPSF(psf)

                cat.write_catalog(catName)
                cat.write_images(nameRoot=imageRoot)

                im = afwImage.ImageF(imageName).getArray()
                tot_flux = im.sum()
                self.assertGreater(tot_flux, 10.0)

                y_centroid = sum([ii*im[ii,:].sum() for ii in range(im.shape[0])])/tot_flux
                x_centroid = sum([ii*im[:,ii].sum() for ii in range(im.shape[1])])/tot_flux
                dd = np.sqrt((x_pix-x_centroid)**2 + (y_pix-y_centroid)**2)
                self.assertLess(dd, 0.5*fwhm)

                dd_wrong = np.sqrt((x_pix_wrong-x_centroid)**2 +
                                   (y_pix_wrong-y_centroid)**2)

                self.assertLess(dd, dd_wrong)

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

        if os.path.exists(scratchDir):
            shutil.rmtree(scratchDir)
    def test_pixel_coords_from_ra_dec_degrees(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 = raP + rr * np.cos(theta)
        dec_list = 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])
    def test_pixel_positions(self):
        """
        Test that CatSim pixel positions are close to PhoSim pixel positions.

        This is complicated by the fact that PhoSim uses the camera team definition
        of pixel space, which differs from the DM definition of pixel space as follows:

        Camera +y = DM +x
        Camera +x = DM -y
        Camera +z = DM +z

        This has been verified both by consulting documentation -- the documentation for
        afwCameraGeom says that +x is along the serial readout direction; LCA-13381
        indicates that, in the Camera team's definition, the serial readout is along +y --
        and phenomenologically by comparing the relationship between
        pixelCoordsFromPupilCoords() to visual inspection of PhoSim-generated FITS images.
        """
        self.assertGreater(len(self.data), 10)
        for ix in range(len(self.data)):

            in_name = self.data['chipName'][ix]
            chip_name = in_name[0] + ':' + in_name[1] + ',' + in_name[2]
            chip_name += ' ' + in_name[3] + ':' + in_name[4] + ',' + in_name[5]
            corner_pixels = getCornerPixels(chip_name, lsst_camera())

            x_center_dm = 0.25 * (corner_pixels[0][0] + corner_pixels[1][0] +
                                  corner_pixels[2][0] + corner_pixels[3][0])

            y_center_dm = 0.25 * (corner_pixels[0][1] + corner_pixels[1][1] +
                                  corner_pixels[2][1] + corner_pixels[3][1])

            obs = ObservationMetaData(pointingRA=self.data['pointingRA'][ix],
                                      pointingDec=self.data['pointingDec'][ix],
                                      rotSkyPos=self.data['rotSkyPos'][ix],
                                      mjd=59580.0)

            xpix, ypix = pixelCoordsFromRaDecLSST(self.data['objRA'][ix],
                                                  self.data['objDec'][ix],
                                                  obs_metadata=obs)

            raObs, decObs = observedFromICRS(self.data['objRA'][ix],
                                             self.data['objDec'][ix],
                                             obs_metadata=obs,
                                             epoch=2000.0)

            # find displacement from center of DM coordinates of the
            # objects as placed by PhoSim
            d_y_phosim = y_center_dm - self.data['xpix'][ix]
            d_x_phosim = self.data['ypix'][ix] - x_center_dm

            # displacement from center of DM coordinates as calculated
            # by DM
            d_x_dm = xpix - x_center_dm
            d_y_dm = ypix - y_center_dm

            d_pix = np.sqrt((d_x_dm - d_x_phosim)**2 +
                            (d_y_dm - d_y_phosim)**2)

            # demand that the difference between the two displacements is less
            # than 0.05 of the total displacement from the center of the object
            # as calculated by DM
            msg = 'dx %e; dy %e' % (d_x_dm, d_y_dm)
            self.assertLess(d_pix,
                            0.05 * np.sqrt(d_x_dm**2 + d_y_dm**2),
                            msg=msg)
    def test_alert_data_generation(self):

        dmag_cutoff = 0.005
        mag_name_to_int = {'u': 0, 'g': 1, 'r': 2, 'i': 3, 'z': 4, 'y': 5}

        _max_var_param_str = self.max_str_len

        class StarAlertTestDBObj(StellarAlertDBObjMixin, CatalogDBObject):
            objid = 'star_alert'
            tableid = 'stars'
            idColKey = 'simobjid'
            raColName = 'ra'
            decColName = 'dec'
            objectTypeId = 0
            columns = [('raJ2000', 'ra*0.01745329252'),
                       ('decJ2000', 'dec*0.01745329252'),
                       ('parallax', 'px*0.01745329252/3600.0'),
                       ('properMotionRa', 'pmra*0.01745329252/3600.0'),
                       ('properMotionDec', 'pmdec*0.01745329252/3600.0'),
                       ('radialVelocity', 'vrad'),
                       ('variabilityParameters', 'varParamStr', str,
                        _max_var_param_str)]

        class TestAlertsVarCatMixin(object):
            @register_method('alert_test')
            def applyAlertTest(self,
                               valid_dexes,
                               params,
                               expmjd,
                               variability_cache=None):
                if len(params) == 0:
                    return np.array([[], [], [], [], [], []])

                if isinstance(expmjd, numbers.Number):
                    dmags_out = np.zeros((6, self.num_variable_obj(params)))
                else:
                    dmags_out = np.zeros(
                        (6, self.num_variable_obj(params), len(expmjd)))

                for i_star in range(self.num_variable_obj(params)):
                    if params['amp'][i_star] is not None:
                        dmags = params['amp'][i_star] * np.cos(
                            params['per'][i_star] * expmjd)
                        for i_filter in range(6):
                            dmags_out[i_filter][i_star] = dmags

                return dmags_out

        class TestAlertsVarCat(TestAlertsVarCatMixin,
                               AlertStellarVariabilityCatalog):
            pass

        class TestAlertsTruthCat(TestAlertsVarCatMixin, CameraCoordsLSST,
                                 AstrometryStars, Variability,
                                 InstanceCatalog):
            column_outputs = ['uniqueId', 'chipName', 'dmagAlert', 'magAlert']

            @compound('delta_umag', 'delta_gmag', 'delta_rmag', 'delta_imag',
                      'delta_zmag', 'delta_ymag')
            def get_TruthVariability(self):
                return self.applyVariability(
                    self.column_by_name('varParamStr'))

            @cached
            def get_dmagAlert(self):
                return self.column_by_name('delta_%smag' %
                                           self.obs_metadata.bandpass)

            @cached
            def get_magAlert(self):
                return self.column_by_name('%smag' % self.obs_metadata.bandpass) + \
                       self.column_by_name('dmagAlert')

        star_db = StarAlertTestDBObj(database=self.star_db_name,
                                     driver='sqlite')

        # assemble the true light curves for each object; we need to figure out
        # if their np.max(dMag) ever goes over dmag_cutoff; then we will know if
        # we are supposed to simulate them
        true_lc_dict = {}
        true_lc_obshistid_dict = {}
        is_visible_dict = {}
        obs_dict = {}
        max_obshistid = -1
        n_total_observations = 0
        for obs in self.obs_list:
            obs_dict[obs.OpsimMetaData['obsHistID']] = obs
            obshistid = obs.OpsimMetaData['obsHistID']
            if obshistid > max_obshistid:
                max_obshistid = obshistid
            cat = TestAlertsTruthCat(star_db, obs_metadata=obs)

            for line in cat.iter_catalog():
                if line[1] is None:
                    continue

                n_total_observations += 1
                if line[0] not in true_lc_dict:
                    true_lc_dict[line[0]] = {}
                    true_lc_obshistid_dict[line[0]] = []

                true_lc_dict[line[0]][obshistid] = line[2]
                true_lc_obshistid_dict[line[0]].append(obshistid)

                if line[0] not in is_visible_dict:
                    is_visible_dict[line[0]] = False

                if line[3] <= self.obs_mag_cutoff[mag_name_to_int[
                        obs.bandpass]]:
                    is_visible_dict[line[0]] = True

        obshistid_bits = int(np.ceil(np.log(max_obshistid) / np.log(2)))

        skipped_due_to_mag = 0

        objects_to_simulate = []
        obshistid_unqid_set = set()
        for obj_id in true_lc_dict:

            dmag_max = -1.0
            for obshistid in true_lc_dict[obj_id]:
                if np.abs(true_lc_dict[obj_id][obshistid]) > dmag_max:
                    dmag_max = np.abs(true_lc_dict[obj_id][obshistid])

            if dmag_max >= dmag_cutoff:
                if not is_visible_dict[obj_id]:
                    skipped_due_to_mag += 1
                    continue

                objects_to_simulate.append(obj_id)
                for obshistid in true_lc_obshistid_dict[obj_id]:
                    obshistid_unqid_set.add((obj_id << obshistid_bits) +
                                            obshistid)

        self.assertGreater(len(objects_to_simulate), 10)
        self.assertGreater(skipped_due_to_mag, 0)

        log_file_name = tempfile.mktemp(dir=self.output_dir, suffix='log.txt')
        alert_gen = AlertDataGenerator(testing=True)

        alert_gen.subdivide_obs(self.obs_list, htmid_level=6)

        for htmid in alert_gen.htmid_list:
            alert_gen.alert_data_from_htmid(htmid,
                                            star_db,
                                            photometry_class=TestAlertsVarCat,
                                            output_prefix='alert_test',
                                            output_dir=self.output_dir,
                                            dmag_cutoff=dmag_cutoff,
                                            log_file_name=log_file_name)

        dummy_sed = Sed()

        bp_dict = BandpassDict.loadTotalBandpassesFromFiles()

        phot_params = PhotometricParameters()

        # First, verify that the contents of the sqlite files are all correct

        n_tot_simulated = 0

        alert_query = 'SELECT alert.uniqueId, alert.obshistId, meta.TAI, '
        alert_query += 'meta.band, quiescent.flux, alert.dflux, '
        alert_query += 'quiescent.snr, alert.snr, '
        alert_query += 'alert.ra, alert.dec, alert.chipNum, '
        alert_query += 'alert.xPix, alert.yPix, ast.pmRA, ast.pmDec, '
        alert_query += 'ast.parallax '
        alert_query += 'FROM alert_data AS alert '
        alert_query += 'INNER JOIN metadata AS meta ON meta.obshistId=alert.obshistId '
        alert_query += 'INNER JOIN quiescent_flux AS quiescent '
        alert_query += 'ON quiescent.uniqueId=alert.uniqueId '
        alert_query += 'AND quiescent.band=meta.band '
        alert_query += 'INNER JOIN baseline_astrometry AS ast '
        alert_query += 'ON ast.uniqueId=alert.uniqueId'

        alert_dtype = np.dtype([('uniqueId', int), ('obshistId', int),
                                ('TAI', float),
                                ('band', int), ('q_flux', float),
                                ('dflux', float), ('q_snr', float),
                                ('tot_snr', float), ('ra', float),
                                ('dec', float), ('chipNum', int),
                                ('xPix', float), ('yPix', float),
                                ('pmRA', float), ('pmDec', float),
                                ('parallax', float)])

        sqlite_file_list = os.listdir(self.output_dir)

        n_tot_simulated = 0
        obshistid_unqid_simulated_set = set()
        for file_name in sqlite_file_list:
            if not file_name.endswith('db'):
                continue
            full_name = os.path.join(self.output_dir, file_name)
            self.assertTrue(os.path.exists(full_name))
            alert_db = DBObject(full_name, driver='sqlite')
            alert_data = alert_db.execute_arbitrary(alert_query,
                                                    dtype=alert_dtype)
            if len(alert_data) == 0:
                continue

            mjd_list = ModifiedJulianDate.get_list(TAI=alert_data['TAI'])
            for i_obj in range(len(alert_data)):
                n_tot_simulated += 1
                obshistid_unqid_simulated_set.add(
                    (alert_data['uniqueId'][i_obj] << obshistid_bits) +
                    alert_data['obshistId'][i_obj])

                unq = alert_data['uniqueId'][i_obj]
                obj_dex = (unq // 1024) - 1
                self.assertAlmostEqual(self.pmra_truth[obj_dex],
                                       0.001 * alert_data['pmRA'][i_obj], 4)
                self.assertAlmostEqual(self.pmdec_truth[obj_dex],
                                       0.001 * alert_data['pmDec'][i_obj], 4)
                self.assertAlmostEqual(self.px_truth[obj_dex],
                                       0.001 * alert_data['parallax'][i_obj],
                                       4)

                ra_truth, dec_truth = applyProperMotion(
                    self.ra_truth[obj_dex],
                    self.dec_truth[obj_dex],
                    self.pmra_truth[obj_dex],
                    self.pmdec_truth[obj_dex],
                    self.px_truth[obj_dex],
                    self.vrad_truth[obj_dex],
                    mjd=mjd_list[i_obj])
                distance = angularSeparation(ra_truth, dec_truth,
                                             alert_data['ra'][i_obj],
                                             alert_data['dec'][i_obj])

                distance_arcsec = 3600.0 * distance
                msg = '\ntruth: %e %e\nalert: %e %e\n' % (
                    ra_truth, dec_truth, alert_data['ra'][i_obj],
                    alert_data['dec'][i_obj])

                self.assertLess(distance_arcsec, 0.0005, msg=msg)

                obs = obs_dict[alert_data['obshistId'][i_obj]]

                chipname = chipNameFromRaDecLSST(
                    self.ra_truth[obj_dex],
                    self.dec_truth[obj_dex],
                    pm_ra=self.pmra_truth[obj_dex],
                    pm_dec=self.pmdec_truth[obj_dex],
                    parallax=self.px_truth[obj_dex],
                    v_rad=self.vrad_truth[obj_dex],
                    obs_metadata=obs,
                    band=obs.bandpass)

                chipnum = int(
                    chipname.replace('R', '').replace('S', '').replace(
                        ' ', '').replace(';', '').replace(',',
                                                          '').replace(':', ''))

                self.assertEqual(chipnum, alert_data['chipNum'][i_obj])

                xpix, ypix = pixelCoordsFromRaDecLSST(
                    self.ra_truth[obj_dex],
                    self.dec_truth[obj_dex],
                    pm_ra=self.pmra_truth[obj_dex],
                    pm_dec=self.pmdec_truth[obj_dex],
                    parallax=self.px_truth[obj_dex],
                    v_rad=self.vrad_truth[obj_dex],
                    obs_metadata=obs,
                    band=obs.bandpass)

                self.assertAlmostEqual(alert_data['xPix'][i_obj], xpix, 4)
                self.assertAlmostEqual(alert_data['yPix'][i_obj], ypix, 4)

                dmag_sim = -2.5 * np.log10(1.0 + alert_data['dflux'][i_obj] /
                                           alert_data['q_flux'][i_obj])
                self.assertAlmostEqual(
                    true_lc_dict[alert_data['uniqueId'][i_obj]][
                        alert_data['obshistId'][i_obj]], dmag_sim, 3)

                mag_name = ('u', 'g', 'r', 'i', 'z',
                            'y')[alert_data['band'][i_obj]]
                m5 = obs.m5[mag_name]

                q_mag = dummy_sed.magFromFlux(alert_data['q_flux'][i_obj])
                self.assertAlmostEqual(
                    self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex],
                    q_mag, 4)

                snr, gamma = calcSNR_m5(
                    self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex],
                    bp_dict[mag_name],
                    self.obs_mag_cutoff[alert_data['band'][i_obj]],
                    phot_params)

                self.assertAlmostEqual(snr / alert_data['q_snr'][i_obj], 1.0,
                                       4)

                tot_mag = self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex] + \
                          true_lc_dict[alert_data['uniqueId'][i_obj]][alert_data['obshistId'][i_obj]]

                snr, gamma = calcSNR_m5(tot_mag, bp_dict[mag_name], m5,
                                        phot_params)
                self.assertAlmostEqual(snr / alert_data['tot_snr'][i_obj], 1.0,
                                       4)

        for val in obshistid_unqid_set:
            self.assertIn(val, obshistid_unqid_simulated_set)
        self.assertEqual(len(obshistid_unqid_set),
                         len(obshistid_unqid_simulated_set))

        astrometry_query = 'SELECT uniqueId, ra, dec, TAI '
        astrometry_query += 'FROM baseline_astrometry'
        astrometry_dtype = np.dtype([('uniqueId', int), ('ra', float),
                                     ('dec', float), ('TAI', float)])

        tai_list = []
        for obs in self.obs_list:
            tai_list.append(obs.mjd.TAI)
        tai_list = np.array(tai_list)

        n_tot_ast_simulated = 0
        for file_name in sqlite_file_list:
            if not file_name.endswith('db'):
                continue
            full_name = os.path.join(self.output_dir, file_name)
            self.assertTrue(os.path.exists(full_name))
            alert_db = DBObject(full_name, driver='sqlite')
            astrometry_data = alert_db.execute_arbitrary(
                astrometry_query, dtype=astrometry_dtype)

            if len(astrometry_data) == 0:
                continue

            mjd_list = ModifiedJulianDate.get_list(TAI=astrometry_data['TAI'])
            for i_obj in range(len(astrometry_data)):
                n_tot_ast_simulated += 1
                obj_dex = (astrometry_data['uniqueId'][i_obj] // 1024) - 1
                ra_truth, dec_truth = applyProperMotion(
                    self.ra_truth[obj_dex],
                    self.dec_truth[obj_dex],
                    self.pmra_truth[obj_dex],
                    self.pmdec_truth[obj_dex],
                    self.px_truth[obj_dex],
                    self.vrad_truth[obj_dex],
                    mjd=mjd_list[i_obj])

                distance = angularSeparation(ra_truth, dec_truth,
                                             astrometry_data['ra'][i_obj],
                                             astrometry_data['dec'][i_obj])

                self.assertLess(3600.0 * distance, 0.0005)

        del alert_gen
        gc.collect()
        self.assertGreater(n_tot_simulated, 10)
        self.assertGreater(len(obshistid_unqid_simulated_set), 10)
        self.assertLess(len(obshistid_unqid_simulated_set),
                        n_total_observations)
        self.assertGreater(n_tot_ast_simulated, 0)
    def test_alert_data_generation(self):

        dmag_cutoff = 0.005
        mag_name_to_int = {'u': 0, 'g': 1, 'r': 2, 'i': 3, 'z' : 4, 'y': 5}

        _max_var_param_str = self.max_str_len

        class StarAlertTestDBObj(StellarAlertDBObjMixin, CatalogDBObject):
            objid = 'star_alert'
            tableid = 'stars'
            idColKey = 'simobjid'
            raColName = 'ra'
            decColName = 'dec'
            objectTypeId = 0
            columns = [('raJ2000', 'ra*0.01745329252'),
                       ('decJ2000', 'dec*0.01745329252'),
                       ('parallax', 'px*0.01745329252/3600.0'),
                       ('properMotionRa', 'pmra*0.01745329252/3600.0'),
                       ('properMotionDec', 'pmdec*0.01745329252/3600.0'),
                       ('radialVelocity', 'vrad'),
                       ('variabilityParameters', 'varParamStr', str, _max_var_param_str)]

        class TestAlertsVarCatMixin(object):

            @register_method('alert_test')
            def applyAlertTest(self, valid_dexes, params, expmjd, variability_cache=None):
                if len(params) == 0:
                    return np.array([[], [], [], [], [], []])

                if isinstance(expmjd, numbers.Number):
                    dmags_out = np.zeros((6, self.num_variable_obj(params)))
                else:
                    dmags_out = np.zeros((6, self.num_variable_obj(params), len(expmjd)))

                for i_star in range(self.num_variable_obj(params)):
                    if params['amp'][i_star] is not None:
                        dmags = params['amp'][i_star]*np.cos(params['per'][i_star]*expmjd)
                        for i_filter in range(6):
                            dmags_out[i_filter][i_star] = dmags

                return dmags_out

        class TestAlertsVarCat(TestAlertsVarCatMixin, AlertStellarVariabilityCatalog):
            pass

        class TestAlertsTruthCat(TestAlertsVarCatMixin, CameraCoordsLSST, AstrometryStars,
                                 Variability, InstanceCatalog):
            column_outputs = ['uniqueId', 'chipName', 'dmagAlert', 'magAlert']

            @compound('delta_umag', 'delta_gmag', 'delta_rmag',
                      'delta_imag', 'delta_zmag', 'delta_ymag')
            def get_TruthVariability(self):
                return self.applyVariability(self.column_by_name('varParamStr'))

            @cached
            def get_dmagAlert(self):
                return self.column_by_name('delta_%smag' % self.obs_metadata.bandpass)

            @cached
            def get_magAlert(self):
                return self.column_by_name('%smag' % self.obs_metadata.bandpass) + \
                       self.column_by_name('dmagAlert')

        star_db = StarAlertTestDBObj(database=self.star_db_name, driver='sqlite')

        # assemble the true light curves for each object; we need to figure out
        # if their np.max(dMag) ever goes over dmag_cutoff; then we will know if
        # we are supposed to simulate them
        true_lc_dict = {}
        true_lc_obshistid_dict = {}
        is_visible_dict = {}
        obs_dict = {}
        max_obshistid = -1
        n_total_observations = 0
        for obs in self.obs_list:
            obs_dict[obs.OpsimMetaData['obsHistID']] = obs
            obshistid = obs.OpsimMetaData['obsHistID']
            if obshistid > max_obshistid:
                max_obshistid = obshistid
            cat = TestAlertsTruthCat(star_db, obs_metadata=obs)

            for line in cat.iter_catalog():
                if line[1] is None:
                    continue

                n_total_observations += 1
                if line[0] not in true_lc_dict:
                    true_lc_dict[line[0]] = {}
                    true_lc_obshistid_dict[line[0]] = []

                true_lc_dict[line[0]][obshistid] = line[2]
                true_lc_obshistid_dict[line[0]].append(obshistid)

                if line[0] not in is_visible_dict:
                    is_visible_dict[line[0]] = False

                if line[3] <= self.obs_mag_cutoff[mag_name_to_int[obs.bandpass]]:
                    is_visible_dict[line[0]] = True

        obshistid_bits = int(np.ceil(np.log(max_obshistid)/np.log(2)))

        skipped_due_to_mag = 0

        objects_to_simulate = []
        obshistid_unqid_set = set()
        for obj_id in true_lc_dict:

            dmag_max = -1.0
            for obshistid in true_lc_dict[obj_id]:
                if np.abs(true_lc_dict[obj_id][obshistid]) > dmag_max:
                    dmag_max = np.abs(true_lc_dict[obj_id][obshistid])

            if dmag_max >= dmag_cutoff:
                if not is_visible_dict[obj_id]:
                    skipped_due_to_mag += 1
                    continue

                objects_to_simulate.append(obj_id)
                for obshistid in true_lc_obshistid_dict[obj_id]:
                    obshistid_unqid_set.add((obj_id << obshistid_bits) + obshistid)

        self.assertGreater(len(objects_to_simulate), 10)
        self.assertGreater(skipped_due_to_mag, 0)

        log_file_name = tempfile.mktemp(dir=self.output_dir, suffix='log.txt')
        alert_gen = AlertDataGenerator(testing=True)

        alert_gen.subdivide_obs(self.obs_list, htmid_level=6)

        for htmid in alert_gen.htmid_list:
            alert_gen.alert_data_from_htmid(htmid, star_db,
                                            photometry_class=TestAlertsVarCat,
                                            output_prefix='alert_test',
                                            output_dir=self.output_dir,
                                            dmag_cutoff=dmag_cutoff,
                                            log_file_name=log_file_name)

        dummy_sed = Sed()

        bp_dict = BandpassDict.loadTotalBandpassesFromFiles()

        phot_params = PhotometricParameters()

        # First, verify that the contents of the sqlite files are all correct

        n_tot_simulated = 0

        alert_query = 'SELECT alert.uniqueId, alert.obshistId, meta.TAI, '
        alert_query += 'meta.band, quiescent.flux, alert.dflux, '
        alert_query += 'quiescent.snr, alert.snr, '
        alert_query += 'alert.ra, alert.dec, alert.chipNum, '
        alert_query += 'alert.xPix, alert.yPix, ast.pmRA, ast.pmDec, '
        alert_query += 'ast.parallax '
        alert_query += 'FROM alert_data AS alert '
        alert_query += 'INNER JOIN metadata AS meta ON meta.obshistId=alert.obshistId '
        alert_query += 'INNER JOIN quiescent_flux AS quiescent '
        alert_query += 'ON quiescent.uniqueId=alert.uniqueId '
        alert_query += 'AND quiescent.band=meta.band '
        alert_query += 'INNER JOIN baseline_astrometry AS ast '
        alert_query += 'ON ast.uniqueId=alert.uniqueId'

        alert_dtype = np.dtype([('uniqueId', int), ('obshistId', int),
                                ('TAI', float), ('band', int),
                                ('q_flux', float), ('dflux', float),
                                ('q_snr', float), ('tot_snr', float),
                                ('ra', float), ('dec', float),
                                ('chipNum', int), ('xPix', float), ('yPix', float),
                                ('pmRA', float), ('pmDec', float), ('parallax', float)])

        sqlite_file_list = os.listdir(self.output_dir)

        n_tot_simulated = 0
        obshistid_unqid_simulated_set = set()
        for file_name in sqlite_file_list:
            if not file_name.endswith('db'):
                continue
            full_name = os.path.join(self.output_dir, file_name)
            self.assertTrue(os.path.exists(full_name))
            alert_db = DBObject(full_name, driver='sqlite')
            alert_data = alert_db.execute_arbitrary(alert_query, dtype=alert_dtype)
            if len(alert_data) == 0:
                continue

            mjd_list = ModifiedJulianDate.get_list(TAI=alert_data['TAI'])
            for i_obj in range(len(alert_data)):
                n_tot_simulated += 1
                obshistid_unqid_simulated_set.add((alert_data['uniqueId'][i_obj] << obshistid_bits) +
                                                  alert_data['obshistId'][i_obj])

                unq = alert_data['uniqueId'][i_obj]
                obj_dex = (unq//1024)-1
                self.assertAlmostEqual(self.pmra_truth[obj_dex], 0.001*alert_data['pmRA'][i_obj], 4)
                self.assertAlmostEqual(self.pmdec_truth[obj_dex], 0.001*alert_data['pmDec'][i_obj], 4)
                self.assertAlmostEqual(self.px_truth[obj_dex], 0.001*alert_data['parallax'][i_obj], 4)

                ra_truth, dec_truth = applyProperMotion(self.ra_truth[obj_dex], self.dec_truth[obj_dex],
                                                        self.pmra_truth[obj_dex], self.pmdec_truth[obj_dex],
                                                        self.px_truth[obj_dex], self.vrad_truth[obj_dex],
                                                        mjd=mjd_list[i_obj])
                distance = angularSeparation(ra_truth, dec_truth,
                                             alert_data['ra'][i_obj], alert_data['dec'][i_obj])

                distance_arcsec = 3600.0*distance
                msg = '\ntruth: %e %e\nalert: %e %e\n' % (ra_truth, dec_truth,
                                                          alert_data['ra'][i_obj],
                                                          alert_data['dec'][i_obj])

                self.assertLess(distance_arcsec, 0.0005, msg=msg)

                obs = obs_dict[alert_data['obshistId'][i_obj]]

                chipname = chipNameFromRaDecLSST(self.ra_truth[obj_dex], self.dec_truth[obj_dex],
                                                 pm_ra=self.pmra_truth[obj_dex],
                                                 pm_dec=self.pmdec_truth[obj_dex],
                                                 parallax=self.px_truth[obj_dex],
                                                 v_rad=self.vrad_truth[obj_dex],
                                                 obs_metadata=obs,
                                                 band=obs.bandpass)

                chipnum = int(chipname.replace('R', '').replace('S', '').
                              replace(' ', '').replace(';', '').replace(',', '').
                              replace(':', ''))

                self.assertEqual(chipnum, alert_data['chipNum'][i_obj])

                xpix, ypix = pixelCoordsFromRaDecLSST(self.ra_truth[obj_dex], self.dec_truth[obj_dex],
                                                      pm_ra=self.pmra_truth[obj_dex],
                                                      pm_dec=self.pmdec_truth[obj_dex],
                                                      parallax=self.px_truth[obj_dex],
                                                      v_rad=self.vrad_truth[obj_dex],
                                                      obs_metadata=obs,
                                                      band=obs.bandpass)

                self.assertAlmostEqual(alert_data['xPix'][i_obj], xpix, 4)
                self.assertAlmostEqual(alert_data['yPix'][i_obj], ypix, 4)

                dmag_sim = -2.5*np.log10(1.0+alert_data['dflux'][i_obj]/alert_data['q_flux'][i_obj])
                self.assertAlmostEqual(true_lc_dict[alert_data['uniqueId'][i_obj]][alert_data['obshistId'][i_obj]],
                                       dmag_sim, 3)

                mag_name = ('u', 'g', 'r', 'i', 'z', 'y')[alert_data['band'][i_obj]]
                m5 = obs.m5[mag_name]

                q_mag = dummy_sed.magFromFlux(alert_data['q_flux'][i_obj])
                self.assertAlmostEqual(self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex],
                                       q_mag, 4)

                snr, gamma = calcSNR_m5(self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex],
                                        bp_dict[mag_name],
                                        self.obs_mag_cutoff[alert_data['band'][i_obj]],
                                        phot_params)

                self.assertAlmostEqual(snr/alert_data['q_snr'][i_obj], 1.0, 4)

                tot_mag = self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex] + \
                          true_lc_dict[alert_data['uniqueId'][i_obj]][alert_data['obshistId'][i_obj]]

                snr, gamma = calcSNR_m5(tot_mag, bp_dict[mag_name],
                                        m5, phot_params)
                self.assertAlmostEqual(snr/alert_data['tot_snr'][i_obj], 1.0, 4)

        for val in obshistid_unqid_set:
            self.assertIn(val, obshistid_unqid_simulated_set)
        self.assertEqual(len(obshistid_unqid_set), len(obshistid_unqid_simulated_set))

        astrometry_query = 'SELECT uniqueId, ra, dec, TAI '
        astrometry_query += 'FROM baseline_astrometry'
        astrometry_dtype = np.dtype([('uniqueId', int),
                                     ('ra', float),
                                     ('dec', float),
                                     ('TAI', float)])

        tai_list = []
        for obs in self.obs_list:
            tai_list.append(obs.mjd.TAI)
        tai_list = np.array(tai_list)

        n_tot_ast_simulated = 0
        for file_name in sqlite_file_list:
            if not file_name.endswith('db'):
                continue
            full_name = os.path.join(self.output_dir, file_name)
            self.assertTrue(os.path.exists(full_name))
            alert_db = DBObject(full_name, driver='sqlite')
            astrometry_data = alert_db.execute_arbitrary(astrometry_query, dtype=astrometry_dtype)

            if len(astrometry_data) == 0:
                continue

            mjd_list = ModifiedJulianDate.get_list(TAI=astrometry_data['TAI'])
            for i_obj in range(len(astrometry_data)):
                n_tot_ast_simulated += 1
                obj_dex = (astrometry_data['uniqueId'][i_obj]//1024) - 1
                ra_truth, dec_truth = applyProperMotion(self.ra_truth[obj_dex], self.dec_truth[obj_dex],
                                                        self.pmra_truth[obj_dex], self.pmdec_truth[obj_dex],
                                                        self.px_truth[obj_dex], self.vrad_truth[obj_dex],
                                                        mjd=mjd_list[i_obj])

                distance = angularSeparation(ra_truth, dec_truth,
                                             astrometry_data['ra'][i_obj],
                                             astrometry_data['dec'][i_obj])

                self.assertLess(3600.0*distance, 0.0005)

        del alert_gen
        gc.collect()
        self.assertGreater(n_tot_simulated, 10)
        self.assertGreater(len(obshistid_unqid_simulated_set), 10)
        self.assertLess(len(obshistid_unqid_simulated_set), n_total_observations)
        self.assertGreater(n_tot_ast_simulated, 0)
    def test_pixel_positions(self):
        """
        Test that CatSim pixel positions are close to PhoSim pixel positions.

        This is complicated by the fact that PhoSim uses the camera team definition
        of pixel space, which differs from the DM definition of pixel space as follows:

        Camera +y = DM +x
        Camera +x = DM -y
        Camera +z = DM +z

        This has been verified both by consulting documentation -- the documentation for
        afwCameraGeom says that +x is along the serial readout direction; LCA-13381
        indicates that, in the Camera team's definition, the serial readout is along +y --
        and phenomenologically by comparing the relationship between
        pixelCoordsFromPupilCoords() to visual inspection of PhoSim-generated FITS images.
        """
        self.assertGreater(len(self.data), 10)
        for ix in range(len(self.data)):

            in_name = self.data['chipName'][ix]
            chip_name = in_name[0]+':'+in_name[1]+','+in_name[2]
            chip_name += ' '+in_name[3]+':'+in_name[4]+','+in_name[5]
            corner_pixels = getCornerPixels(chip_name, lsst_camera())

            x_center_dm = 0.25*(corner_pixels[0][0] + corner_pixels[1][0] +
                                corner_pixels[2][0] + corner_pixels[3][0])

            y_center_dm = 0.25*(corner_pixels[0][1] + corner_pixels[1][1] +
                                corner_pixels[2][1] + corner_pixels[3][1])

            obs = ObservationMetaData(pointingRA=self.data['pointingRA'][ix],
                                      pointingDec=self.data['pointingDec'][ix],
                                      rotSkyPos=self.data['rotSkyPos'][ix],
                                      mjd=59580.0)

            xpix, ypix = pixelCoordsFromRaDecLSST(self.data['objRA'][ix],
                                                  self.data['objDec'][ix],
                                                  obs_metadata=obs)

            raObs, decObs = observedFromICRS(self.data['objRA'][ix],
                                             self.data['objDec'][ix],
                                             obs_metadata=obs,
                                             epoch=2000.0)

            # find displacement from center of DM coordinates of the
            # objects as placed by PhoSim
            d_y_phosim = y_center_dm - self.data['xpix'][ix]
            d_x_phosim = self.data['ypix'][ix] - x_center_dm

            # displacement from center of DM coordinates as calculated
            # by DM
            d_x_dm = xpix - x_center_dm
            d_y_dm = ypix - y_center_dm

            d_pix = np.sqrt((d_x_dm - d_x_phosim)**2 +
                            (d_y_dm - d_y_phosim)**2)

            # demand that the difference between the two displacements is less
            # than 0.05 of the total displacement from the center of the object
            # as calculated by DM
            msg = 'dx %e; dy %e' % (d_x_dm, d_y_dm)
            self.assertLess(d_pix, 0.05*np.sqrt(d_x_dm**2+d_y_dm**2), msg=msg)
示例#10
0
    def test_chip_name_from_ra_dec_degrees(self):
        """
        test that chipNameFromRaDecLSST agrees with chipNameFromRaDec
        """

        n_obj = 1000
        raP = 112.1
        decP = -34.1
        obs = ObservationMetaData(pointingRA=raP,
                                  pointingDec=decP,
                                  rotSkyPos=45.0,
                                  mjd=43000.0)

        rng = np.random.RandomState(8731)
        rr = rng.random_sample(n_obj) * 1.75
        theta = rng.random_sample(n_obj) * 2.0 * np.pi
        ra_list = raP + rr * np.cos(theta)
        dec_list = decP + rr * np.sin(theta)
        control_name_list = chipNameFromRaDec(ra_list,
                                              dec_list,
                                              obs_metadata=obs,
                                              camera=self.camera)

        test_name_list = chipNameFromRaDecLSST(ra_list,
                                               dec_list,
                                               obs_metadata=obs)

        try:
            np.testing.assert_array_equal(control_name_list.astype(str),
                                          test_name_list.astype(str))
        except AssertionError:
            n_problematic = 0
            for ii, (c_n, t_n) in enumerate(
                    zip(control_name_list.astype(str),
                        test_name_list.astype(str))):
                if c_n != t_n:
                    x_pix, y_pix = pixelCoordsFromRaDecLSST(ra_list[ii],
                                                            dec_list[ii],
                                                            obs_metadata=obs)
                    if c_n != 'None':
                        n_problematic += 1
            if n_problematic > 0:
                raise

        self.assertLessEqual(
            len(
                np.where(
                    np.char.rfind(test_name_list.astype(str), 'None') >= 0)
                [0]), n_obj / 10)

        # 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:
            chipNameFromRaDecLSST(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:
            chipNameFromRaDecLSST(ra_list, dec_list, obs_metadata=obs)
        self.assertIn("mjd", context.exception.args[0])

        with self.assertRaises(RuntimeError) as context:
            chipNameFromRaDecLSST(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:
            chipNameFromRaDecLSST(ra_list, dec_list[:5], obs_metadata=obs)
        self.assertIn("chipNameFromRaDecLSST", context.exception.args[0])
示例#11
0
    def test_pixel_coords_from_ra_dec_degrees(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 = raP + rr*np.cos(theta)
        dec_list = 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])