docs: def get_undirected(G):
      """
      Convert a directed graph to an undirected graph that maintains parallel
      edges if geometries differ.
  
      Parameters
      ----------
      G : networkx multidigraph
  
      Returns
      -------
      networkx multigraph
      """
  
      start_time = time.time()
  
      # set from/to nodes before making graph undirected
      G = G.copy()
      for u, v, k, data in G.edges(keys=True, data=True):
          G.edges[u, v, k]['from'] = u
          G.edges[u, v, k]['to'] = v
          
          # add geometry if it doesn't already exist, to retain parallel
          # edges' distinct geometries
          if 'geometry' not in data:
              point_u = Point((G.nodes[u]['x'], G.nodes[u]['y']))
              point_v = Point((G.nodes[v]['x'], G.nodes[v]['y']))
              data['geometry'] = LineString([point_u, point_v])
  
      # update edge keys so we don't retain only one edge of sets of parallel edges
      # when we convert from a multidigraph to a multigraph
      G = update_edge_keys(G)
  
      # now convert multidigraph to a multigraph, retaining all edges in both
      # directions for now, as well as all graph attributes
      H = nx.MultiGraph()
      H.add_nodes_from(G.nodes(data=True))
      H.add_edges_from(G.edges(keys=True, data=True))
      H.graph = G.graph
      H.name = G.name
  
      # the previous operation added all directed edges from G as undirected
      # edges in H. this means we have duplicate edges for every bi-directional
      # street. so, look through the edges and remove any duplicates
      duplicate_edges = []
      for u, v, key, data in H.edges(keys=True, data=True):
  
          # if we haven't already flagged this edge as a duplicate
          if not (u, v, key) in duplicate_edges:
  
              # look at every other edge between u and v, one at a time
              for key_other in H[u][v]:
  
                  # don't compare this edge to itself
                  if not key_other == key:
  
                      # compare the first edge's data to the second's to see if
                      # they are duplicates
                      data_other = H.edges[u, v, key_other]
                      if is_duplicate_edge(data, data_other):
  
                          # if they match up, flag the duplicate for removal
                          duplicate_edges.append((u, v, key_other))
  
      H.remove_edges_from(duplicate_edges)
      log('Made undirected graph in {:,.2f} seconds'.format(time.time() - start_time))
  
      return H