5 from numpy.testing
import assert_allclose, assert_array_equal
7 from .channel
import Channel
8 from .fitsChan
import FitsChan
9 from .polyMap
import PolyMap
10 from .xmlChan
import XmlChan
11 from .stream
import StringStream
15 """Base class for unit tests of objects 19 """Assert that two astshim objects are identical. 21 Identical means the objects are of the same class (if checkType) 22 and all properties are identical (including whether set or defaulted). 25 self.assertIs(
type(obj1),
type(obj2))
26 self.assertEqual(obj1.show(), obj2.show())
27 self.assertEqual(
str(obj1),
str(obj2))
28 self.assertEqual(repr(obj1), repr(obj2))
31 """Check that an astshim object can be deep-copied 33 nobj = obj.getNObject()
34 nref = obj.getRefCount()
40 for cp
in copyIter(obj):
42 self.assertEqual(obj.getNObject(), nobj + 1)
45 self.assertEqual(obj.getRefCount(), nref)
46 self.assertFalse(obj.same(cp))
47 self.assertEqual(cp.getNObject(), nobj + 1)
48 self.assertEqual(cp.getRefCount(), 1)
50 originalIdent = obj.ident
51 cp.ident = obj.ident +
" modified" 52 self.assertEqual(obj.ident, originalIdent)
55 self.assertEqual(obj.getNObject(), nobj)
56 self.assertEqual(obj.getRefCount(), nref)
59 """Check that an astshim object can be persisted and unpersisted 61 @param[in] obj Object to be checked 62 @param[in] typeFromChannel Type of object expected to be read from 63 a channel (since some thin wrapper types are read 64 as the underlying type); None if the original type 66 Check persistence using Channel, FitsChan (with native encoding, 67 as the only encoding compatible with all AST objects), XmlChan 70 for channelType, options
in (
72 (FitsChan,
"Encoding=Native"),
76 chan = channelType(ss, options)
79 if channelType
is FitsChan:
81 obj_copy = chan.read()
82 if typeFromChannel
is not None:
83 self.assertIs(
type(obj_copy), typeFromChannel)
88 obj_copy = pickle.loads(pickle.dumps(obj))
94 """Base class for unit tests of mappings 98 """Check that a mapping's reverse transform is the opposite of forward 100 amap is the mapping to test 101 poslist is a list of input position for a forward transform; 102 a numpy array with shape [nin, num points] 103 or collection that can be cast to same 104 rtol is the relative tolerance for numpy.testing.assert_allclose 105 atol is the absolute tolerance for numpy.testing.assert_allclose 107 poslist = np.array(poslist, dtype=float)
108 if len(poslist.shape) == 1:
110 poslist.shape = (1, len(poslist))
112 to_poslist = amap.applyForward(poslist)
113 rt_poslist = amap.applyInverse(to_poslist)
114 assert_allclose(poslist, rt_poslist, rtol=rtol, atol=atol)
117 amapinv = amap.inverted()
118 rt2_poslist = amapinv.applyForward(to_poslist)
119 assert_allclose(poslist, rt2_poslist, rtol=rtol, atol=atol)
122 acmp = amap.then(amapinv)
123 assert_allclose(poslist, acmp.applyForward(poslist), rtol=rtol, atol=atol)
126 posvec =
list(poslist.flat)
127 to_posvec = amap.applyForward(posvec)
130 assert_allclose(to_posvec,
list(to_poslist.flat), rtol=rtol, atol=atol)
132 rt_posvec = amap.applyInverse(to_posvec)
133 assert_allclose(posvec, rt_posvec, rtol=rtol, atol=atol)
136 """Check basic simplfication for a reversible mapping 139 - A compound mapping of a amap and its inverse simplifies to a unit amap 140 - A compound mapping of a amap and a unit amap simplifies to the original amap 142 amapinv = amap.inverted()
143 cmp1 = amap.then(amapinv)
144 unit1 = cmp1.simplified()
145 self.assertEqual(unit1.className,
"UnitMap")
146 self.assertEqual(amap.nIn, cmp1.nIn)
147 self.assertEqual(amap.nIn, cmp1.nOut)
148 self.assertEqual(cmp1.nIn, unit1.nIn)
149 self.assertEqual(cmp1.nOut, unit1.nOut)
151 cmp2 = amapinv.then(amap)
152 unit2 = cmp2.simplified()
153 self.assertEqual(unit2.className,
"UnitMap")
154 self.assertEqual(amapinv.nIn, cmp2.nIn)
155 self.assertEqual(amapinv.nIn, cmp2.nOut)
156 self.assertEqual(cmp2.nIn, unit2.nIn)
157 self.assertEqual(cmp2.nOut, unit2.nOut)
159 for ma, mb, desmap3
in (
162 (unit2, amapinv, amapinv),
163 (amapinv, unit1, amapinv),
166 cmp3simp = cmp3.simplified()
167 self.assertEqual(cmp3simp.className, amap.simplified().className)
168 self.assertEqual(ma.nIn, cmp3.nIn)
169 self.assertEqual(mb.nOut, cmp3.nOut)
170 self.assertEqual(cmp3.nIn, cmp3simp.nIn)
171 self.assertEqual(cmp3.nOut, cmp3simp.nOut)
174 """Check that a mapping gives identical answers to unpersisted copy 176 poslist is a list of input position for a forward transform 177 (if it exists), or the inverse transform (if not). 178 A numpy array with shape [nAxes, num points] 179 or collection that can be cast to same 181 Checks each direction, if present. However, for generality, 182 does not check that the two directions are inverses of each other; 183 call checkRoundTrip for that. 185 Does everything checkPersistence does, so no need to call both. 187 for channelType, options
in (
189 (FitsChan,
"Encoding=Native"),
196 amap_copy = chan.read()
197 self.assertEqual(amap.className, amap_copy.className)
198 self.assertEqual(amap.show(), amap_copy.show())
199 self.assertEqual(
str(amap),
str(amap_copy))
200 self.assertEqual(repr(amap), repr(amap_copy))
203 outPoslist = amap.applyForward(poslist)
204 assert_array_equal(outPoslist, amap_copy.applyForward(poslist))
207 assert_array_equal(amap.applyInverse(outPoslist),
208 amap_copy.applyInverse(outPoslist))
210 elif amap.hasInverse:
211 assert_array_equal(amap.applyInverse(poslist),
212 amap_copy.applyInverse(poslist))
215 raise RuntimeError(
"mapping has neither forward nor inverse transform")
218 """Check the memory usage for a compoundObject 220 obj1: first object in compound object 221 obj2: second object in compound object 222 cmpObj: compound object (SeriesMap, ParallelMap, CmpMap or CmpFrame) 223 isSeries: is compound object in series? None to not test (e.g. CmpFrame) 227 deltaObj = 2
if type(obj1) ==
type(obj2)
else 1
229 initialNumObj1 = obj1.getNObject()
230 initialNumObj2 = obj2.getNObject()
231 initialNumCmpObj = cmpObj.getNObject()
232 initialRefCountObj1 = obj1.getRefCount()
233 initialRefCountObj2 = obj2.getRefCount()
234 initialRefCountCmpObj = cmpObj.getRefCount()
235 self.assertEqual(obj1.getNObject(), initialNumObj1)
236 self.assertEqual(obj2.getNObject(), initialNumObj2)
237 if isSeries
is not None:
239 self.assertTrue(cmpObj.series)
240 elif isSeries
is False:
241 self.assertFalse(cmpObj.series)
246 self.assertEqual(cmpObj.getRefCount(), initialRefCountCmpObj)
247 self.assertEqual(cmpObj.getNObject(), initialNumCmpObj + 1)
248 self.assertEqual(obj1.getRefCount(), initialRefCountObj1)
249 self.assertEqual(obj2.getRefCount(), initialRefCountObj2)
250 self.assertEqual(obj1.getNObject(), initialNumObj1 + deltaObj)
251 self.assertEqual(obj2.getNObject(), initialNumObj2 + deltaObj)
255 self.assertEqual(cmpObj.getRefCount(), initialRefCountCmpObj)
256 self.assertEqual(cmpObj.getNObject(), initialNumCmpObj)
257 self.assertEqual(obj1.getRefCount(), initialRefCountObj1)
258 self.assertEqual(obj1.getNObject(), initialNumObj1)
259 self.assertEqual(obj2.getRefCount(), initialRefCountObj2)
260 self.assertEqual(obj2.getNObject(), initialNumObj2)
264 """Make an array of coefficients for astshim.PolyMap for the following equation: 266 fj(x) = C0j x0^2 + C1j x1^2 + C2j x2^2 + ... + CNj xN^2 268 * i ranges from 0 to N=nIn-1 269 * j ranges from 0 to nOut-1, 270 * Cij = 0.001 (i+j+1) 274 for out_ind
in range(nOut):
275 coeffOffset = baseCoeff * out_ind
276 for in_ind
in range(nIn):
277 coeff = baseCoeff * (in_ind + 1) + coeffOffset
278 coeffArr = [coeff, out_ind + 1] + [2
if i == in_ind
else 0
for i
in range(nIn)]
279 forwardCoeffs.append(coeffArr)
280 return np.array(forwardCoeffs, dtype=float)
284 """Make an astshim.PolyMap suitable for testing 286 The forward transform is as follows: 287 fj(x) = C0j x0^2 + C1j x1^2 + C2j x2^2 + ... + CNj xN^2 where Cij = 0.001 (i+j+1) 289 The reverse transform is the same equation with i and j reversed 290 thus it is NOT the inverse of the forward direction, 291 but is something that can be easily evaluated. 293 The equation is chosen for the following reasons: 294 - It is well defined for any positive value of nIn, nOut 295 - It stays small for small x, to avoid wraparound of angles for SpherePoint endpoints 299 polyMap = PolyMap(forwardCoeffs, reverseCoeffs)
300 assert polyMap.nIn == nIn
301 assert polyMap.nOut == nOut
302 assert polyMap.hasForward
303 assert polyMap.hasInverse
308 """Make an astshim.PolyMap suitable for testing 310 The forward transform is the same as for `makeTwoWayPolyMap`. 311 This map does not have a reverse transform. 313 The equation is chosen for the following reasons: 314 - It is well defined for any positive value of nIn, nOut 315 - It stays small for small x, to avoid wraparound of angles for SpherePoint endpoints 318 polyMap = PolyMap(forwardCoeffs, nOut,
"IterInverse=0")
319 assert polyMap.nIn == nIn
320 assert polyMap.nOut == nOut
321 assert polyMap.hasForward
322 assert not polyMap.hasInverse
def checkMappingPersistence(self, amap, poslist)
def assertObjectsIdentical(self, obj1, obj2, checkType=True)
def makeTwoWayPolyMap(nIn, nOut)
def checkMemoryForCompoundObject(self, obj1, obj2, cmpObj, isSeries)
def checkBasicSimplify(self, amap)
def makePolyMapCoeffs(nIn, nOut)
def checkRoundTrip(self, amap, poslist, rtol=1e-05, atol=1e-08)
daf::base::PropertyList * list
def makeForwardPolyMap(nIn, nOut)
def checkPersistence(self, obj, typeFromChannel=None)