How to set offset for python cartopy geometry? - python

So the problem is that when I add a geometry from .shp file to the cartopy figure, there is an offset and I have no idea how to set the offset.
I am new to python so any help is appreciated.
picture here
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
#from cartopy.feature import GSHHSFeature
from cartopy.io.shapereader import Reader
canada_east = -63
canada_west = -123
canada_north = 75
canada_south = 37
standard_parallels = (49, 77)
central_longitude = -(91 + 52 / 60)
data = Reader('icitw_wgs84')
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1,
projection=ccrs.LambertConformal(central_longitude=central_longitude,
standard_parallels=standard_parallels))
ax.set_extent([-79.65, -79.1, 43.57, 43.87])
ax.add_feature(cfeature.LAKES.with_scale('10m'))
ax.add_feature(cfeature.LAND.with_scale('10m'))
ax.add_feature(cfeature.RIVERS.with_scale('10m'))
ax.add_geometries(data.geometries(), crs=ccrs.Geodetic(), edgecolor='k', facecolor='none')

I think what you are seeing is due to the low resolution land/lake data set. For maps of this scale you are probably better off using map tiles instead of the NaturalEarth land feature. There are several choices already available in cartopy, Stamen Terrain or Open Street Map might be good choices:
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.io.shapereader import Reader
from cartopy.io.img_tiles import StamenTerrain, OSM
standard_parallels = (49, 77)
central_longitude = -(91 + 52 / 60)
data = Reader('citygcs')
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1,
projection=ccrs.LambertConformal(central_longitude=central_longitude,
standard_parallels=standard_parallels))
ax.set_extent([-79.65, -79.1, 43.57, 43.87])
tiler = OSM()
ax.add_image(tiler, 10)
ax.add_geometries(data.geometries(), crs=ccrs.Geodetic(), edgecolor='k',
facecolor='none')
plt.show()
Or using StamenTerrain:
There may be further issues regarding referencing ellipse (I notice WGS84 in the shapefile name), there is a good reference here: https://scitools.org.uk/cartopy/docs/v0.16/gallery/effects_of_the_ellipse.html.
In future it would help if your code example is minimal and all data is available (I had to go and find a similar shapefile myself to reproduce), see here for a guide: https://stackoverflow.com/help/mcve.

Related

Trouble plotting quivers from netcdf file

I am trying to plot wind quivers from a NetCDF file, however, I can only plot one line of quivers, straight across the base map, as seen in the image. The code is below. Thank you very much for any help :)
data is here, please replace with the onedrive folder, thanks
https://drive.google.com/file/d/160121aFx0Ys6G1jdQZOCT2Ve9eZgOyUy/view?usp=sharing
import xarray as xr
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
data = xr.open_dataset(<Insert google drive file data here>)
data = data.sel(time='2010-04-14T00:00:00.000000000')
X = data.longitude; Y = data.latitude
U = data.u10[200]; V = data.v10[200]
plt.figure()
ax = plt.subplot(111,projection=ccrs.PlateCarree())
ax.quiver(X[::5], Y[::5], U[::5], V[::5],color='green')
plt.show()
I would expect all the quivers to be plotted, so the graph should be full of the green arrows
Currently, this is the plotted image:
You are only taking data from the last row with data.u10[200]. Instead for the quiver, make coordinates as 2D arrays and plot for instance every 5 point of the dataset. Here is my solution, I downloaded and saved your data as "exdata.nc".
#!/usr/bin/env ipython
# --------------------
import xarray as xr
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.pyplot as plt
import numpy as np
# --------------------------------------------------------------------
data = xr.open_dataset('exdata.nc')
data = data.sel(time='2010-04-14T00:00:00.000000000')
X = data.longitude; Y = data.latitude
# --------------------------------------------------------------------
XM,YM = np.meshgrid(X,Y)
U = data.u10; V = data.v10
skipx, skipy = 5,5
# ----------------------------------------------------------------
plt.figure(figsize=(12,12))
ax = plt.subplot(111,projection=ccrs.PlateCarree())
ax.quiver(XM[::skipy,::skipx], YM[::skipy,::skipx], U[::skipy,::skipx], V[::skipy,::skipx],color='green')
ax.add_feature(cfeature.LAND)
ax.add_feature(cfeature.OCEAN)
plt.show()
# ---------------------------------
Hope this helps as an example!

Set plt.colorbar range with python/cartopy

