예제 #1
0
    def testBasics(self):
        """!Test basic functionality of LinearizeSquared
        """
        for imageClass in (afwImage.ImageF, afwImage.ImageD):
            inImage = makeRampImage(bbox=self.bbox,
                                    start=-5,
                                    stop=2500,
                                    imageClass=imageClass)

            measImage = inImage.Factory(inImage, True)
            linCorr = Linearizer(detector=self.detector)
            linRes = linCorr.applyLinearity(image=measImage,
                                            detector=self.detector)
            desNumLinearized = np.sum(self.sqCoeffs.flatten() > 0)
            self.assertEqual(linRes.numLinearized, desNumLinearized)
            self.assertEqual(linRes.numAmps,
                             len(self.detector.getAmplifiers()))

            refImage = inImage.Factory(inImage, True)
            refLinearizeSquared(image=refImage, detector=self.detector)

            self.assertImagesAlmostEqual(refImage, measImage)

            # make sure logging is accepted
            log = logging.getLogger("lsst.ip.isr.LinearizeSquared")
            linRes = linCorr.applyLinearity(image=measImage,
                                            detector=self.detector,
                                            log=log)
예제 #2
0
    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)

            log = logging.getLogger("lsst.ip.isr.LinearizeLookupTable")

            measImage = inImage.Factory(inImage, True)
            llt = Linearizer(table=table, detector=self.detector)
            linRes = llt.applyLinearity(measImage,
                                        detector=self.detector,
                                        log=log)

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

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

            # make sure logging is accepted
            log = logging.getLogger("lsst.ip.isr.LinearizeLookupTable")
            linRes = llt.applyLinearity(image=measImage,
                                        detector=self.detector,
                                        log=log)
예제 #3
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.getAmplifiers()

        # 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 = Linearizer(table=table, detector=detector)

        lltRes = llt.applyLinearity(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))
예제 #4
0
    def bypass_linearizer(self, datasetType, pythonType, butlerLocation, dataId):
        """Return a linearizer for the given detector.

        On each call, a fresh instance of `Linearizer` is returned; the caller
        is responsible for initializing it appropriately for the detector.

        Parameters
        ----------
        datasetType : `str``
            The dataset type.
        pythonType : `str` or `type`
            Type of python object.
        butlerLocation : `lsst.daf.persistence.ButlerLocation`
            Struct-like class that holds information needed to persist and
            retrieve an object using the LSST Persistence Framework.
        dataId : `dict`
            dataId passed to map location.

        Returns
        -------
        Linearizer : `lsst.ip.isr.Linearizer`
            Linearizer object for the given detector.

        Notes
        -----
        Linearizers are not saved to persistent storage; rather, they are
        managed entirely in memory. On each call, this function will return a
        new instance of `Linearizer`, which must be managed (including setting
        it up for use with a particular detector) by the caller. Calling
        `bypass_linearizer` twice for the same detector will return
        _different_ instances of `Linearizer`, which share no state.
        """
        return Linearizer(detectorId=dataId.get('ccd', None))
예제 #5
0
 def testGetLinearizer(self):
     """Test that we can get a linearizer"""
     camera = self.butler.get("camera")
     for ccdnum in (1, 62):
         detector = camera[ccdnum]
         linearizer = Linearizer(table=self.butler.get(
             "linearizer", dataId=dict(ccdnum=ccdnum), immediate=True),
                                 detector=detector)
         for amp in detector:
             self.assertEqual(linearizer.linearityType[amp.getName()],
                              LinearizeLookupTable.LinearityType)
         linearizer.validate(detector=detector)
     for badccdnum in (0, 63):
         with self.assertRaises(Exception):
             self.butler.get("linearizer",
                             dataId=dict(ccdnum=badccdnum),
                             immediate=True)
예제 #6
0
    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 = Linearizer(table=table, detector=self.detector)

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

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

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

        self.assertEqual(refNumOutOfRange, measNumOutOfRange)
        self.assertImagesAlmostEqual(refImage, measImage)
