# modalities.fmri.utils

## Module: `modalities.fmri.utils`

Inheritance diagram for `nipy.modalities.fmri.utils`:

This module defines some convenience functions of time.

interp : an expression for a interpolated function of time

linear_interpan expression for a linearly interpolated function of

  time

step_function : an expression for a step function of time

events : a convenience function to generate sums of events

blocks : a convenience function to generate sums of blocks

convolve_functions : numerically convolve two functions of time

fourier_basis : a convenience function to generate a Fourier basis

## Classes

### `Interp1dNumeric`

class nipy.modalities.fmri.utils.Interp1dNumeric(x, y, kind='linear', axis=-1, copy=True, bounds_error=None, fill_value=nan, assume_sorted=False)

  Bases: `interp1d`

  Wrapper for interp1 to raise TypeError for object array input

  We need this because sympy will try to evaluate interpolated functions when constructing expressions involving floats. At least sympy 1.0 only accepts TypeError or AttributeError as indication that the implemented value cannot be sampled with the sympy expression. Therefore, raise a TypeError directly for an input giving an object array (such as a sympy expression), rather than letting interp1d raise a ValueError.

  See:

  - https://github.com/nipy/nipy/issues/395

  - https://github.com/sympy/sympy/issues/10810

  __init__(x, y, kind='linear', axis=-1, copy=True, bounds_error=None, fill_value=nan, assume_sorted=False)

    Initialize a 1-D linear interpolation class.

  dtype
  property fill_value

    The fill value.

### `TimeConvolver`

class nipy.modalities.fmri.utils.TimeConvolver(expr, support, delta, fill=0)

  Bases: `object`

  Make a convolution kernel from a symbolic function of t

  A convolution kernel is a function with extra attributes to allow it to function as a kernel for numerical convolution (see `convolve_functions()`).

  Parameters:
    expr sympy expression

      An expression that is a function of t only.

    support 2 sequence

      Sequence is `(low, high)` where expression is defined between `low` and `high`, and can be assumed to be fill otherwise

    delta float

      smallest change in domain of expr to use for numerical evaluation of expr

  __init__(expr, support, delta, fill=0)
  convolve(g, g_interval, name=None, **kwargs)

    Convolve sympy expression g with this kernel

    Parameters:
      g sympy expr

        An expression that is a function of t only.

      g_interval(2,) sequence of floats

        Start and end of the interval of t over which to convolve g

      name None or str, optional

        Name of the convolved function in the resulting expression. Defaults to one created by `utils.interp`.

      **kwargs keyword args, optional

        Any other arguments to pass to the `interp1d` function in creating the numerical function for fg.

    Returns:
      fg sympy expr

        An symbolic expression that is a function of t only, and that can be lambdified to produce a function returning the convolved series from an input array.

## Functions

nipy.modalities.fmri.utils.blocks(intervals, amplitudes=None, name=None)

  Step function based on a sequence of intervals.

  Parameters:
    intervals(S,) sequence of (2,) sequences

      Sequence (S0, S1, … S(N-1)) of sequences, where S0 (etc) are sequences of length 2, giving ‘on’ and ‘off’ times of block

    amplitudes(S,) sequence of float, optional

      Optional amplitudes for each block. Defaults to 1.

    name None or str, optional

      Name of the convolved function in the resulting expression. Defaults to one created by `utils.interp`.

  Returns:
    b_of_t sympy expr

      Sympy expression b(t) where b is a sympy anonymous function of time that implements the block step function

  Examples

      >>> on_off = [[1,2],[3,4]]
      >>> tval = np.array([0.4,1.4,2.4,3.4])
      >>> b = blocks(on_off)
      >>> lam = lambdify_t(b)
      >>> lam(tval)
      array([ 0.,  1.,  0.,  1.])
      >>> b = blocks(on_off, amplitudes=[3,5])
      >>> lam = lambdify_t(b)
      >>> lam(tval)
      array([ 0.,  3.,  0.,  5.])

