def test_PolyMapNoTransform(self):
        """Test constructing a PolyMap with neither forward nor inverse
        coefficients
        """
        coeff_f = np.array([], dtype=float)
        coeff_f.shape = (0, 4)
        coeff_i = np.array([], dtype=float)
        coeff_i.shape = (0, 3)

        with self.assertRaises(ValueError):
            ast.PolyMap(coeff_f, coeff_i)

        with self.assertRaises(ValueError):
            ast.PolyMap(coeff_f, 3)
    def test_PolyMapDM10496(self):
        """Test for a segfault when simplifying a SeriesMap

        We saw an intermittent segfault when simplifying a SeriesMap
        consisting of the inverse of PolyMap with 2 inputs and one output
        followed by its inverse (which should simplify to a UnitMap
        with one input and one output). David Berry fixed this bug in AST
        2017-05-10.

        I tried this test on an older version of astshim and found that it
        triggering a segfault nearly every time.
        """
        coeff_f = np.array([
            [-1.1, 1, 2, 0],
            [1.3, 1, 3, 1],
        ])
        coeff_i = np.array([
            [1.6, 1, 3],
            [-3.6, 2, 1],
        ])

        # execute many times to increase the odds of a segfault
        for i in range(1000):
            amap = ast.PolyMap(coeff_f, coeff_i)
            amapinv = amap.getInverse()
            cmp2 = amapinv.then(amap)
            result = cmp2.simplify()
            self.assertIsInstance(result, ast.UnitMap)
Example #3
0
    def test_error_handling(self):
        """Test handling of AST errors
        """
        # To introduce an AST error construct a PolyMap with no inverse mapping
        # and then try to transform in the inverse direction.
        coeff_f = np.array([
            [1.2, 1, 2, 0],
            [-0.5, 1, 1, 1],
            [1.0, 2, 0, 1],
        ])
        pm = ast.PolyMap(coeff_f, 2, "IterInverse=0")
        indata = np.array([
            [1.0, 2.0, 3.0],
            [0.0, 1.0, 2.0],
        ])

        # make sure the error string contains "Error"
        try:
            pm.applyInverse(indata)
        except RuntimeError as e:
            self.assertEqual(e.args[0].count("Error"), 1)
            print(e)

        # cause another error and make sure the first error message was purged
        try:
            pm.applyInverse(indata)
        except RuntimeError as e:
            self.assertEqual(e.args[0].count("Error"), 1)
    def test_PolyMapPolyMapUnivertible(self):
        """Test polyTran on a PolyMap without a single-valued inverse

        The equation is y = x^2 - x^3, whose inverse has 3 values
        between roughly -0.66 and 2.0
        """
        coeff_f = np.array([
            [2.0, 1, 2],
            [-1.0, 1, 3],
        ])
        pm = ast.PolyMap(coeff_f, 1, "IterInverse=1")

        self.checkBasicSimplify(pm)
        self.checkCopy(pm)

        indata = np.array([-0.5, 0.5, 1.1, 1.8])
        pred_outdata = (2.0 * indata.T**2 - indata.T**3).T
        outdata = pm.applyForward(indata)
        npt.assert_allclose(outdata, pred_outdata)

        # the iterative inverse should give valid values
        indata_iterative = pm.applyInverse(outdata)
        outdata_roundtrip = pm.applyForward(indata_iterative)
        npt.assert_allclose(outdata, outdata_roundtrip)

        self.checkMappingPersistence(pm, indata)

        with self.assertRaises(RuntimeError):
            # includes the range where the inverse has multiple values,
            # so no inverse is possible
            pm.polyTran(False, 1e-3, 1e-3, 10, [-1.0], [2.5])
