OSMNX remove buildings from graph - osmnx

I am creating a graph from an osm file using graph_from_file() (it contains both the roads and buildings) using osmnx and then plotting it. While doing this, it is also plotting buildings along with the roads. Is there a way to remove buildings from this graph/just ignore buildings while creating a graph from that osm file?

Set the parameter retain_all to False. This includes the buildings which are usually disconnected (in my experience). You can observe the differences between the following 2 figures.
G = ox.graph_from_file('try.xml', retain_all=True)
fig, ax = ox.plot_graph(G)
[![Figure_1][1]][1]
G = ox.graph_from_file('try.xml', retain_all=False)
fig, ax = ox.plot_graph(G)
[![Figure_2][1]][1]

Note that I only queried highway = pedestrian and building = university using Overpass Turbo (overpass_code) which produced my .xml file.

Related

Is Cartopy capable of plotting georeferenced data from another planet (e.g., Mars, the Moon)?

I'm working with several data sets from the Moon and Mars (topography, crustal thickness) and was wondering if Cartopy can manipulate these data given the reference ellipsoids are different. Do custom ellipsoids need to be created, or are they built in to Cartopy?
I figured out how to do this on my own. Here's the solution I came up with...
Step 1
Import Cartopy...
import cartopy.crs as ccrs
After importing Cartopy and loading your data set, you need to change Cartopy's Globe class such that it does not use the WGS84 ellipse. Simply define new semi-major and semi-minor axes and tell Cartopy to refrain from using a terrestrial ellipse.
img_globe = ccrs.Globe(semimajor_axis = semimajor, semiminor_axis = semiminor, ellipse = None)
Step 2
Next, choose a map projection for plotting and identify your data's format. I decided to plot my data using a Mollweide coordinate system and found my data is defined in the Plate Carree coordinate system. Now we can define the map projection and coordinate system for the data using the new Globe class defined above.
projection = ccrs.Mollweide(globe = img_globe)
data_crs = ccrs.PlateCarree(globe = img_globe)
Step 3
Lastly, plot your data using standard Matplotlib syntax with two important caveats. First create axes that implement the map projection.
fig = plt.figure(figsize = (6,6))
ax = plt.axes(projection = projection)
When plotting the data, you have to inform Matplotlib how your data are formatted using the transform argument.
ax.imshow(data, extent = extent, cmap = 'viridis', transform = data_crs)
The end result looks like this...

Filtering on relation

I'm trying to retrieve a network of the major roads in Norway. However, the "int_ref" and "ref" labels are inconsistent and are resulting in gaps in the road. When looking at the road in OpenStreetMap I can see that the 'relation' tag under 'Part of' is exactly what I need. Is there any way to retrieve this using OSMnx? Is there any other way to retrieve a full road? I'm using the following line of code when filtering one specific road based on int_ref:
G1 = ox.graph_from_place(query = "Norway", retain_all = True, custom_filter = '["int_ref"~"E 39"]')
No, OSMnx filters on way tags, not on relations. If you want to get only the major roads in a country, see this answer: https://stackoverflow.com/a/52412274/7321942
Something like this may do what you are looking for:
import osmnx as ox
ox.config(use_cache=True, log_console=True)
# get the geometry of the norwegian mainland
gdf = ox.geocode_to_gdf('Norway')
geom = max(gdf['geometry'].iloc[0], key=lambda x: x.area)
# get all motorway/trunk roads
cf = '["highway"~"motorway|motorway_link|trunk|trunk_link"]'
G = ox.graph_from_polygon(geom, network_type='drive', custom_filter=cf)
# plot it
fig, ax = ox.plot_graph(G)
It takes ~370 Overpass API requests to download all the area of the Norwegian mainland, so it takes a while to make all those requests. You can watch its progress in the log in the console.

Zooming a pherical projection in matplotlib

I need to display a catalogue of galaxies projected on the sky. Not all the sky is relevant here, so I need to center an zoom on the relevant part. I am OK with more or less any projection, like Lambert, Mollweide, etc. Here are mock data and code sample, using Mollweide:
# Generating mock data
np.random.seed(1234)
(RA,Dec)=(np.random.rand(100)*60 for _ in range(2))
# Creating projection
projection='mollweide'
fig = plt.figure(figsize=(20, 10));
ax = fig.add_subplot(111, projection=projection);
ax.scatter(np.radians(RA),np.radians(Dec));
# Creating axes
xtick_labels = ["$150^{\circ}$", "$120^{\circ}$", "$90^{\circ}$", "$60^{\circ}$", "$30^{\circ}$", "$0^{\circ}$",
"$330^{\circ}$", "$300^{\circ}$", "$270^{\circ}$", "$240^{\circ}$", "$210^{\circ}$"]
labels = ax.set_xticklabels(xtick_labels, fontsize=15);
ytick_labels = ["$-75^{\circ}$", "$-60^{\circ}$", "$-45^{\circ}$", "$-30^{\circ}$", "$-15^{\circ}$",
"$0^{\circ}$","$15^{\circ}$", "$30^{\circ}$", "$45^{\circ}$", "$60^{\circ}$",
"$75^{\circ}$", "$90^{\circ}$"]
ax.set_yticklabels(ytick_labels,fontsize=15);
ax.set_xlabel("RA");
ax.xaxis.label.set_fontsize(20);
ax.set_ylabel("Dec");
ax.yaxis.label.set_fontsize(20);
ax.grid(True);
The result is the following:
I have tried various set_whateverlim, set_extent, clip_box and so on, as well as importing cartopy and passing ccrs.LambertConformal(central_longitude=...,central_latitude=...) as arguments. I was unable to get a result.
Furthermore, I would like to shift RA tick labels down, as they are difficult to read with real data. Unfortunately, ax.tick_params(pad=-5) doesn't do anything.

