def draw(self): '''Generate a random realization of the spline, based on the data.''' y_draw = num.random.normal(self.y, self.ey) self.realizations.append(\ spline2(self.x, y_draw, w=1.0/self.ey, **self.pars)) if len(self.realizations) > self.num_real_keep: self.realizations = self.realizations[1:] self.realization = self.realizations[-1]
def spdata(): x = arange(0,2*pi,0.1) y = sin(x) dy = y + 0.01 tck = spline2.spline2(x, y, w=1.0/dy) return (x,y,tck)
def _setup(self): '''Given the current set of params, setup the interpolator.''' x, y, ey = self._regularize() self.tck = spline2(x, y, w=1.0 / ey, **self.pars) self.setup = True self.realization = None
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)