code: def _graph_from_sparse_matrix(
      klass, matrix, mode="directed", loops="once"
  ):
      """Construct graph from sparse matrix, unweighted.
  
      @param loops: specifies how the diagonal of the matrix should be handled:
  
        - C{"ignore"} - ignore loop edges in the diagonal
        - C{"once"} - treat the diagonal entries as loop edge counts
        - C{"twice"} - treat the diagonal entries as I{twice} the number
          of loop edges
      """
      # This function assumes there is scipy and the matrix is a scipy sparse
      # matrix. The caller should make sure those conditions are met.
      from scipy import sparse
  
      if not isinstance(matrix, sparse.coo_matrix):
          matrix = matrix.tocoo()
  
      nvert = max(matrix.shape)
      if min(matrix.shape) != nvert:
          raise ValueError("Matrix must be square")
  
      # Shorthand notation
      m = matrix
  
      mode = _convert_mode_argument(mode)
  
      keep_loops = loops == "twice" or loops == "once" or loops is True
      m_row, m_col, m_data = _maybe_halve_diagonal(m, loops == "twice")
  
      if mode == "directed":
          edges = []
          for i, j, n in zip(m_row, m_col, m_data):
              if i != j or keep_loops:
                  edges.extend([(i, j)] * n)
  
      elif mode in ("max", "plus"):
          fun = max if mode == "max" else add
          nedges = {}
          for i, j, n in zip(m_row, m_col, m_data):
              if i == j and not keep_loops:
                  continue
              pair = (i, j) if i < j else (j, i)
              nedges[pair] = fun(nedges.get(pair, 0), n)
  
          edges = sum(
              ([e] * n for e, n in nedges.items()),
              [],
          )
  
      elif mode == "min":
          tmp = {(i, j): n for i, j, n in zip(m_row, m_col, m_data)}
  
          nedges = {}
          for pair, weight in tmp.items():
              i, j = pair
              if i == j and keep_loops:
                  nedges[pair] = weight
              elif i < j:
                  nedges[pair] = min(weight, tmp.get((j, i), 0))
  
          edges = sum(
              ([e] * n for e, n in nedges.items()),
              [],
          )
  
      elif mode == "upper":
          edges = []
          for i, j, n in zip(m_row, m_col, m_data):
              if j > i or (keep_loops and j == i):
                  edges.extend([(i, j)] * n)
  
      elif mode == "lower":
          edges = []
          for i, j, n in zip(m_row, m_col, m_data):
              if j < i or (keep_loops and j == i):
                  edges.extend([(i, j)] * n)
  
      else:
          raise ValueError(f"invalid mode: {mode!r}")
  
      return klass(nvert, edges=edges, directed=(mode == "directed"))
  
imports: from __future__ import with_statement
  from operator import add
  from igraph._igraph import ADJ_DIRECTED, ADJ_UNDIRECTED, ADJ_MAX, ADJ_MIN, ADJ_PLUS, ADJ_UPPER, ADJ_LOWER
label_desc: Use image node_id 3 for calling a global function with example usage: _graph_from_sparse_matrix(klass, matrix, mode, loops) and returns: klass