コード例 #1
0
 def testFromGrid(self):
     outOrder = 8
     inOrder = 2
     toInvert = makeRandomScaledPolynomialTransform(inOrder)
     bbox = lsst.afw.geom.Box2D(lsst.afw.geom.Point2D(432, -671), lsst.afw.geom.Point2D(527, -463))
     fitter = ScaledPolynomialTransformFitter.fromGrid(outOrder, bbox, 50, 50, toInvert)
     fitter.fit(outOrder)
     fitter.updateModel()
     data = fitter.getData()
     result = fitter.getTransform()
     inputKey = lsst.afw.table.Point2DKey(data.schema["input"])
     outputKey = lsst.afw.table.Point2DKey(data.schema["output"])
     for record in data:
         self.assertFloatsAlmostEqual(np.array(record.get(inputKey)),
                                      np.array(toInvert(record.get(outputKey))))
         self.assertFloatsAlmostEqual(np.array(result(record.get(inputKey))),
                                      np.array(record.get(outputKey)),
                                      rtol=1E-2)  # even at much higher order, inverse can't be perfect.
コード例 #2
0
 def testFromGrid(self):
     outOrder = 8
     inOrder = 2
     toInvert = makeRandomScaledPolynomialTransform(inOrder)
     bbox = lsst.geom.Box2D(lsst.geom.Point2D(432, -671), lsst.geom.Point2D(527, -463))
     fitter = ScaledPolynomialTransformFitter.fromGrid(outOrder, bbox, 50, 50, toInvert)
     fitter.fit(outOrder)
     fitter.updateModel()
     data = fitter.getData()
     result = fitter.getTransform()
     inputKey = lsst.afw.table.Point2DKey(data.schema["input"])
     outputKey = lsst.afw.table.Point2DKey(data.schema["output"])
     for record in data:
         self.assertFloatsAlmostEqual(np.array(record.get(inputKey)),
                                      np.array(toInvert(record.get(outputKey))))
         self.assertFloatsAlmostEqual(np.array(result(record.get(inputKey))),
                                      np.array(record.get(outputKey)),
                                      rtol=1E-2)  # even at much higher order, inverse can't be perfect.
