Карты
Раньше для построения карт использовался модуль 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
если координаты указаны, как долгота и широта в градусах.
Картографические данные Natural Earth
Картографические данные 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
.
Использование Tile-серверов в cartopy
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()
Некоторые приемы работы с cartopy
# Скрытие части подписей по осям:
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)
Построение карт из NetCDF файлов
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())