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 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 setUp(self): self.pairs = [ '[3021120600588, 3021120600589]', '[3021120600639, 3021120600640]', '[3021120600711, 3021120600712]', '[3021120600774, 3021120600775]', '[3021120600612, 3021120600613]', '[3021120600675, 3021120600676]' ] self.corrections = [ 0.0008682616635145324, 0.0008634151174990838, 0.0008343013803181451, 0.0007904133024002547, 0.0007386119393599833, 0.000780670380485576 ] camBuilder = cameraGeom.Camera.Builder("fakeCam") detBuilder = camBuilder.add('det_a', 1) detBuilder.setSerial("123") bbox = geom.Box2I(geom.Point2I(0, 0), geom.Extent2I(100, 100)) orientation = cameraGeom.Orientation() pixelSize = lsst.geom.Extent2D(1, 1) detBuilder.setBBox(bbox) detBuilder.setOrientation(orientation) detBuilder.setPixelSize(pixelSize) self.camera = camBuilder self.detector = detBuilder
def setUp(self): self.timeSeries = [ 0.0, 0.08496094, 0.1689453, 0.2529297, 0.3378906, 0.421875, 0.5068359, 0.5908203, 0.6757813, 0.7597656, 0.84375, 0.9287109, 1.012695, 1.097656, 1.181641, 1.266602 ] self.currentSeries = [ -1.350031E-12, 1.598721E-13, -1.456613E-13, -1.385558E-13, -3.517187E-13, -3.375078E-13, 3.597549E-10, 3.591616E-10, 3.599823E-10, 3.597158E-10, 3.606893E-10, 3.602736E-10, 3.582272E-10, 3.59293E-10, 3.602878E-10, 3.588703E-10 ] camBuilder = cameraGeom.Camera.Builder("fakeCam") detBuilder = camBuilder.add('det_a', 1) detBuilder.setSerial("123") bbox = geom.Box2I(geom.Point2I(0, 0), geom.Extent2I(100, 100)) orientation = cameraGeom.Orientation() pixelSize = lsst.geom.Extent2D(1, 1) detBuilder.setBBox(bbox) detBuilder.setOrientation(orientation) detBuilder.setPixelSize(pixelSize) self.camera = camBuilder self.detector = detBuilder
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 makeDetector(self, linearityType, bbox=None): """Generate a fake detector for the test. Parameters ---------- linearityType : `str` Which linearity to assign to the detector's cameraGeom. bbox : `lsst.geom.Box2I`, optional Bounding box to use for the detector. Returns ------- detBuilder : `lsst.afw.cameraGeom.Detector` The fake detector. """ bbox = bbox if bbox is not None else self.bbox numAmps = self.ampArrangement detName = "det_a" detId = 1 detSerial = "123" orientation = cameraGeom.Orientation() pixelSize = lsst.geom.Extent2D(1, 1) camBuilder = cameraGeom.Camera.Builder("fakeCam") detBuilder = camBuilder.add(detName, detId) detBuilder.setSerial(detSerial) detBuilder.setBBox(bbox) detBuilder.setOrientation(orientation) detBuilder.setPixelSize(pixelSize) boxArr = BoxGrid(box=bbox, numColRow=numAmps) for i in range(numAmps[0]): for j in range(numAmps[1]): ampInfo = cameraGeom.Amplifier.Builder() ampInfo.setName("amp %d_%d" % (i + 1, j + 1)) ampInfo.setBBox(boxArr[i, j]) ampInfo.setLinearityType(linearityType) if linearityType == 'Squared': ampInfo.setLinearityCoeffs([self.sqCoeffs[i, j]]) elif linearityType == 'LookupTable': # setLinearityCoeffs is picky about getting a mixed # int/float list. ampInfo.setLinearityCoeffs( np.array([ self.rowInds[i, j], self.colIndOffsets[i, j], 0, 0 ], dtype=float)) elif linearityType == 'Polynomial': ampInfo.setLinearityCoeffs(self.polyCoeffs[i, j]) elif linearityType == 'Spline': ampInfo.setLinearityCoeffs(self.splineCoeffs) detBuilder.append(ampInfo) return detBuilder
def makeDetector(self, bbox=None, numAmps=None, rowInds=None, colIndOffsets=None, detName="det_a", detSerial="123", linearityType="LookupTable"): """!Make a detector @param[in] bbox bounding box for image @param[n] numAmps x,y number of amplifiers (pair of int) @param[in] rowInds index of lookup table for each amplifier (array of shape numAmps) @param[in] colIndOffsets column index offset for each amplifier (array of shape numAmps) @param[in] detName detector name (a str) @param[in] detSerial detector serial numbe (a str) @param[in] linearityType name of linearity type (a str) @return a detector (an lsst.afw.cameraGeom.Detector) """ bbox = bbox if bbox is not None else self.bbox numAmps = numAmps if numAmps is not None else self.numAmps rowInds = rowInds if rowInds is not None else self.rowInds colIndOffsets = colIndOffsets if colIndOffsets is not None else self.colIndOffsets detId = 1 orientation = cameraGeom.Orientation() pixelSize = lsst.geom.Extent2D(1, 1) camBuilder = cameraGeom.Camera.Builder("fakeCam") detBuilder = camBuilder.add(detName, detId) detBuilder.setSerial(detSerial) detBuilder.setBBox(bbox) detBuilder.setOrientation(orientation) detBuilder.setPixelSize(pixelSize) boxArr = BoxGrid(box=bbox, numColRow=numAmps) for i in range(numAmps[0]): for j in range(numAmps[1]): ampInfo = cameraGeom.Amplifier.Builder() ampInfo.setName("amp %d_%d" % (i + 1, j + 1)) ampInfo.setBBox(boxArr[i, j]) ampInfo.setLinearityType(linearityType) # setLinearityCoeffs is picky about getting a mixed int/float # list. ampInfo.setLinearityCoeffs( np.array([rowInds[i, j], colIndOffsets[i, j], 0, 0], dtype=float)) detBuilder.append(ampInfo) return detBuilder
def makeDetector(self, bbox=None, numAmps=None, rowInds=None, colIndOffsets=None, detName="det_a", detSerial="123", linearityType="LookupTable"): """!Make a detector @param[in] bbox bounding box for image @param[n] numAmps x,y number of amplifiers (pair of int) @param[in] rowInds index of lookup table for each amplifier (array of shape numAmps) @param[in] colIndOffsets column index offset for each amplifier (array of shape numAmps) @param[in] detName detector name (a str) @param[in] detSerial detector serial numbe (a str) @param[in] linearityType name of linearity type (a str) @return a detector (an lsst.afw.cameraGeom.Detector) """ bbox = bbox if bbox is not None else self.bbox numAmps = numAmps if numAmps is not None else self.numAmps rowInds = rowInds if rowInds is not None else self.rowInds colIndOffsets = colIndOffsets if colIndOffsets is not None else self.colIndOffsets schema = afwTable.AmpInfoTable.makeMinimalSchema() ampInfoCat = afwTable.AmpInfoCatalog(schema) boxArr = BoxGrid(box=bbox, numColRow=numAmps) for i in range(numAmps[0]): for j in range(numAmps[1]): ampInfo = ampInfoCat.addNew() ampInfo.setName("amp %d_%d" % (i + 1, j + 1)) ampInfo.setBBox(boxArr[i, j]) ampInfo.setLinearityType(linearityType) # setLinearityCoeffs is picky about getting a mixed int/float list. ampInfo.setLinearityCoeffs( np.array([rowInds[i, j], colIndOffsets[i, j], 0, 0], dtype=float)) detId = 1 orientation = cameraGeom.Orientation() pixelSize = afwGeom.Extent2D(1, 1) transMap = {} return cameraGeom.Detector( detName, detId, cameraGeom.SCIENCE, detSerial, bbox, ampInfoCat, orientation, pixelSize, transMap, )
def makeCamera(name="DECam"): camera = cameraGeom.Camera(cameraGeom.Id(name), 62, 1) for i in range(62): if i > 31: dewarName = "S%d" % (62 - i + 1) else: dewarName = "S%d" % (i + 1) camera.addDetector(afwGeom.PointI(i, 0), cameraGeom.FpPoint(25.4 * 2.5 * (2.5 - i), 0.0), cameraGeom.Orientation(0), makeRaft(dewarName)) return camera
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 makeDetector(self, bbox=None, numAmps=None, sqCoeffs=None, linearityType="Squared"): """!Make a detector @param[in] bbox bounding box for image @param[n] numAmps x,y number of amplifiers (pair of int) @param[in] sqCoeffs square coefficient for each amplifier (2D array of float) @param[in] detName detector name (a str) @param[in] detID detector ID (an int) @param[in] detSerial detector serial numbe (a str) @param[in] linearityType name of linearity type (a str) @return a detector (an lsst.afw.cameraGeom.Detector) """ bbox = bbox if bbox is not None else self.bbox numAmps = numAmps if numAmps is not None else self.numAmps sqCoeffs = sqCoeffs if sqCoeffs is not None else self.sqCoeffs schema = afwTable.AmpInfoTable.makeMinimalSchema() ampInfoCat = afwTable.AmpInfoCatalog(schema) boxArr = BoxGrid(box=bbox, numColRow=numAmps) for i in range(numAmps[0]): for j in range(numAmps[1]): ampInfo = ampInfoCat.addNew() ampInfo.setName("amp %d_%d" % (i + 1, j + 1)) ampInfo.setBBox(boxArr[i, j]) ampInfo.setLinearityType(linearityType) ampInfo.setLinearityCoeffs([sqCoeffs[i, j]]) detName = "det_a" detId = 1 detSerial = "123" orientation = cameraGeom.Orientation() pixelSize = afwGeom.Extent2D(1, 1) transMap = {} return cameraGeom.Detector( detName, detId, cameraGeom.SCIENCE, detSerial, bbox, ampInfoCat, orientation, pixelSize, transMap, )
def makeDetector(self, bbox=None, numAmps=None, sqCoeffs=None, linearityType="Squared"): """!Make a detector @param[in] bbox bounding box for image @param[n] numAmps x,y number of amplifiers (pair of int) @param[in] sqCoeffs square coefficient for each amplifier (2D array of float) @param[in] detName detector name (a str) @param[in] detID detector ID (an int) @param[in] detSerial detector serial numbe (a str) @param[in] linearityType name of linearity type (a str) @return a detector (an lsst.afw.cameraGeom.Detector) """ bbox = bbox if bbox is not None else self.bbox numAmps = numAmps if numAmps is not None else self.numAmps sqCoeffs = sqCoeffs if sqCoeffs is not None else self.sqCoeffs detName = "det_a" detId = 1 detSerial = "123" orientation = cameraGeom.Orientation() pixelSize = lsst.geom.Extent2D(1, 1) camBuilder = cameraGeom.Camera.Builder("fakeCam") detBuilder = camBuilder.add(detName, detId) detBuilder.setSerial(detSerial) detBuilder.setBBox(bbox) detBuilder.setOrientation(orientation) detBuilder.setPixelSize(pixelSize) boxArr = BoxGrid(box=bbox, numColRow=numAmps) for i in range(numAmps[0]): for j in range(numAmps[1]): ampInfo = cameraGeom.Amplifier.Builder() ampInfo.setName("amp %d_%d" % (i + 1, j + 1)) ampInfo.setBBox(boxArr[i, j]) ampInfo.setLinearityType(linearityType) ampInfo.setLinearityCoeffs([sqCoeffs[i, j]]) detBuilder.append(ampInfo) return detBuilder
def testSortedCcds(self): """Test if the Ccds are sorted by ID after insertion into a Raft""" raft = cameraGeom.Raft(cameraGeom.Id(), 8, 1) Col = 0 for serial in [7, 0, 1, 3, 2, 6, 5, 4]: ccd = cameraGeom.Ccd(cameraGeom.Id(serial)) raft.addDetector(afwGeom.Point2I(Col, 0), cameraGeom.FpPoint(afwGeom.Point2D(0, 0)), cameraGeom.Orientation(0), ccd) Col += 1 # # Check that CCDs are sorted by Id # serials = [] for ccd in raft: serials.append(ccd.getId().getSerial()) self.assertEqual(serials, sorted(serials))
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 testRotatedCcd(self): """Test if we can build a Ccd out of Amps""" #print >> sys.stderr, "Skipping testRotatedCcd"; return ccdId = cameraGeom.Id(1, "Rot. CCD") ccdInfo = {"ampSerial" : CameraGeomTestCase.ampSerial} ccd = cameraGeomUtils.makeCcd(self.geomPolicy, ccdId, ccdInfo=ccdInfo) zero = 0.0*afwGeom.radians ccd.setOrientation(cameraGeom.Orientation(1, zero, zero, zero)) if display: cameraGeomUtils.showCcd(ccd) ds9.incrDefaultFrame() # # Trim the CCD and try again # trimmedImage = trimCcd(ccd) if display: cameraGeomUtils.showCcd(ccd, trimmedImage) ds9.incrDefaultFrame()
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 setUp(self): self.x0, self.y0 = 0, 0 self.nx, self.ny = 512, 512 #2048, 4096 self.sky = 100.0 self.nObj = 100 # make a detector with distortion self.detector = DetectorWrapper( bbox = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Extent2I(self.nx, self.ny)), orientation = cameraGeom.Orientation(afwGeom.Point2D(255.0, 255.0)), radialDistortion = 0.925, ).detector # make a detector with no distortion self.flatDetector = DetectorWrapper( bbox = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Extent2I(self.nx, self.ny)), orientation = cameraGeom.Orientation(afwGeom.Point2D(255.0, 255.0)), radialDistortion = 0.0, ).detector # detection policies detConfig = measAlg.SourceDetectionConfig() # Cannot use default background approximation order (6) for such a small image. detConfig.background.approxOrderX = 4 # measurement policies measConfig = measBase.SingleFrameMeasurementConfig() measConfig.algorithms.names = [ "base_SdssCentroid", "base_SdssShape", "base_GaussianFlux", "base_PsfFlux", ] measConfig.slots.centroid = "base_SdssCentroid" measConfig.slots.shape = "base_SdssShape" measConfig.slots.psfFlux = "base_PsfFlux" measConfig.slots.apFlux = None measConfig.slots.modelFlux = None measConfig.slots.instFlux = None measConfig.slots.calibFlux = None self.schema = afwTable.SourceTable.makeMinimalSchema() detConfig.validate() measConfig.validate() self.detTask = measAlg.SourceDetectionTask(config=detConfig, schema=self.schema) self.measTask = measBase.SingleFrameMeasurementTask(config=measConfig, schema=self.schema) # psf star selector starSelectorConfig = measAlg.SecondMomentStarSelectorTask.ConfigClass() starSelectorConfig.fluxLim = 5000.0 starSelectorConfig.histSize = 32 starSelectorConfig.clumpNSigma = 1.0 starSelectorConfig.badFlags = [] self.starSelector = measAlg.SecondMomentStarSelectorTask( config=starSelectorConfig, schema=self.schema ) # psf determiner psfDeterminerFactory = measAlg.psfDeterminerRegistry["pca"] psfDeterminerConfig = psfDeterminerFactory.ConfigClass() width, height = self.nx, self.ny nEigenComponents = 3 psfDeterminerConfig.sizeCellX = width//3 psfDeterminerConfig.sizeCellY = height//3 psfDeterminerConfig.nEigenComponents = nEigenComponents psfDeterminerConfig.spatialOrder = 1 psfDeterminerConfig.kernelSizeMin = 31 psfDeterminerConfig.nStarPerCell = 0 psfDeterminerConfig.nStarPerCellSpatialFit = 0 # unlimited self.psfDeterminer = psfDeterminerFactory(psfDeterminerConfig)
def setUp(self): """Constructs a CCD with two amplifiers and prepares for ISR""" np.random.seed(12345) baseValue = 100.0 gain = 1.0 readNoise = 123456789.0 saturation = 987654321.0 height = 234 imageSize = Extent2I(123, height) overscanSize = Extent2I(16, height) self.sigma = 1.234 # Set up the various regions overscan1 = Box2I(Point2I(0, 0), overscanSize) image1 = Box2I(Point2I(overscanSize[0], 0), imageSize) image2 = Box2I(Point2I(overscanSize[0] + imageSize[0], 0), imageSize) overscan2 = Box2I(Point2I(overscanSize[0] + 2 * imageSize[0], 0), overscanSize) leftBox = Box2I( overscan1.getMin(), Extent2I(overscan1.getWidth() + image1.getWidth(), height)) rightBox = Box2I( image2.getMin(), Extent2I(image2.getWidth() + overscan2.getWidth(), height)) target1 = Box2I(Point2I(0, 0), imageSize) target2 = Box2I(Point2I(image1.getWidth(), 0), imageSize) # Set the pixels exposure = ExposureF( Box2I(Point2I(0, 0), Extent2I(imageSize[0] * 2 + overscanSize[0] * 2, height))) yy = np.arange(0, height, 1, dtype=np.float32) leftImage = ExposureF(exposure, leftBox) leftImage.image.array[:] = baseValue + yy[:, np.newaxis] rightImage = ExposureF(exposure, rightBox) rightImage.image.array[:] = baseValue - yy[:, np.newaxis] leftOverscan = ExposureF(exposure, overscan1) leftOverscan.image.array += np.random.normal( 0.0, self.sigma, leftOverscan.image.array.shape) rightOverscan = ExposureF(exposure, overscan2) rightOverscan.image.array += np.random.normal( 0.0, self.sigma, leftOverscan.image.array.shape) exposure.mask.array[:] = 0.0 exposure.variance.array[:] = np.nan # Construct the detectors amp1 = makeAmplifier("left", target1, image1, overscan1, gain, readNoise, saturation) amp2 = makeAmplifier("right", target2, image2, overscan2, gain, readNoise, saturation) ccdBox = Box2I(Point2I(0, 0), Extent2I(image1.getWidth() + image2.getWidth(), height)) camBuilder = cameraGeom.Camera.Builder("fakeCam") detBuilder = camBuilder.add("detector", 1) detBuilder.setSerial("det1") detBuilder.setBBox(ccdBox) detBuilder.setPixelSize(Extent2D(1.0, 1.0)) detBuilder.setOrientation(cameraGeom.Orientation()) detBuilder.append(amp1) detBuilder.append(amp2) cam = camBuilder.finish() exposure.setDetector(cam.get('detector')) header = PropertyList() header.add("EXPTIME", 0.0) exposure.getInfo().setVisitInfo(VisitInfo(header)) self.exposure = exposure self.config = IsrTask.ConfigClass() # Disable everything we don't care about self.config.doBias = False self.config.doDark = False self.config.doFlat = False self.config.doFringe = False self.config.doDefect = False self.config.doWrite = False self.config.expectWcs = False self.config.doLinearize = False self.config.doCrosstalk = False self.config.doBrighterFatter = False self.config.doAttachTransmissionCurve = False self.config.doAssembleCcd = False self.config.doNanMasking = False self.config.doInterpolate = False self.config.maskNegativeVariance = False # This runs on mocks. # Set the things that match our test setup self.config.overscan.fitType = "CHEB" self.config.overscan.order = 1 self.config.doEmpiricalReadNoise = True self.task = IsrTask(config=self.config)
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)
def makeRaft(raftName): dewar = cameraGeom.Raft(cameraGeom.Id("DECam"), 1, 1) dewar.addDetector(afwGeom.PointI(0, 0), cameraGeom.FpPoint(0.0, 0.0), cameraGeom.Orientation(0), makeCcd(raftName)) return dewar