def define(name, expr): """ Take an expression of 't' (possibly complicated) and make it a '%s(t)' % name, such that when it evaluates it has the right values. Parameters ---------- expr : sympy expression, with only 't' as a Symbol name : str Returns ------- nexpr: sympy expression Examples -------- >>> t = Term('t') >>> expr = t**2 + 3*t >>> print expr 3*t + t**2 >>> newexpr = define('f', expr) >>> print newexpr f(t) >>> import aliased >>> f = aliased.lambdify(t, newexpr) >>> f(4) 28 >>> 3*4+4**2 28 >>> """ v = vectorize(expr) return aliased_function(name, v)(Term('t'))
def step_function(times, values, name=None, fill=0): """ Right-continuous step function such that f(times[i]) = values[i] if t < times[0]: f(t) = fill Parameters ---------- times : ndarray Increasing sequence of times values : ndarray Values at the specified times fill : float Value on the interval (-np.inf, times[0]) name : str Name of symbolic expression to use. If None, a default is used. Returns ------- f : Formula A Formula with only a step function, as a function of t. Examples -------- >>> s=step_function([0,4,5],[2,4,6]) >>> tval = np.array([-0.1,3.9,4.1,5.1]).view(np.dtype([('t', np.float)])) >>> s.design(tval) array([(0.0,), (2.0,), (4.0,), (6.0,)], dtype=[('step0(t)', '<f8')]) >>> """ times = np.asarray(times) values = np.asarray(values) def anon(x, times=times, values=values, fill=fill): d = values[1:] - values[:-1] f = np.less(x, times[0]) * fill + np.greater(x, times[0]) * values[0] for i in range(d.shape[0]): f = f + np.greater(x, times[i+1]) * d[i] return f if name is None: name = 'step%d' % step_function.counter step_function.counter += 1 s = aliased_function(name, anon) return s(t)
def linear_interp(times, values, fill=0, name=None, **kw): """ Linear interpolation function such that f(times[i]) = values[i] if t < times[0]: f(t) = fill Inputs: ======= times : ndarray Increasing sequence of times values : ndarray Values at the specified times fill : float Value on the interval (-np.inf, times[0]) name : str Name of symbolic expression to use. If None, a default is used. Outputs: ======== f : sympy expression A Function of t. Examples: ========= >>> s=linear_interp([0,4,5.],[2.,4,6], bounds_error=False) >>> tval = np.array([-0.1,0.1,3.9,4.1,5.1]).view(np.dtype([('t', np.float)])) >>> s.design(tval) array([(nan,), (2.0499999999999998,), (3.9500000000000002,), (4.1999999999999993,), (nan,)], dtype=[('interp0(t)', '<f8')]) """ kw['kind'] = 'linear' i = interp1d(times, values, **kw) if name is None: name = 'interp%d' % linear_interp.counter linear_interp.counter += 1 s = aliased_function(name, i) return s(t)
def natural_spline(t, knots=None, order=3, intercept=False): """ Return a Formula containing a natural spline Spline for a Term with specified `knots` and `order`. Parameters ---------- t : ``Term`` knots : None or sequence, optional Sequence of float. Default None (same as empty list) order : int, optional Order of the spline. Defaults to a cubic (==3) intercept : bool, optional If True, include a constant function in the natural spline. Default is False Returns ------- formula : Formula A Formula with (len(knots) + order) Terms (if intercept=False, otherwise includes one more Term), made up of the natural spline functions. Examples -------- The following results depend on machine byte order >>> x = Term('x') >>> n = natural_spline(x, knots=[1,3,4], order=3) >>> xval = np.array([3,5,7.]).view(np.dtype([('x', np.float)])) >>> n.design(xval, return_float=True) array([[ 3., 9., 27., 8., 0., -0.], [ 5., 25., 125., 64., 8., 1.], [ 7., 49., 343., 216., 64., 27.]]) >>> d = n.design(xval) >>> print d.dtype.descr [('ns_1(x)', '<f8'), ('ns_2(x)', '<f8'), ('ns_3(x)', '<f8'), ('ns_4(x)', '<f8'), ('ns_5(x)', '<f8'), ('ns_6(x)', '<f8')] >>> """ if knots is None: knots = {} fns = [] for i in range(order+1): n = 'ns_%d' % i def f(x, i=i): return x**i s = aliased_function(n, f) fns.append(s(t)) for j, k in enumerate(knots): n = 'ns_%d' % (j+i+1,) def f(x, k=k, order=order): return (x-k)**order * np.greater(x, k) s = aliased_function(n, f) fns.append(s(t)) if not intercept: fns.pop(0) ff = Formula(fns) return ff