Python : Basemap barbs , wind vector plotting on map - python

I'm trying to plotting wind vector on map using basemap.barbs.
I try to draw it as a test with simple code.
No error message is shown with this code, Even if I wait, the picture does not come out..
If a picture is being drawn, the picture does not come out even after waiting a long time.
I think there seems to be something else wrong.
It is the first time to draw a wind field with Python, so I'm immature.
Is it because of the high data resolution? (Its len(lon) is 360, len(lat) is 200)
Or is it another matter?
import netCDF4 as nc
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap,addcyclic,shiftgrid
data=nc.Dataset('wind.nc','r')
lon=data.variables['XU_OCEAN'][:]
lat=data.variables['YU_OCEAN'][:]
time=data.variables['TIME1'][:]
uwind=data.variables['WIND_POWER_U'][:]
vwind=data.variables['WIND_POWER_V'][:]
uwind_DJF=[]
vwind_DJF=[]
for i in range(11,20*12+1,12):
uwind_DJF.append((uwind[i]+uwind[i+1]+uwind[i+2])/3)
vwind_DJF.append((vwind[i]+vwind[i+1]+vwind[i+2])/3)
uwind_DJF=np.mean(uwind_DJF,axis=0) ##shape is (200,360)
vwind_DJF=np.mean(vwind_DJF,axis=0) ##shape is (200,360)
fig=plt.figure(figsize=(12,9))
m=Basemap(resolution='l',projection='cyl',llcrnrlon=-90,llcrnrlat=30,urcrnrlon=80,urcrnrlat=70)
m.drawparallels(np.arange(-90,90,30),labels=[1,0,1,0],fontsize=10)
m.drawmeridians(np.arange(-180,180,45),labels=[0,0,0,1],fontsize=10)
m.drawcoastlines()
m.drawstates()
m.drawcountries()
lon2d,lat2d=np.meshgrid(lon,lat)
x,y=m(lon2d,lat2d)
m.barbs(x,y,uwind_DJF,vwind_DJF)
plt.show()

Related

Polar pcolormesh shifts center when used set_ylim in matplotlib

Although I am providing a excerpt of the code I am using, but this piece contains the problem I am facing. I am trying to plot density of the particles over the disc and hence polar plot seems natural to use. So I have used following piece of code to read a density file which contains the density with rows and column representing radius and angular direction.
#! /usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
from os.path import exists
from os import sys
import matplotlib as mpl
from matplotlib import rc
NUMBINS=100
rmax=20.0
dR2=rmax*rmax/NUMBINS
density = np.random.random((NUMBINS, NUMBINS))
r = np.sqrt(np.arange(0,rmax*rmax,dR2) )[:NUMBINS]
theta = np.linspace(0,2*np.pi,NUMBINS)
mpl.rcParams['legend.fontsize'] = 10
mpl.rcParams['pcolor.shading'] ='nearest'
fig = plt.figure(figsize=(5, 5))
ax1 = plt.subplot(111,projection="polar")
rad, th = np.meshgrid(r,theta)
ax1.set_yticks(np.arange(0,rmax,3))
ax1.pcolormesh(th,rad,density,cmap='Blues')
#ax1.set_ylim([rad[0,0], rad[0,NUMBINS-1]])
plt.tight_layout()
plt.show()
which gives me the following plot :
As you can see that the radius starts from 0 to rmax, removing the commented line
ax1.set_ylim([rad[0,0], rad[0,NUMBINS-1]])
shall not have any effect on the plot but it shifts the center of the plot :
I don't understand why setting ymin=0 creates this white space in the center?
Turns out that it is a problem with version of matplotlib. I tried a different version and the plot works as expected. Apologies for not trying it earlier.

Interpolation causes issues with plotting in xarray

