def testBasics(self):
        """!Test basic functionality of LinearizeLookupTable
        """
        for imageClass in (afwImage.ImageF, afwImage.ImageD):
            inImage = makeRampImage(bbox=self.bbox,
                                    start=-5,
                                    stop=250,
                                    imageClass=imageClass)
            table = self.makeTable(inImage)

            measImage = inImage.Factory(inImage, True)
            llt = LinearizeLookupTable(table=table, detector=self.detector)
            linRes = llt(measImage, self.detector)

            refImage = inImage.Factory(inImage, True)
            refNumOutOfRange = refLinearize(image=refImage,
                                            detector=self.detector,
                                            table=table)

            self.assertEqual(linRes.numAmps,
                             len(self.detector.getAmpInfoCatalog()))
            self.assertEqual(linRes.numAmps, linRes.numLinearized)
            self.assertEqual(linRes.numOutOfRange, refNumOutOfRange)
            self.assertImagesAlmostEqual(refImage, measImage)

            # make sure logging is accepted
            log = Log.getLogger("ip.isr.LinearizeLookupTable")
            linRes = llt(image=measImage, detector=self.detector, log=log)
    def testErrorHandling(self):
        """!Test error handling in LinearizeLookupTable
        """
        image = makeRampImage(bbox=self.bbox, start=-5, stop=250)
        table = self.makeTable(image)
        llt = LinearizeLookupTable(table=table, detector=self.detector)

        # bad name
        detBadName = self.makeDetector(detName="bad_detector_name")
        with self.assertRaises(RuntimeError):
            llt(image, detBadName)

        # bad serial
        detBadSerial = self.makeDetector(detSerial="bad_detector_serial")
        with self.assertRaises(RuntimeError):
            llt(image, detBadSerial)

        # bad number of amplifiers
        badNumAmps = (self.numAmps[0] - 1, self.numAmps[1])
        detBadNumMaps = self.makeDetector(numAmps=badNumAmps)
        with self.assertRaises(RuntimeError):
            llt(image, detBadNumMaps)

        # bad linearity type
        detBadLinType = self.makeDetector(linearityType="bad_linearity_type")
        with self.assertRaises(RuntimeError):
            llt(image, detBadLinType)
예제 #3
0
def makeLinearizerDecam(fromFile, force=False, verbose=False):
    """Convert the specified DECam linearity FITS table to standard LSST format

    Details:
    - Input format is one table per CCD, HDU is amplifier number,
        the table has 3 columns: ADU, ADU_LINEAR_A, ADU_LINEAR_B.
        The values of ADU contiguous (0, 1, 2...) but check and error out if not.
        The values of the latter two are replacements (0+delta0, 1+delta1, 2+delta2...)
        and this is converted to offsets for the LSST linearization tables (delta0, delta1, delta2...)
    - Output is a set of LinearizeLookupTable instances, one per CCD, saved as dataset type "linearizer"
    - The row indices for the linearization lookup table are (row index=amp name): 0=A, 1=B

    @param[in] fromFile  path to DECam linearity table (a FITS file with one HDU per amplifier)
    """
    print("Making DECam linearizers from %r" % (fromFile, ))
    butler = Butler(mapper=DecamMapper)
    linearizerDir = DecamMapper.getLinearizerDir()
    if os.path.exists(linearizerDir):
        if not force:
            print("Output directory %r exists; use --force to replace" %
                  (linearizerDir, ))
            sys.exit(1)
        print("Replacing data in linearizer directory %r" % (linearizerDir, ))
    else:
        print("Creating linearizer directory %r" % (linearizerDir, ))
        os.makedirs(linearizerDir)

    camera = DecamMapper().camera
    fromHDUs = fits.open(fromFile)[1:]  # HDU 0 has no data
    assert len(fromHDUs) == len(camera)
    for ccdind, (detector, hdu) in enumerate(zip(camera, fromHDUs)):
        ccdnum = ccdind + 1
        if verbose:
            print("ccdnum=%s; detector=%s" % (ccdnum, detector.getName()))
        fromData = hdu.data
        assert len(fromData.dtype) == 3
        lsstTable = np.zeros((2, len(fromData)), dtype=np.float32)
        uncorr = fromData["ADU"]
        if not np.allclose(uncorr, np.arange(len(fromData))):
            raise RuntimeError(
                "ADU data not a range of integers starting at 0")
        for i, ampName in enumerate("AB"):
            # convert DECam replacement table to LSST offset table
            if verbose:
                print("DECam table for %s=%s..." % (
                    ampName,
                    fromData["ADU_LINEAR_" + ampName][0:5],
                ))
            lsstTable[i, :] = fromData["ADU_LINEAR_" + ampName] - uncorr
            if verbose:
                print("LSST  table for %s=%s..." % (
                    ampName,
                    lsstTable[i, 0:5],
                ))
        linearizer = LinearizeLookupTable(table=lsstTable, detector=detector)
        butler.put(linearizer, "linearizer", dataId=dict(ccdnum=ccdnum))
    print("Wrote %s linearizers" % (ccdind + 1, ))
