Esempio n. 1
0
def refLinearize(image, detector, table):
    """!Basic implementation of lookup table based non-linearity correction

    @param[in,out] image  image to correct in place (an lsst.afw.image.Image
                          of some type)
    @param[in] detector  detector info (an lsst.afw.cameraGeom.Detector)
    @param[in] table  lookup table: a 2D array of values of the same type as
           image;
            - one row for each row index (value of coef[0] in the amp info
              catalog)
            - one column for each image value

    @return the number of pixels whose values were out of range of the lookup
    table
    """
    ampInfoCat = detector.getAmplifiers()
    numOutOfRange = 0
    for ampInfo in ampInfoCat:
        bbox = ampInfo.getBBox()
        rowInd, colIndOffset = ampInfo.getLinearityCoeffs()[0:2]
        rowInd = int(rowInd)
        tableRow = table[rowInd, :]
        imView = image.Factory(image, bbox)
        numOutOfRange += applyLookupTable(imView, tableRow, colIndOffset)
    return numOutOfRange
    def testBasics(self):
        """!Test basic functionality of applyLookupTable
        """
        bbox = afwGeom.Box2I(afwGeom.Point2I(-31, 22),
                             afwGeom.Extent2I(100, 85))
        imMin = -5
        imMax = 2500
        tableLen = 2000
        tableSigma = 55
        for indOffset in (0, -50, 234):
            for imageClass in (afwImage.ImageF, afwImage.ImageD):
                inImage = makeRampImage(bbox=bbox,
                                        start=imMin,
                                        stop=imMax,
                                        imageClass=imageClass)
                table = np.random.normal(scale=tableSigma, size=tableLen)
                table = np.array(table, dtype=inImage.getArray().dtype)

                refImage = imageClass(inImage, True)
                refNumBad = referenceApply(image=refImage,
                                           table=table,
                                           indOffset=indOffset)

                measImage = imageClass(inImage, True)
                measNumBad = applyLookupTable(measImage, table, indOffset)

                self.assertEqual(refNumBad, measNumBad)
                self.assertImagesAlmostEqual(refImage, measImage)
Esempio n. 3
0
    def testKnown(self):
        """Test that a given image and lookup table produce the known answer

        Apply a negative ramp table to a positive ramp image to get a flat
        image, but have one value out of range at each end, to offset each end
        point by one
        """
        # generate a small ramp image with ascending integer values
        # starting at some small negative value going positive
        bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
                               lsst.geom.Extent2I(3, 4))
        numPix = bbox.getWidth() * bbox.getHeight()
        start = -3
        stop = start + numPix - 1
        im = makeRampImage(bbox=bbox,
                           start=start,
                           stop=stop,
                           imageClass=afwImage.ImageF)
        # generate a ramp lookup table with descending integer values,
        # with a range offset by a small arbitrary value from the image ramp
        # make it two elements too short so we can have one value out of range
        # at each end
        numOutOfRangePerEnd = 1
        numOutOfRange = 2 * numOutOfRangePerEnd
        tableOffset = -2
        table = np.linspace(start=stop + tableOffset,
                            stop=numOutOfRange + start + tableOffset,
                            num=numPix - numOutOfRange)
        table = np.array(table, dtype=im.getArray().dtype)
        # apply the table with the first and last image value out of range by
        # one.
        indOffset = -(start + numOutOfRangePerEnd)
        measNumOutOfRange = applyLookupTable(im, table, indOffset)
        self.assertEqual(numOutOfRange, measNumOutOfRange)
        # at this point the image should all have the same value
        # except the first point will be one less and the last one more
        imArr = im.getArray()
        desVal = start + numOutOfRangePerEnd + table[0]
        desImArr = np.zeros(numPix, dtype=im.getArray().dtype)
        desImArr[:] = desVal
        desImArr[0] -= 1
        desImArr[-1] += 1
        desImArr.shape = imArr.shape
        self.assertFloatsAlmostEqual(desImArr, imArr)
