def testCurvedFocalPlane(self): """Test a curved focal plane (with rectangular pixels) """ bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000)) pixelSizeMm = afwGeom.Extent2D(0.02, 0.03) plateScale = 25.0 # arcsec/mm yaw = afwGeom.Angle(20, afwGeom.degrees) fpPosition = afwGeom.Point2D( 50, 25) # focal-plane position of ref position on detector (mm) refPoint = afwGeom.Point2D( -0.5, -0.5) # ref position on detector (pos of lower left corner) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToPupil = afwGeom.RadialXYTransform( (0.0, plateScaleRad, 0.0, 0.001 * plateScaleRad)) pixelToTanPixel = makePixelToTanPixel( bbox=bbox, orientation=orientation, focalPlaneToPupil=focalPlaneToPupil, pixelSizeMm=pixelSizeMm, plateScale=plateScale, ) # the center point of the detector should not move ctrPointPix = afwGeom.Box2D(bbox).getCenter() ctrPointTanPix = pixelToTanPixel.forwardTransform(ctrPointPix) for i in range(2): self.assertAlmostEquals(ctrPointTanPix[i], ctrPointPix[i]) # two points separated by x pixels in tan pixels coordinates # should be separated x * rad/tanPix in pupil coordinates, # where rad/tanPix = plate scale in rad/MM * mean pixel size in mm radPerTanPixel = plateScaleRad * (pixelSizeMm[0] + pixelSizeMm[1]) / 2.0 pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm) pixelToPupil = afwGeom.MultiXYTransform( (pixelToFocalPlane, focalPlaneToPupil)) prevPointPupil = None prevPointTanPix = None for pointPix in ( afwGeom.Point2D(0, 0), afwGeom.Point2D(1000, 2000), afwGeom.Point2D(-100.5, 27.23), afwGeom.Point2D(-95.3, 0.0), ): pointPupil = pixelToPupil.forwardTransform(pointPix) pointTanPix = pixelToTanPixel.forwardTransform(pointPix) if prevPointPupil: pupilSep = numpy.linalg.norm(pointPupil - prevPointPupil) tanPixSep = numpy.linalg.norm(pointTanPix - prevPointTanPix) self.assertAlmostEquals(tanPixSep * radPerTanPixel, pupilSep) prevPointPupil = pointPupil prevPointTanPix = pointTanPix
def testFlatFocalPlane(self): """Test an undistorted focal plane (with rectangular pixels) """ bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000)) pixelSizeMm = afwGeom.Extent2D(0.02, 0.03) plateScale = 25.0 # arcsec/mm yaw = afwGeom.Angle(20, afwGeom.degrees) fpPosition = afwGeom.Point2D(50, 25) # focal-plane position of ref position on detector (mm) refPoint = afwGeom.Point2D(-0.5, -0.5) # ref position on detector (pos of lower left corner) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToPupil = afwGeom.RadialXYTransform((0.0, plateScaleRad)) pixelToTanPixel = makePixelToTanPixel( bbox=bbox, orientation=orientation, focalPlaneToPupil=focalPlaneToPupil, pixelSizeMm=pixelSizeMm, ) # with no distortion, this should be a unity transform for pointPix in ( afwGeom.Point2D(0, 0), afwGeom.Point2D(1000, 2000), afwGeom.Point2D(-100.5, 27.23), ): pointTanPix = pixelToTanPixel.forwardTransform(pointPix) self.assertPairsNearlyEqual(pointTanPix, pointPix)
def testSimpleCurvedFocalPlane(self): """Test a trivial curved focal plane with square pixels The CCD's lower left pixel is centered on the boresight pupil center = focal plane center CCD x is along focal plane x """ bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000)) pixelSizeMm = afwGeom.Extent2D(0.02, 0.02) plateScale = 25.0 # arcsec/mm yaw = 0 * afwGeom.degrees fpPosition = afwGeom.Point2D(0, 0) # focal-plane position of ref position on detector (mm) refPoint = afwGeom.Point2D(0, 0) # ref position on detector (pos of lower left corner) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToPupil = afwGeom.RadialXYTransform((0.0, plateScaleRad, 0.0, 0.001 * plateScaleRad)) pixelToPupil = afwGeom.MultiXYTransform((pixelToFocalPlane, focalPlaneToPupil)) pixelToTanPixel = makePixelToTanPixel( bbox=bbox, orientation=orientation, focalPlaneToPupil=focalPlaneToPupil, pixelSizeMm=pixelSizeMm, ) # pupil center should be pixel position 0, 0 and tan pixel position 0, 0 pixAtPupilCtr = pixelToPupil.reverseTransform(afwGeom.Point2D(0, 0)) self.assertPairsNearlyEqual(pixAtPupilCtr, [0, 0]) tanPixAtPupilCr = pixelToTanPixel.forwardTransform(pixAtPupilCtr) self.assertPairsNearlyEqual(tanPixAtPupilCr, [0, 0]) # build same camera geometry transforms without optical distortion focalPlaneToPupilNoDistortion = afwGeom.RadialXYTransform((0.0, plateScaleRad)) pixelToPupilNoDistortion = afwGeom.MultiXYTransform( (pixelToFocalPlane, focalPlaneToPupilNoDistortion)) for x in (100, 200, 1000): for y in (100, 500, 800): pixPos = afwGeom.Point2D(x, y) tanPixPos = pixelToTanPixel.forwardTransform(pixPos) # pix to tan pix should be radial self.assertAlmostEqual( math.atan2(pixPos[1], pixPos[0]), math.atan2(tanPixPos[1], tanPixPos[0]), ) # for a given pupil angle (which, together with a pointing, gives a position on the sky): # - pupil to pixels gives pixPos # - undistorted pupil to pixels gives tanPixPos pupilPos = pixelToPupil.forwardTransform(pixPos) desTanPixPos = pixelToPupilNoDistortion.reverseTransform(pupilPos) self.assertPairsNearlyEqual(desTanPixPos, tanPixPos)
def testCurvedFocalPlane(self): """Test a curved focal plane (with rectangular pixels) """ bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000)) pixelSizeMm = afwGeom.Extent2D(0.02, 0.03) plateScale = 25.0 # arcsec/mm yaw = afwGeom.Angle(20, afwGeom.degrees) # focal-plane position of ref position on detector (mm) fpPosition = afwGeom.Point2D(50, 25) # ref position on detector (pos of lower left corner) refPoint = afwGeom.Point2D(-0.5, -0.5) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToField = afwGeom.makeRadialTransform( (0.0, plateScaleRad, 0.0, 0.001 * plateScaleRad)) pixelToField = pixelToFocalPlane.then(focalPlaneToField) pixelToTanPixel = makePixelToTanPixel( bbox=bbox, orientation=orientation, focalPlaneToField=focalPlaneToField, pixelSizeMm=pixelSizeMm, ) # the center point of the field angle frame should not move pixAtFieldCtr = pixelToField.applyInverse(afwGeom.Point2D(0, 0)) tanPixAtFieldCr = pixelToTanPixel.applyForward(pixAtFieldCtr) self.assertPairsAlmostEqual(pixAtFieldCtr, tanPixAtFieldCr) # build same camera geometry transforms without optical distortion focalPlaneToFieldNoDistortion = afwGeom.makeRadialTransform( (0.0, plateScaleRad)) pixelToFieldNoDistortion = pixelToFocalPlane.then( focalPlaneToFieldNoDistortion) for x in (100, 200, 1000): for y in (100, 500, 800): pixPos = afwGeom.Point2D(x, y) tanPixPos = pixelToTanPixel.applyForward(pixPos) # for a given field angle (which, together with a pointing, gives a position on the sky): # - field angle to pixels gives pixPos # - undistorted field angle to pixels gives tanPixPos fieldPos = pixelToField.applyForward(pixPos) desTanPixPos = pixelToFieldNoDistortion.applyInverse(fieldPos) # use a degraded accuracy because small Jacobian errors accumulate this far from the center self.assertPairsAlmostEqual(desTanPixPos, tanPixPos, maxDiff=1e-5)
def testCurvedFocalPlane(self): """Test a curved focal plane (with rectangular pixels) """ bbox = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Extent2I(1000, 1000)) pixelSizeMm = afwGeom.Extent2D(0.02, 0.03) plateScale = 25.0 # arcsec/mm yaw = afwGeom.Angle(20, afwGeom.degrees) fpPosition = afwGeom.Point2D(50, 25) # focal-plane position of ref position on detector (mm) refPoint = afwGeom.Point2D(-0.5, -0.5) # ref position on detector (pos of lower left corner) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToPupil = afwGeom.RadialXYTransform((0.0, plateScaleRad, 0.0, 0.001 * plateScaleRad)) pixelToTanPixel = makePixelToTanPixel( bbox = bbox, orientation = orientation, focalPlaneToPupil = focalPlaneToPupil, pixelSizeMm = pixelSizeMm, plateScale = plateScale, ) # the center point of the detector should not move ctrPointPix = afwGeom.Box2D(bbox).getCenter() ctrPointTanPix = pixelToTanPixel.forwardTransform(ctrPointPix) for i in range(2): self.assertAlmostEquals(ctrPointTanPix[i], ctrPointPix[i]) # two points separated by x pixels in tan pixels coordinates # should be separated x * rad/tanPix in pupil coordinates, # where rad/tanPix = plate scale in rad/MM * mean pixel size in mm radPerTanPixel = plateScaleRad * (pixelSizeMm[0] + pixelSizeMm[1]) / 2.0 pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm) pixelToPupil = afwGeom.MultiXYTransform((pixelToFocalPlane, focalPlaneToPupil)) prevPointPupil = None prevPointTanPix = None for pointPix in ( afwGeom.Point2D(0, 0), afwGeom.Point2D(1000, 2000), afwGeom.Point2D(-100.5, 27.23), afwGeom.Point2D(-95.3, 0.0), ): pointPupil = pixelToPupil.forwardTransform(pointPix) pointTanPix = pixelToTanPixel.forwardTransform(pointPix) if prevPointPupil: pupilSep = numpy.linalg.norm(pointPupil - prevPointPupil) tanPixSep = numpy.linalg.norm(pointTanPix - prevPointTanPix) self.assertAlmostEquals(tanPixSep * radPerTanPixel, pupilSep) prevPointPupil = pointPupil prevPointTanPix = pointTanPix
def testCurvedFocalPlane(self): """Test a curved focal plane (with rectangular pixels) """ bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000)) pixelSizeMm = afwGeom.Extent2D(0.02, 0.03) plateScale = 25.0 # arcsec/mm yaw = afwGeom.Angle(20, afwGeom.degrees) fpPosition = afwGeom.Point2D(50, 25) # focal-plane position of ref position on detector (mm) refPoint = afwGeom.Point2D(-0.5, -0.5) # ref position on detector (pos of lower left corner) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToPupil = afwGeom.RadialXYTransform((0.0, plateScaleRad, 0.0, 0.001 * plateScaleRad)) pixelToPupil = afwGeom.MultiXYTransform((pixelToFocalPlane, focalPlaneToPupil)) pixelToTanPixel = makePixelToTanPixel( bbox=bbox, orientation=orientation, focalPlaneToPupil=focalPlaneToPupil, pixelSizeMm=pixelSizeMm, ) # the center point of the pupil frame should not move pixAtPupilCtr = pixelToPupil.reverseTransform(afwGeom.Point2D(0, 0)) tanPixAtPupilCr = pixelToTanPixel.forwardTransform(pixAtPupilCtr) self.assertPairsNearlyEqual(pixAtPupilCtr, tanPixAtPupilCr) # build same camera geometry transforms without optical distortion focalPlaneToPupilNoDistortion = afwGeom.RadialXYTransform((0.0, plateScaleRad)) pixelToPupilNoDistortion = afwGeom.MultiXYTransform( (pixelToFocalPlane, focalPlaneToPupilNoDistortion)) for x in (100, 200, 1000): for y in (100, 500, 800): pixPos = afwGeom.Point2D(x, y) tanPixPos = pixelToTanPixel.forwardTransform(pixPos) # for a given pupil position (which, together with a pointing, gives a position on the sky): # - pupil to pixels gives pixPos # - undistorted pupil to pixels gives tanPixPos pupilPos = pixelToPupil.forwardTransform(pixPos) desTanPixPos = pixelToPupilNoDistortion.reverseTransform(pupilPos) self.assertPairsNearlyEqual(desTanPixPos, tanPixPos)
def testFlatFocalPlane(self): """Test an undistorted focal plane (with rectangular pixels) """ bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000)) pixSizeFactor = numpy.array((1.2, 0.8)) pixelSizeMm = afwGeom.Extent2D(0.02 * pixSizeFactor[0], 0.02 * pixSizeFactor[1]) plateScale = 25.0 # arcsec/mm yaw = afwGeom.Angle(20, afwGeom.degrees) fpPosition = afwGeom.Point2D( 50, 25) # focal-plane position of ref position on detector (mm) refPoint = afwGeom.Point2D( -0.5, -0.5) # ref position on detector (pos of lower left corner) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToPupil = afwGeom.RadialXYTransform((0.0, plateScaleRad)) pixelToTanPixel = makePixelToTanPixel( bbox=bbox, orientation=orientation, focalPlaneToPupil=focalPlaneToPupil, pixelSizeMm=pixelSizeMm, plateScale=plateScale, ) # with no distortion, this should be a unity transform ctrPointPix = numpy.array(afwGeom.Box2D(bbox).getCenter()) for pointPix in ( afwGeom.Point2D(0, 0), afwGeom.Point2D(1000, 2000), afwGeom.Point2D(-100.5, 27.23), ): pointTanPix = pixelToTanPixel.forwardTransform(pointPix) predPointTanPix = ((numpy.array(pointPix) - ctrPointPix) * pixSizeFactor) + ctrPointPix for i in range(2): self.assertAlmostEquals(pointTanPix[i], predPointTanPix[i])
def testFlatFocalPlane(self): """Test an undistorted focal plane (with rectangular pixels) """ bbox = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Extent2I(1000, 1000)) pixSizeFactor = numpy.array((1.2, 0.8)) pixelSizeMm = afwGeom.Extent2D(0.02 * pixSizeFactor[0], 0.02 * pixSizeFactor[1]) plateScale = 25.0 # arcsec/mm yaw = afwGeom.Angle(20, afwGeom.degrees) fpPosition = afwGeom.Point2D(50, 25) # focal-plane position of ref position on detector (mm) refPoint = afwGeom.Point2D(-0.5, -0.5) # ref position on detector (pos of lower left corner) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToPupil = afwGeom.RadialXYTransform((0.0, plateScaleRad)) pixelToTanPixel = makePixelToTanPixel( bbox = bbox, orientation = orientation, focalPlaneToPupil = focalPlaneToPupil, pixelSizeMm = pixelSizeMm, plateScale = plateScale, ) # with no distortion, this should be a unity transform ctrPointPix = numpy.array(afwGeom.Box2D(bbox).getCenter()) for pointPix in ( afwGeom.Point2D(0, 0), afwGeom.Point2D(1000, 2000), afwGeom.Point2D(-100.5, 27.23), ): pointTanPix = pixelToTanPixel.forwardTransform(pointPix) predPointTanPix = ((numpy.array(pointPix) - ctrPointPix) * pixSizeFactor) + ctrPointPix for i in range(2): self.assertAlmostEquals(pointTanPix[i], predPointTanPix[i])
def testSimpleCurvedFocalPlane(self): """Test a trivial curved focal plane with square pixels The CCD's lower left pixel is centered on the boresight pupil center = focal plane center CCD x is along focal plane x """ bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(1000, 1000)) pixelSizeMm = lsst.geom.Extent2D(0.02, 0.02) plateScale = 25.0 # arcsec/mm yaw = 0 * lsst.geom.degrees # focal-plane position of ref position on detector (mm) fpPosition = lsst.geom.Point2D(0, 0) # ref position on detector (pos of lower left corner) refPoint = lsst.geom.Point2D(0, 0) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm) plateScaleRad = lsst.geom.Angle( # rad/mm plateScale, lsst.geom.arcseconds).asRadians() focalPlaneToField = afwGeom.makeRadialTransform( (0.0, plateScaleRad, 0.0, 0.001 * plateScaleRad)) pixelToField = pixelToFocalPlane.then(focalPlaneToField) pixelToTanPixel = makePixelToTanPixel( bbox=bbox, orientation=orientation, focalPlaneToField=focalPlaneToField, pixelSizeMm=pixelSizeMm, ) # field center should be pixel position 0, 0 and tan pixel position 0, # 0 pixAtFieldCtr = pixelToField.applyInverse(lsst.geom.Point2D(0, 0)) self.assertPairsAlmostEqual(pixAtFieldCtr, [0, 0]) tanPixAtFieldCr = pixelToTanPixel.applyForward(pixAtFieldCtr) self.assertPairsAlmostEqual(tanPixAtFieldCr, [0, 0]) # build same camera geometry transforms without optical distortion focalPlaneToFieldNoDistortion = afwGeom.makeRadialTransform( (0.0, plateScaleRad)) pixelToFieldNoDistortion = pixelToFocalPlane.then(focalPlaneToFieldNoDistortion) for x in (100, 200, 1000): for y in (100, 500, 800): pixPos = lsst.geom.Point2D(x, y) tanPixPos = pixelToTanPixel.applyForward(pixPos) # pix to tan pix should be radial self.assertAlmostEqual( math.atan2(pixPos[1], pixPos[0]), math.atan2(tanPixPos[1], tanPixPos[0]), ) # for a given field angle (which, together with a pointing, gives a position on the sky): # - field angle to pixels gives pixPos # - undistorted field anle to pixels gives tanPixPos fieldPos = pixelToField.applyForward(pixPos) desTanPixPos = pixelToFieldNoDistortion.applyInverse( fieldPos) self.assertPairsAlmostEqual(desTanPixPos, tanPixPos)