Example #1
0
    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)
Example #2
0
    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
Example #3
0
    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
Example #4
0
    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
Example #5
0
    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)
Example #6
0
    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)
Example #7
0
    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
Example #8
0
    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,
        )
Example #10
0
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
Example #11
0
    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)
Example #12
0
    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,
        )
Example #13
0
    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
Example #14
0
    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))
Example #15
0
    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])
Example #16
0
    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()
Example #17
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")
Example #18
0
    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)
Example #19
0
    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)
Example #20
0
    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)
Example #21
0
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