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 chipNameFromRaDec(ra, dec, pm_ra=None, pm_dec=None, parallax=None, v_rad=None, obs_metadata=None, camera=None, epoch=2000.0, allow_multiple_chips=False): """ Return the names of detectors that see the object specified by (RA, Dec) in degrees. @param [in] ra in degrees (a numpy array or a float). In the International Celestial Reference System. @param [in] dec in degrees (a numpy array or a float). In the International Celestial Reference System. @param [in] pm_ra is proper motion in RA multiplied by cos(Dec) (arcsec/yr) Can be a numpy array or a number or None (default=None). @param [in] pm_dec is proper motion in dec (arcsec/yr) Can be a numpy array or a number or None (default=None). @param [in] parallax is parallax in arcsec Can be a numpy array or a number or None (default=None). @param [in] v_rad is radial velocity (km/s) Can be a numpy array or a number or None (default=None). @param [in] obs_metadata is an ObservationMetaData characterizing the telescope pointing @param [in] epoch is the epoch in Julian years of the equinox against which RA and Dec are measured. Default is 2000. @param [in] camera is an afw.cameraGeom camera instance characterizing the camera @param [in] allow_multiple_chips is a boolean (default False) indicating whether or not this method will allow objects to be visible on more than one chip. If it is 'False' and an object appears on more than one chip, an exception will be raised. If it is 'True' and an object falls on more than one chip, it will still only return the first chip in the list of chips returned. THIS BEHAVIOR SHOULD BE FIXED IN A FUTURE TICKET. @param [out] a numpy array of chip names """ if pm_ra is not None: pm_ra_out = radiansFromArcsec(pm_ra) else: pm_ra_out = None if pm_dec is not None: pm_dec_out = radiansFromArcsec(pm_dec) else: pm_dec_out = None if parallax is not None: parallax_out = radiansFromArcsec(parallax) else: parallax_out = None return _chipNameFromRaDec(np.radians(ra), np.radians(dec), pm_ra=pm_ra_out, pm_dec=pm_dec_out, parallax=parallax_out, v_rad=v_rad, obs_metadata=obs_metadata, epoch=epoch, camera=camera, allow_multiple_chips=allow_multiple_chips)
def chipNameFromRaDecLSST(ra, dec, pm_ra=None, pm_dec=None, parallax=None, v_rad=None, obs_metadata=None, epoch=2000.0, allow_multiple_chips=False): """ Return the names of detectors on the LSST camera that see the object specified by (RA, Dec) in degrees. @param [in] ra in degrees (a numpy array or a float). In the International Celestial Reference System. @param [in] dec in degrees (a numpy array or a float). In the International Celestial Reference System. @param [in] pm_ra is proper motion in RA multiplied by cos(Dec) (arcsec/yr) Can be a numpy array or a number or None (default=None). @param [in] pm_dec is proper motion in dec (arcsec/yr) Can be a numpy array or a number or None (default=None). @param [in] parallax is parallax in arcsec Can be a numpy array or a number or None (default=None). @param [in] v_rad is radial velocity (km/s) Can be a numpy array or a number or None (default=None). @param [in] obs_metadata is an ObservationMetaData characterizing the telescope pointing @param [in] epoch is the epoch in Julian years of the equinox against which RA and Dec are measured. Default is 2000. @param [in] allow_multiple_chips is a boolean (default False) indicating whether or not this method will allow objects to be visible on more than one chip. If it is 'False' and an object appears on more than one chip, only the first chip will appear in the list of chipNames but NO WARNING WILL BE EMITTED. If it is 'True' and an object falls on more than one chip, a list of chipNames will appear for that object. @param [out] the name(s) of the chips on which ra, dec fall (will be a numpy array if more than one) """ if pm_ra is not None: pm_ra_out = radiansFromArcsec(pm_ra) else: pm_ra_out = None if pm_dec is not None: pm_dec_out = radiansFromArcsec(pm_dec) else: pm_dec_out = None if parallax is not None: parallax_out = radiansFromArcsec(parallax) else: parallax_out = None return _chipNameFromRaDecLSST(np.radians(ra), np.radians(dec), pm_ra=pm_ra_out, pm_dec=pm_dec_out, parallax=parallax_out, v_rad=v_rad, obs_metadata=obs_metadata, epoch=epoch, allow_multiple_chips=allow_multiple_chips)
def focalPlaneCoordsFromRaDec(ra, dec, pm_ra=None, pm_dec=None, parallax=None, v_rad=None, obs_metadata=None, epoch=2000.0, camera=None): """ Get the focal plane coordinates for all objects in the catalog. @param [in] ra is in degrees in the International Celestial Reference System. Can be either a float or a numpy array. @param [in] dec is in degrees in the International Celestial Reference System. Can be either a float or a numpy array. @param [in] pm_ra is proper motion in RA multiplied by cos(Dec) (arcsec/yr) Can be a numpy array or a number or None (default=None). @param [in] pm_dec is proper motion in dec (arcsec/yr) Can be a numpy array or a number or None (default=None). @param [in] parallax is parallax in arcsec Can be a numpy array or a number or None (default=None). @param [in] v_rad is radial velocity (km/s) Can be a numpy array or a number or None (default=None). @param [in] obs_metadata is an ObservationMetaData object describing the telescope pointing (only if specifying RA and Dec rather than pupil coordinates) @param [in] epoch is the julian epoch of the mean equinox used for coordinate transformations (in years; only if specifying RA and Dec rather than pupil coordinates; default is 2000) @param [in] camera is an afw.cameraGeom camera object @param [out] a 2-D numpy array in which the first row is the x focal plane coordinate and the second row is the y focal plane coordinate (both in millimeters) """ if pm_ra is not None: pm_ra_out = radiansFromArcsec(pm_ra) else: pm_ra_out = None if pm_dec is not None: pm_dec_out = radiansFromArcsec(pm_dec) else: pm_dec_out = None if parallax is not None: parallax_out = radiansFromArcsec(parallax) else: parallax_out = None return _focalPlaneCoordsFromRaDec(np.radians(ra), np.radians(dec), pm_ra=pm_ra_out, pm_dec=pm_dec_out, parallax=parallax_out, v_rad=v_rad, obs_metadata=obs_metadata, epoch=epoch, camera=camera)
def observedFromICRS(ra, dec, pm_ra=None, pm_dec=None, parallax=None, v_rad=None, obs_metadata=None, epoch=None, includeRefraction=True): """ Convert mean position (RA, Dec) in the International Celestial Reference Frame to observed (RA, Dec). included are precession-nutation, aberration, proper motion, parallax, refraction, radial velocity, diurnal aberration. This method works in degrees. @param [in] ra is the unrefracted RA in degrees (ICRS). Must be a numpy array. @param [in] dec is the unrefracted Dec in degrees (ICRS). Must be a numpy array. @param [in] pm_ra is proper motion in RA multiplied by cos(Dec) (arcsec/yr) @param [in] pm_dec is proper motion in dec (arcsec/yr) @param [in] parallax is parallax in arcsec @param [in] v_rad is radial velocity (km/s) @param [in] obs_metadata is an ObservationMetaData object describing the telescope pointing. @param [in] epoch is the julian epoch (in years) against which the mean equinoxes are measured. @param [in] includeRefraction toggles whether or not to correct for refraction @param [out] a 2-D numpy array in which the first row is the observed RA and the second row is the observed Dec (both in degrees) """ if pm_ra is not None: pm_ra_in = radiansFromArcsec(pm_ra) else: pm_ra_in = None if pm_dec is not None: pm_dec_in = radiansFromArcsec(pm_dec) else: pm_dec_in = None if parallax is not None: parallax_in = radiansFromArcsec(parallax) else: parallax_in = None output = _observedFromICRS(numpy.radians(ra), numpy.radians(dec), pm_ra=pm_ra_in, pm_dec=pm_dec_in, parallax=parallax_in, v_rad=v_rad, obs_metadata=obs_metadata, epoch=epoch, includeRefraction=includeRefraction) return numpy.degrees(output)
def test_chip_name(self): """ Test that chipNameFromRaDecLSST with non-zero proper motion etc. agrees with chipNameFromPupilCoords 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(11) 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) name_control = chipNameFromPupilCoords(xp, yp, camera=self.camera) name_test = chipNameFromRaDecLSST(ra_list, dec_list, pm_ra=pm_ra, pm_dec=pm_dec, parallax=parallax, v_rad=v_rad, obs_metadata=obs) name_radians = _chipNameFromRaDecLSST( 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(name_control, name_test) np.testing.assert_array_equal(name_control, name_radians) self.assertGreater(len(np.unique(name_control.astype(str))), 4) self.assertLess(len(np.where(np.equal(name_control, None))[0]), len(name_control) / 4)
def setUp(self): self.nStars = 10 np.random.seed(8273) self.raList = np.random.random_sample(self.nStars)*2.0*np.pi self.decList = (np.random.random_sample(self.nStars)-0.5)*np.pi self.mjdList = np.random.random_sample(10)*5000.0 + 52000.0 self.pm_raList = utils.radiansFromArcsec(np.random.random_sample(self.nStars)*10.0 - 5.0) self.pm_decList = utils.radiansFromArcsec(np.random.random_sample(self.nStars)*10.0 - 5.0) self.pxList = utils.radiansFromArcsec(np.random.random_sample(self.nStars)*2.0) self.v_radList = np.random.random_sample(self.nStars)*500.0 - 250.0
def applyProperMotion(ra, dec, pm_ra, pm_dec, parallax, v_rad, epoch=2000.0, mjd=None): """Applies proper motion between two epochs. units: ra (degrees), dec (degrees), pm_ra (arcsec/year), pm_dec (arcsec/year), parallax (arcsec), v_rad (km/sec, positive if receding), epoch (Julian years) Returns corrected ra and dec (in radians) The function palpy.pm does not work properly if the parallax is below 0.00045 arcseconds @param [in] ra in degrees. Can be a number or a numpy array (not a list). @param [in] dec in degrees. Can be a number or a numpy array (not a list). @param [in] pm_ra is ra proper motion multiplied by cos(Dec) in arcsec/year. Can be a number or a numpy array (not a list). @param [in] pm_dec is dec proper motion in arcsec/year. Can be a number or a numpy array (not a list). @param [in] parallax in arcsec. Can be a number or a numpy array (not a list). @param [in] v_rad is radial velocity in km/sec (positive if the object is receding). Can be a number or a numpy array (not a list). @param [in] epoch is epoch in Julian years (default: 2000.0) @param [in] mjd is an instantiation of the ModifiedJulianDate class representing the date of the observation @param [out] a 2-D numpy array in which the first row is the RA corrected for proper motion and the second row is the Dec corrected for proper motion (both in degrees) """ output = _applyProperMotion(np.radians(ra), np.radians(dec), radiansFromArcsec(pm_ra), radiansFromArcsec(pm_dec), radiansFromArcsec(parallax), v_rad, epoch=epoch, mjd=mjd) return np.degrees(output)
def appGeoFromICRS(ra, dec, pm_ra=None, pm_dec=None, parallax=None, v_rad=None, epoch=2000.0, mjd = None): """ Convert the mean position (RA, Dec) in the International Celestial Reference System (ICRS) to the mean apparent geocentric position units: ra (degrees), dec (degrees), pm_ra (arcsec/year), pm_dec (arcsec/year), parallax (arcsec), v_rad (km/sec; positive if receding), epoch (Julian years) @param [in] ra in degrees (ICRS). Must be a numpy array. @param [in] dec in degrees (ICRS). Must be a numpy array. @param [in] pm_ra is ra proper motion multiplied by cos(Dec) in arcsec/year @param [in] pm_dec is dec proper motion in arcsec/year @param [in] parallax in arcsec @param [in] v_rad is radial velocity in km/sec (positive if the object is receding) @param [in] epoch is the julian epoch (in years) of the equinox against which to measure RA (default: 2000.0) @param [in] mjd is an instantiation of the ModifiedJulianDate class representing the date of the observation @param [out] a 2-D numpy array in which the first row is the apparent geocentric RA and the second row is the apparent geocentric Dec (both in degrees) """ if pm_ra is not None: pm_ra_in = radiansFromArcsec(pm_ra) else: pm_ra_in = None if pm_dec is not None: pm_dec_in = radiansFromArcsec(pm_dec) else: pm_dec_in = None if parallax is not None: px_in = radiansFromArcsec(parallax) else: px_in = None output = _appGeoFromICRS(numpy.radians(ra), numpy.radians(dec), pm_ra=pm_ra_in, pm_dec=pm_dec_in, parallax=px_in, v_rad=v_rad, epoch=epoch, mjd=mjd) return numpy.degrees(output)
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 setUp(self): self.nStars = 10 self.rng = np.random.RandomState(8273) self.raList = self.rng.random_sample(self.nStars) * 2.0 * np.pi self.decList = (self.rng.random_sample(self.nStars) - 0.5) * np.pi self.mjdList = self.rng.random_sample(10) * 5000.0 + 52000.0 self.pm_raList = utils.radiansFromArcsec( self.rng.random_sample(self.nStars) * 10.0 - 5.0) self.pm_decList = utils.radiansFromArcsec( self.rng.random_sample(self.nStars) * 10.0 - 5.0) self.pxList = utils.radiansFromArcsec( self.rng.random_sample(self.nStars) * 2.0) self.v_radList = self.rng.random_sample(self.nStars) * 500.0 - 250.0
def create_text_catalog(obs, file_name, raDisplacement, decDisplacement, \ hlr=None, mag_norm=None, pa=None): """ Create a text file containing objects that can be read in by a fileDBObject class. @param [in] obs is an ObservationMetaData specifying the pointing on which the catalog will be centered @param [in] file_name is the name of the file to be created. If a file already exists with that name, throw an error. @param [in] raDisplacement is a numpy array listing the RA displacements of objects from the pointing's center in arcseconds @param [in] decDisplacement is a numpy array listing the Dec displacements of objects from the pointings' center in arcseconds @param [in] hlr is an optional list of half light radii in arcseconds @param [in] mag_norm is an optional list of the objects' magnitude normalizations @param [in] pa is an optional list of the objects' position angles in degrees """ if os.path.exists(file_name): os.unlink(file_name) raDisplacementList = radiansFromArcsec(raDisplacement) decDisplacementList = radiansFromArcsec(decDisplacement) if hlr is None: hlr = [2.0] * len(raDisplacement) if mag_norm is None: mag_norm = [20.0] * len(raDisplacement) if pa is None: pa = [0.0] * len(raDisplacement) with open(file_name, 'w') as outFile: outFile.write('# test_id ra dec hlr mag_norm pa\n') for ix, (dx, dy, halfLight, magNorm, pp) in \ enumerate(zip(raDisplacementList, decDisplacementList, hlr, mag_norm, pa)): rr = numpy.degrees(obs._pointingRA + dx) dd = numpy.degrees(obs._pointingDec + dy) outFile.write('%d %.9f %.9f %.9f %.9f %.9f\n' % (ix, rr, dd, halfLight, magNorm, pp))
def create_text_catalog(obs, file_name, raDisplacement, decDisplacement, \ hlr=None, mag_norm=None, pa=None): """ Create a text file containing objects that can be read in by a fileDBObject class. @param [in] obs is an ObservationMetaData specifying the pointing on which the catalog will be centered @param [in] file_name is the name of the file to be created. If a file already exists with that name, throw an error. @param [in] raDisplacement is a numpy array listing the RA displacements of objects from the pointing's center in arcseconds @param [in] decDisplacement is a numpy array listing the Dec displacements of objects from the pointings' center in arcseconds @param [in] hlr is an optional list of half light radii in arcseconds @param [in] mag_norm is an optional list of the objects' magnitude normalizations @param [in] pa is an optional list of the objects' position angles in degrees """ if os.path.exists(file_name): os.unlink(file_name) raDisplacementList = radiansFromArcsec(raDisplacement) decDisplacementList = radiansFromArcsec(decDisplacement) if hlr is None: hlr = [2.0]*len(raDisplacement) if mag_norm is None: mag_norm = [21.0]*len(raDisplacement) if pa is None: pa = [0.0]*len(raDisplacement) with open(file_name,'w') as outFile: outFile.write('# test_id ra dec hlr mag_norm pa\n') for ix, (dx, dy, halfLight, magNorm, pp) in \ enumerate(zip(raDisplacementList, decDisplacementList, hlr, mag_norm, pa)): rr = numpy.degrees(obs._unrefractedRA+dx) dd = numpy.degrees(obs._unrefractedDec+dy) outFile.write('%d %.9f %.9f %.9f %.9f %.9f\n' % (ix, rr, dd, halfLight, magNorm, pp))
class hlrCat(GalSimGalaxies): camera = ReturnCamera( os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'cameraData')) bandpassNames = ['u'] default_columns = [('sedFilename', 'sed_flat.txt', (str, 12)), ('magNorm', 21.0, float), ('galacticAv', 0.1, float), ('galacticRv', 3.1, float), ('galSimType', 'sersic', (str, 11)), ('internalAv', 0.1, float), ('internalRv', 3.1, float), ('redshift', 0.0, float), ('majorAxis', radiansFromArcsec(1.0), float), ('minorAxis', radiansFromArcsec(1.0), float), ('sindex', 4.0, float)]
def test_chip_name(self): """ Test that chipNameFromRaDecLSST with non-zero proper motion etc. agrees with chipNameFromPupilCoords 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(11) 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) name_control = chipNameFromPupilCoords(xp, yp, camera=self.camera) name_test = chipNameFromRaDecLSST(ra_list, dec_list, pm_ra=pm_ra, pm_dec=pm_dec, parallax=parallax, v_rad=v_rad, obs_metadata=obs) name_radians = _chipNameFromRaDecLSST(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(name_control, name_test) np.testing.assert_array_equal(name_control, name_radians) self.assertGreater(len(np.unique(name_control.astype(str))), 4) self.assertLess(len(np.where(np.equal(name_control, None))[0]), len(name_control)/4)
def _doesObjectImpingeOnDetector(self, xPupil=None, yPupil=None, detector=None, imgScale=None, nonZeroPixels=None): """ Compare an astronomical object to a detector and determine whether or not that object will cast any light on that detector (in case the object is near the edge of a detector and will cast some incidental light onto it). This method is called by the method findAllDetectors. findAllDetectors will generate a test image of an astronomical object. It will find all of the pixels in that test image with flux above a certain threshold and pass that list of pixels into this method along with data characterizing the detector in question. This method compares the pupil coordinates of those pixels with the pupil coordinate domain of the detector. If some of those pixels fall inside the detector, then this method returns True (signifying that the astronomical object does cast light on the detector). If not, this method returns False. @param [in] xPupil the x pupil coordinate of the image's origin in arcseconds @param [in] yPupil the y pupil coordinate of the image's origin in arcseconds @param [in] detector an instantiation of GalSimDetector. This is the detector against which we will compare the object. @param [in] nonZeroPixels is a numpy array of non-zero pixels from the test image referenced above. nonZeroPixels[0] is their x coordinate (in pixel value). nonZeroPixels[1] is ther y coordinate. @param [in] imgScale is the platescale of the test image in arcseconds per pixel """ if detector is None: return False xPupilList = radiansFromArcsec( np.array([xPupil + ix * imgScale for ix in nonZeroPixels[0]])) yPupilList = radiansFromArcsec( np.array([yPupil + iy * imgScale for iy in nonZeroPixels[1]])) answer = detector.containsPupilCoordinates(xPupilList, yPupilList) if True in answer: return True else: return False
def applyProperMotion(ra, dec, pm_ra, pm_dec, parallax, v_rad, \ epoch=2000.0, mjd=None): """Applies proper motion between two epochs. units: ra (degrees), dec (degrees), pm_ra (arcsec/year), pm_dec (arcsec/year), parallax (arcsec), v_rad (km/sec, positive if receding), epoch (Julian years) Returns corrected ra and dec (in radians) The function palpy.pm does not work properly if the parallax is below 0.00045 arcseconds @param [in] ra in degrees. Can be a float or a numpy array (not a list). @param [in] dec in degrees. Can be a float or a numpy array (not a list). @param [in] pm_ra is ra proper motion multiplied by cos(Dec) in arcsec/year. Can be a float or a numpy array (not a list). @param [in] pm_dec is dec proper motion in arcsec/year. Can be a float or a numpy array (not a list). @param [in] parallax in arcsec. Can be a float or a numpy array (not a list). @param [in] v_rad is radial velocity in km/sec (positive if the object is receding). Can be a float or a numpy array (not a list). @param [in] epoch is epoch in Julian years (default: 2000.0) @param [in] mjd is an instantiation of the ModifiedJulianDate class representing the date of the observation @param [out] a 2-D numpy array in which the first row is the RA corrected for proper motion and the second row is the Dec corrected for proper motion (both in degrees) """ output = _applyProperMotion(numpy.radians(ra), numpy.radians(dec), radiansFromArcsec(pm_ra), radiansFromArcsec(pm_dec), radiansFromArcsec(parallax), v_rad, epoch=epoch, mjd=mjd) return numpy.degrees(output)
class hlrCat(GalSimGalaxies): bandpassNames = ['u'] default_columns = [ ('sedFilename', 'sed_flat.txt', (str, 12)), ('magNorm', 21.0, float), ('galacticAv', 0.1, float), ('galacticRv', 3.1, float), ('galSimType', 'sersic', (str, 11)), ('internalAv', 0.1, float), ('internalRv', 3.1, float), ('redshift', 0.0, float), ('majorAxis', radiansFromArcsec(1.0), float), ('minorAxis', radiansFromArcsec(1.0), float), ('sindex', 4.0, float), ('shear1', 0.0, float), ('shear2', 0.0, float), ('kappa', 0.0, float), ]
class hlrCatRandomWalk(GalSimRandomWalk): bandpassNames = ['u'] default_columns = [ ('sedFilename', 'sed_flat.txt', (str, 12)), ('magNorm', 21.0, float), ('galacticAv', 0.1, float), ('galacticRv', 3.1, float), ('galSimType', 'RandomWalk', (str, 10)), ('internalAv', 0.1, float), ('internalRv', 3.1, float), ('redshift', 0.0, float), ('majorAxis', radiansFromArcsec(1.0), float), ('minorAxis', radiansFromArcsec(1.0), float), ('npoints', 10000, int), ('sindex', 0.0, float), ('gamma1', 0.0, float), ('gamma2', 0.0, float), ('kappa', 0.0, float), ]
def _doesObjectImpingeOnDetector(self, xPupil=None, yPupil=None, detector=None, imgScale=None, nonZeroPixels=None): """ Compare an astronomical object to a detector and determine whether or not that object will cast any light on that detector (in case the object is near the edge of a detector and will cast some incidental light onto it). This method is called by the method findAllDetectors. findAllDetectors will generate a test image of an astronomical object. It will find all of the pixels in that test image with flux above a certain threshold and pass that list of pixels into this method along with data characterizing the detector in question. This method compares the pupil coordinates of those pixels with the pupil coordinate domain of the detector. If some of those pixels fall inside the detector, then this method returns True (signifying that the astronomical object does cast light on the detector). If not, this method returns False. @param [in] xPupil the x pupil coordinate of the image's origin in arcseconds @param [in] yPupil the y pupil coordinate of the image's origin in arcseconds @param [in] detector an instantiation of GalSimDetector. This is the detector against which we will compare the object. @param [in] nonZeroPixels is a numpy array of non-zero pixels from the test image referenced above. nonZeroPixels[0] is their x coordinate (in pixel value). nonZeroPixels[1] is ther y coordinate. @param [in] imgScale is the platescale of the test image in arcseconds per pixel """ if detector is None: return False xPupilList = radiansFromArcsec(numpy.array([xPupil + ix*imgScale for ix in nonZeroPixels[0]])) yPupilList = radiansFromArcsec(numpy.array([yPupil + iy*imgScale for iy in nonZeroPixels[1]])) answer = detector.containsPupilCoordinates(xPupilList, yPupilList) if True in answer: return True else: return False
def xyz_from_lon_lat_px(lon, lat, px): """ Parameters ---------- lon is galactic longitude in degrees lat is galactic latitude in degrees px in parallax in arcseconds Returns ------- A numpy array containing the vector from Sgr A* to the input star. Distances in parsecs. """ _d_center = 8.33e3 # distance from the Sun to Sgr A* from # Gillessen et al 2009 (ApJ 692, 1075) eqn 11 _lon_center = 359.9442 _lat_center = -0.0462 # galactic latitude and longitude of Sgr A* from # http://simbad.u-strasbg.fr/simbad/sim-basic?Ident=Sagittarius+A&submit=SIMBAD+search _au_to_parsec = 1.0 / 206265.0 if not hasattr(xyz_from_lon_lat_px, '_xyz_center'): lon_rad = np.radians(_lon_center) lat_rad = np.radians(_lat_center) xx = np.cos(lon_rad) * np.cos(lat_rad) yy = np.sin(lon_rad) * np.cos(lat_rad) zz = np.sin(lat_rad) xyz_from_lon_lat_px._xyz_center = np.array( [_d_center * xx, _d_center * yy, _d_center * zz]) lon_rad = np.radians(lon) lat_rad = np.radians(lat) dd = _au_to_parsec / radiansFromArcsec(px) xx = dd * np.cos(lon_rad) * np.cos(lat_rad) yy = dd * np.sin(lon_rad) * np.cos(lat_rad) zz = dd * np.sin(lat_rad) return np.array([ xx - xyz_from_lon_lat_px._xyz_center[0], yy - xyz_from_lon_lat_px._xyz_center[1], zz - xyz_from_lon_lat_px._xyz_center[2] ])
def testUnitConversion(self): """ Test that arcsecFromRadians, arcsecFromDegrees, radiansFromArcsec, and degreesFromArcsec are all self-consistent """ radList = self.rng.random_sample(100) * 2.0 * np.pi degList = np.degrees(radList) arcsecRadList = utils.arcsecFromRadians(radList) arcsecDegList = utils.arcsecFromDegrees(degList) np.testing.assert_array_equal(arcsecRadList, arcsecDegList) arcsecList = self.rng.random_sample(100) * 1.0 radList = utils.radiansFromArcsec(arcsecList) degList = utils.degreesFromArcsec(arcsecList) np.testing.assert_array_equal(np.radians(degList), radList)
def testUnitConversion(self): """ Test that arcsecFromRadians, arcsecFromDegrees, radiansFromArcsec, and degreesFromArcsec are all self-consistent """ radList = np.random.random_sample(100)*2.0*np.pi degList = np.degrees(radList) arcsecRadList = utils.arcsecFromRadians(radList) arcsecDegList = utils.arcsecFromDegrees(degList) np.testing.assert_array_equal(arcsecRadList, arcsecDegList) arcsecList = np.random.random_sample(100)*1.0 radList = utils.radiansFromArcsec(arcsecList) degList = utils.degreesFromArcsec(arcsecList) np.testing.assert_array_equal(np.radians(degList), radList)
def setUpClass(cls): cls.dataDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'scratchSpace') cls.n_objects = 5 rng = np.random.RandomState(45) pointingRA = 45.2 pointingDec = -31.6 cls.obs = ObservationMetaData(pointingRA=pointingRA, pointingDec=pointingDec, rotSkyPos=1.2, bandpassName='r', mjd=57341.5, boundLength=0.1, boundType='circle') cls.dtype = np.dtype([('id', int), ('raJ2000', np.float), ('decJ2000', np.float), ('ra_deg', np.float), ('dec_deg', np.float), ('sedFilename', (str, 300)), ('magNorm', np.float), ('redshift', np.float), ('majorAxis', np.float), ('minorAxis', np.float), ('positionAngle', np.float), ('halfLightRadius', np.float), ('sindex', np.float), ('internalAv', np.float), ('internalRv', np.float), ('galacticAv', np.float), ('galacticRv', np.float), ('properMotionRa', np.float), ('properMotionDec', np.float), ('radialVelocity', np.float), ('parallax', np.float)]) # generate some galaxy bulge data redshift = rng.random_sample(cls.n_objects)*1.5 rr = rng.random_sample(cls.n_objects)*0.05 theta = rng.random_sample(cls.n_objects)*2.0*np.pi ra = np.radians(pointingRA + rr*np.cos(theta)) dec = np.radians(pointingDec + rr*np.sin(theta)) magNorm = rng.random_sample(cls.n_objects)*7.0 + 18.0 sindex = rng.random_sample(cls.n_objects)*4.0+1.0 hlr = radiansFromArcsec(rng.random_sample(cls.n_objects)*10.0 + 1.0) positionAngle = rng.random_sample(cls.n_objects)*np.pi internalAv = rng.random_sample(cls.n_objects)*0.5+0.1 internalRv = rng.random_sample(cls.n_objects)*0.5+2.7 majorAxis = radiansFromArcsec(rng.random_sample(cls.n_objects)*2.0 + 0.5) minorAxis = radiansFromArcsec(rng.random_sample(cls.n_objects)*2.0 + 0.5) galacticAv = rng.random_sample(cls.n_objects)*0.5+0.1 galacticRv = rng.random_sample(cls.n_objects)*0.5+2.7 properMotionRa = np.zeros(cls.n_objects) properMotionDec = np.zeros(cls.n_objects) radialVelocity = np.zeros(cls.n_objects) parallax = np.zeros(cls.n_objects) cls.bulge_name = os.path.join(cls.dataDir, 'galSimPhoSim_test_bulge.dat') with open(cls.bulge_name, 'w') as output_file: output_file.write('# header\n') for ix in range(cls.n_objects): output_file.write('%d %f %f %f %f Const.79E06.002Z.spec %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n' % (ix, ra[ix], dec[ix], np.degrees(ra[ix]), np.degrees(dec[ix]), magNorm[ix], redshift[ix], max(majorAxis[ix], minorAxis[ix]), min(majorAxis[ix], minorAxis[ix]), positionAngle[ix], hlr[ix], sindex[ix], internalAv[ix], internalRv[ix], galacticAv[ix], galacticRv[ix], properMotionRa[ix], properMotionDec[ix], radialVelocity[ix], parallax[ix])) # generate some galaxy disk data redshift = rng.random_sample(cls.n_objects)*1.5 rr = rng.random_sample(cls.n_objects)*0.05 theta = rng.random_sample(cls.n_objects)*2.0*np.pi ra = np.radians(pointingRA + rr*np.cos(theta)) dec = np.radians(pointingDec + rr*np.sin(theta)) magNorm = rng.random_sample(cls.n_objects)*7.0 + 18.0 sindex = rng.random_sample(cls.n_objects)*4.0+1.0 hlr = radiansFromArcsec(rng.random_sample(cls.n_objects)*10.0 + 1.0) positionAngle = rng.random_sample(cls.n_objects)*np.pi internalAv = rng.random_sample(cls.n_objects)*0.5+0.1 internalRv = rng.random_sample(cls.n_objects)*0.5+2.7 majorAxis = radiansFromArcsec(rng.random_sample(cls.n_objects)*2.0 + 0.5) minorAxis = radiansFromArcsec(rng.random_sample(cls.n_objects)*2.0 + 0.5) galacticAv = rng.random_sample(cls.n_objects)*0.5+0.1 galacticRv = rng.random_sample(cls.n_objects)*0.5+2.7 properMotionRa = np.zeros(cls.n_objects) properMotionDec = np.zeros(cls.n_objects) radialVelocity = np.zeros(cls.n_objects) parallax = np.zeros(cls.n_objects) cls.disk_name = os.path.join(cls.dataDir, 'galSimPhoSim_test_disk.dat') with open(cls.disk_name, 'w') as output_file: output_file.write('# header\n') for ix in range(cls.n_objects): output_file.write('%d %f %f %f %f Inst.79E06.02Z.spec %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n' % (ix, ra[ix], dec[ix], np.degrees(ra[ix]), np.degrees(dec[ix]), magNorm[ix], redshift[ix], max(majorAxis[ix], minorAxis[ix]), min(majorAxis[ix], minorAxis[ix]), positionAngle[ix], hlr[ix], sindex[ix], internalAv[ix], internalRv[ix], galacticAv[ix], galacticRv[ix], properMotionRa[ix], properMotionDec[ix], radialVelocity[ix], parallax[ix])) # generate some agn data redshift = rng.random_sample(cls.n_objects)*1.5 rr = rng.random_sample(cls.n_objects)*0.05 theta = rng.random_sample(cls.n_objects)*2.0*np.pi ra = np.radians(pointingRA + rr*np.cos(theta)) dec = np.radians(pointingDec + rr*np.sin(theta)) magNorm = rng.random_sample(cls.n_objects)*7.0 + 18.0 sindex = np.zeros(cls.n_objects) hlr = np.zeros(cls.n_objects) positionAngle = np.zeros(cls.n_objects) internalAv = np.zeros(cls.n_objects) internalRv = np.zeros(cls.n_objects) majorAxis = np.zeros(cls.n_objects) minorAxis = np.zeros(cls.n_objects) galacticAv = rng.random_sample(cls.n_objects)*0.5+0.1 galacticRv = rng.random_sample(cls.n_objects)*0.5+2.7 properMotionRa = np.zeros(cls.n_objects) properMotionDec = np.zeros(cls.n_objects) radialVelocity = np.zeros(cls.n_objects) parallax = np.zeros(cls.n_objects) cls.agn_name = os.path.join(cls.dataDir, 'galSimPhoSim_test_agn.dat') with open(cls.agn_name, 'w') as output_file: output_file.write('# header\n') for ix in range(cls.n_objects): output_file.write('%d %f %f %f %f agn.spec %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n' % (ix, ra[ix], dec[ix], np.degrees(ra[ix]), np.degrees(dec[ix]), magNorm[ix], redshift[ix], max(majorAxis[ix], minorAxis[ix]), min(majorAxis[ix], minorAxis[ix]), positionAngle[ix], hlr[ix], sindex[ix], internalAv[ix], internalRv[ix], galacticAv[ix], galacticRv[ix], properMotionRa[ix], properMotionDec[ix], radialVelocity[ix], parallax[ix])) # generate some star data redshift = rng.random_sample(cls.n_objects)*1.5 rr = rng.random_sample(cls.n_objects)*0.05 theta = rng.random_sample(cls.n_objects)*2.0*np.pi ra = np.radians(pointingRA + rr*np.cos(theta)) dec = np.radians(pointingDec + rr*np.sin(theta)) magNorm = rng.random_sample(cls.n_objects)*7.0 + 18.0 sindex = np.zeros(cls.n_objects) hlr = np.zeros(cls.n_objects) positionAngle = np.zeros(cls.n_objects) internalAv = np.zeros(cls.n_objects) internalRv = np.zeros(cls.n_objects) majorAxis = np.zeros(cls.n_objects) minorAxis = np.zeros(cls.n_objects) galacticAv = rng.random_sample(cls.n_objects)*0.5+0.1 galacticRv = rng.random_sample(cls.n_objects)*0.5+2.7 properMotionRa = radiansFromArcsec(rng.random_sample(cls.n_objects)*0.0002) properMotionDec = radiansFromArcsec(rng.random_sample(cls.n_objects)*0.0002) radialVelocity = rng.random_sample(cls.n_objects)*200.0 parallax = radiansFromArcsec(rng.random_sample(cls.n_objects)*0.0002) cls.star_name = os.path.join(cls.dataDir, 'galSimPhoSim_test_star.dat') with open(cls.star_name, 'w') as output_file: output_file.write('# header\n') for ix in range(cls.n_objects): output_file.write('%d %f %f %f %f km30_5000.fits_g10_5040 %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n' % (ix, ra[ix], dec[ix], np.degrees(ra[ix]), np.degrees(dec[ix]), magNorm[ix], redshift[ix], max(majorAxis[ix], minorAxis[ix]), min(majorAxis[ix], minorAxis[ix]), positionAngle[ix], hlr[ix], sindex[ix], internalAv[ix], internalRv[ix], galacticAv[ix], galacticRv[ix], properMotionRa[ix], properMotionDec[ix], radialVelocity[ix], parallax[ix]))
def test_with_proper_motion(self): """ Test that calculating pupil coordinates in the presence of proper motion, parallax, and radial velocity is equivalent to observedFromICRS -> icrsFromObserved -> pupilCoordsFromRaDec (mostly to make surethat pupilCoordsFromRaDec is correctly calling observedFromICRS with non-zero proper motion, etc.) """ rng = np.random.RandomState(38442) is_valid = False while not is_valid: mjd_tai = 59580.0 + 10000.0*rng.random_sample() obs = ObservationMetaData(mjd=mjd_tai) ra, dec = raDecFromAltAz(78.0, 112.0, obs) dd = distanceToSun(ra, dec, obs.mjd) if dd > 45.0: is_valid = True n_obj = 1000 rr = rng.random_sample(n_obj)*2.0 theta = rng.random_sample(n_obj)*2.0*np.pi ra_list = ra + rr*np.cos(theta) dec_list = dec + rr*np.sin(theta) obs = ObservationMetaData(pointingRA=ra, pointingDec=dec, mjd=mjd_tai, rotSkyPos=19.0) pm_ra_list = rng.random_sample(n_obj)*100.0 - 50.0 pm_dec_list = rng.random_sample(n_obj)*100.0 - 50.0 px_list = rng.random_sample(n_obj) + 0.05 v_rad_list = rng.random_sample(n_obj)*600.0 - 300.0 for includeRefraction in (True, False): ra_obs, dec_obs = observedFromICRS(ra_list, dec_list, pm_ra=pm_ra_list, pm_dec=pm_dec_list, parallax=px_list, v_rad=v_rad_list, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) ra_icrs, dec_icrs = icrsFromObserved(ra_obs, dec_obs, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) xp_control, yp_control = pupilCoordsFromRaDec(ra_icrs, dec_icrs, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) xp_test, yp_test = pupilCoordsFromRaDec(ra_list, dec_list, pm_ra=pm_ra_list, pm_dec=pm_dec_list, parallax=px_list, v_rad=v_rad_list, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) distance = arcsecFromRadians(np.sqrt(np.power(xp_test-xp_control, 2) + np.power(yp_test-yp_control, 2))) self.assertLess(distance.max(), 0.006) # now test it in radians xp_rad, yp_rad = _pupilCoordsFromRaDec(np.radians(ra_list), np.radians(dec_list), pm_ra=radiansFromArcsec(pm_ra_list), pm_dec=radiansFromArcsec(pm_dec_list), parallax=radiansFromArcsec(px_list), v_rad=v_rad_list, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) np.testing.assert_array_equal(xp_rad, xp_test) np.testing.assert_array_equal(yp_rad, yp_test) # now test it with proper motion = 0 ra_obs, dec_obs = observedFromICRS(ra_list, dec_list, parallax=px_list, v_rad=v_rad_list, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) ra_icrs, dec_icrs = icrsFromObserved(ra_obs, dec_obs, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) xp_control, yp_control = pupilCoordsFromRaDec(ra_icrs, dec_icrs, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) xp_test, yp_test = pupilCoordsFromRaDec(ra_list, dec_list, parallax=px_list, v_rad=v_rad_list, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) distance = arcsecFromRadians(np.sqrt(np.power(xp_test-xp_control, 2) + np.power(yp_test-yp_control, 2))) self.assertLess(distance.max(), 1.0e-6)
def pupilCoordsFromRaDec(ra_in, dec_in, pm_ra=None, pm_dec=None, parallax=None, v_rad=None, includeRefraction=True, obs_metadata=None, epoch=2000.0): """ Take an input RA and dec from the sky and convert it to coordinates on the focal plane. This uses PAL's gnomonic projection routine which assumes that the focal plane is perfectly flat. The output is in Cartesian coordinates, assuming that the Celestial Sphere is a unit sphere. The RA, Dec accepted by this method are in the International Celestial Reference System. Before applying the gnomonic projection, this method transforms those RA, Dec into observed geocentric coordinates, applying the effects of precession, nutation, aberration, parallax and refraction. This is done, because the gnomonic projection ought to be applied to what observers actually see, rather than the idealized, above-the-atmosphere coordinates represented by the ICRS. @param [in] ra_in is in degrees (ICRS). Can be either a numpy array or a number. @param [in] dec_in is in degrees (ICRS). Can be either a numpy array or a number. @param [in] pm_ra is proper motion in RA multiplied by cos(Dec) (arcsec/yr) Can be a numpy array or a number or None (default=None). @param [in] pm_dec is proper motion in dec (arcsec/yr) Can be a numpy array or a number or None (default=None). @param [in] parallax is parallax in arcsec Can be a numpy array or a number or None (default=None). @param [in] v_rad is radial velocity (km/s) Can be a numpy array or a number or None (default=None). @param [in] includeRefraction is a boolean controlling the application of refraction. @param [in] obs_metadata is an ObservationMetaData instantiation characterizing the telescope location and pointing. @param [in] epoch is the epoch of mean ra and dec in julian years (default=2000.0) @param [out] returns a numpy array whose first row is the x coordinate on the pupil in radians and whose second row is the y coordinate in radians """ if pm_ra is not None: pm_ra_in = radiansFromArcsec(pm_ra) else: pm_ra_in = None if pm_dec is not None: pm_dec_in = radiansFromArcsec(pm_dec) else: pm_dec_in = None if parallax is not None: parallax_in = radiansFromArcsec(parallax) else: parallax_in = None return _pupilCoordsFromRaDec(np.radians(ra_in), np.radians(dec_in), pm_ra=pm_ra_in, pm_dec=pm_dec_in, parallax=parallax_in, v_rad=v_rad, includeRefraction=includeRefraction, obs_metadata=obs_metadata, epoch=epoch)
def test_applyProperMotion(self): """ Compare the output of _applyProperMotion to control outputs generated by recreating the 'space motion' section of code from palMapqk.c in palpy/cextern/pal """ VF=0.21094502 pal_das2r=4.8481368110953599358991410235794797595635330237270e-6; numpy.random.seed(18) nSamples = 1000 mjdList = numpy.random.random_sample(20)*20000.0 + 45000.0 for mjd in mjdList: raList_icrs = numpy.random.random_sample(nSamples)*2.0*numpy.pi decList_icrs = (numpy.random.random_sample(nSamples)-0.5)*numpy.pi # stars' original position in Cartesian space x_list_icrs = numpy.cos(decList_icrs)*numpy.cos(raList_icrs) y_list_icrs = numpy.cos(decList_icrs)*numpy.sin(raList_icrs) z_list_icrs = numpy.sin(decList_icrs) pm_ra = (numpy.random.random_sample(nSamples)-0.5)*radiansFromArcsec(1.0) pm_dec = (numpy.random.random_sample(nSamples)-0.5)*radiansFromArcsec(1.0) px = numpy.random.random_sample(nSamples)*radiansFromArcsec(1.0) v_rad = numpy.random.random_sample(nSamples)*200.0 ra_list_pm, dec_list_pm = _applyProperMotion(raList_icrs, decList_icrs, pm_ra*numpy.cos(decList_icrs), pm_dec, px, v_rad, mjd=ModifiedJulianDate(TAI=mjd)) # stars' Cartesian position after proper motion is applied x_list_pm = numpy.cos(dec_list_pm)*numpy.cos(ra_list_pm) y_list_pm = numpy.cos(dec_list_pm)*numpy.sin(ra_list_pm) z_list_pm = numpy.sin(dec_list_pm) ############################################################### # The code below is copied from palMapqk.c in palpy/cextern/pal params = pal.mappa(2000.0, mjd) pmt = params[0] eb = numpy.array([params[1], params[2], params[3]]) pxr = px*pal_das2r w = VF*v_rad*pxr motion_per_year = numpy.array([-1.0*pm_ra*y_list_icrs - pm_dec*numpy.cos(raList_icrs)*numpy.sin(decList_icrs) + w*x_list_icrs, pm_ra*x_list_icrs - pm_dec*numpy.sin(raList_icrs)*numpy.sin(decList_icrs) + w*y_list_icrs, pm_dec*numpy.cos(decList_icrs) + w*z_list_icrs]) xyz_control = numpy.array([ x_list_icrs + pmt*motion_per_year[0] - pxr*eb[0], y_list_icrs + pmt*motion_per_year[1] - pxr*eb[1], z_list_icrs + pmt*motion_per_year[2] - pxr*eb[2] ]) xyz_norm = numpy.sqrt(numpy.power(xyz_control[0],2) + numpy.power(xyz_control[1],2) + numpy.power(xyz_control[2],2)) # stars' Cartesian position after applying the control proper motion method xyz_control[0] = xyz_control[0]/xyz_norm xyz_control[1] = xyz_control[1]/xyz_norm xyz_control[2] = xyz_control[2]/xyz_norm # this is the Cartesian distance between the stars' positions as found by _applyProperMotion # and the distance as found by the control proper motion code above distance = numpy.sqrt(numpy.power(x_list_pm-xyz_control[0],2) + numpy.power(y_list_pm-xyz_control[1],2) + numpy.power(z_list_pm-xyz_control[2],2)) # this is the Cartesian distance between the stars' original positions on the celestial sphere # and their positions after the control proper motion was applied correction = numpy.sqrt(numpy.power(xyz_control[0]-x_list_icrs,2) + numpy.power(xyz_control[1]-y_list_icrs,2) + numpy.power(xyz_control[2]-z_list_icrs,2)) dex = numpy.argmax(distance) msg = 'pm %e %e vr %e px %e; time %e; err %e arcsec; corr %e' % \ (arcsecFromRadians(pm_ra[dex]), arcsecFromRadians(pm_dec[dex]), v_rad[dex], arcsecFromRadians(px[dex]), pmt, arcsecFromRadians(distance[dex]), arcsecFromRadians(correction[dex])) self.assertLess((distance/correction).max(), 0.01, msg=msg)
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 extract_objects(df, header): """ Extract the object information needed by the sims code and pack into a new dataframe. Parameters ---------- df : pandas.DataFrame DataFrame containing the instance catalog object data. header : dictionary dictionary containing the PhoSim header cards as output by extract_commands() (necessary for correctly applying proper motion to stars) Returns ------- pandas.DataFrame A DataFrame with the columns expected by the sims code. """ # Check for unhandled source types and emit warning if any are present. valid_types = dict(point='pointSource', sersic2d='sersic') invalid_types = set(df['SOURCE_TYPE']) - set(valid_types) if invalid_types: warnings.warn("Instance catalog contains unhandled source types:\n%s\nSkipping these." % '\n'.join(invalid_types)) columns = ('uniqueId', 'galSimType', 'magNorm', 'sedFilepath', 'redshift', 'raJ2000', 'decJ2000', 'halfLightRadius', 'minorAxis', 'majorAxis', 'positionAngle', 'sindex', 'properMotionRa', 'properMotionDec', 'parallax', 'radialVelocity') # Process point sources and galaxies separately. source_type = 'point' stars = df.query("SOURCE_TYPE=='%s'" % source_type) phosim_stars = pd.DataFrame(np.zeros((len(stars), len(columns))), index=stars.index, columns=columns) phosim_stars['uniqueId'] = pd.to_numeric(stars['VALUE']).tolist() phosim_stars['galSimType'] = valid_types[source_type] phosim_stars['magNorm'] = pd.to_numeric(stars['MAG_NORM']).tolist() phosim_stars['sedFilepath'] = stars['SED_NAME'].tolist() phosim_stars['redshift'] = pd.to_numeric(stars['REDSHIFT']).tolist() phosim_stars['raJ2000'] = pd.to_numeric(stars['RA']).tolist() phosim_stars['decJ2000'] = pd.to_numeric(stars['DEC']).tolist() phosim_stars['properMotionRa'] = pd.to_numeric(stars['PAR5']).tolist() phosim_stars['properMotionDec'] = pd.to_numeric(stars['PAR6']).tolist() phosim_stars['parallax'] = pd.to_numeric(stars['PAR7']).tolist() phosim_stars['radialVelocity'] = pd.to_numeric(stars['PAR8']).tolist() if len(phosim_stars) > 0: phosim_stars = extract_extinction(stars, phosim_stars, 1) mjd = ModifiedJulianDate(TAI=header['mjd']) raICRS, decICRS = applyProperMotion(phosim_stars.raJ2000.values, phosim_stars.decJ2000.values, phosim_stars.properMotionRa.values, phosim_stars.properMotionDec.values, phosim_stars.parallax.values, phosim_stars.radialVelocity.values, mjd=mjd) phosim_stars = phosim_stars.assign(raICRS=raICRS, decICRS=decICRS) source_type = 'sersic2d' galaxies = df.query("SOURCE_TYPE == '%s'" % source_type) phosim_galaxies = pd.DataFrame(np.zeros((len(galaxies), len(columns))), index=galaxies.index, columns=columns) phosim_galaxies['uniqueId'] = pd.to_numeric(galaxies['VALUE']).tolist() phosim_galaxies['galSimType'] = valid_types[source_type] phosim_galaxies['magNorm'] = pd.to_numeric(galaxies['MAG_NORM']).tolist() phosim_galaxies['sedFilepath'] = galaxies['SED_NAME'].tolist() phosim_galaxies['redshift'] = pd.to_numeric(galaxies['REDSHIFT']).tolist() phosim_galaxies['raJ2000'] = pd.to_numeric(galaxies['RA']).tolist() phosim_galaxies['decJ2000'] = pd.to_numeric(galaxies['DEC']).tolist() phosim_galaxies['majorAxis'] = \ radiansFromArcsec(pd.to_numeric(galaxies['PAR1'])).tolist() phosim_galaxies['minorAxis'] = \ radiansFromArcsec(pd.to_numeric(galaxies['PAR2'])).tolist() phosim_galaxies['halfLightRadius'] = phosim_galaxies['majorAxis'] phosim_galaxies['positionAngle'] = \ (np.pi/180.*pd.to_numeric(galaxies['PAR3'])).tolist() phosim_galaxies['sindex'] = pd.to_numeric(galaxies['PAR4']).tolist() n_gal = len(phosim_galaxies.raJ2000.values) phosim_galaxies = phosim_galaxies.assign(raICRS=phosim_galaxies.raJ2000, decICRS=phosim_galaxies.decJ2000, properMotionRa=np.zeros(n_gal), properMotionDec=np.zeros(n_gal), parallax=np.zeros(n_gal), radialVelocity=np.zeros(n_gal)) if len(phosim_galaxies) > 0: phosim_galaxies = extract_extinction(galaxies, phosim_galaxies, 5) return pd.concat((phosim_stars, phosim_galaxies), ignore_index=True)
def pixelCoordsFromRaDec(ra, dec, pm_ra=None, pm_dec=None, parallax=None, v_rad=None, obs_metadata=None, chipName=None, camera=None, epoch=2000.0, includeDistortion=True): """ Get the pixel positions (or nan if not on a chip) for objects based on their RA, and Dec (in degrees) @param [in] ra is in degrees in the International Celestial Reference System. Can be either a float or a numpy array. @param [in] dec is in degrees in the International Celestial Reference System. Can be either a float or a numpy array. @param [in] pm_ra is proper motion in RA multiplied by cos(Dec) (arcsec/yr) Can be a numpy array or a number or None (default=None). @param [in] pm_dec is proper motion in dec (arcsec/yr) Can be a numpy array or a number or None (default=None). @param [in] parallax is parallax in arcsec Can be a numpy array or a number or None (default=None). @param [in] v_rad is radial velocity (km/s) Can be a numpy array or a number or None (default=None). @param [in] obs_metadata is an ObservationMetaData characterizing the telescope pointing. @param [in] epoch is the epoch in Julian years of the equinox against which RA is measured. Default is 2000. @param [in] chipName designates the names of the chips on which the pixel coordinates will be reckoned. Can be either single value, an array, or None. If an array, there must be as many chipNames as there are (RA, Dec) pairs. If a single value, all of the pixel coordinates will be reckoned on the same chip. If None, this method will calculate which chip each(RA, Dec) pair actually falls on, and return pixel coordinates for each (RA, Dec) pair on the appropriate chip. Default is None. @param [in] camera is an afwCameraGeom object specifying the attributes of the camera. This is an optional argument to be passed to chipName. @param [in] includeDistortion is a boolean. If True (default), then this method will return the true pixel coordinates with optical distortion included. If False, this method will return TAN_PIXEL coordinates, which are the pixel coordinates with estimated optical distortion removed. See the documentation in afw.cameraGeom for more details. @param [out] a 2-D numpy array in which the first row is the x pixel coordinate and the second row is the y pixel coordinate """ if pm_ra is not None: pm_ra_out = radiansFromArcsec(pm_ra) else: pm_ra_out = None if pm_dec is not None: pm_dec_out = radiansFromArcsec(pm_dec) else: pm_dec_out = None if parallax is not None: parallax_out = radiansFromArcsec(parallax) else: parallax_out = None return _pixelCoordsFromRaDec(np.radians(ra), np.radians(dec), pm_ra=pm_ra_out, pm_dec=pm_dec_out, parallax=parallax_out, v_rad=v_rad, chipName=chipName, camera=camera, includeDistortion=includeDistortion, obs_metadata=obs_metadata, epoch=epoch)
def test_flare_magnitudes_mixed_with_none(self): """ Test that we get the expected magnitudes out """ db = MLT_test_DB(database=self.db_name, driver='sqlite') # load the quiescent SEDs of the objects in our catalog sed_list = SedList(['lte028-5.0+0.5a+0.0.BT-Settl.spec.gz']*4, [17.1, 17.2, 17.3, 17.4], galacticAvList = [2.432, 1.876, 2.654, 2.364], fileDir=getPackageDir('sims_sed_library'), specMap=defaultSpecMap) bp_dict = BandpassDict.loadTotalBandpassesFromFiles() # calculate the quiescent fluxes of the objects in our catalog baseline_fluxes = bp_dict.fluxListForSedList(sed_list) bb_wavelen = np.arange(100.0, 1600.0, 0.1) bb = models.BlackBody(temperature=9000.0 * u.K, scale=1.0 * u.erg / (u.cm ** 2 * u.AA * u.s * u.sr)) bb_flambda = bb(bb_wavelen * u.nm).to_value() # this data is taken from the setUpClass() classmethod above t0_list = [456.2, 41006.2, 117.2, 10456.2] av_list = [2.432, 1.876, 2.654, 2.364] parallax_list = np.array([0.25, 0.15, 0.3, 0.22]) distance_list = 1.0/(206265.0*radiansFromArcsec(0.001*parallax_list)) distance_list *= 3.0857e18 # convert to cm dtype = np.dtype([('id', int), ('u', float), ('g', float)]) photParams = PhotometricParameters() ss = Sed() quiet_cat_name = os.path.join(self.scratch_dir, 'mlt_mixed_with_none_quiet_cat.txt') flare_cat_name = os.path.join(self.scratch_dir, 'mlt_mixed_with_none_flaring_cat.txt') # loop over several MJDs and verify that, to within a # milli-mag, our flaring model gives us the magnitudes # expected, given the light curves specified in # setUpClass() for mjd in (59580.0, 60000.0, 70000.0, 80000.0): obs = ObservationMetaData(mjd=mjd) quiet_cat = QuiescentCatalog(db, obs_metadata=obs) quiet_cat.write_catalog(quiet_cat_name) flare_cat = FlaringCatalog(db, obs_metadata=obs) flare_cat._mlt_lc_file = self.mlt_lc_name flare_cat.write_catalog(flare_cat_name) quiescent_data = np.genfromtxt(quiet_cat_name, dtype=dtype, delimiter=',') flaring_data = np.genfromtxt(flare_cat_name, dtype=dtype, delimiter=',') self.assertGreater(len(flaring_data), 3) for ix in range(len(flaring_data)): obj_id = flaring_data['id'][ix] self.assertEqual(obj_id, ix) # the models below are as specified in the # setUpClass() method if obj_id == 0 or obj_id == 1: amp = 1.0e42 dt = 3652.5 t_min = flare_cat._survey_start - t0_list[obj_id] tt = mjd - t_min while tt > dt: tt -= dt u_flux = amp*(1.0+np.power(np.sin(tt/100.0), 2)) g_flux = amp*(1.0+np.power(np.cos(tt/100.0), 2)) elif obj_id==2: amp = 2.0e41 dt = 365.25 t_min = flare_cat._survey_start - t0_list[obj_id] tt = mjd - t_min while tt > dt: tt -= dt u_flux = amp*(1.0+np.power(np.sin(tt/50.0), 2)) g_flux = amp*(1.0+np.power(np.cos(tt/50.0), 2)) else: u_flux = 0.0 g_flux = 0.0 # calculate the multiplicative effect of dust on a 9000K # black body bb_sed = Sed(wavelen=bb_wavelen, flambda=bb_flambda) u_bb_flux = bb_sed.calcFlux(bp_dict['u']) g_bb_flux = bb_sed.calcFlux(bp_dict['g']) a_x, b_x = bb_sed.setupCCM_ab() bb_sed.addDust(a_x, b_x, A_v=av_list[obj_id]) u_bb_dusty_flux = bb_sed.calcFlux(bp_dict['u']) g_bb_dusty_flux = bb_sed.calcFlux(bp_dict['g']) dust_u = u_bb_dusty_flux/u_bb_flux dust_g = g_bb_dusty_flux/g_bb_flux area = 4.0*np.pi*np.power(distance_list[obj_id], 2) tot_u_flux = baseline_fluxes[obj_id][0] + u_flux*dust_u/area tot_g_flux = baseline_fluxes[obj_id][1] + g_flux*dust_g/area msg = ('failed on object %d; mjd %.2f\n u_quiet %e u_flare %e\n g_quiet %e g_flare %e' % (obj_id, mjd, quiescent_data['u'][obj_id], flaring_data['u'][obj_id], quiescent_data['g'][obj_id], flaring_data['g'][obj_id])) self.assertEqual(quiescent_data['id'][obj_id], flaring_data['id'][obj_id], msg=msg) self.assertAlmostEqual(ss.magFromFlux(baseline_fluxes[obj_id][0]), quiescent_data['u'][obj_id], 3, msg=msg) self.assertAlmostEqual(ss.magFromFlux(baseline_fluxes[obj_id][1]), quiescent_data['g'][obj_id], 3, msg=msg) self.assertAlmostEqual(ss.magFromFlux(tot_u_flux), flaring_data['u'][obj_id], 3, msg=msg) self.assertAlmostEqual(ss.magFromFlux(tot_g_flux), flaring_data['g'][obj_id], 3, msg=msg) if obj_id != 3: self.assertGreater(np.abs(flaring_data['g'][obj_id]-quiescent_data['g'][obj_id]), 0.001, msg=msg) self.assertGreater(np.abs(flaring_data['u'][obj_id]-quiescent_data['u'][obj_id]), 0.001, msg=msg) else: self.assertEqual(flaring_data['g'][obj_id]-quiescent_data['g'][obj_id], 0.0, msg=msg) self.assertEqual(flaring_data['u'][obj_id]-quiescent_data['u'][obj_id], 0.0, msg=msg) if os.path.exists(quiet_cat_name): os.unlink(quiet_cat_name) if os.path.exists(flare_cat_name): os.unlink(flare_cat_name)
def sprinkle(self): # Define a list that we can write out to a text file lenslines = [] # For each galaxy in the catsim catalog updated_catalog = self.catalog.copy() print("Running sprinkler. Catalog Length: ", len(self.catalog)) for rowNum, row in enumerate(self.catalog): if rowNum == 100 or rowNum % 100000==0: print("Gone through ", rowNum, " lines of catalog.") if not np.isnan(row['galaxyAgn_magNorm']): candidates = self.find_lens_candidates(row['galaxyAgn_redshift'], row['galaxyAgn_magNorm']) varString = json.loads(row['galaxyAgn_varParamStr']) varString['pars']['t0_mjd'] = 59300.0 row['galaxyAgn_varParamStr'] = json.dumps(varString) np.random.seed(row['galtileid'] % (2^32 -1)) pick_value = np.random.uniform() # If there aren't any lensed sources at this redshift from OM10 move on the next object if ((len(candidates) > 0) and (pick_value <= self.density_param)): # Randomly choose one the lens systems # (can decide with or without replacement) # Sort first to make sure the same choice is made every time candidates = candidates[np.argsort(candidates['twinklesId'])] newlens = np.random.choice(candidates) # Append the lens galaxy # For each image, append the lens images for i in range(newlens['NIMG']): lensrow = row.copy() # XIMG and YIMG are in arcseconds # raPhSim and decPhoSim are in radians #Shift all parts of the lensed object, not just its agn part for lensPart in ['galaxyBulge', 'galaxyDisk', 'galaxyAgn']: lens_ra = lensrow[str(lensPart+'_raJ2000')] lens_dec = lensrow[str(lensPart+'_decJ2000')] delta_ra = np.radians(newlens['XIMG'][i] / 3600.0) / np.cos(lens_dec) delta_dec = np.radians(newlens['YIMG'][i] / 3600.0) lensrow[str(lensPart + '_raJ2000')] = lens_ra + delta_ra lensrow[str(lensPart + '_decJ2000')] = lens_dec + delta_dec mag_adjust = 2.5*np.log10(np.abs(newlens['MAG'][i])) lensrow['galaxyAgn_magNorm'] -= mag_adjust varString = json.loads(lensrow['galaxyAgn_varParamStr']) varString['pars']['t0Delay'] = newlens['DELAY'][i] varString['varMethodName'] = 'applyAgnTimeDelay' lensrow['galaxyAgn_varParamStr'] = json.dumps(varString) lensrow['galaxyDisk_majorAxis'] = 0.0 lensrow['galaxyDisk_minorAxis'] = 0.0 lensrow['galaxyDisk_positionAngle'] = 0.0 lensrow['galaxyDisk_internalAv'] = 0.0 lensrow['galaxyDisk_magNorm'] = np.nan lensrow['galaxyDisk_sedFilename'] = None lensrow['galaxyBulge_majorAxis'] = 0.0 lensrow['galaxyBulge_minorAxis'] = 0.0 lensrow['galaxyBulge_positionAngle'] = 0.0 lensrow['galaxyBulge_internalAv'] = 0.0 lensrow['galaxyBulge_magNorm'] = np.nan lensrow['galaxyBulge_sedFilename'] = None lensrow['galaxyBulge_redshift'] = newlens['ZSRC'] lensrow['galaxyDisk_redshift'] = newlens['ZSRC'] lensrow['galaxyAgn_redshift'] = newlens['ZSRC'] #To get back twinklesID in lens catalog from phosim catalog id number #just use np.right_shift(phosimID-28, 10). Take the floor of the last #3 numbers to get twinklesID in the twinkles lens catalog and the remainder is #the image number minus 1. lensrow['galtileid'] = (lensrow['galtileid']*10000 + newlens['twinklesId']*4 + i) updated_catalog = np.append(updated_catalog, lensrow) #Now manipulate original entry to be the lens galaxy with desired properties #Start by deleting Disk and AGN properties if not np.isnan(row['galaxyDisk_magNorm']): row['galaxyDisk_majorAxis'] = 0.0 row['galaxyDisk_minorAxis'] = 0.0 row['galaxyDisk_positionAngle'] = 0.0 row['galaxyDisk_internalAv'] = 0.0 row['galaxyDisk_magNorm'] = np.nan row['galaxyDisk_sedFilename'] = None row['galaxyAgn_magNorm'] = np.nan row['galaxyAgn_sedFilename'] = None #Now insert desired Bulge properties row['galaxyBulge_sedFilename'] = newlens['lens_sed'] row['galaxyBulge_redshift'] = newlens['ZLENS'] row['galaxyDisk_redshift'] = newlens['ZLENS'] row['galaxyAgn_redshift'] = newlens['ZLENS'] row['galaxyBulge_magNorm'] = matchBase().calcMagNorm([newlens['APMAG_I']], self.LRG, self.bandpassDict) #Changed from i band to imsimband row['galaxyBulge_majorAxis'] = radiansFromArcsec(newlens['REFF'] / np.sqrt(1 - newlens['ELLIP'])) row['galaxyBulge_minorAxis'] = radiansFromArcsec(newlens['REFF'] * np.sqrt(1 - newlens['ELLIP'])) #Convert orientation angle to west of north from east of north by *-1.0 and convert to radians row['galaxyBulge_positionAngle'] = newlens['PHIE']*(-1.0)*np.pi/180.0 #Replace original entry with new entry updated_catalog[rowNum] = row return updated_catalog
host='fatboy.phys.washington.edu', port=1433, driver='mssql+pymssql') results_iter = db.get_arbitrary_chunk_iterator(query, dtype=dtype, chunk_size=100000) dummy_sed = Sed() _au_to_parsec = 1.0 / 206265.0 _cm_per_parsec = 3.08576e18 ct_bad = 0 ct_total = 0 for i_chunk, chunk in enumerate(results_iter): parallax = radiansFromArcsec(0.001 * chunk['parallax']) dd = _au_to_parsec / parallax sphere_area = 4.0 * np.pi * np.power(dd * _cm_per_parsec, 2) flux_factor = 1.0 / sphere_area dust_factor = {} for mag_name in mag_name_list: dust_factor[mag_name] = np.interp(chunk['ebv'], dust_grid['ebv'], dust_grid[mag_name]) lc_int_dex = np.ones(len(chunk), dtype=int) dmag_max = np.zeros(len(chunk), dtype=float) mag_min = np.zeros(len(chunk), dtype=float) for i_star, star in enumerate(chunk): var_dict = json.loads(star['varParamStr'])
lc_curve_time = {} t_max_dex_dict = {} with np.load(fname) as lc_file: for name in lc_file.keys(): if 'time' in name: lc_curve_time[name] = lc_file[name] else: dex = np.argmax(lc_file[name]) t_max_dex_dict[name] = dex lc_name_list = [ 'early_active', 'early_inactive', 'mid_active', 'mid_inactive', 'late_active' ] milliarcsec = radiansFromArcsec(0.001) ebv_grid = np.arange(0.01, 7.01, 0.01) parallax_grid = np.arange(0.01 * milliarcsec, 50.0 * milliarcsec, milliarcsec) n_steps = len(parallax_grid) out_cache = {} out_cache['parallax_grid(mas)'] = parallax_grid / milliarcsec for lc_name_root in lc_name_list: for lc_dex in range(4): lc_name = lc_name_root + '_%d' % lc_dex print(lc_name) t_max_dex = t_max_dex_dict[lc_name + '_u'] for bp in 'grizy':
def test_different_cameras(self): rng = np.random.RandomState(6512) pointing_ra = 15.0 pointing_dec = 13.0 n_obj = 100 ra_list = pointing_ra + 2.0*rng.random_sample(n_obj) dec_list = pointing_dec + 2.0*rng.random_sample(n_obj) px_list = radiansFromArcsec(0.005)*rng.random_sample(n_obj) px_list += radiansFromArcsec(0.001) mura_list = radiansFromArcsec(0.005)*rng.random_sample(n_obj) mudec_list = radiansFromArcsec(0.005)*rng.random_sample(n_obj) vrad_list = 100.0*rng.random_sample(n_obj) with lsst.utils.tests.getTempFilePath('.txt') as db_text_file: with open(db_text_file, 'w') as out_file: for ix, (rdeg, ddeg, rrad, drad, px, mura, mudec, vrad) in \ enumerate(zip(ra_list, dec_list, np.radians(ra_list), np.radians(dec_list), px_list, mura_list, mudec_list, vrad_list)): out_file.write('%d %e %e %e %e %e %e %e %e\n' % (ix, rdeg, ddeg, rrad, drad, px, mura, mudec, vrad)) dtype = np.dtype([('id', int), ('raDeg', float), ('decDeg', float), ('raJ2000', float), ('decJ2000', float), ('parallax', float), ('properMotionRa', float), ('properMotionDec', float), ('radialVelocity', float)]) db = fileDBObject(db_text_file, dtype=dtype, idColKey='id') db.raColName = 'raDeg' db.decColName = 'decDeg' class CameraCoordsCatalog(AstrometryStars, CameraCoords, InstanceCatalog): camera = LsstSimMapper().camera column_outputs = ['id', 'chipName'] class CameraCoordsLSSTCatalog(AstrometryStars, CameraCoordsLSST, InstanceCatalog): column_outputs = ['id', 'chipName'] obs = ObservationMetaData(pointingRA=pointing_ra, pointingDec=pointing_dec, boundLength=1.75, boundType='circle', rotSkyPos=23.0, mjd=59580.0) control_cat = CameraCoordsCatalog(db, obs_metadata=obs) test_cat = CameraCoordsLSSTCatalog(db, obs_metadata=obs) control_line_list = [] none_chips = 0 for line in control_cat.iter_catalog(): if line[1] is None: none_chips += 1 control_line_list.append(line) self.assertGreater(len(control_line_list), 0) self.assertLess(none_chips, len(control_line_list)/2) line_ct = 0 for line in test_cat.iter_catalog(): line_ct += 1 self.assertIn(line, control_line_list) self.assertEqual(line_ct, len(control_line_list))
def test_flare_magnitudes_mixed_with_dummy(self): """ Test that we get the expected magnitudes out """ db = MLT_test_DB(database=self.db_name, driver='sqlite') # load the quiescent SEDs of the objects in our catalog sed_list = SedList(['lte028-5.0+0.5a+0.0.BT-Settl.spec.gz']*4, [17.1, 17.2, 17.3, 17.4], galacticAvList = [2.432, 1.876, 2.654, 2.364], fileDir=getPackageDir('sims_sed_library'), specMap=defaultSpecMap) bp_dict = BandpassDict.loadTotalBandpassesFromFiles() # calculate the quiescent fluxes of the objects in our catalog baseline_fluxes = bp_dict.fluxListForSedList(sed_list) bb_wavelen = np.arange(100.0, 1600.0, 0.1) bb_flambda = blackbody_lambda(bb_wavelen*10.0, 9000.0) # this data is taken from the setUpClass() classmethod above t0_list = [456.2, 41006.2, 117.2, 10456.2] av_list = [2.432, 1.876, 2.654, 2.364] parallax_list = np.array([0.25, 0.15, 0.3, 0.22]) distance_list = 1.0/(206265.0*radiansFromArcsec(0.001*parallax_list)) distance_list *= 3.0857e18 # convert to cm dtype = np.dtype([('id', int), ('u', float), ('g', float)]) photParams = PhotometricParameters() ss = Sed() quiet_cat_name = os.path.join(self.scratch_dir, 'mlt_mixed_with_dummy_quiet_cat.txt') flare_cat_name = os.path.join(self.scratch_dir, 'mlt_mixed_with_dummy_flaring_cat.txt') # loop over several MJDs and verify that, to within a # milli-mag, our flaring model gives us the magnitudes # expected, given the light curves specified in # setUpClass() for mjd in (59580.0, 60000.0, 70000.0, 80000.0): obs = ObservationMetaData(mjd=mjd) quiet_cat = QuiescentCatalog(db, obs_metadata=obs) quiet_cat.write_catalog(quiet_cat_name) flare_cat = FlaringCatalogDummy(db, obs_metadata=obs) flare_cat.scratch_dir = self.scratch_dir flare_cat._mlt_lc_file = self.mlt_lc_name flare_cat.write_catalog(flare_cat_name) quiescent_data = np.genfromtxt(quiet_cat_name, dtype=dtype, delimiter=',') flaring_data = np.genfromtxt(flare_cat_name, dtype=dtype, delimiter=',') self.assertGreater(len(quiescent_data), 2) self.assertEqual(len(quiescent_data), len(flaring_data)) self.assertIn(3, flaring_data['id']) for ix in range(len(flaring_data)): obj_id = flaring_data['id'][ix] self.assertEqual(obj_id, ix) msg = ('failed on object %d; mjd %.2f\n u_quiet %e u_flare %e\n g_quiet %e g_flare %e' % (obj_id, mjd, quiescent_data['u'][obj_id], flaring_data['u'][obj_id], quiescent_data['g'][obj_id], flaring_data['g'][obj_id])) self.assertEqual(quiescent_data['id'][obj_id], flaring_data['id'][obj_id], msg=msg) self.assertAlmostEqual(ss.magFromFlux(baseline_fluxes[obj_id][0]), quiescent_data['u'][obj_id], 3, msg=msg) self.assertAlmostEqual(ss.magFromFlux(baseline_fluxes[obj_id][1]), quiescent_data['g'][obj_id], 3, msg=msg) if obj_id != 3: # the models below are as specified in the # setUpClass() method if obj_id == 0 or obj_id == 1: amp = 1.0e42 dt = 3652.5 t_min = flare_cat._survey_start - t0_list[obj_id] tt = mjd - t_min while tt > dt: tt -= dt u_flux = amp*(1.0+np.power(np.sin(tt/100.0), 2)) g_flux = amp*(1.0+np.power(np.cos(tt/100.0), 2)) elif obj_id==2: amp = 2.0e41 dt = 365.25 t_min = flare_cat._survey_start - t0_list[obj_id] tt = mjd - t_min while tt > dt: tt -= dt u_flux = amp*(1.0+np.power(np.sin(tt/50.0), 2)) g_flux = amp*(1.0+np.power(np.cos(tt/50.0), 2)) # calculate the multiplicative effect of dust on a 9000K # black body bb_sed = Sed(wavelen=bb_wavelen, flambda=bb_flambda) u_bb_flux = bb_sed.calcFlux(bp_dict['u']) g_bb_flux = bb_sed.calcFlux(bp_dict['g']) a_x, b_x = bb_sed.setupCCM_ab() bb_sed.addDust(a_x, b_x, A_v=av_list[obj_id]) u_bb_dusty_flux = bb_sed.calcFlux(bp_dict['u']) g_bb_dusty_flux = bb_sed.calcFlux(bp_dict['g']) dust_u = u_bb_dusty_flux/u_bb_flux dust_g = g_bb_dusty_flux/g_bb_flux area = 4.0*np.pi*np.power(distance_list[obj_id], 2) tot_u_flux = baseline_fluxes[obj_id][0] + u_flux*dust_u/area tot_g_flux = baseline_fluxes[obj_id][1] + g_flux*dust_g/area self.assertAlmostEqual(ss.magFromFlux(tot_u_flux), flaring_data['u'][obj_id], 3, msg=msg) self.assertAlmostEqual(ss.magFromFlux(tot_g_flux), flaring_data['g'][obj_id], 3, msg=msg) self.assertGreater(np.abs(flaring_data['g'][obj_id]-quiescent_data['g'][obj_id]), 0.001, msg=msg) self.assertGreater(np.abs(flaring_data['u'][obj_id]-quiescent_data['u'][obj_id]), 0.001, msg=msg) else: self.assertAlmostEqual(flaring_data['g'][obj_id], quiescent_data['g'][obj_id]+3*(mjd-59580.0)/10000.0, 3, msg=msg) self.assertAlmostEqual(flaring_data['u'][obj_id], quiescent_data['u'][obj_id]+2*(mjd-59580.0)/10000.0, 3, msg=msg) if os.path.exists(quiet_cat_name): os.unlink(quiet_cat_name) if os.path.exists(flare_cat_name): os.unlink(flare_cat_name)
def sprinkle(self): # Define a list that we can write out to a text file lenslines = [] # For each galaxy in the catsim catalog updated_catalog = self.catalog.copy() # print("Running sprinkler. Catalog Length: ", len(self.catalog)) for rowNum, row in enumerate(self.catalog): # if rowNum == 100 or rowNum % 100000==0: # print("Gone through ", rowNum, " lines of catalog.") if not np.isnan(row[self.defs_dict['galaxyAgn_magNorm']]): candidates = self.find_lens_candidates( row[self.defs_dict['galaxyAgn_redshift']], row[self.defs_dict['galaxyAgn_magNorm']]) #varString = json.loads(row[self.defs_dict['galaxyAgn_varParamStr']]) # varString[self.defs_dict['pars']]['t0_mjd'] = 59300.0 #row[self.defs_dict['galaxyAgn_varParamStr']] = json.dumps(varString) np.random.seed(row[self.defs_dict['galtileid']] % (2 ^ 32 - 1)) pick_value = np.random.uniform() # If there aren't any lensed sources at this redshift from OM10 move on the next object if (((len(candidates) > 0) and (pick_value <= self.density_param) and (self.cached_sprinkling is False)) | ((self.cached_sprinkling is True) and (row[self.defs_dict['galtileid']] in self.agn_cache['galtileid'].values))): # Randomly choose one the lens systems # (can decide with or without replacement) # Sort first to make sure the same choice is made every time if self.cached_sprinkling is True: twinkles_sys_cache = self.agn_cache.query( 'galtileid == %i' % row[self.defs_dict['galtileid']] )['twinkles_system'].values[0] newlens = self.lenscat[np.where( self.lenscat['twinklesId'] == twinkles_sys_cache) [0]][0] else: candidates = candidates[np.argsort( candidates['twinklesId'])] newlens = np.random.choice(candidates) # Append the lens galaxy # For each image, append the lens images for i in range(newlens['NIMG']): lensrow = row.copy() # XIMG and YIMG are in arcseconds # raPhSim and decPhoSim are in radians #Shift all parts of the lensed object, not just its agn part for lensPart in [ 'galaxyBulge', 'galaxyDisk', 'galaxyAgn' ]: lens_ra = lensrow[self.defs_dict[str(lensPart + '_raJ2000')]] lens_dec = lensrow[self.defs_dict[str( lensPart + '_decJ2000')]] delta_ra = np.radians( newlens['XIMG'][i] / 3600.0) / np.cos(lens_dec) delta_dec = np.radians(newlens['YIMG'][i] / 3600.0) lensrow[self.defs_dict[str( lensPart + '_raJ2000')]] = lens_ra + delta_ra lensrow[self.defs_dict[ str(lensPart + '_decJ2000')]] = lens_dec + delta_dec mag_adjust = 2.5 * np.log10(np.abs(newlens['MAG'][i])) lensrow[ self.defs_dict['galaxyAgn_magNorm']] -= mag_adjust varString = json.loads( lensrow[self.defs_dict['galaxyAgn_varParamStr']]) varString[self.defs_dict['pars']]['t0Delay'] = newlens[ 'DELAY'][i] varString[self.defs_dict[ 'varMethodName']] = 'applyAgnTimeDelay' lensrow[self.defs_dict[ 'galaxyAgn_varParamStr']] = json.dumps(varString) lensrow[self.defs_dict['galaxyDisk_majorAxis']] = 0.0 lensrow[self.defs_dict['galaxyDisk_minorAxis']] = 0.0 lensrow[ self.defs_dict['galaxyDisk_positionAngle']] = 0.0 lensrow[self.defs_dict['galaxyDisk_internalAv']] = 0.0 lensrow[self.defs_dict[ 'galaxyDisk_magNorm']] = 999. #np.nan To be fixed post run1.1 lensrow[ self.defs_dict['galaxyDisk_sedFilename']] = None lensrow[self.defs_dict['galaxyBulge_majorAxis']] = 0.0 lensrow[self.defs_dict['galaxyBulge_minorAxis']] = 0.0 lensrow[ self.defs_dict['galaxyBulge_positionAngle']] = 0.0 lensrow[self.defs_dict['galaxyBulge_internalAv']] = 0.0 lensrow[self.defs_dict[ 'galaxyBulge_magNorm']] = 999. #np.nan To be fixed post run1.1 lensrow[ self.defs_dict['galaxyBulge_sedFilename']] = None lensrow[self.defs_dict[ 'galaxyBulge_redshift']] = newlens['ZSRC'] lensrow[self.defs_dict[ 'galaxyDisk_redshift']] = newlens['ZSRC'] lensrow[self.defs_dict[ 'galaxyAgn_redshift']] = newlens['ZSRC'] #To get back twinklesID in lens catalog from phosim catalog id number #just use np.right_shift(phosimID-28, 10). Take the floor of the last #3 numbers to get twinklesID in the twinkles lens catalog and the remainder is #the image number minus 1. lensrow[self.defs_dict['galtileid']] = ( lensrow[self.defs_dict['galtileid']] * 10000 + newlens['twinklesId'] * 4 + i) updated_catalog = np.append(updated_catalog, lensrow) #Now manipulate original entry to be the lens galaxy with desired properties #Start by deleting Disk and AGN properties if not np.isnan(row[self.defs_dict['galaxyDisk_magNorm']]): row[self.defs_dict['galaxyDisk_majorAxis']] = 0.0 row[self.defs_dict['galaxyDisk_minorAxis']] = 0.0 row[self.defs_dict['galaxyDisk_positionAngle']] = 0.0 row[self.defs_dict['galaxyDisk_internalAv']] = 0.0 row[self.defs_dict[ 'galaxyDisk_magNorm']] = 999. #np.nan To be fixed post run1.1 row[self.defs_dict['galaxyDisk_sedFilename']] = None row[self.defs_dict[ 'galaxyAgn_magNorm']] = None #np.nan To be fixed post run1.1 row[self.defs_dict[ 'galaxyDisk_magNorm']] = 999. # To be fixed in run1.1 row[self.defs_dict['galaxyAgn_sedFilename']] = None #Now insert desired Bulge properties row[self.defs_dict['galaxyBulge_sedFilename']] = newlens[ 'lens_sed'] row[self. defs_dict['galaxyBulge_redshift']] = newlens['ZLENS'] row[self. defs_dict['galaxyDisk_redshift']] = newlens['ZLENS'] row[self. defs_dict['galaxyAgn_redshift']] = newlens['ZLENS'] row_lens_sed = Sed() row_lens_sed.readSED_flambda( str(self.galDir + newlens['lens_sed'])) row_lens_sed.redshiftSED(newlens['ZLENS'], dimming=True) row[self.defs_dict['galaxyBulge_magNorm']] = matchBase( ).calcMagNorm( [newlens['APMAG_I']], row_lens_sed, self.bandpassDict) #Changed from i band to imsimband row[self.defs_dict[ 'galaxyBulge_majorAxis']] = radiansFromArcsec( newlens['REFF'] / np.sqrt(1 - newlens['ELLIP'])) row[self.defs_dict[ 'galaxyBulge_minorAxis']] = radiansFromArcsec( newlens['REFF'] * np.sqrt(1 - newlens['ELLIP'])) #Convert orientation angle to west of north from east of north by *-1.0 and convert to radians row[self.defs_dict['galaxyBulge_positionAngle']] = newlens[ 'PHIE'] * (-1.0) * np.pi / 180.0 #Replace original entry with new entry updated_catalog[rowNum] = row else: if self.cached_sprinkling is True: if row[self.defs_dict['galtileid']] in self.sne_cache[ 'galtileid'].values: use_system = self.sne_cache.query( 'galtileid == %i' % row[self.defs_dict['galtileid']] )['twinkles_system'].values use_df = self.sne_catalog.query( 'twinkles_sysno == %i' % use_system) self.used_systems.append(use_system) else: continue else: lens_sne_candidates = self.find_sne_lens_candidates( row[self.defs_dict['galaxyDisk_redshift']]) candidate_sysno = np.unique( lens_sne_candidates['twinkles_sysno']) num_candidates = len(candidate_sysno) if num_candidates == 0: continue used_already = np.array([ sys_num in self.used_systems for sys_num in candidate_sysno ]) unused_sysno = candidate_sysno[~used_already] if len(unused_sysno) == 0: continue np.random.seed(row[self.defs_dict['galtileid']] % (2 ^ 32 - 1)) use_system = np.random.choice(unused_sysno) use_df = self.sne_catalog.query('twinkles_sysno == %i' % use_system) for i in range(len(use_df)): lensrow = row.copy() for lensPart in ['galaxyBulge', 'galaxyDisk', 'galaxyAgn']: lens_ra = lensrow[self.defs_dict[str(lensPart + '_raJ2000')]] lens_dec = lensrow[self.defs_dict[str(lensPart + '_decJ2000')]] delta_ra = np.radians( use_df['x'].iloc[i] / 3600.0) / np.cos(lens_dec) delta_dec = np.radians(use_df['y'].iloc[i] / 3600.0) lensrow[self.defs_dict[str( lensPart + '_raJ2000')]] = lens_ra + delta_ra lensrow[self.defs_dict[str( lensPart + '_decJ2000')]] = lens_dec + delta_dec # varString = json.loads(lensrow[self.defs_dict['galaxyAgn_varParamStr']]) varString = 'None' lensrow[ self.defs_dict['galaxyAgn_varParamStr']] = varString lensrow[self.defs_dict['galaxyDisk_majorAxis']] = 0.0 lensrow[self.defs_dict['galaxyDisk_minorAxis']] = 0.0 lensrow[self.defs_dict['galaxyDisk_positionAngle']] = 0.0 lensrow[self.defs_dict['galaxyDisk_internalAv']] = 0.0 lensrow[self.defs_dict[ 'galaxyDisk_magNorm']] = 999. #np.nan To be fixed post run1.1 lensrow[self.defs_dict['galaxyDisk_sedFilename']] = None lensrow[self.defs_dict['galaxyBulge_majorAxis']] = 0.0 lensrow[self.defs_dict['galaxyBulge_minorAxis']] = 0.0 lensrow[self.defs_dict['galaxyBulge_positionAngle']] = 0.0 lensrow[self.defs_dict['galaxyBulge_internalAv']] = 0.0 lensrow[self.defs_dict[ 'galaxyBulge_magNorm']] = 999. #np.nan To be fixed post run1.1 lensrow[self.defs_dict['galaxyBulge_sedFilename']] = None z_s = use_df['zs'].iloc[i] lensrow[self.defs_dict['galaxyBulge_redshift']] = z_s lensrow[self.defs_dict['galaxyDisk_redshift']] = z_s lensrow[self.defs_dict['galaxyAgn_redshift']] = z_s #To get back twinklesID in lens catalog from phosim catalog id number #just use np.right_shift(phosimID-28, 10). Take the floor of the last #3 numbers to get twinklesID in the twinkles lens catalog and the remainder is #the image number minus 1. lensrow[self.defs_dict['galtileid']] = ( lensrow[self.defs_dict['galtileid']] * 10000 + use_system * 4 + i) add_to_cat, sn_magnorm, sn_fname = self.create_sn_sed( use_df.iloc[i], lensrow[self.defs_dict['galaxyAgn_raJ2000']], lensrow[self.defs_dict['galaxyAgn_decJ2000']], self.visit_mjd) lensrow[self.defs_dict['galaxyAgn_sedFilename']] = sn_fname lensrow[self.defs_dict[ 'galaxyAgn_magNorm']] = sn_magnorm #This will need to be adjusted to proper band mag_adjust = 2.5 * np.log10(np.abs(use_df['mu'].iloc[i])) lensrow[self.defs_dict['galaxyAgn_magNorm']] -= mag_adjust if add_to_cat is True: updated_catalog = np.append(updated_catalog, lensrow) else: continue #Now manipulate original entry to be the lens galaxy with desired properties #Start by deleting Disk and AGN properties if not np.isnan(row[self.defs_dict['galaxyDisk_magNorm']]): row[self.defs_dict['galaxyDisk_majorAxis']] = 0.0 row[self.defs_dict['galaxyDisk_minorAxis']] = 0.0 row[self.defs_dict['galaxyDisk_positionAngle']] = 0.0 row[self.defs_dict['galaxyDisk_internalAv']] = 0.0 row[self.defs_dict[ 'galaxyDisk_magNorm']] = 999. #np.nan To be fixed post run1.1 row[self.defs_dict['galaxyDisk_sedFilename']] = None row[self.defs_dict[ 'galaxyAgn_magNorm']] = None #np.nan To be fixed post run1.1 row[self.defs_dict[ 'galaxyDisk_magNorm']] = 999. #To be fixed post run1.1 row[self.defs_dict['galaxyAgn_sedFilename']] = None #Now insert desired Bulge properties row[self.defs_dict['galaxyBulge_sedFilename']] = use_df[ 'lens_sed'].iloc[0] row[self. defs_dict['galaxyBulge_redshift']] = use_df['zl'].iloc[0] row[self. defs_dict['galaxyDisk_redshift']] = use_df['zl'].iloc[0] row[self. defs_dict['galaxyAgn_redshift']] = use_df['zl'].iloc[0] row[self.defs_dict['galaxyBulge_magNorm']] = use_df[ 'bulge_magnorm'].iloc[0] # row[self.defs_dict['galaxyBulge_magNorm']] = matchBase().calcMagNorm([newlens['APMAG_I']], self.LRG, self.bandpassDict) #Changed from i band to imsimband row[self. defs_dict['galaxyBulge_majorAxis']] = radiansFromArcsec( use_df['r_eff'].iloc[0] / np.sqrt(1 - use_df['e'].iloc[0])) row[self. defs_dict['galaxyBulge_minorAxis']] = radiansFromArcsec( use_df['r_eff'].iloc[0] * np.sqrt(1 - use_df['e'].iloc[0])) #Convert orientation angle to west of north from east of north by *-1.0 and convert to radians row[self.defs_dict['galaxyBulge_positionAngle']] = use_df[ 'theta_e'].iloc[0] * (-1.0) * np.pi / 180.0 #Replace original entry with new entry updated_catalog[rowNum] = row return updated_catalog
def test_with_proper_motion(self): """ Test that calculating pupil coordinates in the presence of proper motion, parallax, and radial velocity is equivalent to observedFromICRS -> icrsFromObserved -> pupilCoordsFromRaDec (mostly to make surethat pupilCoordsFromRaDec is correctly calling observedFromICRS with non-zero proper motion, etc.) """ rng = np.random.RandomState(38442) is_valid = False while not is_valid: mjd_tai = 59580.0 + 10000.0 * rng.random_sample() obs = ObservationMetaData(mjd=mjd_tai) ra, dec = raDecFromAltAz(78.0, 112.0, obs) dd = distanceToSun(ra, dec, obs.mjd) if dd > 45.0: is_valid = True n_obj = 1000 rr = rng.random_sample(n_obj) * 2.0 theta = rng.random_sample(n_obj) * 2.0 * np.pi ra_list = ra + rr * np.cos(theta) dec_list = dec + rr * np.sin(theta) obs = ObservationMetaData(pointingRA=ra, pointingDec=dec, mjd=mjd_tai, rotSkyPos=19.0) pm_ra_list = rng.random_sample(n_obj) * 100.0 - 50.0 pm_dec_list = rng.random_sample(n_obj) * 100.0 - 50.0 px_list = rng.random_sample(n_obj) + 0.05 v_rad_list = rng.random_sample(n_obj) * 600.0 - 300.0 for includeRefraction in (True, False): ra_obs, dec_obs = observedFromICRS( ra_list, dec_list, pm_ra=pm_ra_list, pm_dec=pm_dec_list, parallax=px_list, v_rad=v_rad_list, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) ra_icrs, dec_icrs = icrsFromObserved( ra_obs, dec_obs, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) xp_control, yp_control = pupilCoordsFromRaDec( ra_icrs, dec_icrs, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) xp_test, yp_test = pupilCoordsFromRaDec( ra_list, dec_list, pm_ra=pm_ra_list, pm_dec=pm_dec_list, parallax=px_list, v_rad=v_rad_list, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) distance = arcsecFromRadians( np.sqrt( np.power(xp_test - xp_control, 2) + np.power(yp_test - yp_control, 2))) self.assertLess(distance.max(), 0.006) # now test it in radians xp_rad, yp_rad = _pupilCoordsFromRaDec( np.radians(ra_list), np.radians(dec_list), pm_ra=radiansFromArcsec(pm_ra_list), pm_dec=radiansFromArcsec(pm_dec_list), parallax=radiansFromArcsec(px_list), v_rad=v_rad_list, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) np.testing.assert_array_equal(xp_rad, xp_test) np.testing.assert_array_equal(yp_rad, yp_test) # now test it with proper motion = 0 ra_obs, dec_obs = observedFromICRS( ra_list, dec_list, parallax=px_list, v_rad=v_rad_list, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) ra_icrs, dec_icrs = icrsFromObserved( ra_obs, dec_obs, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) xp_control, yp_control = pupilCoordsFromRaDec( ra_icrs, dec_icrs, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) xp_test, yp_test = pupilCoordsFromRaDec( ra_list, dec_list, parallax=px_list, v_rad=v_rad_list, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) distance = arcsecFromRadians( np.sqrt( np.power(xp_test - xp_control, 2) + np.power(yp_test - yp_control, 2))) self.assertLess(distance.max(), 1.0e-6)
def appGeoFromICRS(ra, dec, pm_ra=None, pm_dec=None, parallax=None, v_rad=None, epoch=2000.0, mjd=None): """ Convert the mean position (RA, Dec) in the International Celestial Reference System (ICRS) to the mean apparent geocentric position units: ra (degrees), dec (degrees), pm_ra (arcsec/year), pm_dec (arcsec/year), parallax (arcsec), v_rad (km/sec; positive if receding), epoch (Julian years) @param [in] ra in degrees (ICRS). Can be a numpy array or a number. @param [in] dec in degrees (ICRS). Can be a numpy array or a number. @param [in] pm_ra is ra proper motion multiplied by cos(Dec) in arcsec/year @param [in] pm_dec is dec proper motion in arcsec/year @param [in] parallax in arcsec @param [in] v_rad is radial velocity in km/sec (positive if the object is receding) @param [in] epoch is the julian epoch (in years) of the equinox against which to measure RA (default: 2000.0) @param [in] mjd is an instantiation of the ModifiedJulianDate class representing the date of the observation @param [out] a 2-D numpy array in which the first row is the apparent geocentric RA and the second row is the apparent geocentric Dec (both in degrees) """ if pm_ra is not None: pm_ra_in = radiansFromArcsec(pm_ra) else: pm_ra_in = None if pm_dec is not None: pm_dec_in = radiansFromArcsec(pm_dec) else: pm_dec_in = None if parallax is not None: px_in = radiansFromArcsec(parallax) else: px_in = None output = _appGeoFromICRS(np.radians(ra), np.radians(dec), pm_ra=pm_ra_in, pm_dec=pm_dec_in, parallax=px_in, v_rad=v_rad, epoch=epoch, mjd=mjd) return np.degrees(output)
def setUpClass(cls): cls.camera = camTestUtils.CameraWrapper().camera cls.dataDir = tempfile.mkdtemp(dir=ROOT, prefix='GalSimPhoSimTest-') cls.n_objects = 5 rng = np.random.RandomState(45) pointingRA = 45.2 pointingDec = -31.6 cls.obs = ObservationMetaData(pointingRA=pointingRA, pointingDec=pointingDec, rotSkyPos=1.2, bandpassName='r', mjd=57341.5, boundLength=0.1, boundType='circle') cls.dtype = np.dtype([ ('id', int), ('raJ2000', np.float), ('decJ2000', np.float), ('ra_deg', np.float), ('dec_deg', np.float), ('sedFilename', (str, 300)), ('magNorm', np.float), ('redshift', np.float), ('majorAxis', np.float), ('minorAxis', np.float), ('positionAngle', np.float), ('halfLightRadius', np.float), ('sindex', np.float), ('internalAv', np.float), ('internalRv', np.float), ('galacticAv', np.float), ('galacticRv', np.float), ('properMotionRa', np.float), ('properMotionDec', np.float), ('radialVelocity', np.float), ('parallax', np.float) ]) # generate some galaxy bulge data redshift = rng.random_sample(cls.n_objects) * 1.5 rr = rng.random_sample(cls.n_objects) * 0.05 theta = rng.random_sample(cls.n_objects) * 2.0 * np.pi ra = np.radians(pointingRA + rr * np.cos(theta)) dec = np.radians(pointingDec + rr * np.sin(theta)) magNorm = rng.random_sample(cls.n_objects) * 7.0 + 18.0 sindex = rng.random_sample(cls.n_objects) * 4.0 + 1.0 hlr = radiansFromArcsec(rng.random_sample(cls.n_objects) * 10.0 + 1.0) positionAngle = rng.random_sample(cls.n_objects) * np.pi internalAv = rng.random_sample(cls.n_objects) * 0.5 + 0.1 internalRv = rng.random_sample(cls.n_objects) * 0.5 + 2.7 majorAxis = radiansFromArcsec( rng.random_sample(cls.n_objects) * 2.0 + 0.5) minorAxis = radiansFromArcsec( rng.random_sample(cls.n_objects) * 2.0 + 0.5) galacticAv = rng.random_sample(cls.n_objects) * 0.5 + 0.1 galacticRv = rng.random_sample(cls.n_objects) * 0.5 + 2.7 properMotionRa = np.zeros(cls.n_objects) properMotionDec = np.zeros(cls.n_objects) radialVelocity = np.zeros(cls.n_objects) parallax = np.zeros(cls.n_objects) cls.bulge_name = os.path.join(cls.dataDir, 'galSimPhoSim_test_bulge.dat') with open(cls.bulge_name, 'w') as output_file: output_file.write('# header\n') for ix in range(cls.n_objects): output_file.write( '%d %f %f %f %f Const.79E06.002Z.spec %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n' % (ix, ra[ix], dec[ix], np.degrees(ra[ix]), np.degrees(dec[ix]), magNorm[ix], redshift[ix], max(majorAxis[ix], minorAxis[ix]), min(majorAxis[ix], minorAxis[ix]), positionAngle[ix], hlr[ix], sindex[ix], internalAv[ix], internalRv[ix], galacticAv[ix], galacticRv[ix], properMotionRa[ix], properMotionDec[ix], radialVelocity[ix], parallax[ix])) # generate some galaxy disk data redshift = rng.random_sample(cls.n_objects) * 1.5 rr = rng.random_sample(cls.n_objects) * 0.05 theta = rng.random_sample(cls.n_objects) * 2.0 * np.pi ra = np.radians(pointingRA + rr * np.cos(theta)) dec = np.radians(pointingDec + rr * np.sin(theta)) magNorm = rng.random_sample(cls.n_objects) * 7.0 + 18.0 sindex = rng.random_sample(cls.n_objects) * 4.0 + 1.0 hlr = radiansFromArcsec(rng.random_sample(cls.n_objects) * 10.0 + 1.0) positionAngle = rng.random_sample(cls.n_objects) * np.pi internalAv = rng.random_sample(cls.n_objects) * 0.5 + 0.1 internalRv = rng.random_sample(cls.n_objects) * 0.5 + 2.7 majorAxis = radiansFromArcsec( rng.random_sample(cls.n_objects) * 2.0 + 0.5) minorAxis = radiansFromArcsec( rng.random_sample(cls.n_objects) * 2.0 + 0.5) galacticAv = rng.random_sample(cls.n_objects) * 0.5 + 0.1 galacticRv = rng.random_sample(cls.n_objects) * 0.5 + 2.7 properMotionRa = np.zeros(cls.n_objects) properMotionDec = np.zeros(cls.n_objects) radialVelocity = np.zeros(cls.n_objects) parallax = np.zeros(cls.n_objects) cls.disk_name = os.path.join(cls.dataDir, 'galSimPhoSim_test_disk.dat') with open(cls.disk_name, 'w') as output_file: output_file.write('# header\n') for ix in range(cls.n_objects): output_file.write( '%d %f %f %f %f Inst.79E06.02Z.spec %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n' % (ix, ra[ix], dec[ix], np.degrees(ra[ix]), np.degrees(dec[ix]), magNorm[ix], redshift[ix], max(majorAxis[ix], minorAxis[ix]), min(majorAxis[ix], minorAxis[ix]), positionAngle[ix], hlr[ix], sindex[ix], internalAv[ix], internalRv[ix], galacticAv[ix], galacticRv[ix], properMotionRa[ix], properMotionDec[ix], radialVelocity[ix], parallax[ix])) # generate some agn data redshift = rng.random_sample(cls.n_objects) * 1.5 rr = rng.random_sample(cls.n_objects) * 0.05 theta = rng.random_sample(cls.n_objects) * 2.0 * np.pi ra = np.radians(pointingRA + rr * np.cos(theta)) dec = np.radians(pointingDec + rr * np.sin(theta)) magNorm = rng.random_sample(cls.n_objects) * 7.0 + 18.0 sindex = np.zeros(cls.n_objects) hlr = np.zeros(cls.n_objects) positionAngle = np.zeros(cls.n_objects) internalAv = np.zeros(cls.n_objects) internalRv = np.zeros(cls.n_objects) majorAxis = np.zeros(cls.n_objects) minorAxis = np.zeros(cls.n_objects) galacticAv = rng.random_sample(cls.n_objects) * 0.5 + 0.1 galacticRv = rng.random_sample(cls.n_objects) * 0.5 + 2.7 properMotionRa = np.zeros(cls.n_objects) properMotionDec = np.zeros(cls.n_objects) radialVelocity = np.zeros(cls.n_objects) parallax = np.zeros(cls.n_objects) cls.agn_name = os.path.join(cls.dataDir, 'galSimPhoSim_test_agn.dat') with open(cls.agn_name, 'w') as output_file: output_file.write('# header\n') for ix in range(cls.n_objects): output_file.write( '%d %f %f %f %f agn.spec %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n' % (ix, ra[ix], dec[ix], np.degrees(ra[ix]), np.degrees(dec[ix]), magNorm[ix], redshift[ix], max(majorAxis[ix], minorAxis[ix]), min(majorAxis[ix], minorAxis[ix]), positionAngle[ix], hlr[ix], sindex[ix], internalAv[ix], internalRv[ix], galacticAv[ix], galacticRv[ix], properMotionRa[ix], properMotionDec[ix], radialVelocity[ix], parallax[ix])) # generate some star data redshift = rng.random_sample(cls.n_objects) * 1.5 rr = rng.random_sample(cls.n_objects) * 0.05 theta = rng.random_sample(cls.n_objects) * 2.0 * np.pi ra = np.radians(pointingRA + rr * np.cos(theta)) dec = np.radians(pointingDec + rr * np.sin(theta)) magNorm = rng.random_sample(cls.n_objects) * 7.0 + 18.0 sindex = np.zeros(cls.n_objects) hlr = np.zeros(cls.n_objects) positionAngle = np.zeros(cls.n_objects) internalAv = np.zeros(cls.n_objects) internalRv = np.zeros(cls.n_objects) majorAxis = np.zeros(cls.n_objects) minorAxis = np.zeros(cls.n_objects) galacticAv = rng.random_sample(cls.n_objects) * 0.5 + 0.1 galacticRv = rng.random_sample(cls.n_objects) * 0.5 + 2.7 properMotionRa = radiansFromArcsec( rng.random_sample(cls.n_objects) * 0.0002) properMotionDec = radiansFromArcsec( rng.random_sample(cls.n_objects) * 0.0002) radialVelocity = rng.random_sample(cls.n_objects) * 200.0 parallax = radiansFromArcsec(rng.random_sample(cls.n_objects) * 0.0002) cls.star_name = os.path.join(cls.dataDir, 'galSimPhoSim_test_star.dat') with open(cls.star_name, 'w') as output_file: output_file.write('# header\n') for ix in range(cls.n_objects): output_file.write( '%d %f %f %f %f km30_5000.fits_g10_5040 %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n' % (ix, ra[ix], dec[ix], np.degrees(ra[ix]), np.degrees(dec[ix]), magNorm[ix], redshift[ix], max(majorAxis[ix], minorAxis[ix]), min(majorAxis[ix], minorAxis[ix]), positionAngle[ix], hlr[ix], sindex[ix], internalAv[ix], internalRv[ix], galacticAv[ix], galacticRv[ix], properMotionRa[ix], properMotionDec[ix], radialVelocity[ix], parallax[ix]))
def observedFromICRS(ra, dec, pm_ra=None, pm_dec=None, parallax=None, v_rad=None, obs_metadata=None, epoch=None, includeRefraction=True): """ Convert mean position (RA, Dec) in the International Celestial Reference Frame to observed (RA, Dec). included are precession-nutation, aberration, proper motion, parallax, refraction, radial velocity, diurnal aberration. This method works in degrees. @param [in] ra is the unrefracted RA in degrees (ICRS). Can be a numpy array or a number. @param [in] dec is the unrefracted Dec in degrees (ICRS). Can be a numpy array or a number. @param [in] pm_ra is proper motion in RA multiplied by cos(Dec) (arcsec/yr) Can be a numpy array or a number or None (default=None). @param [in] pm_dec is proper motion in dec (arcsec/yr) Can be a numpy array or a number or None (default=None). @param [in] parallax is parallax in arcsec Can be a numpy array or a number or None (default=None). @param [in] v_rad is radial velocity (km/s) Can be a numpy array or a number or None (default=None). @param [in] obs_metadata is an ObservationMetaData object describing the telescope pointing. @param [in] epoch is the julian epoch (in years) against which the mean equinoxes are measured. @param [in] includeRefraction toggles whether or not to correct for refraction @param [out] a 2-D numpy array in which the first row is the observed RA and the second row is the observed Dec (both in degrees) """ if pm_ra is not None: pm_ra_in = radiansFromArcsec(pm_ra) else: pm_ra_in = None if pm_dec is not None: pm_dec_in = radiansFromArcsec(pm_dec) else: pm_dec_in = None if parallax is not None: parallax_in = radiansFromArcsec(parallax) else: parallax_in = None output = _observedFromICRS(np.radians(ra), np.radians(dec), pm_ra=pm_ra_in, pm_dec=pm_dec_in, parallax=parallax_in, v_rad=v_rad, obs_metadata=obs_metadata, epoch=epoch, includeRefraction=includeRefraction) return np.degrees(output)
def test_appGeoFromICRS(self): """ Test conversion between ICRS RA, Dec and apparent geocentric ICRS. Apparent, geocentric RA, Dec of objects will be taken from this website http://aa.usno.navy.mil/data/docs/geocentric.php dates converted to JD using this website http://aa.usno.navy.mil/data/docs/geocentric.php """ hours = numpy.radians(360.0/24.0) minutes = hours/60.0 seconds = minutes/60.0 # test on Arcturus # data taken from # http://aa.usno.navy.mil/data/docs/geocentric.php ra_icrs = 14.0*hours + 15.0*minutes + 39.67207*seconds dec_icrs = numpy.radians(19.0 + 10.0/60.0 + 56.673/3600.0) pm_ra = radiansFromArcsec(-1.0939) pm_dec = radiansFromArcsec(-2.00006) v_rad = -5.19 px = radiansFromArcsec(0.08883) mjd_list = [] ra_app_list = [] dec_app_list = [] #jd (UT) jd = 2457000.375000 mjd = jd-2400000.5 mjd_list.append(mjd) ra_app_list.append(14.0*hours + 16.0*minutes + 19.59*seconds) dec_app_list.append(numpy.radians(19.0 + 6.0/60.0 + 19.56/3600.0)) jd = 2457187.208333 mjd = jd-2400000.5 mjd_list.append(mjd) ra_app_list.append(14.0*hours + 16.0*minutes + 22.807*seconds) dec_app_list.append(numpy.radians(19.0+6.0/60.0+18.12/3600.0)) jd = 2457472.625000 mjd = jd-2400000.5 mjd_list.append(mjd) ra_app_list.append(14.0*hours + 16.0*minutes + 24.946*seconds) dec_app_list.append(numpy.radians(19.0 + 5.0/60.0 + 49.65/3600.0)) for mjd, ra_app, dec_app in zip(mjd_list, ra_app_list, dec_app_list): obs = ObservationMetaData(mjd=mjd) ra_test, dec_test = _appGeoFromICRS(numpy.array([ra_icrs]), numpy.array([dec_icrs]), mjd=obs.mjd, pm_ra=numpy.array([pm_ra]), pm_dec=numpy.array([pm_dec]), v_rad=numpy.array([v_rad]), parallax=numpy.array([px]), epoch=2000.0) distance = arcsecFromRadians(haversine(ra_app, dec_app, ra_test[0], dec_test[0])) self.assertLess(distance, 0.1) # test on Sirius # data taken from # http://simbad.u-strasbg.fr/simbad/sim-id?Ident=Sirius ra_icrs = 6.0*hours + 45.0*minutes + 8.91728*seconds dec_icrs = numpy.radians(-16.0 - 42.0/60.0 -58.0171/3600.0) pm_ra = radiansFromArcsec(-0.54601) pm_dec = radiansFromArcsec(-1.22307) px = radiansFromArcsec(0.37921) v_rad = -5.5 mjd_list = [] ra_app_list = [] dec_app_list = [] jd = 2457247.000000 mjd_list.append(jd-2400000.5) ra_app_list.append(6.0*hours + 45.0*minutes + 49.276*seconds) dec_app_list.append(numpy.radians(-16.0 - 44.0/60.0 - 18.69/3600.0)) jd = 2456983.958333 mjd_list.append(jd-2400000.5) ra_app_list.append(6.0*hours + 45.0*minutes + 49.635*seconds) dec_app_list.append(numpy.radians(-16.0 - 44.0/60.0 - 17.04/3600.0)) jd = 2457523.958333 mjd_list.append(jd-2400000.5) ra_app_list.append(6.0*hours + 45.0*minutes + 50.99*seconds) dec_app_list.append(numpy.radians(-16.0 - 44.0/60.0 - 39.76/3600.0)) for mjd, ra_app, dec_app in zip(mjd_list, ra_app_list, dec_app_list): obs = ObservationMetaData(mjd=mjd) ra_test, dec_test = _appGeoFromICRS(numpy.array([ra_icrs]), numpy.array([dec_icrs]), mjd=obs.mjd, pm_ra=numpy.array([pm_ra]), pm_dec=numpy.array([pm_dec]), v_rad=numpy.array([v_rad]), parallax=numpy.array([px]), epoch=2000.0) distance = arcsecFromRadians(haversine(ra_app, dec_app, ra_test[0], dec_test[0])) self.assertLess(distance, 0.1)
def testPlacement(self): """ Test that GalSimInterpreter puts objects on the right detectors. Do so by creating a catalog of 10 closely-packed stars. Draw test FITS images of them using the GalSim Catalog infrastructure. Draw control FITS images of the detectors in the camera, paranoidly including every star in every control image (GalSim contains code such that it will not actually add flux to an image in cases where we try to include a star that does not actually fall on a detector). Compare that a) the fluxes of the test and control images agree within some tolerance b) the fluxes of control images that have no corresponding test image (i.e. detectors on which no star actually fell) are effectively zero """ #generate the database numpy.random.seed(32) catSize = 10 dbName = 'galSimPlacementTestDB.db' driver = 'sqlite' if os.path.exists(dbName): os.unlink(dbName) displacedRA = (-40.0 + numpy.random.sample(catSize)*(120.0))/3600.0 displacedDec = (-20.0 + numpy.random.sample(catSize)*(80.0))/3600.0 obs_metadata = makePhoSimTestDB(filename=dbName, displacedRA=displacedRA, displacedDec=displacedDec, bandpass=self.bandpassNameList, m5=self.m5, seeing=self.seeing) catName = 'testPlacementCat.sav' stars = testStarsDBObj(driver=driver, database=dbName) #create the catalog cat = testStarCatalog(stars, obs_metadata = obs_metadata) results = cat.iter_catalog() firstLine = True #iterate over the catalog, giving every star a chance to #illumine every detector controlImages = {} for i, line in enumerate(results): galSimType = line[0] xPupil = line[5] yPupil = line[6] majorAxis = line[8] minorAxis = line[9] sindex = line[10] halfLightRadius = line[11] positionAngle = line[12] if firstLine: sedList = cat._calculateGalSimSeds() for detector in cat.galSimInterpreter.detectors: for bandpass in cat.galSimInterpreter.bandpasses: controlImages['placementControl_' + \ cat.galSimInterpreter._getFileName(detector=detector, bandpassName=bandpass)] = \ cat.galSimInterpreter.blankImage(detector=detector) firstLine = False spectrum = galsim.SED(spec=lambda ll: numpy.interp(ll, sedList[i].wavelen, sedList[i].flambda), flux_type='flambda') for bp in cat.galSimInterpreter.bandpasses: bandpass = cat.galSimInterpreter.bandpasses[bp] for detector in cat.galSimInterpreter.detectors: centeredObj = cat.galSimInterpreter.PSF.applyPSF(xPupil=xPupil, yPupil=yPupil, bandpass=bandpass) xPix, yPix = pixelCoordsFromPupilCoords(numpy.array([radiansFromArcsec(xPupil)]), numpy.array([radiansFromArcsec(yPupil)]), chipNames = [detector.name], camera = detector.afwCamera) dx = xPix[0] - detector.xCenterPix dy = yPix[0] - detector.yCenterPix obj = centeredObj*spectrum localImage = cat.galSimInterpreter.blankImage(detector=detector) localImage = obj.drawImage(bandpass=bandpass, wcs=detector.wcs, method='phot', gain=detector.photParams.gain, image=localImage, offset=galsim.PositionD(dx, dy)) controlImages['placementControl_' + \ cat.galSimInterpreter._getFileName(detector=detector, bandpassName=bp)] += \ localImage for name in controlImages: controlImages[name].write(file_name=name) #write the test images using the catalog infrastructure testNames = cat.write_images(nameRoot='placementTest') #make sure that every test image has a corresponding control image for testName in testNames: controlName = testName.replace('Test', 'Control') msg = '%s has no counterpart ' % testName self.assertTrue(controlName in controlImages, msg=msg) #make sure that the test and control images agree to some tolerance ignored = 0 zeroFlux = 0 for controlName in controlImages: controlImage = afwImage.ImageF(controlName) controlFlux = controlImage.getArray().sum() testName = controlName.replace('Control', 'Test') if testName in testNames: testImage = afwImage.ImageF(testName) testFlux = testImage.getArray().sum() msg = '%s: controlFlux = %e, testFlux = %e' % (controlName, controlFlux, testFlux) if controlFlux>1000.0: #the randomness of photon shooting means that faint images won't agree self.assertTrue(numpy.abs(controlFlux/testFlux - 1.0)<0.1, msg=msg) else: ignored += 1 else: #make sure that controlImages that have no corresponding test image really do #have zero flux (because no star fell on them) zeroFlux += 1 msg = '%s has flux %e but was not written by catalog' % (controlName, controlFlux) self.assertTrue(controlFlux<1.0, msg=msg) self.assertTrue(ignored<len(testNames)/2) self.assertTrue(zeroFlux>0) for testName in testNames: if os.path.exists(testName): os.unlink(testName) for controlName in controlImages: if os.path.exists(controlName): os.unlink(controlName) if os.path.exists(dbName): os.unlink(dbName)
def testPlacement(self): """ Test that GalSimInterpreter puts objects on the right detectors. Do so by creating a catalog of 3 closely-packed stars. Draw test FITS images of them using the GalSim Catalog infrastructure. Draw control FITS images of the detectors in the camera, paranoidly including every star in every control image (GalSim contains code such that it will not actually add flux to an image in cases where we try to include a star that does not actually fall on a detector). Compare that a) the fluxes of the test and control images agree within some tolerance b) the fluxes of control images that have no corresponding test image (i.e. detectors on which no star actually fell) are effectively zero """ # generate the database np_rng = np.random.RandomState(32) gs_rng = galsim.UniformDeviate(112) catSize = 3 dbName = 'galSimPlacementTestDB.db' driver = 'sqlite' if os.path.exists(dbName): os.unlink(dbName) deltaRA = (-40.0 + np_rng.random_sample(catSize) * (120.0)) / 3600.0 deltaDec = (-20.0 + np_rng.random_sample(catSize) * (80.0)) / 3600.0 obs_metadata = makePhoSimTestDB(filename=dbName, deltaRA=deltaRA, deltaDec=deltaDec, bandpass=self.bandpassNameList, m5=self.m5, seeing=self.seeing) stars = testStarsDBObj(driver=driver, database=dbName) # create the catalog cat = testStarCatalog(stars, obs_metadata=obs_metadata) results = cat.iter_catalog() firstLine = True # iterate over the catalog, giving every star a chance to # illumine every detector controlImages = {} for i, line in enumerate(results): xPupil = line[5] yPupil = line[6] if firstLine: sedList = list(cat._calculateGalSimSeds()) for detector in cat.galSimInterpreter.detectors: for bandpass in cat.galSimInterpreter.bandpassDict: controlImages['placementControl_' + cat.galSimInterpreter._getFileName(detector=detector, bandpassName=bandpass)] = \ cat.galSimInterpreter.blankImage(detector=detector) firstLine = False for bp in cat.galSimInterpreter.bandpassDict: bandpass = cat.galSimInterpreter.bandpassDict[bp] adu = sedList[i].calcADU(bandpass, cat.photParams) for detector in cat.galSimInterpreter.detectors: centeredObj = cat.galSimInterpreter.PSF.applyPSF( xPupil=xPupil, yPupil=yPupil) xPix, yPix = pixelCoordsFromPupilCoords( radiansFromArcsec(xPupil), radiansFromArcsec(yPupil), chipName=detector.name, camera=detector.afwCamera) dx = xPix - detector.xCenterPix dy = yPix - detector.yCenterPix obj = centeredObj.withFlux(adu * detector.photParams.gain) localImage = cat.galSimInterpreter.blankImage( detector=detector) localImage = obj.drawImage(wcs=detector.wcs, method='phot', gain=detector.photParams.gain, image=localImage, offset=galsim.PositionD(dx, dy), rng=gs_rng) controlImages[ 'placementControl_' + cat.galSimInterpreter._getFileName( detector=detector, bandpassName=bp)] += localImage self.assertGreater(len(controlImages), 0) for name in controlImages: controlImages[name].write(file_name=name) # write the test images using the catalog infrastructure testNames = cat.write_images(nameRoot='placementTest') # make sure that every test image has a corresponding control image for testName in testNames: controlName = testName.replace('Test', 'Control') msg = '%s has no counterpart ' % testName self.assertIn(controlName, controlImages, msg=msg) # make sure that the test and control images agree to some tolerance ignored = 0 zeroFlux = 0 valid = 0 for controlName in controlImages: controlImage = afwImage.ImageF(controlName) controlFlux = controlImage.getArray().sum() testName = controlName.replace('Control', 'Test') if testName in testNames: testImage = afwImage.ImageF(testName) testFlux = testImage.getArray().sum() if controlFlux > 1000.0: countSigma = np.sqrt(controlFlux / cat.photParams.gain) msg = '%s: controlFlux = %e, testFlux = %e, sigma %e' \ % (controlName, controlFlux, testFlux, countSigma) # the randomness of photon shooting means that faint images won't agree self.assertLess(np.abs(controlFlux - testFlux), 4.0 * countSigma, msg=msg) valid += 1 else: ignored += 1 else: # make sure that controlImages that have no corresponding test image really do # have zero flux (because no star fell on them) zeroFlux += 1 msg = '%s has flux %e but was not written by catalog' % ( controlName, controlFlux) self.assertLess(controlFlux, 1.0, msg=msg) self.assertGreater(valid, 0) self.assertLess(ignored, len(testNames) / 2) self.assertGreater(zeroFlux, 0) for testName in testNames: if os.path.exists(testName): os.unlink(testName) for controlName in controlImages: if os.path.exists(controlName): os.unlink(controlName) if os.path.exists(dbName): os.unlink(dbName)
def _make_gs_object(self, object_line, x_pupil, y_pupil): params = object_line.strip().split() unique_id = params[1] ra_phosim = float(params[2]) dec_phosim = float(params[3]) mag_norm = float(params[4]) sed_name = params[5] redshift = float(params[6]) gamma1 = float(params[7]) gamma2 = self.gamma2_sign * float(params[8]) kappa = float(params[9]) internal_av = 0 internal_rv = 0 galactic_av = 0 galactic_rv = 0 fits_file = None pixel_scale = 0 rotation_angle = 0 npoints = 0 semi_major_arcsec = 0 semi_minor_arcsec = 0 position_angle_degrees = 0 sersic_index = 0 if params[12].lower() == 'point': gs_type = 'pointSource' i_gal_dust_model = 14 if params[13].lower() != 'none': i_gal_dust_model = 16 internal_av = float(params[14]) internal_rv = float(params[15]) if params[i_gal_dust_model].lower() != 'none': galactic_av = float(params[i_gal_dust_model + 1]) galactic_rv = float(params[i_gal_dust_model + 2]) elif params[12].lower() == 'sersic2d': gs_type = 'sersic' semi_major_arcsec = float(params[13]) semi_minor_arcsec = float(params[14]) position_angle_degrees = float(params[15]) sersic_index = float(params[16]) i_gal_dust_model = 18 if params[17].lower() != 'none': i_gal_dust_model = 20 internal_av = float(params[18]) internal_rv = float(params[19]) if params[i_gal_dust_model].lower() != 'none': galactic_av = float(params[i_gal_dust_model + 1]) galactic_rv = float(params[i_gal_dust_model + 2]) elif params[12].lower() == 'knots': gs_type = 'RandomWalk' semi_major_arcsec = float(params[13]) semi_minor_arcsec = float(params[14]) position_angle_degrees = float(params[15]) npoints = int(params[16]) i_gal_dust_model = 18 if params[17].lower() != 'none': i_gal_dust_model = 20 internal_av = float(params[18]) internal_rv = float(params[19]) if params[i_gal_dust_model].lower() != 'none': galactic_av = float(params[i_gal_dust_model + 1]) galactic_rv = float(params[i_gal_dust_model + 2]) elif (params[12].endswith('.fits') or params[12].endswith('.fits.gz')): gs_type = 'FitsImage' fits_file = find_file_path(params[12], get_image_dirs()) pixel_scale = float(params[13]) rotation_angle = float(params[14]) i_gal_dust_model = 16 if params[15].lower() != 'none': i_gal_dust_model = 18 internal_av = float(params[16]) internal_rv = float(params[17]) if params[i_gal_dust_model].lower() != 'none': galactic_av = float(params[i_gal_dust_model + 1]) galactic_rv = float(params[i_gal_dust_model + 2]) else: raise RuntimeError("Do not know how to handle " "object type: %s" % params[12]) object_is_valid = (mag_norm < 50.0 and (galactic_av != 0 or galactic_rv != 0) and not (gs_type == 'sersic' and semi_major_arcsec < semi_minor_arcsec) and not (gs_type == 'RandomWalk' and npoints <= 0)) if not object_is_valid: return None sed_obj = SedWrapper(find_file_path(sed_name, self.sed_dirs), mag_norm, redshift, internal_av, internal_rv, galactic_av, galactic_rv, self.bp_dict) position_angle_radians = np.radians(360 - position_angle_degrees) gs_object = GalSimCelestialObject(gs_type, x_pupil, y_pupil, radiansFromArcsec(semi_major_arcsec), radiansFromArcsec(semi_minor_arcsec), radiansFromArcsec(semi_major_arcsec), position_angle_radians, sersic_index, sed_obj, self.bp_dict, self.phot_params, npoints, fits_file, pixel_scale, rotation_angle, gamma1=gamma1, gamma2=gamma2, kappa=kappa, uniqueId=unique_id) return gs_object
def test_different_cameras(self): rng = np.random.RandomState(6512) pointing_ra = 15.0 pointing_dec = 13.0 n_obj = 100 ra_list = pointing_ra + 2.0 * rng.random_sample(n_obj) dec_list = pointing_dec + 2.0 * rng.random_sample(n_obj) px_list = radiansFromArcsec(0.005) * rng.random_sample(n_obj) px_list += radiansFromArcsec(0.001) mura_list = radiansFromArcsec(0.005) * rng.random_sample(n_obj) mudec_list = radiansFromArcsec(0.005) * rng.random_sample(n_obj) vrad_list = 100.0 * rng.random_sample(n_obj) with lsst.utils.tests.getTempFilePath('.txt') as db_text_file: with open(db_text_file, 'w') as out_file: for ix, (rdeg, ddeg, rrad, drad, px, mura, mudec, vrad) in \ enumerate(zip(ra_list, dec_list, np.radians(ra_list), np.radians(dec_list), px_list, mura_list, mudec_list, vrad_list)): out_file.write( '%d %e %e %e %e %e %e %e %e\n' % (ix, rdeg, ddeg, rrad, drad, px, mura, mudec, vrad)) dtype = np.dtype([('id', int), ('raDeg', float), ('decDeg', float), ('raJ2000', float), ('decJ2000', float), ('parallax', float), ('properMotionRa', float), ('properMotionDec', float), ('radialVelocity', float)]) db = fileDBObject(db_text_file, dtype=dtype, idColKey='id') db.raColName = 'raDeg' db.decColName = 'decDeg' class CameraCoordsCatalog(AstrometryStars, CameraCoords, InstanceCatalog): camera = LsstSimMapper().camera column_outputs = ['id', 'chipName'] class CameraCoordsLSSTCatalog(AstrometryStars, CameraCoordsLSST, InstanceCatalog): column_outputs = ['id', 'chipName'] obs = ObservationMetaData(pointingRA=pointing_ra, pointingDec=pointing_dec, boundLength=1.75, boundType='circle', rotSkyPos=23.0, mjd=59580.0) control_cat = CameraCoordsCatalog(db, obs_metadata=obs) test_cat = CameraCoordsLSSTCatalog(db, obs_metadata=obs) control_line_list = [] none_chips = 0 for line in control_cat.iter_catalog(): if line[1] is None: none_chips += 1 control_line_list.append(line) self.assertGreater(len(control_line_list), 0) self.assertLess(none_chips, len(control_line_list) / 2) line_ct = 0 for line in test_cat.iter_catalog(): line_ct += 1 self.assertIn(line, control_line_list) self.assertEqual(line_ct, len(control_line_list))
frac = find_fraction_flare_active(prob_vec, np.abs(xyz[2])) draws = rng.random_sample(len(frac)) activity_level = ['active' if dd<ff else 'inactive' for ff, dd in zip(frac, draws)] type_dict = {} for ii in range(3): type_dict['M%d' % ii] = 'early' for ii in range(3,6): type_dict['M%d' % ii] = 'mid' for ii in range(6,9): type_dict['M%d' % ii] = 'late' from lsst.sims.utils import radiansFromArcsec dd = _au_to_parsec/radiansFromArcsec(data['parallax']*0.001) from lsst.sims.photUtils import PhotometricParameters params = PhotometricParameters() # divide the effective area of the LSST mirror by the sphere # through which the flare is radiating (3.08576e18 is a parsec # in cm) flux_factor = params.effarea/(4.0*np.pi*np.power(dd*3.08576e18, 2)) types_simulated = [] du = [] dg = [] dr = [] di = [] dz = []
def pixelCoordsFromRaDec(self, ra, dec, pm_ra=None, pm_dec=None, parallax=None, v_rad=None, obs_metadata=None, chipName=None, epoch=2000.0, includeDistortion=True): """ Get the pixel positions (or nan if not on a chip) for objects based on their RA, and Dec (in degrees) Parameters ---------- ra is in degrees in the International Celestial Reference System. Can be either a float or a numpy array. dec is in degrees in the International Celestial Reference System. Can be either a float or a numpy array. pm_ra is proper motion in RA multiplied by cos(Dec) (arcsec/yr) Can be a numpy array or a number or None (default=None). pm_dec is proper motion in dec (arcsec/yr) Can be a numpy array or a number or None (default=None). parallax is parallax in arcsec Can be a numpy array or a number or None (default=None). v_rad is radial velocity (km/s) Can be a numpy array or a number or None (default=None). obs_metadata is an ObservationMetaData characterizing the telescope pointing. epoch is the epoch in Julian years of the equinox against which RA is measured. Default is 2000. chipName designates the names of the chips on which the pixel coordinates will be reckoned. Can be either single value, an array, or None. If an array, there must be as many chipNames as there are (RA, Dec) pairs. If a single value, all of the pixel coordinates will be reckoned on the same chip. If None, this method will calculate which chip each(RA, Dec) pair actually falls on, and return pixel coordinates for each (RA, Dec) pair on the appropriate chip. Default is None. includeDistortion is a boolean. If True (default), then this method will return the true pixel coordinates with optical distortion included. If False, this method will return TAN_PIXEL coordinates, which are the pixel coordinates with estimated optical distortion removed. See the documentation in afw.cameraGeom for more details. Returns ------- a 2-D numpy array in which the first row is the x pixel coordinate and the second row is the y pixel coordinate. These pixel coordinates are defined in the Camera team system, rather than the DM system. """ if pm_ra is not None: pm_ra_out = simsUtils.radiansFromArcsec(pm_ra) else: pm_ra_out = None if pm_dec is not None: pm_dec_out = simsUtils.radiansFromArcsec(pm_dec) else: pm_dec_out = None if parallax is not None: parallax_out = simsUtils.radiansFromArcsec(parallax) else: parallax_out = None return self._pixelCoordsFromRaDec(np.radians(ra), np.radians(dec), pm_ra=pm_ra_out, pm_dec=pm_dec_out, parallax=parallax_out, v_rad=v_rad, chipName=chipName, obs_metadata=obs_metadata, epoch=2000.0, includeDistortion=includeDistortion)
def testPlacement(self): """ Test that GalSimInterpreter puts objects on the right detectors. Do so by creating a catalog of 3 closely-packed stars. Draw test FITS images of them using the GalSim Catalog infrastructure. Draw control FITS images of the detectors in the camera, paranoidly including every star in every control image (GalSim contains code such that it will not actually add flux to an image in cases where we try to include a star that does not actually fall on a detector). Compare that a) the fluxes of the test and control images agree within some tolerance b) the fluxes of control images that have no corresponding test image (i.e. detectors on which no star actually fell) are effectively zero """ # generate the database np_rng = np.random.RandomState(32) gs_rng = galsim.UniformDeviate(112) catSize = 3 dbName = "galSimPlacementTestDB.db" driver = "sqlite" if os.path.exists(dbName): os.unlink(dbName) deltaRA = (-40.0 + np_rng.random_sample(catSize) * (120.0)) / 3600.0 deltaDec = (-20.0 + np_rng.random_sample(catSize) * (80.0)) / 3600.0 obs_metadata = makePhoSimTestDB( filename=dbName, deltaRA=deltaRA, deltaDec=deltaDec, bandpass=self.bandpassNameList, m5=self.m5, seeing=self.seeing, ) stars = testStarsDBObj(driver=driver, database=dbName) # create the catalog cat = testStarCatalog(stars, obs_metadata=obs_metadata) results = cat.iter_catalog() firstLine = True # iterate over the catalog, giving every star a chance to # illumine every detector controlImages = {} for i, line in enumerate(results): xPupil = line[5] yPupil = line[6] if firstLine: sedList = list(cat._calculateGalSimSeds()) for detector in cat.galSimInterpreter.detectors: for bandpass in cat.galSimInterpreter.bandpassDict: controlImages[ "placementControl_" + cat.galSimInterpreter._getFileName(detector=detector, bandpassName=bandpass) ] = cat.galSimInterpreter.blankImage(detector=detector) firstLine = False for bp in cat.galSimInterpreter.bandpassDict: bandpass = cat.galSimInterpreter.bandpassDict[bp] adu = sedList[i].calcADU(bandpass, cat.photParams) for detector in cat.galSimInterpreter.detectors: centeredObj = cat.galSimInterpreter.PSF.applyPSF(xPupil=xPupil, yPupil=yPupil) xPix, yPix = pixelCoordsFromPupilCoords( radiansFromArcsec(xPupil), radiansFromArcsec(yPupil), chipName=detector.name, camera=detector.afwCamera, ) dx = xPix - detector.xCenterPix dy = yPix - detector.yCenterPix obj = centeredObj.withFlux(adu * detector.photParams.gain) localImage = cat.galSimInterpreter.blankImage(detector=detector) localImage = obj.drawImage( wcs=detector.wcs, method="phot", gain=detector.photParams.gain, image=localImage, offset=galsim.PositionD(dx, dy), rng=gs_rng, ) controlImages[ "placementControl_" + cat.galSimInterpreter._getFileName(detector=detector, bandpassName=bp) ] += localImage self.assertGreater(len(controlImages), 0) for name in controlImages: controlImages[name].write(file_name=name) # write the test images using the catalog infrastructure testNames = cat.write_images(nameRoot="placementTest") # make sure that every test image has a corresponding control image for testName in testNames: controlName = testName.replace("Test", "Control") msg = "%s has no counterpart " % testName self.assertIn(controlName, controlImages, msg=msg) # make sure that the test and control images agree to some tolerance ignored = 0 zeroFlux = 0 valid = 0 for controlName in controlImages: controlImage = afwImage.ImageF(controlName) controlFlux = controlImage.getArray().sum() testName = controlName.replace("Control", "Test") if testName in testNames: testImage = afwImage.ImageF(testName) testFlux = testImage.getArray().sum() if controlFlux > 1000.0: countSigma = np.sqrt(controlFlux / cat.photParams.gain) msg = "%s: controlFlux = %e, testFlux = %e, sigma %e" % ( controlName, controlFlux, testFlux, countSigma, ) # the randomness of photon shooting means that faint images won't agree self.assertLess(np.abs(controlFlux - testFlux), 4.0 * countSigma, msg=msg) valid += 1 else: ignored += 1 else: # make sure that controlImages that have no corresponding test image really do # have zero flux (because no star fell on them) zeroFlux += 1 msg = "%s has flux %e but was not written by catalog" % (controlName, controlFlux) self.assertLess(controlFlux, 1.0, msg=msg) self.assertGreater(valid, 0) self.assertLess(ignored, len(testNames) / 2) self.assertGreater(zeroFlux, 0) for testName in testNames: if os.path.exists(testName): os.unlink(testName) for controlName in controlImages: if os.path.exists(controlName): os.unlink(controlName) if os.path.exists(dbName): os.unlink(dbName)