I'm trying to do some analysis of CMIP6 climate model data, and I want to produce some multi-model ensemble plots. In order to do that I need to interpolate the data to a common grid. The interpolation of the data seems to work fine, but whenever I try to plot the interpolated data it seems like there's a gap in the data at the prime meridian and at the poles. Here's a simple example where I interpolate MPI-ESM data to the grid of CESM2-WACCM:
import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
cesm2_waccm = xr.open_dataset('pr_day_CESM2-WACCM_ssp245_r2i1p1f1_gn_20750101-20841231.nc')
mpi = xr.open_dataset('pr_day_MPI-ESM1-2-LR_ssp245_r1i1p1f1_gn_20750101-20941231.nc')
cesm2_waccm_subset = cesm2_waccm.sel(time=slice('2075-01-01', '2075-12-31')).mean(dim='time')
mpi_subset = mpi.sel(time=slice('2075-01-01', '2075-12-31')).mean(dim='time')
map_proj = ccrs.PlateCarree()
# This works.
plot = mpi_subset.pr.plot(subplot_kws={'projection': map_proj})
plot.axes.coastlines()
plt.show()
mpi_interp = mpi_subset.interp(lat=cesm2_waccm_subset['lat'], lon=cesm2_waccm_subset['lon'])
# This has a white line at prime meridian.
plot = mpi_interp.pr.plot(subplot_kws={'projection': map_proj})
plot.axes.coastlines()
plt.show()
As you can see, the first plot is fine:
And the second plot has a white line at the prime meridian and at the poles:
Is there anything I can do to get rid of that line?
Also, here are the versions of the packages I have installed which I think are relevant to this question:
xarray 0.20.1
cartopy 0.20.1
matplotlib 3.3.2

Plot wind vectors with quiver()

I want to plot wind vectors. I use Basemap and this example http://basemaptutorial.readthedocs.org/en/latest/plotting_data.html#quiver.
In my file, the longitudes go from 0 to 360. I use latlon=True to shift it to -180:180. But, when I use "points" to define the point density, the vectors are plotted over half of my figure only.
Here is the code:
Of course, I use this code:
m=Basemap(projection='cyl',llcrnrlat=30,urcrnrlat=80, llcrnrlon=-40,urcrnrlon=40,resolution='c')
latvar=nc.variables['lat']
lat=latvar[:]
lon=nc.variables['lon'][:]
X,Y=m(lon,lat)
lons,lats=meshgrid(lon,lat)
X4,Y4=m(lons,lats)
varU=ncU.variables['var1'][0,0,:,:]
varV=ncV.variables['var2'][0,0,:,:]
speed=np.sqrt(varUvarU+varVvarV)
yy=np.arange(0,len(Y[:]),3)
xx=np.arange(0,len(X[:]),3)
points=np.meshgrid(yy,xx)
m.quiver(X4[points],Y4[points],varU[points],varV[points],speed[points],cmap=cmap‌​,latlon=True)
Can someone help me with this issue? Thanks.
You have a lot of things going on that I am not sure you need. I have tried your code with some minor modifications and it works:
import numpy
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
lon =NC.variables['lon'][:]
lat =NC.variables['lat'][:]
m=Basemap(projection='cyl',,llcrnrlat=30,urcrnrlat=80, llcrnrlon=-40,urcrnrlon=40,resolution='c')
lons,lats=numpy.meshgrid(lon,lat)
X4,Y4=m(lons,lats)
varU=NC.variables['var1'][0,0,:,:]
varV=NC.variables['var2'][0,0,:,:]
speed=numpy.sqrt(varU*varU+varV*varV)
yy=numpy.arange(0,len(lat),3)
xx=numpy.arange(0,len(lon),3)
points=numpy.meshgrid(yy,xx)
m.quiver(X4[points],Y4[points],varU[points],varV[points],speed[points],cmap=cmap,latlon=True)
plt.show()
# with all points for comparison
m.quiver(X4,Y4,varU,varV,speed,cmap=cmap,latlon=True)
plt.show()

Matplotlib Mollweide/Hammer projection: region of interest only

