def __call__(self, x): '''Interpolate at point [x]. Returns a 3-tuple: (y, mask) where [y] is the interpolated point, and [mask] is a boolean array with the same shape as [x] and is True where interpolated and False where extrapolated''' if not self.setup: self._setup() if len(num.shape(x)) < 1: scalar = True else: scalar = False x = num.atleast_1d(x) if self.realization: evm = num.atleast_1d(evalsp(x, self.realization)) mask = num.greater_equal(x, self.realization[0][0])*\ num.less_equal(x,self.realization[0][-1]) else: evm = num.atleast_1d(evalsp(x, self.tck)) mask = num.greater_equal(x, self.tck[0][0]) * num.less_equal( x, self.tck[0][-1]) if scalar: return evm[0], mask[0] else: return evm, mask
def __call__(self, x): '''Interpolate at point [x]. Returns a 3-tuple: (y, mask) where [y] is the interpolated point, and [mask] is a boolean array with the same shape as [x] and is True where interpolated and False where extrapolated''' if not self.setup: self._setup() if len(num.shape(x)) < 1: scalar = True else: scalar = False x = num.atleast_1d(x) if self.realization: evm = num.atleast_1d(evalsp(x, self.realization)) mask = num.greater_equal(x, self.realization[0][0])*\ num.less_equal(x,self.realization[0][-1]) else: evm = num.atleast_1d(evalsp(x, self.tck)) mask = num.greater_equal(x, self.tck[0][0])*num.less_equal(x,self.tck[0][-1]) if scalar: return evm[0],mask[0] else: return evm,mask
def deriv(self, x, n=1): '''Returns the nth derivative of the function at x.''' if self.realization: tck = self.realization else: tck = self.tck if len(num.shape(x)) < 1: scalar = True else: scalar = False x = num.atleast_1d(x) if self.realization: evm = num.atleast_1d(evalsp(x, self.realization, deriv=n)) else: evm = num.atleast_1d(evalsp(x, self.tck, deriv=n)) if scalar: return evm[0] else: return evm
def test_spline2(spdata): x,y,tck = spdata yeval = spline2.evalsp(x, tck) assert alltrue(absolute(yeval-y) < 0.01)
def make_spline2(t, m, e_m, k=3, fitflux=0, zpt=0, tmin=-10, tmax=100, adaptive=0, max_curv_fac=10, **args): """A wrapper around spline2 that makes sure the independent variable is monotonic and non-repeating. Required arguments: time (t), magnitudes (m) and errors (e_m). k is the spline order (default 3) If fitflux is nonzero, convert magnitudes to flux (using provided zpt). tmin and tmax should be set to the limits of the spline.""" # first, we make sure that t is monotonically increasing with no repeated # elements sids = num.argsort(t) tt = num.take(t, sids) mm = num.take(m, sids) ee_m = num.take(e_m, sids) # here's some Numeric magic. first, find where we have repeating x-values Nmatrix = num.equal(tt[:, num.newaxis], tt[num.newaxis, :]) # val_matrix = mm[:,num.newaxis]*num.ones((len(mm),len(mm))) # e_matrix = ee_m[:,num.newaxis]*num.ones((len(mm),len(mm))) val_matrix = mm[:, num.newaxis] * Nmatrix e_matrix = ee_m[:, num.newaxis] * Nmatrix average = sum(val_matrix) / sum(Nmatrix) e_average = sum(e_matrix) / sum(Nmatrix) # at this point, average is the original data, but with repeating data points # replaced with their average. Now, we just pick out the unique x's and # the first of any repeating points: gids = num.concatenate([[True], num.greater(tt[1:] - tt[:-1], 0.0)]) tt = tt[gids] # num.compress(gids, tt) mm = average[gids] # num.compress(gids, average) ee_m = e_average[gids] # num.compress(gids, e_average) # Now get rid of any data that's outside [tmin,tmax] gids = num.less_equal(tt, tmax) * num.greater_equal(tt, tmin) tt = tt[gids] # num.compress(gids,tt) mm = mm[gids] # num.compress(gids,mm) ee_m = ee_m[gids] # num.compress(gids,ee_m) ee_m = num.where(num.less(ee_m, 0.001), 0.001, ee_m) # Now convert to flux if requested: if fitflux: mm = num.power(10, -0.4 * (mm - zpt)) ee_m = mm * ee_m / 1.087 # Okay, now make the spline representation if not adaptive: tck = spline2.spline2(tt, mm, w=1.0 / ee_m, degree=k, **args) fp = num.sum(num.power((mm - spline2.evalsp(tt, tck)) / ee_m, 2)) ier = 0 msg = "not much" return (tck, fp, ier, msg) # Do an adaptive (much slower) search for the best fit, subject # to curvature constraints (right now, just a cap). if "lopt" in args: del args["lopt"] Ks = [] chisqs = [] lopts = range(2, int(0.8 * len(tt) - 1)) for l in lopts: tck = spline2.spline2(tt, mm, w=1.0 / ee_m, degree=k, lopt=l, **args) fp = num.sum(num.power((mm - spline2.evalsp(tt, tck)) / ee_m, 2)) K = quad(K2, tck[0][0], tck[0][-1], args=(tck,), epsrel=0.01)[0] chisqs.append(fp) Ks.append(K) chisqs = num.array(chisqs) Ks = num.array(Ks) chisqs = num.where(num.less(Ks, Ks.min() * max_curv_fac), chisqs, num.Inf) id = num.argmin(chisqs) ier = lopts[id] tck = spline2.spline2(tt, mm, w=1.0 / ee_m, degree=k, lopt=ier, **args) fp = num.sum(num.power((mm - spline2.evalsp(tt, tck)) / ee_m, 2)) return (tck, fp, ier, "Optimized lopt = %d" % ier)
def K2(x, tck): """compute the square curvature of a spline2 at point x""" yp = num.power(spline2.evalsp(x, tck, 1), 2) ypp = num.power(spline2.evalsp(x, tck, 2), 2) return ypp / num.power(1 + yp, 3)
def make_spline2(t, m, e_m, k=3, fitflux=0, zpt=0, tmin=-10, tmax=100, adaptive=0, max_curv_fac=10, **args): '''A wrapper around spline2 that makes sure the independent variable is monotonic and non-repeating. Required arguments: time (t), magnitudes (m) and errors (e_m). k is the spline order (default 3) If fitflux is nonzero, convert magnitudes to flux (using provided zpt). tmin and tmax should be set to the limits of the spline.''' # first, we make sure that t is monotonically increasing with no repeated # elements sids = num.argsort(t) tt = num.take(t, sids) mm = num.take(m, sids) ee_m = num.take(e_m, sids) # here's some Numeric magic. first, find where we have repeating x-values Nmatrix = num.equal(tt[:, num.newaxis], tt[num.newaxis, :]) #val_matrix = mm[:,num.newaxis]*num.ones((len(mm),len(mm))) #e_matrix = ee_m[:,num.newaxis]*num.ones((len(mm),len(mm))) val_matrix = mm[:, num.newaxis] * Nmatrix e_matrix = ee_m[:, num.newaxis] * Nmatrix average = sum(val_matrix) / sum(Nmatrix) e_average = sum(e_matrix) / sum(Nmatrix) # at this point, average is the original data, but with repeating data points # replaced with their average. Now, we just pick out the unique x's and # the first of any repeating points: gids = num.concatenate([[True], num.greater(tt[1:] - tt[:-1], 0.)]) tt = tt[gids] #num.compress(gids, tt) mm = average[gids] # num.compress(gids, average) ee_m = e_average[gids] #num.compress(gids, e_average) # Now get rid of any data that's outside [tmin,tmax] gids = num.less_equal(tt, tmax) * num.greater_equal(tt, tmin) tt = tt[gids] #num.compress(gids,tt) mm = mm[gids] # num.compress(gids,mm) ee_m = ee_m[gids] #num.compress(gids,ee_m) ee_m = num.where(num.less(ee_m, 0.001), 0.001, ee_m) # Now convert to flux if requested: if fitflux: mm = num.power(10, -0.4 * (mm - zpt)) ee_m = mm * ee_m / 1.087 # Okay, now make the spline representation if not adaptive: tck = spline2.spline2(tt, mm, w=1.0 / ee_m, degree=k, **args) fp = num.sum(num.power((mm - spline2.evalsp(tt, tck)) / ee_m, 2)) ier = 0 msg = 'not much' return (tck, fp, ier, msg) # Do an adaptive (much slower) search for the best fit, subject # to curvature constraints (right now, just a cap). if 'lopt' in args: del args['lopt'] Ks = [] chisqs = [] lopts = range(2, int(0.8 * len(tt) - 1)) for l in lopts: tck = spline2.spline2(tt, mm, w=1.0 / ee_m, degree=k, lopt=l, **args) fp = num.sum(num.power((mm - spline2.evalsp(tt, tck)) / ee_m, 2)) K = quad(K2, tck[0][0], tck[0][-1], args=(tck, ), epsrel=0.01)[0] chisqs.append(fp) Ks.append(K) chisqs = num.array(chisqs) Ks = num.array(Ks) chisqs = num.where(num.less(Ks, Ks.min() * max_curv_fac), chisqs, num.Inf) id = num.argmin(chisqs) ier = lopts[id] tck = spline2.spline2(tt, mm, w=1.0 / ee_m, degree=k, lopt=ier, **args) fp = num.sum(num.power((mm - spline2.evalsp(tt, tck)) / ee_m, 2)) return (tck, fp, ier, "Optimized lopt = %d" % ier)
def K2(x, tck): '''compute the square curvature of a spline2 at point x''' yp = num.power(spline2.evalsp(x, tck, 1), 2) ypp = num.power(spline2.evalsp(x, tck, 2), 2) return (ypp / num.power(1 + yp, 3))