- 积分
- 915
- 贡献
-
- 精华
- 在线时间
- 小时
- 注册时间
- 2012-4-24
- 最后登录
- 1970-1-1
|
登录后查看更多精彩内容~
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
from datetime import datetime
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.pyplot as plt
import metpy.calc as mpcalc
from metpy.units import units
import numpy as np
from scipy.ndimage import gaussian_filter
import xarray as xr
from netCDF4 import Dataset
import os
import matplotlib.pyplot as plt
import numpy as np
from copy import copy
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.mpl.gridliner import LATITUDE_FORMATTER, LONGITUDE_FORMATTER
import shapely.geometry as sgeom
import xarray as xr
import gc
#给画刻度用来辅助,确定四周
def find_side(ls, side):
"""
Given a shapely LineString which is assumed to be rectangular, return the
line corresponding to a given side of the rectangle.
"""
minx, miny, maxx, maxy = ls.bounds
points = {'left': [(minx, miny), (minx, maxy)],
'right': [(maxx, miny), (maxx, maxy)],
'bottom': [(minx, miny), (maxx, miny)],
'top': [(minx, maxy), (maxx, maxy)],}
return sgeom.LineString(points[side])
#用来画坐标轴的刻度(包括经度和纬度)
def _lambert_ticks(ax, ticks, tick_location, line_constructor, tick_extractor):
"""得到一个兰伯特正形投影的轴的刻度位置和标签."""
outline_patch = sgeom.LineString(ax.outline_patch.get_path().vertices.tolist())
axis = find_side(outline_patch, tick_location)
n_steps = 30
extent = ax.get_extent(ccrs.PlateCarree())
_ticks = []
for t in ticks:
xy = line_constructor(t, n_steps, extent)
proj_xyz = ax.projection.transform_points(ccrs.Geodetic(), xy[:, 0], xy[:, 1])
xyt = proj_xyz[..., :2]
ls = sgeom.LineString(xyt.tolist())
locs = axis.intersection(ls)
if not locs:
tick = [None]
else:
tick = tick_extractor(locs.xy)
_ticks.append(tick[0])
# Remove ticks that aren't visible:
ticklabels = copy(ticks)
while True:
try:
index = _ticks.index(None)
except ValueError:
break
_ticks.pop(index)
ticklabels.pop(index)
return _ticks, ticklabels
#设置x轴标签(用来画纬度)
def lambert_xticks(ax, ticks):
"""Draw ticks on the bottom x-axis of a Lambert Conformal projection."""
te = lambda xy: xy[0]
lc = lambda t, n, b: np.vstack((np.zeros(n) + t, np.linspace(b[2], b[3], n))).T
xticks, xticklabels = _lambert_ticks(ax, ticks, 'bottom', lc, te)
ax.xaxis.tick_bottom()
ax.set_xticks(xticks)
ax.set_xticklabels([ax.xaxis.get_major_formatter()(xtick) for xtick in xticklabels])
#设置y轴标签(用来画经度)
def lambert_yticks(ax, ticks):
"""Draw ricks on the left y-axis of a Lamber Conformal projection."""
te = lambda xy: xy[1]
lc = lambda t, n, b: np.vstack((np.linspace(b[0], b[1], n), np.zeros(n) + t)).T
yticks, yticklabels = _lambert_ticks(ax, ticks, 'left', lc, te)
ax.yaxis.tick_left()
ax.set_yticks(yticks)
ax.set_yticklabels([ax.yaxis.get_major_formatter()(ytick) for ytick in yticklabels])
#################################以上为绘制地图########################
def huanliu(file,levs,windmin,path):
for file1 in file:
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
print(file1)
ds = xr.open_dataset(file1)
lats = ds.latitude.data
lons = ds.longitude.data
# 选取并抓取数据
hght = ds['z']
uwnd = ds['u']
vwnd = ds['v']
hght_500 = gaussian_filter(hght.sel(level=levs).data[0], sigma=3.0)
uwnd_500 = gaussian_filter(uwnd.sel(level=levs).data[0], sigma=3.0) * units('m/s')
vwnd_500 = gaussian_filter(vwnd.sel(level=levs).data[0], sigma=3.0) * units('m/s')
# 使用MetPy计算填色图的风速,将单位从m / s更改为节
sped_500 = mpcalc.wind_speed(uwnd_500, vwnd_500).to('kt')
# 创建一个干净的datetime对象以根据地势高度的时间进行绘图
vtime = datetime.strptime(str(ds.time.data[0].astype('datetime64[ms]')),'%Y-%m-%dT%H:%M:%S.%f')
# 设置将用于绘图的投影
mapcrs = ccrs.LambertConformal(central_longitude=70,central_latitude=40)
# 设置数据投影; 如果是经/纬度,那么PlateCarree是您想要的
datacrs = ccrs.PlateCarree()
# 启动图形并使用正确的投影创建绘图轴
fig = plt.figure(1, figsize=(12, 10),dpi=150)
ax = plt.subplot(111, projection=mapcrs)
#ax = fig.add_axes([0.08, 0.05, 0.8, 0.94], projection=ccrs.LambertConformal(central_latitude=45, central_longitude=80))
ax.set_extent([40, 100, 20, 55],crs=ccrs.PlateCarree())
fig.canvas.draw()
#设置刻度值,画经纬网格
xticks = [40,45,50,55,60, 65,70, 75,80, 85,90, 95, 100]
yticks = [15,20,25,30 , 35 , 40 , 45 , 50]
ax.gridlines(xlocs=xticks, ylocs=yticks,linestyle='--',lw=1,color='dimgrey')
ax.tick_params(labelsize=12)
# 设置经纬网格的端点(也是用来配合画刻度的,注释掉以后刻度不能正常显示了)
ax.xaxis.set_major_formatter(LONGITUDE_FORMATTER)
ax.yaxis.set_major_formatter(LATITUDE_FORMATTER)
#画经纬度刻度
lambert_xticks(ax, xticks)
lambert_yticks(ax, yticks)
with open(r'D:\MeteoInfo_3.2.2\FY4\CN-border-La.dat') as src:
context = src.read()
blocks = [cnt for cnt in context.split('>') if len(cnt) > 0]
borders = [np.fromstring(block, dtype=float, sep=' ') for block in blocks]
for line in borders:
ax.plot(line[0::2], line[1::2], '-', lw=1.5, color='k',
transform=ccrs.Geodetic())
# 添加地缘边界以供地图参考
ax.add_feature(cfeature.COASTLINE.with_scale('50m'))
ax.add_feature(cfeature.STATES.with_scale('50m'))
# 以节为单位绘制500-hPa填色
clevs_500_sped = np.arange(windmin,windmin+30,4 )
cbar_ax = fig.add_axes([0.9, 0.2, 0.02, 0.6])
cf = ax.contourf(lons, lats, sped_500/2, clevs_500_sped, cmap=plt.cm.BuPu,transform=datacrs)
#cb=plt.colorbar(cf, orientation='vertical', pad=0.0, aspect=30)
#cb.set_label('Abs. Vorticity ($s^{-1}$)')
plt.colorbar(cf,label="速度·m/s", cax=cbar_ax,ticks=clevs_500_sped)
# 以米为单位绘制500-hPa地势高度
clevs_500_hght = np.arange(500, 800, 4)
cs = ax.contour(lons, lats, hght_500/100., clevs_500_hght,linewidths=1.5, colors='black',transform=datacrs)
plt.clabel(cs, fmt='%d',inline=1,fontsize = 14)
# 以节为单位绘制500-hPa的风羽图,以减少风羽的数量
ax.barbs(lons, lats, uwnd_500.to('kt').m, vwnd_500.to('kt').m, pivot='middle',color='black', regrid_shape=20, transform=datacrs)
# 为该图制作一些漂亮的标题(一右一左)
#plt.title('500-hPa NAM Geopotential Heights (m), Wind Speed (kt), and Wind Barbs (kt)', loc='left')
#plt.title('Valid Time: {}'.format(vtime), loc='right')
# 调整图像并展示
plt.subplots_adjust(bottom=0, top=1)
timss=datetime.strftime(vtime,'%Y-%m-%d%H')
fig.savefig("{}\\{}.png".format(path,timss))#快速预览图
fig.savefig("{}\\{}.svg".format(path,timss))#高清矢量图
plt.clf()
ax.cla()
del fig,ax
def get_files_path_list(path):
files = []
filesList = os.listdir(path)
for filename in filesList:
if os.path.splitext(filename)[1] == '.nc':
fileAbsPath = os.path.join(path,filename)
files.append(fileAbsPath)
return files
##################画图设置###########################
path = r'D:\MeteoInfo_3.2.2\era5\ERA5_netCDF'#era5资料存放路径
pathsave=r'D:\MeteoInfo_3.2.2\era5\tu'#图片保存地址
#获取文件的绝对路径列表
files_path = get_files_path_list(path)
huanliu(files_path,500,20,pathsave)#files_path文件名,500代表层次,20代表急流起始,pathsave图像保存路径
|
|