def makeHscDistortion(config):
    """Make an HSC distortion transform

    Note that inverse coefficients provided, but they are not accurate enough
    to use: test_distortion.py reports an error of 2.8 pixels
    (HSC uses pixels for its focal plane units) when transforming
    from pupil to focal plane. That explains why the original HSC model uses
    the inverse coefficients in conjunction with iteration.

    Parameters
    ----------
    config: `lsst.obs.subaru.HscDistortionConfig`
        Distortion coefficients

    Returns
    -------
    focalPlaneToPupil: `lsst.afw.geom.TransformPoint2ToPoint2`
        Transform from focal plane to field angle coordinates
    """
    forwardCoeffs = makeAstPolyMapCoeffs(config.ccdToSkyOrder, config.xCcdToSky, config.yCcdToSky)

    # Note that the actual error can be somewhat larger than TolInverse;
    # the max error I have seen is less than 2, so I scale conservatively
    ccdToSky = ast.PolyMap(forwardCoeffs, 2, "IterInverse=1, TolInverse=%s, NIterInverse=%s" %
                           (config.tolerance / 2.0, config.maxIter))
    plateScaleAngle = config.plateScale * arcseconds
    fullMapping = ccdToSky.then(ast.ZoomMap(2, plateScaleAngle.asRadians()))
    return TransformPoint2ToPoint2(fullMapping)
    def test_PolyMapPolyTran(self):
        coeff_f = np.array([[1., 1, 1, 0], [1., 1, 0, 1], [1., 2, 1, 0],
                            [-1., 2, 0, 1]])
        coeff_i = np.array([
            [0.5, 1, 1, 0],
            [0.5, 1, 0, 1],
            [0.5, 2, 1, 0],
            [-0.5, 2, 0, 1],
        ])
        pm = ast.PolyMap(coeff_f, coeff_i)

        indata = np.array([
            [1.0, 2.0, 3.0],
            [0.0, 1.0, 2.0],
        ])

        outdata = pm.applyForward(indata)

        # create a PolyMap with an identical forward transform and a fit inverse
        forward = False
        pm2 = pm.polyTran(forward, 1.0E-10, 1.0E-10, 4, [-1.0, -1.0],
                          [1.0, 1.0])
        outdata2 = pm2.applyForward(indata)
        npt.assert_equal(outdata, outdata2)
        indata2 = pm2.applyInverse(outdata)
        npt.assert_allclose(indata, indata2, atol=1.0e-10)

        self.checkMappingPersistence(pm, indata)
        self.checkMappingPersistence(pm2, indata)
    def test_polyMapAttributes(self):
        coeff_f = np.array([
            [1.2, 1, 2, 0],
            [-0.5, 1, 1, 1],
            [1.0, 2, 0, 1],
        ])
        pm = ast.PolyMap(coeff_f, 2,
                         "IterInverse=1, NIterInverse=6, TolInverse=1.2e-7")
        self.assertIsInstance(pm, ast.Object)
        self.assertIsInstance(pm, ast.Mapping)
        self.assertIsInstance(pm, ast.PolyMap)
        self.assertEqual(pm.nIn, 2)
        self.assertEqual(pm.nOut, 2)
        self.assertTrue(pm.iterInverse)
        self.assertEqual(pm.nIterInverse, 6)
        self.assertAlmostEqual(pm.tolInverse, 1.2E-7)
        self.assertTrue(pm.hasForward)
        self.assertTrue(pm.hasInverse)

        indata = np.array([
            [1.0, 2.0, 3.0],
            [0.0, 1.0, 2.0],
        ])
        outdata = pm.applyForward(indata)
        xin, yin = indata
        pred_xout = (1.2 * xin * xin) - (0.5 * yin * xin)
        pred_yout = yin
        xout, yout = outdata
        npt.assert_allclose(xout, pred_xout)
        npt.assert_allclose(yout, pred_yout)

        indata_roundtrip = pm.applyInverse(outdata)
        npt.assert_allclose(indata, indata_roundtrip, atol=1.0e-6)

        self.checkMappingPersistence(pm, indata)
 def test_QuadApprox(self):
     # simple parabola
     coeff_f = np.array([
         [0.5, 1, 2, 0],
         [0.5, 1, 0, 2],
     ], dtype=float)
     polymap = ast.PolyMap(coeff_f, 1)
     qa = ast.QuadApprox(polymap, [-1, -1], [1, 1], 3, 3)
     self.assertAlmostEqual(qa.rms, 0)
     self.assertEqual(len(qa.fit), 6)
     assert_allclose(qa.fit, [0, 0, 0, 0, 0.5, 0.5])
