diff --git a/interp/baker/__init__.py b/interp/baker/__init__.py index ddd9e4e..bccd4db 100644 --- a/interp/baker/__init__.py +++ b/interp/baker/__init__.py @@ -1,8 +1,9 @@ -import numpy as np - +from collections import namedtuple from functools import wraps import itertools +import numpy as np + import interp AGGRESSIVE_ERROR_SOLVE = True @@ -10,6 +11,8 @@ RAISE_PATHOLOGICAL_EXCEPTION = False __version__ = interp.__version__ +Answer = namedtuple("Answer", ['qlin', 'final', 'error', 'abc']) + def get_phis(X, R): """ @@ -124,7 +127,7 @@ def get_error(phi, R, R_q, S, S_q, order=2): return error_term, abc -def run_baker(X, R, R_q, S, S_q, order=2): +def interpolate(X, R, R_q, S=None, S_q=None, order=2): """ This is the main function to call to get an interpolation to X from the input meshes @@ -132,23 +135,22 @@ def run_baker(X, R, R_q, S, S_q, order=2): X -- the destination point R = Simplex + R_q = q values at R S = extra points + S_q = q values at S + + order - order of interpolation - 1 """ - answer = { - 'qlin': None, - 'error': None, - 'final': None, - } + qlin=None + error_term=None + final=None + abc={} # calculate values only for the simplex triangle phi, qlin = qlinear(X, R, R_q) - if order == 1: - answer['qlin'] = qlin - answer['final'] = qlin - return answer - elif order in xrange(2, 11): + if order in xrange(2, 11) and S: error_term, abc = get_error(phi, R, R_q, S, S_q, order) # if a pathological vertex configuration was encountered and @@ -157,20 +159,13 @@ def run_baker(X, R, R_q, S, S_q, order=2): if (error_term is None) and (abc is None): if RAISE_PATHOLOGICAL_EXCEPTION: raise np.linalg.LinAlgError("Pathological Vertex Config") - answer['qlin'] = qlin - answer['final'] = qlin - return answer - else: + else: + final = qlin + error_term + elif order not in xrange(2,11): raise Exception('unsupported order "%d" for baker method' % order) - q_final = qlin + error_term - answer['qlin'] = qlin - answer['error'] = error_term - answer['final'] = q_final - answer['abc'] = abc - - return answer + return Answer(qlin=qlin, error=error_term, final=final, abc=abc) def memoize(f): diff --git a/interp/grid/__init__.py b/interp/grid/__init__.py index 3c58fc0..7e3cc4f 100644 --- a/interp/grid/__init__.py +++ b/interp/grid/__init__.py @@ -6,7 +6,7 @@ from xml.dom.minidom import Document import numpy as np from scipy.spatial import KDTree -from interp.baker import run_baker +from interp.baker import interpolate from interp.baker import get_phis import interp @@ -136,9 +136,9 @@ class grid(object): return (r_mesh, s_mesh) - def run_baker(self, X, order=2, extra_points=3): + def interpolate(self, X, order=2, extra_points=3): (R, S) = self.get_simplex_and_nearest_points(X, extra_points) - answer = run_baker(X, R, S, order) + answer = interpolate(X, R, S, order) return answer def for_qhull_generator(self): diff --git a/interp/tools.py b/interp/tools.py index b7fdd19..f824b3a 100644 --- a/interp/tools.py +++ b/interp/tools.py @@ -45,6 +45,10 @@ def baker_exact_3D(X): np.sin(z * np.pi / 2.0)), 2) return answer +def exact_me(X, f): + a = np.array([f(i) for i in X]) + return a + def friendly_exact_3D(X): x, y, z = X @@ -67,6 +71,9 @@ def improved_answer(answer, exact): else: return False +def identical_points(a,b): + return all(set(j[i] for j in a) \ + == set(j[i] for j in b) for i in xrange(len(a[0]))) def improved(qlin, err, final, exact): if np.abs(final - exact) <= np.abs(qlin - exact): diff --git a/test/all.py b/test/all.py index 1888a26..f35b89b 100644 --- a/test/all.py +++ b/test/all.py @@ -21,4 +21,4 @@ if __name__ == '__main__': ] for test in tests: - unittest.TextTestRunner(verbosity=3).run(test) + unittest.TextTestRunner(verbosity=1).run(test) diff --git a/test/baker2d.py b/test/baker2d.py index 599b6e2..40ba2b5 100644 --- a/test/baker2d.py +++ b/test/baker2d.py @@ -3,6 +3,7 @@ import unittest from interp import baker +from interp.baker import Answer class Test(unittest.TestCase): @@ -68,6 +69,17 @@ class Test(unittest.TestCase): self.assertAlmostEqual(result, right_answer) + def testRunBaker_linear(self): + size_of_simplex = 3 + + R, R_q = (self.all_points[:size_of_simplex], + self.q[:size_of_simplex]) + + + answer = baker.interpolate(self.X, R, R_q) + good_answer = Answer(qlin=0.5, final=None, error=None, abc={}) + self.assertEqual(answer, good_answer) + def testRunBaker_1(self): size_of_simplex = 3 extra_points = 3 @@ -79,11 +91,11 @@ class Test(unittest.TestCase): + extra_points], self.q[size_of_simplex:size_of_simplex + extra_points]) - answer = baker.run_baker(self.X, R, R_q, S, S_q) + answer = baker.interpolate(self.X, R, R_q, S, S_q) - a = answer['abc'][0] - b = answer['abc'][1] - c = answer['abc'][2] + a = answer.abc[0] + b = answer.abc[1] + c = answer.abc[2] self.assertEqual(sorted((a, b, c)), sorted((0, 0.0, 1 / 3.))) @@ -97,9 +109,9 @@ class Test(unittest.TestCase): + extra_points], self.q[size_of_simplex:size_of_simplex + extra_points]) - answer = baker.run_baker(self.X, R, R_q, S, S_q) + answer = baker.interpolate(self.X, R, R_q, S, S_q) - a, b, c = sorted(answer['abc']) + a, b, c = sorted(answer.abc) aa, bb, cc = sorted((2 / 3.0, 2 / 3.0, 1 / 3.0)) self.assertAlmostEqual(a, aa) @@ -115,11 +127,11 @@ class Test(unittest.TestCase): S, S_q = (self.all_points[size_of_simplex:size_of_simplex \ + extra_points], self.q[size_of_simplex:size_of_simplex + extra_points]) - answer = baker.run_baker(self.X, R, R_q, S, S_q) + answer = baker.interpolate(self.X, R, R_q, S, S_q) - a = answer['abc'][0] - b = answer['abc'][1] - c = answer['abc'][2] + a = answer.abc[0] + b = answer.abc[1] + c = answer.abc[2] a, b, c = sorted((a, b, c)) aa, bb, cc = sorted((13 / 14., 2 / 7., 15 / 14.)) @@ -137,11 +149,11 @@ class Test(unittest.TestCase): S, S_q = (self.all_points[size_of_simplex:size_of_simplex \ + extra_points], self.q[size_of_simplex:size_of_simplex + extra_points]) - answer = baker.run_baker(self.X, R, R_q, S, S_q) + answer = baker.interpolate(self.X, R, R_q, S, S_q) - a = answer['abc'][0] - b = answer['abc'][1] - c = answer['abc'][2] + a = answer.abc[0] + b = answer.abc[1] + c = answer.abc[2] a, b, c = sorted((a, b, c)) aa, bb, cc = sorted((48 / 53.0, 15 / 53.0, 54 / 53.0)) diff --git a/test/baker2dorder.py b/test/baker2dorder.py index bbc7315..70efff4 100644 --- a/test/baker2dorder.py +++ b/test/baker2dorder.py @@ -77,7 +77,7 @@ class Test(unittest.TestCase): self.phis, self.qlin = baker.qlinear(self.X, self.R, self.q) self.exact = exact_func(self.X) - self.answer = baker.run_baker(self.X, self.R, + self.answer = baker.interpolate(self.X, self.R, self.R_q, self.S, self.S_q) def test_R_contains_X(self): @@ -86,22 +86,22 @@ class Test(unittest.TestCase): def test_1(self): a, b, c, d, e, f = (0, 1, 1, 2, 2, 0) err = calculate_error_term(self, a, b, c, d, e, f) - self.assertAlmostEqual(err, self.answer['error']) + self.assertAlmostEqual(err, self.answer.error) def test_swap_first_elements(self): a, b, c, d, e, f = (1, 0, 1, 2, 2, 0) err = calculate_error_term(self, a, b, c, d, e, f) - self.assertAlmostEqual(err, self.answer['error']) + self.assertAlmostEqual(err, self.answer.error) def test_swap_two_pairs(self): a, b, c, d, e, f = (1, 2, 0, 1, 2, 0) err = calculate_error_term(self, a, b, c, d, e, f) - self.assertAlmostEqual(err, self.answer['error']) + self.assertAlmostEqual(err, self.answer.error) def test_swap_all_pairs(self): a, b, c, d, e, f = (0, 2, 0, 1, 2, 1) err = calculate_error_term(self, a, b, c, d, e, f) - self.assertAlmostEqual(err, self.answer['error']) + self.assertAlmostEqual(err, self.answer.error) if __name__ == '__main__': diff --git a/test/cubic2d.py b/test/cubic2d.py index 53d64ed..a5778de 100644 --- a/test/cubic2d.py +++ b/test/cubic2d.py @@ -2,9 +2,8 @@ import unittest -from interp.baker import run_baker - -from interp.grid import contains +from interp.baker import interpolate +from interp.grid import contains def exact_func(X): @@ -36,42 +35,42 @@ class Test(unittest.TestCase): def test_RunBaker_1_extra_point(self, extra=1): S = self.g[3:3 + extra] S_q = self.q[3:3 + extra] - answer = run_baker(self.X, self.R, self.R_q, S, S_q, order=3) - lin_err = abs(self.exact - answer['qlin']) - final_err = abs(self.exact - answer['final']) + answer = interpolate(self.X, self.R, self.R_q, S, S_q, order=3) + lin_err = abs(self.exact - answer.qlin) + final_err = abs(self.exact - answer.final) # expected failure ... self.assertTrue(lin_err >= final_err) def test_RunBaker_2_extra_point(self, extra=2): S = self.g[3: 3 + extra] S_q = self.q[3:3 + extra] - answer = run_baker(self.X, self.R, self.R_q, S, S_q, order=3) - lin_err = abs(self.exact - answer['qlin']) - final_err = abs(self.exact - answer['final']) + answer = interpolate(self.X, self.R, self.R_q, S, S_q, order=3) + lin_err = abs(self.exact - answer.qlin) + final_err = abs(self.exact - answer.final) self.assertTrue(lin_err >= final_err) def test_RunBaker_3_extra_point(self, extra=3): S = self.g[3: 3 + extra] S_q = self.q[3:3 + extra] - answer = run_baker(self.X, self.R, self.R_q, S, S_q, order=3) - lin_err = abs(self.exact - answer['qlin']) - final_err = abs(self.exact - answer['final']) + answer = interpolate(self.X, self.R, self.R_q, S, S_q, order=3) + lin_err = abs(self.exact - answer.qlin) + final_err = abs(self.exact - answer.final) self.assertTrue(lin_err >= final_err) def test_RunBaker_4_extra_point(self, extra=4): S = self.g[3: 3 + extra] S_q = self.q[3:3 + extra] - answer = run_baker(self.X, self.R, self.R_q, S, S_q, order=3) - lin_err = abs(self.exact - answer['qlin']) - final_err = abs(self.exact - answer['final']) + answer = interpolate(self.X, self.R, self.R_q, S, S_q, order=3) + lin_err = abs(self.exact - answer.qlin) + final_err = abs(self.exact - answer.final) self.assertTrue(lin_err >= final_err) def test_RunBaker_5_extra_point(self, extra=5): S = self.g[3: 3 + extra] S_q = self.q[3:3 + extra] - answer = run_baker(self.X, self.R, self.R_q, S, S_q, order=3) - lin_err = abs(self.exact - answer['qlin']) - final_err = abs(self.exact - answer['final']) + answer = interpolate(self.X, self.R, self.R_q, S, S_q, order=3) + lin_err = abs(self.exact - answer.qlin) + final_err = abs(self.exact - answer.final) self.assertTrue(lin_err >= final_err) if __name__ == '__main__': diff --git a/test/quadratic2d.py b/test/quadratic2d.py index 52fbb5e..eafc5f1 100644 --- a/test/quadratic2d.py +++ b/test/quadratic2d.py @@ -2,8 +2,7 @@ import unittest -from interp.baker import run_baker - +from interp.baker import interpolate from interp.grid import grid from interp.grid import contains @@ -41,9 +40,9 @@ class Test(unittest.TestCase): def test_RunBaker_1_extra_point(self, extra=1): S = self.g[3: 3 + extra] S_q = self.q[3: 3 + extra] - answer = run_baker(self.X, self.R, self.R_q, S, S_q) - lin_err = abs(self.exact - answer['qlin']) - final_err = abs(self.exact - answer['final']) + answer = interpolate(self.X, self.R, self.R_q, S, S_q) + lin_err = abs(self.exact - answer.qlin) + final_err = abs(self.exact - answer.final) #XXX: not sure about this one: self.assertEqual(lin_err, final_err) @@ -51,33 +50,33 @@ class Test(unittest.TestCase): def test_RunBaker_2_extra_point(self, extra=2): S = self.g[3: 3 + extra] S_q = self.q[3: 3 + extra] - answer = run_baker(self.X, self.R, self.R_q, S, S_q) - lin_err = abs(self.exact - answer['qlin']) - final_err = abs(self.exact - answer['final']) + answer = interpolate(self.X, self.R, self.R_q, S, S_q) + lin_err = abs(self.exact - answer.qlin) + final_err = abs(self.exact - answer.final) self.assertTrue(lin_err >= final_err) def test_RunBaker_3_extra_point(self, extra=3): S = self.g[3: 3 + extra] S_q = self.q[3: 3 + extra] - answer = run_baker(self.X, self.R, self.R_q, S, S_q) - lin_err = abs(self.exact - answer['qlin']) - final_err = abs(self.exact - answer['final']) + answer = interpolate(self.X, self.R, self.R_q, S, S_q) + lin_err = abs(self.exact - answer.qlin) + final_err = abs(self.exact - answer.final) self.assertTrue(lin_err >= final_err) def test_RunBaker_4_extra_point(self, extra=4): S = self.g[3: 3 + extra] S_q = self.q[3: 3 + extra] - answer = run_baker(self.X, self.R, self.R_q, S, S_q) - lin_err = abs(self.exact - answer['qlin']) - final_err = abs(self.exact - answer['final']) + answer = interpolate(self.X, self.R, self.R_q, S, S_q) + lin_err = abs(self.exact - answer.qlin) + final_err = abs(self.exact - answer.final) self.assertTrue(lin_err >= final_err) def test_RunBaker_5_extra_point(self, extra=5): S = self.g[3: 3 + extra] S_q = self.q[3: 3 + extra] - answer = run_baker(self.X, self.R, self.R_q, S, S_q) - lin_err = abs(self.exact - answer['qlin']) - final_err = abs(self.exact - answer['final']) + answer = interpolate(self.X, self.R, self.R_q, S, S_q) + lin_err = abs(self.exact - answer.qlin) + final_err = abs(self.exact - answer.final) self.assertTrue(lin_err >= final_err) if __name__ == '__main__':