예제 #7
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)

        sqCoeffs = np.array(((0, 0.11), (-0.15, -12)))
        detector = self.makeDetector(bbox=bbox,
                                     numAmps=numAmps,
                                     sqCoeffs=sqCoeffs)
        ampInfoCat = detector.getAmplifiers()

        linSq = Linearizer(detector=detector)
        linSq.applyLinearity(im, detector=detector)

        # amp 0 has 0 squared coefficient and so makes no correction
        imArr0 = im.Factory(im, ampInfoCat[0].getBBox()).getArray()
        linCoeff0 = ampInfoCat[0].getLinearityCoeffs()[0]
        self.assertEqual(0, linCoeff0)
        self.assertFloatsAlmostEqual(imArr0.flatten(), (-1, 0, 1, 2))

        # test all amps
        for ampInfo in ampInfoCat:
            imArr = im.Factory(im, ampInfo.getBBox()).getArray()
            linCoeff = ampInfo.getLinearityCoeffs()[0]
            expect = np.array(
                (-1 + linCoeff, 0, 1 + linCoeff, 2 + 4 * linCoeff),
                dtype=imArr.dtype)
            self.assertFloatsAlmostEqual(imArr.flatten(), expect)
예제 #8
0
    def testErrorHandling(self):
        """!Test error handling in LinearizeLookupTable
        """
        image = makeRampImage(bbox=self.bbox, start=-5, stop=250)
        table = self.makeTable(image)
        llt = Linearizer(table=table, detector=self.detector)

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

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

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

        # bad linearity type
        detBadLinType = self.makeDetector(linearityType="bad_linearity_type")
        with self.assertRaises(RuntimeError):
            llt.applyLinearity(image, detBadLinType)

        # wrong dimension
        badTable = table[..., np.newaxis]
        with self.assertRaises(RuntimeError):
            Linearizer(table=badTable, detector=self.detector)

        # wrong size
        badTable = np.transpose(table)
        with self.assertRaises(RuntimeError):
            Linearizer(table=badTable, detector=self.detector)