Example #9
0
    def test_PolyMapIterInverseDominates(self):
        """Test that IterInverse dominates inverse coefficients for applyInverse
        """
        coeff_f = np.array([
            [1., 1, 1],
        ])
        # these coefficients don't match coeff_f, in that the inverse mapping
        # does not undo the forward mapping (as proven below)
        coeff_i = np.array([
            [25., 1, 2],
        ])
        polyMap = ast.PolyMap(coeff_f, coeff_i, "IterInverse=1")

        indata = np.array([-0.5, 0.5, 1.1, 1.8])
        outdata = polyMap.applyForward(indata)
        indata_roundtrip = polyMap.applyInverse(outdata)
        npt.assert_allclose(indata, indata_roundtrip)

        # prove that without the iterative inverse the PolyMap does not invert correctly
        polyMap2 = ast.PolyMap(coeff_f, coeff_i)
        indata_roundtrip2 = polyMap2.applyInverse(outdata)
        self.assertFalse(np.allclose(indata, indata_roundtrip2))
Example #10
0
    def test_PolyMapPolyTranIterInverse(self):
        """Test PolyTran on a PolyMap that has an iterative inverse

        The result should use the fit inverse, not the iterative inverse
        """
        coeff_f = np.array([
            [1., 1, 1],
        ])
        for polyMap in (
                ast.PolyMap(coeff_f, 1, "IterInverse=1"),
                ast.PolyMap(coeff_f, coeff_f, "IterInverse=1"),
        ):
            # make sure IterInverse is True and set
            self.assertTrue(polyMap.iterInverse)
            self.assertTrue(polyMap.test("IterInverse"))

            # fit inverse; this should clear iterInverse
            polyMapFitInv = polyMap.polyTran(False, 1.0E-10, 1.0E-10, 4,
                                             [-1.0], [1.0])
            self.assertFalse(polyMapFitInv.iterInverse)
            self.assertFalse(polyMapFitInv.test("IterInverse"))

            # Fit forward direction of inverted mapping; this should also
            # clear IterInverse.
            polyMapInvFitFwd = polyMap.inverted().polyTran(
                True, 1.0E-10, 1.0E-10, 4, [-1.0], [1.0])
            self.assertFalse(polyMapInvFitFwd.iterInverse)
            self.assertFalse(polyMapFitInv.test("IterInverse"))

            # cannot fit forward because inverse is iterative
            with self.assertRaises(ValueError):
                polyMap.polyTran(True, 1.0E-10, 1.0E-10, 4, [-1.0], [1.0])

            # Cannot fit inverse of inverted mapping because forward is
            # iterative.
            with self.assertRaises(ValueError):
                polyMap.inverted().polyTran(False, 1.0E-10, 1.0E-10, 4, [-1.0],
                                            [1.0])
