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)
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")
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")