wps的domain转为shp矢量

wps的namelist制作、python出图和转矢量

简介

wps(WRF Preprocessing System)是中尺度数值天气预报系统WRF(Weather Research and Forecasting)的预处理系统。

wrf模型示意图

wps的安装地址在GitHub上:https://github.com/wrf-model/WPS

下载完成后,就可以进行WPS安装,教程请查看官网:https://www2.mmm.ucar.edu/wrf/OnLineTutorial/compilation_tutorial.php

在wps安装成功后,会得到三个编译软件分别为geogrid、ungrib和metgrid。分别的功能是:

  • geogrid处理下垫面数据;

  • ungrib是将不同格式的气象数据转为统一格式

  • metgrid会将气象数据统一"裁剪"下垫面数据的网格上。

这三个exe文件的控制参数都是由namelist.wps进行控制的。

我今天想介绍的主要内容为根据namelist.input反推domain的空间位置并导出shp矢量,其他东西只会简单介绍。

namelist参数含义

不要去看汉化后的博客,官网有详细解释的:https://www2.mmm.ucar.edu/wrf/users/namelist_best_prac_wps.html#io_form_geogrid

由于我们要根据namelist.wps反推domain的空间分布,由几个特别重要的的参数,官网没有详细解释,我这里做一下补充:

(1)每一个domain都是由格网组成的,每层的格网大小由dxdyparent_grid_ratio决定。

请注意,e_wee_sn代表的是格的端点数,它们如果为n,则对应的格子数目为n-1,如图所示(e_we不会只有3,只是距离):

(2)e_we和e_sn都是指在该层范围内分辨率下的格子数目,比如304就是d02每行拥有303个格子。


(3)i_parent_start是经度的指标,一般用X表示,数字代表的子域d02左下角和d01的左下角的x方向的水平方向格子数。特别需要注意,

i_parent_start所代表的格子数量是d01的,不是d02。

j_parent_start是纬度的指标,一般用Y标识,是垂直方向的格子数

domain坐标计算的原理

(1)d01层的平面坐标计算

ref_lon,ref_lat是d01的中心位置,此外,它还有个特殊的作用:在wps中所有网格都是在一个投影的平面坐标系中的,(ref_lon,ref_lat)代表了在平面坐标系下的原点(0,0)。如果我们以d01举例,求它的四个顶点的坐标,我们需要明确,在兰伯特投影下的平面坐标系单位是米,d01的格子横向长度为dx,d01的格子纵向长度为dy。现在我们就可以求出d01的四个顶点在投影的平面坐标系下的坐标。

(2)d02、d03层的平面坐标计算

上面一步,我们已经求得了d01的四个顶点的坐标值。

d02的坐标,我们需要根据d01的左下角的坐标求得。

由此,我们获得了d02的四个顶点在投影下的平面坐标。

在获得d02的左下角坐标之后,按照相同方法,我们可以获得d03的平面坐标。

自此,我们明白了wps的namelist.wps的平面坐标计算原理,开始写代码。计算坐标点的代码如下:

# 初始化网格域
def initialize_domains(e_we, e_sn, i_parent_start, j_parent_start, parent_id, parent_grid_ratio, dx, dy, ref_lat, ref_lon, truelat1, truelat2):domains = []# 坐标系详细信息# 兰伯特 坐标系信息proj_params = {'proj': 'lcc','lat_1': truelat1,'lat_2': truelat2,'lat_0': ref_lat,'lon_0': ref_lon,'x_0': 0,'y_0': 0,'datum': 'WGS84'}# 创建平面坐标系p_lcc = Proj(proj_params)# 计算d01的中心点平面坐标系的坐标x_center, y_center = p_lcc(ref_lon, ref_lat)print("x_center, y_center",x_center, y_center)for i in range(len(e_we)):if parent_id[i] == 1:# 针对d01if i == 0:parent_dx = dxparent_dy = dyparent_ref_lon = x_centerparent_ref_lat = y_centergrid_ratio = parent_grid_ratio[i]# 计算d01的左下角坐标d01_start_x = x_center - ((e_we[i] - 1) / 2) * parent_dxd01_start_y = y_center - ((e_sn[i] - 1) / 2) * parent_dy# 计算d01的平面坐标domains.append(compute_boundaries(parent_ref_lat, parent_ref_lon, e_we[i], e_sn[i], dx, dy, i_parent_start[i], j_parent_start[i], parent_dx, parent_dy, d01_start_y, d01_start_x, grid_ratio))# 针对d02else:parent_domain_idx = parent_id[i] - 1grid_ratio = parent_grid_ratio[i]parent_dx = dxparent_dy = dydx = dx / grid_ratiody = dy / grid_ratioparent_ref_lat = domains[parent_domain_idx][2]parent_ref_lon = domains[parent_domain_idx][0]# 计算d02的左下角坐标d02_start_x = domains[parent_domain_idx][0] + (i_parent_start[i] - 1) * parent_dxd02_start_y = domains[parent_domain_idx][2] + (j_parent_start[i] - 1) * parent_dy# 计算d02的经纬度domains.append(compute_boundaries(parent_ref_lat, parent_ref_lon, e_we[i], e_sn[i], dx, dy, i_parent_start[i], j_parent_start[i], parent_dx, parent_dy, d02_start_y, d02_start_x, grid_ratio))else:# 针对d03parent_domain_idx = parent_id[i] - 1grid_ratio = parent_grid_ratio[i]parent_dx = domains[parent_domain_idx][6]parent_dy = domains[parent_domain_idx][7]parent_ref_lat = domains[parent_domain_idx][2]parent_ref_lon = domains[parent_domain_idx][0]# 计算d03的左下角坐标d03_start_x = domains[parent_domain_idx][0] + (i_parent_start[i] - 1) * parent_dxd03_start_y = domains[parent_domain_idx][2] + (j_parent_start[i] - 1) * parent_dy# 计算d03的经纬度domains.append(compute_boundaries(parent_ref_lat, parent_ref_lon, e_we[i], e_sn[i], dx / grid_ratio, dy / grid_ratio, i_parent_start[i], j_parent_start[i], parent_dx, parent_dy, d03_start_y, d03_start_x, grid_ratio))return domains, proj_params# 计算网格的边界
def compute_boundaries(ref_lat, ref_lon, e_we, e_sn, dx, dy, i_start, j_start, parent_dx, parent_dy, d_start_y, d_start_x, grid_ratio):# 计算子网格的左下角坐标grid_start_lon = d_start_xgrid_start_lat = d_start_y# 计算右上角坐标grid_end_lon = grid_start_lon + (e_we - 1) * dxgrid_end_lat = grid_start_lat + (e_sn - 1) * dy# 各方向的坐标west = grid_start_lonsouth = grid_start_lateast = grid_end_lonnorth = grid_end_latgrid_center_lat = (south + north) / 2grid_center_lon = (west + east) / 2return west, east, south, north, grid_center_lat, grid_center_lon, dx, dy

python出图