예제 #9
0
    def run(self, inputPtc, camera, inputDims):
        """Fit non-linearity to PTC data, returning the correct Linearizer
        object.

        Parameters
        ----------
        inputPtc : `lsst.cp.pipe.PtcDataset`
            Pre-measured PTC dataset.
        camera : `lsst.afw.cameraGeom.Camera`
            Camera geometry.
        inputDims : `lsst.daf.butler.DataCoordinate` or `dict`
            DataIds to use to populate the output calibration.

        Returns
        -------
        results : `lsst.pipe.base.Struct`
            The results struct containing:

            ``outputLinearizer`` : `lsst.ip.isr.Linearizer`
                Final linearizer calibration.
            ``outputProvenance`` : `lsst.ip.isr.IsrProvenance`
                Provenance data for the new calibration.

        Notes
        -----
        This task currently fits only polynomial-defined corrections,
        where the correction coefficients are defined such that:
            corrImage = uncorrImage + sum_i c_i uncorrImage^(2 + i)
        These `c_i` are defined in terms of the direct polynomial fit:
            meanVector ~ P(x=timeVector) = sum_j k_j x^j
        such that c_(j-2) = -k_j/(k_1^j) in units of DN^(1-j) (c.f.,
        Eq. 37 of 2003.05978). The `config.polynomialOrder` or
        `config.splineKnots` define the maximum order of x^j to fit.
        As k_0 and k_1 are degenerate with bias level and gain, they
        are not included in the non-linearity correction.
        """
        detector = camera[inputDims['detector']]
        if self.config.linearityType == 'LookupTable':
            table = np.zeros((len(detector), self.config.maxLookupTableAdu),
                             dtype=np.float32)
            tableIndex = 0
        else:
            table = None
            tableIndex = None  # This will fail if we increment it.

        if self.config.linearityType == 'Spline':
            fitOrder = self.config.splineKnots
        else:
            fitOrder = self.config.polynomialOrder

        # Initialize the linearizer.
        linearizer = Linearizer(detector=detector, table=table, log=self.log)

        for i, amp in enumerate(detector):
            ampName = amp.getName()
            if (len(inputPtc.expIdMask[ampName]) == 0):
                self.log.warn(
                    f"Mask not found for {ampName} in non-linearity fit. Using all points."
                )
                mask = np.repeat(True, len(inputPtc.expIdMask[ampName]))
            else:
                mask = inputPtc.expIdMask[ampName]

            inputAbscissa = np.array(inputPtc.rawExpTimes[ampName])[mask]
            inputOrdinate = np.array(inputPtc.rawMeans[ampName])[mask]

            # Determine proxy-to-linear-flux transformation
            fluxMask = inputOrdinate < self.config.maxLinearAdu
            lowMask = inputOrdinate > self.config.minLinearAdu
            fluxMask = fluxMask & lowMask
            linearAbscissa = inputAbscissa[fluxMask]
            linearOrdinate = inputOrdinate[fluxMask]

            linearFit, linearFitErr, chiSq, weights = irlsFit([0.0, 100.0],
                                                              linearAbscissa,
                                                              linearOrdinate,
                                                              funcPolynomial)
            # Convert this proxy-to-flux fit into an expected linear flux
            linearOrdinate = linearFit[0] + linearFit[1] * inputAbscissa

            # Exclude low end outliers
            threshold = self.config.nSigmaClipLinear * np.sqrt(linearOrdinate)
            fluxMask = np.abs(inputOrdinate - linearOrdinate) < threshold
            linearOrdinate = linearOrdinate[fluxMask]
            fitOrdinate = inputOrdinate[fluxMask]
            self.debugFit('linearFit', inputAbscissa, inputOrdinate,
                          linearOrdinate, fluxMask, ampName)
            # Do fits
            if self.config.linearityType in [
                    'Polynomial', 'Squared', 'LookupTable'
            ]:
                polyFit = np.zeros(fitOrder + 1)
                polyFit[1] = 1.0
                polyFit, polyFitErr, chiSq, weights = irlsFit(
                    polyFit, linearOrdinate, fitOrdinate, funcPolynomial)

                # Truncate the polynomial fit
                k1 = polyFit[1]
                linearityFit = [
                    -coeff / (k1**order) for order, coeff in enumerate(polyFit)
                ]
                significant = np.where(
                    np.abs(linearityFit) > 1e-10, True, False)
                self.log.info(f"Significant polynomial fits: {significant}")

                modelOrdinate = funcPolynomial(polyFit, linearAbscissa)
                self.debugFit('polyFit', linearAbscissa, fitOrdinate,
                              modelOrdinate, None, ampName)

                if self.config.linearityType == 'Squared':
                    linearityFit = [linearityFit[2]]
                elif self.config.linearityType == 'LookupTable':
                    # Use linear part to get time at wich signal is maxAduForLookupTableLinearizer DN
                    tMax = (self.config.maxLookupTableAdu -
                            polyFit[0]) / polyFit[1]
                    timeRange = np.linspace(0, tMax,
                                            self.config.maxLookupTableAdu)
                    signalIdeal = polyFit[0] + polyFit[1] * timeRange
                    signalUncorrected = funcPolynomial(polyFit, timeRange)
                    lookupTableRow = signalIdeal - signalUncorrected  # LinearizerLookupTable has correction

                    linearizer.tableData[tableIndex, :] = lookupTableRow
                    linearityFit = [tableIndex, 0]
                    tableIndex += 1
            elif self.config.linearityType in ['Spline']:
                # See discussion in `lsst.ip.isr.linearize.py` before modifying.
                numPerBin, binEdges = np.histogram(linearOrdinate,
                                                   bins=fitOrder)
                with np.errstate(invalid="ignore"):
                    # Algorithm note: With the counts of points per
                    # bin above, the next histogram calculates the
                    # values to put in each bin by weighting each
                    # point by the correction value.
                    values = np.histogram(
                        linearOrdinate,
                        bins=fitOrder,
                        weights=(inputOrdinate[fluxMask] -
                                 linearOrdinate))[0] / numPerBin

                    # After this is done, the binCenters are
                    # calculated by weighting by the value we're
                    # binning over.  This ensures that widely
                    # spaced/poorly sampled data aren't assigned to
                    # the midpoint of the bin (as could be done using
                    # the binEdges above), but to the weighted mean of
                    # the inputs.  Note that both histograms are
                    # scaled by the count per bin to normalize what
                    # the histogram returns (a sum of the points
                    # inside) into an average.
                    binCenters = np.histogram(
                        linearOrdinate, bins=fitOrder,
                        weights=linearOrdinate)[0] / numPerBin
                    values = values[numPerBin > 0]
                    binCenters = binCenters[numPerBin > 0]

                self.debugFit('splineFit', binCenters, np.abs(values), values,
                              None, ampName)
                interp = afwMath.makeInterpolate(
                    binCenters.tolist(), values.tolist(),
                    afwMath.stringToInterpStyle("AKIMA_SPLINE"))
                modelOrdinate = linearOrdinate + interp.interpolate(
                    linearOrdinate)
                self.debugFit('splineFit', linearOrdinate, fitOrdinate,
                              modelOrdinate, None, ampName)

                # If we exclude a lot of points, we may end up with
                # less than fitOrder points.  Pad out the low-flux end
                # to ensure equal lengths.
                if len(binCenters) != fitOrder:
                    padN = fitOrder - len(binCenters)
                    binCenters = np.pad(binCenters, (padN, 0),
                                        'linear_ramp',
                                        end_values=(binCenters.min() - 1.0, ))
                    # This stores the correction, which is zero at low values.
                    values = np.pad(values, (padN, 0))

                # Pack the spline into a single array.
                linearityFit = np.concatenate(
                    (binCenters.tolist(), values.tolist())).tolist()
                polyFit = [0.0]
                polyFitErr = [0.0]
                chiSq = np.nan
            else:
                polyFit = [0.0]
                polyFitErr = [0.0]
                chiSq = np.nan
                linearityFit = [0.0]

            linearizer.linearityType[ampName] = self.config.linearityType
            linearizer.linearityCoeffs[ampName] = np.array(linearityFit)
            linearizer.linearityBBox[ampName] = amp.getBBox()
            linearizer.fitParams[ampName] = np.array(polyFit)
            linearizer.fitParamsErr[ampName] = np.array(polyFitErr)
            linearizer.fitChiSq[ampName] = chiSq

            image = afwImage.ImageF(len(inputOrdinate), 1)
            image.getArray()[:, :] = inputOrdinate
            linearizeFunction = linearizer.getLinearityTypeByName(
                linearizer.linearityType[ampName])
            linearizeFunction()(image, **{
                'coeffs': linearizer.linearityCoeffs[ampName],
                'table': linearizer.tableData,
                'log': linearizer.log
            })
            linearizeModel = image.getArray()[0, :]

            self.debugFit('solution', inputOrdinate[fluxMask], linearOrdinate,
                          linearizeModel[fluxMask], None, ampName)

        linearizer.hasLinearity = True
        linearizer.validate()
        linearizer.updateMetadata(camera=camera,
                                  detector=detector,
                                  filterName='NONE')
        linearizer.updateMetadata(setDate=True, setCalibId=True)
        provenance = IsrProvenance(calibType='linearizer')

        return pipeBase.Struct(
            outputLinearizer=linearizer,
            outputProvenance=provenance,
        )