Example #11
0
    def test_MakeRadialMappingForward(self):
        """Test a radial_map mapping that only has a forward transform
        """
        coeff_f = np.array([
            [5.0, 1, 1],
            [-0.12, 1, 2],
        ])
        mapping1d = ast.PolyMap(coeff_f, 1)
        self.assertTrue(mapping1d.hasForward)
        self.assertFalse(mapping1d.hasInverse)

        # If center = [0.0] then the radial_map mapping is identical to
        # mapping1d.
        radial_map = ast.makeRadialMapping([0], mapping1d)
        self.assertTrue(radial_map.hasForward)
        self.assertFalse(radial_map.hasInverse)
        in_data1 = self.in_data_full[0]
        npt.assert_allclose(radial_map.applyForward(in_data1),
                            mapping1d.applyForward(in_data1))

        for center in (
            [0.0],
            [1.1],
            [0.0, 0.0],
            [-5.5, 4.7],
            [0.0, 0.0, 0.0],
            [1.1, 2.2, -3.3],
        ):
            naxes = len(center)
            center_reshaped = np.expand_dims(center, 1)
            in_data = self.in_data_full[0:naxes]

            radial_map = ast.makeRadialMapping(center, mapping1d)
            self.assertTrue(radial_map.hasForward)
            self.assertFalse(radial_map.hasInverse)

            # compute desired output
            in_from_center = in_data - center_reshaped
            in_norm = np.linalg.norm(in_from_center, axis=0)
            with np.errstate(invalid='ignore'):
                unit_vector = np.where(in_norm != 0, in_from_center / in_norm,
                                       in_from_center)
            out_norm = mapping1d.applyForward(in_norm)
            out_from_center = unit_vector * out_norm
            desired_out_data = out_from_center + center_reshaped

            out_data = radial_map.applyForward(in_data)
            npt.assert_allclose(out_data, desired_out_data)
    def setUp(self):
        # Make fake sources
        self.nSources = 10
        self.bbox = geom.Box2I(geom.Point2I(0, 0),
                               geom.Extent2I(1024, 1153))
        self.xyLoc = 100
        dataset = measTests.TestDataset(self.bbox)
        for srcIdx in range(self.nSources):
            dataset.addSource(100000.0,
                              geom.Point2D(srcIdx*self.xyLoc,
                                           srcIdx*self.xyLoc))
        schema = dataset.makeMinimalSchema()
        schema.addField("base_PixelFlags_flag", type="Flag")
        schema.addField("base_PixelFlags_flag_offimage", type="Flag")
        self.exposure, catalog = dataset.realize(
            10.0, schema, randomSeed=1234)
        for src in catalog:
            src.setCoord(self.exposure.getWcs().pixelToSky(src.getCentroid()))
        # Non-invertible WCS to test robustness to distortions.
        # Coefficients transform (x - 1e-7*x^3 -> x, y -> y); see docs for PolyMap.
        pixelCoeffs = np.array([[-1.0e-7, 1, 3, 0],
                                [1.0, 1, 1, 0],
                                [1.0, 2, 0, 1],
                                ])
        self.exposure.setWcs(afwGeom.makeModifiedWcs(
            afwGeom.TransformPoint2ToPoint2(ast.PolyMap(pixelCoeffs, 2, options="IterInverse=1")),
            self.exposure.wcs,
            modifyActualPixels=False
        ))

        # Convert to task required format
        self.testDiaSources = catalog.asAstropy().to_pandas()
        self.testDiaSources.rename(columns={"coord_ra": "ra",
                                            "coord_dec": "decl"},
                                   inplace=True,)
        self.testDiaSources.loc[:, "ra"] = np.rad2deg(self.testDiaSources["ra"])
        self.testDiaSources.loc[:, "decl"] = np.rad2deg(self.testDiaSources["decl"])
        self.testDiaSources["ssObjectId"] = 0

        # Grab a subset to treat as solar system objects
        self.testSsObjects = self.testDiaSources[2:8].reset_index()
        # Assign them ids starting from 1.
        self.testSsObjects.loc[:, "ssObjectId"] = np.arange(
            1, len(self.testSsObjects) + 1, dtype=int,)
        self.testSsObjects["Err(arcsec)"] = np.ones(len(self.testSsObjects))
Example #13
0
    def test_PolyMapEmptyInverseCoeffs(self):
        """Test constructing a PolyMap with empty inverse coefficients
        """
        coeff_f = np.array([[1., 1, 1, 0], [1., 1, 0, 1], [1., 2, 1, 0],
                            [-1., 2, 0, 1]])
        coeff_i = np.array([], dtype=float)
        coeff_i.shape = (0, 4)
        pm = astshim.PolyMap(coeff_f, coeff_i)
        self.assertEqual(pm.nIn, 2)
        self.assertEqual(pm.nOut, 2)

        self.checkBasicSimplify(pm)
        self.checkCopy(pm)
        self.checkPersistence(pm)

        self.assertTrue(pm.hasForward)
        self.assertFalse(pm.hasInverse)
        self.assertFalse(pm.iterInverse)
Example #14
0
    def test_PolyMapEmptyForwardCoeffs(self):
        """Test constructing a PolyMap with empty forward coefficients
        """
        coeff_f = np.array([], dtype=float)
        coeff_f.shape = (0, 4)
        coeff_i = np.array([
            [0.5, 1, 1, 0],
            [0.5, 1, 0, 1],
            [0.5, 2, 1, 0],
            [-0.5, 2, 0, 1],
        ])
        pm = ast.PolyMap(coeff_f, coeff_i)
        self.assertEqual(pm.nIn, 2)
        self.assertEqual(pm.nOut, 2)

        self.checkBasicSimplify(pm)
        self.checkCopy(pm)

        self.assertFalse(pm.hasForward)
        self.assertTrue(pm.hasInverse)
        self.assertFalse(pm.iterInverse)
