Street names in OSMNX network maps - python

I am constructing street networks on osmnx using below code.I see that I can print lat/lon information, but
Is there a way to include street/road names in network maps as well? I don't see how to do this in the documentation. Thanks!
import osmnx as ox
G = ox.graph_from_bbox(37.79, 37.78, -122.41, -122.43, network_type='drive')
G_projected = ox.project_graph(G)
ox.plot_graph(G_projected)
Output:

Here's how you annotate your map with OSMnx to show street/road names (or any other edge attributes in the plot). The same logic would apply to labeling nodes instead.
import matplotlib.pyplot as plt
import osmnx as ox
ox.config(use_cache=True, log_console=True)
G = ox.graph_from_address('Piedmont, CA, USA', dist=200, network_type='drive')
G = ox.get_undirected(G)
fig, ax = ox.plot_graph(G, bgcolor='k', edge_linewidth=3, node_size=0,
show=False, close=False)
for _, edge in ox.graph_to_gdfs(G, nodes=False).fillna('').iterrows():
c = edge['geometry'].centroid
text = edge['name']
ax.annotate(text, (c.x, c.y), c='w')
plt.show()
The only aesthetic challenge being the label placement problem, which is one of the most difficult problems in computational cartography.

Related

Which query reproduces city street network orientation plots using OSMnx?

We are interested in reproducing the street network orientation plots from this blog post using OSMnx. However, using the modified example notebook code
import matplotlib.pyplot as plt
import numpy as np
import osmnx as ox
ox.config(log_console=True)
weight_by_length = False
ox.__version__
# define the study sites as label : query
places = {
"Berlin": "Berlin, Germany",
"Munich": "München, Germany",
"Minneapolis": "Minneapolis, MN, USA",
}
# verify OSMnx geocodes each query to what you expect (i.e., a [multi]polygon geometry)
gdf = ox.geocode_to_gdf(list(places.values()))
gdf
# create figure and axes
n = len(places)
ncols = int(np.ceil(np.sqrt(n)))
nrows = int(np.ceil(n / ncols))
figsize = (ncols * 5, nrows * 5)
fig, axes = plt.subplots(nrows, ncols, figsize=figsize, subplot_kw={"projection": "polar"})
# plot each city's polar histogram
for ax, place in zip(axes.flat, sorted(places.keys())):
print(ox.utils.ts(), place)
# get undirected graphs with edge bearing attributes
G = ox.graph_from_place(place, network_type="drive")
Gu = ox.add_edge_bearings(ox.get_undirected(G))
fig, ax = ox.bearing.plot_orientation(Gu, ax=ax, title=place, area=True)
our results differ from those in the blog post:
our Berlin Geoff's Berlin our Minneapolis Geoff's Minneapolis (sorry, I'm not allowed to embed images)
As Geoff mentions in his blog post, that "cities proper (municipalities), not wider metro areas or urban agglomerations" are used, we speculated that choosing the appropriate admin-level in the query might help. However using, e.g.,
gdf = ox.geometries.geometries_from_place('Minneapolis, MN, USA', {'boundary':'administrative','admin_level':'8'})
returns a multitude of polygons, where it is unclear to us how to select from them. The unary union
gdf_unified = gdf[gdf.admin_level=='8'].unary_union
does not seem to do the trick:
Minneapolis, unary union, admin-level 8
Can anyone advise which query to use to successfully reproduce the plots?

Generating building footprints from street point

I am using OSMNX to generate building footprints from a specific point. However, OSMNx doesn't display any footprints. I verified the same place from GoogleMaps where it shows there are many buildings around set point as shown in the below figure:
OSMNx Script
import osmnx
import pandas as pd
import networkx as nx
import osmnx as ox
from IPython.display import Image
import matplotlib.colors as colors
import pprint
ox.config(use_cache=True, log_console=True)
# get a graph for some city
G = ox.graph_from_place('Colac, Victoria, Australia', network_type='drive')
img_folder = 'images'
extension = 'png'
size = 640
dpi = 20
# #-----------------------------------------------------------------------------------------------------
def make_plot(place, point, network_type='drive', bldg_color='orange', dpi=400,
dist=500, default_width=4, street_widths=None):
gdf = ox.footprints.footprints_from_point(point=point, distance=dist)
fig, ax = ox.plot_figure_ground(point=point, dist=dist, network_type=network_type, default_width=default_width,
street_widths=street_widths, save=False, show=False, close=True)
fig, ax = ox.footprints.plot_footprints(gdf, fig=fig, ax=ax, color=bldg_color, set_bounds=False,
save=True, show=False, close=True, filename=place, dpi=dpi)
# #-----------------------------------------------------------------------------------------------------
place = 'Colac_buildings'
#Colac Lat,Lon
point = (-38.338850, 143.599013)
make_plot(place, point)
Image('{}/{}.{}'.format(img_folder, place, extension), height=size, width=size)
Does it mean the information is missing in OSMNx? What is the best way to get the building information or footprints?
Actually I am trying to extract addresses of all buildings in a specific area. Is there any other way to achieve this?
OSMNx uses data from OpenStreetMap, not from Google Maps. For your location -38.338850, 143.599013 there are no buildings in OSM yet (but there are several nearby, e.g. to the west).
To improve this you can create an OSM account and start to improve the map. Besides building footprints you can also add missing addresses to OSM (if you have access to a compatible license). Afterwards you can retrieve them with a geocoder, for example Nominatim.

How to add edge weights to plot output in Bokeh?

I wonder how I can add the edge weights to my Bokeh plot (from NetworkX), preferably for edge_renderer.hover_glyph, like in this picture:
A possible answer for this problem is using nx.get_edge_attributes and pass the values to draw_networkx_edge_labels as the labels for the edges.
Here's the so awaited code:
pos=nx.spring_layout(G)
nx.draw_networkx(G, pos)
labels = nx.get_edge_attributes(G,'weight')
nx.draw_networkx_edge_labels(G,pos,edge_labels=labels)
Here's a full working example:
import networkx as nx
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(4,4))
G = nx.Graph()
G.add_node('A', pos="1,3!", demand=-10)
G.add_node('B', pos="3,5!")
G.add_node('C', pos="3,1!")
G.add_node('D', pos="4,3!")
G.add_node('E', pos="5,5!")
G.add_node('F', pos="5,1!")
G.add_node('G', pos="7,3!", demand=10)
G.add_edge('A','B',weight=20,capacity=20,label='(20,20)')
G.add_edge('A','C',weight=7,capacity=15,label='(7,15)')
G.add_edge('B','E',weight=16,capacity=21,label='(16,21)')
G.add_edge('B','D',weight=4,capacity=4,label='(4,4)')
G.add_edge('C','F',weight=3,capacity=9,label='(3,9)')
G.add_edge('C','D',weight=4,capacity=4,label='(4,4)')
G.add_edge('D','E',weight=2,capacity=2,label='(2,2)')
G.add_edge('D','F',weight=6,capacity=10,label='(6,10)')
G.add_edge('E','G',weight=18,capacity=24,label='(18,24)')
G.add_edge('F','G',weight=9,capacity=10,label='(9,10)')
pos=nx.spring_layout(G)
nx.draw_networkx(G, pos)
labels = nx.get_edge_attributes(G,'weight')
nx.draw_networkx_edge_labels(G,pos,edge_labels=labels)