예제 #10
0
    def makeLinearizer(self, linearityType, bbox=None):
        """Construct a linearizer with the test coefficients.

        Parameters
        ----------
        linearityType : `str`
            Type of linearity to use.  The coefficients are set by the
            setUp method.
        bbox : `lsst.geom.Box2I`
            Bounding box for the full detector.  Used to assign
            amp-based bounding boxes.

        Returns
        -------
        linearizer : `lsst.ip.isr.Linearizer`
            A fully constructed, persistable linearizer.
        """
        bbox = bbox if bbox is not None else self.bbox
        numAmps = self.ampArrangement
        boxArr = BoxGrid(box=bbox, numColRow=numAmps)
        linearizer = Linearizer()
        linearizer.hasLinearity = True

        for i in range(numAmps[0]):
            for j in range(numAmps[1]):
                ampName = f"amp {i+1}_{j+1}"
                ampBox = boxArr[i, j]
                linearizer.ampNames.append(ampName)

                if linearityType == 'Squared':
                    linearizer.linearityCoeffs[ampName] = np.array(
                        [self.sqCoeffs[i, j]])
                elif linearityType == 'LookupTable':
                    linearizer.linearityCoeffs[ampName] = np.array(
                        self.lookupIndices[i, j])
                    linearizer.tableData = self.table
                elif linearityType == 'Polynomial':
                    linearizer.linearityCoeffs[ampName] = np.array(
                        self.polyCoeffs[i, j])
                elif linearityType == 'Spline':
                    linearizer.linearityCoeffs[ampName] = np.array(
                        self.splineCoeffs)

                linearizer.linearityType[ampName] = linearityType
                linearizer.linearityBBox[ampName] = ampBox
                linearizer.fitParams[ampName] = np.array([])
                linearizer.fitParamsErr[ampName] = np.array([])
                linearizer.fitChiSq[ampName] = np.nan
                linearizer.fitResiduals[ampName] = np.array([])
                linearizer.linearFit[ampName] = np.array([])

        return linearizer
