docs: def _prepare_input(expression_data,
                     gene_names,
                     tf_names):
      """
      Wrangle the inputs into the correct formats.
  
      :param expression_data: one of:
                              * a pandas DataFrame (rows=observations, columns=genes)
                              * a dense 2D numpy.ndarray
                              * a sparse scipy.sparse.csc_matrix
      :param gene_names: optional list of gene names (strings).
                         Required when a (dense or sparse) matrix is passed as 'expression_data' instead of a DataFrame.
      :param tf_names: optional list of transcription factors. If None or 'all', the list of gene_names will be used.
      :return: a triple of:
               1. a np.ndarray or scipy.sparse.csc_matrix
               2. a list of gene name strings
               3. a list of transcription factor name strings.
      """
  
      if isinstance(expression_data, pd.DataFrame):
          expression_matrix = expression_data.as_matrix()
          gene_names = list(expression_data.columns)
      else:
          expression_matrix = expression_data
          assert expression_matrix.shape[1] == len(gene_names)
  
      if tf_names is None:
          tf_names = gene_names
      elif tf_names == 'all':
          tf_names = gene_names
      else:
          if len(tf_names) == 0:
              raise ValueError('Specified tf_names is empty')
  
          if not set(gene_names).intersection(set(tf_names)):
              raise ValueError('Intersection of gene_names and tf_names is empty.')
  
      return expression_matrix, gene_names, tf_names