From 234be3466444ae3deea661a1aa8786546eea3ce9 Mon Sep 17 00:00:00 2001 From: Eric Bellm Date: Wed, 12 Jun 2024 16:59:01 -0700 Subject: [PATCH 1/3] Add psf to CCDData cutouts. --- python/lsst/ap/association/packageAlerts.py | 6 +++++- tests/test_packageAlerts.py | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/python/lsst/ap/association/packageAlerts.py b/python/lsst/ap/association/packageAlerts.py index ecd84b82..a385eaaa 100644 --- a/python/lsst/ap/association/packageAlerts.py +++ b/python/lsst/ap/association/packageAlerts.py @@ -393,11 +393,12 @@ def createCcdDataCutout(self, image, skyCenter, extent, photoCalib, srcId): CCDData object storing the calibrate information from the input difference or template image. """ + point = image.getWcs().skyToPixel(skyCenter) + # Catch errors in retrieving the cutout. try: cutout = image.getCutout(skyCenter, extent) except InvalidParameterError: - point = image.getWcs().skyToPixel(skyCenter) imBBox = image.getBBox() if not geom.Box2D(image.getBBox()).contains(point): self.log.warning( @@ -414,6 +415,8 @@ def createCcdDataCutout(self, image, skyCenter, extent, photoCalib, srcId): % srcId) return None + cutoutPsf = image.psf.computeKernelImage(point).array + # Find the value of the bottom corner of our cutout's BBox and # subtract 1 so that the CCDData cutout position value will be # [1, 1]. @@ -437,6 +440,7 @@ def createCcdDataCutout(self, image, skyCenter, extent, photoCalib, srcId): uncertainty=VarianceUncertainty(calibCutout.getVariance().array), flags=calibCutout.getMask().array, wcs=cutoutWcs, + psf=cutoutPsf, meta={"cutMinX": cutOutMinX, "cutMinY": cutOutMinY}, unit=u.nJy) diff --git a/tests/test_packageAlerts.py b/tests/test_packageAlerts.py index 9b3a2f3f..45962da0 100644 --- a/tests/test_packageAlerts.py +++ b/tests/test_packageAlerts.py @@ -265,6 +265,9 @@ def testCreateCcdDataCutout(self): self.cutoutWcs.wcs.cd) self.assertFloatsAlmostEqual(ccdData.data, calibExposure.getImage().array) + self.assertFloatsAlmostEqual(ccdData.psf, + self.exposure.psf.computeKernelImage(self.center).array) + self.assertFloatsAlmostEqual(np.sum(ccdData.psf), 1.0) ccdData = packageAlerts.createCcdDataCutout( self.exposure, From 4503b903964f06e96806176e4ab24f068c2dabe0 Mon Sep 17 00:00:00 2001 From: Eric Bellm Date: Tue, 18 Jun 2024 11:44:36 -0700 Subject: [PATCH 2/3] Use pixel coordinates when computing the PSF. --- python/lsst/ap/association/packageAlerts.py | 14 +++++++++++--- tests/test_packageAlerts.py | 7 ++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/python/lsst/ap/association/packageAlerts.py b/python/lsst/ap/association/packageAlerts.py index a385eaaa..82012e23 100644 --- a/python/lsst/ap/association/packageAlerts.py +++ b/python/lsst/ap/association/packageAlerts.py @@ -265,23 +265,28 @@ def run(self, sphPoint = geom.SpherePoint(diaSource["ra"], diaSource["dec"], geom.degrees) + pixelPoint = geom.Point2D(diaSource["x"], + diaSource["y"]) cutoutExtent = self.createDiaSourceExtent(diaSource["bboxSize"]) diffImCutout = self.createCcdDataCutout( diffIm, sphPoint, + pixelPoint, cutoutExtent, diffImPhotoCalib, diaSource["diaSourceId"]) calexpCutout = self.createCcdDataCutout( calexp, sphPoint, + pixelPoint, cutoutExtent, calexpPhotoCalib, diaSource["diaSourceId"]) templateCutout = self.createCcdDataCutout( template, sphPoint, + pixelPoint, cutoutExtent, templatePhotoCalib, diaSource["diaSourceId"]) @@ -370,7 +375,7 @@ def produceAlerts(self, alerts, visit, detector): self.producer.flush() - def createCcdDataCutout(self, image, skyCenter, extent, photoCalib, srcId): + def createCcdDataCutout(self, image, skyCenter, pixelCenter, extent, photoCalib, srcId): """Grab an image as a cutout and return a calibrated CCDData image. Parameters @@ -379,6 +384,8 @@ def createCcdDataCutout(self, image, skyCenter, extent, photoCalib, srcId): Image to pull cutout from. skyCenter : `lsst.geom.SpherePoint` Center point of DiaSource on the sky. + pixelCenter : `lsst.geom.Point2D` + Pixel center of DiaSource on the sky. extent : `lsst.geom.Extent2I` Bounding box to cutout from the image. photoCalib : `lsst.afw.image.PhotoCalib` @@ -393,12 +400,12 @@ def createCcdDataCutout(self, image, skyCenter, extent, photoCalib, srcId): CCDData object storing the calibrate information from the input difference or template image. """ - point = image.getWcs().skyToPixel(skyCenter) # Catch errors in retrieving the cutout. try: cutout = image.getCutout(skyCenter, extent) except InvalidParameterError: + point = image.getWcs().skyToPixel(skyCenter) imBBox = image.getBBox() if not geom.Box2D(image.getBBox()).contains(point): self.log.warning( @@ -415,7 +422,8 @@ def createCcdDataCutout(self, image, skyCenter, extent, photoCalib, srcId): % srcId) return None - cutoutPsf = image.psf.computeKernelImage(point).array + # use image.psf.computeKernelImage to provide PSF centered in the array + cutoutPsf = image.psf.computeKernelImage(pixelCenter).array # Find the value of the bottom corner of our cutout's BBox and # subtract 1 so that the CCDData cutout position value will be diff --git a/tests/test_packageAlerts.py b/tests/test_packageAlerts.py index 45962da0..89085d8f 100644 --- a/tests/test_packageAlerts.py +++ b/tests/test_packageAlerts.py @@ -255,6 +255,7 @@ def testCreateCcdDataCutout(self): ccdData = packageAlerts.createCcdDataCutout( self.exposure, self.exposure.getWcs().getSkyOrigin(), + self.exposure.getWcs().getPixelOrigin(), self.exposure.getBBox().getDimensions(), self.exposure.getPhotoCalib(), diaSrcId) @@ -267,11 +268,11 @@ def testCreateCcdDataCutout(self): calibExposure.getImage().array) self.assertFloatsAlmostEqual(ccdData.psf, self.exposure.psf.computeKernelImage(self.center).array) - self.assertFloatsAlmostEqual(np.sum(ccdData.psf), 1.0) ccdData = packageAlerts.createCcdDataCutout( self.exposure, geom.SpherePoint(0, 0, geom.degrees), + geom.Point2D(0, 0), self.exposure.getBBox().getDimensions(), self.exposure.getPhotoCalib(), diaSrcId) @@ -324,12 +325,14 @@ def testMakeAlertDict(self): sphPoint = geom.SpherePoint(diaSource["ra"], diaSource["dec"], geom.degrees) + pixelPoint = geom.Point2D(diaSource["x"], diaSource["y"]) cutout = self.exposure.getCutout(sphPoint, geom.Extent2I(self.cutoutSize, self.cutoutSize)) ccdCutout = packageAlerts.createCcdDataCutout( cutout, sphPoint, + pixelPoint, geom.Extent2I(self.cutoutSize, self.cutoutSize), cutout.getPhotoCalib(), 1234) @@ -512,12 +515,14 @@ def testRun_without_produce(self, mock_server_check): sphPoint = geom.SpherePoint(alert["diaSource"]["ra"], alert["diaSource"]["dec"], geom.degrees) + pixelPoint = geom.Point2D(alert["diaSource"]["x"], alert["diaSource"]["y"]) cutout = self.exposure.getCutout(sphPoint, geom.Extent2I(self.cutoutSize, self.cutoutSize)) ccdCutout = packageAlerts.createCcdDataCutout( cutout, sphPoint, + pixelPoint, geom.Extent2I(self.cutoutSize, self.cutoutSize), cutout.getPhotoCalib(), 1234) From 45493ae961d0c1d3d0bf6e97be0c370a296938ef Mon Sep 17 00:00:00 2001 From: Eric Bellm Date: Tue, 18 Jun 2024 12:02:10 -0700 Subject: [PATCH 3/3] Use pixel coordinates directly when making cutouts. --- python/lsst/ap/association/packageAlerts.py | 7 +++---- tests/test_packageAlerts.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/python/lsst/ap/association/packageAlerts.py b/python/lsst/ap/association/packageAlerts.py index 82012e23..8e6cf8cf 100644 --- a/python/lsst/ap/association/packageAlerts.py +++ b/python/lsst/ap/association/packageAlerts.py @@ -403,16 +403,15 @@ def createCcdDataCutout(self, image, skyCenter, pixelCenter, extent, photoCalib, # Catch errors in retrieving the cutout. try: - cutout = image.getCutout(skyCenter, extent) + cutout = image.getCutout(pixelCenter, extent) except InvalidParameterError: - point = image.getWcs().skyToPixel(skyCenter) imBBox = image.getBBox() - if not geom.Box2D(image.getBBox()).contains(point): + if not geom.Box2D(image.getBBox()).contains(pixelCenter): self.log.warning( "DiaSource id=%i centroid lies at pixel (%.2f, %.2f) " "which is outside the Exposure with bounding box " "((%i, %i), (%i, %i)). Returning None for cutout...", - srcId, point.x, point.y, + srcId, pixelCenter.x, pixelCenter.y, imBBox.minX, imBBox.maxX, imBBox.minY, imBBox.maxY) else: raise InvalidParameterError( diff --git a/tests/test_packageAlerts.py b/tests/test_packageAlerts.py index 89085d8f..0d24f7c2 100644 --- a/tests/test_packageAlerts.py +++ b/tests/test_packageAlerts.py @@ -272,7 +272,7 @@ def testCreateCcdDataCutout(self): ccdData = packageAlerts.createCcdDataCutout( self.exposure, geom.SpherePoint(0, 0, geom.degrees), - geom.Point2D(0, 0), + geom.Point2D(-100, -100), self.exposure.getBBox().getDimensions(), self.exposure.getPhotoCalib(), diaSrcId)