nipy.modalities.fmri.utils.convolve_functions(f, g, f_interval, g_interval, dt, fill=0, name=None, **kwargs)

  Expression containing numerical convolution of fn1 with fn2

  Parameters:
    f sympy expr

      An expression that is a function of t only.

    g sympy expr

      An expression that is a function of t only.

    f_interval(2,) sequence of float

      The start and end of the interval of t over which to convolve values of f

    g_interval(2,) sequence of floats

      Start and end of the interval of t over which to convolve g

    dt float

      Time step for discretization. We use this for creating the interpolator to form the numerical implementation

    fill None or float

      Value to return from sampling output fg function outside range.

    name None or str, optional

      Name of the convolved function in the resulting expression. Defaults to one created by `utils.interp`.

    **kwargs keyword args, optional

      Any other arguments to pass to the `interp1d` function in creating the numerical function for fg.

  Returns:
    fg sympy expr

      An symbolic expression that is a function of t only, and that can be lambdified to produce a function returning the convolved series from an input array.

  Examples

      >>> from nipy.algorithms.statistics.formula.formulae import Term
      >>> t = Term('t')

  This is a square wave on (0,1)

      >>> f1 = sympy.Piecewise((0, t <= 0), (1, t < 1), (0, True))

  The convolution of `f1` with itself is a triangular wave on [0, 2], peaking at 1 with height 1

      >>> tri = convolve_functions(f1, f1, [0, 2], [0, 2], 1.0e-3, name='conv')

  The result is a symbolic function

      >>> print(tri)
      conv(t)

  Get the numerical values for a time vector

      >>> ftri = lambdify(t, tri)
      >>> x = np.arange(0, 2, 0.2)
      >>> y = ftri(x)

  The peak is at 1 >>> x[np.argmax(y)] 1.0

nipy.modalities.fmri.utils.define(name, expr)

  Create function of t expression from arbitrary expression expr

  Take an arbitrarily complicated expression expr of ‘t’ and make it an expression that is a simple function of t, of form `'%s(t)' % name` such that when it evaluates (via `lambdify`) 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
      >>> expr
      t**2 + 3*t
      >>> newexpr = define('f', expr)
      >>> print(newexpr)
      f(t)
      >>> f = lambdify_t(newexpr)
      >>> f(4)
      28
      >>> 3*4+4**2
      28

nipy.modalities.fmri.utils.events(times, amplitudes=None, f=DiracDelta, g=a)

  Return a sum of functions based on a sequence of times.

  Parameters:
    times sequence

      vector of onsets length \(N\)

    amplitudes None or sequence length \(N\), optional

      Optional sequence of amplitudes. None (default) results in sequence length \(N\) of 1s

    f sympy.Function, optional

      Optional function. Defaults to DiracDelta, can be replaced with another function, f, in which case the result is the convolution with f.

    g sympy.Basic, optional

      Optional sympy expression function of amplitudes. The amplitudes, should be represented by the symbol ‘a’, which will be substituted, by the corresponding value in amplitudes.

  Returns:
    sum_expression Sympy.Add

      Sympy expression of time \(t\), where onsets, as a function of \(t\), have been symbolically convolved with function f, and any function g of corresponding amplitudes.

  Examples

  We import some sympy stuff so we can test if we’ve got what we expected

      >>> from sympy import DiracDelta, Symbol, Function
      >>> from nipy.modalities.fmri.utils import T
      >>> evs = events([3,6,9])
      >>> evs == DiracDelta(-9 + T) + DiracDelta(-6 + T) + DiracDelta(-3 + T)
      True
      >>> hrf = Function('hrf')
      >>> evs = events([3,6,9], f=hrf)
      >>> evs == hrf(-9 + T) + hrf(-6 + T) + hrf(-3 + T)
      True
      >>> evs = events([3,6,9], amplitudes=[2,1,-1])
      >>> evs == -DiracDelta(-9 + T) + 2*DiracDelta(-3 + T) + DiracDelta(-6 + T)
      True

