OSMNX and Shapely polygon cut - python

I wanted to spilt the polygon into a numbered grid consisting of many small squares/shapes but the result is a polygon split into four sections instead is there anything wrong with the code I have been trying to solve this for hours but not sure what to do:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import geopandas as gpd
import osmnx as ox
from descartes import PolygonPatch
from shapely.geometry import Polygon
city=ox.geocode_to_gdf("Paris,France")
geometry = city['geometry'].iloc[0]
geometry_split =
ox.utils_geo._quadrat_cut_geometry(geometry,
quadrat_width = 750)
polylist = [p for p in geometry_split]
west, south, east, north = city.unary_union.bounds
fig, ax = plt.subplots(figsize=(30,30))
for polygon, n in zip(geometry_split,
np.arange(len(polylist))):
p = polygon.representative_point().coords[:][0]
patch =
PolygonPatch(polygon,ec='#100000',alpha=0.5,
zorder=2)
ax.add_patch(patch)
plt.annotate(text=n, xy=p,
horizontalalignment='center', size=15)
ax.set_xlim(west, east)
ax.set_ylim(south, north)
ax.axis('off')
plt.show()
The result is shown below:

Related

plot df on map - two plots instead of one

enter image description hereenter image description hereI want to plot data from a df in a map. However, I don't manage to print out the values in the plot, but I get two plots - one with an empty map and one with the values without map.
What am I doing wrong?
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import cartopy
import cartopy.crs as ccrs
import cartopy.feature as cf
#ax1=plt.axes(projection=ccrs.Mercator())
#fig, ax=plt.subplots(figsize=(8,6))
ax1.add_feature(cf.BORDERS);
ax1.add_feature(cf.RIVERS);
ax1.set_extent([7.4, 8.8, 47.5, 49.1])
ax1.set_title('Niederschlag', fontsize=13);
ax.grid(b=True, alpha=0.5)
df.plot(x="longitude", y="latitude", kind="scatter",
c='RR',colormap="YlOrRd")
plt.show()
Thanks in advance
pandas.DataFrame.plot creates a new plot by default, this is why you are getting two plots: first you crate one with ax1=plt.axes(projection=ccrs.Mercator()), then pandas creates another one.
To fix this you can use the ax argument on pandas.DataFrame.plot:
df.plot(x="longitude", y="latitude", kind="scatter", c='RR',colormap="YlOrRd", ax=ax1)
Edit
There is also a problem with the projection. You are setting the projection as Mercator which uses a different coordinates system from the standard one. When you set the bounds you are not specifying the projection and it being converted automatically. Your points though are in a different projection and no automatic conversion is performed.
To fix this I suggest using a different projection to start with (e.g.: PlateCarree). If this is not possible then you would need to convert the coordinates yourself.
This code produces a map with points:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import cartopy
import cartopy.crs as ccrs
import cartopy.feature as cf
df = pd.DataFrame(
{
"longitude": [7.99, 8.42, 7.78],
"latitude": [48.98, 48.74, 47.59],
"RR": [5, 15, 25],
}
)
ax1=plt.axes(projection=ccrs.PlateCarree())
ax1.add_feature(cf.BORDERS)
ax1.add_feature(cf.RIVERS)
ax1.set_extent([7.4, 8.8, 47.5, 49.1], crs=ccrs.PlateCarree())
ax1.set_title('Niederschlag', fontsize=13);
ax1.grid(b=True, alpha=0.5)
df.plot(x="longitude", y="latitude", kind="scatter", c="RR", colormap="YlOrRd", ax=ax1)
try this : plt.scatter(x=df['Longitude'], y=df['Latitude'])
or try using geo pandas like so
import pandas as pd
from shapely.geometry import Point
import geopandas as gpd
from geopandas import GeoDataFrame
df = pd.read_csv("Long_Lats.csv", delimiter=',', skiprows=0, low_memory=False)
geometry = [Point(xy) for xy in zip(df['Longitude'], df['Latitude'])]
gdf = GeoDataFrame(df, geometry=geometry)
#this is a simple map that goes with geopandas
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
gdf.plot(ax=world.plot(figsize=(10, 6)), marker='o', color='red', markersize=15);

Draw circle with longitude, latitude and radius (km) in cartopy of python

