def testObservedFromAppGeo(self):
        obs = ObservationMetaData(pointingRA=35.0, pointingDec=-45.0,
                                  mjd=43572.0)

        for includeRefraction in [True, False]:
            raRad, decRad = utils._observedFromAppGeo(self.raList, self.decList,
                                                           includeRefraction=includeRefraction,
                                                           altAzHr=False, obs_metadata=obs)

            raDeg, decDeg = utils.observedFromAppGeo(np.degrees(self.raList),
                                                          np.degrees(self.decList),
                                                          includeRefraction=includeRefraction,
                                                          altAzHr=False, obs_metadata=obs)

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

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


            raDec, altAz = utils._observedFromAppGeo(self.raList, self.decList,
                                                          includeRefraction=includeRefraction,
                                                          altAzHr=True, obs_metadata=obs)

            raRad = raDec[0]
            decRad = raDec[1]
            altRad = altAz[0]
            azRad = altAz[1]

            raDec, altAz = utils.observedFromAppGeo(np.degrees(self.raList),
                                                         np.degrees(self.decList),
                                                         includeRefraction=includeRefraction,
                                                         altAzHr=True, obs_metadata=obs)

            raDeg = raDec[0]
            decDeg = raDec[1]
            altDeg = altAz[0]
            azDeg = altAz[1]

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

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

            dAz = utils.arcsecFromRadians(azRad-np.radians(azDeg))
            np.testing.assert_array_almost_equal(dAz, np.zeros(self.nStars), 9)

            dAlt = utils.arcsecFromRadians(altRad-np.radians(altDeg))
            np.testing.assert_array_almost_equal(dAlt, np.zeros(self.nStars), 9)
Exemple #2
0
    def _find_objects_on_chip(self, object_lines, chip_name):
        num_lines = len(object_lines)
        ra_phosim = np.zeros(num_lines, dtype=float)
        dec_phosim = np.zeros(num_lines, dtype=float)
        mag_norm = 55. * np.ones(num_lines, dtype=float)
        for i, line in enumerate(object_lines):
            if not line.startswith('object'):
                raise RuntimeError('Trying to process non-object entry from '
                                   'the instance catalog.')
            tokens = line.split()
            ra_phosim[i] = float(tokens[2])
            dec_phosim[i] = float(tokens[3])
            mag_norm[i] = float(tokens[4])
        ra_appGeo, dec_appGeo \
            = PhoSimAstrometryBase._appGeoFromPhoSim(np.radians(ra_phosim),
                                                     np.radians(dec_phosim),
                                                     self.obs_md)
        ra_obs_rad, dec_obs_rad \
            = _observedFromAppGeo(ra_appGeo, dec_appGeo,
                                  obs_metadata=self.obs_md,
                                  includeRefraction=True)
        x_pupil, y_pupil = _pupilCoordsFromObserved(ra_obs_rad, dec_obs_rad,
                                                    self.obs_md)
        on_chip_dict = _chip_downselect(mag_norm, x_pupil, y_pupil,
                                        self.logger, [chip_name])
        index = on_chip_dict[chip_name]

        self.object_lines = []
        for i in index[0]:
            self.object_lines.append(object_lines[i])
        self.x_pupil = list(x_pupil[index])
        self.y_pupil = list(y_pupil[index])
        self.bp_dict = BandpassDict.loadTotalBandpassesFromFiles()
    def test_appGeoFromObserved(self):
        """
        Test that _appGeoFromObserved really does invert _observedFromAppGeo
        """
        mjd = 58350.0
        site = Site(longitude=numpy.degrees(0.235), latitude=numpy.degrees(-1.2), name='LSST')
        raCenter, decCenter = raDecFromAltAz(90.0, 0.0,
                                             ObservationMetaData(mjd=mjd, site=site))

        obs = ObservationMetaData(pointingRA=raCenter, pointingDec=decCenter,
                                  mjd=ModifiedJulianDate(TAI=58350.0),
                                  site=site)

        numpy.random.seed(125543)
        nSamples = 200

        # Note: the PALPY routines in question start to become inaccurate at
        # a zenith distance of about 75 degrees, so we restrict our test points
        # to be within 50 degrees of the telescope pointing, which is at zenith
        # in a flat sky approximation
        rr = numpy.random.random_sample(nSamples)*numpy.radians(50.0)
        theta = numpy.random.random_sample(nSamples)*2.0*numpy.pi
        ra_in = numpy.radians(raCenter) + rr*numpy.cos(theta)
        dec_in = numpy.radians(decCenter) + rr*numpy.sin(theta)

        xx_in = numpy.cos(dec_in)*numpy.cos(ra_in)
        yy_in = numpy.cos(dec_in)*numpy.sin(ra_in)
        zz_in = numpy.sin(dec_in)

        for includeRefraction in [True, False]:
            for wavelength in (0.5, 0.3, 0.7):
                ra_obs, dec_obs = _observedFromAppGeo(ra_in, dec_in, obs_metadata=obs,
                                                      wavelength=wavelength,
                                                      includeRefraction=includeRefraction)

                ra_out, dec_out = _appGeoFromObserved(ra_obs, dec_obs, obs_metadata=obs,
                                                      wavelength=wavelength,
                                                      includeRefraction=includeRefraction)


                xx_out = numpy.cos(dec_out)*numpy.cos(ra_out)
                yy_out = numpy.cos(dec_out)*numpy.sin(ra_out)
                zz_out = numpy.sin(dec_out)

                distance = numpy.sqrt(numpy.power(xx_in-xx_out,2) +
                                      numpy.power(yy_in-yy_out,2) +
                                      numpy.power(zz_in-zz_out,2))

                self.assertLess(distance.max(), 1.0e-12)
