Major: made scripts pass pep8 and pyflakes
This commit is contained in:
+167
-183
@@ -1,220 +1,204 @@
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
from functools import wraps
|
||||
import itertools
|
||||
|
||||
import interp
|
||||
import logging
|
||||
log = logging.getLogger('interp')
|
||||
|
||||
AGGRESSIVE_ERROR_SOLVE = True
|
||||
RAISE_PATHOLOGICAL_EXCEPTION = False
|
||||
|
||||
__version__ = interp.__version__
|
||||
|
||||
|
||||
def get_phis(X, R):
|
||||
"""
|
||||
The get_phis function is used to get barycentric coordonites for a
|
||||
point on a triangle or tetrahedron. This is equation (*\ref{eq:qlinarea}*)
|
||||
"""
|
||||
The get_phis function is used to get barycentric coordonites for a
|
||||
point on a triangle or tetrahedron (Equation (*\ref{eq:qlinarea}*))
|
||||
|
||||
in 2D:
|
||||
in 2D:
|
||||
|
||||
X - the destination point (2D)
|
||||
X = [0,0]
|
||||
R - the three points that make up the 2-D triangular simplex
|
||||
R = [[-1, -1], [0, 2], [1, -1]]
|
||||
X - the destination point (2D)
|
||||
X = [0,0]
|
||||
R - the three points that make up the 2-D triangular simplex
|
||||
R = [[-1, -1], [0, 2], [1, -1]]
|
||||
|
||||
this will return [0.333, 0.333, 0.333]
|
||||
this will return [0.333, 0.333, 0.333]
|
||||
|
||||
|
||||
in 3D:
|
||||
in 3D:
|
||||
|
||||
X - the destination point (3D)
|
||||
X = [0,0,0]
|
||||
R - the four points that make up the 3-D simplex (tetrahedron)
|
||||
R = [
|
||||
[ 0.0000, 0.0000, 1.0000],
|
||||
[ 0.9428, 0.0000, -0.3333],
|
||||
[-0.4714, 0.8165, -0.3333],
|
||||
[-0.4714, -0.8165, -0.3333],
|
||||
]
|
||||
X - the destination point (3D)
|
||||
X = [0,0,0]
|
||||
R - the four points that make up the 3-D simplex (tetrahedron)
|
||||
R = [
|
||||
[ 0.0000, 0.0000, 1.0000],
|
||||
[ 0.9428, 0.0000, -0.3333],
|
||||
[-0.4714, 0.8165, -0.3333],
|
||||
[-0.4714, -0.8165, -0.3333],
|
||||
]
|
||||
|
||||
this will return [0.25, 0.25, 0.25, 0.25]
|
||||
"""
|
||||
this will return [0.25, 0.25, 0.25, 0.25]
|
||||
"""
|
||||
|
||||
# equations (*\ref{eq:lin3d}*) and (*\ref{eq:lin2d}*)
|
||||
if len(X) == 2:
|
||||
log.debug("running 2D")
|
||||
A = np.array([
|
||||
[ 1, 1, 1],
|
||||
[R[0][0], R[1][0], R[2][0]],
|
||||
[R[0][1], R[1][1], R[2][1]],
|
||||
])
|
||||
b = np.array([ 1,
|
||||
X[0],
|
||||
X[1]
|
||||
])
|
||||
elif len(X) == 3:
|
||||
log.debug("running 3D")
|
||||
A = np.array([
|
||||
[ 1, 1, 1, 1 ],
|
||||
[R[0][0], R[1][0], R[2][0], R[3][0]],
|
||||
[R[0][1], R[1][1], R[2][1], R[3][1]],
|
||||
[R[0][2], R[1][2], R[2][2], R[3][2]],
|
||||
])
|
||||
b = np.array([ 1,
|
||||
X[0],
|
||||
X[1],
|
||||
X[2]
|
||||
])
|
||||
else:
|
||||
raise Exception("inapropriate demension on X")
|
||||
|
||||
try:
|
||||
phi = np.linalg.solve(A,b)
|
||||
except np.linalg.LinAlgError as e:
|
||||
msg = "calculation of phis yielded a linearly dependant system (%s)" % e
|
||||
log.error(msg)
|
||||
# raise Exception(msg)
|
||||
phi = np.dot(np.linalg.pinv(A), b)
|
||||
|
||||
log.debug("phi: %s", phi)
|
||||
|
||||
return phi
|
||||
|
||||
def qlinear(X, R):
|
||||
"""
|
||||
this calculates the linear portion of q from R to X
|
||||
|
||||
This is equation (*\ref{eq:qlinbasis}*)
|
||||
|
||||
X = destination point
|
||||
R = a inter.grid object; must have R.points and R.q
|
||||
"""
|
||||
|
||||
phis = get_phis(X, R.verts)
|
||||
qlin = np.sum([q_i * phi_i for q_i, phi_i in zip(R.q, phis)])
|
||||
|
||||
log.debug("phis: %s", phis)
|
||||
log.debug("qlin: %s", qlin)
|
||||
|
||||
return phis, qlin
|
||||
|
||||
def get_error(phi, R, S, order = 2):
|
||||
"""
|
||||
Calculate the error approximation terms, returning the unknowns
|
||||
a,b, and c in equation (*\ref{eq:quadratic2d}*).
|
||||
"""
|
||||
B = [] # equation ((*\ref{eq:B2d}*)
|
||||
w = [] # equation ((*\ref{eq:w}*)
|
||||
|
||||
cur_pattern = pattern(len(phi), order)
|
||||
log.info("pattern: %s" % cur_pattern)
|
||||
|
||||
for (s,q) in zip(S.verts, S.q):
|
||||
cur_phi, cur_qlin = qlinear(s, R)
|
||||
l = []
|
||||
for i in cur_pattern:
|
||||
cur_sum = cur_phi[i[0]]
|
||||
for j in i[1:]:
|
||||
cur_sum *= cur_phi[j]
|
||||
l.append(cur_sum)
|
||||
|
||||
B.append(l)
|
||||
w.append(q - cur_qlin)
|
||||
|
||||
log.info("B: %s" % B)
|
||||
log.info("w: %s" % w)
|
||||
# equations (*\ref{eq:lin3d}*) and (*\ref{eq:lin2d}*)
|
||||
if len(X) == 2:
|
||||
A = np.array([
|
||||
[1, 1, 1],
|
||||
[R[0][0], R[1][0], R[2][0]],
|
||||
[R[0][1], R[1][1], R[2][1]],
|
||||
])
|
||||
b = np.array([1, X[0], X[1]])
|
||||
elif len(X) == 3:
|
||||
A = np.array([
|
||||
[1, 1, 1, 1],
|
||||
[R[0][0], R[1][0], R[2][0], R[3][0]],
|
||||
[R[0][1], R[1][1], R[2][1], R[3][1]],
|
||||
[R[0][2], R[1][2], R[2][2], R[3][2]],
|
||||
])
|
||||
b = np.array([1, X[0], X[1], X[2]])
|
||||
else:
|
||||
raise Exception("inapropriate demension on X")
|
||||
phi = np.linalg.solve(A, b)
|
||||
return phi
|
||||
|
||||
|
||||
B = np.array(B)
|
||||
w = np.array(w)
|
||||
def qlinear(X, R, q):
|
||||
"""
|
||||
this calculates the linear portion of q from R to X
|
||||
|
||||
A = np.dot(B.T, B)
|
||||
b = np.dot(B.T, w)
|
||||
This is equation (*\ref{eq:qlinbasis}*)
|
||||
|
||||
try:
|
||||
abc = np.linalg.solve(A,b)
|
||||
except np.linalg.LinAlgError as e:
|
||||
log.error("linear calculation went bad, resorting to np.linalg.pinv: %s" % e)
|
||||
abc = np.dot(np.linalg.pinv(A), b)
|
||||
X = destination point
|
||||
R = a inter.grid object; must have R.points and R.q
|
||||
"""
|
||||
|
||||
error_term = 0.0
|
||||
for (a, i) in zip(abc, cur_pattern):
|
||||
cur_sum = a
|
||||
for j in i:
|
||||
cur_sum *= phi[j]
|
||||
error_term += cur_sum
|
||||
phis = get_phis(X, R)
|
||||
qlin = np.sum([q_i * phi_i for q_i, phi_i in zip(q, phis)])
|
||||
|
||||
log.debug("error_term: %s" % error_term)
|
||||
return error_term, abc
|
||||
return phis, qlin
|
||||
|
||||
def run_baker(X, R, S, order=2):
|
||||
"""
|
||||
This is the main function to call to get an interpolation to X from the
|
||||
input meshes
|
||||
|
||||
X -- the destination point
|
||||
def get_error(phi, R, R_q, S, S_q, order=2):
|
||||
"""
|
||||
Calculate the error approximation terms, returning the unknowns
|
||||
a,b, and c in equation (*\ref{eq:quadratic2d}*).
|
||||
"""
|
||||
B = [] # equation ((*\ref{eq:B2d}*)
|
||||
w = [] # equation ((*\ref{eq:w}*)
|
||||
|
||||
R = Simplex
|
||||
S = extra points
|
||||
"""
|
||||
log.debug("order = %d" % order)
|
||||
log.debug("extra points = %d" % len(S.verts))
|
||||
cur_pattern = pattern(len(phi), order)
|
||||
|
||||
answer = {
|
||||
'qlin': None,
|
||||
'error': None,
|
||||
'final': None,
|
||||
}
|
||||
# calculate values only for the simplex triangle
|
||||
phi, qlin = qlinear(X, R)
|
||||
for (s, cur_q) in zip(S, S_q):
|
||||
cur_phi, cur_qlin = qlinear(s, R, R_q)
|
||||
l = []
|
||||
for i in cur_pattern:
|
||||
cur_sum = cur_phi[i[0]]
|
||||
for j in i[1:]:
|
||||
cur_sum *= cur_phi[j]
|
||||
l.append(cur_sum)
|
||||
|
||||
B.append(l)
|
||||
w.append(cur_q - cur_qlin)
|
||||
|
||||
B = np.array(B)
|
||||
w = np.array(w)
|
||||
|
||||
A = np.dot(B.T, B)
|
||||
b = np.dot(B.T, w)
|
||||
|
||||
try:
|
||||
abc = np.linalg.solve(A, b)
|
||||
except np.linalg.LinAlgError:
|
||||
if not AGGRESSIVE_ERROR_SOLVE:
|
||||
return None, None
|
||||
abc = np.dot(np.linalg.pinv(A), b)
|
||||
|
||||
error_term = 0.0
|
||||
for (a, i) in zip(abc, cur_pattern):
|
||||
cur_sum = a
|
||||
for j in i:
|
||||
cur_sum *= phi[j]
|
||||
error_term += cur_sum
|
||||
|
||||
return error_term, abc
|
||||
|
||||
|
||||
def run_baker(X, R, R_q, S, S_q, order=2):
|
||||
"""
|
||||
This is the main function to call to get an interpolation to X from the
|
||||
input meshes
|
||||
|
||||
X -- the destination point
|
||||
|
||||
R = Simplex
|
||||
S = extra points
|
||||
"""
|
||||
|
||||
answer = {
|
||||
'qlin': None,
|
||||
'error': None,
|
||||
'final': None,
|
||||
}
|
||||
|
||||
# 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):
|
||||
error_term, abc = get_error(phi, R, R_q, S, S_q, order)
|
||||
|
||||
# if a pathological vertex configuration was encountered and
|
||||
# AGGRESSIVE_ERROR_SOLVE is False, get_error will return (None, None)
|
||||
# indicating that only linear interpolation should be performed
|
||||
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:
|
||||
raise Exception('unsupported order "%d" for baker method' % order)
|
||||
|
||||
q_final = qlin + error_term
|
||||
|
||||
if order == 1:
|
||||
answer['qlin'] = qlin
|
||||
answer['final'] = qlin
|
||||
answer['error'] = error_term
|
||||
answer['final'] = q_final
|
||||
answer['abc'] = abc
|
||||
|
||||
return answer
|
||||
elif order in xrange(2,11):
|
||||
error_term, abc = get_error(phi, R, S, order)
|
||||
else:
|
||||
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
|
||||
|
||||
log.debug(answer)
|
||||
|
||||
return answer
|
||||
|
||||
|
||||
def memoize(f):
|
||||
"""
|
||||
for more information on what I'm doing here, please read:
|
||||
http://en.wikipedia.org/wiki/Memoize
|
||||
"""
|
||||
cache = {}
|
||||
@wraps(f)
|
||||
def memf(simplex_size, nu):
|
||||
x = (simplex_size, nu)
|
||||
if x not in cache:
|
||||
log.debug("adding to cache: %s", x)
|
||||
cache[x] = f(simplex_size, nu)
|
||||
return cache[x]
|
||||
return memf
|
||||
"""
|
||||
for more information on what I'm doing here, please read:
|
||||
http://en.wikipedia.org/wiki/Memoize
|
||||
"""
|
||||
cache = {}
|
||||
|
||||
@wraps(f)
|
||||
def memf(simplex_size, nu):
|
||||
x = (simplex_size, nu)
|
||||
if x not in cache:
|
||||
cache[x] = f(simplex_size, nu)
|
||||
return cache[x]
|
||||
return memf
|
||||
|
||||
|
||||
@memoize
|
||||
def pattern(simplex_size, nu):
|
||||
"""
|
||||
This function returns the pattern requisite to compose the error
|
||||
approximation function, and the matrix B.
|
||||
"""
|
||||
log.debug("pattern: simplex: %d, order: %d" % (simplex_size, nu))
|
||||
"""
|
||||
This function returns the pattern requisite to compose the error
|
||||
approximation function, and the matrix B.
|
||||
"""
|
||||
|
||||
r = []
|
||||
for i in itertools.product(xrange(simplex_size), repeat = nu):
|
||||
if len(set(i)) !=1:
|
||||
r.append(tuple(sorted(i)))
|
||||
unique_r = list(set(r))
|
||||
return unique_r
|
||||
r = []
|
||||
for i in itertools.product(xrange(simplex_size), repeat=nu):
|
||||
if len(set(i)) != 1:
|
||||
r.append(tuple(sorted(i)))
|
||||
unique_r = list(set(r))
|
||||
return unique_r
|
||||
|
||||
Reference in New Issue
Block a user