예제 #4
0
    def testKnown(self):
        """!Test a few known values
        """
        numAmps = (2, 2)
        bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
                               lsst.geom.Extent2I(4, 4))
        # make a 4x4 image with 4 identical 2x2 subregions that flatten to -1, 0, 1, 2
        im = afwImage.ImageF(bbox)
        imArr = im.getArray()
        imArr[:, :] = np.array(
            ((-1, 0, -1, 0), (1, 2, 1, 2), (-1, 0, -1, 0), (1, 2, 1, 2)),
            dtype=imArr.dtype)

        def castAndReshape(arr):
            arr = np.array(arr, dtype=float)
            arr.shape = numAmps
            return arr

        rowInds = castAndReshape(
            (3, 2, 1,
             0))  # avoid the trivial mapping to exercise more of the code
        colIndOffsets = castAndReshape((0, 0, 1, 1))
        detector = self.makeDetector(bbox=bbox,
                                     numAmps=numAmps,
                                     rowInds=rowInds,
                                     colIndOffsets=colIndOffsets)
        ampInfoCat = detector.getAmpInfoCatalog()

        # note: table rows are reversed relative to amplifier order because rowInds is a descending ramp
        table = np.array(
            ((7, 6, 5, 4), (1, 1, 1, 1), (5, 4, 3, 2), (0, 0, 0, 0)),
            dtype=imArr.dtype)

        llt = LinearizeLookupTable(table=table, detector=detector)

        lltRes = llt(image=im, detector=detector)
        self.assertEqual(lltRes.numOutOfRange, 2)

        # amp 0 is a constant correction of 0; one image value is out of range, but it doesn't matter
        imArr0 = im.Factory(im, ampInfoCat[0].getBBox()).getArray()
        self.assertFloatsAlmostEqual(imArr0.flatten(), (-1, 0, 1, 2))

        # amp 1 is a correction of (5, 4, 3, 2), but the first image value is under range
        imArr1 = im.Factory(im, ampInfoCat[1].getBBox()).getArray()
        self.assertFloatsAlmostEqual(imArr1.flatten(), (4, 5, 5, 5))

        # amp 2 is a constant correction of +1; all image values are in range, but it doesn't matter
        imArr2 = im.Factory(im, ampInfoCat[2].getBBox()).getArray()
        self.assertFloatsAlmostEqual(imArr2.flatten(), (0, 1, 2, 3))

        # amp 3 is a correction of (7, 6, 5, 4); all image values in range
        imArr1 = im.Factory(im, ampInfoCat[3].getBBox()).getArray()
        self.assertFloatsAlmostEqual(imArr1.flatten(), (6, 6, 6, 6))
    def testPickle(self):
        """!Test that a LinearizeLookupTable can be pickled and unpickled
        """
        inImage = makeRampImage(bbox=self.bbox, start=-5, stop=2500)
        table = self.makeTable(inImage)
        llt = LinearizeLookupTable(table=table, detector=self.detector)

        refImage = inImage.Factory(inImage, True)
        refNumOutOfRange = llt(refImage, self.detector)

        pickledStr = pickle.dumps(llt)
        restoredLlt = pickle.loads(pickledStr)

        measImage = inImage.Factory(inImage, True)
        measNumOutOfRange = restoredLlt(measImage, self.detector)

        self.assertEqual(refNumOutOfRange, measNumOutOfRange)
        self.assertImagesAlmostEqual(refImage, measImage)