Example #15
0
def makeSipIwcToPixel(metadata):
    """Make an IWC to pixel transform with SIP distortion from FITS-WCS metadata

    This function is primarily intended for unit tests.
    IWC is intermediate world coordinates, as described in the FITS papers.

    Parameters
    ----------
    metadata : lsst.daf.base.PropertySet
        FITS metadata describing a WCS with inverse SIP coefficients

    Returns
    -------
    lsst.afw.geom.TransformPoint2ToPoint2
        Transform from IWC position to pixel position (zero-based)
        in the forward direction. The inverse direction is not defined.

    Notes
    -----

    The inverse SIP terms APn_m, BPn_m are polynomial coefficients x^n y^m
    for computing transformed x, y respectively. If we call the resulting
    polynomial inverseSipPolynomial, the returned transformation is:

        pixelPosition = pixel origin + uv + inverseSipPolynomial(uv)
        where uv = inverseCdMatrix * iwcPosition
    """
    crpix = (metadata.getScalar("CRPIX1") - 1,
             metadata.getScalar("CRPIX2") - 1)
    pixelRelativeToAbsoluteMap = ast.ShiftMap(crpix)
    cdMatrix = getCdMatrixFromMetadata(metadata)
    cdMatrixMap = ast.MatrixMap(cdMatrix.copy())
    coeffList = makeSipPolyMapCoeffs(metadata, "AP") + makeSipPolyMapCoeffs(
        metadata, "BP")
    coeffArr = np.array(coeffList, dtype=float)
    sipPolyMap = ast.PolyMap(coeffArr, 2, "IterInverse=0")

    iwcToPixelMap = cdMatrixMap.inverted().then(sipPolyMap).then(
        pixelRelativeToAbsoluteMap)
    return afwGeom.TransformPoint2ToPoint2(iwcToPixelMap)
    def setUp(self):
        self.longMessage = True

        # an arbitrary bounding box (not that this kind of field cares)
        self.bbox = lsst.afw.geom.Box2I(lsst.afw.geom.Point2I(-3, 4),
                                        lsst.afw.geom.Extent2I(5, 30))

        # a list of points contained in the bbox
        self.pointList = lsst.afw.geom.Box2D(self.bbox).getCorners()
        self.pointList.append(lsst.afw.geom.Box2D(self.bbox).getCenter())
        self.xList = np.array([p[0] for p in self.pointList])
        self.yList = np.array([p[1] for p in self.pointList])

        # a simple polynomial mapping
        coeff_f = np.array([
            [1.5, 1, 0, 0],
            [-0.5, 1, 1, 0],
            [1.0, 1, 0, 1],
        ])
        polyMap = astshim.PolyMap(coeff_f, 1)
        self.transform = lsst.afw.geom.TransformPoint2ToGeneric(polyMap)
        self.boundedField = TransformBoundedField(self.bbox, self.transform)
Example #17
0
    def test_PolyMapIterativeInverse(self):
        """Test a unidirectional polymap with its default iterative inverse
        """
        coeff_f = np.array([
            [1.2, 1, 2, 0],
            [-0.5, 1, 1, 1],
            [1.0, 2, 0, 1],
        ])
        pm = ast.PolyMap(coeff_f, 2, "IterInverse=1")
        self.assertIsInstance(pm, ast.Object)
        self.assertIsInstance(pm, ast.Mapping)
        self.assertIsInstance(pm, ast.PolyMap)
        self.assertEqual(pm.nIn, 2)
        self.assertEqual(pm.nOut, 2)
        self.assertTrue(pm.iterInverse)
        self.assertEqual(pm.nIterInverse, 4)
        self.assertAlmostEqual(pm.tolInverse, 1.0E-6)
        self.assertTrue(pm.hasForward)
        self.assertTrue(pm.hasInverse)

        self.checkBasicSimplify(pm)
        self.checkCopy(pm)

        indata = np.array([
            [1.0, 2.0, 3.0],
            [0.0, 1.0, 2.0],
        ])
        outdata = pm.applyForward(indata)
        xin, yin = indata
        pred_xout = (1.2 * xin * xin) - (0.5 * yin * xin)
        pred_yout = yin
        xout, yout = outdata
        npt.assert_allclose(xout, pred_xout)
        npt.assert_allclose(yout, pred_yout)

        indata_roundtrip = pm.applyInverse(outdata)
        npt.assert_allclose(indata, indata_roundtrip, atol=1.0e-4)

        self.checkMappingPersistence(pm, indata)