#!/usr/bin/env python
import os, sys
import pandas as pd
import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import shapely.geometry as sgeom
import numpy as np
from cartopy.geodesic import Geodesic
if __name__ == '__main__':
stn = pd.read_csv('obs_station.csv')
gd = Geodesic()
lcc = ccrs.LambertConformal(central_longitude=126., central_latitude=38.)
fig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(111, projection=lcc)
ax.coastlines(resolution='50m')
geoms = []
for lon, lat in zip(stn['longitude'], stn['latitude']):
cp = gd.circle(lon=lon, lat=lat, radius=250000.)
geoms.append(sgeom.Polygon(cp))
ax.add_geometries(geoms, crs=lcc, edgecolor='r')
ax.set_extent([120., 133., 30., 43.])
plt.show()
The file 'obs_station.csv' contain several coordinates of longitudes and latitudes.
Using code above, I try to draw circles with specific radius (250 km).
But, nothing is on the map as below. Only show the map with coastlines.
I don't know what is the problem. Help please.
Result
You did not get the plots of the circles because of wrong coordinate transformation you specifies in .add_geometries() statement.
To get it right, suppose I use this data file:
'obs_station.csv':
longitude,latitude
127.603897,36.932988
126.505337,38.555939
And the modified code:-
#import os, sys
import pandas as pd
import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import shapely.geometry as sgeom
import numpy as np
from cartopy.geodesic import Geodesic
if __name__ == '__main__':
stn = pd.read_csv('obs_station.csv')
gd = Geodesic()
# This is long-lat coordinate system for use in ..
# .. coordinate transformation options
src_crs = ccrs.PlateCarree()
lcc = ccrs.LambertConformal(central_longitude=126., central_latitude=38.)
fig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(111, projection=lcc)
ax.coastlines(resolution='50m')
geoms = []
for lon, lat in zip(stn['longitude'], stn['latitude']):
cp = gd.circle(lon=lon, lat=lat, radius=250000.)
#x,y = lcc.transform_point(lon, lat, src_crs)
#cp = gd.circle(lon=x, lat=y, radius=250000.)
geoms.append(sgeom.Polygon(cp))
# Note the specification of coordinate transformation, using the
# .. correct parameter: crs=src_crs
ax.add_geometries(geoms, crs=src_crs, edgecolor='r', alpha=0.5)
ax.set_extent([120., 133., 30., 43.])
plt.show()
The output:
In conclusion, your line of code:
ax.add_geometries(geoms, crs=lcc, edgecolor='r')
needs correct CRS. And the correct CRS is
ccrs.PlateCarree()

Inscribing a smaller domain onto a cartopy map in Python

