def test_read_tree_rings(self): """Check reading of tree_ring_parameters file""" camera_wrapper = LSSTCameraWrapper() desc.imsim.read_config() needed_stuff = desc.imsim.parsePhoSimInstanceFile(self.instcat_file, ()) obs_md = needed_stuff.obs_metadata phot_params = needed_stuff.phot_params detector_list = [] for sensor in self.sensors: detector_list.append(make_galsim_detector(camera_wrapper, sensor, phot_params, obs_md)) gs_interpreter = GalSimInterpreter(detectors=detector_list) tr_filename = os.path.join(lsstUtils.getPackageDir('imsim'), 'data', 'tree_ring_data', 'tree_ring_parameters_19mar18.txt') desc.imsim.add_treering_info(gs_interpreter.detectors, tr_filename=tr_filename) for i, detector in enumerate(gs_interpreter.detectors): center = detector.tree_rings.center shifted_center = (center.x - detector._xCenterPix, center.y - detector._yCenterPix) self.assertAlmostEqual(shifted_center, self.centers[i], 1) r_value_test = detector.tree_rings.func(self.rtest) self.assertAlmostEqual(r_value_test, self.rvalues[i], 6)
def compare_to_imsim(phosim_commands): bandpass = bandpass_all[int(phosim_commands['filter'].values[0])] obs_md = ObservationMetaData( pointingRA=float(phosim_commands['rightascension'].values[0]), pointingDec=float(phosim_commands['declination'].values[0]), mjd=float(phosim_commands['mjd'].values[0]), rotSkyPos=float(phosim_commands['rotskypos'].values[0]), bandpassName=bandpass, m5=LSSTdefaults().m5(bandpass), seeing=float(phosim_commands['seeing'].values[0])) noise_and_background = ESOSkyModel(obs_md, addNoise=True, addBackground=True) phot_params = PhotometricParameters( exptime=float(phosim_commands['vistime'].values[0]), nexp=int(phosim_commands['nsnap'].values[0]), gain=1, readnoise=0, darkcurrent=0, bandpass=bandpass) # We are going to check one sensor only detector_list = [ make_galsim_detector(camera_wrapper, "R:2,2 S:1,1", phot_params, obs_md) ] 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=1234) image = gs_interpreter.blankImage(detector=detector_list[0]) image_2 = noise_and_background.addNoiseAndBackground( image, bandpass=obs_md.bandpass, m5=obs_md.m5, FWHMeff=obs_md.seeing, photParams=phot_params, chipName=detector_list[0].name) return compute_bkg(image_2.array)
def _initializeGalSimInterpreter(self): """ This method creates the GalSimInterpreter (if it is None) This method reads in all of the data about the camera and pass it into the GalSimInterpreter. This method calls _getBandpasses to construct the paths to the files containing the bandpass data. """ if not isinstance(self.camera_wrapper, GalSimCameraWrapper): raise RuntimeError("GalSimCatalog.camera_wrapper must be an instantiation of " "GalSimCameraWrapper or one of its daughter classes\n" "It is actually of type %s" % str(type(self.camera_wrapper))) if self.galSimInterpreter is None: # This list will contain instantiations of the GalSimDetector class # (see galSimInterpreter.py), which stores detector information in a way # that the GalSimInterpreter will understand detectors = [] for dd in self.camera_wrapper.camera: if dd.getType() == WAVEFRONT or dd.getType() == GUIDER: # This package does not yet handle the 90-degree rotation # in WCS that occurs for wavefront or guide sensors continue if self.allowed_chips is None or dd.getName() in self.allowed_chips: centerPupil = self.camera_wrapper.getCenterPupil(dd.getName()) centerPixel = self.camera_wrapper.getCenterPixel(dd.getName()) translationPupil = self.camera_wrapper.pupilCoordsFromPixelCoords(centerPixel.getX()+1, centerPixel.getY()+1, dd.getName()) plateScale = np.sqrt(np.power(translationPupil[0]-centerPupil.getX(), 2) + np.power(translationPupil[1]-centerPupil.getY(), 2))/np.sqrt(2.0) plateScale = 3600.0*np.degrees(plateScale) # make a detector-custom photParams that copies all of the quantities # in the catalog photParams, except the platescale, which is # calculated above params = PhotometricParameters(exptime=self.photParams.exptime, nexp=self.photParams.nexp, effarea=self.photParams.effarea, gain=self.photParams.gain, readnoise=self.photParams.readnoise, darkcurrent=self.photParams.darkcurrent, othernoise=self.photParams.othernoise, platescale=plateScale) detector = GalSimDetector(dd.getName(), self.camera_wrapper, obs_metadata=self.obs_metadata, epoch=self.db_obj.epoch, photParams=params) detectors.append(detector) if not hasattr(self, 'bandpassDict'): if self.noise_and_background is not None: if self.obs_metadata.m5 is None: raise RuntimeError('WARNING in GalSimCatalog; you did not specify m5 in your ' 'obs_metadata. m5 is required in order to ' 'add noise to your images') for name in self.bandpassNames: if name not in self.obs_metadata.m5: raise RuntimeError('WARNING in GalSimCatalog; your obs_metadata does not have ' + 'm5 values for all of your bandpasses \n' + 'bandpass has: %s \n' % self.bandpassNames.__repr__() + 'm5 has: %s ' % list(self.obs_metadata.m5.keys()).__repr__()) if self.obs_metadata.seeing is None: raise RuntimeError('WARNING in GalSimCatalog; you did not specify seeing in your ' 'obs_metadata. seeing is required in order to add ' 'noise to your images') for name in self.bandpassNames: if name not in self.obs_metadata.seeing: raise RuntimeError('WARNING in GalSimCatalog; your obs_metadata does not have ' + 'seeing values for all of your bandpasses \n' + 'bandpass has: %s \n' % self.bandpassNames.__repr__() + 'seeing has: %s ' % list(self.obs_metadata.seeing.keys()).__repr__()) (self.bandpassDict, hardwareDict) = BandpassDict.loadBandpassesFromFiles(bandpassNames=self.bandpassNames, filedir=self.bandpassDir, bandpassRoot=self.bandpassRoot, componentList=self.componentList, atmoTransmission=os.path.join(self.bandpassDir, self.atmoTransmissionName)) self.galSimInterpreter = GalSimInterpreter(obs_metadata=self.obs_metadata, epoch=self.db_obj.epoch, detectors=detectors, bandpassDict=self.bandpassDict, noiseWrapper=self.noise_and_background, seed=self.seed) self.galSimInterpreter.setPSF(PSF=self.PSF)
def _initializeGalSimInterpreter(self): """ This method creates the GalSimInterpreter (if it is None) This method reads in all of the data about the camera and pass it into the GalSimInterpreter. This method calls _getBandpasses to construct the paths to the files containing the bandpass data. """ if not isinstance(self.camera_wrapper, GalSimCameraWrapper): raise RuntimeError( "GalSimCatalog.camera_wrapper must be an instantiation of " "GalSimCameraWrapper or one of its daughter classes\n" "It is actually of type %s" % str(type(self.camera_wrapper))) if self.galSimInterpreter is None: # This list will contain instantiations of the GalSimDetector class # (see galSimInterpreter.py), which stores detector information in a way # that the GalSimInterpreter will understand detectors = [] for dd in self.camera_wrapper.camera: if dd.getType() == WAVEFRONT or dd.getType() == GUIDER: # This package does not yet handle the 90-degree rotation # in WCS that occurs for wavefront or guide sensors continue if self.allowed_chips is None or dd.getName( ) in self.allowed_chips: detectors.append( make_galsim_detector(self.camera_wrapper, dd.getName(), self.photParams, self.obs_metadata, epoch=self.db_obj.epoch)) if not hasattr(self, 'bandpassDict'): if self.noise_and_background is not None: if self.obs_metadata.m5 is None: raise RuntimeError( 'WARNING in GalSimCatalog; you did not specify m5 in your ' 'obs_metadata. m5 is required in order to ' 'add noise to your images') for name in self.bandpassNames: if name not in self.obs_metadata.m5: raise RuntimeError( 'WARNING in GalSimCatalog; your obs_metadata does not have ' + 'm5 values for all of your bandpasses \n' + 'bandpass has: %s \n' % self.bandpassNames.__repr__() + 'm5 has: %s ' % list(self.obs_metadata.m5.keys()).__repr__()) if self.obs_metadata.seeing is None: raise RuntimeError( 'WARNING in GalSimCatalog; you did not specify seeing in your ' 'obs_metadata. seeing is required in order to add ' 'noise to your images') for name in self.bandpassNames: if name not in self.obs_metadata.seeing: raise RuntimeError( 'WARNING in GalSimCatalog; your obs_metadata does not have ' + 'seeing values for all of your bandpasses \n' + 'bandpass has: %s \n' % self.bandpassNames.__repr__() + 'seeing has: %s ' % list(self.obs_metadata.seeing.keys()).__repr__( )) (self.bandpassDict, hardwareDict) = BandpassDict.loadBandpassesFromFiles( bandpassNames=self.bandpassNames, filedir=self.bandpassDir, bandpassRoot=self.bandpassRoot, componentList=self.componentList, atmoTransmission=os.path.join(self.bandpassDir, self.atmoTransmissionName)) self.galSimInterpreter = GalSimInterpreter( obs_metadata=self.obs_metadata, epoch=self.db_obj.epoch, detectors=detectors, bandpassDict=self.bandpassDict, noiseWrapper=self.noise_and_background, seed=self.seed) self.galSimInterpreter.setPSF(PSF=self.PSF)
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']))
def _initializeGalSimInterpreter(self): """ This method creates the GalSimInterpreter (if it is None) This method reads in all of the data about the camera and pass it into the GalSimInterpreter. This method calls _getBandpasses to construct the paths to the files containing the bandpass data. """ if self.galSimInterpreter is None: # This list will contain instantiations of the GalSimDetector class # (see galSimInterpreter.py), which stores detector information in a way # that the GalSimInterpreter will understand detectors = [] for dd in self.camera: if self.allowed_chips is None or dd.getName( ) in self.allowed_chips: cs = dd.makeCameraSys(PUPIL) centerPupil = self.camera.transform( dd.getCenter(FOCAL_PLANE), cs).getPoint() centerPixel = dd.getCenter(PIXELS).getPoint() translationPixel = afwGeom.Point2D(centerPixel.getX() + 1, centerPixel.getY() + 1) translationPupil = self.camera.transform( dd.makeCameraPoint(translationPixel, PIXELS), cs).getPoint() plateScale = np.sqrt( np.power(translationPupil.getX() - centerPupil.getX(), 2) + np.power(translationPupil.getY() - centerPupil.getY(), 2)) / np.sqrt(2.0) plateScale = 3600.0 * np.degrees(plateScale) # make a detector-custom photParams that copies all of the quantities # in the catalog photParams, except the platescale, which is # calculated above params = PhotometricParameters( exptime=self.photParams.exptime, nexp=self.photParams.nexp, effarea=self.photParams.effarea, gain=self.photParams.gain, readnoise=self.photParams.readnoise, darkcurrent=self.photParams.darkcurrent, othernoise=self.photParams.othernoise, platescale=plateScale) detector = GalSimDetector(dd, self.camera, obs_metadata=self.obs_metadata, epoch=self.db_obj.epoch, photParams=params) detectors.append(detector) if not hasattr(self, 'bandpassDict'): if self.noise_and_background is not None: if self.obs_metadata.m5 is None: raise RuntimeError( 'WARNING in GalSimCatalog; you did not specify m5 in your ' 'obs_metadata. m5 is required in order to ' 'add noise to your images') for name in self.bandpassNames: if name not in self.obs_metadata.m5: raise RuntimeError( 'WARNING in GalSimCatalog; your obs_metadata does not have ' + 'm5 values for all of your bandpasses \n' + 'bandpass has: %s \n' % self.bandpassNames.__repr__() + 'm5 has: %s ' % list(self.obs_metadata.m5.keys()).__repr__()) if self.obs_metadata.seeing is None: raise RuntimeError( 'WARNING in GalSimCatalog; you did not specify seeing in your ' 'obs_metadata. seeing is required in order to add ' 'noise to your images') for name in self.bandpassNames: if name not in self.obs_metadata.seeing: raise RuntimeError( 'WARNING in GalSimCatalog; your obs_metadata does not have ' + 'seeing values for all of your bandpasses \n' + 'bandpass has: %s \n' % self.bandpassNames.__repr__() + 'seeing has: %s ' % list(self.obs_metadata.seeing.keys()).__repr__( )) (self.bandpassDict, hardwareDict) = BandpassDict.loadBandpassesFromFiles( bandpassNames=self.bandpassNames, filedir=self.bandpassDir, bandpassRoot=self.bandpassRoot, componentList=self.componentList, atmoTransmission=os.path.join(self.bandpassDir, self.atmoTransmissionName)) self.galSimInterpreter = GalSimInterpreter( obs_metadata=self.obs_metadata, epoch=self.db_obj.epoch, detectors=detectors, bandpassDict=self.bandpassDict, noiseWrapper=self.noise_and_background, seed=self.seed) self.galSimInterpreter.setPSF(PSF=self.PSF)
def test_checkpointing(self): "Test checkpointing of .detectorImages data." camera = camTestUtils.CameraWrapper().camera camera_wrapper = GalSimCameraWrapper(camera) phot_params = PhotometricParameters() obs_md = ObservationMetaData(pointingRA=23.0, pointingDec=12.0, rotSkyPos=13.2, mjd=59580.0, bandpassName='r') detectors = [ make_galsim_detector(camera_wrapper, dd.getName(), phot_params, obs_md) for dd in camera_wrapper.camera ] # Create a GalSimInterpreter object and set the checkpoint # attributes. gs_interpreter = GalSimInterpreter(detectors=detectors) gs_interpreter.checkpoint_file = self.cp_file nobj = 10 gs_interpreter.nobj_checkpoint = nobj # Set the image data by hand. key = "R00_S00_r.fits" detname = "R:0,0 S:0,0" detector = make_galsim_detector(camera_wrapper, detname, phot_params, obs_md) image = gs_interpreter.blankImage(detector=detector) image += 17 gs_interpreter.detectorImages[key] = image # Add some drawn objects and check that the checkpoint file is # written at the right cadence. for uniqueId in range(1, nobj + 1): gs_interpreter.drawn_objects.add(uniqueId) gs_interpreter.write_checkpoint() if uniqueId < nobj: self.assertFalse(os.path.isfile(self.cp_file)) else: self.assertTrue(os.path.isfile(self.cp_file)) # Verify that the checkpointed data has the expected content. with open(self.cp_file, 'rb') as input_: cp_data = pickle.load(input_) self.assertTrue(np.array_equal(cp_data['images'][key], image.array)) # Check the restore_checkpoint function. new_interpreter = GalSimInterpreter(detectors=detectors) new_interpreter.checkpoint_file = self.cp_file new_interpreter.restore_checkpoint(camera_wrapper, phot_params, obs_md) self.assertEqual(new_interpreter.drawn_objects, gs_interpreter.drawn_objects) self.assertEqual(set(new_interpreter.detectorImages.keys()), set(gs_interpreter.detectorImages.keys())) for det_name in new_interpreter.detectorImages.keys(): new_img = new_interpreter.detectorImages[det_name] gs_img = gs_interpreter.detectorImages[det_name] np.testing.assert_array_equal(new_img.array, gs_img.array) self.assertEqual(new_img.bounds, gs_img.bounds) self.assertEqual(new_img.wcs.crpix1, gs_img.wcs.crpix1) self.assertEqual(new_img.wcs.crpix2, gs_img.wcs.crpix2) self.assertEqual(new_img.wcs.crval1, gs_img.wcs.crval1) self.assertEqual(new_img.wcs.crval2, gs_img.wcs.crval2) self.assertEqual(new_img.wcs.detectorName, gs_img.wcs.detectorName) for name in new_img.wcs.fitsHeader.names(): self.assertEqual(new_img.wcs.fitsHeader.get(name), gs_img.wcs.fitsHeader.get(name))