Simplify networkx node labels

%matplotlib inline
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_node('abc#gmail.com')
nx.draw(G, with_labels=True)
plt.show()
The output figure is
What I want is
I have thousands of email records from person#email.com to another#email.com in a csv file, I use G.add_node(email_address) and G.add_edge(from, to) to build G. I want keep the whole email address in Graph G but display it in a simplified string.
networkx has a method called relabel_nodes that takes a graph (G), a mapping (the relabeling rules) and returns a new graph (new_G) with the nodes relabeled.
That said, in your case:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_node('abc#gmail.com')
mapping = {
'abc#gmail.com': 'abc'
}
relabeled_G = nx.relabel_nodes(G,mapping)
nx.draw(relabeled_G, with_labels=True)
plt.show()
That way you keep G intact and haves simplified labels.
You can optionally modify the labels in place, without having a new copy, in which case you'd simply call G = nx.relabel_nodes(G, mapping, copy=False)
If you don't know the email addresses beforehand, you can pass relabel_nodes a function, like so:
G = nx.relabel_nodes(G, lambda email: email.split("#")[0], copy=False)

NetworkX and Matplotlib - Misplaced Text Labels

The following code tries to place a label for each node apart from the one that is by default included by NetworkX/Matplotlib. The original positions of the nodes are obtained through the call to "nx.spring_layout(g)".
The problem is that, when it comes to draw with Matplotlib the labels, the latter are misplaced, as it can be seen in the attached graph.
Should I be doing something differently?
import logging
import networkx as nx
import matplotlib.pyplot as plt
__log = logging.getLogger(__name__)
g = nx.Graph()
nodes = ['shield', 'pcb-top', 'pcb-config', 'chassis']
for k in nodes:
g.add_node(k)
plt.figure(figsize=(8, 11), dpi=150)
nx.draw(g, with_labels=True)
node_cfg = nx.spring_layout(g)
for k, node in node_cfg.items():
__log.debug('node = %s #(%.6f, %.6f)', k, node[0], node[1])
plt.text(node[0], node[1], k, bbox={'color': 'grey'})
plt.savefig('test.png')
Use the same position information for the network drawing as for the labels.
node_cfg = nx.spring_layout(g)
plt.figure(figsize=(8, 11), dpi=150)
nx.draw(g, pos=node_cfg, with_labels=True)

Categories

Resources