# 绘制地图
def plot_map(domains, gdf_level1, gdf_level2, gdf_level3, truelat1, truelat2, stand_lon, proj_params):proj = ccrs.LambertConformal(central_longitude=stand_lon, standard_parallels=(truelat1, truelat2))fig, ax = plt.subplots(figsize=(10, 10), subplot_kw={'projection': proj})# 绘制shapefile背景gdf_level1.to_crs(proj).plot(ax=ax, edgecolor='blue', facecolor='none', linewidth=1)  # 蓝色边框,空心gdf_level2.to_crs(proj).plot(ax=ax, edgecolor='red', facecolor='none', linewidth=1)   # 红色边框,空心gdf_level3.to_crs(proj).plot(ax=ax, edgecolor='black', facecolor='#43A7EE', linewidth=1)  # 黑色边框,RGB(67,167,238)填充# 创建坐标系对象crs_wgs84 = CRS.from_epsg(4326)  # 使用 EPSG 代码 4326 表示 WGS84 地理坐标系crs_lcc = CRS(proj_params)transformer = Transformer.from_crs(crs_lcc, crs_wgs84, always_xy=True)# 绘制每个嵌套网格的范围for i, (west, east, south, north, _, _, _, _) in enumerate(domains):# 将网格边界转换为经纬度# 左下west_lon_ZUO, south_lat_ZUO = transformer.transform(west, south)# 左上west_lon_ZUO2, north_lat_ZUO2 = transformer.transform(west, north)# 右上east_lon_YOU2, north_lat_YOU2 = transformer.transform(east, north)# 右下east_lon_YOU, south_lat_YOU = transformer.transform(east, south)# 打印经纬度范围print(f"Domain {i+1} bounds (west, east, south, north):")print(f"Longitude: {west_lon_ZUO} to {east_lon_YOU2}")print(f"Latitude: {south_lat_ZUO} to {north_lat_ZUO2}")# 使用 Polygon 创建每个网格的多边形,按照逆时针顺序连接点vertices = [(west_lon_ZUO, south_lat_ZUO), (east_lon_YOU, south_lat_YOU), (east_lon_YOU2, north_lat_YOU2), (west_lon_ZUO2, north_lat_ZUO2)]polygon = Polygon(vertices)ax.add_geometries([polygon], crs=ccrs.PlateCarree(), edgecolor='red' if i == 0 else 'blue' if i == 1 else 'green', facecolor='none', linewidth=2, label=f'Domain {i+1}')# 计算标注的位置(使用多边形的右上角点)lon_label, lat_label = east_lon_YOU2, north_lat_YOU2# 添加标注,并调整标注的位置ax.text(lon_label, lat_label, f'd0{i+1}', color='red', fontsize=12, ha='right', va='top', transform=ccrs.PlateCarree())# 转换 d01 的边界坐标到地理坐标west_d01, south_d01 = transformer.transform(domains[0][0], domains[0][2])east_d01, north_d01 = transformer.transform(domains[0][1], domains[0][3])print("west_d01, south_d01, east_d01, north_d01", west_d01, south_d01, east_d01, north_d01)# 设置显示范围,在经度和纬度方向上各自添加边距lon_margin = (east_d01 - west_d01) * 0.1  # 经度方向上的边距为d01经度范围的10%lat_margin = (north_d01 - south_d01) * 0.1  # 纬度方向上的边距为d01纬度范围的10%ax.set_extent([west_d01 - lon_margin, east_d01 + lon_margin, south_d01 - lat_margin, north_d01 + lat_margin], crs=ccrs.PlateCarree())# 添加海岸线和网格线ax.gridlines(draw_labels=True)plt.title('WRF Domains')plt.show()

我们加入研究区的矢量如下,出图效果如下:

namelist转矢量shp

既然我们已经知道d01到d03的坐标点,按照逆时针把矢量点串联起来,获得shp矢量。

# 输出d01到d03范围为shp
def output_domains_to_shapefile(domains, proj_params, output_shapefile_path):# 创建一个空的 GeoDataFrame,用于存储域的范围gdf_domains = gpd.GeoDataFrame(columns=['geometry', 'domain_id'], crs="EPSG:4326")# 创建坐标系对象crs_wgs84 = CRS.from_epsg(4326)  # 使用 EPSG 代码 4326 表示 WGS84 地理坐标系crs_lcc = CRS(proj_params)transformer = Transformer.from_crs(crs_lcc, crs_wgs84, always_xy=True)# 绘制每个嵌套网格的范围并添加到 GeoDataFramefor i, (west, east, south, north, _, _, _, _) in enumerate(domains):# 将网格边界转换为经纬度# 左下west_lon_ZUO, south_lat_ZUO = transformer.transform(west, south)# 左上west_lon_ZUO2, north_lat_ZUO2 = transformer.transform(west, north)# 右上east_lon_YOU2, north_lat_YOU2 = transformer.transform(east, north)# 右下east_lon_YOU, south_lat_YOU = transformer.transform(east, south)# 使用 Polygon 创建每个网格的多边形,按照逆时针顺序连接点vertices = [(west_lon_ZUO, south_lat_ZUO), (east_lon_YOU, south_lat_YOU), (east_lon_YOU2, north_lat_YOU2), (west_lon_ZUO2, north_lat_ZUO2)]polygon = Polygon(vertices)# 创建一个临时的 GeoDataFrametemp_gdf = gpd.GeoDataFrame([{'geometry': polygon, 'domain_id': f'Domain {i+1}'}], crs="EPSG:4326")# 使用 pd.concat 将临时的 GeoDataFrame 添加到主要的 GeoDataFrame 中gdf_domains = pd.concat([gdf_domains, temp_gdf], ignore_index=True)# 保存为 shapefilegdf_domains.to_file(output_shapefile_path, driver='ESRI Shapefile')

特别注意,我们需要最后生成的shp是wgs84坐标系,所以需要把平面坐标转回为wgs84坐标系。