コード例 #3
0
 def testFromMatches(self):
     # Setup artifical matches that correspond to a known (random) PolynomialTransform.
     order = 3
     truePoly = makeRandomPolynomialTransform(order)
     crval = lsst.afw.coord.IcrsCoord(lsst.afw.geom.Point2D(35.0, 10.0),
                                      lsst.afw.geom.degrees)
     crpix = lsst.afw.geom.Point2D(50, 50)
     cd = lsst.afw.geom.LinearTransform.makeScaling(
         (0.2 * lsst.afw.geom.arcseconds).asDegrees())
     initialWcs = lsst.afw.image.makeWcs(crval, crpix, cd[cd.XX], cd[cd.XY],
                                         cd[cd.YX], cd[cd.YY])
     bbox = lsst.afw.geom.Box2D(
         (lsst.afw.geom.Point2D(crval.getPosition(lsst.afw.geom.arcseconds))
          - lsst.afw.geom.Extent2D(20, 20)),
         (lsst.afw.geom.Point2D(crval.getPosition(lsst.afw.geom.arcseconds))
          + lsst.afw.geom.Extent2D(20, 20)))
     srcSchema = lsst.afw.table.SourceTable.makeMinimalSchema()
     srcPosKey = lsst.afw.table.Point2DKey.addFields(
         srcSchema, "pos", "source position", "pix")
     srcErrKey = lsst.afw.table.CovarianceMatrix2fKey.addFields(
         srcSchema, "pos", ["x", "y"], ["pix", "pix"])
     srcSchema.getAliasMap().set("slot_Centroid", "pos")
     nPoints = 10
     trueSrc = lsst.afw.table.SourceCatalog(srcSchema)
     trueSrc.reserve(nPoints)
     measSrc = lsst.afw.table.SourceCatalog(srcSchema)
     measSrc.reserve(nPoints)
     ref = lsst.afw.table.SimpleCatalog(
         lsst.afw.table.SimpleTable.makeMinimalSchema())
     ref.reserve(nPoints)
     refCoordKey = ref.getCoordKey()
     errScaling = 1E-14
     matches = []
     for i in range(nPoints):
         refRec = ref.addNew()
         skyPos = lsst.afw.geom.Point2D(
             np.random.uniform(low=bbox.getMinX(), high=bbox.getMaxX()),
             np.random.uniform(low=bbox.getMinY(), high=bbox.getMaxY()))
         skyCoord = lsst.afw.coord.IcrsCoord(skyPos,
                                             lsst.afw.geom.arcseconds)
         refRec.set(refCoordKey, skyCoord)
         trueRec = trueSrc.addNew()
         truePos = truePoly(
             initialWcs.skyToIntermediateWorldCoord(skyCoord))
         trueRec.set(srcPosKey, truePos)
         measRec = measSrc.addNew()
         covSqrt = np.random.randn(3, 2)
         cov = (errScaling * (np.dot(covSqrt.transpose(), covSqrt) +
                              np.diag([1.0, 1.0]))).astype(np.float32)
         # We don't actually perturb positions according to noise level, as
         # this makes it much harder to test that the result agrees with
         # what we put in.
         measPos = truePos
         measRec.set(srcPosKey, measPos)
         measRec.set(srcErrKey, cov)
         match = lsst.afw.table.ReferenceMatch(
             refRec, measRec, (measPos - truePos).computeNorm())
         matches.append(match)
     # Construct a fitter, and verify that the internal catalog it constructs is what we expect.
     fitter = ScaledPolynomialTransformFitter.fromMatches(
         order, matches, initialWcs, 0.0)
     expected = lsst.meas.astrom.compose(
         fitter.getOutputScaling(),
         lsst.meas.astrom.compose(truePoly,
                                  fitter.getInputScaling().invert()))
     data = fitter.getData()
     dataOutKey = lsst.afw.table.Point2DKey(data.schema["src"])
     dataInKey = lsst.afw.table.Point2DKey(data.schema["intermediate"])
     dataErrKey = lsst.afw.table.CovarianceMatrix2fKey(
         data.schema["src"], ["x", "y"])
     scaledInBBox = lsst.afw.geom.Box2D()
     scaledOutBBox = lsst.afw.geom.Box2D()
     vandermonde = np.zeros((nPoints, (order + 1) * (order + 2) // 2),
                            dtype=float)
     for i, (match, dataRec,
             trueRec) in enumerate(zip(matches, data, trueSrc)):
         self.assertEqual(match.second.getX(), dataRec.get("src_x"))
         self.assertEqual(match.second.getY(), dataRec.get("src_y"))
         self.assertEqual(match.first.getId(), dataRec.get("ref_id"))
         self.assertEqual(match.second.getId(), dataRec.get("src_id"))
         refPos = initialWcs.skyToIntermediateWorldCoord(
             match.first.getCoord())
         self.assertEqual(refPos.getX(), dataRec.get("intermediate_x"))
         self.assertEqual(refPos.getY(), dataRec.get("intermediate_y"))
         self.assertFloatsAlmostEqual(match.second.get(srcErrKey),
                                      dataRec.get(dataErrKey),
                                      rtol=1E-7)
         scaledIn = fitter.getInputScaling()(dataRec.get(dataInKey))
         scaledOut = fitter.getOutputScaling()(dataRec.get(dataOutKey))
         scaledInBBox.include(scaledIn)
         scaledOutBBox.include(scaledOut)
         self.assertFloatsAlmostEqual(np.array(expected(scaledIn)),
                                      np.array(scaledOut),
                                      rtol=1E-7)
         j = 0
         for n in range(order + 1):
             for p in range(n + 1):
                 q = n - p
                 vandermonde[i, j] = scaledIn.getX()**p * scaledIn.getY()**q
                 j += 1
     # Verify that scaling transforms move inputs and outputs into [-1, 1]
     self.assertFloatsAlmostEqual(scaledInBBox.getMinX(), -1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledInBBox.getMinY(), -1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledInBBox.getMaxX(), 1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledInBBox.getMaxY(), 1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledOutBBox.getMinX(), -1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledOutBBox.getMinY(), -1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledOutBBox.getMaxX(), 1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledOutBBox.getMaxY(), 1.0, rtol=1E-12)
     # Run the fitter, and check that we get out approximately what we put in.
     fitter.fit(order)
     fitter.updateModel()
     # Check the transformed input points.
     self.assertFloatsAlmostEqual(data.get("model_x"),
                                  trueSrc.getX(),
                                  rtol=1E-15)
     self.assertFloatsAlmostEqual(data.get("model_y"),
                                  trueSrc.getY(),
                                  rtol=1E-15)
     # Check the actual transform's coefficients (after composing in the scaling, which is
     # a lot of the reason we lose a lot of precision here).
     fittedPoly = lsst.meas.astrom.PolynomialTransform.convert(
         fitter.getTransform())
     self.assertFloatsAlmostEqual(fittedPoly.getXCoeffs(),
                                  truePoly.getXCoeffs(),
                                  rtol=1E-5,
                                  atol=1E-5)
     self.assertFloatsAlmostEqual(fittedPoly.getYCoeffs(),
                                  truePoly.getYCoeffs(),
                                  rtol=1E-5,
                                  atol=1E-5)
コード例 #4
0
 def testFromMatches(self):
     # Setup artifical matches that correspond to a known (random) PolynomialTransform.
     order = 3
     truePoly = makeRandomPolynomialTransform(order)
     crval = lsst.afw.geom.SpherePoint(35.0, 10.0, lsst.afw.geom.degrees)
     crpix = lsst.afw.geom.Point2D(50, 50)
     cd = lsst.afw.geom.LinearTransform.makeScaling((0.2*lsst.afw.geom.arcseconds).asDegrees()).getMatrix()
     initialWcs = lsst.afw.geom.makeSkyWcs(crpix=crpix, crval=crval, cdMatrix=cd)
     bbox = lsst.afw.geom.Box2D(
         crval.getPosition(lsst.afw.geom.arcseconds) - lsst.afw.geom.Extent2D(20, 20),
         crval.getPosition(lsst.afw.geom.arcseconds) + lsst.afw.geom.Extent2D(20, 20),
     )
     srcSchema = lsst.afw.table.SourceTable.makeMinimalSchema()
     srcPosKey = lsst.afw.table.Point2DKey.addFields(srcSchema, "pos", "source position", "pix")
     srcErrKey = lsst.afw.table.CovarianceMatrix2fKey.addFields(srcSchema, "pos",
                                                                ["x", "y"], ["pix", "pix"])
     srcSchema.getAliasMap().set("slot_Centroid", "pos")
     nPoints = 10
     trueSrc = lsst.afw.table.SourceCatalog(srcSchema)
     trueSrc.reserve(nPoints)
     measSrc = lsst.afw.table.SourceCatalog(srcSchema)
     measSrc.reserve(nPoints)
     ref = lsst.afw.table.SimpleCatalog(lsst.afw.table.SimpleTable.makeMinimalSchema())
     ref.reserve(nPoints)
     refCoordKey = ref.getCoordKey()
     errScaling = 1E-14
     matches = []
     initialIwcToSky = lsst.afw.geom.getIntermediateWorldCoordsToSky(initialWcs)
     for i in range(nPoints):
         refRec = ref.addNew()
         raDeg, decDeg = (
             np.random.uniform(low=bbox.getMinX(), high=bbox.getMaxX()),
             np.random.uniform(low=bbox.getMinY(), high=bbox.getMaxY()),
         )
         skyCoord = lsst.afw.geom.SpherePoint(raDeg, decDeg, lsst.afw.geom.arcseconds)
         refRec.set(refCoordKey, skyCoord)
         trueRec = trueSrc.addNew()
         truePos = truePoly(initialIwcToSky.applyInverse(skyCoord))
         trueRec.set(srcPosKey, truePos)
         measRec = measSrc.addNew()
         covSqrt = np.random.randn(3, 2)
         cov = (errScaling*(np.dot(covSqrt.transpose(), covSqrt) +
                np.diag([1.0, 1.0]))).astype(np.float32)
         # We don't actually perturb positions according to noise level, as
         # this makes it much harder to test that the result agrees with
         # what we put in.
         measPos = truePos
         measRec.set(srcPosKey, measPos)
         measRec.set(srcErrKey, cov)
         match = lsst.afw.table.ReferenceMatch(refRec, measRec, (measPos - truePos).computeNorm())
         matches.append(match)
     # Construct a fitter, and verify that the internal catalog it constructs is what we expect.
     fitter = ScaledPolynomialTransformFitter.fromMatches(order, matches, initialWcs, 0.0)
     expected = lsst.meas.astrom.compose(
         fitter.getOutputScaling(),
         lsst.meas.astrom.compose(truePoly, fitter.getInputScaling().inverted())
     )
     data = fitter.getData()
     dataOutKey = lsst.afw.table.Point2DKey(data.schema["src"])
     dataInKey = lsst.afw.table.Point2DKey(data.schema["intermediate"])
     dataErrKey = lsst.afw.table.CovarianceMatrix2fKey(data.schema["src"], ["x", "y"])
     scaledInBBox = lsst.afw.geom.Box2D()
     scaledOutBBox = lsst.afw.geom.Box2D()
     vandermonde = np.zeros((nPoints, (order + 1)*(order + 2)//2), dtype=float)
     for i, (match, dataRec, trueRec) in enumerate(zip(matches, data, trueSrc)):
         self.assertEqual(match.second.getX(), dataRec.get("src_x"))
         self.assertEqual(match.second.getY(), dataRec.get("src_y"))
         self.assertEqual(match.first.getId(), dataRec.get("ref_id"))
         self.assertEqual(match.second.getId(), dataRec.get("src_id"))
         refPos = initialIwcToSky.applyInverse(match.first.getCoord())
         self.assertEqual(refPos.getX(), dataRec.get("intermediate_x"))
         self.assertEqual(refPos.getY(), dataRec.get("intermediate_y"))
         self.assertFloatsAlmostEqual(match.second.get(srcErrKey), dataRec.get(dataErrKey), rtol=1E-7)
         scaledIn = fitter.getInputScaling()(dataRec.get(dataInKey))
         scaledOut = fitter.getOutputScaling()(dataRec.get(dataOutKey))
         scaledInBBox.include(scaledIn)
         scaledOutBBox.include(scaledOut)
         self.assertFloatsAlmostEqual(np.array(expected(scaledIn)), np.array(scaledOut), rtol=1E-7)
         j = 0
         for n in range(order + 1):
             for p in range(n + 1):
                 q = n - p
                 vandermonde[i, j] = scaledIn.getX()**p * scaledIn.getY()**q
                 j += 1
     # Verify that scaling transforms move inputs and outputs into [-1, 1]
     self.assertFloatsAlmostEqual(scaledInBBox.getMinX(), -1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledInBBox.getMinY(), -1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledInBBox.getMaxX(), 1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledInBBox.getMaxY(), 1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledOutBBox.getMinX(), -1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledOutBBox.getMinY(), -1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledOutBBox.getMaxX(), 1.0, rtol=1E-12)
     self.assertFloatsAlmostEqual(scaledOutBBox.getMaxY(), 1.0, rtol=1E-12)
     # Run the fitter, and check that we get out approximately what we put in.
     fitter.fit(order)
     fitter.updateModel()
     # Check the transformed input points.
     self.assertFloatsAlmostEqual(data.get("model_x"), trueSrc.getX(), rtol=1E-15)
     self.assertFloatsAlmostEqual(data.get("model_y"), trueSrc.getY(), rtol=1E-15)
     # Check the actual transform's coefficients (after composing in the scaling, which is
     # a lot of the reason we lose a lot of precision here).
     fittedPoly = lsst.meas.astrom.PolynomialTransform.convert(fitter.getTransform())
     self.assertFloatsAlmostEqual(fittedPoly.getXCoeffs(), truePoly.getXCoeffs(), rtol=1E-5, atol=1E-5)
     self.assertFloatsAlmostEqual(fittedPoly.getYCoeffs(), truePoly.getYCoeffs(), rtol=1E-5, atol=1E-5)