code: def make_recarray(rows, names, dtypes=None, drop_name_dim=_NoValue):
      """Create recarray from `rows` with field names `names`
  
      Create a recarray with named columns from a list or ndarray of `rows` and
      sequence of `names` for the columns. If `rows` is an ndarray, `dtypes` must
      be None, otherwise we raise a ValueError. Otherwise, if `dtypes` is None,
      we cast the data in all columns in `rows` as np.float64. If `dtypes` is not
      None, the routine uses `dtypes` as a dtype specifier for the output
      structured array.
  
      Parameters
      ----------
      rows: list or array
          Rows that will be turned into an recarray.
      names: sequence
          Sequence of strings - names for the columns.
      dtypes: None or sequence of str or sequence of np.dtype, optional
          Used to create a np.dtype, can be sequence of np.dtype or string.
      drop_name_dim : {_NoValue, False, True}, optional
          Flag for compatibility with future default behavior.  Current default
          is False.  If True, drops the length 1 dimension corresponding to the
          axis transformed into fields when converting into a recarray.  If
          _NoValue specified, gives default.  Default will change to True in the
          next version of Nipy.
  
      Returns
      -------
      v : np.ndarray
          Structured array with field names given by `names`.
  
      Examples
      --------
      The following tests depend on machine byte order for their exact output.
  
      >>> arr = np.array([[3, 4], [4, 6], [6, 8]])
      >>> make_recarray(arr, ['x', 'y'],
      ...               drop_name_dim=True) #doctest: +FIX
      array([(3, 4), (4, 6), (6, 8)],
            dtype=[('x', '<i8'), ('y', '<i8')])
      >>> make_recarray(arr, ['x', 'y'],
      ...               drop_name_dim=False) #doctest: +FIX
      array([[(3, 4)],
             [(4, 6)],
             [(6, 8)]],
            dtype=[('x', '<i8'), ('y', '<i8')])
      >>> r = make_recarray(arr, ['w', 'u'], drop_name_dim=True)
      >>> make_recarray(r, ['x', 'y'],
      ...               drop_name_dim=True) #doctest: +FIX
      array([(3, 4), (4, 6), (6, 8)],
            dtype=[('x', '<i8'), ('y', '<i8')])
      >>> make_recarray([[3, 4], [4, 6], [7, 9]], 'wv',
      ...               [np.float64, np.int_])  #doctest: +FIX +FLOAT_CMP
      array([(3.0, 4), (4.0, 6), (7.0, 9)],
            dtype=[('w', '<f8'), ('v', '<i8')])
  
      Raises
      ------
      ValueError
          `dtypes` not None when `rows` is array.
      """
      # XXX This function is sort of one of convenience
      # Would be nice to use DataArray or something like that
      # to add axis names.
      if isinstance(rows, np.ndarray):
          if dtypes is not None:
              raise ValueError("dtypes not used if rows is an ndarray")
          return _recarray_from_array(rows, names, drop_name_dim)
      # Structured array from list
      if dtypes is None:
          dtype = np.dtype([(n, np.float64) for n in names])
      else:
          dtype = np.dtype(list(zip(names, dtypes)))
      # Peek at first value in iterable
      irows = iter(rows)
      row0 = next(irows)
      irows = itertools.chain([row0], irows)
      if np.array(row0).shape == ():  # a vector
          if len(names) != 1:  # a 'row vector'
              return np.array(tuple(irows), dtype)
          return np.array([(r,) for r in irows], dtype)
      return np.array([tuple(r) for r in irows], dtype)
  
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 8 for calling a global function with example usage: make_recarray(rows, names, dtypes, drop_name_dim) and returns: np, _recarray_from_array, np, np