Exemple #4
0
    def testParallax(self):
        """
        This test will output a catalog of ICRS and observed positions.
        It will also output the quantities (proper motion, radial velocity,
        and parallax) needed to apply the transformaiton between the two.
        It will then run the catalog through PALPY and verify that the catalog
        generating code correctly applied the transformations.
        """

        # create and write a catalog that performs astrometric transformations
        # on a cartoon star database
        cat = parallaxTestCatalog(self.starDBObject, obs_metadata=self.obs_metadata)
        parallaxName = os.path.join(getPackageDir('sims_catUtils'), 'tests',
                                    'scratchSpace', 'parallaxCatalog.sav')

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

        cat.write_catalog(parallaxName)

        data = np.genfromtxt(parallaxName, delimiter=',')
        self.assertGreater(len(data), 0)

        epoch = cat.db_obj.epoch
        mjd = cat.obs_metadata.mjd
        prms = pal.mappa(epoch, mjd.TDB)
        for vv in data:
            # run the PALPY routines that actuall do astrometry `by hand' and compare
            # the results to the contents of the catalog
            ra0 = np.radians(vv[0])
            dec0 = np.radians(vv[1])
            pmra = np.radians(vv[4])
            pmdec = np.radians(vv[5])
            rv = vv[6]
            px = vv[7]
            ra_apparent, dec_apparent = pal.mapqk(ra0, dec0, pmra, pmdec, px, rv, prms)
            ra_apparent = np.array([ra_apparent])
            dec_apparent = np.array([dec_apparent])
            raObserved, decObserved = _observedFromAppGeo(ra_apparent, dec_apparent,
                                                          obs_metadata=cat.obs_metadata)

            self.assertAlmostEqual(raObserved[0], np.radians(vv[2]), 7)
            self.assertAlmostEqual(decObserved[0], np.radians(vv[3]), 7)

        if os.path.exists(parallaxName):
            os.unlink(parallaxName)
    def testParallax(self):
        """
        This test will output a catalog of ICRS and observed positions.
        It will also output the quantities (proper motion, radial velocity,
        and parallax) needed to apply the transformaiton between the two.
        It will then run the catalog through PALPY and verify that the catalog
        generating code correctly applied the transformations.
        """

        #create and write a catalog that performs astrometric transformations
        #on a cartoon star database
        cat = parallaxTestCatalog(self.starDBObject, obs_metadata=self.obs_metadata)
        parallaxName = os.path.join(getPackageDir('sims_catUtils'), 'tests',
                                    'scratchSpace', 'parallaxCatalog.sav')

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

        cat.write_catalog(parallaxName)

        data = numpy.genfromtxt(parallaxName,delimiter=',')
        self.assertGreater(len(data), 0)

        epoch = cat.db_obj.epoch
        mjd = cat.obs_metadata.mjd
        prms = pal.mappa(epoch, mjd.TDB)
        for vv in data:
            #run the PALPY routines that actuall do astrometry `by hand' and compare
            #the results to the contents of the catalog
            ra0 = numpy.radians(vv[0])
            dec0 = numpy.radians(vv[1])
            pmra = numpy.radians(vv[4])
            pmdec = numpy.radians(vv[5])
            rv = vv[6]
            px = vv[7]
            ra_apparent, dec_apparent = pal.mapqk(ra0, dec0, pmra, pmdec, px, rv, prms)
            ra_apparent = numpy.array([ra_apparent])
            dec_apparent = numpy.array([dec_apparent])
            raObserved, decObserved = _observedFromAppGeo(ra_apparent, dec_apparent,
                                                                 obs_metadata=cat.obs_metadata)

            self.assertAlmostEqual(raObserved[0],numpy.radians(vv[2]),7)
            self.assertAlmostEqual(decObserved[0],numpy.radians(vv[3]),7)

        if os.path.exists(parallaxName):
            os.unlink(parallaxName)
    def test_stellar_observed_radians(self):
        """
        Test ability to go all the way to observed RA, Dec
        from PhoSim (this is necessary for the ImSim software
        that DESC is working on)
        """
        db = testStarsDBObj(driver='sqlite', database=self.db_name)
        cat = StarTestCatalog(db, obs_metadata=self.obs)
        with lsst.utils.tests.getTempFilePath('.txt') as cat_name:
            cat.write_catalog(cat_name)
            dtype = np.dtype([('raICRS', float), ('decICRS', float),
                             ('raPhoSim', float), ('decPhoSim', float),
                             ('raJ2000', float), ('decJ2000', float),
                             ('pmRA', float), ('pmDec', float),
                             ('parallax', float), ('vRad', float)])
            data = np.genfromtxt(cat_name, dtype=dtype)
        self.assertGreater(len(data), 100)

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

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

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

        dd = arcsecFromRadians(_angularSeparation(ra_obs, dec_obs, ra_obs_2, dec_obs_2))
        self.assertLess(dd.max(), 1.0e-5)
    def test_stellar_observed_radians(self):
        """
        Test ability to go all the way to observed RA, Dec
        from PhoSim (this is necessary for the ImSim software
        that DESC is working on)
        """
        db = testStarsDBObj(driver='sqlite', database=self.db_name)
        cat = StarTestCatalog(db, obs_metadata=self.obs)
        with lsst.utils.tests.getTempFilePath('.txt') as cat_name:
            cat.write_catalog(cat_name)
            dtype = np.dtype([('raICRS', float), ('decICRS', float),
                              ('raPhoSim', float), ('decPhoSim', float),
                              ('raJ2000', float), ('decJ2000', float),
                              ('pmRA', float), ('pmDec', float),
                              ('parallax', float), ('vRad', float)])
            data = np.genfromtxt(cat_name, dtype=dtype)
        self.assertGreater(len(data), 100)

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

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

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

        dd = arcsecFromRadians(
            _angularSeparation(ra_obs, dec_obs, ra_obs_2, dec_obs_2))
        self.assertLess(dd.max(), 1.0e-5)
    def test_icrsFromObserved(self):
        """
        Test that _icrsFromObserved really inverts _observedFromAppGeo.

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

        numpy.random.seed(412)
        nSamples = 100

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

        site = Site(name='LSST')

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

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

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

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

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

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

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

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

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

                        self.assertGreater(len(valid_pts), 0)

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

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


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

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

                        self.assertLess(distance.max(), 0.01)
    def testAstrometryExceptions(self):
        """
        Test to make sure that stand-alone astrometry methods raise an exception when they are called without
        the necessary arguments
        """
        obs_metadata = makeObservationMetaData()
        ra, dec, pm_ra, pm_dec, parallax, v_rad = makeRandomSample()

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        #test that it actually runs
        test = _observedFromICRS(ra, dec, obs_metadata=dummy, epoch=2000.0)
Exemple #10
0
def sources_from_file(file_name, obs_md, phot_params, numRows=None):
    """
    Read in an InstanceCatalog and extract all of the astrophysical
    sources from it

    Parameters
    ----------
    file_name: str
        The name of the InstanceCatalog

    obs_md: ObservationMetaData
        The ObservationMetaData characterizing the pointing

    phot_params: PhotometricParameters
        The PhotometricParameters characterizing this telescope

    numRows: int (optional)
        The number of rows of the InstanceCatalog to read in (including the
        header)

    Returns
    -------
    gs_obj_arr: numpy array
        Contains the GalSimCelestialObjects for all of the
        astrophysical sources in this InstanceCatalog

    out_obj_dict: dict
        Keyed on the names of the detectors in the LSST camera.
        The values are numpy arrays of GalSimCelestialObjects
        that should be simulated for that detector, including
        objects that are near the edge of the chip or
        just bright (in which case, they might still illuminate
        the detector).
    """

    camera = get_obs_lsstSim_camera()

    num_objects = 0
    ct_rows = 0
    with fopen(file_name, mode='rt') as input_file:
        for line in input_file:
            ct_rows += 1
            params = line.strip().split()
            if params[0] == 'object':
                num_objects += 1
            if numRows is not None and ct_rows >= numRows:
                break

    # RA, Dec in the coordinate system expected by PhoSim
    ra_phosim = np.zeros(num_objects, dtype=float)
    dec_phosim = np.zeros(num_objects, dtype=float)

    sed_name = [None] * num_objects
    mag_norm = 55.0 * np.ones(num_objects, dtype=float)
    gamma1 = np.zeros(num_objects, dtype=float)
    gamma2 = np.zeros(num_objects, dtype=float)
    kappa = np.zeros(num_objects, dtype=float)

    internal_av = np.zeros(num_objects, dtype=float)
    internal_rv = np.zeros(num_objects, dtype=float)
    galactic_av = np.zeros(num_objects, dtype=float)
    galactic_rv = np.zeros(num_objects, dtype=float)
    semi_major_arcsec = np.zeros(num_objects, dtype=float)
    semi_minor_arcsec = np.zeros(num_objects, dtype=float)
    position_angle_degrees = np.zeros(num_objects, dtype=float)
    sersic_index = np.zeros(num_objects, dtype=float)
    npoints = np.zeros(num_objects, dtype=int)
    redshift = np.zeros(num_objects, dtype=float)

    unique_id = np.zeros(num_objects, dtype=int)
    object_type = np.zeros(num_objects, dtype=int)

    i_obj = -1
    with fopen(file_name, mode='rt') as input_file:
        for line in input_file:
            params = line.strip().split()
            if params[0] != 'object':
                continue
            i_obj += 1
            if numRows is not None and i_obj >= num_objects:
                break
            unique_id[i_obj] = int(params[1])
            ra_phosim[i_obj] = float(params[2])
            dec_phosim[i_obj] = float(params[3])
            mag_norm[i_obj] = float(params[4])
            sed_name[i_obj] = params[5]
            redshift[i_obj] = float(params[6])
            gamma1[i_obj] = float(params[7])
            gamma2[i_obj] = float(params[8])
            kappa[i_obj] = float(params[9])
            if params[12].lower() == 'point':
                object_type[i_obj] = _POINT_SOURCE
                i_gal_dust_model = 14
                if params[13].lower() != 'none':
                    i_gal_dust_model = 16
                    internal_av[i_obj] = float(params[14])
                    internal_rv[i_obj] = float(params[15])
                if params[i_gal_dust_model].lower() != 'none':
                    galactic_av[i_obj] = float(params[i_gal_dust_model + 1])
                    galactic_rv[i_obj] = float(params[i_gal_dust_model + 2])
            elif params[12].lower() == 'sersic2d':
                object_type[i_obj] = _SERSIC_2D
                semi_major_arcsec[i_obj] = float(params[13])
                semi_minor_arcsec[i_obj] = float(params[14])
                position_angle_degrees[i_obj] = float(params[15])
                sersic_index[i_obj] = float(params[16])
                i_gal_dust_model = 18
                if params[17].lower() != 'none':
                    i_gal_dust_model = 20
                    internal_av[i_obj] = float(params[18])
                    internal_rv[i_obj] = float(params[19])
                if params[i_gal_dust_model].lower() != 'none':
                    galactic_av[i_obj] = float(params[i_gal_dust_model + 1])
                    galactic_rv[i_obj] = float(params[i_gal_dust_model + 2])
            elif params[12].lower() == 'knots':
                object_type[i_obj] = _RANDOM_WALK
                semi_major_arcsec[i_obj] = float(params[13])
                semi_minor_arcsec[i_obj] = float(params[14])
                position_angle_degrees[i_obj] = float(params[15])
                npoints[i_obj] = int(params[16])
                i_gal_dust_model = 18
                if params[17].lower() != 'none':
                    i_gal_dust_model = 20
                    internal_av[i_obj] = float(params[18])
                    internal_rv[i_obj] = float(params[19])
                if params[i_gal_dust_model].lower() != 'none':
                    galactic_av[i_obj] = float(params[i_gal_dust_model + 1])
                    galactic_rv[i_obj] = float(params[i_gal_dust_model + 2])
            else:
                raise RuntimeError("Do not know how to handle "
                                   "object type: %s" % params[12])

    ra_appGeo, dec_appGeo = PhoSimAstrometryBase._appGeoFromPhoSim(
        np.radians(ra_phosim), np.radians(dec_phosim), obs_md)

    (ra_obs_rad, dec_obs_rad) = _observedFromAppGeo(ra_appGeo,
                                                    dec_appGeo,
                                                    obs_metadata=obs_md,
                                                    includeRefraction=True)

    semi_major_radians = radiansFromArcsec(semi_major_arcsec)
    semi_minor_radians = radiansFromArcsec(semi_minor_arcsec)
    position_angle_radians = np.radians(position_angle_degrees)

    x_pupil, y_pupil = _pupilCoordsFromObserved(ra_obs_rad, dec_obs_rad,
                                                obs_md)

    bp_dict = BandpassDict.loadTotalBandpassesFromFiles()

    sed_dir = lsstUtils.getPackageDir('sims_sed_library')

    object_is_valid = np.array([True] * num_objects)

    invalid_objects = np.where(
        np.logical_or(
            np.logical_or(
                mag_norm > 50.0,
                np.logical_and(galactic_av == 0.0, galactic_rv == 0.0)),
            np.logical_or(
                np.logical_and(object_type == _SERSIC_2D,
                               semi_major_arcsec < semi_minor_arcsec),
                np.logical_and(object_type == _RANDOM_WALK, npoints <= 0))))

    object_is_valid[invalid_objects] = False

    if len(invalid_objects[0]) > 0:
        message = "\nOmitted %d suspicious objects from " % len(
            invalid_objects[0])
        message += "the instance catalog:\n"
        n_bad_mag_norm = len(np.where(mag_norm > 50.0)[0])
        message += "    %d had mag_norm > 50.0\n" % n_bad_mag_norm
        n_bad_av = len(
            np.where(np.logical_and(galactic_av == 0.0,
                                    galactic_rv == 0.0))[0])
        message += "    %d had galactic_Av == galactic_Rv == 0\n" % n_bad_av
        n_bad_axes = len(
            np.where(
                np.logical_and(object_type == _SERSIC_2D,
                               semi_major_arcsec < semi_minor_arcsec))[0])
        message += "    %d had semi_major_axis < semi_minor_axis\n" % n_bad_axes
        n_bad_knots = len(
            np.where(np.logical_and(object_type == _RANDOM_WALK,
                                    npoints <= 0))[0])
        message += "    %d had n_points <= 0 \n" % n_bad_knots
        warnings.warn(message)

    wav_int = None
    wav_gal = None

    gs_object_arr = []
    for i_obj in range(num_objects):
        if not object_is_valid[i_obj]:
            continue

        if object_type[i_obj] == _POINT_SOURCE:
            gs_type = 'pointSource'
        elif object_type[i_obj] == _SERSIC_2D:
            gs_type = 'sersic'
        elif object_type[i_obj] == _RANDOM_WALK:
            gs_type = 'RandomWalk'

        # load the SED
        sed_obj = Sed()
        sed_obj.readSED_flambda(os.path.join(sed_dir, sed_name[i_obj]))
        fnorm = getImsimFluxNorm(sed_obj, mag_norm[i_obj])
        sed_obj.multiplyFluxNorm(fnorm)
        if internal_av[i_obj] != 0.0:
            if wav_int is None or not np.array_equal(sed_obj.wavelen, wav_int):
                a_int, b_int = sed_obj.setupCCMab()
                wav_int = copy.deepcopy(sed_obj.wavelen)

            sed_obj.addCCMDust(a_int,
                               b_int,
                               A_v=internal_av[i_obj],
                               R_v=internal_rv[i_obj])

        if redshift[i_obj] != 0.0:
            sed_obj.redshiftSED(redshift[i_obj], dimming=True)

        sed_obj.resampleSED(wavelen_match=bp_dict.wavelenMatch)

        if galactic_av[i_obj] != 0.0:
            if wav_gal is None or not np.array_equal(sed_obj.wavelen, wav_gal):
                a_g, b_g = sed_obj.setupCCMab()
                wav_gal = copy.deepcopy(sed_obj.wavelen)

            sed_obj.addCCMDust(a_g,
                               b_g,
                               A_v=galactic_av[i_obj],
                               R_v=galactic_rv[i_obj])

        gs_object = GalSimCelestialObject(gs_type,
                                          x_pupil[i_obj],
                                          y_pupil[i_obj],
                                          semi_major_radians[i_obj],
                                          semi_minor_radians[i_obj],
                                          semi_major_radians[i_obj],
                                          position_angle_radians[i_obj],
                                          sersic_index[i_obj],
                                          sed_obj,
                                          bp_dict,
                                          phot_params,
                                          npoints[i_obj],
                                          gamma1=gamma1[i_obj],
                                          gamma2=gamma2[i_obj],
                                          kappa=kappa[i_obj],
                                          uniqueId=unique_id[i_obj])

        gs_object_arr.append(gs_object)

    gs_object_arr = np.array(gs_object_arr)

    # how close to the edge of the detector a source has
    # to be before we will just simulate it anyway
    pix_tol = 50.0

    # any source brighter than this will be considered
    # so bright that it should be simulated for all
    # detectors, just in case light scatters onto them.
    max_mag = 16.0

    # down-select mag_norm, x_pupil, and y_pupil
    # to only contain those objects that were
    # deemed to be valid above
    valid = np.where(object_is_valid)
    mag_norm = mag_norm[valid]
    x_pupil = x_pupil[valid]
    y_pupil = y_pupil[valid]

    assert len(mag_norm) == len(gs_object_arr)
    assert len(x_pupil) == len(gs_object_arr)
    assert len(y_pupil) == len(gs_object_arr)

    out_obj_dict = {}
    for det in lsst_camera():
        chip_name = det.getName()
        pixel_corners = getCornerPixels(chip_name, lsst_camera())
        x_min = pixel_corners[0][0]
        x_max = pixel_corners[2][0]
        y_min = pixel_corners[0][1]
        y_max = pixel_corners[3][1]
        xpix, ypix = pixelCoordsFromPupilCoords(x_pupil,
                                                y_pupil,
                                                chipName=chip_name,
                                                camera=lsst_camera())

        on_chip = np.where(
            np.logical_or(
                mag_norm < max_mag,
                np.logical_and(
                    xpix > x_min - pix_tol,
                    np.logical_and(
                        xpix < x_max + pix_tol,
                        np.logical_and(ypix > y_min - pix_tol,
                                       ypix < y_max + pix_tol)))))

        out_obj_dict[chip_name] = gs_object_arr[on_chip]

    return gs_object_arr, out_obj_dict
    def testObservedFromAppGeo(self):
        obs = ObservationMetaData(pointingRA=35.0,
                                  pointingDec=-45.0,
                                  mjd=43572.0)

        for includeRefraction in [True, False]:
            raRad, decRad = utils._observedFromAppGeo(
                self.raList,
                self.decList,
                includeRefraction=includeRefraction,
                altAzHr=False,
                obs_metadata=obs)

            raDeg, decDeg = utils.observedFromAppGeo(
                np.degrees(self.raList),
                np.degrees(self.decList),
                includeRefraction=includeRefraction,
                altAzHr=False,
                obs_metadata=obs)

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

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

            raDec, altAz = utils._observedFromAppGeo(
                self.raList,
                self.decList,
                includeRefraction=includeRefraction,
                altAzHr=True,
                obs_metadata=obs)

            raRad = raDec[0]
            altRad = altAz[0]
            azRad = altAz[1]

            raDec, altAz = utils.observedFromAppGeo(
                np.degrees(self.raList),
                np.degrees(self.decList),
                includeRefraction=includeRefraction,
                altAzHr=True,
                obs_metadata=obs)

            raDeg = raDec[0]
            altDeg = altAz[0]
            azDeg = altAz[1]

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

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

            dAz = utils.arcsecFromRadians(azRad - np.radians(azDeg))
            np.testing.assert_array_almost_equal(dAz, np.zeros(self.nStars), 9)

            dAlt = utils.arcsecFromRadians(altRad - np.radians(altDeg))
            np.testing.assert_array_almost_equal(dAlt, np.zeros(self.nStars),
                                                 9)