Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

calc:maps [2023/04/10 09:45] (текущий)
root создано
Строка 1: Строка 1:
 +<div slide>
  
 +===== Карты =====
 +
 +Раньше для построения карт использовался модуль ''basemap''<sup>pip</sup>, но он устарел и более не поддерживается. На замену ему пришел модуль ''cartopy''<sup>pip</sup>. Установка пакета ''cartopy'' в Windows из pip вызывает сложности, поэтому вот готовые пакеты для разных версий Python:
 +
 +  * {{ :calc:cartopy-0.21.1-cp38-cp38-win_amd64.whl | cartopy-0.21.1-cp38-cp38-win_amd64.whl}}
 +  * {{ :calc:cartopy-0.21.1-cp39-cp39-win_amd64.whl | cartopy-0.21.1-cp39-cp39-win_amd64.whl}}
 +  * {{ :calc:cartopy-0.21.1-cp310-cp310-win_amd64.whl | cartopy-0.21.1-cp310-cp310-win_amd64.whl}}
 +  * {{ :calc:cartopy-0.21.1-cp311-cp311-win_amd64.whl | cartopy-0.21.1-cp311-cp311-win_amd64.whl}}
 +
 +Для выбора нужной проекции используем [[https://scitools.org.uk/cartopy/docs/latest/reference/projections.html#cartopy-projections|документацию]].
 +
 +<sxh 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')
 +</sxh>
 +
 +Рисование данных поверх карты выполняется обычными методами, например ''plot'' с добавлением параметра ''transform'' если координаты указаны, как долгота и широта в градусах.
 +
 +</div><div slide>
 +
 +==== Пример карты построенной в cartopy ====
 +
 +{{:calc:cartopy_2.png?400|}}
 +
 +</div><div slide>
 +
 +==== Картографические данные Natural Earth  ====
 +
 +Картографические данные ''cartopy'' берет из проекта [[https://www.naturalearthdata.com/|Natural Earth]].
 +
 +<sxh python>
 +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)
 +</sxh>
 +
 +Какие именно картографические данные доступны см. по ссылке [[https://github.com/nvkelso/natural-earth-vector]] в наборах ''cultural'' и ''physical''. Карты автоматически скачиваются по мере надобности, при этом в консоль выводится предупреждение ''DownloadWarning''.
 +
 +</div><div slide>
 +
 +==== Пример карты построенной в cartopy ====
 +
 +{{:calc:cartopy_3.png?400|}}
 +
 +</div><div slide>
 +
 +==== Использование Tile-серверов в cartopy ====
 +
 +<sxh python>
 +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()
 +</sxh>
 +
 +</div><div slide>
 +
 +==== Пример карты построенной в cartopy ====
 +
 +{{:calc:cartopy_4.png?400|}}
 +
 +</div><div slide>
 +
 +==== Некоторые приемы работы с cartopy ====
 +
 +<sxh python>
 +
 +# Скрытие части подписей по осям:
 +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)
 +
 +</sxh>
 +
 +</div><div slide>
 +
 +==== Построение карт из NetCDF файлов ====
 +
 +{{ :calc:yanao_era5_1959-2020.nc | Пример NetCDF файла}}
 +
 +<sxh python>
 +
 +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())
 +
 +</sxh>
 +
 +</div>