Python Basemap Heatmap - python

I am trying to copy the method that was done on this page: https://makersportal.com/blog/2018/7/20/geographic-mapping-from-a-csv-file-using-python-and-basemap under "Mapping Interesting Data" to have a color bar associated with my data.
Right now I just get a plain map of South America, which is what I want as my background but there is no data included.
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
m = Basemap(projection='mill',
llcrnrlat = -30, #bottom
llcrnrlon = -120, #left
urcrnrlat = 20, #top
urcrnrlon = -50, #right
resolution='c')
m.drawcoastlines()
m.drawcountries()
# format colors for elevation range
SST_min = np.min(df5.DaasgardSST)
SST_max = np.max(df5.DaasgardSST)
cmap = plt.get_cmap('gist_earth')
normalize = matplotlib.colors.Normalize(vmin=SST_min, vmax=SST_max)
# plot SST with different colors
for i in range(0,len(df5.DaasgardSST)):
x,y = m(lon,lat)
color_interp = np.interp(df5,[SST_min,SST_max],[0,30])
plt.plot(x,y,marker='o',markersize=6,color=cmap(int(color_interp)))
# format the colorbar
cax, _ = matplotlib.colorbar.make_axes(ax)
cbar = matplotlib.colorbar.ColorbarBase(cax, cmap=cmap,norm=normalize,label='Elevation')
plt.title('Title')
plt.show()

Related

Overlay/Fill country boundaries with image in

Is there a way to fill a country with an image similar to R solution using custom library here:
I have a solution where the face colour is filled for instance the below where Italy is blue. However, I would like to add the Italian flag. Is there a way in Python (I have not found much after searching) or is something like QGIS needed:
#create a map where I can load images in to fill the countries
import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.io.shapereader as shpreader
flag = "italy.png" #this is a locally saved png.
plt.figure(figsize=(15, 15)) #size of plot
ax = plt.axes(projection=cartopy.crs.TransverseMercator(25))
ax.add_feature(cartopy.feature.BORDERS, linestyle='-', alpha=1)
ax.coastlines(resolution='110m') #simplifies the border lines
ax.add_feature(cartopy.feature.OCEAN, facecolor="#40e0d0") #colour of ocean
# ax.gridlines() #adds global grid lines
ax.set_extent ((-7.5, 50, 34, 69), cartopy.crs.PlateCarree()) #makes it european
shpfilename = shpreader.natural_earth(resolution='110m',
category='cultural',
name='admin_0_countries')
for country in shpreader.Reader(shpfilename).records():
if country.attributes['NAME_LONG'] == "Italy":
ax.add_geometries(country.geometry, ccrs.PlateCarree(),
facecolor="blue",
#no attribute like this img= "fd",
label=country.attributes['NAME_LONG'])
plt.show()
Any help, much appreciated!
Here is a demo code that does what you need. As a matter of fact, cartopy logo uses this technique to create.
import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.io.shapereader as shpreader
import matplotlib.patches as mpatches
import numpy as np
imdat1 = plt.imread('flag-of-italy.jpg', format='jpg') # use your flag
plt.figure(figsize=(8, 8))
ax = plt.axes(projection=cartopy.crs.TransverseMercator(25))
ax.add_feature(cartopy.feature.BORDERS, linestyle='-', alpha=1)
ax.coastlines(resolution='110m')
ax.add_feature(cartopy.feature.OCEAN, facecolor="#40e0d0")
# ax.gridlines() #adds global grid lines
ax.set_extent ((-7.5, 50, 24, 69), cartopy.crs.PlateCarree())
shpfilename = shpreader.natural_earth(resolution='110m',
category='cultural',
name='admin_0_countries')
italy_ctry = None #use this to grab italy's
for country in shpreader.Reader(shpfilename).records():
if country.attributes['NAME_LONG'] == "Italy":
italy_ctry = country
ax.add_geometries(country.geometry, ccrs.PlateCarree(),
facecolor="none",
alpha=0.7,
zorder=2,
label=country.attributes['NAME_LONG'])
# create mpatch from `italy` geometry
cg = italy_ctry.geometry
cg2 = cg.simplify(0.02)
if cg2.geometryType()=='MultiPolygon':
# if == `Polygon`, dont need to loop
for ea in cg2.geoms:
cg2xy = ea.exterior.xy # tuple of (x,y)
xys = []
for ea in zip(cg2xy[0], cg2xy[1]):
#print(ea[0],ea[1])
xys.append([ea[0],ea[1]])
# add a patch
poly = mpatches.Polygon(xys, closed=True, ec='r', \
lw=2, fc='yellow', \
transform=ccrs.PlateCarree(), \
alpha=0.5, zorder=30)
plate_carree_transform = ccrs.PlateCarree()._as_mpl_transform(ax)
xtent1 = (6.519950, 17.122259, 35.783370, 47.962952)
imdat2 = ax.imshow(imdat1, origin='upper', extent=xtent1, \
transform=ccrs.PlateCarree(), \
zorder=15, alpha=.9)
##imdat2 = ax.stock_img() #for testing
imdat2.set_clip_path(mpatches.Path(xys), transform=plate_carree_transform)
pass
plt.show()
The sample plot (varies with the flag in use):