Example #18
0
    def test_PolyMapPolyTranNontrivial(self):
        """Test PolyMap.polyTran on a non-trivial case
        """
        # Approximate "field angle to focal plane" transformation coefficients
        # for LSST thus the domain of the forward direction is
        # 1.75 degrees = 0.0305 radians.
        # The camera has 10 um pixels = 0.01 mm
        # The desired accuracy of the inverse transformation is
        # 0.001 pixels = 1e-5 mm = 9.69e-10 radians.
        plateScaleRad = 9.69627362219072e-05  # radians per mm
        radialCoeff = np.array([0.0, 1.0, 0.0, 0.925]) / plateScaleRad
        polyCoeffs = []
        for i, coeff in enumerate(radialCoeff):
            polyCoeffs.append((coeff, 1, i))
        polyCoeffs = np.array(polyCoeffs)
        fieldAngleToFocalPlane = ast.PolyMap(polyCoeffs, 1)

        atolRad = 1.0e-9
        fieldAngleToFocalPlane2 = fieldAngleToFocalPlane.polyTran(
            forward=False,
            acc=atolRad,
            maxacc=atolRad,
            maxorder=10,
            lbnd=[0],
            ubnd=[0.0305])
        fieldAngle = np.linspace(0, 0.0305, 100)
        focalPlane = fieldAngleToFocalPlane.applyForward(fieldAngle)
        fieldAngleRoundTrip = fieldAngleToFocalPlane2.applyInverse(focalPlane)
        npt.assert_allclose(fieldAngle, fieldAngleRoundTrip, atol=atolRad)

        # Verify that polyTran cannot fit the inverse when maxorder is
        # too small.
        with self.assertRaises(RuntimeError):
            fieldAngleToFocalPlane.polyTran(forward=False,
                                            acc=atolRad,
                                            maxacc=atolRad,
                                            maxorder=3,
                                            lbnd=[0],
                                            ubnd=[0.0305])
Example #19
0
def makeSipPixelToIwc(metadata):
    """Make a pixel to IWC transform with SIP distortion from FITS-WCS metadata

    This function is primarily intended for unit tests.
    IWC is intermediate world coordinates, as described in the FITS papers.

    Parameters
    ----------
    metadata : lsst.daf.base.PropertySet
        FITS metadata describing a WCS with forward SIP coefficients

    Returns
    -------
    lsst.afw.geom.TransformPoint2ToPoint2
        Transform from pixel position (zero-based) to IWC position
        in the forward direction. The inverse direction is not defined.

    Notes
    -----

    The forward SIP terms An_m, Bn_m are polynomial coefficients x^n y^m
    for computing transformed x, y respectively. If we call the resulting
    polynomial sipPolynomial, the returned transformation is:

        iwcPosition = cdMatrix * (dxy + sipPolynomial(dxy))
        where dxy = pixelPosition - pixelOrigin
    """
    crpix = (metadata.get("CRPIX1") - 1, metadata.get("CRPIX2") - 1)
    pixelAbsoluteToRelativeMap = ast.ShiftMap(crpix).getInverse()
    cdMatrix = getCdMatrixFromMetadata(metadata)
    cdMatrixMap = ast.MatrixMap(cdMatrix.copy())
    coeffList = makeSipPolyMapCoeffs(metadata, "A") + makeSipPolyMapCoeffs(
        metadata, "B")
    coeffArr = np.array(coeffList, dtype=float)
    sipPolyMap = ast.PolyMap(coeffArr, 2, "IterInverse=0")
    pixelToIwcMap = pixelAbsoluteToRelativeMap.then(sipPolyMap).then(
        cdMatrixMap)
    return afwGeom.TransformPoint2ToPoint2(pixelToIwcMap)
