def test_SNRdocumentPSF(self): fwhm_in = 0.3 pixel_scale = 0.2 psf_gen = SNRdocumentPSF(fwhm=fwhm_in, pixel_scale=pixel_scale) psf = psf_gen._getPSF() image = galsim.ImageD(256, 256, scale=pixel_scale) image = psf.drawImage(image) self.verify_analytic_fwhm(fwhm_in, pixel_scale, image.array)
class testGalSimStars(GalSimStars): #only draw images in the u and g band for speed bandpassNames = ['u','g'] #convolve with a PSF; note that galaxies are not convolved with a PSF #PSF defined in galSimInterface/galSimUtilities.py PSF = SNRdocumentPSF()
def __init__(self, obs_md, seed, nxy=64, pixel_scale=0.2): self.psf = SNRdocumentPSF(obs_md.OpsimMetaData['FWHMgeom']) self._rng = galsim.UniformDeviate(seed) self.nxy = nxy self.pixel_scale = pixel_scale fratio = 1.234 obscuration = 0.606 angles = galsim.FRatioAngles(fratio, obscuration, self._rng) self.bandpass = gs_bandpasses(obs_md.bandpass) self.sed = galsim.SED(lambda x: 1, 'nm', 'flambda').withFlux(1., self.bandpass) waves = galsim.WavelengthSampler(sed=self.sed, bandpass=self.bandpass, rng=self._rng) self.surface_ops = (waves, angles)
def testFwhmOfImage(self): """ Test that GalSim generates images with the expected Full Width at Half Maximum. """ scratchDir = tempfile.mkdtemp(dir=ROOT, prefix='testFwhmOfImage-') catName = os.path.join(scratchDir, 'fwhm_test_Catalog.dat') imageRoot = os.path.join(scratchDir, 'fwhm_test_Image') dbFileName = os.path.join(scratchDir, 'fwhm_test_InputCatalog.dat') baseDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'cameraData') # instantiate a test camera with pixel_scale = 0.02 arcsec/pixel camera = ReturnCamera(baseDir) detector = camera[0] detName = detector.getName() imageName = '%s_%s_u.fits' % (imageRoot, detName) obs = ObservationMetaData(pointingRA=75.0, pointingDec=-12.0, boundType='circle', boundLength=4.0, rotSkyPos=33.0, mjd=49250.0) create_text_catalog(obs, dbFileName, np.array([3.0]), np.array([1.0]), mag_norm=[13.0]) db = fwhmFileDBObj(dbFileName, runtable='test') for fwhm in (0.1, 0.14): cat = fwhmCat(db, obs_metadata=obs) cat.camera_wrapper = GalSimCameraWrapper(camera) psf = SNRdocumentPSF(fwhm=fwhm, pixel_scale=0.02) cat.setPSF(psf) cat.write_catalog(catName) cat.write_images(nameRoot=imageRoot) self.verify_fwhm(imageName, fwhm, 0.02) if os.path.exists(catName): os.unlink(catName) if os.path.exists(imageName): os.unlink(imageName) if os.path.exists(dbFileName): os.unlink(dbFileName) if os.path.exists(scratchDir): shutil.rmtree(scratchDir)
class testGalSimGalaxiesNoiseless(GalSimGalaxies): #only draw images for u and g bands (for speed) bandpassNames = ['u', 'g'] #If you want to use the LSST camera, uncomment the line below. #You can similarly assign any camera object you want here #camera = LsstSimMapper().camera PSF = SNRdocumentPSF()
def make_psf(psf_name, obs_md, log_level='WARN', rng=None, **kwds): """ Make the requested PSF object. Parameters ---------- psf_name: str Either "DoubleGaussian", "Kolmogorov", or "Atmospheric". The name is case-insensitive. obs_md: lsst.sims.utils.ObservationMetaData Metadata associated with the visit, e.g., pointing direction, observation time, seeing, etc.. log_level: str ['WARN'] Logging level ('DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL'). rng: galsim.BaseDeviate Instance of the galsim.baseDeviate random number generator. **kwds: **dict Additional keyword arguments to pass to the AtmosphericPSF, i.e., screen_size(=819.2) and screen_scale(=0.1). Returns ------- lsst.sims.GalSimInterface.PSFbase: Instance of a subclass of PSFbase. """ if psf_name.lower() == 'doublegaussian': return SNRdocumentPSF(obs_md.OpsimMetaData['FWHMgeom']) rawSeeing = obs_md.OpsimMetaData['rawSeeing'] my_airmass = airmass(obs_md.OpsimMetaData['altitude']) if psf_name.lower() == 'kolmogorov': psf = Kolmogorov_and_Gaussian_PSF(my_airmass, rawSeeing=rawSeeing, band=obs_md.bandpass) elif psf_name.lower() == 'atmospheric': if rng is None: # Use the 'seed' value from the instance catalog for the rng # used by the atmospheric PSF. rng = galsim.UniformDeviate(obs_md.OpsimMetaData['seed']) if 'gaussianFWHM' not in kwds: # Retrieve the additional instrumental PSF FWHM from the # imSim config file. config = get_config() kwds['gaussianFWHM'] = config['psf']['gaussianFWHM'] logger = get_logger(log_level, 'psf') psf = AtmosphericPSF(airmass=my_airmass, rawSeeing=rawSeeing, band=obs_md.bandpass, rng=rng, logger=logger, **kwds) return psf
def testPSF(self): """ This method will test that SNRdocumentPSF returns a PSF with the correct Full Width at Half Max """ fwhm = 0.4 # in arc-seconds; make sure that it divides evenly by scale, so that rounding # half integer numbers of pixels does not affect the unit test scale = 0.1 # arc-seconds per pixel psf = SNRdocumentPSF(fwhm=fwhm) image = psf._cached_psf.drawImage(scale=scale) xCenter = (image.getXMax() + image.getXMin()) / 2 yCenter = (image.getYMax() + image.getYMin()) / 2 maxValue = image(xCenter, yCenter) # because the default is to center GSObjects halfDex = int(np.round( 0.5 * fwhm / scale)) # the distance from the center corresponding to FWHM # Test that pixel combinations bracketing the expected FWHM value behave # the way we expect them to midP1 = image(xCenter + halfDex + 1, yCenter) midM1 = image(xCenter + halfDex - 1, yCenter) msg = '%e is not > %e ' % (midM1, 0.5 * maxValue) self.assertGreater(midM1, 0.5 * maxValue, msg=msg) msg = '%e is not < %e ' % (midP1, 0.5 * maxValue) self.assertLess(midP1, 0.5 * maxValue, msg=msg) midP1 = image(xCenter - halfDex - 1, yCenter) midM1 = image(xCenter - halfDex + 1, yCenter) msg = '%e is not > %e ' % (midM1, 0.5 * maxValue) self.assertGreater(midM1, 0.5 * maxValue, msg=msg) msg = '%e is not < %e ' % (midP1, 0.5 * maxValue) self.assertLess(midP1, 0.5 * maxValue, msg=msg) midP1 = image(xCenter, yCenter + halfDex + 1) midM1 = image(xCenter, yCenter + halfDex - 1) msg = '%e is not > %e ' % (midM1, 0.5 * maxValue) self.assertGreater(midM1, 0.5 * maxValue, msg=msg) msg = '%e is not < %e ' % (midP1, 0.5 * maxValue) self.assertLess(midP1, 0.5 * maxValue, msg=msg) midP1 = image(xCenter, yCenter - halfDex - 1) midM1 = image(xCenter, yCenter - halfDex + 1) msg = '%e is not > %e ' % (midM1, 0.5 * maxValue) self.assertGreater(midM1, 0.5 * maxValue, msg=msg) msg = '%e is not < %e ' % (midP1, 0.5 * maxValue) self.assertLess(midP1, 0.5 * maxValue, msg=msg)
def __init__(self, obs_metadata=None, detectors=None, bandpassDict=None, noiseWrapper=None, epoch=None, seed=None, bf_strength=1): super(GalSimSiliconInterpeter, self)\ .__init__(obs_metadata=obs_metadata, detectors=detectors, bandpassDict=bandpassDict, noiseWrapper=noiseWrapper, epoch=epoch, seed=seed) self.gs_bandpass_dict = {} for bandpassName in bandpassDict: bandpass = bandpassDict[bandpassName] index = np.where(bandpass.sb != 0) bp_lut = galsim.LookupTable(x=bandpass.wavelen[index], f=bandpass.sb[index]) self.gs_bandpass_dict[bandpassName] \ = galsim.Bandpass(bp_lut, wave_type='nm') self.sky_bg_per_pixel = None # Create a PSF that's fast to evaluate for the postage stamp # size calculation for extended objects in .getStampBounds. FWHMgeom = obs_metadata.OpsimMetaData['FWHMgeom'] self._double_gaussian_psf = SNRdocumentPSF(FWHMgeom) # Save the parameters needed to create a Kolmogorov PSF for a # custom value of gsparams.folding_threshold. That PSF will # to be used in the .getStampBounds function for bright stars. altRad = np.radians(obs_metadata.OpsimMetaData['altitude']) self._airmass = 1.0/np.sqrt(1.0-0.96*(np.sin(0.5*np.pi-altRad))**2) self._rawSeeing = obs_metadata.OpsimMetaData['rawSeeing'] self._band = obs_metadata.bandpass # Save the default folding threshold for determining when to recompute # the PSF for bright point sources. self._ft_default = galsim.GSParams().folding_threshold # Create SiliconSensor objects for each detector. self.sensor = dict() for det in detectors: self.sensor[det.name] \ = galsim.SiliconSensor(strength=bf_strength, treering_center=det.tree_rings.center, treering_func=det.tree_rings.func, transpose=True)
class testAgnCatalog(GalSimAgn): """ Wraps the GalSimAgn class. Adds columns to the output so that we can read the InstanceCatalog back in and verify that GalSim put the correct number of ADU in each FITS file. """ bandpassNames = ['u', 'g', 'r'] column_outputs = copy.deepcopy(GalSimAgn.column_outputs) column_outputs.remove('fitsFiles') column_outputs.append('magNorm') column_outputs.append('redshift') column_outputs.append('internalAv') column_outputs.append('internalRv') column_outputs.append('galacticAv') column_outputs.append('galacticRv') column_outputs.append('fitsFiles') PSF = SNRdocumentPSF()
class StarTimer(object): def __init__(self, obs_md, seed, nxy=64, pixel_scale=0.2): self.psf = SNRdocumentPSF(obs_md.OpsimMetaData['FWHMgeom']) self._rng = galsim.UniformDeviate(seed) self.nxy = nxy self.pixel_scale = pixel_scale fratio = 1.234 obscuration = 0.606 angles = galsim.FRatioAngles(fratio, obscuration, self._rng) self.bandpass = gs_bandpasses(obs_md.bandpass) self.sed = galsim.SED(lambda x: 1, 'nm', 'flambda').withFlux(1., self.bandpass) waves = galsim.WavelengthSampler(sed=self.sed, bandpass=self.bandpass, rng=self._rng) self.surface_ops = (waves, angles) def get_sensor(self, nrecalc): return galsim.SiliconSensor(rng=self._rng, nrecalc=nrecalc) def timing(self, flux, sensor=None): point = galsim.DeltaFunction(flux=flux) star = galsim.Convolve(point*self.sed, self.psf._getPSF()) image = galsim.Image(self.nxy, self.nxy) surface_ops = self.surface_ops if sensor is not None else () t0 = time.clock() image = star.drawImage(method='phot', bandpass=self.bandpass, image=image, scale=self.pixel_scale, rng=self._rng, sensor=sensor, surface_ops=surface_ops) return time.clock() - t0 def flux_loop_timing(self, apply_model, nrecalc=10000, flux_min=10, flux_max=1e5, nflux=8): sensor = self.get_sensor(nrecalc) if apply_model else None timing = OrderedDict() for flux in np.logspace(np.log10(flux_min), np.log10(flux_max), nflux): timing[flux] = self.timing(flux, sensor=sensor) return timing
class backgroundCatalog(testGalaxyCatalog): """ Add sky background but no noise to testGalaxyCatalog """ PSF = SNRdocumentPSF() noise_and_background = ExampleCCDNoise(addNoise=False, seed=42)
class testGalSimGalaxies(GalSimGalaxies): bandpassNames = ['u', 'g'] PSF = SNRdocumentPSF()
def testOutputWcsOfImage(self): """ Test that, when GalSim generates an image, in encodes the WCS in a way afw can read. This is done by creating an image,then reading it back in, getting its WCS, and comparing the pixel-to-sky conversion both for the read WCS and the original afw.cameraGeom.detector. Raise an exception if the median difference between the two is greater than 0.01 arcseconds. """ scratchDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'scratchSpace') catName = os.path.join(scratchDir, 'outputWcs_test_Catalog.dat') imageRoot = os.path.join(scratchDir, 'outputWcs_test_Image') dbFileName = os.path.join(scratchDir, 'outputWcs_test_InputCatalog.dat') baseDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'cameraData') camera = ReturnCamera(baseDir) detector = camera[0] detName = detector.getName() imageName = '%s_%s_u.fits' % (imageRoot, detName) nSamples = 3 rng = np.random.RandomState(42) pointingRaList = rng.random_sample(nSamples) * 360.0 pointingDecList = rng.random_sample(nSamples) * 180.0 - 90.0 rotSkyPosList = rng.random_sample(nSamples) * 360.0 for raPointing, decPointing, rotSkyPos in \ zip(pointingRaList, pointingDecList, rotSkyPosList): obs = ObservationMetaData(pointingRA=raPointing, pointingDec=decPointing, boundType='circle', boundLength=4.0, rotSkyPos=rotSkyPos, mjd=49250.0) fwhm = 0.7 create_text_catalog(obs, dbFileName, np.array([3.0]), np.array([1.0])) db = outputWcsFileDBObj(dbFileName, runtable='test') cat = outputWcsCat(db, obs_metadata=obs) cat.camera = camera psf = SNRdocumentPSF(fwhm=fwhm) cat.setPSF(psf) cat.write_catalog(catName) cat.write_images(nameRoot=imageRoot) # 20 March 2017 # the 'try' block is how it worked in SWIG; # the 'except' block is how it works in pybind11 try: exposure = afwImage.ExposureD_readFits(imageName) except AttributeError: exposure = afwImage.ExposureD.readFits(imageName) wcs = exposure.getWcs() xxTestList = [] yyTestList = [] raImage = [] decImage = [] for xx in np.arange(0.0, 4001.0, 100.0): for yy in np.arange(0.0, 4001.0, 100.0): xxTestList.append(xx) yyTestList.append(yy) pt = afwGeom.Point2D(xx, yy) skyPt = wcs.pixelToSky(pt).getPosition() raImage.append(skyPt.getX()) decImage.append(skyPt.getY()) xxTestList = np.array(xxTestList) yyTestList = np.array(yyTestList) raImage = np.radians(np.array(raImage)) decImage = np.radians(np.array(decImage)) raControl, \ decControl = _raDecFromPixelCoords(xxTestList, yyTestList, [detector.getName()]*len(xxTestList), camera=camera, obs_metadata=obs, epoch=2000.0) errorList = arcsecFromRadians( haversine(raControl, decControl, raImage, decImage)) medianError = np.median(errorList) msg = 'medianError was %e' % medianError self.assertLess(medianError, 0.01, msg=msg) if os.path.exists(catName): os.unlink(catName) if os.path.exists(dbFileName): os.unlink(dbFileName) if os.path.exists(imageName): os.unlink(imageName)
def testGalSimPhoSimCat(self): """ Run a GalSimPhoSim catalog on some data. Then, generate an ordinary PhoSim catalog using the same data. Verify that the two resulting PhoSim catalogs are identical. """ galsim_cat_name = os.path.join(self.dataDir, 'galSimPhoSim_galsim_cat.txt') phosim_cat_name = os.path.join(self.dataDir, 'galSimPhoSim_phosim_cat.txt') galsim_image_root = os.path.join(self.dataDir, 'galSimPhoSim_images') db = fileDBObject(self.bulge_name, dtype=self.dtype, runtable='test_bulges', idColKey='id') db.raColName = 'ra_deg' db.decColName = 'dec_deg' db.objectTypeId = 55 gs_cat = GalSimPhoSimGalaxies(db, obs_metadata=self.obs) gs_cat.camera_wrapper = GalSimCameraWrapper(self.camera) gs_cat.bandpassNames = self.obs.bandpass gs_cat.PSF = SNRdocumentPSF() gs_cat.phoSimHeaderMap = {} gs_cat.write_catalog(galsim_cat_name) gs_cat_0 = gs_cat ps_cat = PhoSimCatalogSersic2D(db, obs_metadata=self.obs) ps_cat.phoSimHeaderMap = {} ps_cat.write_catalog(phosim_cat_name) db = fileDBObject(self.disk_name, dtype=self.dtype, runtable='test_disks', idColKey='id') db.raColName = 'ra_deg' db.decColName = 'dec_deg' db.objectTypeId = 155 gs_cat = GalSimPhoSimGalaxies(db, obs_metadata=self.obs) gs_cat.bandpassNames = self.obs.bandpass gs_cat.copyGalSimInterpreter(gs_cat_0) gs_cat.write_catalog(galsim_cat_name, write_header=False, write_mode='a') gs_cat_0 = gs_cat ps_cat = PhoSimCatalogSersic2D(db, obs_metadata=self.obs) ps_cat.write_catalog(phosim_cat_name, write_header=False, write_mode='a') db = fileDBObject(self.agn_name, dtype=self.dtype, runtable='test_agn', idColKey='id') db.raColName = 'ra_deg' db.decColName = 'dec_deg' db.objectTypeId = 255 gs_cat = GalSimPhoSimAgn(db, obs_metadata=self.obs) gs_cat.bandpassNames = self.obs.bandpass gs_cat.copyGalSimInterpreter(gs_cat_0) gs_cat.write_catalog(galsim_cat_name, write_header=False, write_mode='a') gs_cat_0 = gs_cat ps_cat = PhoSimCatalogZPoint(db, obs_metadata=self.obs) ps_cat.write_catalog(phosim_cat_name, write_header=False, write_mode='a') db = fileDBObject(self.star_name, dtype=self.dtype, runtable='test_agn', idColKey='id') db.raColName = 'ra_deg' db.decColName = 'dec_deg' db.objectTypeId = 255 gs_cat = GalSimPhoSimStars(db, obs_metadata=self.obs) gs_cat.bandpassNames = self.obs.bandpass gs_cat.copyGalSimInterpreter(gs_cat_0) gs_cat.write_catalog(galsim_cat_name, write_header=False, write_mode='a') ps_cat = PhoSimCatalogPoint(db, obs_metadata=self.obs) ps_cat.write_catalog(phosim_cat_name, write_header=False, write_mode='a') written_files = gs_cat.write_images(nameRoot=galsim_image_root) self.assertGreater(len(written_files), 0) for name in written_files: os.unlink(name) with open(galsim_cat_name, 'r') as galsim_input: with open(phosim_cat_name, 'r') as phosim_input: galsim_lines = galsim_input.readlines() phosim_lines = phosim_input.readlines() self.assertEqual(len(galsim_lines), len(phosim_lines)) self.assertEqual(len(galsim_lines), 4 * self.n_objects + 7) for line in galsim_lines: self.assertIn(line, phosim_lines) for line in phosim_lines: self.assertIn(line, galsim_lines) if os.path.exists(galsim_cat_name): os.unlink(galsim_cat_name) if os.path.exists(phosim_cat_name): os.unlink(phosim_cat_name)
class testGalSimGalaxies(GalSimGalaxies): #only draw images for u and g bands (for speed) bandpassNames = ['u', 'g'] PSF = SNRdocumentPSF()
def testObjectPlacement(self): """ Test that GalSim places objects on the correct pixel by drawing images, reading them in, and then comparing the flux contained in circles of 2 fwhm radii about the object's expected positions with the actual expected flux of the objects. """ scratchDir = tempfile.mkdtemp(dir=ROOT, prefix='testObjectPlacement-') catName = os.path.join(scratchDir, 'placementCatalog.dat') imageRoot = os.path.join(scratchDir, 'placementImage') dbFileName = os.path.join(scratchDir, 'placementInputCatalog.dat') cameraDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'cameraData') camera = ReturnCamera(cameraDir) detector = camera[0] imageName = '%s_%s_u.fits' % (imageRoot, detector.getName()) controlSed = Sed() controlSed.readSED_flambda(os.path.join(getPackageDir('sims_sed_library'), 'flatSED', 'sed_flat.txt.gz')) uBandpass = Bandpass() uBandpass.readThroughput(os.path.join(getPackageDir('throughputs'), 'baseline', 'total_u.dat')) controlBandpass = Bandpass() controlBandpass.imsimBandpass() ff = controlSed.calcFluxNorm(self.magNorm, uBandpass) controlSed.multiplyFluxNorm(ff) a_int, b_int = controlSed.setupCCMab() controlSed.addCCMDust(a_int, b_int, A_v=0.1, R_v=3.1) nSamples = 3 rng = np.random.RandomState(42) pointingRaList = rng.random_sample(nSamples)*360.0 pointingDecList = rng.random_sample(nSamples)*180.0 - 90.0 rotSkyPosList = rng.random_sample(nSamples)*360.0 fwhmList = rng.random_sample(nSamples)*1.0 + 0.3 actualCounts = None for pointingRA, pointingDec, rotSkyPos, fwhm in \ zip(pointingRaList, pointingDecList, rotSkyPosList, fwhmList): obs = ObservationMetaData(pointingRA=pointingRA, pointingDec=pointingDec, boundType='circle', boundLength=4.0, mjd=49250.0, rotSkyPos=rotSkyPos) xDisplacementList = rng.random_sample(nSamples)*60.0-30.0 yDisplacementList = rng.random_sample(nSamples)*60.0-30.0 create_text_catalog(obs, dbFileName, xDisplacementList, yDisplacementList, mag_norm=[self.magNorm]*len(xDisplacementList)) db = placementFileDBObj(dbFileName, runtable='test') cat = placementCatalog(db, obs_metadata=obs) cat.camera_wrapper = GalSimCameraWrapper(camera) if actualCounts is None: actualCounts = controlSed.calcADU(uBandpass, cat.photParams) psf = SNRdocumentPSF(fwhm=fwhm) cat.setPSF(psf) cat.write_catalog(catName) cat.write_images(nameRoot=imageRoot) objRaList = [] objDecList = [] with open(catName, 'r') as inFile: for line in inFile: if line[0] != '#': words = line.split(';') objRaList.append(np.radians(np.float(words[2]))) objDecList.append(np.radians(np.float(words[3]))) objRaList = np.array(objRaList) objDecList = np.array(objDecList) self.assertGreater(len(objRaList), 0) # make sure we aren't testing # an empty catalog/image self.check_placement(imageName, objRaList, objDecList, [fwhm]*len(objRaList), np.array([actualCounts]*len(objRaList)), cat.photParams.gain, detector, camera, obs, epoch=2000.0) if os.path.exists(dbFileName): os.unlink(dbFileName) if os.path.exists(catName): os.unlink(catName) if os.path.exists(imageName): os.unlink(imageName) if os.path.exists(scratchDir): shutil.rmtree(scratchDir)
class noisyCatalog(testGalaxyCatalog): """ Adds a noise and sky background wrapper to testGalaxyCatalog """ PSF = SNRdocumentPSF() noise_and_background = ExampleCCDNoise(seed=42)
def main(file, psf, outdir): """ Drive GalSim to simulate the LSST. """ # Setup a parser to take command line arguments config = desc.imsim.read_config(None) logger = desc.imsim.get_logger("INFO") # Get the number of rows to read from the instance file. Use # default if not specified. numRows = None sensor = None # The PhoSim instance file contains both pointing commands and # objects. The parser will split them and return a both phosim # command dictionary and a dataframe of objects. commands, phosim_objects = \ desc.imsim.parsePhoSimInstanceFile(file, numRows) phosim_objects = \ desc.imsim.validate_phosim_object_list(phosim_objects).accepted # Build the ObservationMetaData with values taken from the # PhoSim commands at the top of the instance file. obs_md = desc.imsim.phosim_obs_metadata(commands) #print (commands) #obs_md.OpsimMetaData['altitude' ] = 20 camera = LsstSimMapper().camera # Sub-divide the source dataframe into stars and galaxies. if sensor is not None: # Trim the input catalog to a single chip. phosim_objects['chipName'] = \ chipNameFromRaDec(phosim_objects['raICRS'].values, phosim_objects['decICRS'].values, parallax=phosim_objects['parallax'].values, camera=camera, obs_metadata=obs_md, epoch=2000.0) starDataBase = \ phosim_objects.query("galSimType=='pointSource' and chipName=='%s'" % sensor) galaxyDataBase = \ phosim_objects.query("galSimType=='sersic' and chipName=='%s'" % sensor) else: starDataBase = \ phosim_objects.query("galSimType=='pointSource'") galaxyDataBase = \ phosim_objects.query("galSimType=='sersic'") # Simulate the objects in the Pandas Dataframes. # First simulate stars phoSimStarCatalog = desc.imsim.ImSimStars(starDataBase, obs_md) phoSimStarCatalog.photParams = desc.imsim.photometricParameters(commands) # Add noise and sky background # The simple code using the default lsst-GalSim interface would be: # # PhoSimStarCatalog.noise_and_background = ExampleCCDNoise(addNoise=True, # addBackground=True) # # But, we need a more realistic sky model and we need to pass more than # this basic info to use Peter Y's ESO sky model. # We must pass obs_metadata, chip information etc... phoSimStarCatalog.noise_and_background = ESOSkyModel(obs_md, addNoise=True, addBackground=True) # Add a PSF. if psf.lower() == "doublegaussian": # This one is taken from equation 30 of # www.astro.washington.edu/users/ivezic/Astr511/LSST_SNRdoc.pdf . # # Set seeing from self.obs_metadata. phoSimStarCatalog.PSF = \ SNRdocumentPSF(obs_md.OpsimMetaData['FWHMgeom']) elif psf.lower() == "kolmogorov": # This PSF was presented by David Kirkby at the 23 March 2017 # Survey Simulations Working Group telecon # # https://confluence.slac.stanford.edu/pages/viewpage.action?spaceKey=LSSTDESC&title=SSim+2017-03-23 # equation 3 of Krisciunas and Schaefer 1991 airmass = 1.0 / np.sqrt( 1.0 - 0.96 * (np.sin(0.5 * np.pi - obs_md.OpsimMetaData['altitude']))**2) phoSimStarCatalog.PSF = \ Kolmogorov_and_Gaussian_PSF(airmass=airmass, rawSeeing=obs_md.OpsimMetaData['rawSeeing'], band=obs_md.bandpass) else: raise RuntimeError("Do not know what to do with psf model: " "%s" % psf) phoSimStarCatalog.camera = camera phoSimStarCatalog.get_fitsFiles() # Now galaxies phoSimGalaxyCatalog = desc.imsim.ImSimGalaxies(galaxyDataBase, obs_md) phoSimGalaxyCatalog.copyGalSimInterpreter(phoSimStarCatalog) phoSimGalaxyCatalog.PSF = phoSimStarCatalog.PSF phoSimGalaxyCatalog.noise_and_background = phoSimStarCatalog.noise_and_background phoSimGalaxyCatalog.get_fitsFiles() # Write out the fits files outdir = outdir if not os.path.isdir(outdir): os.makedirs(outdir) prefix = config['persistence']['eimage_prefix'] phoSimGalaxyCatalog.write_images(nameRoot=os.path.join(outdir, prefix) + str(commands['obshistid']))
class psfCatalog(testGalaxyCatalog): """ Adds a PSF to testGalaxyCatalog """ PSF = SNRdocumentPSF()
def testCamera(self): """ Test that GalSimCatalogs respect the allowed_chips variable by generating a catalog with one object on each chip. Generate images from a control catalog that allows all chips. Verify that each image contains the expected flux. Generate images from a test catalog that only allows two chips. Verify that only the two expected images exist and that each contains only the expected flux. """ controlCatalog = allowedChipsCatalog(self.db, obs_metadata=self.obs) testCatalog = allowedChipsCatalog(self.db, obs_metadata=self.obs) psf = SNRdocumentPSF() controlCatalog.setPSF(psf) testCatalog.setPSF(psf) controlCatalog.camera_wrapper = GalSimCameraWrapper(self.camera) testCatalog.camera_wrapper = GalSimCameraWrapper(self.camera) test_root = os.path.join(self.scratchDir, 'allowed_chip_test_image') control_root = os.path.join(self.scratchDir, 'allowed_chip_control_image') name_list = [] for dd in self.camera: if dd.getType() == WAVEFRONT or dd.getType() == GUIDER: continue name = dd.getName() name_list.append(name) stripped_name = name.replace(':', '') stripped_name = stripped_name.replace(',', '') stripped_name = stripped_name.replace(' ', '_') test_image_name = os.path.join( self.scratchDir, test_root + '_' + stripped_name + '_u.fits') control_image_name = os.path.join( self.scratchDir, control_root + '_' + stripped_name + '_u.fits') # remove any images that were generated the last time this test # was run if os.path.exists(test_image_name): os.unlink(test_image_name) if os.path.exists(control_image_name): os.unlink(control_image_name) # only allow two chips in the test catalog allowed_chips = [name_list[3], name_list[4]] testCatalog.allowed_chips = allowed_chips test_cat_name = os.path.join(self.scratchDir, 'allowed_chips_test_cat.txt') control_cat_name = os.path.join(self.scratchDir, 'allowed_chips_control_cat.txt') testCatalog.write_catalog(test_cat_name) controlCatalog.write_catalog(control_cat_name) testCatalog.write_images(nameRoot=test_root) controlCatalog.write_images(nameRoot=control_root) test_image_ct = 0 for name in name_list: # Loop through each chip on the camera. # Verify that the control catalog generated an image for each chip. # Verify that the test catalog only generated images for the two # specified chips. # Verify that each image contains the expected amount of flux. stripped_name = name.replace(':', '') stripped_name = stripped_name.replace(',', '') stripped_name = stripped_name.replace(' ', '_') test_image_name = os.path.join( self.scratchDir, test_root + '_' + stripped_name + '_u.fits') control_image_name = os.path.join( self.scratchDir, control_root + '_' + stripped_name + '_u.fits') msg = '%s does not exist; it should' % control_image_name self.assertTrue(os.path.exists(control_image_name), msg=msg) im = afwImage.ImageF(control_image_name).getArray() msg = "\nimage contains %e counts\nshould contain %e\n\n" % ( im.sum(), self.controlADU) self.assertLess(np.abs(im.sum() - self.controlADU), 3.0 * self.countSigma, msg=msg) os.unlink(control_image_name) if name in allowed_chips: msg = '%s does not exist; it should' % test_image_name self.assertTrue(os.path.exists(test_image_name), msg=msg) im = afwImage.ImageF(test_image_name).getArray() self.assertLess(np.abs(im.sum() - self.controlADU), 3.0 * self.countSigma) os.unlink(test_image_name) test_image_ct += 1 else: msg = '%s exists; it should not' % test_image_name self.assertFalse(os.path.exists(test_image_name), msg=msg) self.assertEqual(test_image_ct, len(allowed_chips)) if os.path.exists(test_cat_name): os.unlink(test_cat_name) if os.path.exists(control_cat_name): os.unlink(control_cat_name)
def testFitsHeader(self): """ Create a test image with the LSST camera and with the cartoon camera. Verify that the image created with the LSST camera has the DM-required cards in its FITS header while the image created with the cartoon camera does not """ cameraDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'cameraData') cartoonCamera = ReturnCamera(cameraDir) outputDir = tempfile.mkdtemp(dir=ROOT, prefix='testFitsHeader-') lsst_cat_name = os.path.join(outputDir, 'fits_test_lsst_cat.txt') lsst_cat_root = os.path.join(outputDir, 'fits_test_lsst_image') cartoon_cat_name = os.path.join(outputDir, 'fits_test_cartoon_cat.txt') cartoon_cat_root = os.path.join(outputDir, 'fits_test_cartoon_image') obs = ObservationMetaData(pointingRA=32.0, pointingDec=22.0, boundLength=0.1, boundType='circle', mjd=58000.0, rotSkyPos=14.0, bandpassName='u') obs.OpsimMetaData = {'obshistID': 112} dbFileName = os.path.join(outputDir, 'fits_test_db.dat') create_text_catalog(obs, dbFileName, np.array([30.0]), np.array([30.0]), [22.0]) db = fitsHeaderFileDBObj(dbFileName, runtable='test') # first test the lsst camera lsstCat = fitsHeaderCatalog(db, obs_metadata=obs) lsstCat.camera_wrapper = LSSTCameraWrapper() lsstCat.PSF = SNRdocumentPSF() lsstCat.write_catalog(lsst_cat_name) lsstCat.write_images(nameRoot=lsst_cat_root) list_of_files = os.listdir(outputDir) ct = 0 for file_name in list_of_files: true_name = os.path.join(outputDir, file_name) if lsst_cat_root in true_name: ct += 1 with fits.open(true_name) as fitsTest: header = fitsTest[0].header self.assertIn('CHIPID', header) self.assertIn('OBSID', header) self.assertIn('OUTFILE', header) self.assertEqual(header['OBSID'], 112) self.assertEqual(header['CHIPID'], 'R22_S11') self.assertEqual(header['OUTFILE'], 'lsst_e_112_f0_R22_S11_E000') os.unlink(true_name) self.assertGreater(ct, 0) if os.path.exists(lsst_cat_name): os.unlink(lsst_cat_name) # now test with the cartoon camera cartoonCat = fitsHeaderCatalog(db, obs_metadata=obs) cartoonCat.camera_wrapper = GalSimCameraWrapper(cartoonCamera) cartoonCat.PSF = SNRdocumentPSF() cartoonCat.write_catalog(cartoon_cat_name) cartoonCat.write_images(nameRoot=cartoon_cat_root) list_of_files = os.listdir(outputDir) ct = 0 for file_name in list_of_files: true_name = os.path.join(outputDir, file_name) if cartoon_cat_root in true_name: ct += 1 with fits.open(true_name) as fitsTest: header = fitsTest[0].header self.assertNotIn('CHIPID', header) self.assertNotIn('OBSID', header) self.assertNotIn('OUTFILE', header) os.unlink(true_name) self.assertGreater(ct, 0) if os.path.exists(cartoon_cat_name): os.unlink(cartoon_cat_name) if os.path.exists(dbFileName): os.unlink(dbFileName) if os.path.exists(outputDir): shutil.rmtree(outputDir)
class testGalSimAgn(GalSimAgn): bandpassNames = ['u', 'g'] #defined in galSimInterface/galSimUtilities.py PSF = SNRdocumentPSF()
class testGalSimStars(GalSimStars): #only draw images for u and g bands (for speed) bandpassNames = ['u', 'g'] #defined in galSimInterface/galSimUtilities.py PSF = SNRdocumentPSF()
def testObjectPlacement(self): """ Test that GalSim places objects on the correct pixel by drawing images containing single objects and no background, reading those images back in, and comparing the flux-averaged centroids of the images with the expected pixel positions of the input objects. """ scratchDir = tempfile.mkdtemp(dir=ROOT, prefix='testLSSTObjectPlacement-') if os.path.exists(scratchDir): shutil.rmtree(scratchDir) os.mkdir(scratchDir) detector = lsst_camera()['R:0,3 S:2,2'] det_name = 'R03_S22' magNorm = 19.0 pixel_transformer = DMtoCameraPixelTransformer() for band in 'ugrizy': obs = self.obs_dict[band] catName = os.path.join(scratchDir, 'placementCatalog.dat') imageRoot = os.path.join(scratchDir, 'placementImage') dbFileName = os.path.join(scratchDir, 'placementInputCatalog.dat') imageName = '%s_%s_%s.fits' % (imageRoot, det_name, obs.bandpass) ra_c, dec_c = raDecFromPixelCoordsLSST(2000.0, 2000.0, detector.getName(), band=obs.bandpass, obs_metadata=obs) nSamples = 30 rng = np.random.RandomState(42) fwhm = 0.12 for iteration in range(nSamples): if os.path.exists(dbFileName): os.unlink(dbFileName) ra_obj = ra_c + rng.random_sample()*0.2 - 0.1 dec_obj = dec_c + rng.random_sample()*0.2 - 0.1 dmx_wrong, dmy_wrong = pixelCoordsFromRaDec(ra_obj, dec_obj, chipName=detector.getName(), obs_metadata=obs, camera=lsst_camera()) dmx_pix, dmy_pix = pixelCoordsFromRaDecLSST(ra_obj, dec_obj, chipName=detector.getName(), obs_metadata=obs, band=obs.bandpass) x_pix, y_pix = pixel_transformer.cameraPixFromDMPix(dmx_pix, dmy_pix, detector.getName()) x_pix_wrong, y_pix_wrong = pixel_transformer.cameraPixFromDMPix(dmx_wrong, dmy_wrong, detector.getName()) d_ra = 360.0*(ra_obj - obs.pointingRA) # in arcseconds d_dec = 360.0*(dec_obj - obs.pointingDec) create_text_catalog(obs, dbFileName, np.array([d_ra]), np.array([d_dec]), mag_norm=[magNorm]) db = LSSTPlacementFileDBObj(dbFileName, runtable='test') cat = LSSTPlacementCatalog(db, obs_metadata=obs) cat.camera_wrapper = LSSTCameraWrapper() psf = SNRdocumentPSF(fwhm=fwhm) cat.setPSF(psf) cat.write_catalog(catName) cat.write_images(nameRoot=imageRoot) im = afwImage.ImageF(imageName).getArray() tot_flux = im.sum() self.assertGreater(tot_flux, 10.0) y_centroid = sum([ii*im[ii,:].sum() for ii in range(im.shape[0])])/tot_flux x_centroid = sum([ii*im[:,ii].sum() for ii in range(im.shape[1])])/tot_flux dd = np.sqrt((x_pix-x_centroid)**2 + (y_pix-y_centroid)**2) self.assertLess(dd, 0.5*fwhm) dd_wrong = np.sqrt((x_pix_wrong-x_centroid)**2 + (y_pix_wrong-y_centroid)**2) self.assertLess(dd, dd_wrong) if os.path.exists(dbFileName): os.unlink(dbFileName) if os.path.exists(catName): os.unlink(catName) if os.path.exists(imageName): os.unlink(imageName) if os.path.exists(scratchDir): shutil.rmtree(scratchDir)
def main(): """ Drive GalSim to simulate the LSST. """ # Setup a parser to take command line arguments parser = argparse.ArgumentParser() parser.add_argument('file', help="The instance catalog") parser.add_argument('-n', '--numrows', default=None, type=int, help="Read the first numrows of the file.") parser.add_argument('--outdir', type=str, default='fits', help='Output directory for eimage file') parser.add_argument( '--sensor', type=str, default=None, help='Sensor to simulate, e.g., "R:2,2 S:1,1".' + 'If None, then simulate all sensors with sources on them') parser.add_argument( '--config_file', type=str, default=None, help="Config file. If None, the default config will be used.") parser.add_argument('--log_level', type=str, choices=['DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL'], default='INFO', help='Logging level. Default: "INFO"') parser.add_argument( '--psf', type=str, default='Kolmogorov', choices=['DoubleGaussian', 'Kolmogorov'], help="PSF model to use; either the double Gaussian " "from LSE=40 (equation 30), or the Kolmogorov convolved " "with a Gaussian proposed by David Kirkby at the " "23 March 2017 SSims telecon") parser.add_argument('--checkpoint_file', type=str, default=None, help='Checkpoint file name.') parser.add_argument('--nobj_checkpoint', type=int, default=1000, help='# objects to process between checkpoints') parser.add_argument('--seed', type=int, default=267, help='integer used to seed random number generator') arguments = parser.parse_args() config = desc.imsim.read_config(arguments.config_file) logger = desc.imsim.get_logger(arguments.log_level) # Get the number of rows to read from the instance file. Use # default if not specified. numRows = arguments.numrows if numRows is not None: logger.info("Reading %i rows from the instance catalog %s.", numRows, arguments.file) else: logger.info("Reading all rows from the instance catalog %s.", arguments.file) camera_wrapper = LSSTCameraWrapper() catalog_contents = desc.imsim.parsePhoSimInstanceFile(arguments.file, numRows=numRows) obs_md = catalog_contents.obs_metadata phot_params = catalog_contents.phot_params sources = catalog_contents.sources gs_object_arr = sources[0] gs_object_dict = sources[1] # Sub-divide the source dataframe into stars and galaxies. if arguments.sensor is not None: detector_list = [ make_galsim_detector(camera_wrapper, arguments.sensor, phot_params, obs_md) ] else: detector_list = [] for det in camera_wrapper.camera: det_type = det.getType() if det_type != WAVEFRONT and det_type != GUIDER: detector_list.append( make_galsim_detector(camera_wrapper, det.getName(), phot_params, obs_md)) # Add noise and sky background # The simple code using the default lsst-GalSim interface would be: # # PhoSimStarCatalog.noise_and_background = ExampleCCDNoise(addNoise=True, # addBackground=True) # # But, we need a more realistic sky model and we need to pass more than # this basic info to use Peter Y's ESO sky model. # We must pass obs_metadata, chip information etc... noise_and_background \ = ESOSkyModel(obs_md, addNoise=True, addBackground=True) bp_dict = BandpassDict.loadTotalBandpassesFromFiles( bandpassNames=obs_md.bandpass) gs_interpreter = GalSimInterpreter(obs_metadata=obs_md, epoch=2000.0, detectors=detector_list, bandpassDict=bp_dict, noiseWrapper=noise_and_background, seed=arguments.seed) gs_interpreter.checkpoint_file = arguments.checkpoint_file gs_interpreter.nobj_checkpoint = arguments.nobj_checkpoint gs_interpreter.restore_checkpoint(camera_wrapper, phot_params, obs_md) # Add a PSF. if arguments.psf.lower() == "doublegaussian": # This one is taken from equation 30 of # www.astro.washington.edu/users/ivezic/Astr511/LSST_SNRdoc.pdf . # # Set seeing from self.obs_metadata. local_PSF = \ SNRdocumentPSF(obs_md.OpsimMetaData['FWHMgeom']) elif arguments.psf.lower() == "kolmogorov": # This PSF was presented by David Kirkby at the 23 March 2017 # Survey Simulations Working Group telecon # # https://confluence.slac.stanford.edu/pages/viewpage.action?spaceKey=LSSTDESC&title=SSim+2017-03-23 # equation 3 of Krisciunas and Schaefer 1991 airmass = 1.0 / np.sqrt( 1.0 - 0.96 * (np.sin(0.5 * np.pi - obs_md.OpsimMetaData['altitude']))**2) local_PSF = \ Kolmogorov_and_Gaussian_PSF(airmass=airmass, rawSeeing=obs_md.OpsimMetaData['rawSeeing'], band=obs_md.bandpass) else: raise RuntimeError("Do not know what to do with psf model: " "%s" % arguments.psf) gs_interpreter.setPSF(PSF=local_PSF) if arguments.sensor is not None: gs_objects_to_draw = gs_object_dict[arguments.sensor] else: gs_objects_to_draw = gs_object_arr for gs_obj in gs_objects_to_draw: if gs_obj.uniqueId in gs_interpreter.drawn_objects: continue gs_interpreter.drawObject(gs_obj) desc.imsim.add_cosmic_rays(gs_interpreter, phot_params) # Write out the fits files outdir = arguments.outdir if not os.path.isdir(outdir): os.makedirs(outdir) prefix = config['persistence']['eimage_prefix'] gs_interpreter.writeImages(nameRoot=os.path.join(outdir, prefix) + str(obs_md.OpsimMetaData['obshistID']))