code: def parse_optional_matrix(x):
      
  
      # Split input by spaces to get each row and convert into a vector. The row can be 'none', in which case it will
      # return None
      matrix = [parse_optional_vector(x, dtype=float) for x in x.split()]
  
      # Get the size of each row vector, 0 if None
      sizes = np.array([0 if x is None else len(x) for x in matrix])
  
      # Get sizes of each row vector removing duplicate sizes
      # Since each row vector should be same size, the unique sizes should return one value for the row size or it may
      # return a second one (0) if there are None vectors
      unique_sizes = np.unique(sizes)
  
      if len(unique_sizes) != 1 and (len(unique_sizes) != 2 or unique_sizes.min() != 0):
          raise NRRDError('Matrix should have same number of elements in each row')
  
      # Create a vector row of NaN's that matches same size of remaining vector rows
      # Stack the vector rows together to create matrix
      nan_row = np.full((unique_sizes.max()), np.nan)
      matrix = np.vstack([nan_row if x is None else x for x in matrix])
  
      return matrix
docs: Parse optional NRRD matrix from string into (M,N) :class:`numpy.ndarray` of :class:`float`.
  
      Function parses optional NRRD matrix from string into an (M,N) :class:`numpy.ndarray` of :class:`float`. This
      function works the same as :meth:`parse_matrix` except if a row vector in the matrix is none, the resulting row in
      the returned matrix will be all NaNs.
  
      See :ref:`user-guide:double matrix` for more information on the format.
  
      Parameters
      ----------
      x : :class:`str`
          String containing NRRD matrix
  
      Returns
      -------
      matrix : (M,N) :class:`numpy.ndarray` of :class:`float`
          Matrix that is parsed from the :obj:`x` string