nipy.modalities.fmri.utils.fourier_basis(freq)

  sin and cos Formula for Fourier drift

  The Fourier basis consists of sine and cosine waves of given frequencies.

  Parameters:
    freq sequence of float

      Frequencies for the terms in the Fourier basis.

  Returns:
    f Formula

  Examples

      >>> f=fourier_basis([1,2,3])
      >>> f.terms
      array([cos(2*pi*t), sin(2*pi*t), cos(4*pi*t), sin(4*pi*t), cos(6*pi*t),
             sin(6*pi*t)], dtype=object)
      >>> f.mean
      _b0*cos(2*pi*t) + _b1*sin(2*pi*t) + _b2*cos(4*pi*t) + _b3*sin(4*pi*t) + _b4*cos(6*pi*t) + _b5*sin(6*pi*t)

nipy.modalities.fmri.utils.interp(times, values, fill=0, name=None, **kw)

  Generic interpolation function of t given times and values

  Imterpolator such that:

  f(times[i]) = values[i]

  if t < times[0] or t > times[-1]:

    f(t) = fill

  See `scipy.interpolate.interp1d` for details of interpolation types and other keyword arguments. Default is ‘kind’ is linear, making this function, by default, have the same behavior as `linear_interp`.

  Parameters:
    times array-like

      Increasing sequence of times

    values array-like

      Values at the specified times

    fill None or float, optional

      Value on the interval (-np.inf, times[0]). Default 0. If None, raises error outside bounds

    name None or str, optional

      Name of symbolic expression to use. If None, a default is used.

    **kw keyword args, optional

      passed to `interp1d`

  Returns:
    f sympy expression

      A Function of t.

  Examples

      >>> s = interp([0,4,5.],[2.,4,6])
      >>> tval = np.array([-0.1,0.1,3.9,4.1,5.1])
      >>> res = lambdify_t(s)(tval)

  0 outside bounds by default

      >>> np.allclose(res, [0, 2.05, 3.95, 4.2, 0])
      True

nipy.modalities.fmri.utils.lambdify_t(expr)

  Return sympy function of t expr lambdified as function of t

  Parameters:
    expr sympy expr
  Returns:
    func callable

      Numerical implementation of function

nipy.modalities.fmri.utils.linear_interp(times, values, fill=0, name=None, **kw)

  Linear interpolation function of t given times and values

  Imterpolator such that:

  f(times[i]) = values[i]

  if t < times[0] or t > times[-1]:

    f(t) = fill

  This version of the function enforces the ‘linear’ kind of interpolation (argument to `scipy.interpolate.interp1d`).

  Parameters:
    times array-like

      Increasing sequence of times

    values array-like

      Values at the specified times

    fill None or float, optional

      Value on the interval (-np.inf, times[0]). Default 0. If None, raises error outside bounds

    name None or str, optional

      Name of symbolic expression to use. If None, a default is used.

    **kw keyword args, optional

      passed to `interp1d`

  Returns:
    f sympy expression

      A Function of t.

  Examples

      >>> s = linear_interp([0,4,5.],[2.,4,6])
      >>> tval = np.array([-0.1,0.1,3.9,4.1,5.1])
      >>> res = lambdify_t(s)(tval)

  0 outside bounds by default

      >>> np.allclose(res, [0, 2.05, 3.95, 4.2, 0])
      True

nipy.modalities.fmri.utils.step_function(times, values, name=None, fill=0)

  Right-continuous step function of time t

  Function of t such that

  f(times[i]) = values[i]

  if t < times[0]:

    f(t) = fill

  Parameters:
    times(N,) sequence

      Increasing sequence of times

    values(N,) sequence

      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_t sympy expr

      Sympy expression f(t) where f is a sympy implemented anonymous function of time that implements the step function. To get the numerical version of the function, use `lambdify_t(f_t)`

  Examples

      >>> s = step_function([0,4,5],[2,4,6])
      >>> tval = np.array([-0.1,3.9,4.1,5.1])
      >>> lam = lambdify_t(s)
      >>> lam(tval)
      array([ 0.,  2.,  4.,  6.])