Hello I have this code here, that I use to plot climate maps of aerosols.
import matplotlib.pyplot as plt
from netCDF4 import Dataset as netcdf_dataset
import numpy as np
from cartopy import config
import cartopy.crs as ccrs
import cartopy.feature as cfeature
AODs_Season = netcdf_dataset('/home/vescovint/Documents/AOD_0219_DJF.nc')
lats = AODs_Season.variables['lat'][:]
lons = AODs_Season.variables['lon'][:]
AODS = AODs_Season.variables['AOD_550_Dark_Target_Deep_Blue_Combined_Mean_Mean'][0, :, :]
ax = plt.axes(projection=ccrs.PlateCarree())
plt.contourf(lons, lats, AODS, 60, transform=ccrs.PlateCarree(), cmap='YlOrRd')
plt.colorbar(shrink=0.55)
plt.gcf().set_size_inches(15, 11)
ax.coastlines()
plt.savefig('/home/vescovint/Documents/AOD_Maps/DJF2002')
My problem is that, all my maps avec different range of value on the colorbar from 0 to 5 and i would to set it to min = 0 and max = 3.
I can't figure it out, if anyone can help me, I would be grateful.
Thomas
You can use clim() method from pyplot. For example:
plt.clim(0,3)
to set the color range of your plot (see doc)

ValueError: A non-empty list of tiles should be provided to merge

Can someone help me figure out the error message while using cartopy?
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid.inset_locator import inset_axes
import cartopy.crs as ccrs
import cartopy.io.img_tiles as cimgt
import windrose
ws = np.random.random(500) * 6
wd = np.random.random(500) * 360
minlon, maxlon, minlat, maxlat = (6.5, 7.0, 45.85, 46.05)
proj = ccrs.PlateCarree()
fig = plt.figure(figsize=(12, 6))
# Draw main ax on top of which we will add windroses
main_ax = fig.add_subplot(1, 1, 1, projection=proj)
main_ax.set_extent([minlon, maxlon, minlat, maxlat], crs=proj)
main_ax.gridlines(draw_labels=True)
main_ax.coastlines()
request = cimgt.OSM()
main_ax.add_image(request, 12)
The error I receive is ValueError: A non-empty list of tiles should be provided to merge.
and can't seem to figure out what's the issue.
Your request is rejected by OSM server. To get around it, you need to use image_spoof() as demonstrated
in this link.
With image_spoof() in place, your relevant code should be:-
# reformat web request for street map spoofing
cimgt.OSM.get_image = image_spoof
# continued with your code
request = cimgt.OSM() # spoofed

Visualizing netCDFs xarray

Hello everyone.In the picture you can see a sample of my code(it repeats for i==6),and the outputs.Can somone tell me how to add coastlines/boundaries to maps?"ax.coastlines() failed. Thank you
I think the problem is that your axes is not a geoAxes. To make it a geoAxes you have to tell matplotlib what projection (e.g. PlateCarree) you would like to use.
What you could do is using the cartopy library and adding the projection key word to your subplot. See example below:
import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
# Create sample data
lon = np.arange(129.4, 153.75+0.05, 0.25)
lat = np.arange(-43.75, -10.1+0.05, 0.25)
data = 10 * np.random.rand(len(lat), len(lon))
data_array = xr.Dataset({"DC": (["lat", "lon"], data),
'DMC': (["lat", "lon"], data),
'FFMC': (["lat", "lon"], data)},
coords={"lon": lon,"lat": lat})
# Just checking the datasets are not empty
print(data_array)
#< Plotting
fig, axes = plt.subplots(nrows=3, ncols=3, subplot_kw={'projection': ccrs.PlateCarree()}) # Use PlateCarree projection
data_array['DC'].plot(ax=axes[0,0], cmap='Spectral_r', add_colorbar=True, extend='both')
axes[0,0].coastlines() # Add coastlines

cartopy North Pole Stereographic contour plot does not plot correctly even with cyclic point