完整代码

import re
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import geopandas as gpd
import pandas as pd
from shapely.geometry import Polygon
from pyproj import Proj,transform
from pyproj import CRS, Transformer# 提取单个参数的函数
def get_param(pattern, content, index=0):match = re.search(pattern, content)if match:return float(match.group(1))else:raise ValueError(f'Parameter {pattern} not found in namelist.wps')# 提取多个参数的函数
def get_params(pattern, content):match = re.search(pattern, content)if match:return [int(x) for x in match.group(1).split(',')]else:raise ValueError(f'Parameter {pattern} not found in namelist.wps')# 读取并解析namelist.wps文件
def parse_namelist(namelist_path):with open(namelist_path, 'r') as file:namelist_content = file.read()dx = get_param(r'dx\s*=\s*(\d+)', namelist_content)dy = get_param(r'dy\s*=\s*(\d+)', namelist_content)ref_lat = get_param(r'ref_lat\s*=\s*([-+]?\d*\.\d+|\d+)', namelist_content)ref_lon = get_param(r'ref_lon\s*=\s*([-+]?\d*\.\d+|\d+)', namelist_content)e_we = get_params(r'e_we\s*=\s*([\d,\s]+)', namelist_content)e_sn = get_params(r'e_sn\s*=\s*([\d,\s]+)', namelist_content)i_parent_start = get_params(r'i_parent_start\s*=\s*([\d,\s]+)', namelist_content)j_parent_start = get_params(r'j_parent_start\s*=\s*([\d,\s]+)', namelist_content)parent_id = get_params(r'parent_id\s*=\s*([\d,\s]+)', namelist_content)parent_grid_ratio = get_params(r'parent_grid_ratio\s*=\s*([\d,\s]+)', namelist_content)truelat1 = get_param(r'truelat1\s*=\s*([-+]?\d*\.\d+|\d+)', namelist_content)truelat2 = get_param(r'truelat2\s*=\s*([-+]?\d*\.\d+|\d+)', namelist_content)stand_lon = get_param(r'stand_lon\s*=\s*([-+]?\d*\.\d+|\d+)', namelist_content)return dx, dy, ref_lat, ref_lon, e_we, e_sn, i_parent_start, j_parent_start, parent_id, parent_grid_ratio, truelat1, truelat2, stand_lon# 初始化网格域
def initialize_domains(e_we, e_sn, i_parent_start, j_parent_start, parent_id, parent_grid_ratio, dx, dy, ref_lat, ref_lon, truelat1, truelat2):domains = []# 坐标系详细信息# 兰伯特 坐标系信息proj_params = {'proj': 'lcc','lat_1': truelat1,'lat_2': truelat2,'lat_0': ref_lat,'lon_0': ref_lon,'x_0': 0,'y_0': 0,'datum': 'WGS84'}# 创建平面坐标系p_lcc = Proj(proj_params)# 计算d01的中心点平面坐标系的坐标x_center, y_center = p_lcc(ref_lon, ref_lat)print("x_center, y_center",x_center, y_center)for i in range(len(e_we)):if parent_id[i] == 1:# 针对d01if i == 0:parent_dx = dxparent_dy = dyparent_ref_lon = x_centerparent_ref_lat = y_centergrid_ratio = parent_grid_ratio[i]# 计算d01的左下角坐标d01_start_x = x_center - ((e_we[i] - 1) / 2) * parent_dxd01_start_y = y_center - ((e_sn[i] - 1) / 2) * parent_dy# 计算d01的平面坐标domains.append(compute_boundaries(parent_ref_lat, parent_ref_lon, e_we[i], e_sn[i], dx, dy, i_parent_start[i], j_parent_start[i], parent_dx, parent_dy, d01_start_y, d01_start_x, grid_ratio))# 针对d02else:parent_domain_idx = parent_id[i] - 1grid_ratio = parent_grid_ratio[i]parent_dx = dxparent_dy = dydx = dx / grid_ratiody = dy / grid_ratioparent_ref_lat = domains[parent_domain_idx][2]parent_ref_lon = domains[parent_domain_idx][0]# 计算d02的左下角坐标d02_start_x = domains[parent_domain_idx][0] + (i_parent_start[i] - 1) * parent_dxd02_start_y = domains[parent_domain_idx][2] + (j_parent_start[i] - 1) * parent_dy# 计算d02的经纬度domains.append(compute_boundaries(parent_ref_lat, parent_ref_lon, e_we[i], e_sn[i], dx, dy, i_parent_start[i], j_parent_start[i], parent_dx, parent_dy, d02_start_y, d02_start_x, grid_ratio))else:# 针对d03parent_domain_idx = parent_id[i] - 1grid_ratio = parent_grid_ratio[i]parent_dx = domains[parent_domain_idx][6]parent_dy = domains[parent_domain_idx][7]parent_ref_lat = domains[parent_domain_idx][2]parent_ref_lon = domains[parent_domain_idx][0]# 计算d03的左下角坐标d03_start_x = domains[parent_domain_idx][0] + (i_parent_start[i] - 1) * parent_dxd03_start_y = domains[parent_domain_idx][2] + (j_parent_start[i] - 1) * parent_dy# 计算d03的经纬度domains.append(compute_boundaries(parent_ref_lat, parent_ref_lon, e_we[i], e_sn[i], dx / grid_ratio, dy / grid_ratio, i_parent_start[i], j_parent_start[i], parent_dx, parent_dy, d03_start_y, d03_start_x, grid_ratio))return domains, proj_params# 计算网格的边界
def compute_boundaries(ref_lat, ref_lon, e_we, e_sn, dx, dy, i_start, j_start, parent_dx, parent_dy, d_start_y, d_start_x, grid_ratio):# 计算子网格的左下角坐标grid_start_lon = d_start_xgrid_start_lat = d_start_y# 计算右上角坐标grid_end_lon = grid_start_lon + (e_we - 1) * dxgrid_end_lat = grid_start_lat + (e_sn - 1) * dy# 各方向的坐标west = grid_start_lonsouth = grid_start_lateast = grid_end_lonnorth = grid_end_latgrid_center_lat = (south + north) / 2grid_center_lon = (west + east) / 2return west, east, south, north, grid_center_lat, grid_center_lon, dx, dy# 绘制地图
def plot_map(domains, gdf_level1, gdf_level2, gdf_level3, truelat1, truelat2, stand_lon, proj_params):proj = ccrs.LambertConformal(central_longitude=stand_lon, standard_parallels=(truelat1, truelat2))fig, ax = plt.subplots(figsize=(10, 10), subplot_kw={'projection': proj})# 绘制shapefile背景gdf_level1.to_crs(proj).plot(ax=ax, edgecolor='blue', facecolor='none', linewidth=1)  # 蓝色边框,空心gdf_level2.to_crs(proj).plot(ax=ax, edgecolor='red', facecolor='none', linewidth=1)   # 红色边框,空心gdf_level3.to_crs(proj).plot(ax=ax, edgecolor='black', facecolor='#43A7EE', linewidth=1)  # 黑色边框,RGB(67,167,238)填充# 创建坐标系对象crs_wgs84 = CRS.from_epsg(4326)  # 使用 EPSG 代码 4326 表示 WGS84 地理坐标系crs_lcc = CRS(proj_params)transformer = Transformer.from_crs(crs_lcc, crs_wgs84, always_xy=True)# 绘制每个嵌套网格的范围for i, (west, east, south, north, _, _, _, _) in enumerate(domains):# 将网格边界转换为经纬度# 左下west_lon_ZUO, south_lat_ZUO = transformer.transform(west, south)# 左上west_lon_ZUO2, north_lat_ZUO2 = transformer.transform(west, north)# 右上east_lon_YOU2, north_lat_YOU2 = transformer.transform(east, north)# 右下east_lon_YOU, south_lat_YOU = transformer.transform(east, south)# 打印经纬度范围print(f"Domain {i+1} bounds (west, east, south, north):")print(f"Longitude: {west_lon_ZUO} to {east_lon_YOU2}")print(f"Latitude: {south_lat_ZUO} to {north_lat_ZUO2}")# 使用 Polygon 创建每个网格的多边形,按照逆时针顺序连接点vertices = [(west_lon_ZUO, south_lat_ZUO), (east_lon_YOU, south_lat_YOU), (east_lon_YOU2, north_lat_YOU2), (west_lon_ZUO2, north_lat_ZUO2)]polygon = Polygon(vertices)ax.add_geometries([polygon], crs=ccrs.PlateCarree(), edgecolor='red' if i == 0 else 'blue' if i == 1 else 'green', facecolor='none', linewidth=2, label=f'Domain {i+1}')# 计算标注的位置(使用多边形的右上角点)lon_label, lat_label = east_lon_YOU2, north_lat_YOU2# 添加标注,并调整标注的位置ax.text(lon_label, lat_label, f'd0{i+1}', color='red', fontsize=12, ha='right', va='top', transform=ccrs.PlateCarree())# 转换 d01 的边界坐标到地理坐标west_d01, south_d01 = transformer.transform(domains[0][0], domains[0][2])east_d01, north_d01 = transformer.transform(domains[0][1], domains[0][3])print("west_d01, south_d01, east_d01, north_d01", west_d01, south_d01, east_d01, north_d01)# 设置显示范围,在经度和纬度方向上各自添加边距lon_margin = (east_d01 - west_d01) * 0.1  # 经度方向上的边距为d01经度范围的10%lat_margin = (north_d01 - south_d01) * 0.1  # 纬度方向上的边距为d01纬度范围的10%ax.set_extent([west_d01 - lon_margin, east_d01 + lon_margin, south_d01 - lat_margin, north_d01 + lat_margin], crs=ccrs.PlateCarree())# 添加海岸线和网格线ax.gridlines(draw_labels=True)plt.title('WRF Domains')plt.show()# 输出d01到d03范围为shp
def output_domains_to_shapefile(domains, proj_params, output_shapefile_path):# 创建一个空的 GeoDataFrame,用于存储域的范围gdf_domains = gpd.GeoDataFrame(columns=['geometry', 'domain_id'], crs="EPSG:4326")# 创建坐标系对象crs_wgs84 = CRS.from_epsg(4326)  # 使用 EPSG 代码 4326 表示 WGS84 地理坐标系crs_lcc = CRS(proj_params)transformer = Transformer.from_crs(crs_lcc, crs_wgs84, always_xy=True)# 绘制每个嵌套网格的范围并添加到 GeoDataFramefor i, (west, east, south, north, _, _, _, _) in enumerate(domains):# 将网格边界转换为经纬度# 左下west_lon_ZUO, south_lat_ZUO = transformer.transform(west, south)# 左上west_lon_ZUO2, north_lat_ZUO2 = transformer.transform(west, north)# 右上east_lon_YOU2, north_lat_YOU2 = transformer.transform(east, north)# 右下east_lon_YOU, south_lat_YOU = transformer.transform(east, south)# 使用 Polygon 创建每个网格的多边形,按照逆时针顺序连接点vertices = [(west_lon_ZUO, south_lat_ZUO), (east_lon_YOU, south_lat_YOU), (east_lon_YOU2, north_lat_YOU2), (west_lon_ZUO2, north_lat_ZUO2)]polygon = Polygon(vertices)# 创建一个临时的 GeoDataFrametemp_gdf = gpd.GeoDataFrame([{'geometry': polygon, 'domain_id': f'Domain {i+1}'}], crs="EPSG:4326")# 使用 pd.concat 将临时的 GeoDataFrame 添加到主要的 GeoDataFrame 中gdf_domains = pd.concat([gdf_domains, temp_gdf], ignore_index=True)# 保存为 shapefilegdf_domains.to_file(output_shapefile_path, driver='ESRI Shapefile')def main():# 读取namelist.wps文件read_path = r"E:\ruiduobao\namelis设置\namelist.wps"dx, dy, ref_lat, ref_lon, e_we, e_sn, i_parent_start, j_parent_start, parent_id, parent_grid_ratio, truelat1, truelat2, stand_lon = parse_namelist(read_path)# 初始化网格域domains, proj_params = initialize_domains(e_we, e_sn, i_parent_start, j_parent_start, parent_id, parent_grid_ratio, dx, dy, ref_lat, ref_lon, truelat1, truelat2)# 读取shapefileshapefile_path_level1 = r'E:\ruiduobao\数据和代码\行政区划\jiangsu.shp'shapefile_path_level2 = r'E:\ruiduobao\数据和代码\行政区划\xuzhou.shp'shapefile_path_level3 = r'E:\ruiduobao\数据和代码\行政区划\xuzhouxian.shp'# 加载shapefile到 GeoDataFramegdf_level1 = gpd.read_file(shapefile_path_level1)gdf_level2 = gpd.read_file(shapefile_path_level2)gdf_level3 = gpd.read_file(shapefile_path_level3)# 绘制地图plot_map(domains, gdf_level1, gdf_level2, gdf_level3, truelat1, truelat2, stand_lon, proj_params)# 输出d01到d03范围为shpoutput_shapefile_path = r'E:\ruiduobao\行政区划\wrf_domains_平面.shp'output_domains_to_shapefile(domains, proj_params, output_shapefile_path)if __name__ == '__main__':main()