def refLinearize(image, detector, table):
    """!Basic implementation of lookup table based non-linearity correction

    @param[in,out] image  image to correct in place (an lsst.afw.image.Image of some type)
    @param[in] detector  detector info (an lsst.afw.cameraGeom.Detector)
    @param[in] table  lookup table: a 2D array of values of the same type as image;
            - one row for each row index (value of coef[0] in the amp info catalog)
            - one column for each image value

    @return the number of pixels whose values were out of range of the lookup table
    """
    ampInfoCat = detector.getAmpInfoCatalog()
    numOutOfRange = 0
    for ampInfo in ampInfoCat:
        bbox = ampInfo.getBBox()
        rowInd, colIndOffset = ampInfo.getLinearityCoeffs()[0:2]
        rowInd = int(rowInd)
        tableRow = table[rowInd, :]
        imView = image.Factory(image, bbox)
        numOutOfRange += applyLookupTable(imView, tableRow, colIndOffset)
    return numOutOfRange
    def testBasics(self):
        """!Test basic functionality of applyLookupTable
        """
        bbox = afwGeom.Box2I(afwGeom.Point2I(-31, 22), afwGeom.Extent2I(100, 85))
        imMin = -5
        imMax = 2500
        tableLen = 2000
        tableSigma = 55
        for indOffset in (0, -50, 234):
            for imageClass in (afwImage.ImageF, afwImage.ImageD):
                inImage = makeRampImage(bbox=bbox, start=imMin, stop=imMax, imageClass=imageClass)
                table = np.random.normal(scale=tableSigma, size=tableLen)
                table = np.array(table, dtype=inImage.getArray().dtype)

                refImage = imageClass(inImage, True)
                refNumBad = referenceApply(image=refImage, table=table, indOffset=indOffset)

                measImage = imageClass(inImage, True)
                measNumBad = applyLookupTable(measImage, table, indOffset)

                self.assertEqual(refNumBad, measNumBad)
                self.assertImagesAlmostEqual(refImage, measImage)
    def testKnown(self):
        """Test that a given image and lookup table produce the known answer

        Apply a negative ramp table to a positive ramp image to get a flat image,
        but have one value out of range at each end, to offset each end point by one
        """
        # generate a small ramp image with ascending integer values
        # starting at some small negative value going positive
        bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(3, 4))
        numPix = bbox.getWidth()*bbox.getHeight()
        start = -3
        stop = start + numPix - 1
        im = makeRampImage(bbox=bbox, start=start, stop=stop, imageClass=afwImage.ImageF)
        # generate a ramp lookup table with descending integer values,
        # with a range offset by a small arbitrary value from the image ramp
        # make it two elements too short so we can have one value out of range at each end
        numOutOfRangePerEnd = 1
        numOutOfRange = 2*numOutOfRangePerEnd
        tableOffset = -2
        table = np.linspace(
            start=stop + tableOffset,
            stop=numOutOfRange + start + tableOffset,
            num=numPix - numOutOfRange)
        table = np.array(table, dtype=im.getArray().dtype)
        # apply the table with the first and last image value out of range by one
        indOffset = -(start + numOutOfRangePerEnd)
        measNumOutOfRange = applyLookupTable(im, table, indOffset)
        self.assertEqual(numOutOfRange, measNumOutOfRange)
        # at this point the image should all have the same value
        # except the first point will be one less and the last one more
        imArr = im.getArray()
        desVal = start + numOutOfRangePerEnd + table[0]
        desImArr = np.zeros(numPix, dtype=im.getArray().dtype)
        desImArr[:] = desVal
        desImArr[0] -= 1
        desImArr[-1] += 1
        desImArr.shape = imArr.shape
        self.assertFloatsAlmostEqual(desImArr, imArr)
Esempio n. 7
0
def referenceImage(image, detector, linearityType, inputData, table=None):
    """Generate a reference linearization.

    Parameters
    ----------
    image: `lsst.afw.image.Image`
        Image to linearize.
    detector: `lsst.afw.cameraGeom.Detector`
        Detector this image is from.
    linearityType: `str`
        Type of linearity to apply.
    inputData: `numpy.array`
        An array of values for the linearity correction.
    table: `numpy.array`, optional
        An optional lookup table to use.

    Returns
    -------
    outImage: `lsst.afw.image.Image`
        The output linearized image.
    numOutOfRange: `int`
        The number of values that could not be linearized.

    Raises
    ------
    RuntimeError :
        Raised if an invalid linearityType is supplied.
    """
    numOutOfRange = 0
    for ampIdx, amp in enumerate(detector.getAmplifiers()):
        ampIdx = (ampIdx // 3, ampIdx % 3)
        bbox = amp.getBBox()
        imageView = image.Factory(image, bbox)

        if linearityType == 'Squared':
            sqCoeff = inputData[ampIdx]
            array = imageView.getArray()

            array[:] = array + sqCoeff * array**2
        elif linearityType == 'LookupTable':
            rowInd, colIndOffset = inputData[ampIdx]
            rowInd = int(rowInd)
            tableRow = table[rowInd, :]
            numOutOfRange += applyLookupTable(imageView, tableRow,
                                              colIndOffset)
        elif linearityType == 'Polynomial':
            coeffs = inputData[ampIdx]
            array = imageView.getArray()
            summation = np.zeros_like(array)
            for index, coeff in enumerate(coeffs):
                summation += coeff * np.power(array, (index + 2))
            array += summation
        elif linearityType == 'Spline':
            centers, values = np.split(inputData, 2)  # This uses the full data
            interp = afwMath.makeInterpolate(
                centers.tolist(), values.tolist(),
                afwMath.stringToInterpStyle('AKIMA_SPLINE'))
            array = imageView.getArray()
            delta = interp.interpolate(array.flatten())
            array -= np.array(delta).reshape(array.shape)
        else:
            raise RuntimeError(f"Unknown linearity: {linearityType}")
    return image, numOutOfRange