I've been working to make a visual for a poster regarding the physical domain that I am studying. I'm working with a nested domain, so I have 1 smaller domain inside a larger outer domain. I'm trying to create a cartopy plot that shows both the outer domain and inner domain. Ideally, the result would look something like this:
I'm really struggling with trying to get my smaller domain inscribed onto my map. I've attempted to make a Shapely LinearRing to show the inner domain, but it is not working. Here's the code I have created so far:
# Imports
import numpy as np
import sys, os
import matplotlib.pyplot as plt
%matplotlib inline
import netCDF4
from netCDF4 import Dataset
from matplotlib.cm import get_cmap
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.feature import NaturalEarthFeature, COLORS
import metpy as mp
import metpy.calc as mpcalc
from metpy.calc import divergence, smooth_gaussian
from metpy.units import units
import xarray as xr
from wrf import getvar, interplevel, to_np, latlon_coords, get_cartopy, cartopy_xlim, cartopy_ylim, ALL_TIMES
from shapely.geometry.polygon import LinearRing
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
from shapely import geometry
# Get 1km lats/lons
lats1km = getvar(ds1, 'lat')
lons1km = getvar(ds1, 'lon')
lat1km_max = to_np(np.max(lats1km))
lat1km_min = to_np(np.min(lats1km))
lon1km_max = to_np(np.max(lons1km))
lon1km_min = to_np(np.min(lons1km))
# Get 3km lats/lons
lats3km = getvar(ds3, 'lat')
lons3km = getvar(ds3, 'lon')
lat3km_max = to_np(np.max(lats3km))
lat3km_min = to_np(np.min(lats3km))
lon3km_max = to_np(np.max(lons3km))
lon3km_min = to_np(np.min(lons3km))
domain = [lon3km_min, lat3km_min, lon3km_max, lat3km_max]
lons = [lat1km_min, lat1km_min, lat1km_max, lat1km_max]
lats = [lon1km_min, lon1km_max, lon1km_max, lon1km_min]
ring = LinearRing(list(zip(lons, lats)))
geom = geometry.box(minx=lon1km_min, miny=lat1km_min, maxx=lon1km_max, maxy=lat1km_max)
# Grab CRS
crs = get_cartopy(wrfin=ds1)
# Create figure and axes
fig = plt.figure(figsize=(20,10))
ax0 = fig.add_subplot(1, 1, 1, projection=crs)
ax0.set_extent([lon3km_min, lon3km_max, lat3km_min, lat3km_max])
ax0.add_geometries([ring], crs=crs, facecolor='blue', edgecolor='black')
ax0.add_geometries([geom], crs=crs, alpha=0.3)
plot_background(ax0)
This yields my outer domain, but not my inner domain:
What am I doing wrong, and what can I do to get my inner domain shown on the map? Thank you for the help! I really appreciate it!
NOTE: I have already attempted the solution in this link. I am still unable to visualize my polygon.
Have a look at EOmaps ! (I'm the dev) it provides simple functions to add static (or interactive) indicators such as projected rectangles or ellipses to cartopy plots in 1 line!
from eomaps import Maps
m = Maps()
m.add_coastlines()
props = dict(xy=(10, 45), xy_crs=4326, radius_crs=4326, shape="rectangles")
m.add_marker(**props, radius=3, fc=(0,1,0,.5), ec="r", lw=2)
m.add_marker(**props, radius=5, fc="none", ec="k")
m.add_marker(**props, radius=(15, 10), fc="none", ec="m", ls="--", lw=2)
m.figure.ax.set_extent((-15., 65., -5., 75.))

How to use numpy to build a 3D-model?

Original(2018.11.01)
I have 3 numpy:x、y、z,created by my laser scanner(40 degree / 1 step).
I want to used them to build a 3D model.
I think it must should be use matplotlib.tri
But I have no idea to decide triangulated data
Here is my data :https://www.dropbox.com/s/d9p62kv9jcq9bwh/xyz.zip?dl=0
And Original model:https://i.imgur.com/XSyONff.jpg
Code:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.tri as mtri
x_all=np.load("x.npy")
y_all=np.load("y.npy")
z_all=np.load("z.npy")
tri = #I have no idea...
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_trisurf(x_all,y_all,z_all,triangles=tri.triangles)
Thank so much.
Update(2018.11.02)
I try this way to decide triangulated data
Delaunay Triangulation of points from 2D surface in 3D with python?
code:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.tri as mtri
from stl import mesh
x_all=np.load("x.npy")
y_all=np.load("y.npy")
z_all=np.load("z.npy")
model=np.vstack((x_all,y_all,z_all))
model=np.transpose(model)
model -= model.mean(axis=0)
rad = np.linalg.norm(model, axis=1)
zen = np.arccos(model[:,-1] / rad)
azi = np.arctan2(model[:,1], model[:,0])
tris = mtri.Triangulation(zen, azi)
plt.show()
And my model looks like:
https://i.stack.imgur.com/KVPHP.png
https://i.stack.imgur.com/LLQsQ.png
https://i.stack.imgur.com/HdzFm.png
Even though it has better surface on it,but there is a big hole over my model.Any idea to fixs it?
Assuming you want to reduce the complexity, i.e find triangles in your files to reduce the complexity. You may look into fitting a convex hull to your points, see here fore more info
Based on the file you provided this produces a surf plot of the object.
from numpy import load, stack
from matplotlib.pyplot import subplots
from mpl_toolkits.mplot3d import Axes3D
from scipy import spatial
x = load("x.npy")
y = load("y.npy")
z = load("z.npy")
points = stack((x,y,z), axis = -1)
v = spatial.ConvexHull(points)
fig, ax = subplots(subplot_kw = dict(projection = '3d'))
ax.plot_trisurf(*v.points.T, triangles = v.simplices.T)
fig.show()

Smoothing a shapefile output - Basemap python

I'm working with a shapefile. I have no issues whatsoever reading it in, plotting it, and making the map pretty-looking. However, when I plot it (after reprojecting it to the correct EPSG using QGIS), the edges are all jagged (as shown below). Is there a way to smooth it using Python?
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
import numpy as np
#insert code for basemap setup m = Basemap(...)
m.arcgisimage(service = 'ESRI_StreetMap_World_2D', xpixels = 1000, verbose = True)
states_info = m.readshapefile('shapefiles/states', 'states')
spc_info = m.readshapefile('shapefiles/corrected_epsg', 'spc', drawbounds = False)
patches = []
ax = plt.gca()
for info, shape in zip(m.spc_info, m.spc):
x, y = zip(*shape)
if info['DN'] == 2:
color = '#80c580'
zorder = 2
patches.append( Polygon(np.array(shape), True))
if info['DN'] == 5:
color = '#f7f780'
zorder = 3
patches.append( Polygon(np.array(shape), True))
ax.add_collection(PatchCollection(patches, facecolor= color, zorder=zorder, alpha = 0.7))
Source for these shapefiles.
This question's answers explain how the Shapely Package has a Simplify method based on the Douglas-Puecker algorithm.

Categories