How to plot coordinate using basemap and file.csv

I am in trouble with how to plot the coordinate given in a file.csv using basemap. It has error when I run with latlon=True. My code below :
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
df=pd.read_csv('E:\Classification\DATA.csv')
lat=df['Latitude']
lon=df['Longitude']
plt.figure(figsize=(12,7))
m = Basemap(projection='mill',
llcrnrlat = 7,
urcrnrlat = 25,
llcrnrlon = 90,
urcrnrlon = 120,
resolution = 'l')
m.drawcoastlines()
m.drawcountries()
m.drawstates()
m.fillcontinents(color='None',lake_color='#FFFFFF')
m.drawmapboundary(color='k', linewidth=1.0, fill_color=None, zorder=None, ax=None)
parallels = np.arange(0.,81,10.)
# labels = [left,right,top,bottom]
m.drawparallels(parallels,labels=[False,True,True,False])
meridians = np.arange(10.,351.,5.)
m.drawmeridians(meridians,labels=[True,False,False,True])
m.scatter(lon,lat,latlon=True,c='red', marker='o',linewidth=1, zorder=2)
plt.show()
I really appreciate if some of you can help me. Thank you so much.
Try using lon.values, lat.values in place of lon, lat in m.scatter().
m.scatter(lon.values, lat.values, latlon=True,c='red', marker='o',linewidth=1, zorder=2)

Aligning data (contourf) on Basemap

I've started working with Basemap, which seems potentially very useful.
If I plot some global data on a latitude/longitude grid as filled contours, it works great: Iff I leave the lat_0 and lon_0 as zero. Once I change the center location, the map moves but the data doesn't. I would be grateful for advice.
I've created a simple version of the code I'm using, with some simple sample data that illustrates the problem. The values should be (are) large at the equator but small at the poles. If you run the code with lat_0 and lon_0 = 0, it works fine. But if you change the center location to a different coordinate, the same pattern/data is presented even though the map has moved.
from mpl_toolkits.basemap import Basemap, cm
import matplotlib.pyplot as plt
import numpy as np
# create data
lat = np.linspace(-90,90,num=180)
lon = np.linspace(-180,180,num=361)
h2o_north = np.linspace(1,65,num=90)
h2o_south = np.flipud(h2o_north)
h2o = np.append(h2o_north,h2o_south)
data = np.transpose(np.tile(h2o,(len(lon),1)))
# create figure and axes instances
fig = plt.figure(figsize=(10,10))
ax = fig.add_axes([0.1,0.1,0.8,0.8])
# create map
m = Basemap(projection='ortho',lon_0=-50,lat_0=50,resolution='l')
# draw coastlines and country boundaries
m.drawcoastlines()
m.drawcountries()
# draw parallels
parallels = np.arange(-90.,90,10.)
m.drawparallels(parallels)
# draw meridians
meridians = np.arange(180.,360.,10.)
m.drawmeridians(meridians)
ny = data.shape[0]
nx = data.shape[1]
lons, lats = m.makegrid(nx, ny) # get lat/lons of ny by nx evenly space grid
x, y = m(lons, lats) # compute map projection coordinates
# draw filled contours.
clevs = np.linspace(0,70,num=281)
cs = m.contourf(x,y,data,clevs,cmap=plt.cm.jet)
# colorbar
cbar = m.colorbar(cs,location='bottom',pad="5%",ticks=np.linspace(0,70,15))
cbar.set_label('Scale of the data')
plt.title('Some global data', fontsize=14)
Use np.meshgrid() to create the meshgrid of lon-lat, then, convert it to projection coordinates, and the data are ready to generate contours and plot.
Here is the working code:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
# data for z (2D array)
h2o_north = np.linspace(1, 65, num=90)
h2o_south = np.flipud(h2o_north)
h2o = np.append(h2o_north, h2o_south)
data = np.transpose(np.tile(h2o, (len(h2o_north), 1)))
# create figure and axes instances
fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot()
# create basemap instance
m = Basemap(projection='ortho', lon_0=-50, lat_0=50, resolution='c', ax=ax)
# create meshgrid covering the whole globe with ...
# conforming dimensions of the `data`
lat = np.linspace(-90, 90, data.shape[0])
lon = np.linspace(-180, 180, data.shape[1])
xs, ys = np.meshgrid(lon, lat) # basic mesh in lon, lat (degrees)
x, y = m(xs, ys) # convert (lon,lat) to map (x,y)
# draw filled contours
clevs = np.linspace(0, np.max(data), 60)
cs = m.contourf(x, y, data, clevs, cmap=plt.cm.jet)
m.drawcoastlines()
m.drawcountries()
m.drawmeridians(range(-180, 180, 30))
m.drawparallels(range(-90, 90, 30))
# draw colorbar
cbar = m.colorbar(cs, location='bottom', pad="5%", ticks=np.linspace(0, np.max(data), 5))
cbar.set_label('Scale of the data')
plt.show()
The resulting plot:

