def testConstructImage(self):
        """Test construction of image from the spectrum

        Reverse process of extraction.
        """
        spectrum = drpStella.Spectrum(self.fullDims.getY(), self.fiberId)
        spectrum.spectrum[self.xy0.getY():self.xy0.getY() + self.height] = 1.0
        image = self.fiberTrace.constructImage(spectrum, self.bbox)
        self.assertEqual(image.getBBox(), self.bbox)
        self.assertImagesEqual(image[self.bbox, lsst.afw.image.PARENT], self.subimage.image)
        image[self.bbox, lsst.afw.image.PARENT].set(0.0)
        self.assertFloatsEqual(image.array, 0.0)

        # Modify provided image
        image.set(0.0)
        self.fiberTrace.constructImage(image, spectrum)
        self.assertImagesEqual(image[self.bbox, lsst.afw.image.PARENT], self.subimage.image)
        # Check that we're actually adding, not simply setting
        self.fiberTrace.constructImage(image, spectrum)
        self.image += self.image
        self.assertImagesEqual(image[self.bbox, lsst.afw.image.PARENT], self.subimage.image)
        image[self.bbox, lsst.afw.image.PARENT].set(0.0)
        self.assertFloatsEqual(image.array, 0.0)
Beispiel #2
0
    def setUp(self):
        width, height = 250, 500
        self.numAmps = 4
        numPixelsPerAmp = 1000
        # crosstalk[i][j] is the fraction of the j-th amp present on the i-th
        # amp.
        self.crosstalk = [[0.0, 1e-4, 2e-4, 3e-4], [3e-4, 0.0, 2e-4, 1e-4],
                          [4e-4, 5e-4, 0.0, 6e-4], [7e-4, 8e-4, 9e-4, 0.0]]
        self.value = 12345
        self.crosstalkStr = "XTLK"

        # A bit of noise is important, because otherwise the pixel
        # distributions are razor-thin and then rejection doesn't work.
        rng = np.random.RandomState(12345)
        self.noise = rng.normal(0.0, 0.1, (2 * height, 2 * width))

        # Create amp images
        withoutCrosstalk = [
            lsst.afw.image.ImageF(width, height) for _ in range(self.numAmps)
        ]
        for image in withoutCrosstalk:
            image.set(0)
            xx = rng.randint(0, width, numPixelsPerAmp)
            yy = rng.randint(0, height, numPixelsPerAmp)
            image.getArray()[yy, xx] = self.value

        # Add in crosstalk
        withCrosstalk = [
            image.Factory(image, True) for image in withoutCrosstalk
        ]
        for ii, iImage in enumerate(withCrosstalk):
            for jj, jImage in enumerate(withoutCrosstalk):
                value = self.crosstalk[ii][jj]
                iImage.scaledPlus(value, jImage)

        # Put amp images together
        def construct(imageList):
            image = lsst.afw.image.ImageF(2 * width, 2 * height)
            image.getArray()[:height, :width] = imageList[0].getArray()
            image.getArray()[:height,
                             width:] = imageList[1].getArray()[:, ::
                                                               -1]  # flip in x
            image.getArray()[height:, :width] = imageList[2].getArray(
            )[::-1, :]  # flip in y
            image.getArray()[height:, width:] = imageList[3].getArray(
            )[::-1, ::-1]  # flip in x and y
            image.getArray()[:] += self.noise
            return image

        # Construct detector
        detName = 'detector 1'
        detId = 1
        detSerial = 'serial 1'
        orientation = cameraGeom.Orientation()
        pixelSize = lsst.geom.Extent2D(1, 1)
        bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
                               lsst.geom.Extent2I(2 * width, 2 * height))
        crosstalk = np.array(self.crosstalk, dtype=np.float32)

        camBuilder = cameraGeom.Camera.Builder("fakeCam")
        detBuilder = camBuilder.add(detName, detId)
        detBuilder.setSerial(detSerial)
        detBuilder.setBBox(bbox)
        detBuilder.setOrientation(orientation)
        detBuilder.setPixelSize(pixelSize)
        detBuilder.setCrosstalk(crosstalk)

        # Construct second detector in this fake camera
        detName = 'detector 2'
        detId = 2
        detSerial = 'serial 2'
        orientation = cameraGeom.Orientation()
        pixelSize = lsst.geom.Extent2D(1, 1)
        bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
                               lsst.geom.Extent2I(2 * width, 2 * height))
        crosstalk = np.array(self.crosstalk, dtype=np.float32)

        detBuilder2 = camBuilder.add(detName, detId)
        detBuilder2.setSerial(detSerial)
        detBuilder2.setBBox(bbox)
        detBuilder2.setOrientation(orientation)
        detBuilder2.setPixelSize(pixelSize)
        detBuilder2.setCrosstalk(crosstalk)

        # Create amp info
        for ii, (xx, yy, corner) in enumerate([
            (0, 0, lsst.afw.cameraGeom.ReadoutCorner.LL),
            (width, 0, lsst.afw.cameraGeom.ReadoutCorner.LR),
            (0, height, lsst.afw.cameraGeom.ReadoutCorner.UL),
            (width, height, lsst.afw.cameraGeom.ReadoutCorner.UR)
        ]):

            amp = cameraGeom.Amplifier.Builder()
            amp.setName("amp %d" % ii)
            amp.setBBox(
                lsst.geom.Box2I(lsst.geom.Point2I(xx, yy),
                                lsst.geom.Extent2I(width, height)))
            amp.setRawDataBBox(
                lsst.geom.Box2I(lsst.geom.Point2I(xx, yy),
                                lsst.geom.Extent2I(width, height)))
            amp.setReadoutCorner(corner)
            detBuilder.append(amp)
            detBuilder2.append(amp)

        cam = camBuilder.finish()
        ccd1 = cam.get('detector 1')
        ccd2 = cam.get('detector 2')

        self.exposure = lsst.afw.image.makeExposure(
            lsst.afw.image.makeMaskedImage(construct(withCrosstalk)))
        self.exposure.setDetector(ccd1)

        # Create a single ctSource that will be used for interChip CT
        # correction.
        self.ctSource = lsst.afw.image.makeExposure(
            lsst.afw.image.makeMaskedImage(construct(withCrosstalk)))
        self.ctSource.setDetector(ccd2)

        self.corrected = construct(withoutCrosstalk)

        if display:
            disp = lsst.afw.display.Display(frame=1)
            disp.mtv(self.exposure, title="exposure")
            disp = lsst.afw.display.Display(frame=0)
            disp.mtv(self.corrected, title="corrected exposure")
