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: Construct the design matrix, and optional contrast matrices.
  
  Parameters
  ----------
  input : np.recarray
     Recarray including fields needed to compute the Terms in
     getparams(self.design_expr).
  param : None or np.recarray
     Recarray including fields that are not Terms in
     getparams(self.design_expr)
  return_float : bool, optional
     If True, return a np.float64 array rather than a np.recarray
  contrasts : None or dict, optional
     Contrasts. The items in this dictionary should be (str,
     Formula) pairs where a contrast matrix is constructed for
     each Formula by evaluating its design at the same parameters
     as self.design. If not None, then the return_float is set to True.
  
  Returns
  -------
  des : 2D array
      design matrix
  cmatrices : dict, optional
      Dictionary with keys from `contrasts` input, and contrast matrices
      corresponding to `des` design matrix.  Returned only if `contrasts`
      input is not None
docstr_tok: ["Construct","the","design","matrix",",","and","optional","contrast","matrices",".","Parameters","--","--","--","--","--","input",":","np.recarray","Recarray","including","fields","needed","to","compute","the","Terms","in","getparams","(","self.design_expr",")",".","param",":","None","or","np.recarray","Recarray","including","fields","that","are","not","Terms","in","getparams","(","self.design_expr",")","return_float",":","bool",",","optional","If","True",",","return","a","np.float64","array","rather","than","a","np.recarray","contrasts",":","None","or","dict",",","optional","Contrasts",".","The","items","in","this","dictionary","should","be","(","str",",","Formula",")","pairs","where","a","contrast","matrix","is","constructed","for","each","Formula","by","evaluating","its","design","at","the","same","parameters","as","self.design",".","If","not","None",",","then","the","return_float","is","set","to","True",".","Returns","--","--","--","-","des",":","2D","array","design","matrix","cmatrices",":","dict",",","optional","Dictionary","with","keys","from","`","contrasts","`","input",",","and","contrast","matrices","corresponding","to","`","des","`","design","matrix",".","Returned","only","if","`","contrasts","`","input","is","not","None"]
code: def design(
      self, input, param=None, return_float=False, contrasts=None
  ):
      """Construct the design matrix, and optional contrast matrices.
  
      Parameters
      ----------
      input : np.recarray
         Recarray including fields needed to compute the Terms in
         getparams(self.design_expr).
      param : None or np.recarray
         Recarray including fields that are not Terms in
         getparams(self.design_expr)
      return_float : bool, optional
         If True, return a np.float64 array rather than a np.recarray
      contrasts : None or dict, optional
         Contrasts. The items in this dictionary should be (str,
         Formula) pairs where a contrast matrix is constructed for
         each Formula by evaluating its design at the same parameters
         as self.design. If not None, then the return_float is set to True.
  
      Returns
      -------
      des : 2D array
          design matrix
      cmatrices : dict, optional
          Dictionary with keys from `contrasts` input, and contrast matrices
          corresponding to `des` design matrix.  Returned only if `contrasts`
          input is not None
      """
      self._setup_design()
  
      preterm_recarray = input
      param_recarray = param
  
      # The input to design should have field names for all fields in self._dtypes['preterm']
      if not set(preterm_recarray.dtype.names).issuperset(
          self._dtypes["preterm"].names
      ):
          raise ValueError(
              "for term, expecting a recarray with "
              "dtype having the following names: {!r}".format(
                  self._dtypes["preterm"].names
              )
          )
      # The parameters should have field names for all fields in self._dtypes['param']
      if param_recarray is not None:
          if not set(param_recarray.dtype.names).issuperset(
              self._dtypes["param"].names
          ):
              raise ValueError(
                  "for param, expecting a recarray with "
                  "dtype having the following names: {!r}".format(
                      self._dtypes["param"].names
                  )
              )
      # If the only term is an intercept,
      # the return value is a matrix of 1's.
      if list(self.terms) == [sympy.Number(1)]:
          a = np.ones(preterm_recarray.shape[0], np.float64)
          if not return_float:
              a = a.view(np.dtype([("intercept", np.float64)]))
          return a
      elif not self._dtypes["term"]:
          raise ValueError(
              "none of the expressions in self.terms "
              "are Term instances; shape of resulting "
              "undefined"
          )
      # The term_recarray is essentially the same as preterm_recarray,
      # except that all factors in self are expanded
      # into their respective binary columns.
      term_recarray = np.zeros(
          preterm_recarray.shape[0], dtype=self._dtypes["term"]
      )
      for t in self.__terms:
          if not is_factor_term(t):
              term_recarray[t.name] = preterm_recarray[t.name]
          else:
              factor_col = preterm_recarray[t.factor_name]
              # Python 3: If column type is bytes, convert to string, to allow
              # level comparison
              if factor_col.dtype.kind == "S":
                  factor_col = factor_col.astype("U")
              fl_ind = np.array(
                  [x == t.level for x in factor_col]
              ).reshape(-1)
              term_recarray[f"{t.factor_name}_{t.level}"] = fl_ind
      # The lambda created in self._setup_design needs to take a tuple of
      # columns as argument, not an ndarray, so each column
      # is extracted and put into float_tuple.
      float_array = term_recarray.view(np.float64)
      float_array.shape = (term_recarray.shape[0], -1)
      float_array = float_array.T
      float_tuple = tuple(float_array)
      # If there are any parameters, they also must be extracted
      # and put into a tuple with the order specified
      # by self._dtypes['param']
      if param_recarray is not None:
          param = tuple(
              float(param_recarray[n])
              for n in self._dtypes["param"].names
          )
      else:
          param = ()
      # Evaluate the design at the parameters and tuple of arrays
      D = self._f(*(param + float_tuple))
      # TODO: check if this next stepis necessary
      # I think it is because the lambda evaluates sympy.Number(1) to 1
      # and not an array.
      D_tuple = [np.asarray(w) for w in D]
  
      need_to_modify_shape = []
      OK_row_shapes = []
      for i, row in enumerate(D_tuple):
          if row.shape in [(), (1,)]:
              need_to_modify_shape.append(i)
          else:
              OK_row_shapes.append(row.shape[0])
      # Make sure that each array has the correct shape.
      # The columns in need_to_modify should just be
      # the intercept column, which evaluates to have shape == ().
      # This makes sure that it has the correct number of rows.
      for i in need_to_modify_shape:
          D_tuple[i].shape = ()
          D_tuple[i] = np.multiply.outer(
              D_tuple[i], np.ones(preterm_recarray.shape[0])
          )
      # At this point, all the columns have the correct shape and the
      # design matrix is almost ready to output.
      D = np.array(D_tuple).T
      # If we will return a float matrix or any contrasts,
      # we may have some reshaping to do.
      if contrasts is None:
          contrasts = {}
      if return_float or contrasts:
          # If the design matrix is just a column of 1s
          # return a 1-dimensional array.
          D = np.squeeze(D.astype(np.float64))
          # If there are contrasts, the pseudo-inverse of D
          # must be computed.
          if contrasts:
              if D.ndim == 1:
                  _D = D.reshape((D.shape[0], 1))
              else:
                  _D = D
              pinvD = np.linalg.pinv(_D)
      else:
          # Correct the dtype.
          # XXX There seems to be a lot of messing around with the dtype.
          # This would be a convenient place to just add
          # labels like a DataArray.
          D = np.array([tuple(r) for r in D], self.dtype)
      # Compute the contrast matrices, if any.
      if contrasts:
          cmatrices = {}
          for key, cf in contrasts.items():
              if not is_formula(cf):
                  cf = Formula([cf])
              L = cf.design(
                  input, param=param_recarray, return_float=True
              )
              cmatrices[key] = contrast_from_cols_or_rows(
                  L, _D, pseudo=pinvD
              )
          return D, cmatrices
      else:
          return D
  
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 18 for calling the Formula obj's underlying member method code with example usage: obj.design(input, param, return_float, contrasts) and returns: a, D,  cmatrices, D