def test_solve_centroid(self): exposure = ExposureF(400, 400) psfConfig = InstallGaussianPsfConfig() psfConfig.fwhm = 4 psfTask = InstallGaussianPsfTask(config=psfConfig) psfTask.run(exposure=exposure) variance_image = exposure.getMaskedImage().getVariance() variance_image += 100 exposure.getMaskedImage().getVariance().getArray()[203, 203] = np.nan add_psf_image(exposure, 200.0, 200.0, 600.0) # exposure.image.array += 20*np.random.randn(*exposure.image.array.shape) schema = afwTable.SourceTable.makeMinimalSchema() simultaneousPsfFlux_key = schema.addField( "crowd_psfFlux_flux_instFlux", type=np.float64, doc="PSF Flux from simultaneous fitting") afwTable.Point2DKey.addFields(schema, "coarse_centroid", "Detection peak", "pixels") centroid_key = afwTable.Point2DKey.addFields( schema, "new_centroid", "Measurement of centroid", "pixels") schema.getAliasMap().set("slot_Centroid", "coarse_centroid") schema.getAliasMap().set("slot_PsfFlux", "crowd_psfFlux_flux") source_catalog = afwTable.SourceCatalog(schema) child = source_catalog.addNew() child['coarse_centroid_x'] = 200.0 child['coarse_centroid_y'] = 200.5 # Fit once with fixed positions to get the fluxes matrix = CrowdedFieldMatrix(exposure, source_catalog, simultaneousPsfFlux_key, fitCentroids=False, centroidKey=centroid_key) matrix.solve() # Now that we have rough fluxes, re-fit and allow # centroids to move. matrix = CrowdedFieldMatrix(exposure, source_catalog, simultaneousPsfFlux_key, fitCentroids=True, centroidKey=centroid_key) result = matrix.solve() self.assertFloatsAlmostEqual(source_catalog[0]['new_centroid_x'], 200.0, atol=5e-2) self.assertFloatsAlmostEqual(source_catalog[0]['new_centroid_y'], 200.0, atol=5e-2)
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 = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.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.matcher.sourceSelector.config.minSnr = 0
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 test_solve(self): exposure = ExposureF(1000, 1000) psfConfig = InstallGaussianPsfConfig() psfConfig.fwhm = 4 psfTask = InstallGaussianPsfTask(config=psfConfig) psfTask.run(exposure=exposure) variance_image = exposure.getMaskedImage().getVariance() variance_image += 50 add_psf_image(exposure, 200.0, 400.0, 600.0) add_psf_image(exposure, 210.0, 210.0, 300.0) # These last two are to catch edge effects. add_psf_image(exposure, 5.0, 210.0, 400.0) add_psf_image(exposure, 300.0, 5.0, 500.0) matrix = CrowdedFieldMatrix(exposure, np.array([200.0, 210.0, 5.0, 300.0]), np.array([400.0, 210.0, 210.0, 5.0])) status = matrix.solve() self.assertEqual(status, matrix.SUCCESS) result = matrix.result() self.assertFloatsAlmostEqual(result, np.array([600.0, 300.0, 400.0, 500.0]), atol=1e-3)
def test_solve_catalog(self): exposure = ExposureF(1000, 1000) psfConfig = InstallGaussianPsfConfig() psfConfig.fwhm = 4 psfTask = InstallGaussianPsfTask(config=psfConfig) psfTask.run(exposure=exposure) variance_image = exposure.getMaskedImage().getVariance() variance_image += 50 add_psf_image(exposure, 200.0, 400.0, 600.0) add_psf_image(exposure, 210.0, 210.0, 300.0) schema = afwTable.SourceTable.makeMinimalSchema() schema.addField("centroid_x", type=np.float64) schema.addField("centroid_y", type=np.float64) flux_key = schema.addField("flux_flux", type=np.float64) schema.getAliasMap().set("slot_Centroid", "centroid") testCatalog = afwTable.SourceCatalog(schema) for x, y in zip([200.0, 210.0], [400.0, 210]): r = testCatalog.addNew() r["centroid_x"] = x r["centroid_y"] = y matrix = CrowdedFieldMatrix(exposure, testCatalog, flux_key) result = matrix.solve() self.assertFloatsAlmostEqual(testCatalog["flux_flux"], np.array([600.0, 300.0]), atol=1e-3)
def test_reject_maskedpixels(self): exposure = ExposureF(1000, 1000) psfConfig = InstallGaussianPsfConfig() psfConfig.fwhm = 4 psfTask = InstallGaussianPsfTask(config=psfConfig) psfTask.run(exposure=exposure) variance_image = exposure.getMaskedImage().getVariance() variance_image += 50 add_psf_image(exposure, 200.0, 400.0, 600.0) add_psf_image(exposure, 210.0, 210.0, 300.0) exposure.getMaskedImage().getImage()[200, 400] += 10000 mask_dict = exposure.getMaskedImage().getMask().getMaskPlaneDict() exposure.getMaskedImage().getMask()[200, 400] |= mask_dict['SAT'] matrix = CrowdedFieldMatrix(exposure, np.array([200.0, 210.0]), np.array([400.0, 210.0])) status = matrix.solve() self.assertEqual(status, matrix.SUCCESS) result = matrix.result() self.assertFloatsAlmostEqual(result, np.array([600.0, 300.0]), atol=1e-3)
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 = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.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.matcher.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 back from an a.n.d catalogue""" 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] names = ref.getSchema().getNames() for b in ("u", "g", "r", "i", "z"): self.assertIn("%s_flux" % (b,), names) self.assertIn("%s_fluxSigma" % (b,), names)
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)
class CrowdedFieldMatrixTestCase(lsst.utils.tests.TestCase): def setUp(self): self.exposure = ExposureF(1000, 1000) psfConfig = InstallGaussianPsfConfig() psfConfig.fwhm = 4 psfTask = InstallGaussianPsfTask(config=psfConfig) psfTask.run(exposure=self.exposure) variance_image = self.exposure.getMaskedImage().getVariance() variance_image += 50 def test_singleSource(self): matrix = CrowdedFieldMatrix(self.exposure, np.array([200.0]), np.array([200.0])) self.assertGreater(len(matrix.getMatrixEntries()), 0) def test_multipleSources(self): x_arr = np.linspace(20.0, 60.0, 20) y_arr = np.linspace(30.0, 70.0, 20) matrix = CrowdedFieldMatrix(self.exposure, x_arr, y_arr) self.assertGreater(len(matrix.getMatrixEntries()), 0) def test_unequalLengths(self): x_arr = np.linspace(20.0, 60.0, 20) y_arr = np.linspace(30.0, 70.0, 21) # Note 21 != 20 with self.assertRaises(lsst.pex.exceptions.wrappers.LengthError): matrix = CrowdedFieldMatrix(self.exposure, x_arr, y_arr) def test_createFromCatalog(self): schema = afwTable.SourceTable.makeMinimalSchema() schema.addField("centroid_x", type=np.float64) schema.addField("centroid_y", type=np.float64) flux_key = schema.addField("flux_flux", type=np.float64) schema.getAliasMap().set("slot_Centroid", "centroid") testCatalog = afwTable.SourceCatalog(schema) for n in range(20): r = testCatalog.addNew() r["centroid_x"] = n * 3 r["centroid_y"] = n * 3 matrix = CrowdedFieldMatrix(self.exposure, testCatalog, flux_key) self.assertGreater(len(matrix.getMatrixEntries()), 0) @unittest.skip def test_renameMatrixRows(self): # # Haven't figured out how to get access to pre-renaming matrix # to do the comparision with the post-renaming one. # pre_rename_entries = matrix.getMatrixEntries() matrix.renameMatrixRows() matrix = CrowdedFieldMatrix(self.exposure, np.array([200.0, 200.0]), np.array([204.0, 204.0])) post_rename_entries = matrix.getMatrixEntries() self.assertEqual(len(pre_rename_entries), len(post_rename_entries)) # We check that the count of rows that appear a given number of times # remains the same, since this is invariant under renaming. pre_counter = Counter(x[1] for x in pre_rename_entries) post_counter = Counter(x[1] for x in post_rename_entries) pre_counts = list(pre_counter.values()) post_counts = list(post_counter.values()) pre_counts.sort() post_counts.sort() self.assertListEqual(pre_counts, post_counts) def test_solve(self): exposure = ExposureF(1000, 1000) psfConfig = InstallGaussianPsfConfig() psfConfig.fwhm = 4 psfTask = InstallGaussianPsfTask(config=psfConfig) psfTask.run(exposure=exposure) variance_image = exposure.getMaskedImage().getVariance() variance_image += 50 add_psf_image(exposure, 200.0, 400.0, 600.0) add_psf_image(exposure, 210.0, 210.0, 300.0) # These last two are to catch edge effects. add_psf_image(exposure, 5.0, 210.0, 400.0) add_psf_image(exposure, 300.0, 5.0, 500.0) matrix = CrowdedFieldMatrix(exposure, np.array([200.0, 210.0, 5.0, 300.0]), np.array([400.0, 210.0, 210.0, 5.0])) status = matrix.solve() self.assertEqual(status, matrix.SUCCESS) result = matrix.result() self.assertFloatsAlmostEqual(result, np.array([600.0, 300.0, 400.0, 500.0]), atol=1e-3) def test_solve_catalog(self): exposure = ExposureF(1000, 1000) psfConfig = InstallGaussianPsfConfig() psfConfig.fwhm = 4 psfTask = InstallGaussianPsfTask(config=psfConfig) psfTask.run(exposure=exposure) variance_image = exposure.getMaskedImage().getVariance() variance_image += 50 add_psf_image(exposure, 200.0, 400.0, 600.0) add_psf_image(exposure, 210.0, 210.0, 300.0) schema = afwTable.SourceTable.makeMinimalSchema() schema.addField("centroid_x", type=np.float64) schema.addField("centroid_y", type=np.float64) flux_key = schema.addField("flux_flux", type=np.float64) schema.getAliasMap().set("slot_Centroid", "centroid") testCatalog = afwTable.SourceCatalog(schema) for x, y in zip([200.0, 210.0], [400.0, 210]): r = testCatalog.addNew() r["centroid_x"] = x r["centroid_y"] = y matrix = CrowdedFieldMatrix(exposure, testCatalog, flux_key) result = matrix.solve() self.assertFloatsAlmostEqual(testCatalog["flux_flux"], np.array([600.0, 300.0]), atol=1e-3) def test_reject_maskedpixels(self): exposure = ExposureF(1000, 1000) psfConfig = InstallGaussianPsfConfig() psfConfig.fwhm = 4 psfTask = InstallGaussianPsfTask(config=psfConfig) psfTask.run(exposure=exposure) variance_image = exposure.getMaskedImage().getVariance() variance_image += 50 add_psf_image(exposure, 200.0, 400.0, 600.0) add_psf_image(exposure, 210.0, 210.0, 300.0) exposure.getMaskedImage().getImage()[200, 400] += 10000 mask_dict = exposure.getMaskedImage().getMask().getMaskPlaneDict() exposure.getMaskedImage().getMask()[200, 400] |= mask_dict['SAT'] matrix = CrowdedFieldMatrix(exposure, np.array([200.0, 210.0]), np.array([400.0, 210.0])) status = matrix.solve() self.assertEqual(status, matrix.SUCCESS) result = matrix.result() self.assertFloatsAlmostEqual(result, np.array([600.0, 300.0]), atol=1e-3) @unittest.skip def test_solve_subimage(self): exposure = ExposureF(1000, 1000) psfConfig = InstallGaussianPsfConfig() psfConfig.fwhm = 4 psfTask = InstallGaussianPsfTask(config=psfConfig) psfTask.run(exposure=exposure) variance_image = exposure.getMaskedImage().getVariance() variance_image += 50 self.add_psf_image(exposure, 200.0, 400.0, 600.0) self.add_psf_image(exposure, 210.0, 210.0, 300.0) matrix = CrowdedFieldMatrix(exposure, np.array([200.0, 210.0]), np.array([400.0, 210.0])) status = matrix.solve() self.assertEqual(status, matrix.SUCCESS) result = matrix.result() self.assertFloatsAlmostEqual(result, np.array([600.0, 300.0]), atol=1e-3) def test_solve_centroid(self): exposure = ExposureF(400, 400) psfConfig = InstallGaussianPsfConfig() psfConfig.fwhm = 4 psfTask = InstallGaussianPsfTask(config=psfConfig) psfTask.run(exposure=exposure) variance_image = exposure.getMaskedImage().getVariance() variance_image += 100 exposure.getMaskedImage().getVariance().getArray()[203, 203] = np.nan add_psf_image(exposure, 200.0, 200.0, 600.0) # exposure.image.array += 20*np.random.randn(*exposure.image.array.shape) schema = afwTable.SourceTable.makeMinimalSchema() simultaneousPsfFlux_key = schema.addField( "crowd_psfFlux_flux_instFlux", type=np.float64, doc="PSF Flux from simultaneous fitting") afwTable.Point2DKey.addFields(schema, "coarse_centroid", "Detection peak", "pixels") centroid_key = afwTable.Point2DKey.addFields( schema, "new_centroid", "Measurement of centroid", "pixels") schema.getAliasMap().set("slot_Centroid", "coarse_centroid") schema.getAliasMap().set("slot_PsfFlux", "crowd_psfFlux_flux") source_catalog = afwTable.SourceCatalog(schema) child = source_catalog.addNew() child['coarse_centroid_x'] = 200.0 child['coarse_centroid_y'] = 200.5 # Fit once with fixed positions to get the fluxes matrix = CrowdedFieldMatrix(exposure, source_catalog, simultaneousPsfFlux_key, fitCentroids=False, centroidKey=centroid_key) matrix.solve() # Now that we have rough fluxes, re-fit and allow # centroids to move. matrix = CrowdedFieldMatrix(exposure, source_catalog, simultaneousPsfFlux_key, fitCentroids=True, centroidKey=centroid_key) result = matrix.solve() self.assertFloatsAlmostEqual(source_catalog[0]['new_centroid_x'], 200.0, atol=5e-2) self.assertFloatsAlmostEqual(source_catalog[0]['new_centroid_y'], 200.0, atol=5e-2)