Coverage for tests/test_gaussianProcess.py: 2%
1236 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-22 03:22 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-22 03:22 -0800
1#
2# LSST Data Management System
3# Copyright 2008, 2009, 2010 LSST Corporation.
4#
5# This product includes software developed by the
6# LSST Project (http://www.lsst.org/).
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the LSST License Statement and
19# the GNU General Public License along with this program. If not,
20# see < http://www.lsstcorp.org/LegalNotices/ > .
21#
23import os
24import unittest
26import numpy as np
28import lsst.utils.tests
29import lsst.afw.math as afwMath
30import lsst.pex.exceptions as pex
32testPath = os.path.abspath(os.path.dirname(__file__))
35class KdTreeGaussianProcessTestCase(lsst.utils.tests.TestCase):
37 def testKdTreeGetData(self):
38 """
39 Test that KdTree.getData() throws exceptions when it should and returns
40 the correct data when it should.
41 """
42 rng = np.random.RandomState(112)
43 data = rng.random_sample((10, 10))
44 kd = afwMath.KdTreeD()
45 kd.Initialize(data)
47 # test that an exception is thrown if you ask for a point with
48 # a negative index
49 with self.assertRaises(RuntimeError) as context:
50 kd.getData(-1, 0)
51 self.assertIn("Asked for point that does not exist",
52 context.exception.args[0])
54 # test that an exception is thrown if you ask for a point beyond
55 # the number of points stored in the tree
56 with self.assertRaises(RuntimeError) as context:
57 kd.getData(10, 0)
58 self.assertIn("Asked for point that does not exist",
59 context.exception.args[0])
61 # test that an exception is thrown if you ask for dimensions that
62 # don't exist
63 with self.assertRaises(RuntimeError) as context:
64 kd.getData(0, -1)
65 self.assertIn("points of that many dimensions",
66 context.exception.args[0])
68 with self.assertRaises(RuntimeError) as context:
69 kd.getData(0, 10)
70 self.assertIn("points of that many dimensions",
71 context.exception.args[0])
73 # test that the correct values are returned when they should be
74 for ix in range(10):
75 for iy in range(10):
76 self.assertAlmostEqual(
77 data[ix][iy], kd.getData(ix, iy), places=10)
79 def testKdTreeGetDataVec(self):
80 """
81 Test that KdTree.getData(int) throws exceptions when it should and returns
82 the correct data when it should.
83 """
84 rng = np.random.RandomState(112)
85 data = rng.random_sample((10, 10))
86 kd = afwMath.KdTreeD()
87 kd.Initialize(data)
89 # test that an exception is thrown if you ask for a point with
90 # a negative index
91 with self.assertRaises(RuntimeError) as context:
92 kd.getData(-1)
93 self.assertIn("point that does not exist",
94 context.exception.args[0])
96 # test that an exception is thrown if you ask for a point beyond
97 # the number of points stored in the tree
98 with self.assertRaises(RuntimeError) as context:
99 kd.getData(10)
100 self.assertIn("point that does not exist",
101 context.exception.args[0])
103 # test that the correct values are returned when they should be
104 for ix in range(10):
105 vv = kd.getData(ix)
106 for iy in range(10):
107 self.assertAlmostEqual(data[ix][iy], vv[iy], places=10)
109 def testKdTreeNeighborExceptions(self):
110 """
111 This test will test that KdTree throws exceptions when you ask it for
112 nonsensical number of nearest neighbors.
113 """
114 rng = np.random.RandomState(112)
115 data = rng.random_sample((10, 10))
116 kd = afwMath.KdTreeD()
117 kd.Initialize(data)
118 pt = rng.random_sample(10).astype(float)
119 neighdex = np.zeros((5), dtype=np.int32)
120 distances = np.zeros((5), dtype=float)
122 # ask for a negative number of neighbors
123 with self.assertRaises(RuntimeError) as context:
124 kd.findNeighbors(neighdex, distances, pt, -2)
125 self.assertIn("zero or a negative number of neighbors",
126 context.exception.args[0])
128 # ask for zero neighbors
129 with self.assertRaises(RuntimeError) as context:
130 kd.findNeighbors(neighdex, distances, pt, 0)
131 self.assertIn("zero or a negative number of neighbors",
132 context.exception.args[0])
134 # ask for more neighbors than you have data
135 with self.assertRaises(RuntimeError) as context:
136 kd.findNeighbors(neighdex, distances, pt, 11)
137 self.assertIn("more neighbors than kd tree contains",
138 context.exception.args[0])
140 # try sending neighdex of wrong size
141 neighdex_bad = np.zeros((1), dtype=np.int32)
142 with self.assertRaises(RuntimeError) as context:
143 kd.findNeighbors(neighdex_bad, distances, pt, 5)
144 self.assertIn("Size of neighdex",
145 context.exception.args[0])
147 # try sending distances array of wrong size
148 distances_bad = np.zeros((1), dtype=float)
149 with self.assertRaises(RuntimeError) as context:
150 kd.findNeighbors(neighdex, distances_bad, pt, 5)
151 self.assertIn("Size of dd",
152 context.exception.args[0])
154 # run something that works
155 kd.findNeighbors(neighdex, distances, pt, 5)
157 def testKdTree(self):
158 """
159 This test will test the construction of KdTree in the pathological case
160 where many of the input data points are identical.
161 """
162 pp = 100
163 dd = 5
164 data = np.zeros((pp, dd), dtype=float)
165 tol = 1.0e-10
167 with open(os.path.join(testPath, "data", "kd_test_data.sav"), "r") as f:
168 ff = f.readlines()
170 for i in range(len(ff)):
171 s = ff[i].split()
172 for j in range(dd):
173 data[i][j] = float(s[j])
175 kd = afwMath.KdTreeD()
177 kd.Initialize(data)
179 kds = afwMath.KdTreeD()
181 kds.Initialize(data)
183 kds.removePoint(2)
185 worstErr = -1.0
186 for i in range(100):
187 if i > 2:
188 dd = 0.0
189 for j in range(5):
190 dd = dd+(kd.getData(i, j)-kds.getData(i-1, j)) * \
191 (kd.getData(i, j)-kds.getData(i-1, j))
192 if dd > worstErr:
193 worstErr = dd
194 self.assertLess(worstErr, tol)
196 kd.removePoint(2)
198 kds.removePoint(10)
200 for i in range(99):
201 if i > 10:
202 dd = 0.0
203 for j in range(5):
204 dd = dd+(kd.getData(i, j)-kds.getData(i-1, j)) * \
205 (kd.getData(i, j)-kds.getData(i-1, j))
206 if dd > worstErr:
207 worstErr = dd
208 self.assertLess(worstErr, tol)
210 kd.removePoint(10)
212 kds.removePoint(21)
214 for i in range(98):
215 if i > 21:
216 dd = 0.0
217 for j in range(5):
218 dd = dd+(kd.getData(i, j)-kds.getData(i-1, j)) * \
219 (kd.getData(i, j)-kds.getData(i-1, j))
220 if dd > worstErr:
221 worstErr = dd
222 self.assertLess(worstErr, tol)
223 print("\nworst distance error in kdTest ", worstErr, "\n")
225 def testKdTreeNeighbors(self):
226 """
227 Test that KdTree.findNeighbors() does find the nearest neighbors
228 """
229 rng = np.random.RandomState(112)
230 data = rng.random_sample((10, 10))
231 kd = afwMath.KdTreeD()
232 kd.Initialize(data)
233 pt = rng.random_sample(10).astype(float)
234 neighdex = np.zeros((5), dtype=np.int32)
235 distances = np.zeros((5), dtype=float)
236 kd.findNeighbors(neighdex, distances, pt, 5)
238 # check that the distances to the nearest neighbors are
239 # correctly reported
240 for ix in range(len(neighdex)):
241 dd_true = np.sqrt(np.power(pt - data[neighdex[ix]], 2).sum())
242 self.assertAlmostEqual(dd_true, distances[ix], places=10)
244 # check that the distances are returned in ascending order
245 for ix in range(len(distances)-1):
246 self.assertGreaterEqual(distances[ix+1], distances[ix])
248 # check that the actual nearest neighbors were found
249 dd_true = np.sqrt(np.power(pt-data, 2).sum(axis=1))
250 sorted_dexes = np.argsort(dd_true)
251 for ix in range(len(neighdex)):
252 self.assertEqual(neighdex[ix], sorted_dexes[ix])
254 def testKdTreeAddPoint(self):
255 """
256 Test the behavior of KdTree.addPoint
257 """
258 data = np.array([[1.0, 0.0, 2.0], [1.1, 2.5, 0.0], [4.5, 6.1, 0.0]])
259 kd = afwMath.KdTreeD()
260 kd.Initialize(data)
262 # test that, if you try to add an improperly-sized point, an exception
263 # is thrown
264 with self.assertRaises(RuntimeError) as context:
265 kd.addPoint(np.array([1.1]*2))
266 self.assertIn("incorrect dimensionality",
267 context.exception.args[0])
269 with self.assertRaises(RuntimeError) as context:
270 kd.addPoint(np.array([1.1]*4))
271 self.assertIn("incorrect dimensionality",
272 context.exception.args[0])
274 # test that adding a correctly sized-point works
275 # (i.e. that the new point is added to the tree's data)
276 kd.addPoint(np.array([1.1]*3))
278 self.assertEqual(kd.getNPoints(), 4)
279 for ix in range(3):
280 for iy in range(3):
281 self.assertAlmostEqual(
282 data[ix][iy], kd.getData(ix, iy), places=10)
284 for ix in range(3):
285 self.assertAlmostEqual(kd.getData(3, ix), 1.1, places=10)
287 # check that the new point is accounted for in findNeighbors()
288 neighdex = np.ones(2, dtype=np.int32)
289 distances = np.ones(2, dtype=float)
290 vv = np.array([1.2]*3)
291 kd.findNeighbors(neighdex, distances, vv, 2)
292 self.assertEqual(neighdex[0], 3)
293 self.assertEqual(neighdex[1], 0)
295 def testKdTreeRemovePoint(self):
296 """
297 Test the behavior of KdTree.removePoint()
298 """
299 data = np.array([[1.5, 1.5, 1.5], [2.0, 2.0, 2.0],
300 [4.0, 4.0, 4.0], [3.0, 3.0, 3.0]])
301 kd = afwMath.KdTreeD()
302 kd.Initialize(data)
303 self.assertEqual(kd.getNPoints(), 4)
305 # test that an exception is raised if you try to remove a non-existent
306 # point
307 with self.assertRaises(RuntimeError) as context:
308 kd.removePoint(-1)
309 self.assertIn("point that doesn't exist",
310 context.exception.args[0])
312 with self.assertRaises(RuntimeError) as context:
313 kd.removePoint(4)
314 self.assertIn("point that doesn't exist",
315 context.exception.args[0])
317 # test that things work correctly when you do remove a point
318 kd.removePoint(1)
319 self.assertEqual(kd.getNPoints(), 3)
320 for ix in range(3):
321 self.assertAlmostEqual(kd.getData(0, ix), 1.5, places=10)
322 self.assertAlmostEqual(kd.getData(1, ix), 4.0, places=10)
323 self.assertAlmostEqual(kd.getData(2, ix), 3.0, places=10)
325 neighdex = np.zeros(2, dtype=np.int32)
326 distances = np.zeros(2, dtype=float)
327 kd.findNeighbors(neighdex, distances, np.array([2.0, 2.0, 2.0]), 2)
328 self.assertEqual(neighdex[0], 0)
329 self.assertEqual(neighdex[1], 2)
331 # test that an exception is raised when you try to remove the last
332 # point
333 kd.removePoint(0)
334 kd.removePoint(0)
335 with self.assertRaises(RuntimeError) as context:
336 kd.removePoint(0)
337 self.assertIn("There is only one point",
338 context.exception.args[0])
340 def testKdTreeGetTreeNode(self):
341 """
342 Test that KdTree.GetTreeNode raises exceptions if you give it bad inputs
343 """
344 data = np.array([[1.5, 1.5, 1.5], [2.0, 2.0, 2.0],
345 [4.0, 4.0, 4.0], [3.0, 3.0, 3.0]])
346 kd = afwMath.KdTreeD()
347 kd.Initialize(data)
349 vv = np.ones(4, dtype=np.int32)
350 vv_small = np.ones(1, dtype=np.int32)
351 vv_large = np.ones(5, dtype=np.int32)
353 with self.assertRaises(RuntimeError) as context:
354 kd.getTreeNode(vv_small, 0)
355 self.assertIn("Need to pass a 4-element",
356 context.exception.args[0])
358 with self.assertRaises(RuntimeError) as context:
359 kd.getTreeNode(vv_large, 0)
360 self.assertIn("Need to pass a 4-element",
361 context.exception.args[0])
363 with self.assertRaises(RuntimeError) as context:
364 kd.getTreeNode(vv, -1)
365 self.assertIn("point that does not exist",
366 context.exception.args[0])
368 with self.assertRaises(RuntimeError) as context:
369 kd.getTreeNode(vv, 4)
370 self.assertIn("point that does not exist",
371 context.exception.args[0])
373 # make sure that a call with good inputs passes
374 kd.getTreeNode(vv, 0)
377class GaussianProcessTestCase(lsst.utils.tests.TestCase):
379 def testConstructorExceptions(self):
380 """
381 Test that exceptions are raised when constructor is given
382 improper inputs
383 """
384 rng = np.random.RandomState(22)
386 # when you pass a different number of data points and function
387 # values in
388 data = rng.random_sample((10, 4))
389 fn_values = rng.random_sample(11)
390 with self.assertRaises(RuntimeError) as context:
391 afwMath.GaussianProcessD(
392 data, fn_values, afwMath.SquaredExpCovariogramD())
393 self.assertIn("did not pass in the same number",
394 context.exception.args[0])
396 max_val = np.ones(4)
397 min_val = np.ones(4)
398 with self.assertRaises(RuntimeError) as context:
399 afwMath.GaussianProcessD(data, min_val, max_val, fn_values,
400 afwMath.SquaredExpCovariogramD())
401 self.assertIn("did not pass in the same number",
402 context.exception.args[0])
404 many_fn_values = rng.random_sample((11, 3))
405 with self.assertRaises(RuntimeError) as context:
406 afwMath.GaussianProcessD(
407 data, many_fn_values, afwMath.SquaredExpCovariogramD())
408 self.assertIn("did not pass in the same number",
409 context.exception.args[0])
411 with self.assertRaises(RuntimeError) as context:
412 afwMath.GaussianProcessD(data, min_val, max_val, many_fn_values,
413 afwMath.SquaredExpCovariogramD())
414 self.assertIn("did not pass in the same number",
415 context.exception.args[0])
417 fn_values = rng.random_sample(data.shape[0])
418 many_fn_values = rng.random_sample((10, 3))
420 # when you pass in improperly sized min and max val arrays
421 bad_max_val = np.ones(3)
422 bad_min_val = np.zeros(3)
423 with self.assertRaises(RuntimeError) as context:
424 afwMath.GaussianProcessD(data, bad_min_val, max_val,
425 fn_values, afwMath.SquaredExpCovariogramD())
426 self.assertIn("min/max values have different dimensionality",
427 context.exception.args[0])
429 with self.assertRaises(RuntimeError) as context:
430 afwMath.GaussianProcessD(data, min_val, bad_max_val,
431 fn_values, afwMath.SquaredExpCovariogramD())
432 self.assertIn("min/max values have different dimensionality",
433 context.exception.args[0])
435 with self.assertRaises(RuntimeError) as context:
436 afwMath.GaussianProcessD(data, bad_min_val, max_val,
437 many_fn_values, afwMath.SquaredExpCovariogramD())
438 self.assertIn("min/max values have different dimensionality",
439 context.exception.args[0])
441 with self.assertRaises(RuntimeError) as context:
442 afwMath.GaussianProcessD(data, min_val, bad_max_val,
443 many_fn_values, afwMath.SquaredExpCovariogramD())
444 self.assertIn("min/max values have different dimensionality",
445 context.exception.args[0])
447 # check that the constructor runs when it should
448 afwMath.GaussianProcessD(
449 data, fn_values, afwMath.SquaredExpCovariogramD())
451 afwMath.GaussianProcessD(data, min_val, max_val, fn_values,
452 afwMath.SquaredExpCovariogramD())
454 afwMath.GaussianProcessD(data, many_fn_values,
455 afwMath.SquaredExpCovariogramD())
457 afwMath.GaussianProcessD(data, min_val, max_val, many_fn_values,
458 afwMath.SquaredExpCovariogramD())
460 def testGetDataExceptions(self):
461 """
462 Test that getData() returns exceptions on bad input
463 """
464 rng = np.random.RandomState(111)
465 data = rng.random_sample((14, 3))
466 fn = rng.random_sample(14)
467 gp = afwMath.GaussianProcessD(
468 data, fn, afwMath.SquaredExpCovariogramD())
469 indices = np.array([0, 5, 7], dtype=np.int32)
470 indices_bad = np.array([0, 5, 16], dtype=np.int32)
471 fn_out_good = np.zeros(3)
472 fn_out_bad = np.zeros(4)
473 pts_out_good = np.zeros((3, 3))
474 pts_out_bad_ct = np.zeros((5, 3))
475 pts_out_bad_dim = np.zeros((3, 7))
477 # check that an exception is raised if we pass in an invalid
478 # index
479 with self.assertRaises(RuntimeError) as context:
480 gp.getData(pts_out_good, fn_out_good, indices_bad)
481 self.assertIn("point that does not exist",
482 context.exception.args[0])
484 # check that an exception is raised if pts_out asks for
485 # the wrong number of points
486 with self.assertRaises(RuntimeError) as context:
487 gp.getData(pts_out_bad_ct, fn_out_good, indices)
488 self.assertIn("enough room in your pts array",
489 context.exception.args[0])
491 # check that an exception is raised if pts_out expects
492 # points of the wrong dimensionality
493 with self.assertRaises(RuntimeError) as context:
494 gp.getData(pts_out_bad_dim, fn_out_good, indices)
495 self.assertIn("points of the wrong dimensionality",
496 context.exception.args[0])
498 # check that an exception is raised if fn_out expects
499 # the wrong number of points
500 with self.assertRaises(RuntimeError) as context:
501 gp.getData(pts_out_good, fn_out_bad, indices)
502 self.assertIn("room in your function value array",
503 context.exception.args[0])
505 # check that getData runs safely when given good input
506 gp.getData(pts_out_good, fn_out_good, indices)
508 fn_many = rng.random_sample((14, 5))
509 gp_many = afwMath.GaussianProcessD(
510 data, fn_many, afwMath.SquaredExpCovariogramD())
512 # check that a GaussianProcess with many functions throws an
513 # exception when you try to run getData designed for just one
514 # function
515 with self.assertRaises(RuntimeError) as context:
516 gp_many.getData(pts_out_good, fn_out_good, indices)
517 self.assertIn("enough room for all of the functions",
518 context.exception.args[0])
520 # now test on a GaussianProcess with many functions
522 fn_out_good = np.zeros((3, 5))
523 fn_out_bad_ct = np.zeros((4, 5))
524 fn_out_bad_fn = np.zeros((3, 6))
526 # check that an exception is raised when pts_out expects
527 # the wrong number of points
528 with self.assertRaises(RuntimeError) as context:
529 gp_many.getData(pts_out_bad_ct, fn_out_good, indices)
530 self.assertIn("room in your pts array",
531 context.exception.args[0])
533 # check that an exception is raised when pts_out expects
534 # pts of the wrong dimensionality
535 with self.assertRaises(RuntimeError) as context:
536 gp_many.getData(pts_out_bad_dim, fn_out_good, indices)
537 self.assertIn("points of the wrong dimensionality",
538 context.exception.args[0])
540 # check that an exception is raised when fn_out expects the
541 # wrong number of pts
542 with self.assertRaises(RuntimeError) as context:
543 gp_many.getData(pts_out_good, fn_out_bad_ct, indices)
544 self.assertIn("room in your function value array",
545 context.exception.args[0])
547 # check that an exception is raised when fn_out expects the
548 # wrong number of functions
549 with self.assertRaises(RuntimeError) as context:
550 gp_many.getData(pts_out_good, fn_out_bad_fn, indices)
551 self.assertIn("enough room for all of the functions",
552 context.exception.args[0])
554 # check that an exception is raised when one of the indices is
555 # invalid
556 with self.assertRaises(RuntimeError) as context:
557 gp_many.getData(pts_out_good, fn_out_good, indices_bad)
558 self.assertIn("point that does not exist",
559 context.exception.args[0])
561 # check that getData runs safely when given good input
562 gp_many.getData(pts_out_good, fn_out_good, indices)
564 def testGetData(self):
565 """
566 Test that getData actually returns what you expect
567 """
568 rng = np.random.RandomState(131)
569 data = rng.random_sample((14, 3))
570 fn = rng.random_sample(14)
571 gp = afwMath.GaussianProcessD(
572 data, fn, afwMath.SquaredExpCovariogramD())
573 pts_out = np.zeros((4, 3))
574 fn_out = np.zeros(4)
575 indices = np.array([4, 1, 12, 8], dtype=np.int32)
576 gp.getData(pts_out, fn_out, indices)
578 for ii in range(len(indices)):
579 self.assertAlmostEqual(fn_out[ii], fn[indices[ii]], 10)
580 for jj in range(3):
581 self.assertAlmostEqual(pts_out[ii][jj], data[indices[ii]][jj])
583 # now test with a max and min array
584 max_arr = np.array([0.3]*3)
585 min_arr = np.array([0.12]*3)
586 gp = afwMath.GaussianProcessD(data, min_arr, max_arr,
587 fn, afwMath.SquaredExpCovariogramD())
589 gp.getData(pts_out, fn_out, indices)
591 for ii in range(len(indices)):
592 self.assertAlmostEqual(fn_out[ii], fn[indices[ii]], 10)
593 for jj in range(3):
594 self.assertAlmostEqual(pts_out[ii][jj], data[indices[ii]][jj])
596 # now test on a GaussianProcess with many functions
597 fn_many = rng.random_sample((14, 6))
598 fn_out = np.zeros((4, 6))
599 gp = afwMath.GaussianProcessD(
600 data, fn_many, afwMath.SquaredExpCovariogramD())
602 gp.getData(pts_out, fn_out, indices)
604 for ii in range(len(indices)):
605 for jj in range(6):
606 self.assertAlmostEqual(
607 fn_out[ii][jj], fn_many[indices[ii]][jj], 10)
608 for jj in range(3):
609 self.assertAlmostEqual(pts_out[ii][jj], data[indices[ii]][jj])
611 # with min and max array
612 gp = afwMath.GaussianProcessD(data, min_arr, max_arr,
613 fn_many, afwMath.SquaredExpCovariogramD())
615 gp.getData(pts_out, fn_out, indices)
617 for ii in range(len(indices)):
618 for jj in range(6):
619 self.assertAlmostEqual(
620 fn_out[ii][jj], fn_many[indices[ii]][jj], 10)
621 for jj in range(3):
622 self.assertAlmostEqual(pts_out[ii][jj], data[indices[ii]][jj])
624 def testInterpolateExceptions(self):
625 """
626 Test that interpolate() raises exceptions when given improper
627 arguments
628 """
629 rng = np.random.RandomState(88)
630 data = rng.random_sample((13, 5))
631 fn = rng.random_sample(13)
632 many_fn = rng.random_sample((13, 3))
633 gg = afwMath.GaussianProcessD(
634 data, fn, afwMath.SquaredExpCovariogramD())
635 gg_many = afwMath.GaussianProcessD(
636 data, many_fn, afwMath.SquaredExpCovariogramD())
638 var = np.zeros(1)
640 many_var = np.zeros(3)
641 many_mu = np.zeros(3)
643 # test that an exception is raised if you try to interpolate at
644 # a point with an incorrect number of dimensions
645 bad_pt = rng.random_sample(3)
646 with self.assertRaises(RuntimeError) as context:
647 gg.interpolate(var, bad_pt, 5)
648 self.assertIn("point with different dimensionality",
649 context.exception.args[0])
651 with self.assertRaises(RuntimeError) as context:
652 gg_many.interpolate(many_mu, many_var, bad_pt, 5)
653 self.assertIn("point with different dimensionality",
654 context.exception.args[0])
656 good_pt = rng.random_sample(5)
658 # test that an exception is raised if you try to ask for an improper
659 # number of nearest neighbors when interpolating
660 with self.assertRaises(RuntimeError) as context:
661 gg.interpolate(var, good_pt, 0)
662 self.assertIn("zero or negative number of neighbors",
663 context.exception.args[0])
665 with self.assertRaises(RuntimeError) as context:
666 gg.interpolate(var, good_pt, -1)
667 self.assertIn("zero or negative number of neighbors",
668 context.exception.args[0])
670 with self.assertRaises(RuntimeError) as context:
671 gg.interpolate(var, good_pt, 14)
672 self.assertIn("more neighbors than you have",
673 context.exception.args[0])
675 with self.assertRaises(RuntimeError) as context:
676 gg_many.interpolate(many_mu, many_var, good_pt, 0)
677 self.assertIn("zero or negative number of neighbors",
678 context.exception.args[0])
680 with self.assertRaises(RuntimeError) as context:
681 gg_many.interpolate(many_mu, many_var, good_pt, -1)
682 self.assertIn("zero or negative number of neighbors",
683 context.exception.args[0])
685 with self.assertRaises(RuntimeError) as context:
686 gg_many.interpolate(many_mu, many_var, good_pt, 14)
687 self.assertIn("more neighbors than you have",
688 context.exception.args[0])
690 # make sure that a Gaussian Process interpolating many functions
691 # does not let you call the interpolate() method that returns
692 # a scalar
693 with self.assertRaises(RuntimeError) as context:
694 gg_many.interpolate(many_var, good_pt, 4)
695 self.assertIn("You need to call the version",
696 context.exception.args[0])
698 # test that the many-function interpolate throws an exception
699 # on improperly-sized mu and variance arrays
700 bad_var = np.zeros(6)
701 bad_mu = np.zeros(6)
703 with self.assertRaises(RuntimeError) as context:
704 gg_many.interpolate(bad_mu, many_var, good_pt, 5)
705 self.assertIn("mu and/or var arrays are improperly sized",
706 context.exception.args[0])
708 with self.assertRaises(RuntimeError) as context:
709 gg_many.interpolate(many_mu, bad_var, good_pt, 5)
710 self.assertIn("mu and/or var arrays are improperly sized",
711 context.exception.args[0])
713 # if you try to pass a variance array with len != 1 to
714 # the single value interpolate()
715 with self.assertRaises(RuntimeError) as context:
716 gg.interpolate(many_var, good_pt, 5)
717 self.assertIn("variance array is the incorrect size",
718 context.exception.args[0])
720 gg.interpolate(var, good_pt, 5)
721 gg_many.interpolate(many_mu, many_var, good_pt, 5)
723 def testSelfInterpolateExceptions(self):
724 """
725 Test that selfInterpolate raises exceptions on bad arguments.
726 """
727 rng = np.random.RandomState(632)
728 data = rng.random_sample((15, 4))
729 fn = rng.random_sample(15)
730 gg = afwMath.GaussianProcessD(
731 data, fn, afwMath.SquaredExpCovariogramD())
732 many_fn = rng.random_sample((15, 3))
733 gg_many = afwMath.GaussianProcessD(
734 data, many_fn, afwMath.SquaredExpCovariogramD())
736 var_good = np.zeros(3)
737 mu_good = np.zeros(3)
739 var_bad = np.zeros(5)
740 mu_bad = np.zeros(5)
742 # test that an exception is raised when you try to use scalar
743 # selfInterpolation() on a many-function GaussianProcess
744 with self.assertRaises(RuntimeError) as context:
745 gg_many.selfInterpolate(var_good, 11, 6)
746 self.assertIn("that accepts mu and variance array",
747 context.exception.args[0])
749 # test that an exception is raised when you pass a var_array that is
750 # too large into a scalar GaussianProcess
751 with self.assertRaises(RuntimeError) as context:
752 gg.selfInterpolate(var_good, 11, 6)
753 self.assertIn("variance array is the incorrect size",
754 context.exception.args[0])
756 # test that an exception is thrown when you pass in improperly-sized
757 # mu and/or var arrays
758 with self.assertRaises(RuntimeError) as context:
759 gg_many.selfInterpolate(mu_good, var_bad, 11, 6)
760 self.assertIn("mu and/or var arrays are improperly sized",
761 context.exception.args[0])
763 with self.assertRaises(RuntimeError) as context:
764 gg_many.selfInterpolate(mu_bad, var_good, 11, 6)
765 self.assertIn("mu and/or var arrays are improperly sized",
766 context.exception.args[0])
768 # make surethat selfInterpolate runs when it should
769 gg_many.selfInterpolate(mu_good, var_good, 11, 6)
770 var_one = np.zeros(1)
771 gg.selfInterpolate(var_one, 11, 6)
773 def testBatchInterpolateExceptions(self):
774 """
775 Test that batchInterpolate() throws exceptions on bad input
776 """
777 rng = np.random.RandomState(88)
778 rng = np.random.RandomState(632)
779 data = rng.random_sample((15, 4))
780 fn = rng.random_sample(15)
781 gg = afwMath.GaussianProcessD(
782 data, fn, afwMath.SquaredExpCovariogramD())
784 pts_good = rng.random_sample((11, 4))
785 pts_bad = rng.random_sample((11, 3))
786 mu_good = np.zeros(11)
787 mu_bad = np.zeros(9)
788 var_good = np.zeros(11)
789 var_bad = np.zeros(9)
791 # test for exception on points of incorrect size
792 with self.assertRaises(RuntimeError) as context:
793 gg.batchInterpolate(mu_good, var_good, pts_bad)
794 self.assertIn("wrong dimensionality",
795 context.exception.args[0])
797 with self.assertRaises(RuntimeError) as context:
798 gg.batchInterpolate(mu_good, pts_bad)
799 self.assertIn("wrong dimensionality",
800 context.exception.args[0])
802 # test for exception on output arrays of incorrect size
803 with self.assertRaises(RuntimeError) as context:
804 gg.batchInterpolate(mu_bad, var_good, pts_good)
805 self.assertIn("do not have room for all of the points",
806 context.exception.args[0])
808 with self.assertRaises(RuntimeError) as context:
809 gg.batchInterpolate(mu_bad, pts_good)
810 self.assertIn("does not have enough room for all of the points",
811 context.exception.args[0])
813 with self.assertRaises(RuntimeError) as context:
814 gg.batchInterpolate(mu_good, var_bad, pts_good)
815 self.assertIn("do not have room",
816 context.exception.args[0])
818 # test that it runs properly with good inputs
819 gg.batchInterpolate(mu_good, var_good, pts_good)
820 gg.batchInterpolate(mu_good, pts_good)
822 fn_many = rng.random_sample((15, 6))
823 gg_many = afwMath.GaussianProcessD(
824 data, fn_many, afwMath.SquaredExpCovariogramD())
826 # test that a GaussianProcess on many functions raises an exception
827 # when you call batchInterpolate with output arrays that only have
828 # room for one function
829 with self.assertRaises(RuntimeError) as context:
830 gg_many.batchInterpolate(mu_good, var_good, pts_good)
831 self.assertIn("do not have room for all of the functions",
832 context.exception.args[0])
834 with self.assertRaises(RuntimeError) as context:
835 gg_many.batchInterpolate(mu_good, pts_good)
836 self.assertIn("does not have enough room for all of the functions",
837 context.exception.args[0])
839 mu_good = np.zeros((11, 6))
840 mu_bad_fn = np.zeros((11, 5))
841 mu_bad_pts = np.zeros((10, 6))
842 var_good = np.zeros((11, 6))
843 var_bad_fn = np.zeros((11, 5))
844 var_bad_pts = np.zeros((10, 6))
846 # test that a Gaussian Process on many functions raises an exception
847 # when you try to interpolate on points of the wrong dimensionality
848 with self.assertRaises(RuntimeError) as context:
849 gg_many.batchInterpolate(mu_good, var_good, pts_bad)
850 self.assertIn("wrong dimensionality",
851 context.exception.args[0])
853 with self.assertRaises(RuntimeError) as context:
854 gg_many.batchInterpolate(mu_good, pts_bad)
855 self.assertIn("do not have the correct dimensionality",
856 context.exception.args[0])
858 # test that a Gaussian Process on many functions rases an exception
859 # when the output arrays are of the wrong size
860 with self.assertRaises(RuntimeError) as context:
861 gg_many.batchInterpolate(mu_bad_fn, var_good, pts_good)
862 self.assertIn("do not have room for all of the functions",
863 context.exception.args[0])
865 with self.assertRaises(RuntimeError) as context:
866 gg_many.batchInterpolate(mu_bad_pts, var_good, pts_good)
867 self.assertIn("do not have room for all of the points",
868 context.exception.args[0])
870 with self.assertRaises(RuntimeError) as context:
871 gg_many.batchInterpolate(mu_bad_pts, pts_good)
872 self.assertIn("does not have enough room for all of the points",
873 context.exception.args[0])
875 with self.assertRaises(RuntimeError) as context:
876 gg_many.batchInterpolate(mu_bad_fn, pts_good)
877 self.assertIn("does not have enough room for all of the functions",
878 context.exception.args[0])
880 with self.assertRaises(RuntimeError) as context:
881 gg_many.batchInterpolate(mu_good, var_bad_fn, pts_good)
882 self.assertIn("do not have room for all of the functions",
883 context.exception.args[0])
885 with self.assertRaises(RuntimeError) as context:
886 gg_many.batchInterpolate(mu_good, var_bad_pts, pts_good)
887 self.assertIn("do not have room for all of the points",
888 context.exception.args[0])
890 # check that a Gaussian Process on many functions runs properly
891 # when given good inputs
892 gg_many.batchInterpolate(mu_good, var_good, pts_good)
893 gg_many.batchInterpolate(mu_good, pts_good)
895 def testTooManyNeighbors(self):
896 """
897 Test that GaussianProcess checks if too many neighbours are requested
898 """
899 nData = 100 # number of data points
900 dimen = 10 # dimension of each point
901 data = np.zeros((nData, dimen))
902 fn = np.zeros(nData)
903 gg = afwMath.GaussianProcessD(
904 data, fn, afwMath.SquaredExpCovariogramD())
905 test = np.zeros(dimen)
906 sigma = np.empty(1)
907 mu_arr = np.empty(1)
909 with self.assertRaises(pex.Exception) as context:
910 gg.interpolate(sigma, test, 2*nData)
911 self.assertIn("more neighbors than",
912 context.exception.args[0])
914 with self.assertRaises(pex.Exception) as context:
915 gg.interpolate(sigma, test, -5)
916 self.assertIn("zero or negative number of neighbors",
917 context.exception.args[0])
919 with self.assertRaises(pex.Exception) as context:
920 gg.selfInterpolate(sigma, 0, 2*nData)
921 self.assertIn("more neighbors than",
922 context.exception.args[0])
924 with self.assertRaises(pex.Exception) as context:
925 gg.selfInterpolate(sigma, 0, -5)
926 self.assertIn("zero or negative number of neighbors",
927 context.exception.args[0])
929 with self.assertRaises(pex.Exception) as context:
930 gg.selfInterpolate(sigma, -1, nData-1)
931 self.assertIn("point that does not exist",
932 context.exception.args[0])
934 with self.assertRaises(pex.Exception) as context:
935 gg.selfInterpolate(sigma, nData, nData-1)
936 self.assertIn("point that does not exist",
937 context.exception.args[0])
939 with self.assertRaises(RuntimeError) as context:
940 gg.interpolate(mu_arr, sigma, 2*nData)
941 self.assertIn("more neighbors than",
942 context.exception.args[0])
944 with self.assertRaises(pex.Exception) as context:
945 gg.interpolate(mu_arr, sigma, 2*nData)
946 self.assertIn("more neighbors than",
947 context.exception.args[0])
949 with self.assertRaises(pex.Exception) as context:
950 gg.interpolate(mu_arr, sigma, -5)
951 self.assertIn("zero or negative number of neighbors",
952 context.exception.args[0])
954 def testInterpolate(self):
955 """
956 This will test GaussianProcess.interpolate using both the squared
957 exponential covariogram and the neural network covariogram on data
958 that was generated with known answers.
960 The test will check that the code returns the correct values of both
961 mu (interpolated function value) and sig2 (the variance)
963 This test uses the GaussianProcess constructor that does not normalize
964 coordinate values with minima and maxima.
965 """
967 pp = 2000 # number of data points
968 dd = 10 # number of dimensions
969 kk = 15 # number of nearest neighbors being used
970 tol = 1.0e-3 # the largest relative error that will be tolerated
972 data = np.zeros((pp, dd), dtype=float) # input data points
973 fn = np.zeros((pp), dtype=float) # input function values
974 test = np.zeros((dd), dtype=float) # query points
975 sigma = np.zeros((1), dtype=float) # variance
977 xx = afwMath.SquaredExpCovariogramD()
978 xx.setEllSquared(100.0)
980 # read in the input data
981 with open(os.path.join(testPath, "data", "gp_exp_covar_data.sav"), "r") as f:
982 ff = f.readlines()
984 for i in range(len(ff)):
985 s = ff[i].split()
986 fn[i] = float(s[10])
987 for j in range(10):
988 data[i][j] = float(s[j])
990 # first try the squared exponential covariogram (the default)
991 try:
992 gg = afwMath.GaussianProcessD(data, fn, xx)
993 except pex.Exception as e:
994 print(e.what())
996 gg.setLambda(0.001)
998 # now, read in the test points and their corresponding known solutions
999 with open(os.path.join(testPath, "data", "gp_exp_covar_solutions.sav"), "r") as f:
1000 ff = f.readlines()
1002 worstMuErr = -1.0 # keep track of the worst fractional error in mu
1003 worstSigErr = -1.0 # keep track of the worst fractional error in the variance
1005 for z in range(len(ff)):
1006 s = ff[z].split() # s will store the zth line of the solution file
1007 for i in range(dd):
1008 test[i] = float(s[i]) # read in the test point coordinates
1010 mushld = float(s[dd + kk]) # read in what mu should be
1011 # read in what the variance should be
1012 sigshld = float(s[dd + kk + 1])
1014 mu = gg.interpolate(sigma, test, kk)
1016 err = (mu - mushld)
1017 if mushld != 0.0:
1018 err = err/mushld
1020 if err < 0.0:
1021 err = -1.0 * err
1022 if z == 0 or err > worstMuErr:
1023 worstMuErr = err
1025 err = (sigma[0] - sigshld)
1026 if sigshld != 0.0:
1027 err = err/sigshld
1029 if err < 0.0:
1030 err = -1.0 * err
1031 if z == 0 or err > worstSigErr:
1032 worstSigErr = err
1034 print("\nThe errors for squared exponent covariogram\n")
1035 print("worst mu error ", worstMuErr)
1036 print("worst sig2 error ", worstSigErr)
1038 self.assertLess(worstMuErr, tol)
1039 self.assertLess(worstSigErr, tol)
1041 # now try with the Neural Network covariogram
1043 kk = 50
1045 nn = afwMath.NeuralNetCovariogramD()
1046 nn.setSigma0(1.23)
1047 nn.setSigma1(0.452)
1049 gg.setCovariogram(nn)
1050 gg.setLambda(0.0045)
1052 with open(os.path.join(testPath, "data", "gp_nn_solutions.sav"), "r") as f:
1053 ff = f.readlines()
1055 worstMuErr = -1.0
1056 worstSigErr = -1.0
1058 for z in range(len(ff)):
1059 s = ff[z].split()
1060 for i in range(dd):
1061 test[i] = float(s[i])
1063 mushld = float(s[dd + kk])
1064 sigshld = float(s[dd + kk + 1])
1066 mu = gg.interpolate(sigma, test, kk)
1068 err = (mu - mushld)
1069 if mushld != 0.0:
1070 err = err/mushld
1072 if err < 0.0:
1073 err = -1.0 * err
1074 if z == 0 or err > worstMuErr:
1075 worstMuErr = err
1077 err = (sigma[0] - sigshld)
1078 if sigshld != 0.0:
1079 err = err/sigshld
1081 if err < 0.0:
1082 err = -1.0 * err
1083 if z == 0 or err > worstSigErr:
1084 worstSigErr = err
1086 print("\nThe errors for neural net covariogram\n")
1087 print("worst mu error ", worstMuErr)
1088 print("worst sig2 error ", worstSigErr)
1090 self.assertLess(worstMuErr, tol)
1091 self.assertLess(worstSigErr, tol)
1093 def testMinMax(self):
1094 """
1095 This test will test GaussianProcess.interpolate using the constructor
1096 that normalizes data point coordinates by minima and maxima.
1098 It will only use the squared exponential covariogram (since testInterpolate() presumably
1099 tested the performance of the neural network covariogram; this test is only concerned
1100 with the alternate constructor)
1102 This test proceeds largely like testInterpolate above
1103 """
1104 pp = 2000
1105 dd = 10
1106 kk = 50
1107 tol = 1.0e-4
1108 data = np.zeros((pp, dd), dtype=float)
1109 fn = np.zeros((pp), dtype=float)
1110 test = np.zeros((dd), dtype=float)
1111 sigma = np.zeros((1), dtype=float)
1113 mins = np.zeros((dd), dtype=float)
1114 maxs = np.zeros((dd), dtype=float)
1116 nn = afwMath.NeuralNetCovariogramD()
1117 nn.setSigma0(0.555)
1118 nn.setSigma1(0.112)
1120 with open(os.path.join(testPath, "data", "gp_exp_covar_data.sav"), "r") as f:
1121 ff = f.readlines()
1123 for i in range(len(ff)):
1124 s = ff[i].split()
1125 fn[i] = float(s[10])
1126 for j in range(10):
1127 data[i][j] = float(s[j])
1129 for i in range(pp):
1130 for j in range(dd):
1131 if (i == 0) or (data[i][j] < mins[j]):
1132 mins[j] = data[i][j]
1133 if (i == 0) or (data[i][j] > maxs[j]):
1134 maxs[j] = data[i][j]
1136 mins[2] = 0.0
1137 maxs[2] = 10.0
1138 try:
1139 gg = afwMath.GaussianProcessD(data, mins, maxs, fn, nn)
1140 except pex.Exception as e:
1141 print(e.what())
1143 gg.setLambda(0.0045)
1145 with open(os.path.join(testPath, "data", "gp_minmax_solutions.sav"), "r") as f:
1146 ff = f.readlines()
1148 worstMuErr = -1.0
1149 worstSigErr = -1.0
1150 for z in range(len(ff)):
1151 s = ff[z].split()
1152 for i in range(dd):
1153 test[i] = float(s[i])
1155 mushld = float(s[dd + kk])
1156 sigshld = float(s[dd + kk + 1])
1158 mu = gg.interpolate(sigma, test, kk)
1160 err = (mu - mushld)
1161 if mushld != 0.0:
1162 err = err/mushld
1164 if err < 0.0:
1165 err = -1.0 * err
1166 if z == 0 or err > worstMuErr:
1167 worstMuErr = err
1169 err = (sigma[0] - sigshld)
1170 if sigshld != 0.0:
1171 err = err/sigshld
1173 if err < 0.0:
1174 err = -1.0 * err
1175 if z == 0 or err > worstSigErr:
1176 worstSigErr = err
1178 print("\nThe errors for Gaussian process using min-max normalization\n")
1179 print("worst mu error ", worstMuErr)
1180 print("worst sig2 error ", worstSigErr)
1182 self.assertLess(worstMuErr, tol)
1183 self.assertLess(worstSigErr, tol)
1185 def testAddPointExceptions(self):
1186 """
1187 Test that addPoint() raises exceptions when it should
1188 """
1189 rng = np.random.RandomState(44)
1190 data = rng.random_sample((10, 3))
1191 fn = rng.random_sample(10)
1192 gg = afwMath.GaussianProcessD(
1193 data, fn, afwMath.SquaredExpCovariogramD())
1194 fn_many = rng.random_sample((10, 5))
1195 gg_many = afwMath.GaussianProcessD(
1196 data, fn_many, afwMath.SquaredExpCovariogramD())
1198 pt_good = rng.random_sample(3)
1199 pt_bad = rng.random_sample(6)
1200 fn_good = rng.random_sample(5)
1201 fn_bad = rng.random_sample(4)
1203 # test that, when you add a point of the wrong dimensionality,
1204 # an exception is raised
1205 with self.assertRaises(RuntimeError) as context:
1206 gg.addPoint(pt_bad, 5.0)
1207 self.assertIn("dimensionality",
1208 context.exception.args[0])
1210 with self.assertRaises(RuntimeError) as context:
1211 gg.addPoint(pt_bad, fn_good)
1212 self.assertIn("dimensionality",
1213 context.exception.args[0])
1215 # test that a GaussianProcess on many functions raises an exception
1216 # when you try to add a point with just one function value
1217 with self.assertRaises(RuntimeError) as context:
1218 gg_many.addPoint(pt_good, 5.0)
1219 self.assertIn("calling the wrong addPoint",
1220 context.exception.args[0])
1222 # test that a GaussianProcess on many functions raises an
1223 # exception when you try to add a point with the wrong number
1224 # of function values
1225 with self.assertRaises(RuntimeError) as context:
1226 gg_many.addPoint(pt_good, fn_bad)
1227 self.assertIn("number of function values",
1228 context.exception.args[0])
1230 # check that, given good inputs, addPoint will run
1231 gg.addPoint(pt_good, 5.0)
1232 gg_many.addPoint(pt_good, fn_good)
1234 # since we started with 10 data points, we should now have 11
1235 self.assertEqual(gg.getNPoints(), 11)
1236 self.assertEqual(gg_many.getNPoints(), 11)
1238 def testAddPoint(self):
1239 """
1240 Test that getData works as expected after running addPoint()
1241 """
1242 rng = np.random.RandomState(99)
1243 data = rng.random_sample((15, 4))
1244 fn = rng.random_sample(15)
1245 gp = afwMath.GaussianProcessD(
1246 data, fn, afwMath.SquaredExpCovariogramD())
1247 self.assertEqual(gp.getNPoints(), 15)
1248 pt_add = rng.random_sample(4)
1249 fn_add = 0.98453
1250 gp.addPoint(pt_add, fn_add)
1251 self.assertEqual(gp.getNPoints(), 16)
1252 fn_out = np.zeros(1)
1253 pt_out = np.zeros((1, 4))
1254 indices = np.array([15], dtype=np.int32)
1255 gp.getData(pt_out, fn_out, indices)
1256 for ii in range(4):
1257 self.assertAlmostEqual(pt_out[0][ii], pt_add[ii], 10)
1258 self.assertAlmostEqual(fn_out[0], fn_add, 10)
1260 # now try it with a GaussianProcess on many functions
1261 fn = rng.random_sample((15, 3))
1262 gp = afwMath.GaussianProcessD(
1263 data, fn, afwMath.SquaredExpCovariogramD())
1264 self.assertEqual(gp.getNPoints(), 15)
1265 pt_add = rng.random_sample(4)
1266 fn_add = rng.random_sample(3)
1267 gp.addPoint(pt_add, fn_add)
1268 self.assertEqual(gp.getNPoints(), 16)
1269 fn_out = np.zeros((1, 3))
1270 gp.getData(pt_out, fn_out, indices)
1271 for ii in range(4):
1272 self.assertEqual(pt_out[0][ii], pt_add[ii], 10)
1273 for ii in range(3):
1274 self.assertEqual(fn_out[0][ii], fn_add[ii], 10)
1276 def testAdditionInterpolation(self):
1277 """
1278 This will test the performance of interpolation after adding new points
1279 to GaussianProcess' data set
1280 """
1281 pp = 1000
1282 dd = 10
1283 kk = 15
1284 tol = 1.0e-4
1286 data = np.zeros((pp, dd), dtype=float)
1287 fn = np.zeros((pp), dtype=float)
1288 test = np.zeros((dd), dtype=float)
1289 sigma = np.zeros((1), dtype=float)
1291 xx = afwMath.SquaredExpCovariogramD()
1292 xx.setEllSquared(5.0)
1294 with open(os.path.join(testPath, "data", "gp_additive_test_root.sav"), "r") as f:
1295 ff = f.readlines()
1297 for i in range(len(ff)):
1298 s = ff[i].split()
1299 fn[i] = float(s[10])
1300 for j in range(10):
1301 data[i][j] = float(s[j])
1303 # establish the Gaussian Process
1304 try:
1305 gg = afwMath.GaussianProcessD(data, fn, xx)
1306 except pex.Exception as e:
1307 print(e.what())
1309 gg.setLambda(0.002)
1311 # now add new points to it and see if GaussianProcess.interpolate performs
1312 # correctly
1313 with open(os.path.join(testPath, "data", "gp_additive_test_data.sav"), "r") as f:
1314 ff = f.readlines()
1316 for z in range(len(ff)):
1317 s = ff[z].split()
1318 for i in range(dd):
1319 test[i] = float(s[i])
1320 mushld = float(s[dd])
1321 try:
1322 gg.addPoint(test, mushld)
1323 except pex.Exception as e:
1324 print(e.what())
1326 with open(os.path.join(testPath, "data", "gp_additive_test_solutions.sav"), "r") as f:
1327 ff = f.readlines()
1329 worstMuErr = -1.0
1330 worstSigErr = -1.0
1332 for z in range(len(ff)):
1333 s = ff[z].split()
1334 for i in range(dd):
1335 test[i] = float(s[i])
1337 mushld = float(s[dd + kk])
1338 sigshld = float(s[dd + kk + 1])
1340 mu = gg.interpolate(sigma, test, kk)
1342 err = (mu - mushld)
1343 if mushld != 0:
1344 err = err/mushld
1345 if err < 0.0:
1346 err = -1.0 * err
1347 if z == 0 or err > worstMuErr:
1348 worstMuErr = err
1350 err = (sigma[0] - sigshld)
1351 if sigshld != 0:
1352 err = err/sigshld
1353 if err < 0.0:
1354 err = -1.0 * err
1355 if z == 0 or err > worstSigErr:
1356 worstSigErr = err
1358 print("\nThe errors for the test of adding points to the Gaussian process\n")
1359 print("worst mu error ", worstMuErr)
1360 print("worst sig2 error ", worstSigErr)
1362 self.assertLess(worstMuErr, tol)
1363 self.assertLess(worstSigErr, tol)
1365 def testBatch(self):
1366 """
1367 This test will test GaussianProcess.batchInterpolate both with
1368 and without variance calculation
1369 """
1370 pp = 100
1371 dd = 10
1372 tol = 1.0e-3
1374 data = np.zeros((pp, dd), dtype=float)
1375 fn = np.zeros((pp), dtype=float)
1377 with open(os.path.join(testPath, "data", "gp_exp_covar_data.sav"), "r") as f:
1378 ff = f.readlines()
1380 for i in range(100):
1381 s = ff[i].split()
1382 for j in range(dd):
1383 data[i][j] = float(s[j])
1384 fn[i] = float(s[dd])
1386 xx = afwMath.SquaredExpCovariogramD()
1387 xx.setEllSquared(2.0)
1389 try:
1390 gg = afwMath.GaussianProcessD(data, fn, xx)
1391 except pex.Exception as e:
1392 print(e.what())
1394 gg.setLambda(0.0032)
1396 with open(os.path.join(testPath, "data", "gp_batch_solutions.sav"), "r") as f:
1397 ff = f.readlines()
1399 ntest = len(ff)
1400 mushld = np.zeros((ntest), dtype=float)
1401 varshld = np.zeros((ntest), dtype=float)
1402 mu = np.zeros((ntest), dtype=float)
1403 var = np.zeros((ntest), dtype=float)
1405 queries = np.zeros((ntest, dd), dtype=float)
1407 for i in range(ntest):
1408 s = ff[i].split()
1409 for j in range(dd):
1410 queries[i][j] = float(s[j])
1411 mushld[i] = float(s[dd])
1412 varshld[i] = float(s[dd + 1])
1414 # test with variance calculation
1415 gg.batchInterpolate(mu, var, queries)
1417 worstMuErr = -1.0
1418 worstVarErr = -1.0
1419 for i in range(ntest):
1420 err = mu[i]-mushld[i]
1421 if mushld[i] != 0.0:
1422 err = err/mushld[i]
1423 if err < 0.0:
1424 err = -1.0 * err
1425 if err > worstMuErr:
1426 worstMuErr = err
1428 err = var[i]-varshld[i]
1429 if varshld[i] != 0.0:
1430 err = err/varshld[i]
1431 if err < 0.0:
1432 err = -1.0 * err
1433 if err > worstVarErr:
1434 worstVarErr = err
1436 # test without variance interpolation
1437 # continue keeping track of worstMuErr
1438 gg.batchInterpolate(mu, queries)
1439 for i in range(ntest):
1440 err = mu[i]-mushld[i]
1441 if mushld[i] != 0.0:
1442 err = err/mushld[i]
1443 if err < 0.0:
1444 err = -1.0 * err
1445 if err > worstMuErr:
1446 worstMuErr = err
1448 self.assertLess(worstMuErr, tol)
1449 self.assertLess(worstVarErr, tol)
1451 print("\nThe errors for batch interpolation\n")
1452 print("worst mu error ", worstMuErr)
1453 print("worst sig2 error ", worstVarErr)
1455 def testSelf(self):
1456 """
1457 This test will test GaussianProcess.selfInterpolation
1458 """
1459 pp = 2000
1460 dd = 10
1461 tol = 1.0e-3
1462 kk = 20
1464 data = np.zeros((pp, dd), dtype=float)
1465 fn = np.zeros((pp), dtype=float)
1467 with open(os.path.join(testPath, "data", "gp_exp_covar_data.sav"), "r") as f:
1468 ff = f.readlines()
1470 for i in range(pp):
1471 s = ff[i].split()
1472 for j in range(dd):
1473 data[i][j] = float(s[j])
1474 fn[i] = float(s[dd])
1476 xx = afwMath.SquaredExpCovariogramD()
1477 xx.setEllSquared(20.0)
1478 try:
1479 gg = afwMath.GaussianProcessD(data, fn, xx)
1480 except pex.Exception as e:
1481 print(e.what())
1483 gg.setKrigingParameter(30.0)
1484 gg.setLambda(0.00002)
1486 with open(os.path.join(testPath, "data", "gp_self_solutions.sav"), "r") as f:
1487 ff = f.readlines()
1489 variance = np.zeros((1), dtype=float)
1491 worstMuErr = -1.0
1492 worstSigErr = -1.0
1494 for i in range(pp):
1495 s = ff[i].split()
1496 mushld = float(s[0])
1497 sig2shld = float(s[1])
1499 try:
1500 mu = gg.selfInterpolate(variance, i, kk)
1501 except pex.Exception as e:
1502 print(e.what())
1504 err = mu - mushld
1505 if mushld != 0.0:
1506 err = err/mushld
1507 if err < 0.0:
1508 err = err * (-1.0)
1509 if i == 0 or err > worstMuErr:
1510 worstMuErr = err
1512 err = variance[0] - sig2shld
1513 if sig2shld != 0.0:
1514 err = err/sig2shld
1515 if err < 0.0:
1516 err = err * (-1.0)
1517 if i == 0 or err > worstSigErr:
1518 worstSigErr = err
1520 print("\nThe errors for self interpolation\n")
1521 print("worst mu error ", worstMuErr)
1522 print("worst sig2 error ", worstSigErr)
1523 self.assertLess(worstMuErr, tol)
1524 self.assertLess(worstSigErr, tol)
1526 def testVector(self):
1527 """
1528 This will test interpolate using a vector of functions
1529 """
1531 tol = 1.0e-3
1532 data = np.zeros((2000, 10), dtype=float)
1533 fn = np.zeros((2000, 4), dtype=float)
1534 mu = np.zeros((4), dtype=float)
1535 sig = np.zeros((4), dtype=float)
1536 mushld = np.zeros((4), dtype=float)
1537 vv = np.zeros((10), dtype=float)
1538 vvf = np.zeros((4), dtype=float)
1540 kk = 30
1542 with open(os.path.join(testPath, "data", "gp_vector_data.sav"), "r") as f:
1543 ff = f.readlines()
1545 for i in range(len(ff)):
1546 s = ff[i].split()
1547 for j in range(10):
1548 data[i][j] = float(s[j])
1549 for j in range(4):
1550 fn[i][j] = float(s[j+10])
1552 nn = afwMath.NeuralNetCovariogramD()
1553 nn.setSigma0(2.25)
1554 nn.setSigma1(0.76)
1555 try:
1556 gg = afwMath.GaussianProcessD(data, fn, nn)
1557 except pex.Exception as e:
1558 print(e.what())
1560 gg.setLambda(0.0045)
1562 worstMuErr = -1.0
1563 worstSigErr = -1.0
1565 with open(os.path.join(testPath, "data", "gp_vector_solutions.sav"), "r") as f:
1566 ff = f.readlines()
1568 for i in range(len(ff)):
1569 s = ff[i].split()
1570 for j in range(10):
1571 vv[j] = float(s[j])
1572 for j in range(4):
1573 mushld[j] = float(s[j+10])
1574 sigshld = float(s[14])
1576 gg.interpolate(mu, sig, vv, kk)
1578 for j in range(4):
1579 muErr = (mu[j]-mushld[j])/mushld[j]
1580 sigErr = (sig[j]-sigshld)/sigshld
1581 if muErr < 0.0:
1582 muErr = -1.0 * muErr
1583 if sigErr < 0.0:
1584 sigErr = -1.0 * sigErr
1585 if (muErr > worstMuErr):
1586 worstMuErr = muErr
1587 if (sigErr > worstSigErr):
1588 worstSigErr = sigErr
1590 print("\nThe errors for vector interpolation\n")
1591 print("worst mu error ", worstMuErr)
1592 print("worst sig2 error ", worstSigErr)
1593 self.assertLess(worstMuErr, tol)
1594 self.assertLess(worstSigErr, tol)
1596 worstMuErr = -1.0
1597 worstSigErr = -1.0
1599 with open(os.path.join(testPath, "data", "gp_vector_selfinterpolate_solutions.sav"), "r") as f:
1600 ff = f.readlines()
1602 for i in range(len(ff)):
1603 s = ff[i].split()
1604 try:
1605 gg.selfInterpolate(mu, sig, i, kk)
1606 except pex.Exception as e:
1607 print(e.what())
1609 for j in range(4):
1610 mushld[j] = float(s[j])
1611 sigshld = float(s[4])
1613 for j in range(4):
1614 muErr = (mu[j]-mushld[j])/mushld[j]
1615 if muErr < -1.0:
1616 muErr = -1.0 * muErr
1617 if muErr > worstMuErr:
1618 worstMuErr = muErr
1620 sigErr = (sig[j]-sigshld)/sigshld
1621 if sigErr < -1.0:
1622 sigErr = -1.0*sigErr
1623 if sigErr > worstSigErr:
1624 worstSigErr = sigErr
1626 print("\nThe errors for vector self interpolation\n")
1627 print("worst mu error ", worstMuErr)
1628 print("worst sig2 error ", worstSigErr)
1629 self.assertLess(worstMuErr, tol)
1630 self.assertLess(worstSigErr, tol)
1632 queries = np.zeros((100, 10), dtype=float)
1633 batchMu = np.zeros((100, 4), dtype=float)
1634 batchSig = np.zeros((100, 4), dtype=float)
1635 batchMuShld = np.zeros((100, 4), dtype=float)
1636 batchSigShld = np.zeros((100, 4), dtype=float)
1637 batchData = np.zeros((200, 10), dtype=float)
1638 batchFunctions = np.zeros((200, 4), dtype=float)
1640 with open(os.path.join(testPath, "data", "gp_vectorbatch_data.sav"), "r") as f:
1641 ff = f.readlines()
1643 for i in range(len(ff)):
1644 s = ff[i].split()
1645 for j in range(10):
1646 batchData[i][j] = float(s[j])
1647 for j in range(4):
1648 batchFunctions[i][j] = float(s[j+10])
1650 try:
1651 ggbatch = afwMath.GaussianProcessD(batchData, batchFunctions, nn)
1652 except pex.Exception as e:
1653 print(e.what())
1655 ggbatch.setLambda(0.0045)
1657 with open(os.path.join(testPath, "data", "gp_vectorbatch_solutions.sav"), "r") as f:
1658 ff = f.readlines()
1660 for i in range(len(ff)):
1661 s = ff[i].split()
1662 for j in range(10):
1663 queries[i][j] = float(s[j])
1664 for j in range(4):
1665 batchMuShld[i][j] = float(s[j+10])
1666 sigShld = float(s[14])
1667 for j in range(4):
1668 batchSigShld[i][j] = sigShld
1670 ggbatch.batchInterpolate(batchMu, batchSig, queries)
1671 worstMuErr = -1.0
1672 worstSigErr = -1.0
1673 for i in range(100):
1674 for j in range(4):
1675 muErr = (batchMu[i][j]-batchMuShld[i][j])/batchMuShld[i][j]
1676 sigErr = (batchSig[i][j]-batchSigShld[i][j])/batchSigShld[i][j]
1677 if muErr < 0.0:
1678 muErr = muErr * (-1.0)
1679 if sigErr < 0.0:
1680 sigErr = sigErr * (-1.0)
1682 if muErr > worstMuErr:
1683 worstMuErr = muErr
1684 if sigErr > worstSigErr:
1685 worstSigErr = sigErr
1687 print("\nThe errors for vector batch interpolation with variance\n")
1688 print("worst mu error ", worstMuErr)
1689 print("worst sig2 error ", worstSigErr)
1690 self.assertLess(worstMuErr, tol)
1691 self.assertLess(worstSigErr, tol)
1693 ggbatch.batchInterpolate(batchMu, queries)
1694 worstMuErr = -1.0
1695 worstSigErr = -1.0
1696 for i in range(100):
1697 for j in range(4):
1698 muErr = (batchMu[i][j]-batchMuShld[i][j])/batchMuShld[i][j]
1699 if muErr < 0.0:
1700 muErr = muErr * (-1.0)
1702 if muErr > worstMuErr:
1703 worstMuErr = muErr
1705 print("\nThe errors for vector batch interpolation without variance\n")
1706 print("worst mu error ", worstMuErr)
1707 self.assertLess(worstMuErr, tol)
1709 with open(os.path.join(testPath, "data", "gp_vector_add_data.sav"), "r") as f:
1710 ff = f.readlines()
1712 for i in range(len(ff)):
1713 s = ff[i].split()
1714 for j in range(10):
1715 vv[j] = float(s[j])
1716 for j in range(4):
1717 vvf[j] = float(s[j+10])
1718 try:
1719 gg.addPoint(vv, vvf)
1720 except pex.Exception as e:
1721 print(e.what())
1723 with open(os.path.join(testPath, "data", "gp_vector_add_solutions.sav"), "r") as f:
1724 ff = f.readlines()
1726 for i in range(len(ff)):
1727 s = ff[i].split()
1728 try:
1729 gg.selfInterpolate(mu, sig, i, kk)
1730 except pex.Exception as e:
1731 print(e.what())
1733 for j in range(4):
1734 mushld[j] = float(s[j])
1735 sigshld = float(s[4])
1737 for j in range(4):
1738 muErr = (mu[j]-mushld[j])/mushld[j]
1739 if muErr < 0.0:
1740 muErr = -1.0 * muErr
1741 if muErr > worstMuErr:
1742 worstMuErr = muErr
1744 sigErr = (sig[j]-sigshld)/sigshld
1745 if sigErr < 0.0:
1746 sigErr = -1.0*sigErr
1747 if sigErr > worstSigErr:
1748 worstSigErr = sigErr
1750 print("\nThe errors for vector add interpolation\n")
1751 print("worst mu error ", worstMuErr)
1752 print("worst sig2 error ", worstSigErr)
1754 self.assertLess(worstMuErr, tol)
1755 self.assertLess(worstSigErr, tol)
1757 def testRemovePointException(self):
1758 """
1759 Test that an exception is raised if you try to remove
1760 a point that does not exist from a Gaussian Process
1761 """
1762 rng = np.random.RandomState(118)
1763 data = rng.random_sample((13, 6))
1764 fn = rng.random_sample(13)
1765 gg = afwMath.GaussianProcessD(
1766 data, fn, afwMath.SquaredExpCovariogramD())
1768 with self.assertRaises(RuntimeError) as context:
1769 gg.removePoint(-1)
1770 self.assertIn("doesn't exist",
1771 context.exception.args[0])
1773 with self.assertRaises(RuntimeError) as context:
1774 gg.removePoint(13)
1775 self.assertIn("doesn't exist",
1776 context.exception.args[0])
1778 # test that it runs fine
1779 gg.removePoint(11)
1780 self.assertEqual(gg.getNPoints(), 12)
1782 def testRemovePoint(self):
1783 """
1784 Test that, after a point is removed, getData works as you would expect
1785 """
1786 rng = np.random.RandomState(99)
1787 data = rng.random_sample((15, 4))
1788 fn = rng.random_sample(15)
1789 gp = afwMath.GaussianProcessD(
1790 data, fn, afwMath.SquaredExpCovariogramD())
1791 self.assertEqual(gp.getNPoints(), 15)
1792 gp.removePoint(6)
1793 self.assertEqual(gp.getNPoints(), 14)
1794 indices = np.array([9, 5, 4, 11], dtype=np.int32)
1795 fn_out = np.zeros(4)
1796 pts_out = np.zeros((4, 4))
1797 gp.getData(pts_out, fn_out, indices)
1798 for ii in range(len(indices)):
1799 if indices[ii] >= 6:
1800 target = indices[ii]+1
1801 else:
1802 target = indices[ii]
1803 for jj in range(4):
1804 self.assertAlmostEqual(pts_out[ii][jj], data[target][jj], 10)
1805 self.assertAlmostEqual(fn_out[ii], fn[target], 10)
1807 # now test it on a GaussianProcess on many functions
1808 fn = rng.random_sample((15, 5))
1809 gp = afwMath.GaussianProcessD(
1810 data, fn, afwMath.SquaredExpCovariogramD())
1811 self.assertEqual(gp.getNPoints(), 15)
1812 gp.removePoint(6)
1813 self.assertEqual(gp.getNPoints(), 14)
1814 indices = np.array([9, 5, 4, 11], dtype=np.int32)
1815 fn_out = np.zeros((4, 5))
1816 pts_out = np.zeros((4, 4))
1817 gp.getData(pts_out, fn_out, indices)
1818 for ii in range(len(indices)):
1819 if indices[ii] >= 6:
1820 target = indices[ii]+1
1821 else:
1822 target = indices[ii]
1823 for jj in range(4):
1824 self.assertAlmostEqual(pts_out[ii][jj], data[target][jj], 10)
1825 for jj in range(5):
1826 self.assertAlmostEqual(fn_out[ii][jj], fn[target][jj], 10)
1828 def testSubtractionInterpolation(self):
1829 """
1830 This will test interpolate after subtracting points
1831 """
1833 tol = 1.0e-3
1834 data = np.zeros((2000, 10), dtype=float)
1835 fn = np.zeros((2000, 4), dtype=float)
1836 mu = np.zeros((4), dtype=float)
1837 sig = np.zeros((4), dtype=float)
1838 mushld = np.zeros((4), dtype=float)
1839 vv = np.zeros((10), dtype=float)
1840 kk = 30
1842 with open(os.path.join(testPath, "data", "gp_subtraction_data.sav"), "r") as f:
1843 ff = f.readlines()
1845 for i in range(len(ff)):
1846 s = ff[i].split()
1847 for j in range(10):
1848 data[i][j] = float(s[j])
1849 for j in range(4):
1850 fn[i][j] = float(s[j+10])
1852 xx = afwMath.SquaredExpCovariogramD()
1853 xx.setEllSquared(2.3)
1854 try:
1855 gg = afwMath.GaussianProcessD(data, fn, xx)
1856 except pex.Exception as e:
1857 print(e.what())
1859 gg.setLambda(0.002)
1861 j = 1
1862 for i in range(1000):
1863 try:
1864 gg.removePoint(j)
1865 except pex.Exception as e:
1866 print(e.what())
1868 j = j+1
1870 worstMuErr = -1.0
1871 worstSigErr = -1.0
1873 with open(os.path.join(testPath, "data", "gp_subtraction_solutions.sav"), "r") as f:
1874 ff = f.readlines()
1876 for i in range(len(ff)):
1877 s = ff[i].split()
1878 for j in range(10):
1879 vv[j] = float(s[j])
1880 for j in range(4):
1881 mushld[j] = float(s[j+10])
1882 sigshld = float(s[14])
1884 gg.interpolate(mu, sig, vv, kk)
1886 for j in range(4):
1887 muErr = (mu[j]-mushld[j])/mushld[j]
1888 sigErr = (sig[j]-sigshld)/sigshld
1889 if muErr < 0.0:
1890 muErr = -1.0 * muErr
1891 if sigErr < 0.0:
1892 sigErr = -1.0 * sigErr
1893 if (muErr > worstMuErr):
1894 worstMuErr = muErr
1895 if (sigErr > worstSigErr):
1896 worstSigErr = sigErr
1898 print("\nThe errors for subtraction interpolation\n")
1899 print("worst mu error ", worstMuErr)
1900 print("worst sig2 error ", worstSigErr)
1901 self.assertLess(worstMuErr, tol)
1902 self.assertLess(worstSigErr, tol)
1904 worstMuErr = -1.0
1905 worstSigErr = -1.0
1907 with open(os.path.join(testPath, "data", "gp_subtraction_selfinterpolate_solutions.sav"), "r") as f:
1908 ff = f.readlines()
1910 for i in range(len(ff)):
1911 s = ff[i].split()
1912 try:
1913 gg.selfInterpolate(mu, sig, i, kk)
1914 except pex.Exception as e:
1915 print(e.what())
1917 for j in range(4):
1918 mushld[j] = float(s[j])
1919 sigshld = float(s[4])
1921 for j in range(4):
1922 muErr = (mu[j]-mushld[j])/mushld[j]
1923 if muErr < 0.0:
1924 muErr = -1.0 * muErr
1925 if muErr > worstMuErr:
1926 worstMuErr = muErr
1928 sigErr = (sig[j]-sigshld)/sigshld
1929 if sigErr < 0.0:
1930 sigErr = -1.0*sigErr
1931 if sigErr > worstSigErr:
1932 worstSigErr = sigErr
1934 print("\nThe errors for subtraction self interpolation\n")
1935 print("worst mu error ", worstMuErr)
1936 print("worst sig2 error ", worstSigErr)
1937 self.assertLess(worstMuErr, tol)
1938 self.assertLess(worstSigErr, tol)
1941class MemoryTester(lsst.utils.tests.MemoryTestCase):
1942 pass
1945def setup_module(module):
1946 lsst.utils.tests.init()
1949if __name__ == "__main__": 1949 ↛ 1950line 1949 didn't jump to line 1950, because the condition on line 1949 was never true
1950 lsst.utils.tests.init()
1951 unittest.main()