Пример #1
0
    def readFits(cls, path):
        """Read an external detrended image and create an LSST Exposure object
        from it.

        Any significant processing (e.g. pixel interpolation) should probably
        be done in a ExternalIsrTask instead of here so it can be done once and
        saved, instead of being done every time the image is loaded.

        THIS METHOD IS INCOMPLETE; IT MUST BE MODIFIED ACCORDING TO THE
        FORMAT OF THE DATA BEING LOADED.
        """
        directory, filename = os.path.split(path)
        match = cls.EXTERNAL_REGEX.match(filename)
        camera = cls.getCameraFromVisit(match.group("visit"))

        # Customize the code below based on the camera determined above.
        # To support more than one camera it may be useful to delegate
        # to other methods that are specific to certain cameras.

        # Read the actual image in from the given path using e.g. astropy,
        # and use it to fill in various arrays below.

        bbox = Box2I(Point2I(0, 0), Extent2I(..., ...))  # width, height
        result = ExposureF(bbox)
        # main image, as a [y, x] numpy.float32 array
        result.image.array = ...
        # variance image, as a [y, x] numpy.float32 array
        result.variance.array = ...

        # This example includes masking NaN pixels as NO_DATA and pixels above
        # 1E5 counts as SAT.  External information about where bad pixels
        # should be preferred when available, and obviously that saturation
        # threshold is just an example (saturation should actually be
        # determined before flat-fielding, of course).
        # Interpolating these bad pixels is handled by ExternalIsrTask.
        noDataBitMask = result.mask.getPlaneBitMask("NO_DATA")
        satBitMask = result.mask.getPlaneBitMask("SAT")
        result.mask.array |= noDataBitMask * np.isnan(result.image.array)
        result.mask.array |= satBitMask * (result.image.array > 1E5)

        # If you have a better guess at the PSF, we can find a way to use it.
        # But it'd be a good idea to at least put this in with a guess at the
        # seeing (RMS in pixels).
        result.setPsf(SingleGaussianPsf(seeingRMS))

        # Add a guess for the WCS, in this case assuming it's in the FITS
        # header of the first HDU.  Need to have something here, even if it
        # isn't very good (e.g. whatever comes from the telescope).
        metadata = readMetadata(filename)
        wcs = SkyWcs(metadata)
        result.setWcs(wcs)

        return result
