I have multiple shapefiles that I am trying to map in geopandas, but I can't get aerial/satellite imagery as a background image. These are very zoomed in shapefiles, and probably cover less than half a mile square. These are in Iowa in the United States.
Here is my code.
import geopandas as gpd
import fiona, os
import matplotlib.pyplot as plt
from geopandas import GeoDataFrame
from shapely.geometry import Polygon
import pandas as pd
import contextily as ctx
boundary = gpd.read_file(boundaryFile)
sample_data = gpd.read_file(sampleFile)
yieldData = gpd.read_file(yieldFile)
filesList = [boundary, sample_data, yieldData]
for i in filesList:
i.set_crs(epsg=3857, inplace=True)
fig = plt.figure()
ax = yieldData.plot()
ctx.add_basemap(ax, source=ctx.providers.Esri.WorldImagery)
I am getting a ValueError: The inferred zoom level of 34 is not valid for the current tile provider. This can indicate that the extent of your figure is wrong (e.g. too small extent, or in the wrong coordinate reference system)
Thanks for your help
Related
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.))
Im fairly new to using the cartopy package. I wanted to use a land sea mask from a given binary map in netcdf format. Here lsm_set is my netcdf file that contains that binary map and t2m_set is the data that I'd like to map. I'm still playing around with cartopy a little bit to get the hang of it, but I can't seem to figure out how to use the land sea mask. I've read several related questions here, but they didn't work on my code because my t2m variables did not have the attribute mask.
My teacher said I could use it to mark the sea values as "NaN" but I didn't know an efficient way to do it. I tried it with a while loop but that's super slow when you're working with this much data :')
I used data found from the copernicus institute on the following link: https://cds.climate.copernicus.eu/cdsapp#!/dataset/reanalysis-uerra-europe-single-levels?tab=form
import os
import numpy as np
import matplotlib.pyplot as plt
import netCDF4 as nc
from netCDF4 import Dataset
import xarray as xr
from cartopy import config
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader
filepath1 = '... file path... '
lsm_set = xr.open_dataset(filepath1)
filepath2 = '... file path...'
t2m_set= xr.open_dataset(filepath2)
lons = lsm_set.variables['longitude']#[:]
lats = lsm_set.variables['latitude']#[:]
lsm = lsm_set.variables['lsm']
t2m = t2m_set.variables['t2m']
plt.figure(figsize=(8, 8))
ax = plt.axes(projection = ccrs.Mercator())
ax.contourf(lons[200:400,100:300], lats[100:300,200:400], t2m[100:300,100:300],transform=ccrs.Mercator())
lsm_set.close()
t2m_set.close()
plt.show()
Any nudge in the right direction is appreciated, thanks!
Solved!
Turns out the solution was a lot easier than I thought.
lons = t2m_set.variables['longitude']#[:]
lats = t2m_set.variables['latitude']#[:]
lsm = lsm_set.variables['lsm']
t2m = t2m_set.variables['t2m']
lsm_masked = lsm.where(lsm!=0.)
mapdata = t2m+lsm_masked
And than plot mapdata instead of just t2m
You could use the where method of xarray :
t2m_set.where(lsm_set)
It should give you a nicely masked xarray.Dataset.
Let me assume you have the land/sea data as 1's and 0's and the same size as your data... Then you can easily make a plot like this:
#!/usr/bin/env ipython
# --------------------
import matplotlib as mpl
mpl.rcParams['font.size'] = 18
import matplotlib.pylab as plt
import numpy as np
# -----------------------------
xx = np.linspace(9.,30,100);
yy = np.linspace(54.0,66.0,100);
xm,ym = np.meshgrid(xx,yy);
zz = 50.0 + 10.0*np.random.random((np.size(yy),np.size(xx)));
# -----------------------------
# let me have some random landmask/seamask data:
smask = np.zeros(np.shape(zz));smask[0:10,0:10]=1.0;smask[60:90,60:90]=1.0;
# -----------------------------
# let us set 0.0 to NaNs in seamask:
smask[smask==0]=np.nan;
smask=np.ma.array(smask,mask=np.isnan(smask))
# -----------------------------
# let us make a plot:
fig = plt.figure();ax=fig.add_subplot(111);
ax.pcolormesh(xx,yy,zz);
ax.pcolormesh(xx,yy,smask,vmin=0.0,vmax=8.0,cmap='Greys');
plt.show()
# ------------------------------------------------------------
I am trying to plot a raster with rasterio but somehow that data is being resampled, I think.
The map created does not show the detail in the data. See here:
python plot
...compared to the original data (plotted with GIS):
topo data
Any idea how to stop rasterio from interpolating/resampling the data?
Here is my code:
import rasterio
from rasterio.plot import show
import matplotlib.pyplot as plt
topo = rasterio.open('../topo_raster/nz100dem2ihs21.tif')
nz_mask_file = '../gis_data/NZ_mask.shp'
nzmask = gpd.read_file(nz_mask_file)
fig= plt.figure(dpi=300. )
ax = plt.axes( projection=ccrs.epsg(27200))
show(topo.read(1,masked=True), ax=ax,transform=topo.transform,interpolation='none',zorder=1,cmap='gist_gray')
nzmask.plot(ax=ax,facecolor="white", edgecolor='black', lw=linewidths_rr,zorder=0.5)
plt.savefig('../newzealand.png')
plt.clf()
I am posting this question after three days searching the net but no success. Hope can get the answer here. Please do NOT delete the post as I did not find an answer for it here also. Thanks.
I have 2 files:
A raster image file (i.e., Air temperature 2020-01-01.tif)
World countries boundary shapefile ((i.e., World_Countries_base_map.shp)
Goal: I want to plot the shapefile on top of raster file, and then save the plot in a Jpeg file format to get something like this eventually:
I am quite new in Python, and used Spyder to prepare this simple code to do so:
# Import needed packages
import os
import rasterio
import matplotlib.pyplot as plt
import geopandas as gpd
import earthpy as et
from matplotlib import pyplot
## list all raster images in tiff format in the folder:
list_files = [f for f in
os.listdir('C:/Users/Desktop/Question/Raster_Air_temp')
if '.tif' in f]
print(list_files[1]) # checking the 1st file in the list
## reading the first tiff file:
raster_image = rasterio.open(list_files[1])
## plot it
draft_output = pyplot.imshow(raster_image.read(1), cmap='jet')
## importing world shapefile
World_map = gpd.read_file('C:/Users/Desktop/Question/World_shapefile/World_Countries_base_map.shp')
# plot World shapefile
fig, ax = plt.subplots(figsize = (30,30)) # image size and quality can be controled by figsize
ax.set_title('The Glob Map', fontsize=50);
World_map.plot(ax=ax, color='white', edgecolor='black') # colors note at https://matplotlib.org/tutorials/colors/colormaps.html
plt.show()
## Plot both World shapefile and raster image in one graph:
????
However, this code just produces 2 separated plots in the console for me as can be seen above.
Question: How can I type a proper code in ???? section of the code to get to my Goal (mentioned above)?
Thanks to all comments and helps.
Here, I share the two files in order to make it easier for those who want help.
Download the files from my Dropbox
.
since i have no access to your data I am showing the principle with some sample data from geopandas and a random numpy ndarray as a tiff surrogate.
the key point is to show the tiff with rasterios rasterplot and don't forget to set the extent of your DEM!
import rasterio
import numpy as np
from rasterio import plot as rasterplot
import geopandas as gpd
from matplotlib import pyplot as plt
# this is how you'd open the raster dataset if you have one
#tiff = rasterio.open('example.tif')
#tiff_extent = [tiff.bounds[0], tiff.bounds[2], tiff.bounds[1], tiff.bounds[3]]
# i am making this array up
tiff_band_1 = np.random.randint(0, 10, size=(65, 64))
tiff_extent = [4159200.0, 4808100.0, 2828000.0, 3482600.0]
shapefile = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
shapefile = shapefile.to_crs('epsg:3035')
shapefile = shapefile[shapefile.name == 'Germany']
f, ax = plt.subplots()
# plot DEM
rasterplot.show(
tiff_band_1, # use tiff.read(1) with your data
extent=tiff_extent,
ax=ax,
)
# plot shapefiles
shapefile.plot(ax=ax, facecolor='w', edgecolor='k')
plt.savefig('test.jpg')
plt.show()
I'm trying to plot data onto a map. I would like to generate data for specific points on the map (e.g. transit times to one or more prespecified location) for a specific city.
I found data for New York City here: https://data.cityofnewyork.us/City-Government/Borough-Boundaries/tqmj-j8zm
It looks like they have a shapefile available. I'm wondering if there is a way to sample a latitude-longitude grid within the bounds of the shapefile for each borough (perhaps using Shapely package, etc).
Sorry if this is naive, I'm not very familiar with working with these files--I'm doing this as a fun project to learn about them
I figured out how to do this. Essentially, I just created a full grid of points and then removed those that did not fall within the shape files corresponding to the boroughs. Here is the code:
import geopandas
from geopandas import GeoDataFrame, GeoSeries
import matplotlib.pyplot as plt
from matplotlib.colors import Normalize
import matplotlib.cm as cm
%matplotlib inline
import seaborn as sns
from shapely.geometry import Point, Polygon
import numpy as np
import googlemaps
from datetime import datetime
plt.rcParams["figure.figsize"] = [8,6]
# Get the shape-file for NYC
boros = GeoDataFrame.from_file('./Borough Boundaries/geo_export_b641af01-6163-4293-8b3b-e17ca659ed08.shp')
boros = boros.set_index('boro_code')
boros = boros.sort_index()
# Plot and color by borough
boros.plot(column = 'boro_name')
# Get rid of are that you aren't interested in (too far away)
plt.gca().set_xlim([-74.05, -73.85])
plt.gca().set_ylim([40.65, 40.9])
# make a grid of latitude-longitude values
xmin, xmax, ymin, ymax = -74.05, -73.85, 40.65, 40.9
xx, yy = np.meshgrid(np.linspace(xmin,xmax,100), np.linspace(ymin,ymax,100))
xc = xx.flatten()
yc = yy.flatten()
# Now convert these points to geo-data
pts = GeoSeries([Point(x, y) for x, y in zip(xc, yc)])
in_map = np.array([pts.within(geom) for geom in boros.geometry]).sum(axis=0)
pts = GeoSeries([val for pos,val in enumerate(pts) if in_map[pos]])
# Plot to make sure it makes sense:
pts.plot(markersize=1)
# Now get the lat-long coordinates in a dataframe
coords = []
for n, point in enumerate(pts):
coords += [','.join(__ for __ in _.strip().split(' ')[::-1]) for _ in str(point).split('(')[1].split(')')[0].split(',')]
which results in the following plots:
I also got a matrix of lat-long coordinates I used to make a transport-time map for every point in the city to Columbia Medical Campus. Here is that map:
and a zoomed-up version so you can see how the map is made up of the individual points: