def _testMaskedImageCopy(testCase, maskedImage1): maskedImage2 = maskedImage1.clone() maskedImage2.setXY0(Point2I(11, 23)) testCase.assertEqual(maskedImage2.getBBox(), Box2I(Point2I(11, 23), Extent2I(200, 100))) testCase.assertEqual(maskedImage1.getBBox(), Box2I(Point2I(1000, 2000), Extent2I(200, 100))) testCase.assertTrue( np.all([ img.getBBox() == maskedImage1.getBBox() for img in maskedImage1.image ])) testCase.assertTrue( np.all([ img.getBBox() == maskedImage2.getBBox() for img in maskedImage2.image ])) maskedImage2.image.array = 1 testCase.assertFloatsEqual(maskedImage1.image.array, testCase.imgValue) testCase.assertFloatsEqual(maskedImage2.image.array, 1) testCase.assertFloatsEqual(maskedImage1["G"].image.array, testCase.imgValue) testCase.assertFloatsEqual(maskedImage2["G"].image.array, 1) maskedImage2 = maskedImage1.clone(False) maskedImage2.image.array = 1 testCase.assertFloatsEqual(maskedImage1.image.array, 1) testCase.assertFloatsEqual(maskedImage2.image.array, 1) testCase.assertFloatsEqual(maskedImage1["G"].image.array, 1) testCase.assertFloatsEqual(maskedImage2["G"].image.array, 1)
def test_getNumGoodPixels(self): """Test the the number of pixels in the image not masked is as expected.""" testImage = self.flatExp.clone() mi = testImage.maskedImage imageSize = testImage.getBBox().getArea() nGood = self.defaultTask.measure._getNumGoodPixels(mi) self.assertEqual(imageSize, nGood) NODATABIT = mi.mask.getPlaneBitMask("NO_DATA") noDataBox = Box2I(Point2I(31, 49), Extent2I(3, 6)) testImage.mask[noDataBox] |= NODATABIT self.assertEqual(imageSize - noDataBox.getArea(), self.defaultTask.measure._getNumGoodPixels(mi)) # check for misfire; we're setting NO_DATA here, not BAD self.assertEqual(imageSize, self.defaultTask.measure._getNumGoodPixels(mi, 'BAD')) testImage.mask[noDataBox] ^= NODATABIT # XOR to reset what we did self.assertEqual(imageSize, nGood) BADBIT = mi.mask.getPlaneBitMask("BAD") badBox = Box2I(Point2I(85, 98), Extent2I(4, 7)) testImage.mask[badBox] |= BADBIT self.assertEqual(imageSize - badBox.getArea(), self.defaultTask.measure._getNumGoodPixels(mi, 'BAD'))
def for_subimage(self, bbox: Box2I) -> ImageSectionTransform: """Return the transform that maps a subimage to the same coordinate system. Parameters ---------- bbox : `Box2I` Bounding box of the subimage that the new transform will operate on. Must satisfy ``self.input_bbox.contains(bbox)``. Returns ------- subimage_transform : `ImageSectionTransform` A transform whose ``input_bbox`` is the given ``bbox`` that maps it to the appropriate location within ``self.output_bbox`` and applies the same flips. """ # Distances (defined to be positive) between minimum points of both # boxes and maximum points of both boxes. lower_dist_x, lower_dist_y = bbox.getMin() - self.input_bbox.getMin() upper_dist_x, upper_dist_y = self.input_bbox.getMax() - bbox.getMax() if self.flip_x: lower_dist_x, upper_dist_x = upper_dist_x, lower_dist_x if self.flip_y: lower_dist_y, upper_dist_y = upper_dist_y, lower_dist_y output_bbox = Box2I( minimum=self.output_bbox.getMin() + ExtentI(lower_dist_x, lower_dist_y), maximum=self.output_bbox.getMax() - ExtentI(upper_dist_x, upper_dist_y), ) return ImageSectionTransform( input_bbox=bbox, output_bbox=output_bbox, flip_x=self.flip_x, flip_y=self.flip_y, )
def _testImageModification(testCase, mImage1, mImage2, bbox1, bbox2, value1, value2): """Test the image-like objects can be modified""" mImage1[:"R", bbox2].array = value2 testCase.assertFloatsEqual(mImage1["G", bbox2].array, mImage2["G"].array) testCase.assertFloatsEqual(mImage1["R"].array, value1) mImage1.setXY0(Point2I(500, 150)) testCase.assertEqual( mImage1.getBBox(), Box2I(Point2I(500, 150), Extent2I(bbox1.getDimensions()))) mImage1["G"].array[:] = value2 testCase.assertFloatsEqual(mImage1["G"].array, value2) testCase.assertFloatsEqual(mImage1.array[0], value2) if "Z" in mImage1.filters: filterSlice = slice("R", "Z") else: filterSlice = slice("R", None) mImage1[filterSlice].array[:] = 7 testCase.assertFloatsEqual(mImage1["I"].array, 7) newBBox = Box2I(Point2I(10000, 20000), mImage1.getBBox().getDimensions()) mImage1.setXY0(newBBox.getMin()) testCase.assertEqual(mImage1.getBBox(), newBBox) for image in mImage1: testCase.assertEqual(image.getBBox(), newBBox)
def _testImageCopy(testCase, mImage1, value1, value2): """Test copy and deep copy in image-like objects""" mImage2 = mImage1.clone() mImage2.setXY0(Point2I(11, 23)) testCase.assertEqual(mImage2.getBBox(), Box2I(Point2I(11, 23), Extent2I(200, 100))) testCase.assertEqual(mImage1.getBBox(), Box2I(Point2I(1000, 2000), Extent2I(200, 100))) testCase.assertTrue( np.all([s.getBBox() == mImage1.getBBox() for s in mImage1.singles])) testCase.assertTrue( np.all([s.getBBox() == mImage2.getBBox() for s in mImage2.singles])) mImage2.array[:] = 17 testCase.assertNotEqual(mImage1.array[0, 0, 0], 17) mImage2.array[:] = value2 testCase.assertFloatsEqual(mImage1.array, value1) testCase.assertFloatsEqual(mImage2.array, value2) testCase.assertFloatsEqual(mImage1["G"].array, value1) testCase.assertFloatsEqual(mImage2["G"].array, value2) mImage2 = mImage1.clone(False) mImage2.setXY0(Point2I(11, 23)) mImage2.array[:] = 17 testCase.assertFloatsEqual(mImage2.array, mImage1.array) mImage2.array[:] = value2 testCase.assertFloatsEqual(mImage1.array, value2) testCase.assertFloatsEqual(mImage2.array, value2) testCase.assertFloatsEqual(mImage1["G"].array, value2) testCase.assertFloatsEqual(mImage2["G"].array, value2)
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)
def _markBlocksInBadColumn(self, x, y, multipleX, defects): """Mask blocks in a column if number of on-and-off bad pixels is above threshold. This function is called if the number of on-and-off bad pixels in a column is larger or equal than self.config.badOnAndOffPixelColumnThreshold. Parameters --------- x: `list` Lower left x coordinate of defect box. x coordinate is along the short axis if amp. y: `list` Lower left y coordinate of defect box. x coordinate is along the long axis if amp. multipleX: list List of x coordinates in amp. with multiple bad pixels (i.e., columns with defects). defects: `lsst.ip.isr.Defect` The defcts found in the image so far Returns ------- defects: `lsst.ip.isr.Defect` The defects list returned that will include boxes that mask blocks of on-and-of pixels. """ with defects.bulk_update(): goodPixelColumnGapThreshold = self.config.goodPixelColumnGapThreshold for x0 in multipleX: index = np.where(x == x0) multipleY = y[ index] # multipleY and multipleX are in 1-1 correspondence. minY, maxY = np.min(multipleY), np.max(multipleY) # Next few lines: don't mask pixels in column if gap of good pixels between # two consecutive bad pixels is larger or equal than 'goodPixelColumnGapThreshold'. diffIndex = np.where( np.diff(multipleY) >= goodPixelColumnGapThreshold)[0] if len(diffIndex) != 0: limits = [minY] # put the minimum first for gapIndex in diffIndex: limits.append(multipleY[gapIndex]) limits.append(multipleY[gapIndex + 1]) limits.append(maxY) # maximum last assert len( limits ) % 2 == 0, 'limits is even by design, but check anyways' for i in np.arange(0, len(limits) - 1, 2): s = Box2I(minimum=Point2I(x0, limits[i]), maximum=Point2I(x0, limits[i + 1])) defects.append(s) else: # No gap is large enough s = Box2I(minimum=Point2I(x0, minY), maximum=Point2I(x0, maxY)) defects.append(s) return defects
def subimage(self, bbox: Box2I) -> NumPyImageSection: # Docstring inherited. start = bbox.getMin() - self._bbox_min stop = start + bbox.getSize() return NumPyImageSection( self._array[start.getY():stop.getY(), start.getX():stop.getX(), ...], # noqa:E203 bbox, )
def setUp(self): np.random.seed(1) self.bbox1 = Box2I(Point2I(1000, 2000), Extent2I(200, 100)) self.filters = ["G", "R", "I", "Z", "Y"] self.value1, self.value2 = 10, 100 images = [ImageF(self.bbox1, self.value1) for f in self.filters] self.mImage1 = MultibandImage.fromImages(self.filters, images) self.bbox2 = Box2I(Point2I(1100, 2025), Extent2I(30, 50)) images = [ImageF(self.bbox2, self.value2) for f in self.filters] self.mImage2 = MultibandImage.fromImages(self.filters, images)
def test_amp_curve(self): # Future versions of astropy will pass unit through concatenation amp_wavelength = np.concatenate([self.wavelength.value, self.wavelength.value])*u.angstrom # Two amps amp_efficiency = np.concatenate([self.efficiency.value, self.efficiency.value*0.8])*u.percent # Two amps amp_name = np.concatenate([['A' for el in self.wavelength], ['B' for el in self.wavelength]]) amplist = [MockAmp('A', Box2I(Point2I(0, 0), Extent2I(512, 1025))), MockAmp('B', Box2I(Point2I(512, 10), Extent2I(512, 1024)))] args = (amp_name, amp_wavelength, amp_efficiency, self.metadata) self.curve_tester(algorithms.AmpCurve, args) self.interp_tester(algorithms.AmpCurve, args, amplist)
def setUp(self): self.dtypes = [ np.dtype(t) for t in (np.uint16, np.int32, np.float32, np.float64) ] self.bbox = Box2I(Point2I(2, 1), Extent2I(5, 7)) self.args = [ (), (Box2I(Point2I(3, 4), Extent2I(2, 1)), ), (Box2I(Point2I(3, 4), Extent2I(2, 1)), PARENT), (Box2I(Point2I(1, 0), Extent2I(3, 2)), LOCAL), ]
def runExposureCompositePutGetTest(self, storageClass, datasetTypeName): example = os.path.join(TESTDIR, "data", "basic", "small.fits") exposure = lsst.afw.image.ExposureF(example) butler = Butler(self.tmpConfigFile) dimensions = butler.registry.dimensions.extract( ["instrument", "visit"]) self.registerDatasetTypes(datasetTypeName, dimensions, storageClass, butler.registry) dataId = { "visit": 42, "instrument": "DummyCam", "physical_filter": "d-r" } # Add needed Dimensions butler.registry.addDimensionEntry("instrument", {"instrument": "DummyCam"}) butler.registry.addDimensionEntry("physical_filter", { "instrument": "DummyCam", "physical_filter": "d-r" }) butler.registry.addDimensionEntry("visit", { "instrument": "DummyCam", "visit": 42, "physical_filter": "d-r" }) butler.put(exposure, datasetTypeName, dataId) # Get the full thing butler.get(datasetTypeName, dataId) # TODO enable check for equality (fix for Exposure type) # self.assertEqual(full, exposure) # Get a component compsRead = {} for compName in ("wcs", "image", "mask", "coaddInputs", "psf"): compTypeName = DatasetType.nameWithComponent( datasetTypeName, compName) component = butler.get(compTypeName, dataId) # TODO enable check for component instance types # compRef = butler.registry.find(butler.run.collection, # f"calexp.{compName}", dataId) # self.assertIsInstance(component, # compRef.datasetType.storageClass.pytype) compsRead[compName] = component # Simple check of WCS bbox = Box2I(Point2I(0, 0), Extent2I(9, 9)) self.assertWcsAlmostEqualOverBBox(compsRead["wcs"], exposure.getWcs(), bbox) # With parameters inBBox = Box2I(minimum=Point2I(0, 0), maximum=Point2I(3, 3)) parameters = dict(bbox=inBBox, origin=LOCAL) subset = butler.get(datasetTypeName, dataId, parameters=parameters) outBBox = subset.getBBox() self.assertEqual(inBBox, outBBox)
def testConstructor(self): def projectSpans(radius, value, bbox, asArray): ss = SpanSet.fromShape(radius, Stencil.CIRCLE, offset=(10, 10)) image = ImageF(bbox) ss.setImage(image, value) if asArray: return image.array else: return image def runTest(images, mFoot, peaks=self.peaks, footprintBBox=Box2I(Point2I(6, 6), Extent2I(9, 9))): self.assertEqual(mFoot.getBBox(), footprintBBox) try: fpImage = np.array(images)[:, 1:-1, 1:-1] except IndexError: fpImage = np.array([img.array for img in images])[:, 1:-1, 1:-1] # result = mFoot.getImage(fill=0).image.array self.assertFloatsAlmostEqual(mFoot.getImage(fill=0).image.array, fpImage) if peaks is not None: self.verifyPeaks(mFoot.getPeaks(), peaks) bbox = Box2I(Point2I(5, 5), Extent2I(11, 11)) xy0 = Point2I(5, 5) images = np.array([projectSpans(n, 5-n, bbox, True) for n in range(2, 5)]) mFoot = MultibandFootprint.fromArrays(self.filters, images, xy0=xy0, peaks=self.peaks) runTest(images, mFoot) mFoot = MultibandFootprint.fromArrays(self.filters, images) runTest(images, mFoot, None, Box2I(Point2I(1, 1), Extent2I(9, 9))) images = [projectSpans(n, 5-n, bbox, False) for n in range(2, 5)] mFoot = MultibandFootprint.fromImages(self.filters, images, peaks=self.peaks) runTest(images, mFoot) images = np.array([projectSpans(n, n, bbox, True) for n in range(2, 5)]) mFoot = MultibandFootprint.fromArrays(self.filters, images, peaks=self.peaks, xy0=bbox.getMin()) runTest(images, mFoot) images = np.array([projectSpans(n, 5-n, bbox, True) for n in range(2, 5)]) thresh = [1, 2, 2.5] mFoot = MultibandFootprint.fromArrays(self.filters, images, xy0=bbox.getMin(), thresh=thresh) footprintBBox = Box2I(Point2I(8, 8), Extent2I(5, 5)) self.assertEqual(mFoot.getBBox(), footprintBBox) fpImage = np.array(images)[:, 3:-3, 3:-3] mask = np.all(fpImage <= np.array(thresh)[:, None, None], axis=0) fpImage[:, mask] = 0 self.assertFloatsAlmostEqual(mFoot.getImage(fill=0).image.array, fpImage) img = mFoot.getImage().image.array img[~np.isfinite(img)] = 1.1 self.assertFloatsAlmostEqual(mFoot.getImage(fill=1.1).image.array, img)
def getCellInfo(self, index): """Return information for the specified cell. Parameters ---------- index : `lsst.skymap.Index2D` or `int` Index of cell, as `Index2D`, or `Iterable` [`int`, `int`]; or a sequential index as returned by getSequentialCellIndex; negative values are not supported. Returns ------- result : `lsst.skymap.CellInfo` The cell info for that index. Raises ------ IndexError If index is out of range. """ if self._numCells.x == 0 or self._numCells.y == 0: raise IndexError("Patch does not contain cells.") if isinstance(index, Index2D): _index = index else: if isinstance(index, numbers.Number): _index = self.getCellIndexPair(index) else: _index = Index2D(*index) if (not 0 <= _index.x < self._numCells.x) \ or (not 0 <= _index.y < self._numCells.y): raise IndexError("Cell index %s is not in range [0-%d, 0-%d]" % (_index, self._numCells.x - 1, self._numCells.y - 1)) # We offset the index by numCellsInPatchBorder because the cells # start outside the inner dimensions. # The cells are defined relative to the patch bounding box (within the tract). patchInnerBBox = self.getInnerBBox() innerMin = Point2I(*[(_index[i] - self._numCellsInPatchBorder)*self._cellInnerDimensions[i] + patchInnerBBox.getBegin()[i] for i in range(2)]) innerBBox = Box2I(innerMin, self._cellInnerDimensions) outerBBox = Box2I(innerBBox) outerBBox.grow(self._cellBorder) return CellInfo( index=_index, innerBBox=innerBBox, outerBBox=outerBBox, sequentialIndex=self.getSequentialCellIndexFromPair(_index), tractWcs=self._wcs )
def test_maskBlocks_short_column(self): """A test for maskBlocksIfIntermitentBadPixelsInColumn. Tests that a contigous bad column Npix < badOnAndOffPixelColumnThreshold (10) does not get split by the code. Plots can be found in DM-19903 on Jira. """ expectedDefects = [Box2I(corner=Point2I(25, 1), dimensions=Extent2I(1, 8))] defects = self.allDefectsList defects.append(Box2I(corner=Point2I(25, 1), dimensions=Extent2I(1, 8))) self.check_maskBlocks(defects, expectedDefects)
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 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
def test_maskBlocks_full_column(self): """A test for maskBlocksIfIntermitentBadPixelsInColumn. Tests that a contigous bad column does not get split by the code. The mock flat has a size of 200X204 pixels. This column has a maximum length of 50 pixels, otherwise there would be a split along the mock amp boundary. Plots can be found in DM-19903 on Jira. """ defects = self.allDefectsList defects.append(Box2I(corner=Point2I(15, 1), dimensions=Extent2I(1, 50))) expectedDefects = [Box2I(corner=Point2I(15, 1), dimensions=Extent2I(1, 50))] self.check_maskBlocks(defects, expectedDefects)
def tripleFromArrays(cls, filters, image, mask, variance, bbox=None): """Construct a MultibandTriple from a set of arrays Parameters ---------- filters: `list` List of filter names. image: array Array of image values mask: array Array of mask values variance: array Array of variance values bbox: `Box2I` Location of the array in a larger single band image. This argument is ignored if `singles` is not `None`. """ if bbox is None: bbox = Box2I(Point2I(0, 0), Extent2I(image.shape[1], image.shape[0])) mImage = MultibandImage(filters, image, bbox) if mask is not None: mMask = MultibandMask(filters, mask, bbox) else: mMask = None if variance is not None: mVariance = MultibandImage(filters, variance, bbox) else: mVariance = None return cls(filters, mImage, mMask, mVariance)
def setUp(self): np.random.seed(1) self.filters = ["G", "R", "I"] self.Mask = Mask[MaskPixel] # Store the default mask planes for later use maskPlaneDict = self.Mask().getMaskPlaneDict() self.defaultMaskPlanes = sorted(maskPlaneDict, key=maskPlaneDict.__getitem__) # reset so tests will be deterministic self.Mask.clearMaskPlaneDict() for p in ("BAD", "SAT", "INTRP", "CR", "EDGE"): self.Mask.addMaskPlane(p) self.BAD = self.Mask.getPlaneBitMask("BAD") self.CR = self.Mask.getPlaneBitMask("CR") self.EDGE = self.Mask.getPlaneBitMask("EDGE") self.values1 = [ self.BAD | self.CR, self.BAD | self.EDGE, self.BAD | self.CR | self.EDGE ] self.bbox = Box2I(Point2I(1000, 2000), Extent2I(200, 100)) singles = [self.Mask(self.bbox) for f in range(len(self.filters))] for n in range(len(singles)): singles[n].set(self.values1[n]) self.mMask1 = MultibandMask.fromMasks(self.filters, singles) self.values2 = [self.EDGE, self.BAD, self.CR | self.EDGE] singles = [self.Mask(self.bbox) for f in range(len(self.filters))] for n in range(len(singles)): singles[n].set(self.values2[n]) self.mMask2 = MultibandMask.fromMasks(self.filters, singles)
def setUp(self): np.random.seed(1) self.bbox = Box2I(Point2I(1000, 2000), Extent2I(200, 100)) self.filters = ["G", "R", "I"] self.imgValue = 10 images = [ImageF(self.bbox, self.imgValue) for f in self.filters] mImage = MultibandImage.fromImages(self.filters, images) self.Mask = Mask[MaskPixel] # Store the default mask planes for later use maskPlaneDict = self.Mask().getMaskPlaneDict() self.defaultMaskPlanes = sorted(maskPlaneDict, key=maskPlaneDict.__getitem__) # reset so tests will be deterministic self.Mask.clearMaskPlaneDict() for p in ("BAD", "SAT", "INTRP", "CR", "EDGE"): self.Mask.addMaskPlane(p) self.maskValue = self.Mask.getPlaneBitMask("BAD") singles = [self.Mask(self.bbox) for f in range(len(self.filters))] for n in range(len(singles)): singles[n].set(self.maskValue) mMask = MultibandMask.fromMasks(self.filters, singles) self.varValue = 1e-2 images = [ImageF(self.bbox, self.varValue) for f in self.filters] mVariance = MultibandImage.fromImages(self.filters, images) self.maskedImage = MultibandMaskedImage(self.filters, image=mImage, mask=mMask, variance=mVariance)
def translateSliceArgs(sliceArgs, bboxGetter): """Transform a tuple of slice objects into a Box2I, correctly handling negative indices. see `interpretSliceArgs` for a description of parameters Returns ------- box : `Box2I` or `None` A box to use to create a subimage, or None if the slice refers to a scalar. index: `tuple` or `None` An ``(x, y)`` tuple of integers, or None if the slice refers to a box. origin : `ImageOrigin` Enum indicating whether to account for xy0. """ slices, origin = splitSliceArgs(sliceArgs) if isinstance(slices, Point2I): return None, slices, origin elif isinstance(slices, Box2I): return slices, None, origin x, y, origin = interpretSliceArgs(sliceArgs, bboxGetter) if isinstance(x, slice): assert isinstance(y, slice) if x.step is not None or y.step is not None: raise ValueError( "Slices with steps are not supported in image indexing.") begin = Point2I(x.start, y.start) end = Point2I(x.stop, y.stop) return Box2I(begin, end - begin), None, origin assert not isinstance(y, slice) return None, Point2I(x, y), origin
def make_coadd_dm_wcs_simple(coadd_dim): """ make a coadd wcs, using the default world origin. Parameters ---------- coadd_origin: int Origin in pixels of the coadd, can be within a larger pixel grid e.g. tract surrounding the patch Returns -------- A galsim wcs, see make_wcs for return type """ coadd_bbox = Box2I(Point2I(0), Extent2I(coadd_dim)) coadd_origin = coadd_bbox.getCenter() gs_coadd_origin = galsim.PositionD( x=coadd_origin.x, y=coadd_origin.y, ) coadd_wcs = make_dm_wcs( make_wcs( scale=SCALE, image_origin=gs_coadd_origin, world_origin=WORLD_ORIGIN, )) return coadd_wcs, coadd_bbox
def getBBox(self, origin=PARENT): """Bounding box """ if origin == PARENT: return self._bbox elif origin == LOCAL: return Box2I(Point2I(0, 0), self._bbox.getDimensions()) raise ValueError("Unrecognized origin, expected either PARENT or LOCAL")
def _testImageSlicing(testCase, mImage, gVal, rVal, iVal): """Test slicing in the spatial dimensions for image-like objects""" testCase.assertIsInstance(mImage[:, -1, -1, LOCAL], MultibandPixel) testCase.assertEqual(mImage["G", -1, -1, LOCAL], gVal) testCase.assertEqual(mImage[:, 1100:, 2025:].getBBox(), Box2I(Point2I(1100, 2025), Extent2I(100, 75))) testCase.assertEqual(mImage[:, -20:-10, -10:-5, LOCAL].getBBox(), Box2I(Point2I(1180, 2090), Extent2I(10, 5))) testCase.assertEqual(mImage[:, :1100, :2050].getBBox(), Box2I(Point2I(1000, 2000), Extent2I(100, 50))) coord = Point2I(1075, 2015) bbox = Box2I(Point2I(1050, 2010), coord) testCase.assertEqual(mImage[:, bbox].getBBox(), bbox) testCase.assertEqual(mImage[:, 1010, 2010].getBBox().getMin(), Point2I(1010, 2010)) testCase.assertEqual(mImage[:, Point2I(1075, 2015)].getBBox().getMin(), coord) testCase.assertEqual(mImage["G", 1100:, 2025:].getBBox(), Box2I(Point2I(1100, 2025), Extent2I(100, 75))) testCase.assertEqual(mImage["R", -20:-10, -10:-5, LOCAL].getBBox(), Box2I(Point2I(1180, 2090), Extent2I(10, 5))) testCase.assertEqual(mImage["I", :1100, :2050].getBBox(), Box2I(Point2I(1000, 2000), Extent2I(100, 50))) testCase.assertEqual(mImage["R", bbox].getBBox(), bbox) testCase.assertEqual(mImage["I", 1010, 2010], iVal) testCase.assertEqual(mImage["R", Point2I(1075, 2015)], rVal) with testCase.assertRaises(TypeError): mImage[:, 0] with testCase.assertRaises(TypeError): mImage[:, 10:] with testCase.assertRaises(TypeError): mImage[:, :10] with testCase.assertRaises(TypeError): mImage[:, :, 0]
def fromTable(cls, tableList): """Read linearity from a FITS file. This method uses the `fromDict` method to create the calibration, after constructing an appropriate dictionary from the input tables. Parameters ---------- tableList : `list` [`astropy.table.Table`] afwTable read from input file name. Returns ------- linearity : `~lsst.ip.isr.linearize.Linearizer`` Linearity parameters. Notes ----- The method reads a FITS file with 1 or 2 extensions. The metadata is read from the header of extension 1, which must exist. Then the table is loaded, and the ['AMPLIFIER_NAME', 'TYPE', 'COEFFS', 'BBOX_X0', 'BBOX_Y0', 'BBOX_DX', 'BBOX_DY'] columns are read and used to set each dictionary by looping over rows. Eextension 2 is then attempted to read in the try block (which only exists for lookup tables). It has a column named 'LOOKUP_VALUES' that contains a vector of the lookup entries in each row. """ coeffTable = tableList[0] metadata = coeffTable.meta inDict = dict() inDict['metadata'] = metadata inDict['hasLinearity'] = metadata.get('HAS_LINEARITY', False) inDict['amplifiers'] = dict() for record in coeffTable: ampName = record['AMPLIFIER_NAME'] fitParams = record['FIT_PARAMS'] if 'FIT_PARAMS' in record.columns else np.array([0.0]) fitParamsErr = record['FIT_PARAMS_ERR'] if 'FIT_PARAMS_ERR' in record.columns else np.array([0.0]) fitChiSq = record['RED_CHI_SQ'] if 'RED_CHI_SQ' in record.columns else np.nan inDict['amplifiers'][ampName] = { 'linearityType': record['TYPE'], 'linearityCoeffs': record['COEFFS'], 'linearityBBox': Box2I(Point2I(record['BBOX_X0'], record['BBOX_Y0']), Extent2I(record['BBOX_DX'], record['BBOX_DY'])), 'fitParams': fitParams, 'fitParamsErr': fitParamsErr, 'fitChiSq': fitChiSq, } if len(tableList) > 1: tableData = tableList[1] inDict['tableData'] = [record['LOOKUP_VALUES'] for record in tableData] return cls().fromDict(inDict)
def setUp(self): dimensions = Extent2I(7, 7) self.bbox = Box2I(Point2I(-dimensions/2), dimensions) self.img = Image(self.bbox, dtype=np.float64) x, y = np.ogrid[-3:4, -3:4] rsqr = x**2 + y**2 # Some arbitrary circular double Gaussian self.img.array[:] = np.exp(-0.5*rsqr**2) + np.exp(-0.5*rsqr**2/4) self.img.array /= np.sum(self.img.array) self.psf = MyTestImagePsf(self.img)
def runTest(images, mFoot, peaks=self.peaks, footprintBBox=Box2I(Point2I(6, 6), Extent2I(9, 9))): self.assertEqual(mFoot.getBBox(), footprintBBox) try: fpImage = np.array(images)[:, 1:-1, 1:-1] except IndexError: fpImage = np.array([img.array for img in images])[:, 1:-1, 1:-1] # result = mFoot.getImage(fill=0).image.array self.assertFloatsAlmostEqual(mFoot.getImage(fill=0).image.array, fpImage) if peaks is not None: self.verifyPeaks(mFoot.getPeaks(), peaks)
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())
def _doComputeKernelImage(self, position=None, color=None): bbox = Box2I(Point2I(-3, -3), Extent2I(7, 7)) img = Image(bbox, dtype=np.float64) x, y = np.ogrid[bbox.minY:bbox.maxY + 1, bbox.minX:bbox.maxX + 1] rsqr = x**2 + y**2 if position.x >= 0.0: img.array[:] = np.exp(-0.5 * rsqr) else: img.array[:] = np.exp(-0.5 * rsqr / 4) img.array /= np.sum(img.array) return img