Exemplo n.º 1
0
 def setUp(self):
     # Test geometry:
     #
     # -100,99                99,99
     #     +--------------------+
     #     |AAAAAAAAAACCCCCDDDDD|    A == only in epoch A
     #     |AAAAAAAAAACCCCCDDDDD|    B == only in epoch B
     #     |AAAAAAAAAACCCCCDDDDD|    C == in both epoch A and epoch B
     #     |AAAAAAAAAACCCCCDDDDD|    D == in epoch A; in B's bbox but outside its ValidPolygon
     #     |AAAAAAAAAACCCCCDDDDD|
     #     |          BBBBBBBBBB|    All WCSs have the same CRVAL and CD.
     #     |          BBBBBBBBBB|
     #     |          BBBBBBBBBB|    Coadd has CRPIX=(0, 0)
     #     |          BBBBBBBBBB|    Epoch A has CRPIX=(0, -50)
     #     |          BBBBBBBBBB|    Epoch B has CRPIX=(-50, 0)
     #     +--------------------+
     # -100,-100             99,-100
     #
     self.rng = np.random.RandomState(50)
     crval = SpherePoint(45.0, 45.0, degrees)
     cdMatrix = makeCdMatrix(scale=5E-5 * degrees, flipX=True)
     self.wcsCoadd = makeSkyWcs(crpix=Point2D(0.0, 0.0),
                                crval=crval,
                                cdMatrix=cdMatrix)
     self.wcsA = makeSkyWcs(crpix=Point2D(0.0, -50.0),
                            crval=crval,
                            cdMatrix=cdMatrix)
     self.wcsB = makeSkyWcs(crpix=Point2D(-50.0, 0.0),
                            crval=crval,
                            cdMatrix=cdMatrix)
     self.bboxCoadd = Box2I(Point2I(-100, -100), Point2I(99, 99))
     self.bboxA = Box2I(Point2I(-100, -50), Point2I(99, 49))
     self.bboxB = Box2I(Point2I(-50, -100), Point2I(49, 99))
     self.polygonA = None
     polygonD = Polygon(Box2D(Box2I(Point2I(0, 0), Point2I(49, 99))))
     self.polygonB, = polygonD.symDifference(Polygon(Box2D(self.bboxB)))
     self.curveA = makeRandomTransmissionCurve(self.rng)
     self.curveB = makeRandomTransmissionCurve(self.rng)
     self.weightA = 0.6
     self.weightB = 0.2
     schema = ExposureTable.makeMinimalSchema()
     weightKey = schema.addField("weight",
                                 type=float,
                                 doc="relative weight of image in Coadd")
     catalog = ExposureCatalog(schema)
     recordA = catalog.addNew()
     recordA[weightKey] = self.weightA
     recordA.setWcs(self.wcsA)
     recordA.setValidPolygon(self.polygonA)
     recordA.setBBox(self.bboxA)
     recordA.setTransmissionCurve(self.curveA)
     recordB = catalog.addNew()
     recordB[weightKey] = self.weightB
     recordB.setWcs(self.wcsB)
     recordB.setValidPolygon(self.polygonB)
     recordB.setBBox(self.bboxB)
     recordB.setTransmissionCurve(self.curveB)
     self.curveCoadd = makeCoaddTransmissionCurve(self.wcsCoadd, catalog)
Exemplo n.º 2
0
    def setUp(self):
        xy0 = Point2I(12345, 67890)  # xy0 for image
        dims = Extent2I(2345, 2345)  # Dimensions of image
        box = Box2I(xy0, dims)  # Bounding box of image
        sigma = 3.21  # PSF sigma
        buffer = 4.0  # Buffer for star centers around edge
        nSigmaForKernel = 5.0  # Number of PSF sigmas for kernel
        sky = 12345.6  # Sky level
        numStars = 100  # Number of stars
        noise = np.sqrt(sky) * np.pi * sigma**2  # Poisson noise per PSF
        faint = 1.0 * noise  # Faintest level for star fluxes
        bright = 100.0 * noise  # Brightest level for star fluxes
        starBox = Box2I(box)  # Area on image in which we can put star centers
        starBox.grow(-int(buffer * sigma))
        scale = 1.0e-5 * degrees  # Pixel scale

        np.random.seed(12345)
        stars = [(xx, yy, ff, sigma) for xx, yy, ff in zip(
            np.random.uniform(starBox.getMinX(), starBox.getMaxX(), numStars),
            np.random.uniform(starBox.getMinY(), starBox.getMaxY(), numStars),
            np.linspace(faint, bright, numStars))]
        self.exposure = plantSources(box, 2 * int(nSigmaForKernel * sigma) + 1,
                                     sky, stars, True)
        self.exposure.setWcs(
            makeSkyWcs(crpix=Point2D(0, 0),
                       crval=SpherePoint(0, 0, degrees),
                       cdMatrix=makeCdMatrix(scale=scale)))

        # Make a large area of extra background; we should be robust against it
        # Unfortunately, some tuning is required here to get something challenging but not impossible:
        # * A very large box will cause failures because the "extra" and the "normal" are reversed.
        # * A small box will not be challenging because it's simple to clip out.
        # * A large value will cause failures because it produces large edges in background-subtrction that
        #     broaden flux distributions.
        # * A small value will not be challenging because it has little effect.
        extraBox = Box2I(xy0 + Extent2I(345, 456),
                         Extent2I(1234, 1234))  # Box for extra background
        extraValue = 0.5 * noise  # Extra background value to add in
        self.exposure.image[extraBox, PARENT] += extraValue

        self.config = DynamicDetectionTask.ConfigClass()
        self.config.skyObjects.nSources = 300
        self.config.reEstimateBackground = False
        self.config.doTempWideBackground = True
        self.config.thresholdType = "pixel_stdev"

        # Relative tolerance for tweak factor
        # Not sure why this isn't smaller; maybe due to use of Poisson instead of Gaussian noise?
        self.rtol = 0.1