Пример #2
0
class FilterFractionTest(lsst.utils.tests.TestCase):
    def setUp(self):
        # Set up a Coadd with CoaddInputs tables that have blank filter columns to be filled
        # in by later test code.
        self.coadd = ExposureF(30, 90)
        # WCS is arbitrary, since it'll be the same for all images
        wcs = makeSkyWcs(crpix=Point2D(0, 0),
                         crval=SpherePoint(45.0, 45.0, degrees),
                         cdMatrix=makeCdMatrix(scale=0.17 * degrees))
        self.coadd.setWcs(wcs)
        schema = ExposureCatalog.Table.makeMinimalSchema()
        self.filterKey = schema.addField("filter", type=str, doc="", size=16)
        weightKey = schema.addField("weight", type=float, doc="")
        # First input image covers the first 2/3, second covers the last 2/3, so they
        # overlap in the middle 1/3.
        inputs = ExposureCatalog(schema)
        self.input1 = inputs.addNew()
        self.input1.setId(1)
        self.input1.setBBox(Box2I(Point2I(0, 0), Point2I(29, 59)))
        self.input1.setWcs(wcs)
        self.input1.set(weightKey, 2.0)
        self.input2 = inputs.addNew()
        self.input2.setId(2)
        self.input2.setBBox(Box2I(Point2I(0, 30), Point2I(29, 89)))
        self.input2.setWcs(wcs)
        self.input2.set(weightKey, 3.0)
        # Use the same catalog for visits and CCDs since the algorithm we're testing only cares
        # about CCDs.
        self.coadd.getInfo().setCoaddInputs(CoaddInputs(inputs, inputs))

        # Set up a catalog with centroids and a FilterFraction plugin.
        # We have one record in each region (first input only, both inputs, second input only)
        schema = SourceCatalog.Table.makeMinimalSchema()
        centroidKey = Point2DKey.addFields(schema,
                                           "centroid",
                                           doc="position",
                                           unit="pixel")
        schema.getAliasMap().set("slot_Centroid", "centroid")
        self.plugin = FilterFractionPlugin(
            config=FilterFractionPlugin.ConfigClass(),
            schema=schema,
            name="subaru_FilterFraction",
            metadata=PropertyList())
        catalog = SourceCatalog(schema)
        self.record1 = catalog.addNew()
        self.record1.set(centroidKey, Point2D(14.0, 14.0))
        self.record12 = catalog.addNew()
        self.record12.set(centroidKey, Point2D(14.0, 44.0))
        self.record2 = catalog.addNew()
        self.record2.set(centroidKey, Point2D(14.0, 74.0))

    def tearDown(self):
        del self.coadd
        del self.input1
        del self.input2
        del self.record1
        del self.record2
        del self.record12
        del self.plugin

    def testSingleFilter(self):
        """Test that we get FilterFraction=1 for filters with only one version."""
        self.input1.set(self.filterKey, "g")
        self.input2.set(self.filterKey, "g")
        self.plugin.measure(self.record1, self.coadd)
        self.plugin.measure(self.record12, self.coadd)
        self.plugin.measure(self.record2, self.coadd)
        self.assertEqual(self.record1.get("subaru_FilterFraction_unweighted"),
                         1.0)
        self.assertEqual(self.record12.get("subaru_FilterFraction_unweighted"),
                         1.0)
        self.assertEqual(self.record2.get("subaru_FilterFraction_unweighted"),
                         1.0)
        self.assertEqual(self.record1.get("subaru_FilterFraction_weighted"),
                         1.0)
        self.assertEqual(self.record12.get("subaru_FilterFraction_weighted"),
                         1.0)
        self.assertEqual(self.record2.get("subaru_FilterFraction_weighted"),
                         1.0)

    def testTwoFiltersI(self):
        """Test that we get the right answers for a mix of i and i2."""
        self.input1.set(self.filterKey, "i")
        self.input2.set(self.filterKey, "i2")
        self.plugin.measure(self.record1, self.coadd)
        self.plugin.measure(self.record12, self.coadd)
        self.plugin.measure(self.record2, self.coadd)
        self.assertEqual(self.record1.get("subaru_FilterFraction_unweighted"),
                         0.0)
        self.assertEqual(self.record12.get("subaru_FilterFraction_unweighted"),
                         0.5)
        self.assertEqual(self.record2.get("subaru_FilterFraction_unweighted"),
                         1.0)
        self.assertEqual(self.record1.get("subaru_FilterFraction_weighted"),
                         0.0)
        self.assertEqual(self.record12.get("subaru_FilterFraction_weighted"),
                         0.6)
        self.assertEqual(self.record2.get("subaru_FilterFraction_weighted"),
                         1.0)

    def testTwoFiltersR(self):
        """Test that we get the right answers for a mix of r and r2."""
        self.input1.set(self.filterKey, "r")
        self.input2.set(self.filterKey, "r2")
        self.plugin.measure(self.record1, self.coadd)
        self.plugin.measure(self.record12, self.coadd)
        self.plugin.measure(self.record2, self.coadd)
        self.assertEqual(self.record1.get("subaru_FilterFraction_unweighted"),
                         0.0)
        self.assertEqual(self.record12.get("subaru_FilterFraction_unweighted"),
                         0.5)
        self.assertEqual(self.record2.get("subaru_FilterFraction_unweighted"),
                         1.0)
        self.assertEqual(self.record1.get("subaru_FilterFraction_weighted"),
                         0.0)
        self.assertEqual(self.record12.get("subaru_FilterFraction_weighted"),
                         0.6)
        self.assertEqual(self.record2.get("subaru_FilterFraction_weighted"),
                         1.0)

    def testInvalidCombination(self):
        """Test that we get a fatal exception for weird combinations of filters."""
        self.input1.set(self.filterKey, "i")
        self.input2.set(self.filterKey, "r")
        with self.assertRaises(FatalAlgorithmError):
            self.plugin.measure(self.record12, self.coadd)
Пример #3
0
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)