code: def _construct_graph_from_networkx(
      cls, g, vertex_attr_hashable: str = "_nx_name"
  ):
      """Converts the graph from networkx
  
      Vertex names will be stored as a vertex_attr_hashable attribute (usually
      "_nx_name", but see below). Because igraph stored vertices in an
      ordered manner, vertices will get new IDs from 0 up. In case of
      multigraphs, each edge will have an "_nx_multiedge_key" attribute, to
      distinguish edges that connect the same two vertices.
  
      @param g: networkx Graph or DiGraph
      @param vertex_attr_hashable: attribute used to store the Python
          hashable used by networkx to identify each vertex. The default value
          '_nx_name' ensures lossless round trip conversions to/from networkx. An
          alternative choice is 'name': in that case, using strings for vertex
          names is recommended and, if the graph is re-exported to networkx,
          Graph.to_networkx(vertex_attr_hashable="name") must be used to recover
          the correct vertex nomenclature in the exported network.
  
      """
      import networkx as nx
  
      # Graph attributes
      gattr = dict(g.graph)
  
      # Nodes
      vnames = list(g.nodes)
      vattr = {vertex_attr_hashable: vnames}
      vcount = len(vnames)
  
      # Dictionary connecting networkx hashables with igraph indices
      if len(g) and "_igraph_index" in next(iter(g.nodes.values())):
          # Collect _igraph_index and fill gaps
          idx = [x["_igraph_index"] for v, x in g.nodes.data()]
          idx.sort()
          idx_dict = {x: i for i, x in enumerate(idx)}
  
          vd = {}
          for v, datum in g.nodes.data():
              vd[v] = idx_dict[datum["_igraph_index"]]
      else:
          vd = {v: i for i, v in enumerate(vnames)}
  
      # NOTE: we do not need a special class for multigraphs, it is taken
      # care for at the edge level rather than at the graph level.
      graph = cls(
          n=vcount,
          directed=g.is_directed(),
          graph_attrs=gattr,
          vertex_attrs=vattr,
      )
  
      # Vertex attributes
      for v, datum in g.nodes.data():
          for key, val in datum.items():
              # Get rid of _igraph_index (we used it already)
              if key == "_igraph_index":
                  continue
              graph.vs[vd[v]][key] = val
  
      # Edges and edge attributes
      eattr_names = {
          name for (_, _, data) in g.edges.data() for name in data
      }
      eattr = {name: [] for name in eattr_names}
      edges = []
      # Multigraphs need a hidden attribute for multiedges
      if isinstance(g, (nx.MultiGraph, nx.MultiDiGraph)):
          eattr["_nx_multiedge_key"] = []
          for u, v, edgekey, data in g.edges.data(keys=True):
              edges.append((vd[u], vd[v]))
              for name in eattr_names:
                  eattr[name].append(data.get(name))
              eattr["_nx_multiedge_key"].append(edgekey)
  
      else:
          for u, v, data in g.edges.data():
              edges.append((vd[u], vd[v]))
              for name in eattr_names:
                  eattr[name].append(data.get(name))
  
      # Sort edges if there is a trace of a previous igraph ordering
      if "_igraph_index" in eattr:
          # Poor man's argsort
          sortd = list(enumerate(eattr["_igraph_index"]))
          sortd.sort(key=lambda x: x[1])
          idx = [i for i, x in sortd]
  
          # Get rid of the _igraph_index now
          del eattr["_igraph_index"]
  
          # Sort edges
          edges = [edges[i] for i in idx]
          # Sort each attribute
          eattr = {
              key: [val[i] for i in idx] for key, val in eattr.items()
          }
  
      graph.add_edges(edges, eattr)
  
      return graph
  
label_desc: Use image node_id 2 for calling a global function with example usage: _construct_graph_from_networkx(cls, g, vertex_attr_hashable) and returns: graph