Exemplo n.º 3
0
    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))
Exemplo n.º 4
0
    def makeRandomPoint(self, *args, **kwds):
        """Draw a random Point2D within a Box2I.

        All arguments are forwarded directly to the Box2I constructor, allowing
        the caller to pass a fully-constructed Box2I, a (Point2I, Point2I) pair,
        or a (Point2I, Extent2I) pair.
        """
        bboxD = Box2D(Box2I(*args, **kwds))
        return bboxD.getMin() + Extent2D(bboxD.getWidth() * self.rng.rand(),
                                         bboxD.getHeight() * self.rng.rand())
Exemplo n.º 5
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
Exemplo n.º 6
0
def extractCtorArgs(md):
    wcs = makeSkyWcs(makePropertyListFromDict(md))
    kwds = {
        "pixelToIwc": getPixelToIntermediateWorldCoords(wcs),
        "bbox":
        Box2D(Box2I(Point2I(0, 0), Extent2I(md["NAXES1"], md["NAXES2"]))),
        "crpix":
        Point2D(md["CRPIX1"] - 1.0,
                md["CRPIX2"] - 1.0),  # -1 for LSST vs. FITS conventions
        "cd": np.array([[md["CD1_1"], md["CD1_2"]], [md["CD2_1"],
                                                     md["CD2_2"]]]),
    }
    return kwds
    def testBasics(self):
        """Test detection and measurement on simple synthesized data
        """
        bbox = Box2I(Point2I(256, 100), Extent2I(128, 127))
        minCounts = 5000
        maxCounts = 50000
        starSigma = 1.5
        numX = 5
        numY = 5
        coordList = self.makeCoordList(
            bbox=bbox,
            numX=numX,
            numY=numY,
            minCounts=minCounts,
            maxCounts=maxCounts,
            sigma=starSigma,
        )
        kwid = 11  # kernel width
        sky = 2000
        # create an exposure without a Wcs; add the Wcs later
        exposure = plantSources(bbox=bbox,
                                kwid=kwid,
                                sky=sky,
                                coordList=coordList,
                                addPoissonNoise=True)

        schema = SourceTable.makeMinimalSchema()

        config = DetectAndMeasureTask.ConfigClass()
        task = DetectAndMeasureTask(config=config, schema=schema)

        butler = Butler(root=InputDir)
        dataRef = butler.dataRef("calexp", dataId=dict(visit=1))
        wcs = dataRef.get("raw").getWcs()
        exposure.setWcs(wcs)
        exposureIdInfo = dataRef.get("expIdInfo")
        taskRes = task.run(exposure=exposure, exposureIdInfo=exposureIdInfo)
        self.assertEqual(len(taskRes.sourceCat), numX * numY)
        schema = taskRes.sourceCat.schema
        centroidFlagKey = schema.find("slot_Centroid_flag").getKey()
        parentKey = schema.find("parent").getKey()
        psfFluxFlagKey = schema.find("slot_PsfFlux_flag").getKey()
        psfFluxKey = schema.find("slot_PsfFlux_flux").getKey()
        for src in taskRes.sourceCat:
            self.assertFalse(src.get(centroidFlagKey))  # centroid found
            self.assertEqual(src.get(parentKey), 0)  # not debelended
            self.assertFalse(src.get(psfFluxFlagKey))  # flux measured
            self.assertGreater(src.get(psfFluxKey), 4000)  # flux sane
Exemplo n.º 8
0
def makeCasuWfcam():
    path = os.path.join(getPackageDir("obs_ukirt"), "casuWfcam", "camera")

    for detNum, (gain, sat) in enumerate(zip(GAIN, SATURATION), 1):
        det = AmpInfoCatalog(AmpInfoTable.makeMinimalSchema())
        amp = det.addNew()
        amp.setName(str(detNum))
        amp.setBBox(Box2I())
        amp.setGain(gain)
        amp.setReadNoise(READNOISE)
        amp.setSaturation(sat)
        #        amp.setSuspectLevel(float("nan"))
        amp.setReadoutCorner(LL)
        amp.setLinearityType("none")
        amp.setHasRawInfo(False)

        det.writeFits(os.path.join(path, "%d.fits" % (detNum, )))
Exemplo n.º 9
0
 def setUp(self):
     self.crpix = Point2D(100, 100)
     self.crvalList = [
         SpherePoint(0 * degrees, 45 * degrees),
         SpherePoint(0.00001 * degrees, 45 * degrees),
         SpherePoint(359.99999 * degrees, 45 * degrees),
         SpherePoint(30 * degrees, 89.99999 * degrees),
         SpherePoint(30 * degrees, -89.99999 * degrees),
     ]
     self.orientationList = [
         0 * degrees,
         0.00001 * degrees,
         -0.00001 * degrees,
         -45 * degrees,
         90 * degrees,
     ]
     self.scale = 1.0 * arcseconds
     self.tinyPixels = 1.0e-10
     self.tinyAngle = 1.0e-10 * radians
     self.bbox = Box2I(Point2I(-1000, -1000),
                       Extent2I(2000, 2000))  # arbitrary but reasonable
Exemplo n.º 10
0
 def setUp(self):
     # ImageL (uint64) is not supported by FITS standard, needs special tests
     self.IntegerImages = (afwImage.ImageU, afwImage.ImageI)
     self.FloatImages = (afwImage.ImageF, afwImage.ImageD)
     self.bbox = Box2I(minimum=Point2I(3, 4), maximum=Point2I(9, 7))