Example #20
0
    def test_polyMapNoInverse(self):
        """Test a unidirectional polymap with no numeric inverse
        """
        coeff_f = np.array([
            [1.2, 1, 2, 0],
            [-0.5, 1, 1, 1],
            [1.0, 2, 0, 1],
        ])
        pm = ast.PolyMap(coeff_f, 2)
        self.assertIsInstance(pm, ast.PolyMap)
        self.assertEqual(pm.nIn, 2)
        self.assertEqual(pm.nOut, 2)
        self.assertTrue(pm.hasForward)
        self.assertFalse(pm.hasInverse)
        self.assertFalse(pm.iterInverse)

        indata = np.array([
            [1.0, 2.0, 3.0],
            [0.0, 1.0, 2.0],
        ])
        outdata = pm.applyForward(indata)
        with self.assertRaises(RuntimeError):
            pm.applyInverse(indata)

        pminv = pm.getInverse()
        self.assertFalse(pminv.hasForward)
        self.assertTrue(pminv.hasInverse)
        self.assertTrue(pminv.isInverted)
        self.assertFalse(pm.iterInverse)

        outdata2 = pminv.applyInverse(indata)
        # outdata and outdata2 should be identical because inverting
        # swaps the behavior of applyForward and applyInverse
        npt.assert_equal(outdata, outdata2)
        with self.assertRaises(RuntimeError):
            pminv.applyForward(indata)

        self.checkMappingPersistence(pm, indata)
Example #21
0
    def test_PolyMapBidirectional(self):
        coeff_f = np.array([[1., 1, 1, 0], [1., 1, 0, 1], [1., 2, 1, 0],
                            [-1., 2, 0, 1]])
        coeff_i = np.array([
            [0.5, 1, 1, 0],
            [0.5, 1, 0, 1],
            [0.5, 2, 1, 0],
            [-0.5, 2, 0, 1],
        ])
        pm = ast.PolyMap(coeff_f, coeff_i)
        self.assertEqual(pm.nIn, 2)
        self.assertEqual(pm.nOut, 2)

        self.checkBasicSimplify(pm)
        self.checkCopy(pm)

        indata = np.array([
            [1.0, 2.0, 3.0],
            [0.0, 1.0, 2.0],
        ])

        self.checkRoundTrip(pm, indata)
        self.checkMappingPersistence(pm, indata)
Example #22
0
    def testComplexPersistence(self):
        """Test persistence of a TransformBoundedField whose string representation is huge
        """
        # DM-11964 shows that CFITSIO cannot handle string fields
        # in binary tables that have more than 28799 characters
        # make sure the test has plenty of margin
        minChars = 10 * 28799
        degree = 100  # make large enough that len(transform.writeString()) > minChars
        n_coeffs = (degree + 1) * (degree + 2) // 2
        coeffs = np.zeros((n_coeffs, 4), dtype=float)
        k = 0
        for j in range(degree + 1):
            for i in range(degree - j + 1):
                coeffs[k][0] = np.random.random()
                coeffs[k][1] = 1
                coeffs[k][2] = i
                coeffs[k][3] = j
                k += 1
        chebyMap = astshim.PolyMap(coeffs, 1)
        transform = lsst.afw.geom.TransformPoint2ToGeneric(chebyMap)
        print("nchar=%s; minChar=%s" %
              (len(transform.writeString()), minChars))
        self.assertGreater(len(transform.writeString()), minChars)
        complexBoundedField = TransformBoundedField(self.bbox, transform)
        with lsst.utils.tests.getTempFilePath(".fits") as filename:
            complexBoundedField.writeFits(filename)
            readField = TransformBoundedField.readFits(filename)

        self.assertTrue(complexBoundedField == readField)
        self.assertFalse(complexBoundedField != readField)
        self.assertEqual(complexBoundedField, readField)

        resArr = complexBoundedField.evaluate(self.xList, self.yList)
        readResArr = readField.evaluate(self.xList, self.yList)
        assert_allclose(resArr, readResArr)
        self.assertEqual(readField.getBBox(), self.bbox)