I was wondering if there's a way to only show the region of interest from a plot based on Mollweide/Hammer projection in basemap (matplotlib).
I am trying to set the plot-bounds roughly to the Pacific plate, as in the link below. However, the set_xlim and set_ylim functions do not seem to have any effect. Thanks in advance for any guidance.
http://geology.gsapubs.org/content/29/8/695/F1.large.jpg
From the documentation, both Hammer and Mollweide projections don't allow this as they print out entire world maps. Here's some code using Polyconic projection, but it is bounded by straight lines. The trick here is to define the corner longitude and latitudes on creation.
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
my_map = Basemap(projection='poly', lat_0=0, lon_0=-160,
resolution = 'h', area_thresh = 0.1,
llcrnrlon=140, llcrnrlat=-60,
urcrnrlon=-100, urcrnrlat=60)
plt.figure(figsize=(16,12))
my_map.drawcoastlines()
my_map.drawcountries()
my_map.fillcontinents(color='coral', lake_color='aqua')
my_map.drawmapboundary(fill_color='aqua')
my_map.drawmeridians(np.arange(0, 360, 20))
my_map.drawparallels(np.arange(-90, 90, 10))
plt.show()
Result:
Note that this effectively shows less area than the one in the picture you provided.

pcolormesh draws not points but lines between data points

I need to plot data of rain summas (from satellite observations) onto a map from grib2 files. Finally I managed to load the data via text files into numpy arrays and tie it with picture coordinates using Basemap. But problem is that Python do not put the coloured points from the data, but tends to draw lines between neighbouring points in data field, so the plot looks ugly.
I do not see the source of the problem.
Fragments of my code are:
import numpy as np
import matplotlib
matplotlib.use('Agg')
from scipy import *
from pylab import *
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import cm
After that I read the data needed and produce 3 numpy arrays with shapes approximately (100000, 2), which contain respectively latitude, longitude, in degrees and the value of each data point. I visualize it using these commands:
def joonista(lats,lons,value,nimi,clevs,koloriit):
---------fragment of described reshaping (not shown), produces arrays "lats", "lons", "value"------------
map=Basemap(projection='aea',lat_1=30,lat_2=50,lat_0=45,lon_0=0,llcrnrlon=-30,llcrnrlat=20,urcrnrlon=80,urcrnrlat=53,resolution='l',)
x, y = map(lons, lats)
map.drawcoastlines(linewidth=0.17,color='0.7')
map.drawcountries(linewidth=0.17,color='0.7')
map.drawmeridians(np.arange(-50,60,5),linewidth=0.17,color='0.7',labels=[False,False,False,True])
map.drawparallels(np.arange(-25, 70, 5),linewidth=0.17,color='0.7',labels=[True,False,False,False])
varvid=mpl.colors.ListedColormap(koloriit)
norm = mpl.colors.BoundaryNorm(clevs,varvid.N)
cs = map.pcolormesh(x,y,value,cmap=varvid,norm=norm)
savefig(nimi,dpi=300)
plt.clf()
joonista(latA,lonA,valueA,'h05',[-1,0.00001,0.001,0.01,0.1,0.3,0.5,1,2,3,4,5,6,7,8,9,10,11,12,13],['k','c','#a0fff9','#00b354','#69b300','#97ff03','#C2524D','#FF7500','#b3a900','#fff551','#515bff','#45adff','#da000d','#ff2a36','#ffa0a5','#f003ff','#f778ff','0.5','0.75'])
joonista(latB,lonB,valueB,'h04',[-1,0.0000000000001,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18],['k','c','#a0fff9','#00b354','#69b300','#97ff03','#C2524D','#FF7500','#b3a900','#fff551','#515bff','#45adff','#da000d','#ff2a36','#ffa0a5','#f003ff','#f778ff','0.5','0.75'])
Here is an example picture:
I would be grateful, if I am told how to solve this problem.
Aleksei
Using Joe Kington recommendation, I replaced command
cs=map.pcolormesh(x,y,value,cmap=varvid,norm=norm)
by command
cs=plt.scatter(x,y,c=value,s=0.6, edgecolors='none',marker=',',cmap=varvid,norm=norm)
which well visualises precipitation distribution.
Thanks for assistance!

Categories

Resources