最后,我们把生成的namelist.wps的矢量放到GIS软件中,就可以任意编辑了:

总结

这个代码看起来很简单,但我实际上搞了快两天才弄懂里面的原理,尴尬,故写一篇技术博客方便以后自己查阅。我主要遇到以下问题:

(1)一开始我是用wgs84的经纬度去计算的各个domain的空间位置的,但实际上会有偏移,因为每度随着纬度的不同是会变化的,需要放到平面坐标系中才会有正确的结果。

(2)我刚开始是计算每一个domain的中心点,但实际上这是比较傻的方法,因为i_parent_start等是从左下角开始计数的。

参考

https://github.com/wrf-model/WPS

https://www2.mmm.ucar.edu/wrf/OnLineTutorial/compilation_tutorial.php

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/362105.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一步步带你解锁Stable Diffusion:老外都眼馋的 SD 中文提示词插件分享

大家好我是极客菌!今天我们继续来分享一个外国人都眼馋的 SD 中文提示词插件。 那我们废话不多说,直接开整。 SD 的插件安装,小伙伴们应该都会了吧,我这里再简单讲下哦,到「扩展」中的「可下载」中点击「加载扩展列表…

分布式锁实现方案-基于Redis实现的分布式锁

目录 一、基于Lua看门狗实现 1.1 缓存实体 1.2 延迟队列存储实体 1.3 分布式锁RedisDistributedLockWithDog 1.4 看门狗线程续期 1.5 测试类 1.6 测试结果 1.7 总结 二、RedLock分布式锁 2.1 Redlock分布式锁简介 2.2 RedLock测试例子 2.3 RedLock 加锁核心源码分析…