I am trying to plot contours over the north pole, using cartopy. I have used add_cyclic_point and this has successfully filled in the gap at the prime meridian in pcolormesh, but the contours do not cross successfully, and instead wrap all the way around the globe to connect (but it seems not always?) My longitudes go from 0-360 and I have tried to switch to -180-180 but still get the same issue.
Here is my code:
import numpy as np
from netCDF4 import Dataset
import cartopy.crs as ccrs
import cartopy
from cartopy.util import add_cyclic_point as cycpt
import matplotlib.pyplot as plt
date = '2018_02_10'
pdatafile = Dataset(date+'_mslp.nc')
plat = np.array(pdatafile.variables['lat'])
plon = np.array(pdatafile.variables['lon'])
p = np.array(pdatafile.variables['slp'][0,:,:])
p_cyclic,lon_cyclic = cycpt(p,coord=plon)
lon_cyclic = np.ma.getdata(lon_cyclic)
plon2d,plat2d= np.meshgrid(lon_cyclic,plat)
p_cyclic = np.ma.getdata(p_cyclic)
g1000datafile = Dataset(date+'_1000mb_gph.nc')
g1lat = np.array(g1000datafile.variables['lat'])
g1lon = np.array(g1000datafile.variables['lon'])
g1000 = np.array(g1000datafile.variables['hgt'][0,0,:,:])
g1_cyclic,g1lon_cyclic = cycpt(g1000,coord=g1lon)
g1lon2d,g1lat2d= np.meshgrid(g1lon_cyclic,g1lat)
g1lon2d = np.ma.getdata(g1lon2d)
g1_cyclic = np.ma.getdata(g1_cyclic)
g500datafile = Dataset(date+'_500mb_gph.nc')
g5lat = np.array(g500datafile.variables['lat'])
g5lon = np.array(g500datafile.variables['lon'])
g500 = np.array(g500datafile.variables['hgt'][0,0,:,:])
g5_cyclic,g5lon_cyclic = cycpt(g500,coord=g5lon)
g5lon2d,g5lat2d= np.meshgrid(g5lon_cyclic,g5lat)
g5lon2d = np.ma.getdata(g5lon2d)
g5_cyclic = np.ma.getdata(g5_cyclic)
thickness = g5_cyclic - g1_cyclic
mslplevels=[960,970,980,990,1000,1010,1020,1030,1040,1050]
levels500hPa = [470,480,490,500,510,520,530,540,550,560]
ax = plt.axes(projection=ccrs.NorthPolarStereo(central_longitude=0))
ax.set_extent([-180, 180, 50, 90], crs=ccrs.PlateCarree())
plt.pcolormesh(plon2d,plat2d,thickness/10, transform=ccrs.PlateCarre(),cmap='inferno')
cbar=plt.colorbar()
cbar.set_label('ReTop (gpdam)')
cs=plt.contour(plon2d,plat2d,g5_cyclic/10,colors='w',transform=ccrs.PlateCarree(),\
levels=levels500hPa)
plt.clabel(cs,inline=1,fontsize=6,fmt='%3.0f')
ax.coastlines()
plt.show()
plt.close()
an example plot
import numpy as np
from netCDF4 import Dataset
import cartopy.crs as ccrs
from cartopy.util import add_cyclic_point as cycpt
import matplotlib.pyplot as plt
pdatafile = Dataset('X158.39.88.89.59.7.59.32.nc')
plat = np.array(pdatafile.variables['lat'])
plon = np.array(pdatafile.variables['lon'])
p = np.array(pdatafile.variables['slp'][0,:,:])
p_cyclic,lon_cyclic = cycpt(p,coord=plon)
lon_cyclic = np.ma.getdata(lon_cyclic)
p_cyclic = np.ma.getdata(p_cyclic)
plon2d,plat2d= np.meshgrid(lon_cyclic,plat)
ax = plt.axes(projection=ccrs.NorthPolarStereo(central_longitude=0))
ax.set_extent([-180, 180, 50, 90], crs=ccrs.PlateCarree())
plt.contour(plon2d,plat2d,g5_cyclic/10,colors='w',transform=ccrs.PlateCarree())
plt.clabel(cs,inline=1,fontsize=6,fmt='%3.0f')
ax.coastlines()
plt.show()
ftp://ftp.cdc.noaa.gov/Public/www/X158.39.88.89.59.7.59.32.nc
I suspect the problem is to do with contour labels, which are known not to work well in Cartopy (see https://github.com/SciTools/cartopy/issues/13 and https://github.com/SciTools/cartopy/issues/327). If you remove the labels the contours should render correctly.
I'm a cartopy developer and I'd like to see what I can do, but your code snippet is a little bit impenetrable. If I could access your data then it might not matter so much, but I can't, so I can't run it or debug it.
Can you cut down your script please to something self-contained or at least minimal, noiseless and clear. Thanks.
Also you have a typo in your plot call so your transform is PlateCarre instead of Platecarree. I don't know how much difference this will make but it's worth correcting.

Categories

Resources