Bigger marker size for plot using pcolormesh

I am trying to create a color mesh plot but the data points and their corresponding colors appear too small.
My script is:
import pandas as pd
import numpy as np
from mpl_toolkits.basemap import Basemap, cm
import matplotlib.pyplot as plt
df = pd.read_csv('data.csv', usecols=[1,2,4])
df = df.apply(pd.to_numeric)
val_pivot_df = df.pivot(index='Latitude', columns='Longitude', values='Bin 1')
lons = val_pivot_df.columns.astype(float)
lats = val_pivot_df.index.astype(float)
fig, ax = plt.subplots(1, figsize=(8,8))
m = Basemap(projection='merc',
llcrnrlat=df.dropna().min().Latitude-5
, urcrnrlat=df.dropna().max().Latitude+5
, llcrnrlon=df.dropna().min().Longitude-5
, urcrnrlon=df.dropna().max().Longitude+5
, resolution='i', area_thresh=10000
)
m.drawcoastlines()
m.drawstates()
m.drawcountries()
m.fillcontinents(color='gray', lake_color='white')
m.drawmapboundary(fill_color='0.3')
x, y = np.meshgrid(lons,lats)
px,py = m(x,y)
data_values = val_pivot_df.values
masked_data = np.ma.masked_invalid(data_values)
cmap = plt.cm.viridis
m.pcolormesh(px, py, masked_data, vmin=0, vmax=8000)
m.colorbar()
plt.show()
I'm looking to get the markersize larger of each data point but I can't seem to find any documentation on how to do this for pcolormesh
There is no marker in a pcolormesh. The size of the colored areas in a pcolor plot is determined by the underlying grid. As an example, if the grid in x direction was [0,1,5,105], the last column would be 100 times larger in size than the first.
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)
x = [0,1,5,25,27,100]
y = [0,10,20,64,66,100]
X,Y = np.meshgrid(x,y)
Z = np.random.rand(len(y)-1, len(x)-1)
plt.pcolormesh(X,Y,Z)
plt.show()

Contour data with cartopy

I am trying to plot some bathymetry data using cartopy. I slice out a section of the data and plot it over a Mercator projection. It produces a map that looks ok but I get the following error,
IllegalArgumentException: Invalid number of points in LinearRing found 3 - must be 0 or >= 4
Shell is not a LinearRing
Should I be worried about this? My code is below,
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['contour.negative_linestyle'] = 'solid'
import cartopy.crs as ccrs
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
import cartopy.feature as cfeature
from netCDF4 import Dataset
# load data and slice out region of interest
_file = 'GEBCO_2014_2D.nc'
gebco = Dataset(_file, mode='r')
g_lons = gebco.variables['lon'][:]
g_lon_inds = np.where((g_lons>=-30) & (g_lons<=10))[0]
g_lons = g_lons[g_lon_inds]
g_lats = gebco.variables['lat'][:]
g_lat_inds = np.where((g_lats>=40) & (g_lats<=65))[0]
g_lats = g_lats[g_lat_inds]
d = gebco.variables['elevation'][g_lat_inds, g_lon_inds]
gebco.close()
# plot data
projection=ccrs.Mercator()
extent = [-30, 10, 40, 65]
fig = plt.figure(figsize=(13.3, 10))
ax = fig.add_subplot(111, projection=projection)
lon_labels = np.arange(-30, 20, 10)
lat_labels = np.arange(40, 75, 10)
gl = ax.gridlines(draw_labels=True, xlocs=lon_labels, ylocs=lat_labels)
gl.xlabels_top = gl.ylabels_right = False
gl.xformatter = LONGITUDE_FORMATTER
gl.yformatter = LATITUDE_FORMATTER
ax.set_extent(extent, crs=ccrs.PlateCarree())
coastline_10m = cfeature.NaturalEarthFeature('physical', 'coastline', '10m',
edgecolor='k', alpha=0.6,
facecolor=cfeature.COLORS['land'])
ax.add_feature(coastline_10m)
CS = plt.contour(g_lons, g_lats, d, [-1000,-150],
colors='k', alpha=0.4, linewidth=0.5, zorder=1,
transform=ccrs.PlateCarree())
plt.clabel(CS, inline=True, fontsize=10, fmt='%i')

Categories

Resources