예제 #11
0
    def testBasics(self):
        """Test basic linearization functionality.
        """
        for imageClass in (afwImage.ImageF, afwImage.ImageD):
            inImage = makeRampImage(bbox=self.bbox,
                                    start=-5,
                                    stop=2500,
                                    imageClass=imageClass)

            for linearityType in ('Squared', 'LookupTable', 'Polynomial',
                                  'Spline'):
                detector = self.makeDetector(linearityType)
                table = None
                inputData = {
                    'Squared': self.sqCoeffs,
                    'LookupTable': self.lookupIndices,
                    'Polynomial': self.polyCoeffs,
                    'Spline': self.splineCoeffs
                }[linearityType]
                if linearityType == 'LookupTable':
                    table = np.array(self.table,
                                     dtype=inImage.getArray().dtype)
                linearizer = Linearizer(detector=detector, table=table)

                measImage = inImage.Factory(inImage, True)
                result = linearizer.applyLinearity(measImage,
                                                   detector=detector,
                                                   log=self.log)
                refImage, refNumOutOfRange = referenceImage(
                    inImage.Factory(inImage, True), detector, linearityType,
                    inputData, table)

                # This is necessary for the same tests to be used on
                # all types.  The first amplifier has 0.0 for the
                # coefficient, which should be tested (it has a log
                # message), but we are not linearizing an amplifier
                # with no correction, so it fails the test that
                # numLinearized == numAmps.
                zeroLinearity = 1 if linearityType == 'Squared' else 0

                self.compareResults(measImage, result.numOutOfRange,
                                    result.numLinearized, result.numAmps,
                                    refImage, refNumOutOfRange,
                                    self.numAmps - zeroLinearity, self.numAmps)

                # Test a stand alone linearizer.  This ignores validate checks.
                measImage = inImage.Factory(inImage, True)
                storedLinearizer = self.makeLinearizer(linearityType)
                storedResult = storedLinearizer.applyLinearity(measImage,
                                                               log=self.log)

                self.compareResults(measImage, storedResult.numOutOfRange,
                                    storedResult.numLinearized,
                                    storedResult.numAmps, refImage,
                                    refNumOutOfRange,
                                    self.numAmps - zeroLinearity, self.numAmps)

                # "Save to yaml" and test again
                storedDict = storedLinearizer.toDict()
                storedLinearizer = Linearizer().fromDict(storedDict)

                measImage = inImage.Factory(inImage, True)
                storedLinearizer = self.makeLinearizer(linearityType)
                storedResult = storedLinearizer.applyLinearity(measImage,
                                                               log=self.log)

                self.compareResults(measImage, storedResult.numOutOfRange,
                                    storedResult.numLinearized,
                                    storedResult.numAmps, refImage,
                                    refNumOutOfRange,
                                    self.numAmps - zeroLinearity, self.numAmps)

                # "Save to fits" and test again
                storedTable = storedLinearizer.toTable()
                storedLinearizer = Linearizer().fromTable(storedTable)

                measImage = inImage.Factory(inImage, True)
                storedLinearizer = self.makeLinearizer(linearityType)
                storedResult = storedLinearizer.applyLinearity(measImage,
                                                               log=self.log)

                self.compareResults(measImage, storedResult.numOutOfRange,
                                    storedResult.numLinearized,
                                    storedResult.numAmps, refImage,
                                    refNumOutOfRange,
                                    self.numAmps - zeroLinearity, self.numAmps)