code: def _to_networkx_heterogeneous(
      g, node_attrs, edge_attrs, ntype_attr, etype_attr, eid_attr
  ):
      nx_graph = nx.MultiDiGraph()
  
      # This implementation does not use `ndata` and `edata` in the call to
      # `to_homogeneous` because the function expects node and edge attributes
      # both to be defined for every type and to have the same shape.
      # If the `to_homogeneous` function is updated to support non-uniform node
      # and edge attributes, the implementation can be simplified.
      hom_g = to_homogeneous(g, store_type=True, return_count=False)
      ntypes = g.ntypes
      etypes = g.canonical_etypes
  
      for hom_nid, ndata in enumerate(
          zip(hom_g.ndata[NID], hom_g.ndata[NTYPE])
      ):
          orig_nid, ntype = ndata
          attrs = {ntype_attr: ntypes[ntype]}
  
          if node_attrs is not None:
              assert ntype_attr not in node_attrs, (
                  f"'{ntype_attr}' already used as node type attribute, "
                  f"please provide a different value for ntype_attr"
              )
  
              feat_dict = g._get_n_repr(ntype, orig_nid)
              attrs.update(
                  {
                      key: F.squeeze(feat_dict[key], 0)
                      for key in node_attrs
                      if key in feat_dict
                  }
              )
  
          nx_graph.add_node(hom_nid, **attrs)
  
      for hom_eid, edata in enumerate(
          zip(hom_g.edata[EID], hom_g.edata[ETYPE])
      ):
          orig_eid, etype = edata
          attrs = {eid_attr: hom_eid, etype_attr: etypes[etype]}
  
          if edge_attrs is not None:
              assert etype_attr not in edge_attrs, (
                  f"'{etype_attr}' already used as edge type attribute, "
                  f"please provide a different value for etype_attr"
              )
              assert eid_attr not in edge_attrs, (
                  f"'{eid_attr}' already used as edge ID attribute, "
                  f"please provide a different value for eid_attr"
              )
  
              feat_dict = g._get_e_repr(etype, orig_eid)
              attrs.update(
                  {
                      key: F.squeeze(feat_dict[key], 0)
                      for key in edge_attrs
                      if key in feat_dict
                  }
              )
  
          src, dst = hom_g.find_edges(hom_eid)
          nx_graph.add_edge(int(src), int(dst), **attrs)
  
      return nx_graph
  
imports: from collections import defaultdict
  from collections.abc import Mapping
  import networkx
  import numpy
  from scipy.sparse import spmatrix
  from .None import backend, graph_index, heterograph_index, utils
  from .base import DGLError, EID, ETYPE, NID, NTYPE
  from .heterograph import combine_frames, DGLBlock, DGLGraph
label_desc: Use image node_id 14 for calling a global function with example usage: _to_networkx_heterogeneous(g, node_attrs, edge_attrs, ntype_attr, etype_attr, eid_attr) and returns: nx_graph