Visualizing Data, Tracking Specific SD Values

BLUF: I want to track a specific Std Dev, e.g. 1.0 to 1.25, by color coding it and making a separate KDF or other probability density graph.
What I want to do with this is be able to pick out other Std Dev ranges and get back new graphs that I can turn around and use to predict outcomes in that specific Std Dev.
Data: https://www.dropbox.com/s/y78pynq9onyw9iu/Data.csv?dl=0
What I have so far is normalized data that looks like a shotgun blast:
Code used to produce it:
data = pd.read_csv("Data.csv")
sns.jointplot(data.x,data.y, space=0.2, size=10, ratio=2, kind="reg");
What I want to achieve here looks like what I have marked up below:
I kind of know how to do this in RStudio using RidgePlot-type functions, but I'm at a loss here in Python, even while using Seaborn. Any/All help appreciated!
The following code might point you in the right directly, you can tweak the appearance of the plot as you please from there.
tips = sns.load_dataset("tips")
g = sns.jointplot(x="total_bill", y="tip", data=tips)
top_lim = 4
bottom_lim = 2
temp = tips.loc[(tips.tip>=bottom_lim)&(tips.tip<top_lim)]
g.ax_joint.axhline(top_lim, c='k', lw=2)
g.ax_joint.axhline(bottom_lim, c='k', lw=2)
# we have to create a secondary y-axis to the joint-plot, otherwise the
# kde might be very small compared to the scale of the original y-axis
ax_joint_2 = g.ax_joint.twinx()
sns.kdeplot(temp.total_bill, shade=True, color='red', ax=ax_joint_2, legend=False)
ax_joint_2.spines['right'].set_visible(False)
ax_joint_2.spines['top'].set_visible(False)
ax_joint_2.yaxis.set_visible(False)

Mask cube with features

I want to plot data from a global cube, but only for a list of countries. So I select a subcube according to the countries' "bounding box".
So far so good. What I'm looking for is an easy way to mask out all points of a cube which do not fall in any of my countries (which are represented as features), so that only those points of the cube which lie within any of my features are plotted.
Any idea is greatly appreciated =)
You can achieve this directly at the plotting stage rather than masking the cube within iris. I've approached this by setting the clip path of the artist returned by pcolor. The method is to create a list of geometries from features (in this case countries from Natural Earth, they could be from a shapefile) then transform these geometries into a matplotlib path which the image can be clipped to. I'll detail this method, and hopefully this will be enough to get you started:
I first defined a function to retrieve the Shapely geometries corresponding to given country names, the geometries come from the Natural Earth 110m administrative boundaries shapefile, access through the cartopy interface.
I then defined a second function which is a wrapper around the iris.plot.pcolor function which makes the plot and clips it to the given geometries.
Now all I need to do is set up the plot as normal, but use the plotting wrapper instead of directly calling the iris.plot.pcolor function.
Here is a complete example:
import cartopy.crs as ccrs
from cartopy.io.shapereader import natural_earth, Reader
from cartopy.mpl.patch import geos_to_path
import iris
import iris.plot as iplt
import matplotlib.pyplot as plt
from matplotlib.path import Path
def get_geometries(country_names):
"""
Get an iterable of Shapely geometries corrresponding to given countries.
"""
# Using the Natural Earth feature interface provided by cartopy.
# You could use a different source, all you need is the geometries.
shape_records = Reader(natural_earth(resolution='110m',
category='cultural',
name='admin_0_countries')).records()
geoms = []
for country in shape_records:
if country.attributes['name_long'] in country_names:
try:
geoms += country.geometry
except TypeError:
geoms.append(country.geometry)
return geoms, ccrs.PlateCarree()._as_mpl_transform
def pcolor_mask_geoms(cube, geoms, transform):
path = Path.make_compound_path(*geos_to_path(geoms))
im = iplt.pcolor(cube)
im.set_clip_path(path, transform=transform)
# First plot the full map:
cube = iris.load_cube(iris.sample_data_path('air_temp.pp'))
plt.figure(figsize=(12, 6))
ax1 = plt.axes(projection=ccrs.PlateCarree())
ax1.coastlines()
iplt.pcolor(cube)
# Now plot just the required countries:
plt.figure(figsize=(12, 6))
ax2 = plt.axes(projection=ccrs.PlateCarree())
ax2.coastlines()
countries = [
'United States',
'United Kingdom',
'Saudi Arabia',
'South Africa',
'Nigeria']
geoms, transform = get_geometries(countries)
pcolor_mask_geoms(cube, geoms, transform(ax2))
plt.show()
The results of which look like this:
If you want to use iris.plot.pcolormesh instead you will need to modify the plotting function a little bit. This is dues to a workaround for a matplotlib issue that is currently included in cartopy. The modified version would look like this:
def pcolor_mask_geoms(cube, geoms, transform):
path = Path.make_compound_path(*geos_to_path(geoms))
im = iplt.pcolormesh(cube)
im.set_clip_path(path, transform=transform)
try:
im._wrapped_collection_fix.set_clip_path(path, transform)
except AttributeError:
pass