class_docstr: A Formula is a model for a mean in a regression model.
  
  It is often given by a sequence of sympy expressions, with the mean
  model being the sum of each term multiplied by a linear regression
  coefficient.
  
  The expressions may depend on additional Symbol instances, giving a
  non-linear regression model.
class_docstr_tok: ["A","Formula","is","a","model","for","a","mean","in","a","regression","model",".","It","is","often","given","by","a","sequence","of","sympy","expressions",",","with","the","mean","model","being","the","sum","of","each","term","multiplied","by","a","linear","regression","coefficient",".","The","expressions","may","depend","on","additional","Symbol","instances",",","giving","a","non-linear","regression","model","."]
docstr: Initialize design
  
  Create a callable object to evaluate the design matrix at a given set
  of parameter values to be specified by a recarray and observed Term
  values, also specified by a recarray.
docstr_tok: ["Initialize","design","Create","a","callable","object","to","evaluate","the","design","matrix","at","a","given","set","of","parameter","values","to","be","specified","by","a","recarray","and","observed","Term","values",",","also","specified","by","a","recarray","."]
code: def _setup_design(self):
      """Initialize design
  
      Create a callable object to evaluate the design matrix at a given set
      of parameter values to be specified by a recarray and observed Term
      values, also specified by a recarray.
      """
      # the design expression is the differentiation of the expression
      # for the mean.  It is a list
      d = self.design_expr
      # Before evaluating, we recreate the formula
      # with numbered terms, and numbered parameters.
  
      # This renaming has no impact on the
      # final design matrix as the
      # callable, self._f below, is a lambda
      # that does not care about the names of the terms.
  
      # First, find all terms in the mean expression,
      # and rename them in the form "__t%d__" with a
      # random offset.
      # This may cause a possible problem
      # when there are parameters named something like "__t%d__".
      # Using the random offset will minimize the possibility
      # of this happening.
  
      # This renaming is here principally because of the intercept.
  
      random_offset = np.random.randint(low=0, high=2**30)
  
      terms = getterms(self.mean)
  
      newterms = []
      for i, t in enumerate(terms):
          newt = sympy.Symbol("__t%d__" % (i + random_offset))
          for j, _ in enumerate(d):
              d[j] = d[j].subs(t, newt)
          newterms.append(newt)
  
      # Next, find all parameters that remain in the design expression.
      # In a standard regression model, there will be no parameters
      # because they will all be differentiated away in computing
      # self.design_expr. In nonlinear models, parameters will remain.
  
      params = getparams(self.design_expr)
      newparams = []
      for i, p in enumerate(params):
          newp = Dummy("__p%d__" % (i + random_offset))
          for j, _ in enumerate(d):
              d[j] = d[j].subs(p, newp)
          newparams.append(newp)
  
      # If there are any aliased functions, these need to be added
      # to the name space before sympy lambdifies the expression
  
      # These "aliased" functions are used for things like
      # the natural splines, etc. You can represent natural splines
      # with sympy but the expression is pretty awful.  Note that
      # ``d`` here is list giving the differentiation of the
      # expression for the mean.  self._f(...) therefore also returns
      # a list
      self._f = lambdify(newparams + newterms, d, ("numpy"))
  
      # The input to self.design will be a recarray of that must
      # have field names that the Formula will expect to see.
      # However, if any of self.terms are FactorTerms, then the field
      # in the recarray will not actually be in the Term.
      #
      # For example, if there is a Factor 'f' with levels ['a','b'],
      # there will be terms 'f_a' and 'f_b', though the input to
      # design will have a field named 'f'. In this sense,
      # the recarray used in the call to self.design
      # is not really made up of terms, but "preterms".
  
      # In this case, the callable
  
      preterm = []
      for t in terms:
          if not is_factor_term(t):
              preterm.append(str(t))
          else:
              preterm.append(t.factor_name)
      preterm = list(set(preterm))
  
      # There is also an argument for parameters that are not
      # Terms.
  
      self._dtypes = {
          "param": np.dtype([(str(p), np.float64) for p in params]),
          "term": np.dtype([(str(t), np.float64) for t in terms]),
          "preterm": np.dtype([(n, np.float64) for n in preterm]),
      }
  
      self.__terms = terms
  
imports: import itertools
  import warnings
  from string import ascii_letters, digits
  import numpy
  import sympy
  from scipy.linalg import pinv
  from sympy import Dummy, default_sort_key
  from sympy.utilities.lambdify import implemented_function, lambdify
  from nipy.algorithms.utils.matrices import full_rank, matrix_rank
  from nipy.utils import VisibleDeprecationWarning, _NoValue
label_desc: Use image node_id 17 for calling the Formula obj's underlying member method code with example usage: obj._setup_design() without return types