560. 和为 K 的子数组

题目描述 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 解题 简单直接, 但时间复杂度最高 O(n3) class Solution {func subarraySum(_ nums: [Int], _ k: Int) -> Int {var t…

华三中小企业组网

一、组网需求 在中小园区中,S5130系列或S5130S系列以太网交换机通常部署在网络的接入层,S5560X系列或 S6520X系列以太网交换机通常部署在网络的核心,出口路由器一般选用MSR系列路由器。 核心交换机配置VRRP保证网络可靠性。园区网中不同的…

哪些AI生图软件值得推荐,有需要的建议收藏!

人工智能(AI)已经渗透到我们生活的方方面面,AI生图软件就是其中的一种,它们能够帮助我们快速生成高质量的图片,无论是社交媒体的配图,还是设计作品的素材,都能够得到极大的帮助。那么哪些AI生图软件值得推荐呢? 首先&…

自定义APT插件导致IDEA调试时StreamTrace(跟踪当前流链)报internal error(内部错误)

IDEA里面debug的时候,针对stream流提供了流追踪调试功能,方便大家调试stream流代码。 最近改其他人代码,需要用到这个,发现提示内部错误。 然后百度一圈发现没啥解决方案,就自己看IDEA的日志,看看是什么引…

Centos安装redis(附:图形化管理工具)

第一步:下载redis wget http://download.redis.io/releases/redis-6.2.7.tar.gz 第二步:解压 tar zxvf redis-6.2.7.tar.gz 第三步:安装依赖环境 yum -y install gcc-c第四步:安装依赖环境 make install第五步:修…

基于matlab的K-means聚类图像分割

1 原理 K-means聚类算法在图像分割中的应用是基于一种无监督的学习方法,它将图像中的像素点或特征区域划分为K个不同的簇或类别。以下是K-means聚类算法用于图像分割的原理,包括步骤和公式: 1.1 原理概述 选择簇的数量(K): 首先…

如何科学减肥先从了解自己在到饮食运动

在这个以瘦为美的时代,许多人被肥胖所困扰着, 今天就来教大家如何科学减脂。 一、如何判断自己是否需要减脂? 第一步就是判断自己的体重指数(BMI)是否在正常标准。BMI是国际上衡量人体胖瘦程度及是否健康的一个常用指…

定位问题6.27 petal数据接口问题

petal接口响应结果 响应结果为空的数据,而我们需要的是正确的响应结果。 排查问题 确认接口是否正确 以下是爬虫的配置文件内容,我查看了PETAL_URL的接口,并询问接口开发人员,得知接口地址并未改变 确认接口请求体是否正确 我使…

开源“卖货主播”AI大模型——拳打李佳琦、脚踢小杨哥、人人都能当销冠?

开源“卖货主播”AI大模型——拳打李佳琦、脚踢小杨哥、人人都能当销冠? 刚刚在知名同性交友平台发现了一个或许能让你致富的开源项目——“Streamer-Sales 销冠”。 正如其名字所言,这是一个卖货主播LLM大模型,旨在让你成为销冠。 https:/…

d3dx9_42.dll找不到怎么正确处理?教学级修复d3dx9_42.dll的方法分享

d3dx9_42.dll找不到?别着急,这只是普普通通的dll文件找不到而已,它可能因为各种原因而导致丢失,我们只要直接对d3dx9_42.dll进行修复就可以了。下面我们一起来了解一下d3dx9_42.dll找不到的正确处理方法。 一.d3dx9_42.dll找不到是…

微信公众号写作时必备的AI提示词(也称为指令或Prompt)

猫头虎 🐯 微信公众号写作时必备的AI提示词(也称为指令或Prompt) 🎉 大家好,我是猫头虎,科技自媒体博主。今天,我们来聊聊如何利用AI提示词,打造出爆款的微信公众号文章。&#x1…

OnlyOffice:为现代工作方式而生的办公套件

ONLYOFFICE官网链接:https://www.onlyoffice.com/zh/office-suite.aspx https://www.onlyoffice.com/zh/pdf-editor.aspx OnlyOffice 是一款开源的办公套件,它提供了一系列的办公工具,包括文档编辑器、表格编辑器和演示文稿编辑器。这些工具…

靶机渗透之DC-7

一、信息收集 扫描网段,发现靶机ip为192.168.145.235。 nmap -sP 192.168.145.* 进一步对端口,靶机系统等信息进行一个收集。可以看到开放了22端口,80端口,主机系统为linux等信息。 nmap -sT -T4 -O -sV -sC -p1-65535 192.16…

零知识证明基础:对称加密与非对称加密

1、绪论 在密码学体系中,对称加密、非对称加密、单向散列函数、消息认证码、数字签名和伪随机数生成器被统称为密码学家的工具箱。其中,对称加密和非对称加密主要是用来保证机密性;单向散列函数用来保证消息的完整性;消息认证码的…

工具篇:鸿蒙DevEco Studio5.0版本下载及安装

1、下载中心地址 下载中心 | 华为开发者联盟-HarmonyOS开发者官网,共建鸿蒙生态 2、安装 DevEco Studio支持Windows和macOS系统,下面将针对两种操作系统的软件安装方式分别进行介绍。 Windows环境 运行环境要求 为保证DevEco Studio正常运行&#…

人工智能AI风口已开:如何赋予UI设计与视频剪辑新生命

随着科技的浪潮不断向前推进,人工智能(AI)正以惊人的速度重塑着我们的世界,特别是在创意产业的核心领域——UI设计与视频剪辑中,AI正逐步成为驱动行业创新与变革的关键力量。在这个AI技术全面开花的新时代,…

将产品制作成3D模型在网站上展示需要多少费用?

将产品制作成3D模型并在网站上展示的费用会因多种因素而异,包括模型的复杂度、所需的细节程度、制作3D模型的软件和工具、以及是否需要专业设计师的服务等。此外,不同的3D模型制作服务提供商可能会有不同的定价标准。 如果能自己制作3D模型,…

高性能并行计算华为云实验三:蒙特卡罗算法实验

目录 一、实验目的 二、实验说明 三、实验过程 3.1 创建蒙特卡罗算法源码 3.2 Makefile的创建与编译 3.3 主机文件配置与运行监测​​​​​​​ 四、实验结果与分析 4.1 原教程对应的实验结果 4.2 改进后的实验结果 五、实验思考与总结 5.1 实验思考 5.2 实验总结…