Вопрос или проблема
Я хочу отобразить переменную LU_INDEX в WRF с помощью pcolormesh и добавить береговые линии из shapefile в pcolormesh. Моя координатная система WRF — LambertConformal, а shapefile — WGS84. Я думаю, что проблемы возникли из-за несоответствия двух наборов данных. Как я могу отредактировать свой код и получить четкую фигуру?
Данные проекции карты WRF
map_proj = 'lambert',
ref_lat = 35.50,
ref_lon = 125.00,
truelat1 = 30.0,
truelat2 = 60.0,
stand_lon = 125.0,
from netCDF4 import Dataset
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import numpy as np
from wrf import (to_np, getvar, get_cartopy, latlon_coords,smooth2d)
from cartopy.feature import NaturalEarthFeature
from cartopy.feature import ShapelyFeature
from cartopy.io.shapereader import Reader
from matplotlib.backends.backend_pdf import PdfPages
from matplotlib.colors import ListedColormap, BoundaryNorm
import matplotlib
matplotlib.use('Agg')
# Установка пути к shapefile
shp_path = "/home/chwan/data/shp/241002/gadm41_KOR_1.shp"
base_path = "/home/chwan/UCM/WPS-4.3.1/"
pdf_pages = PdfPages(f"{base_path.split('https://stackoverflow.com/')[-2]}_LU_INDEX_contour.pdf")
dates = [19]
timeidx = 0
colors = [
"white", # 0
"navy", # 1
"grey", # 2
"olivedrab", # 3
"orange", # 4
"yellow", # 5
"green", # 6
"lime", # 7
"limegreen", # 8
"white",# 9
"tan", # 10
"forestgreen", # 11
"white", # 12
"white",# 13
"darkgreen", # 14
"olive", # 15
"skyblue", # 16
"deepskyblue", # 17
"seagreen", # 18
"white", # 19
"white", # 20
"white", # 21
"white", # 22
"chocolate", # 23
"white", # 24
"white", # 25
"white", # 26
"white", # 27
"white", # 28
"white", # 29
"white", # 30
"white", # 31
"white", # 32
"maroon" # 33
]
colorlist = [colors[i] if i < len(colors) else "white" for i in range(34)]
non_white_colors = [color for color in colors if color != "white"]
non_white_indices = [i for i, color in enumerate(colors) if color != "white"]
cmap = ListedColormap(non_white_colors)
norm = BoundaryNorm(np.arange(0,len(colors)+1)-0.5,len(colors))
norm = BoundaryNorm(non_white_indices + [max(non_white_indices)+1],cmap.N)
globe = ccrs.Globe(ellipse="sphere", semimajor_axis=6370000,semiminor_axis=6370000)
for day in dates:
filename = f"{base_path}geo_em.d03.nc"
ncfile = Dataset(filename, "r")
lu = getvar(ncfile, "LU_INDEX")
cart_proj = get_cartopy(lu)
lats, lons = latlon_coords(lu)
print(cart_proj)
print(lats)
fig = plt.figure(figsize=(10, 10))
ax = plt.axes(projection=ccrs.LambertConformal(globe=globe,central_longitude=125.0,central_latitude=35.5,standard_parallels=(30,60)))
#ax.set_extent([125.5, 127.5, 34, 35.5])
lat_mask = (to_np(lats) >= 34) & (to_np(lats) <= 35.5)
lon_mask = (to_np(lons) >= 125.5) & (to_np(lons) <= 127.5)
mask = lat_mask & lon_mask
lu_np = to_np(lu)
shpfile = Reader(shp_path)
shapefile_feature = ShapelyFeature(shpfile.geometries(),
ccrs.LambertConformal(globe=globe,central_longitude=125.0,central_latitude=35.5,standard_parallels=(30,60)),
edgecolor="black", facecolor="none", linewidth=1)
ax.add_feature(shapefile_feature) # Добавление shapefile
# Добавление государственных границ
#states = NaturalEarthFeature(category="cultural", scale="10m", name="admin_0_countries",
# facecolor="none", edgecolor="black")
#ax.add_feature(states, linewidth=1, edgecolor="black")
def get_edges(arr):
edges = (arr[:-1] + arr[1:]) / 2.0
return np.concatenate([[arr[0] - (edges[0] - arr[0])], edges, [arr[-1] + (arr[-1] - edges[-1])]])
# Вычисление границ долгот и широт
lon_edges = get_edges(to_np(lons)[0, :])
lat_edges = get_edges(to_np(lats)[:, 0])
mesh = ax.pcolormesh(lon_edges, lat_edges, to_np(lu), transform = ccrs.LambertConformal(globe=globe,central_longitude=125.0,central_latitude=35.5,standard_parallels=(30,60)),cmap=cmap,norm = norm, shading = 'auto', edgecolors="face")
# Добавление цветовой шкалы
cbar = plt.colorbar(mesh, orientation='vertical', shrink=1, pad=0.075, aspect=15)
cbar.ax.tick_params(labelsize=11)
cbar.set_label("ЗЕМЕЛЬНОЕ ИСПОЛЬЗОВАНИЕ", labelpad=15, rotation=270, ha="center", va="center")
# Сохранение в PDF
pdf_pages.savefig(fig)
plt.close(fig)
pdf_pages.close()
Ответ или решение
Чтобы объединить выходные данные WRF с шейпфайлом в Python, вам нужно убедиться, что оба используемых проекционных пространства соответствуют друг другу. В данном случае у вас есть выходные данные WRF в проекции Lambert Conformal и шейпфайл в системе координат WGS84. Мы можем использовать библиотеку Cartopy для работы с картами и визуализации данных. Давайте разберем вашу задачу шаг за шагом и исправим код, чтобы обеспечить правильное наложение данных.
Шаги по объединению данных
-
Конверсия координат: Вам нужно убедиться, что проекция шейпфайла соответствует проекции данных WRF. Для этого используем Cartopy для преобразования координат WGS84 в Lambert Conformal.
-
Наложение данных: После преобразования координат шейпфайла вы сможете отобразить его на том же графике, что и выходные данные WRF.
Вот исправленный код с учетом ваших требований:
from netCDF4 import Dataset
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import numpy as np
from wrf import (to_np, getvar, get_cartopy, latlon_coords)
from cartopy.feature import ShapelyFeature
from cartopy.io.shapereader import Reader
from matplotlib.backends.backend_pdf import PdfPages
from matplotlib.colors import ListedColormap, BoundaryNorm
import matplotlib
# Настройки для использования PDF
matplotlib.use('Agg')
pdf_pages = PdfPages("output_LU_INDEX_contour.pdf")
# Путь к shapefile
shp_path = "/home/chwan/data/shp/241002/gadm41_KOR_1.shp"
base_path = "/home/chwan/UCM/WPS-4.3.1/"
dates = [19]
colors = [...] # Укажите свой массив цветов
cmap = ListedColormap([colors[i] for i in range(len(colors)) if colors[i] != "white"])
norm = BoundaryNorm(np.arange(0, len(colors) + 1) - 0.5, len(colors))
globe = ccrs.Globe(ellipse="sphere", semimajor_axis=6370000, semiminor_axis=6370000)
for day in dates:
filename = f"{base_path}geo_em.d03.nc"
ncfile = Dataset(filename, "r")
lu = getvar(ncfile, "LU_INDEX")
cart_proj = get_cartopy(lu)
lats, lons = latlon_coords(lu)
fig = plt.figure(figsize=(10, 10))
ax = plt.axes(projection=ccrs.LambertConformal(central_longitude=125.0, central_latitude=35.5, standard_parallels=(30, 60)))
lu_np = to_np(lu)
# Наложение пектограммы
mesh = ax.pcolormesh(to_np(lons), to_np(lats), lu_np, transform=cart_proj, cmap=cmap, norm=norm, shading='auto')
# Чтение шейпфайла и преобразование координат
shpfile = Reader(shp_path)
shapefile_feature = ShapelyFeature(shpfile.geometries(),
ccrs.LambertConformal(central_longitude=125.0, central_latitude=35.5, standard_parallels=(30, 60)),
edgecolor="black", facecolor="none", linewidth=1)
ax.add_feature(shapefile_feature)
# Добавление цветового бара
cbar = plt.colorbar(mesh, ax=ax, orientation='vertical', shrink=0.8, pad=0.05)
cbar.set_label("LANDUSE", rotation=270, labelpad=20)
# Сохранение в PDF
pdf_pages.savefig(fig)
plt.close(fig)
pdf_pages.close()
Примечания:
-
Преобразование координат: Мы использовали
ShapelyFeature
в Cartopy для того, чтобы добавить шейпфайл в соответствующей проекции Lambert Conformal. Это помогает корректно наложить геометрические данные на карту. -
Ошибки в индексации: Убедитесь, что индексы для
lu_np
,lats
, иlons
соответствуют друг другу. Проверьте, что при наложении данных вы используете непосредственно численные значения, а не переменные, содержащие данные в проекции изображения. -
Убедитесь в параметрах цвета: Параметры цвета в коде могут быть адаптированы в соответствии с вашими требованиями. Я указал массив
colors
как комментарий, так как он должен быть определен вами заранее. -
Просмотр результата: Проверьте полученный PDF-файл для визуализации. При необходимости настраивайте размеры, пропорции и другие элементы графиков для достижения наилучшего результата.
Следуя данным шагам и рекомендациям, вы сможете успешно совместить результаты WRF с данными из шейпфайлов, получая четкие и корректно отображенные графики.