23 __all__ = [
"BoxGrid",
"makeSipIwcToPixel",
"makeSipPixelToIwc"]
32 from numpy.testing
import assert_allclose, assert_array_equal
33 from astshim.test import makeForwardPolyMap, makeTwoWayPolyMap
44 """Divide a box into nx by ny sub-boxes that tile the region 46 The sub-boxes will be of the same type as `box` and will exactly tile `box`; 47 they will also all be the same size, to the extent possible (some variation 48 is inevitable for integer boxes that cannot be evenly divided. 52 box : `lsst.geom.Box2I` or `lsst.geom.Box2D` 53 the box to subdivide; the boxes in the grid will be of the same type 54 numColRow : pair of `int` 55 number of columns and rows 59 if len(numColRow) != 2:
60 raise RuntimeError(f
"numColRow={numColRow!r}; must be a sequence of two integers")
61 self.
_numColRow = tuple(int(val)
for val
in numColRow)
68 raise RuntimeError(f
"Unknown class {type(box)} of box {box}")
72 minPoint = box.getMin()
74 dtype = np.array(minPoint).dtype
76 self.
_divList = [np.linspace(start=box.getMin()[i],
80 dtype=dtype)
for i
in range(2)]
87 """Return the box at the specified x,y index 91 indXY : pair of `ints` 92 the x,y index to return 96 subBox : `lsst.geom.Box2I` or `lsst.geom.Box2D` 104 return self.shape[0]*self.shape[1]
107 """Return an iterator over all boxes, where column varies most quickly 115 """Information about a FrameSet 119 frameSet : `ast.FrameSet` 120 The FrameSet about which you want information 129 Index of current frame 130 isBaseSkyFrame : `bool` 131 Is the base frame an `ast.SkyFrame`? 132 isCurrSkyFrame : `bool` 133 Is the current frame an `ast.SkyFrame`? 143 """Return a list of ast.PolyMap coefficients for the specified SIP matrix 145 The returned list of coefficients for an ast.PolyMap 146 that computes the following function: 148 f(dxy) = dxy + sipPolynomial(dxy)) 149 where dxy = pixelPosition - pixelOrigin 150 and sipPolynomial is a polynomial with terms `<name>n_m for x^n y^m` 151 (e.g. A2_0 is the coefficient for x^2 y^0) 155 metadata : lsst.daf.base.PropertySet 156 FITS metadata describing a WCS with the specified SIP coefficients 158 The desired SIP terms: one of A, B, AP, BP 163 A list of coefficients for an ast.PolyMap that computes 164 the specified SIP polynomial, including a term for out = in 168 This is an internal function for use by makeSipIwcToPixel 169 and makeSipPixelToIwc 171 outAxisDict = dict(A=1, B=2, AP=1, BP=2)
172 outAxis = outAxisDict.get(name)
174 raise RuntimeError(f
"{name} not a supported SIP name")
175 width = metadata.getAsInt(f
"{name}_ORDER") + 1
180 coeffs.append([1.0, outAxis, 1, 0])
182 coeffs.append([1.0, outAxis, 0, 1])
184 for xPower
in range(width):
185 for yPower
in range(width):
186 coeffName = f
"{name}_{xPower}_{yPower}" 187 if not metadata.exists(coeffName):
190 coeff = metadata.getAsDouble(coeffName)
191 coeffs.append([coeff, outAxis, xPower, yPower])
193 raise RuntimeError(f
"No {name} coefficients found")
198 """Make an IWC to pixel transform with SIP distortion from FITS-WCS metadata 200 This function is primarily intended for unit tests. 201 IWC is intermediate world coordinates, as described in the FITS papers. 205 metadata : lsst.daf.base.PropertySet 206 FITS metadata describing a WCS with inverse SIP coefficients 210 lsst.afw.geom.TransformPoint2ToPoint2 211 Transform from IWC position to pixel position (zero-based) 212 in the forward direction. The inverse direction is not defined. 217 The inverse SIP terms APn_m, BPn_m are polynomial coefficients x^n y^m 218 for computing transformed x, y respectively. If we call the resulting 219 polynomial inverseSipPolynomial, the returned transformation is: 221 pixelPosition = pixel origin + uv + inverseSipPolynomial(uv) 222 where uv = inverseCdMatrix * iwcPosition 224 crpix = (metadata.getScalar(
"CRPIX1") - 1, metadata.getScalar(
"CRPIX2") - 1)
229 coeffArr = np.array(coeffList, dtype=float)
230 sipPolyMap =
ast.PolyMap(coeffArr, 2,
"IterInverse=0")
232 iwcToPixelMap = cdMatrixMap.inverted().
then(sipPolyMap).
then(pixelRelativeToAbsoluteMap)
237 """Make a pixel to IWC transform with SIP distortion from FITS-WCS metadata 239 This function is primarily intended for unit tests. 240 IWC is intermediate world coordinates, as described in the FITS papers. 244 metadata : lsst.daf.base.PropertySet 245 FITS metadata describing a WCS with forward SIP coefficients 249 lsst.afw.geom.TransformPoint2ToPoint2 250 Transform from pixel position (zero-based) to IWC position 251 in the forward direction. The inverse direction is not defined. 256 The forward SIP terms An_m, Bn_m are polynomial coefficients x^n y^m 257 for computing transformed x, y respectively. If we call the resulting 258 polynomial sipPolynomial, the returned transformation is: 260 iwcPosition = cdMatrix * (dxy + sipPolynomial(dxy)) 261 where dxy = pixelPosition - pixelOrigin 263 crpix = (metadata.getScalar(
"CRPIX1") - 1, metadata.getScalar(
"CRPIX2") - 1)
264 pixelAbsoluteToRelativeMap =
ast.ShiftMap(crpix).inverted()
268 coeffArr = np.array(coeffList, dtype=float)
269 sipPolyMap =
ast.PolyMap(coeffArr, 2,
"IterInverse=0")
270 pixelToIwcMap = pixelAbsoluteToRelativeMap.then(sipPolyMap).
then(cdMatrixMap)
275 """A FrameSet with base or current frame possibly permuted, with associated 278 Only two-axis frames will be permuted. 282 frameSet : `ast.FrameSet` 283 The FrameSet you wish to permute. A deep copy is made. 285 Permute the base frame's axes? 287 Permute the current frame's axes? 292 If you try to permute a frame that does not have 2 axes 298 frameSet : `ast.FrameSet` 299 The FrameSet that may be permuted. A local copy is made. 300 isBaseSkyFrame : `bool` 301 Is the base frame an `ast.SkyFrame`? 302 isCurrSkyFrame : `bool` 303 Is the current frame an `ast.SkyFrame`? 304 isBasePermuted : `bool` 305 Are the base frame axes permuted? 306 isCurrPermuted : `bool` 307 Are the current frame axes permuted? 309 def __init__(self, frameSet, permuteBase, permuteCurr):
317 raise RuntimeError(
"Base frame has {} axes; 2 required to permute".
format(baseNAxes))
318 self.
frameSet.current = fsInfo.baseInd
320 self.
frameSet.current = fsInfo.currInd
324 raise RuntimeError(
"Current frame has {} axes; 2 required to permute".
format(currNAxes))
332 """Base class for unit tests of Transform<X>To<Y> 334 Subclasses must call `TransformTestBaseClass.setUp(self)` 335 if they provide their own version. 337 If a package other than afw uses this class then it must 338 override the `getTestDir` method to avoid writing into 339 afw's test directory. 343 """Return a directory where temporary test files can be written 345 The default implementation returns the test directory of the `afw` 348 If this class is used by a test in a package other than `afw` 349 then the subclass must override this method. 356 Subclasses should call this method if they override setUp. 368 "Generic": (1, 2, 3, 4),
378 "SpherePoint": (1, 3, 4),
391 """Make an array of generic point data 393 The data will be suitable for spherical points 398 Number of points in the array 400 Number of axes in the point 404 np.array of floats with shape (nAxes, nPoints) 405 The values are as follows; if nAxes != 2: 406 The first point has values `[0, delta, 2*delta, ..., (nAxes-1)*delta]` 407 The Nth point has those values + N 408 if nAxes == 2 then the data is scaled so that the max value of axis 1 409 is a bit less than pi/2 413 oneAxis = np.arange(nPoints, dtype=float)
415 rawData = np.array([j * delta + oneAxis
for j
in range(nAxes)], dtype=float)
419 maxLatitude = np.max(rawData[1])
420 rawData *= math.pi * 0.4999 / maxLatitude
425 """Make one generic point 430 Number of axes in the point 432 Increment between axis values 436 A list of `nAxes` floats with values `[0, delta, ..., (nAxes-1)*delta] 438 return [i*delta
for i
in range(nAxes)]
447 Endpoint class name prefix; the full class name is name + "Endpoint" 448 nAxes : `int` or `None`, optional 449 number of axes; an int is required if `name` == "Generic"; 454 subclass of `lsst.afw.geom.BaseEndpoint` 455 The constructed endpoint 460 If `name` == "Generic" and `nAxes` is None or <= 0 462 EndpointClassName = name +
"Endpoint" 463 EndpointClass = getattr(afwGeom, EndpointClassName)
464 if name ==
"Generic":
466 raise TypeError(
"nAxes must be an integer for GenericEndpoint")
467 return EndpointClass(nAxes)
468 return EndpointClass()
472 """Return the appropriate frame for the given name and nAxes 477 Endpoint class name prefix; the full class name is name + "Endpoint" 478 nAxes : `int` or `None`, optional 479 number of axes; an int is required if `name` == "Generic"; 485 The constructed frame 490 If `name` == "Generic" and `nAxes` is `None` or <= 0 496 """Return a list of 0 or more frames that are not a valid match for the 502 Endpoint class name prefix; the full class name is name + "Endpoint" 506 Collection of `ast.Frame` 507 A collection of 0 or more frames 526 The FrameSet will contain 4 frames and three transforms connecting them. 527 The idenity of each frame is provided by self.frameIdentDict 529 Frame Index Mapping from this frame to the next 530 `baseFrame` 1 `ast.UnitMap(nIn)` 531 Frame(nIn) 2 `polyMap` 532 Frame(nOut) 3 `ast.UnitMap(nOut)` 536 - `nIn` = `baseFrame.nAxes` 537 - `nOut` = `currFrame.nAxes` 538 - `polyMap` = `makeTwoWayPolyMap(nIn, nOut)` 543 The FrameSet as described above 547 baseFrame : `ast.Frame` 549 currFrame : `ast.Frame` 552 nIn = baseFrame.nAxes
553 nOut = currFrame.nAxes
558 baseFrame = baseFrame.copy()
560 currFrame = currFrame.copy()
566 frameSet.addFrame(ast.FrameSet.CURRENT,
ast.UnitMap(nIn), frame2)
569 frameSet.addFrame(ast.FrameSet.CURRENT, polyMap, frame3)
570 frameSet.addFrame(ast.FrameSet.CURRENT,
ast.UnitMap(nOut), currFrame)
575 """Iterator over 0 or more frameSets with SkyFrames axes permuted 577 Only base and current SkyFrames are permuted. If neither the base nor 578 the current frame is a SkyFrame then no frames are returned. 582 iterator over `PermutedFrameSet` 586 if not (fsInfo.isBaseSkyFrame
or fsInfo.isCurrSkyFrame):
589 permuteBaseList = [
False,
True]
if fsInfo.isBaseSkyFrame
else [
False]
590 permuteCurrList = [
False,
True]
if fsInfo.isCurrSkyFrame
else [
False]
591 for permuteBase
in permuteBaseList:
592 for permuteCurr
in permuteCurrList:
597 """Make a Jacobian matrix for the equation described by 603 the dimensions of the input and output data; see makeTwoWayPolyMap 604 inPoint : `numpy.ndarray` 605 an array of size `nIn` representing the point at which the Jacobian 611 an `nOut` x `nIn` array of first derivatives 613 basePolyMapCoeff = 0.001
614 baseCoeff = 2.0 * basePolyMapCoeff
615 coeffs = np.empty((nOut, nIn))
616 for iOut
in range(nOut):
617 coeffOffset = baseCoeff * iOut
618 for iIn
in range(nIn):
619 coeffs[iOut, iIn] = baseCoeff * (iIn + 1) + coeffOffset
620 coeffs[iOut, iIn] *= inPoint[iIn]
621 assert coeffs.ndim == 2
623 assert coeffs.shape == (nOut, nIn)
627 """Check applyForward and applyInverse for a transform 631 transform : `lsst.afw.geom.Transform` 632 The transform to check 633 mapping : `ast.Mapping` 634 The mapping the transform should use. This mapping 635 must contain valid forward or inverse transformations, 636 but they need not match if both present. Hence the 637 mappings returned by make*PolyMap are acceptable. 639 Error message suffix describing test parameters 641 fromEndpoint = transform.fromEndpoint
642 toEndpoint = transform.toEndpoint
643 mappingFromTransform = transform.getMapping()
647 self.assertEqual(nIn, fromEndpoint.nAxes, msg=msg)
648 self.assertEqual(nOut, toEndpoint.nAxes, msg=msg)
652 inPoint = fromEndpoint.pointFromData(rawInPoint)
657 inArray = fromEndpoint.arrayFromData(rawInArray)
659 if mapping.hasForward:
660 self.assertTrue(transform.hasForward)
661 outPoint = transform.applyForward(inPoint)
662 rawOutPoint = toEndpoint.dataFromPoint(outPoint)
663 assert_allclose(rawOutPoint, mapping.applyForward(rawInPoint), err_msg=msg)
664 assert_allclose(rawOutPoint, mappingFromTransform.applyForward(rawInPoint), err_msg=msg)
666 outArray = transform.applyForward(inArray)
667 rawOutArray = toEndpoint.dataFromArray(outArray)
668 self.assertFloatsAlmostEqual(rawOutArray, mapping.applyForward(rawInArray), msg=msg)
669 self.assertFloatsAlmostEqual(rawOutArray, mappingFromTransform.applyForward(rawInArray), msg=msg)
673 outPoint = toEndpoint.pointFromData(rawOutPoint)
675 outArray = toEndpoint.arrayFromData(rawOutArray)
677 self.assertFalse(transform.hasForward)
679 if mapping.hasInverse:
680 self.assertTrue(transform.hasInverse)
684 inversePoint = transform.applyInverse(outPoint)
685 rawInversePoint = fromEndpoint.dataFromPoint(inversePoint)
686 assert_allclose(rawInversePoint, mapping.applyInverse(rawOutPoint), err_msg=msg)
687 assert_allclose(rawInversePoint, mappingFromTransform.applyInverse(rawOutPoint), err_msg=msg)
692 inverseArray = transform.applyInverse(outArray)
693 rawInverseArray = fromEndpoint.dataFromArray(inverseArray)
694 self.assertFloatsAlmostEqual(rawInverseArray, mapping.applyInverse(rawOutArray), msg=msg)
695 self.assertFloatsAlmostEqual(rawInverseArray, mappingFromTransform.applyInverse(rawOutArray),
698 self.assertFalse(transform.hasInverse)
701 """Check that two Transforms are each others' inverses. 705 forward : `lsst.afw.geom.Transform` 706 the reference Transform to test 707 inverse : `lsst.afw.geom.Transform` 708 the transform that should be the inverse of `forward` 710 error message suffix describing test parameters 712 fromEndpoint = forward.fromEndpoint
713 toEndpoint = forward.toEndpoint
714 forwardMapping = forward.getMapping()
715 inverseMapping = inverse.getMapping()
718 self.assertEqual(forward.fromEndpoint,
719 inverse.toEndpoint, msg=msg)
720 self.assertEqual(forward.toEndpoint,
721 inverse.fromEndpoint, msg=msg)
722 self.assertEqual(forward.hasForward, inverse.hasInverse, msg=msg)
723 self.assertEqual(forward.hasInverse, inverse.hasForward, msg=msg)
729 inPoint = fromEndpoint.pointFromData(rawInPoint)
731 outPoint = toEndpoint.pointFromData(rawOutPoint)
736 inArray = fromEndpoint.arrayFromData(rawInArray)
738 outArray = toEndpoint.arrayFromData(rawOutArray)
740 if forward.hasForward:
741 self.assertEqual(forward.applyForward(inPoint),
742 inverse.applyInverse(inPoint), msg=msg)
743 self.assertEqual(forwardMapping.applyForward(rawInPoint),
744 inverseMapping.applyInverse(rawInPoint), msg=msg)
746 assert_array_equal(forward.applyForward(inArray),
747 inverse.applyInverse(inArray),
749 assert_array_equal(forwardMapping.applyForward(rawInArray),
750 inverseMapping.applyInverse(rawInArray),
753 if forward.hasInverse:
754 self.assertEqual(forward.applyInverse(outPoint),
755 inverse.applyForward(outPoint), msg=msg)
756 self.assertEqual(forwardMapping.applyInverse(rawOutPoint),
757 inverseMapping.applyForward(rawOutPoint), msg=msg)
758 assert_array_equal(forward.applyInverse(outArray),
759 inverse.applyForward(outArray),
761 assert_array_equal(forwardMapping.applyInverse(rawOutArray),
762 inverseMapping.applyForward(rawOutArray),
766 """Check Transform_<fromName>_<toName> using the Mapping constructor 770 fromName, toName : `str` 771 Endpoint name prefix for "from" and "to" endpoints, respectively, 772 e.g. "Point2" for `lsst.afw.geom.Point2Endpoint` 773 fromAxes, toAxes : `int` 774 number of axes in fromFrame and toFrame, respectively 776 transformClassName =
"Transform{}To{}".
format(fromName, toName)
777 TransformClass = getattr(afwGeom, transformClassName)
778 baseMsg =
"TransformClass={}".
format(TransformClass.__name__)
781 for nIn, nOut
in itertools.product(self.
goodNAxes[fromName],
783 msg =
"{}, nIn={}, nOut={}".
format(baseMsg, nIn, nOut)
788 desStr =
"{}[{}->{}]".
format(transformClassName, nIn, nOut)
789 self.assertEqual(
"{}".
format(transform), desStr)
790 self.assertEqual(repr(transform),
"lsst.afw.geom." + desStr)
805 for nIn, badNOut
in itertools.product(self.
goodNAxes[fromName],
808 msg =
"{}, nIn={}, badNOut={}".
format(baseMsg, nIn, badNOut)
809 with self.assertRaises(InvalidParameterError, msg=msg):
813 for badNIn, nOut
in itertools.product(self.
badNAxes[fromName],
816 msg =
"{}, badNIn={}, nOut={}".
format(baseMsg, nIn, nOut)
817 with self.assertRaises(InvalidParameterError, msg=msg):
821 """Check Transform_<fromName>_<toName> using the FrameSet constructor 825 fromName, toName : `str` 826 Endpoint name prefix for "from" and "to" endpoints, respectively, 827 e.g. "Point2" for `lsst.afw.geom.Point2Endpoint` 829 transformClassName =
"Transform{}To{}".
format(fromName, toName)
830 TransformClass = getattr(afwGeom, transformClassName)
831 baseMsg =
"TransformClass={}".
format(TransformClass.__name__)
832 for nIn, nOut
in itertools.product(self.
goodNAxes[fromName],
834 msg =
"{}, nIn={}, nOut={}".
format(baseMsg, nIn, nOut)
839 self.assertEqual(frameSet.nFrame, 4)
843 badFrameSet = self.
makeFrameSet(badBaseFrame, currFrame)
844 with self.assertRaises(InvalidParameterError):
847 reallyBadFrameSet = self.
makeFrameSet(badBaseFrame, badCurrFrame)
848 with self.assertRaises(InvalidParameterError):
851 badFrameSet = self.
makeFrameSet(baseFrame, badCurrFrame)
852 with self.assertRaises(InvalidParameterError):
857 desStr =
"{}[{}->{}]".
format(transformClassName, nIn, nOut)
858 self.assertEqual(
"{}".
format(transform), desStr)
859 self.assertEqual(repr(transform),
"lsst.afw.geom." + desStr)
863 mappingFromTransform = transform.getMapping()
865 self.assertEqual(
type(transform),
type(transformCopy))
866 self.assertEqual(transform.getMapping(), mappingFromTransform)
878 if permutedFS.isBaseSkyFrame:
879 baseFrame = permutedFS.frameSet.getFrame(ast.FrameSet.BASE)
881 desBaseLonAxis = 2
if permutedFS.isBasePermuted
else 1
882 self.assertEqual(baseFrame.lonAxis, desBaseLonAxis)
883 if permutedFS.isCurrSkyFrame:
884 currFrame = permutedFS.frameSet.getFrame(ast.FrameSet.CURRENT)
886 desCurrLonAxis = 2
if permutedFS.isCurrPermuted
else 1
887 self.assertEqual(currFrame.lonAxis, desCurrLonAxis)
893 """Test Transform<fromName>To<toName>.inverted 897 fromName, toName : `str` 898 Endpoint name prefix for "from" and "to" endpoints, respectively, 899 e.g. "Point2" for `lsst.afw.geom.Point2Endpoint` 901 transformClassName =
"Transform{}To{}".
format(fromName, toName)
902 TransformClass = getattr(afwGeom, transformClassName)
903 baseMsg =
"TransformClass={}".
format(TransformClass.__name__)
904 for nIn, nOut
in itertools.product(self.
goodNAxes[fromName],
906 msg =
"{}, nIn={}, nOut={}".
format(baseMsg, nIn, nOut)
910 "{}, Map={}".
format(msg,
"TwoWay"))
914 "{}, Map={}".
format(msg,
"Forward"))
918 "{}, Map={}".
format(msg,
"Inverse"))
921 """Test Transform<fromName>To<toName>.inverted for a specific 924 Also check that inverted() and getInverted() return the same 929 TransformClass : `type` 930 The class of transform to test, such as TransformPoint2ToPoint2 931 mapping : `ast.Mapping` 932 The mapping to use for the transform 937 inverse = transform.inverted()
938 inverseInverse = inverse.inverted()
945 """Test Transform<fromName>To<toName>.getJacobian 949 fromName, toName : `str` 950 Endpoint name prefix for "from" and "to" endpoints, respectively, 951 e.g. "Point2" for `lsst.afw.geom.Point2Endpoint` 953 transformClassName =
"Transform{}To{}".
format(fromName, toName)
954 TransformClass = getattr(afwGeom, transformClassName)
955 baseMsg =
"TransformClass={}".
format(TransformClass.__name__)
956 for nIn, nOut
in itertools.product(self.
goodNAxes[fromName],
958 msg =
"{}, nIn={}, nOut={}".
format(baseMsg, nIn, nOut)
961 fromEndpoint = transform.fromEndpoint
965 inPoint = fromEndpoint.pointFromData(rawInPoint)
966 jacobian = transform.getJacobian(inPoint)
967 assert_allclose(jacobian, self.
makeJacobian(nIn, nOut, rawInPoint),
971 inPoint = fromEndpoint.pointFromData(rawInPoint)
972 jacobian = transform.getJacobian(inPoint)
973 assert_allclose(jacobian, self.
makeJacobian(nIn, nOut, rawInPoint),
977 """Test Transform<fromName>To<midName>.then(Transform<midName>To<toName>) 982 the prefix of the starting endpoint (e.g., "Point2" for a 983 Point2Endpoint) for the final, concatenated Transform 985 the prefix for the shared endpoint where two Transforms will be 988 the prefix of the ending endpoint for the final, concatenated 991 TransformClass1 = getattr(afwGeom,
992 "Transform{}To{}".
format(fromName, midName))
993 TransformClass2 = getattr(afwGeom,
994 "Transform{}To{}".
format(midName, toName))
995 baseMsg =
"{}.then({})".
format(TransformClass1.__name__,
996 TransformClass2.__name__)
997 for nIn, nMid, nOut
in itertools.product(self.
goodNAxes[fromName],
1000 msg =
"{}, nIn={}, nMid={}, nOut={}".
format(
1001 baseMsg, nIn, nMid, nOut)
1003 transform1 = TransformClass1(polyMap1)
1005 transform2 = TransformClass2(polyMap2)
1006 transform = transform1.then(transform2)
1008 fromEndpoint = transform1.fromEndpoint
1009 toEndpoint = transform2.toEndpoint
1012 outPointMerged = transform.applyForward(inPoint)
1013 outPointSeparate = transform2.applyForward(
1014 transform1.applyForward(inPoint))
1015 assert_allclose(toEndpoint.dataFromPoint(outPointMerged),
1016 toEndpoint.dataFromPoint(outPointSeparate),
1020 inPointMerged = transform.applyInverse(outPoint)
1021 inPointSeparate = transform1.applyInverse(
1022 transform2.applyInverse(outPoint))
1024 fromEndpoint.dataFromPoint(inPointMerged),
1025 fromEndpoint.dataFromPoint(inPointSeparate),
1029 if midName ==
"Generic":
1033 transform1 = TransformClass1(polyMap)
1035 transform2 = TransformClass2(polyMap)
1036 with self.assertRaises(InvalidParameterError):
1037 transform = transform1.then(transform2)
1040 if fromName != midName:
1043 joinNAxes =
set(self.
goodNAxes[fromName]).intersection(
1046 for nIn, nMid, nOut
in itertools.product(self.
goodNAxes[fromName],
1050 transform1 = TransformClass1(polyMap)
1052 transform2 = TransformClass1(polyMap)
1053 with self.assertRaises(InvalidParameterError):
1054 transform = transform1.then(transform2)
1057 """Assert that two transforms are equal""" 1058 self.assertEqual(
type(transform1),
type(transform2))
1059 self.assertEqual(transform1.fromEndpoint, transform2.fromEndpoint)
1060 self.assertEqual(transform1.toEndpoint, transform2.toEndpoint)
1061 self.assertEqual(transform1.getMapping(), transform2.getMapping())
1063 fromEndpoint = transform1.fromEndpoint
1064 toEndpoint = transform1.toEndpoint
1065 mapping = transform1.getMapping()
1069 if mapping.hasForward:
1072 inArray = fromEndpoint.arrayFromData(rawInArray)
1073 outArray = transform1.applyForward(inArray)
1074 outData = toEndpoint.dataFromArray(outArray)
1075 outArrayRoundTrip = transform2.applyForward(inArray)
1076 outDataRoundTrip = toEndpoint.dataFromArray(outArrayRoundTrip)
1077 assert_allclose(outData, outDataRoundTrip)
1079 if mapping.hasInverse:
1082 outArray = toEndpoint.arrayFromData(rawOutArray)
1083 inArray = transform1.applyInverse(outArray)
1084 inData = fromEndpoint.dataFromArray(inArray)
1085 inArrayRoundTrip = transform2.applyInverse(outArray)
1086 inDataRoundTrip = fromEndpoint.dataFromArray(inArrayRoundTrip)
1087 assert_allclose(inData, inDataRoundTrip)
1090 """Check persistence of a transform 1092 className =
type(transform).__name__
1095 transformStr = transform.writeString()
1096 serialVersion, serialClassName, serialRest = transformStr.split(
" ", 2)
1097 self.assertEqual(int(serialVersion), 1)
1098 self.assertEqual(serialClassName, className)
1099 badStr1 =
" ".join([
"2", serialClassName, serialRest])
1101 transform.readString(badStr1)
1102 badClassName =
"x" + serialClassName
1103 badStr2 =
" ".join([
"1", badClassName, serialRest])
1105 transform.readString(badStr2)
1106 transformFromStr1 = transform.readString(transformStr)
1110 transformFromStr2 = afwGeom.transformFromString(transformStr)
1118 transform.writeFits(filename)
def __init__(self, frameSet, permuteBase, permuteCurr)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Eigen::Matrix2d getCdMatrixFromMetadata(daf::base::PropertySet &metadata)
Read a CD matrix from FITS WCS metadata.
def __init__(self, frameSet)
MatrixMap is a form of Mapping which performs a general linear transformation.
A floating-point coordinate rectangle geometry.
A UnitMap is a unit (null) Mapping that has no effect on the coordinates supplied to it...
daf::base::PropertySet * set
std::string getPackageDir(std::string const &packageName)
return the root directory of a setup package
SkyFrame is a specialised form of Frame which describes celestial longitude/latitude coordinate syste...
def makeTwoWayPolyMap(nIn, nOut)
Frame is used to represent a coordinate system.
def makeSipPixelToIwc(metadata)
ShiftMap is a linear Mapping which shifts each axis by a specified constant value.
def __getitem__(self, indXY)
def getTempFilePath(ext, expectOutput=True)
def __init__(self, box, numColRow)
Reports invalid arguments.
PolyMap is a Mapping which performs a general polynomial transformation.
def makeSipPolyMapCoeffs(metadata, name)
An integer coordinate rectangle.
def makeForwardPolyMap(nIn, nOut)
A FrameSet consists of a set of one or more Frames (which describe coordinate systems), connected together by Mappings (which describe how the coordinate systems are inter-related).
def makeSipIwcToPixel(metadata)