Beispiel #3
0
    def makeImage(self, ImageClass, scaling, addNoise=True):
        """Make an image for testing

        We create an image, persist and unpersist it, returning
        some data to the caller.

        Parameters
        ----------
        ImageClass : `type`, an `lsst.afw.image.Image` class
            Class of image to create.
        scaling : `lsst.afw.fits.ImageScalingOptions`
            Scaling to apply during persistence.
        addNoise : `bool`
            Add noise to image?

        Returns
        -------
        image : `lsst.afw.image.Image` (ImageClass)
            Created image.
        unpersisted : `lsst.afw.image.Image` (ImageClass)
            Unpersisted image.
        bscale, bzero : `float`
            FITS scale factor and zero used.
        minValue, maxValue : `float`
            Minimum and maximum value given the nominated scaling.
        """
        image = ImageClass(self.bbox)
        mask = lsst.afw.image.Mask(self.bbox)
        mask.addMaskPlane(self.badMask)
        bad = mask.getPlaneBitMask(self.badMask)
        image.set(self.base)
        image[self.highPixel, LOCAL] = self.highValue
        image[self.lowPixel, LOCAL] = self.lowValue
        image[self.maskedPixel, LOCAL] = self.maskedValue
        mask[self.maskedPixel, LOCAL] = bad

        rng = np.random.RandomState(12345)
        dtype = image.getArray().dtype
        if addNoise:
            image.getArray()[:] += rng.normal(
                0.0, self.stdev,
                image.getArray().shape).astype(dtype)

        with lsst.utils.tests.getTempFilePath(".fits") as filename:
            with lsst.afw.fits.Fits(filename, "w") as fits:
                options = lsst.afw.fits.ImageWriteOptions(scaling)
                header = lsst.daf.base.PropertyList()
                image.writeFits(fits, options, header, mask)
            unpersisted = ImageClass(filename)
            self.assertEqual(image.getBBox(), unpersisted.getBBox())

            header = lsst.afw.fits.readMetadata(filename)
            bscale = header.getScalar("BSCALE")
            bzero = header.getScalar("BZERO")

            if scaling.algorithm != ImageScalingOptions.NONE:
                self.assertEqual(header.getScalar("BITPIX"), scaling.bitpix)

            if scaling.bitpix == 8:  # unsigned, says FITS
                maxValue = bscale * (2**scaling.bitpix - 1) + bzero
                minValue = bzero
            else:
                maxValue = bscale * (2**(scaling.bitpix - 1) - 1) + bzero
                if scaling.bitpix == 32:
                    # cfitsio pads 10 values, and so do we
                    minValue = -bscale * (2**(scaling.bitpix - 1) - 10) + bzero
                else:
                    minValue = -bscale * (2**(scaling.bitpix - 1)) + bzero

            # Convert scalars to the appropriate type
            maxValue = np.array(maxValue, dtype=image.getArray().dtype)
            minValue = np.array(minValue, dtype=image.getArray().dtype)

            checkAstropy(unpersisted, filename)

        return image, unpersisted, bscale, bzero, minValue, maxValue
    def setUp(self):
        width, height = 250, 500
        self.numAmps = 4
        numPixelsPerAmp = 1000
        # crosstalk[i][j] is the fraction of the j-th amp present on the i-th amp.
        self.crosstalk = [[0.0, 1e-4, 2e-4, 3e-4], [3e-4, 0.0, 2e-4, 1e-4],
                          [4e-4, 5e-4, 0.0, 6e-4], [7e-4, 8e-4, 9e-4, 0.0]]
        self.value = 12345
        self.crosstalkStr = "XTLK"

        # A bit of noise is important, because otherwise the pixel distributions are razor-thin
        # and then rejection doesn't work
        rng = np.random.RandomState(12345)
        self.noise = rng.normal(0.0, 0.1, (2 * height, 2 * width))

        # Create amp images
        withoutCrosstalk = [
            lsst.afw.image.ImageF(width, height) for _ in range(self.numAmps)
        ]
        for image in withoutCrosstalk:
            image.set(0)
            xx = rng.randint(0, width, numPixelsPerAmp)
            yy = rng.randint(0, height, numPixelsPerAmp)
            image.getArray()[yy, xx] = self.value

        # Add in crosstalk
        withCrosstalk = [
            image.Factory(image, True) for image in withoutCrosstalk
        ]
        for ii, iImage in enumerate(withCrosstalk):
            for jj, jImage in enumerate(withoutCrosstalk):
                value = self.crosstalk[ii][jj]
                iImage.scaledPlus(value, jImage)

        # Put amp images together
        def construct(imageList):
            image = lsst.afw.image.ImageF(2 * width, 2 * height)
            image.getArray()[:height, :width] = imageList[0].getArray()
            image.getArray()[:height,
                             width:] = imageList[1].getArray()[:, ::
                                                               -1]  # flip in x
            image.getArray()[height:, :width] = imageList[2].getArray(
            )[::-1, :]  # flip in y
            image.getArray()[height:, width:] = imageList[3].getArray(
            )[::-1, ::-1]  # flip in x and y
            image.getArray()[:] += self.noise
            return image

        # Create amp info
        schema = lsst.afw.table.AmpInfoTable.makeMinimalSchema()
        amplifiers = lsst.afw.table.AmpInfoCatalog(schema)
        for ii, (xx, yy, corner) in enumerate([(0, 0, LL), (width, 0, LR),
                                               (0, height, UL),
                                               (width, height, UR)]):
            amp = amplifiers.addNew()
            amp.setName("amp %d" % ii)
            amp.setBBox(
                lsst.afw.geom.Box2I(lsst.afw.geom.Point2I(xx, yy),
                                    lsst.afw.geom.Extent2I(width, height)))
            amp.setRawDataBBox(
                lsst.afw.geom.Box2I(lsst.afw.geom.Point2I(xx, yy),
                                    lsst.afw.geom.Extent2I(width, height)))
            amp.setReadoutCorner(corner)

        # Put everything together
        ccd = lsst.afw.cameraGeom.Detector(
            "detector", 123, lsst.afw.cameraGeom.SCIENCE, "serial",
            lsst.afw.geom.Box2I(lsst.afw.geom.Point2I(0, 0),
                                lsst.afw.geom.Extent2I(2 * width, 2 * height)),
            amplifiers, lsst.afw.cameraGeom.Orientation(),
            lsst.afw.geom.Extent2D(1, 1), {},
            np.array(self.crosstalk, dtype=np.float32))

        self.exposure = lsst.afw.image.makeExposure(
            lsst.afw.image.makeMaskedImage(construct(withCrosstalk)))
        self.exposure.setDetector(ccd)

        self.corrected = construct(withoutCrosstalk)

        if display:
            disp = lsst.afw.display.Display(frame=1)
            disp.mtv(self.exposure, title="exposure")
            disp = lsst.afw.display.Display(frame=0)
            disp.mtv(self.corrected, title="corrected exposure")
    def setUp(self):
        width, height = 250, 500
        self.numAmps = 4
        numPixelsPerAmp = 1000
        # crosstalk[i][j] is the fraction of the j-th amp present on the i-th amp.
        self.crosstalk = [[0.0, 1e-4, 2e-4, 3e-4],
                          [3e-4, 0.0, 2e-4, 1e-4],
                          [4e-4, 5e-4, 0.0, 6e-4],
                          [7e-4, 8e-4, 9e-4, 0.0]]
        self.value = 12345
        self.crosstalkStr = "XTLK"

        # A bit of noise is important, because otherwise the pixel distributions are razor-thin
        # and then rejection doesn't work
        rng = np.random.RandomState(12345)
        self.noise = rng.normal(0.0, 0.1, (2*height, 2*width))

        # Create amp images
        withoutCrosstalk = [lsst.afw.image.ImageF(width, height) for _ in range(self.numAmps)]
        for image in withoutCrosstalk:
            image.set(0)
            xx = rng.randint(0, width, numPixelsPerAmp)
            yy = rng.randint(0, height, numPixelsPerAmp)
            image.getArray()[yy, xx] = self.value

        # Add in crosstalk
        withCrosstalk = [image.Factory(image, True) for image in withoutCrosstalk]
        for ii, iImage in enumerate(withCrosstalk):
            for jj, jImage in enumerate(withoutCrosstalk):
                value = self.crosstalk[ii][jj]
                iImage.scaledPlus(value, jImage)

        # Put amp images together
        def construct(imageList):
            image = lsst.afw.image.ImageF(2*width, 2*height)
            image.getArray()[:height, :width] = imageList[0].getArray()
            image.getArray()[:height, width:] = imageList[1].getArray()[:, ::-1]  # flip in x
            image.getArray()[height:, :width] = imageList[2].getArray()[::-1, :]  # flip in y
            image.getArray()[height:, width:] = imageList[3].getArray()[::-1, ::-1]  # flip in x and y
            image.getArray()[:] += self.noise
            return image

        # Create amp info
        schema = lsst.afw.table.AmpInfoTable.makeMinimalSchema()
        amplifiers = lsst.afw.table.AmpInfoCatalog(schema)
        for ii, (xx, yy, corner) in enumerate([(0, 0, LL),
                                               (width, 0, LR),
                                               (0, height, UL),
                                               (width, height, UR)]):
            amp = amplifiers.addNew()
            amp.setName("amp %d" % ii)
            amp.setBBox(lsst.afw.geom.Box2I(lsst.afw.geom.Point2I(xx, yy),
                                            lsst.afw.geom.Extent2I(width, height)))
            amp.setRawDataBBox(lsst.afw.geom.Box2I(lsst.afw.geom.Point2I(xx, yy),
                                                   lsst.afw.geom.Extent2I(width, height)))
            amp.setReadoutCorner(corner)

        # Put everything together
        ccd = lsst.afw.cameraGeom.Detector("detector", 123, lsst.afw.cameraGeom.SCIENCE, "serial",
                                           lsst.afw.geom.Box2I(lsst.afw.geom.Point2I(0, 0),
                                                               lsst.afw.geom.Extent2I(2*width, 2*height)),
                                           amplifiers, lsst.afw.cameraGeom.Orientation(),
                                           lsst.afw.geom.Extent2D(1, 1), {},
                                           np.array(self.crosstalk, dtype=np.float32))

        self.exposure = lsst.afw.image.makeExposure(lsst.afw.image.makeMaskedImage(construct(withCrosstalk)))
        self.exposure.setDetector(ccd)

        self.corrected = construct(withoutCrosstalk)

        if display:
            disp = lsst.afw.display.Display(frame=1)
            disp.mtv(self.exposure, title="exposure")
            disp = lsst.afw.display.Display(frame=0)
            disp.mtv(self.corrected, title="corrected exposure")