docs: def graph_from_bbox(north, south, east, west, network_type='all_private',
                      simplify=True, retain_all=False, truncate_by_edge=False,
                      name='unnamed', timeout=180, memory=None,
                      max_query_area_size=50*1000*50*1000, clean_periphery=True,
                      infrastructure='way["highway"]', custom_filter=None):
      """
      Create a networkx graph from OSM data within some bounding box.
  
      Parameters
      ----------
      north : float
          northern latitude of bounding box
      south : float
          southern latitude of bounding box
      east : float
          eastern longitude of bounding box
      west : float
          western longitude of bounding box
      network_type : string
          what type of street network to get
      simplify : bool
          if true, simplify the graph topology
      retain_all : bool
          if True, return the entire graph even if it is not connected
      truncate_by_edge : bool
          if True retain node if it's outside bbox but at least one of node's
          neighbors are within bbox
      name : string
          the name of the graph
      timeout : int
          the timeout interval for requests and to pass to API
      memory : int
          server memory allocation size for the query, in bytes. If none, server
          will use its default allocation size
      max_query_area_size : float
          max size for any part of the geometry, in square degrees: any polygon
          bigger will get divided up for multiple queries to API
      clean_periphery : bool
          if True (and simplify=True), buffer 0.5km to get a graph larger than
          requested, then simplify, then truncate it to requested spatial extent
      infrastructure : string
          download infrastructure of given type (default is streets (ie, 'way["highway"]') but other
          infrastructures may be selected like power grids (ie, 'way["power"~"line"]'))
      custom_filter : string
          a custom network filter to be used instead of the network_type presets
  
      Returns
      -------
      networkx multidigraph
      """
  
      if clean_periphery and simplify:
          # create a new buffered bbox 0.5km around the desired one
          buffer_dist = 500
          polygon = Polygon([(west, north), (west, south), (east, south), (east, north)])
          polygon_utm, crs_utm = project_geometry(geometry=polygon)
          polygon_proj_buff = polygon_utm.buffer(buffer_dist)
          polygon_buff, _ = project_geometry(geometry=polygon_proj_buff, crs=crs_utm, to_latlong=True)
          west_buffered, south_buffered, east_buffered, north_buffered = polygon_buff.bounds
  
          # get the network data from OSM then create the graph
          response_jsons = osm_net_download(north=north_buffered, south=south_buffered,
                                            east=east_buffered, west=west_buffered,
                                            network_type=network_type, timeout=timeout,
                                            memory=memory, max_query_area_size=max_query_area_size,
                                            infrastructure=infrastructure, custom_filter=custom_filter)
          G_buffered = create_graph(response_jsons, name=name, retain_all=retain_all,
                                    bidirectional=network_type in settings.bidirectional_network_types)
          G = truncate_graph_bbox(G_buffered, north, south, east, west, retain_all=True, truncate_by_edge=truncate_by_edge)
  
          # simplify the graph topology
          G_buffered = simplify_graph(G_buffered)
  
          # truncate graph by desired bbox to return the graph within the bbox
          # caller wants
          G = truncate_graph_bbox(G_buffered, north, south, east, west, retain_all=retain_all, truncate_by_edge=truncate_by_edge)
  
          # count how many street segments in buffered graph emanate from each
          # intersection in un-buffered graph, to retain true counts for each
          # intersection, even if some of its neighbors are outside the bbox
          G.graph['streets_per_node'] = count_streets_per_node(G_buffered, nodes=G.nodes())
  
      else:
          # get the network data from OSM
          response_jsons = osm_net_download(north=north, south=south, east=east,
                                            west=west, network_type=network_type,
                                            timeout=timeout, memory=memory,
                                            max_query_area_size=max_query_area_size,
                                            infrastructure=infrastructure, custom_filter=custom_filter)
  
          # create the graph, then truncate to the bounding box
          G = create_graph(response_jsons, name=name, retain_all=retain_all,
                           bidirectional=network_type in settings.bidirectional_network_types)
          G = truncate_graph_bbox(G, north, south, east, west, retain_all=retain_all, truncate_by_edge=truncate_by_edge)
  
          # simplify the graph topology as the last step. don't truncate after
          # simplifying or you may have simplified out to an endpoint
          # beyond the truncation distance, in which case you will then strip out
          # your entire edge
          if simplify:
              G = simplify_graph(G)
  
      log('graph_from_bbox() returning graph with {:,} nodes and {:,} edges'.format(len(list(G.nodes())), len(list(G.edges()))))
      return  G