Skip to content

Instantly share code, notes, and snippets.

@ev-br
Last active December 26, 2015 06:49
Show Gist options
  • Save ev-br/7110020 to your computer and use it in GitHub Desktop.
Save ev-br/7110020 to your computer and use it in GitHub Desktop.
Subclassing PPoly / BPoly to have custom out-of-bounds behavior. Eg: periodic boundary conditions, custom asymptotics.
from __future__ import division, print_function, absolute_import
import numpy as np
from scipy.interpolate import BPoly, PPoly
class MixinAsympt(object):
def _evaluate(self, x, nu, extrapolate, out):
super(MixinAsympt, self)._evaluate(x, nu, False, out)
below, above = x < self.x[0], x > self.x[-1]
np.place(out, below, self.f_below(x[below]))
np.place(out, above, self.f_above(x[above]))
return out
def f_above(self, x):
return f_lim(x)
def f_below(self, x):
return f_lim(x)
class BPolyAsympt(MixinAsympt, BPoly):
pass
class PPolyAsympt(MixinAsympt, PPoly):
pass
def f(x):
return np.log(1. + np.exp(x**4))
def f_lim(x):
return x**4
if __name__ == "__main__":
xi = np.linspace(-5, 5, 30)
yi = [[f(x)] for x in xi]
bp = BPolyAsympt.from_derivatives(xi, yi)
pp = PPolyAsympt.from_bernstein_basis(bp)
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
xx = np.linspace(-3, 7, 50)
ax.plot(xi, yi, 'ro', mec='r', ms=12, label='tabulated')
ax.plot(xx, bp(xx), 'm-', lw=6, alpha=0.4, label='bernstein')
ax.plot(xx, pp(xx), 'b-', lw=2, label='power, conv')
ax.legend(loc='lower left')
ax.set_yscale('log')
plt.savefig('asympt.png')
from __future__ import division, print_function, absolute_import
import numpy as np
from scipy.interpolate import BPoly, PPoly
"""
Piecewise polynomials w/ periodic boundary conditions.
"""
class MixinPBC(object):
def _evaluate(self, x, nu, extrapolate, out):
x = np.mod(x - self.x[0], self.x[-1] - self.x[0]) + self.x[0]
return super(MixinPBC, self)._evaluate(x, nu, False, out)
class BPolyPBC(MixinPBC, BPoly):
pass
class PPolyPBC(MixinPBC, PPoly):
pass
def plot_cos():
xi = np.linspace(0, np.pi, 20)
yi = np.asarray([[np.cos(x), -np.sin(x)] for x in xi])
bp = BPolyPBC.from_derivatives(xi, yi)
pp = PPolyPBC.from_bernstein_basis(bp)
import matplotlib.pyplot as plt
fig, (ax, ax1) = plt.subplots(2,1)
xx = np.linspace(-5, 5, 100)
ax.plot(xi, yi[:, 0], 'ro', mec='r', ms=12, label='tabulated')
ax.plot(xx, bp(xx), 'm-', lw=6, alpha=0.4, label='bernstein')
ax.plot(xx, pp(xx), 'b-', lw=2, label='converted')
ax.legend(loc='lower left')
# derivative
bpd = bp.derivative()
ppd = pp.derivative()
ax1.plot(xi, yi[:, 1], 'ro', mec='r', ms=12, label='f\', tabulated')
ax1.plot(xx, bpd(xx), 'm-', lw=6, alpha=0.4, label='f\', bernstein')
ax1.plot(xx, ppd(xx), 'b-', lw=2, label='f\', converted')
ax1.legend(loc='lower left')
plt.savefig('periodic.png')
if __name__ == "__main__":
plot_cos()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment