Раньше для построения карт использовался модуль basemap
pip, но он устарел и более не поддерживается. На замену ему пришел модуль cartopy
pip. Установка пакета cartopy
в Windows из pip вызывает сложности, поэтому вот готовые пакеты для разных версий Python:
Для выбора нужной проекции используем документацию.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from cartopy import crs as ccrs
fig = plt.figure()
ax = fig.add_subplot(projection=ccrs.PlateCarree())
ax.set_extent([-6, 3, 48, 58], crs=ccrs.PlateCarree())
gl = ax.gridlines(draw_labels=True)
gl.xlocator = mticker.FixedLocator(np.arange(-6.0,3.0,2.0))
gl.ylocator = mticker.FixedLocator(np.arange(48.0,58.0,2.0))
ax.scatter([-2],[52], transform=ccrs.PlateCarree())
ax.coastlines(resolution='50m')
Рисование данных поверх карты выполняется обычными методами, например plot
с добавлением параметра transform
если координаты указаны, как долгота и широта в градусах.
Картографические данные cartopy
берет из проекта Natural Earth.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from cartopy import crs as ccrs
import cartopy.feature
#%%
fig = plt.figure()
ax = fig.add_subplot(projection=ccrs.PlateCarree())
ax.set_extent([-6, 3, 38, 48], crs=ccrs.PlateCarree())
gl = ax.gridlines(draw_labels=True)
gl.xlocator = mticker.FixedLocator(np.arange(-6.0,3.0,2.0))
gl.ylocator = mticker.FixedLocator(np.arange(38.0,48.0,2.0))
resol = '50m' # еще есть '110m' - самая грубая версия и '10m' - самая точная версия
bodr = cartopy.feature.NaturalEarthFeature(category='cultural',
name='admin_0_boundary_lines_land', scale=resol, facecolor='none', alpha=0.7)
land = cartopy.feature.NaturalEarthFeature('physical', 'land', \
scale=resol, edgecolor='k', facecolor=cartopy.feature.COLORS['land'])
ocean = cartopy.feature.NaturalEarthFeature('physical', 'ocean', \
scale=resol, edgecolor='none', facecolor=cartopy.feature.COLORS['water'])
lakes = cartopy.feature.NaturalEarthFeature('physical', 'lakes', \
scale=resol, edgecolor='b', facecolor=cartopy.feature.COLORS['water'])
rivers = cartopy.feature.NaturalEarthFeature('physical', 'rivers_lake_centerlines', \
scale=resol, edgecolor='b', facecolor='none')
ax.add_feature(land)
ax.add_feature(ocean)
ax.add_feature(lakes)
ax.add_feature(rivers)
ax.add_feature(bodr, linestyle='--', alpha=1)
Какие именно картографические данные доступны см. по ссылке https://github.com/nvkelso/natural-earth-vector в наборах cultural
и physical
. Карты автоматически скачиваются по мере надобности, при этом в консоль выводится предупреждение DownloadWarning
.
from cartopy.io.img_tiles import GoogleWTS, OSM, GoogleTiles
class ArcGISWSR(GoogleWTS):
def _image_url(self, tile):
x, y, z = tile
return f'https://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}.jpg'
tiles_provider = OSM()
#tiles_provider = GoogleTiles()
#tiles_provider = GoogleTiles()
plt.figure(figsize=(16, 16))
ax = plt.axes(projection=tiles_provider.crs)
ax.set_extent([-6, 3, 38, 48], ccrs.PlateCarree())
ax.add_image(tiles_provider, 6)
plt.show()
# Скрытие части подписей по осям:
gridlines = ax.gridlines(draw_labels=True)
gridlines.top_labels = False
gridlines.right_labels = False
# Добавление теплокарты:
im = ax.imshow(data, origin='upper', extent =[lon[0], lon[-1], lat[-1], lat[0]], transform=ccrs.PlateCarree(), cmap = cmap)
fig.colorbar(im, ax=ax)
#Добавление точки с подписью:
ax.scatter([50.8667],[61.6667], transform=ccrs.PlateCarree())
mpl_trans = ccrs.PlateCarree()._as_mpl_transform(ax)
ax.annotate('SYKTYVKAR',(50.8667,61.6667), xycoords=mpl_trans)
import netCDF4 as nc
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from cartopy import crs as ccrs
# Добавляем encoding если 1. в Windows и 2. в пути к файлу есть русские буквы (и другие символы Unicode)
ds = nc.Dataset("file.nc", encoding="cp1251")
print(ds) # обзор структуры NetCDF файла
data = ds['varname'][57,:,:] # получаем нужный срез нужной переменной
#Задаем экстент по границам данных в файле
ax.set_extent([ds['lon'][0], ds['lon'][-1], ds['lat'][0], ds['lat'][-1]], crs=ccrs.PlateCarree())