def testNoPsf(self): """Test InstallGaussianPsfTask when the input exposure has no PSF.""" for width in (21, 25): for fwhm in (2.8, 7.1): config = InstallGaussianPsfTask.ConfigClass() config.width = width config.fwhm = fwhm task = InstallGaussianPsfTask(config=config) exposure = ExposureF(100, 100) task.run(exposure=exposure) self.assertTrue(exposure.hasPsf()) psf = exposure.getPsf() psfIm = psf.computeImage() self.assertEqual(psfIm.getWidth(), width) self.assertEqual(psfIm.getHeight(), width) measFwhm = psf.computeShape().getDeterminantRadius()*FwhmPerSigma self.assertAlmostEqual(measFwhm, fwhm, delta=1e-3)
def testMatchSingleGaussianPsf(self): """Test InstallGaussianPsfTask when the input exposure has a single Gaussian PSF.""" config = InstallGaussianPsfTask.ConfigClass() task = InstallGaussianPsfTask(config=config) for desWidth, desHeight, desSigma in ( (21, 23, 1.2), (23, 25, 3.5), ): exposure = ExposureF(100, 100) inPsf = SingleGaussianPsf(desWidth, desHeight, desSigma) exposure.setPsf(inPsf) task.run(exposure=exposure) self.assertTrue(exposure.hasPsf()) psf = exposure.getPsf() psfIm = psf.computeImage() self.assertEqual(psfIm.getWidth(), desWidth) self.assertEqual(psfIm.getHeight(), desHeight) self.assertAlmostEqual(psf.computeShape().getDeterminantRadius(), desSigma, delta=1e-3)
def testMatchDoubleGaussianPsf(self): """Test InstallGaussianPsfTask when the input exposure has a DoubleGaussian PSF.""" config = InstallGaussianPsfTask.ConfigClass() task = InstallGaussianPsfTask(config=config) for doubleGaussParms in ( # width, height, inner sigma, outer sigma, outer/inner peak amplitude (21, 23, 1.2, 3.5, 0.02), (23, 25, 3.5, 9.0, 0.02), ): exposure = ExposureF(100, 100) inPsf = DoubleGaussianPsf(*doubleGaussParms) exposure.setPsf(inPsf) desWidth, desHeight, innerSigma = doubleGaussParms[0:3] task.run(exposure=exposure) self.assertTrue(exposure.hasPsf()) psf = exposure.getPsf() psfIm = psf.computeImage() self.assertEqual(psfIm.getWidth(), desWidth) self.assertEqual(psfIm.getHeight(), desHeight) self.assertAlmostEqual(psf.computeShape().getDeterminantRadius(), innerSigma, delta=0.1)
def setUp(self): # Load sample input from disk testDir = os.path.dirname(__file__) self.srcSet = SourceCatalog.readFits(os.path.join(testDir, "v695833-e0-c000.xy.fits")) self.bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(2048, 4612)) # approximate # create an exposure with the right metadata; the closest thing we have is # apparently v695833-e0-c000-a00.sci.fits, which is much too small smallExposure = ExposureF(os.path.join(testDir, "v695833-e0-c000-a00.sci.fits")) self.exposure = ExposureF(self.bbox) self.exposure.setWcs(smallExposure.getWcs()) self.exposure.setFilter(smallExposure.getFilter()) # copy the pixels we can, in case the user wants a debug display mi = self.exposure.getMaskedImage() mi.assign(smallExposure.getMaskedImage(), smallExposure.getBBox()) logLevel = Log.INFO refCatDir = os.path.join(testDir, "data", "sdssrefcat") butler = Butler(refCatDir) refObjLoader = LoadIndexedReferenceObjectsTask(butler=butler) astrometryConfig = AstrometryTask.ConfigClass() self.astrom = AstrometryTask(config=astrometryConfig, refObjLoader=refObjLoader) self.astrom.log.setLevel(logLevel) # Since our sourceSelector is a registry object we have to wait for it to be created # before setting default values. self.astrom.sourceSelector.config.minSnr = 0
def setUp(self): self.camera = CameraWrapper().camera self.detector = DetectorWrapper().detector self.crpix = afwGeom.Point2D(50, 100) self.crval = afwGeom.SpherePoint(36, 71, afwGeom.degrees) scale = 1.0*afwGeom.arcseconds self.cdMatrix = afwGeom.makeCdMatrix(scale=scale) self.wcs = afwGeom.makeSkyWcs(crpix=self.crpix, crval=self.crval, cdMatrix=self.cdMatrix) self.bbox = afwGeom.Box2I(afwGeom.Point2I(-10, 10), afwGeom.Extent2I(1000, 1022)) self.exposure = ExposureF(self.bbox) # set the few items of ExposureInfo needed by IsrTask.run # when only adding a distortion model exposureInfo = ExposureInfo(photoCalib=PhotoCalib(1.0), detector=self.detector, visitInfo=VisitInfo(exposureTime=1.0), wcs=self.wcs) self.exposure.setInfo(exposureInfo)
def setUp(self): """Constructs a CCD with two amplifiers and prepares for ISR""" np.random.seed(12345) baseValue = 100.0 gain = 1.0 readNoise = 123456789.0 saturation = 987654321.0 height = 234 imageSize = Extent2I(123, height) overscanSize = Extent2I(16, height) self.sigma = 1.234 # Set up the various regions overscan1 = Box2I(Point2I(0, 0), overscanSize) image1 = Box2I(Point2I(overscanSize[0], 0), imageSize) image2 = Box2I(Point2I(overscanSize[0] + imageSize[0], 0), imageSize) overscan2 = Box2I(Point2I(overscanSize[0] + 2*imageSize[0], 0), overscanSize) leftBox = Box2I(overscan1.getMin(), Extent2I(overscan1.getWidth() + image1.getWidth(), height)) rightBox = Box2I(image2.getMin(), Extent2I(image2.getWidth() + overscan2.getWidth(), height)) target1 = Box2I(Point2I(0, 0), imageSize) target2 = Box2I(Point2I(image1.getWidth(), 0), imageSize) # Set the pixels exposure = ExposureF(Box2I(Point2I(0, 0), Extent2I(imageSize[0]*2 + overscanSize[0]*2, height))) yy = np.arange(0, height, 1, dtype=np.float32) leftImage = ExposureF(exposure, leftBox) leftImage.image.array[:] = baseValue + yy[:, np.newaxis] rightImage = ExposureF(exposure, rightBox) rightImage.image.array[:] = baseValue - yy[:, np.newaxis] leftOverscan = ExposureF(exposure, overscan1) leftOverscan.image.array += np.random.normal(0.0, self.sigma, leftOverscan.image.array.shape) rightOverscan = ExposureF(exposure, overscan2) rightOverscan.image.array += np.random.normal(0.0, self.sigma, leftOverscan.image.array.shape) exposure.mask.array[:] = 0.0 exposure.variance.array[:] = np.nan # Construct the detectors amps = AmpInfoCatalog(AmpInfoTable.makeMinimalSchema()) makeAmplifier(amps, "left", target1, image1, overscan1, gain, readNoise, saturation) makeAmplifier(amps, "right", target2, image2, overscan2, gain, readNoise, saturation) ccdBox = Box2I(Point2I(0, 0), Extent2I(image1.getWidth() + image2.getWidth(), height)) ccd = Detector("detector", 1, SCIENCE, "det1", ccdBox, amps, Orientation(), Extent2D(1.0, 1.0), {}) exposure.setDetector(ccd) header = PropertyList() header.add("EXPTIME", 0.0) exposure.getInfo().setVisitInfo(VisitInfo(header)) self.exposure = exposure self.config = IsrTask.ConfigClass() # Disable everything we don't care about self.config.doBias = False self.config.doDark = False self.config.doFlat = False self.config.doFringe = False self.config.doDefect = False self.config.doAddDistortionModel = False self.config.doWrite = False self.config.expectWcs = False self.config.doLinearize = False self.config.doCrosstalk = False self.config.doBrighterFatter = False self.config.doAttachTransmissionCurve = False # Set the things that match our test setup self.config.overscanFitType = "CHEB" self.config.overscanOrder = 1 self.config.doEmpiricalReadNoise = True self.task = IsrTask(config=self.config)
class ApplyLookupTableTestCase(lsst.utils.tests.TestCase): """Test IsrTask.addDistortionModel """ def setUp(self): self.camera = CameraWrapper().camera self.detector = DetectorWrapper().detector self.crpix = afwGeom.Point2D(50, 100) self.crval = afwGeom.SpherePoint(36, 71, afwGeom.degrees) scale = 1.0*afwGeom.arcseconds self.cdMatrix = afwGeom.makeCdMatrix(scale=scale) self.wcs = afwGeom.makeSkyWcs(crpix=self.crpix, crval=self.crval, cdMatrix=self.cdMatrix) self.bbox = afwGeom.Box2I(afwGeom.Point2I(-10, 10), afwGeom.Extent2I(1000, 1022)) self.exposure = ExposureF(self.bbox) # set the few items of ExposureInfo needed by IsrTask.run # when only adding a distortion model exposureInfo = ExposureInfo(photoCalib=PhotoCalib(1.0), detector=self.detector, visitInfo=VisitInfo(exposureTime=1.0), wcs=self.wcs) self.exposure.setInfo(exposureInfo) def tearDown(self): self.detector = None self.exposure = None def testAddDistortionMethod(self): """Call IsrTask.addDistortionModel directly""" isrFunctions.addDistortionModel(self.exposure, self.camera) self.assertFalse(wcsAlmostEqualOverBBox(self.wcs, self.exposure.getWcs(), self.bbox)) desiredWcs = self.makeDesiredDistortedWcs() self.assertWcsAlmostEqualOverBBox(desiredWcs, self.exposure.getWcs(), self.bbox) def makeMinimalIsrConfig(self): """Return an IsrConfig with all boolean flags disabled""" isrConfig = IsrTask.ConfigClass() for name in isrConfig: if name.startswith("do"): setattr(isrConfig, name, False) return isrConfig def makeDesiredDistortedWcs(self): """Make the expected distorted WCS""" pixelToFocalPlane = self.detector.getTransform(PIXELS, FOCAL_PLANE) focalPlaneToFieldAngle = self.camera.getTransformMap().getTransform(FOCAL_PLANE, FIELD_ANGLE) return makeDistortedTanWcs(self.wcs, pixelToFocalPlane, focalPlaneToFieldAngle) def testRunWithAddDistortionModel(self): """Test IsrTask.run with config.doAddDistortionModel true""" isrConfig = self.makeMinimalIsrConfig() isrConfig.doAddDistortionModel = True isrTask = IsrTask(config=isrConfig) with self.assertRaises(RuntimeError): # the camera argument is required isrTask.run(ccdExposure=self.exposure) exposure = isrTask.run(ccdExposure=self.exposure, camera=self.camera).exposure desiredWcs = self.makeDesiredDistortedWcs() self.assertWcsAlmostEqualOverBBox(desiredWcs, exposure.getWcs(), self.bbox) def testRunWithoutAddDistortionModel(self): """Test IsrTask.run with config.doAddDistortionModel false""" isrConfig = self.makeMinimalIsrConfig() isrTask = IsrTask(config=isrConfig) # the camera argument is not needed exposure = isrTask.run(ccdExposure=self.exposure).exposure self.assertEqual(self.wcs, exposure.getWcs()) # and the camera argument is ignored if provided exposure2 = isrTask.run(ccdExposure=self.exposure, camera=self.camera).exposure self.assertEqual(self.wcs, exposure2.getWcs())
class JoinMatchListWithCatalogTestCase(unittest.TestCase): def setUp(self): # Load sample input from disk testDir = os.path.dirname(__file__) self.srcSet = SourceCatalog.readFits(os.path.join(testDir, "v695833-e0-c000.xy.fits")) self.bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(2048, 4612)) # approximate # create an exposure with the right metadata; the closest thing we have is # apparently v695833-e0-c000-a00.sci.fits, which is much too small smallExposure = ExposureF(os.path.join(testDir, "v695833-e0-c000-a00.sci.fits")) self.exposure = ExposureF(self.bbox) self.exposure.setWcs(smallExposure.getWcs()) self.exposure.setFilter(smallExposure.getFilter()) # copy the pixels we can, in case the user wants a debug display mi = self.exposure.getMaskedImage() mi.assign(smallExposure.getMaskedImage(), smallExposure.getBBox()) logLevel = Log.INFO refCatDir = os.path.join(testDir, "data", "sdssrefcat") butler = Butler(refCatDir) refObjLoader = LoadIndexedReferenceObjectsTask(butler=butler) astrometryConfig = AstrometryTask.ConfigClass() self.astrom = AstrometryTask(config=astrometryConfig, refObjLoader=refObjLoader) self.astrom.log.setLevel(logLevel) # Since our sourceSelector is a registry object we have to wait for it to be created # before setting default values. self.astrom.sourceSelector.config.minSnr = 0 def tearDown(self): del self.srcSet del self.bbox del self.exposure del self.astrom def getAstrometrySolution(self): return self.astrom.solve(exposure=self.exposure, sourceCat=self.srcSet) def testJoin(self): res = self.getAstrometrySolution() matches = res.matches matchmeta = res.matchMeta normalized = packMatches(matches) normalized.table.setMetadata(matchmeta) matches2 = self.astrom.refObjLoader.joinMatchListWithCatalog(normalized, self.srcSet) self.assertEqual(len(matches2), len(matches)) for i in range(len(matches)): self.assertEqual(matches2[i].second.table, matches[i].second.table) self.assertEqual(matches2[i].second.getId(), matches[i].second.getId()) self.assertEqual(matches2[i].second, matches[i].second) # no deep copying, so we can compare ptrs self.assertEqual(matches2[i].first.getId(), matches[i].first.getId()) self.assertEqual(matches2[i].first.getRa().asDegrees(), matches[i].first.getRa().asDegrees()) self.assertEqual(matches2[i].first.getDec().asDegrees(), matches[i].first.getDec().asDegrees()) self.assertEqual(matches2[i].first.get("i_flux"), matches[i].first.get("i_flux")) def testJoinAllFluxes(self): """Test that we can read all the fluxes from a reference catalog""" res = self.getAstrometrySolution() matches = res.matches matchmeta = res.matchMeta normalized = packMatches(matches) normalized.table.setMetadata(matchmeta) matches2 = self.astrom.refObjLoader.joinMatchListWithCatalog(normalized, self.srcSet) self.assertGreater(len(matches2), 0) ref = matches2[0][0] refSchema = ref.getSchema() for b in ("u", "g", "r", "i", "z"): self.assertIn("%s_flux" % (b,), refSchema) self.assertIn("%s_fluxErr" % (b,), refSchema)
def testPersistence(self): for pgp in self.pgps: assert cppLib.isPersistable(pgp) im = ExposureF(10, 10) im.setPsf(pgp) self.assertEqual(im.getPsf(), pgp) with lsst.utils.tests.getTempFilePath(".fits") as tmpFile: im.writeFits(tmpFile) newIm = ExposureF(tmpFile) self.assertEqual(newIm.getPsf(), im.getPsf())
from lsst.afw.image import ExposureF from lsst.meas.algorithms.installGaussianPsf import InstallGaussianPsfTask, FwhmPerSigma exposure = ExposureF(100, 100) task = InstallGaussianPsfTask() task.run(exposure=exposure) # This particular exposure had no PSF model to begin with, so the new PSF model # uses the config's FWHM. However, measured FWHM is based on the truncated # PSF image, so it does not exactly match the input measFwhm = exposure.getPsf().computeShape().getDeterminantRadius() * FwhmPerSigma assert abs(measFwhm - task.config.fwhm) < 1e-3
def testPersistence(self): im = ExposureF(10, 10) im.setPsf(self.psf) self.assertEqual(im.getPsf(), self.psf) with lsst.utils.tests.getTempFilePath(".fits") as tmpFile: im.writeFits(tmpFile) newIm = ExposureF(tmpFile) self.assertEqual(newIm.getPsf(), im.getPsf())