def draw_Crosssection_Wind_Theta_e_div( cross_div3d=None, cross_Theta_e=None, cross_u=None, cross_v=None,cross_terrain=None, gh=None, h_pos=None,st_point=None,ed_point=None, levels=None,map_extent=(50, 150, 0, 65),lw_ratio=None, output_dir=None): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) initTime = pd.to_datetime( str(cross_Theta_e['forecast_reference_time'].values)).replace(tzinfo=None).to_pydatetime() fcst_time=initTime+timedelta(hours=gh['forecast_period'].values[0]) fig = plt.figure(1, figsize=(lw_ratio[0], lw_ratio[1])) ax = plt.axes() absv_contour = ax.contourf(cross_div3d['lon'], cross_div3d['level'], cross_div3d['data']*1e6, levels=range(-100, 100, 1), cmap=dk_ctables2.ncl_cmaps('GMT_haxby'),extend='both') absv_colorbar = fig.colorbar(absv_contour) # Plot potential temperature using contour, with some custom labeling Theta_e_contour = ax.contour(cross_Theta_e['lon'], cross_Theta_e['level'],cross_Theta_e.values, levels=np.arange(250, 450, 5), colors='k', linewidths=2) Theta_e_contour.clabel(np.arange(250, 450, 5), fontsize=20, colors='k', inline=1, inline_spacing=8, fmt='%i', rightside_up=True, use_clabeltext=True) wind_slc_vert = list(range(0, len(levels), 1)) wind_slc_horz = slice(5, 100, 5) ax.barbs(cross_u['lon'][wind_slc_horz], cross_u['level'][wind_slc_vert], cross_u['t_wind'][wind_slc_vert, wind_slc_horz]*2.5, cross_v['n_wind'][wind_slc_vert, wind_slc_horz]*2.5, color='k') startcolor = '#8B4513' #棕色 endcolor='#DAC2AD' #绿 cmap2 = col.LinearSegmentedColormap.from_list('own3',[endcolor,startcolor]) # extra arguments are N=256, gamma=1.0 cm.register_cmap(cmap=cmap2) terrain_contour = ax.contourf(cross_terrain['lon'], cross_terrain['level'], cross_terrain.values, levels=np.arange(0, 500, 1), cmap=cm.get_cmap('own3'),zorder=100) # Adjust the y-axis to be logarithmic ax.set_yscale('symlog') ax.set_yticklabels(np.arange(levels[0], levels[-1], -100)) ax.set_ylim(levels[0], levels[-1]) ax.set_yticks(np.arange(levels[0], levels[-1], -100)) # Define the CRS and inset axes data_crs = ccrs.PlateCarree() ax_inset = fig.add_axes(h_pos, projection=data_crs) ax_inset.set_extent(map_extent, crs=data_crs) # Plot geopotential height at 500 hPa using xarray's contour wrapper ax_inset.contour(gh['lon'], gh['lat'], np.squeeze(gh['data']), levels=np.arange(500, 600, 4), cmap='inferno') # Plot the path of the cross section endpoints = data_crs.transform_points(ccrs.Geodetic(), *np.vstack([st_point, ed_point]).transpose()[::-1]) ax_inset.scatter(endpoints[:, 0], endpoints[:, 1], c='k', zorder=2) ax_inset.plot(cross_u['lon'], cross_u['lat'], c='k', zorder=2) # Add geographic features ax_inset.coastlines() utl.add_china_map_2cartopy_public( ax_inset, name='province', edgecolor='black', lw=0.8, zorder=105) # Set the titles and axes labels ax_inset.set_title('') ax.set_title('相当位温, 水平散度, 沿剖面风', loc='right', fontsize=20) ax.set_ylabel('Pressure (hPa)') ax.set_xlabel('Longitude') absv_colorbar.set_label('水平散度 (dimensionless)') if(sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if(sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') bax=fig.add_axes([0.10,0.88,.25,.07],facecolor='#FFFFFFCC') bax.axis('off') #bax.set_yticks([]) #bax.set_xticks([]) bax.axis([0, 10, 0, 10]) plt.text(2.5, 7.5,'起报时间: '+initTime.strftime("%Y年%m月%d日%H时"),size=11) plt.text(2.5, 5,'预报时间: '+fcst_time.strftime("%Y年%m月%d日%H时"),size=11) plt.text(2.5, 2.5,'预报时效: '+str(int(gh['forecast_period'].values[0]))+'小时',size=11) plt.text(2.5, 0.5,'www.nmc.cn',size=11) utl.add_logo_extra_in_axes(pos=[0.1,0.88,.07,.07],which='nmc', size='Xlarge') # show figure if(output_dir != None): plt.savefig(output_dir+'相当位温_水平散度_沿剖面风_预报_'+ '起报时间_'+initTime.strftime("%Y年%m月%d日%H时")+ '预报时效_'+str(int(gh['forecast_period'].values[0]))+'小时'+'.png', dpi=200,bbox_inches='tight') plt.close() if(output_dir == None): plt.show()
def draw_isentropic_uv(isentrh=None, isentuv=None, isentprs=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True,city=False,south_China_sea=True, output_dir=None,Global=False): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # draw figure plt.figure(figsize=(16,9)) # set data projection if(Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea(central_latitude=(map_extent[2]+map_extent[3])/2., central_longitude=(map_extent[0]+map_extent[1])/2., standard_parallels=[30., 60.]) ax = plt.axes([0.01,0.1,.98,.84], projection=plotcrs) plt.title('['+isentrh['model']+'] '+ isentrh['lev']+'等熵面 风场 相对湿度 气压', loc='left', fontsize=30) datacrs = ccrs.PlateCarree() #adapt to the map ratio map_extent2=utl.adjust_map_ratio(ax,map_extent=map_extent,datacrs=datacrs) #adapt to the map ratio ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public( ax, name='coastline', edgecolor='gray', lw=0.8, zorder=105,alpha=0.5) if add_china: utl.add_china_map_2cartopy_public( ax, name='province', edgecolor='gray', lw=0.5, zorder=105) utl.add_china_map_2cartopy_public( ax, name='nation', edgecolor='black', lw=0.8, zorder=105) utl.add_china_map_2cartopy_public( ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=105,alpha=0.5) # define return plots plots = {} # draw mean sea level pressure if isentrh is not None: x, y = np.meshgrid(isentrh['lon'], isentrh['lat']) z=np.squeeze(isentrh['data']) clevs_rh= range(10, 106, 5) plots['isentrh'] = ax.contourf( x, y, z,clevs_rh,cmap=plt.cm.gist_earth_r, transform=datacrs,alpha=0.5,extend='both') # draw -hPa wind bards if isentuv is not None: x, y = np.meshgrid(isentuv['lon'], isentuv['lat']) u = np.squeeze(isentuv['isentu']) * 2.5 v = np.squeeze(isentuv['isentv']) * 2.5 plots['uv'] = ax.barbs( x, y, u, v, length=6, regrid_shape=regrid_shape, transform=datacrs, fill_empty=False, sizes=dict(emptybarb=0.05), zorder=20) # draw -hPa geopotential height if isentprs is not None: x, y = np.meshgrid(isentprs['lon'], isentprs['lat']) clevs_isentprs = np.arange(0, 1000, 25) z=gaussian_filter(np.squeeze(isentprs['data']),5) plots['isentprs'] = ax.contour( x, y, z , clevs_isentprs, colors='black', linewidths=2, transform=datacrs, zorder=30) plt.clabel(plots['isentprs'], inline=1, fontsize=20, fmt='%.0f',colors='black') # grid lines gl = ax.gridlines( crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=40) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) #http://earthpy.org/cartopy_backgroung.html #C:\ProgramData\Anaconda3\Lib\site-packages\cartopy\data\raster\natural_earth ax.background_img(name='RD', resolution='high') #forecast information bax=plt.axes([0.01,0.835,.25,.1],facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initTime = pd.to_datetime( str(isentrh['init_time'])).replace(tzinfo=None).to_pydatetime() fcst_time=initTime+timedelta(hours=isentrh['fhour']) #发布时间 if(sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if(sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5,'起报时间: '+initTime.strftime("%Y年%m月%d日%H时"),size=15) plt.text(2.5, 5,'预报时间: '+fcst_time.strftime("%Y年%m月%d日%H时"),size=15) plt.text(2.5, 2.5,'预报时效: '+str(isentrh['fhour'])+'小时',size=15) plt.text(2.5, 0.5,'www.nmc.cn',size=15) # add color bar if(isentrh != None): cax=plt.axes([0.11,0.06,.86,.02]) cb = plt.colorbar(plots['isentrh'], cax=cax, orientation='horizontal', ticks=clevs_rh[:], extend='both',extendrect=False) cb.ax.tick_params(labelsize='x-large') cb.set_label('Relative Humidity (%)',size=20) # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[0.85,0.13,.1,.2]) small_city=False if(map_extent2[1]-map_extent2[0] < 25): small_city=True if city: utl.add_city_on_map(ax,map_extent=map_extent2,transform=datacrs,zorder=110,size=13,small_city=small_city) utl.add_logo_extra_in_axes(pos=[-0.01,0.835,.1,.1],which='nmc', size='Xlarge') # show figure if(output_dir != None): plt.savefig(output_dir+isentrh['lev']+'等熵面分析_相对湿度_风场_气压_预报_'+ '起报时间_'+initTime.strftime("%Y年%m月%d日%H时")+ '预报时效_'+str(isentrh['fhour'])+'小时'+'.png', dpi=200) if(output_dir == None): plt.show()
def Horizontal_Pallete(figsize=(16, 9), plotcrs=ccrs.PlateCarree(), datacrs=ccrs.PlateCarree(), map_extent=(60, 145, 15, 55), title='', forcast_info='', add_china=True, add_city=False, add_background=True, south_China_sea=True, info_zorder=10, title_fontsize=30): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') fig = plt.figure(figsize=figsize) if (plotcrs is None): plotcrs = ccrs.AlbersEqualArea( central_latitude=(map_extent[2] + map_extent[3]) / 2., central_longitude=(map_extent[0] + map_extent[1]) / 2., standard_parallels=[30., 60.]) ax = plt.axes([0.01, 0.1, .98, .84], projection=plotcrs) #ax.set_extent(map_extent, crs=crs) map_extent = adjust_map_ratio(ax, map_extent=map_extent, datacrs=datacrs) plt.title(title, loc='left', fontsize=title_fontsize) # add grid lines gl = ax.gridlines(crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=info_zorder) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) if add_china: utl.add_china_map_2cartopy_public(ax, name='coastline', edgecolor='gray', lw=0.8, zorder=info_zorder, alpha=0.5) utl.add_china_map_2cartopy_public(ax, name='province', edgecolor='gray', lw=0.5, zorder=info_zorder) utl.add_china_map_2cartopy_public(ax, name='nation', edgecolor='black', lw=0.8, zorder=info_zorder) utl.add_china_map_2cartopy_public(ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=info_zorder, alpha=0.5) if add_city: small_city = False if (map_extent[1] - map_extent[0] < 25): small_city = True utl.add_city_on_map(ax, map_extent=map_extent, size=12, transform=datacrs, zorder=info_zorder + 1, small_city=small_city) if add_background: ax.add_feature(cfeature.OCEAN) utl.add_cartopy_background(ax, name='RD') if south_China_sea: l, b, w, h = ax.get_position().bounds utl.add_south_China_sea(pos=[l + w - 0.0875, b, .1, .2]) if forcast_info: l, b, w, h = ax.get_position().bounds bax = plt.axes([l, b + h - 0.1, .25, .1], facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) bax.text( 2.2, 9.8, forcast_info, size=15, va='top', ha='left', ) l, b, w, h = ax.get_position().bounds utl.add_logo_extra_in_axes(pos=[l - 0.022, b + h - 0.1, .1, .1], which='nmc', size='Xlarge') return fig, ax, map_extent
def draw_gh_rain(gh=None, rain=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True,city=True,south_China_sea=True, output_dir=None,Global=False): # set font plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # set figure plt.figure(figsize=(16,9)) if(Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea(central_latitude=(map_extent[2]+map_extent[3])/2., central_longitude=(map_extent[0]+map_extent[1])/2., standard_parallels=[30., 60.]) datacrs = ccrs.PlateCarree() ax = plt.axes([0.01,0.1,.98,.84], projection=plotcrs) map_extent2=utl.adjust_map_ratio(ax,map_extent=map_extent,datacrs=datacrs) # define return plots plots = {} # draw mean sea level pressure if rain is not None: x, y = np.meshgrid(rain['lon'], rain['lat']) z=np.squeeze(rain['data'].values) z[z<0.1]=np.nan cmap,norm=dk_ctables.cm_qpf_nws(atime=rain.attrs['atime']) cmap.set_under(color=[0,0,0,0],alpha=0.0) plots['rain'] = ax.pcolormesh( x,y,z, norm=norm, cmap=cmap, zorder=1,transform=datacrs,alpha=0.5) # draw -hPa geopotential height if gh is not None: x, y = np.meshgrid(gh['lon'], gh['lat']) clevs_gh = np.append(np.append(np.arange(0, 480, 4),np.append(np.arange(480, 584, 8), np.arange(580, 604, 4))), np.arange(604, 2000, 8)) plots['gh'] = ax.contour( x, y, np.squeeze(gh['data']), clevs_gh, colors='black', linewidths=2, transform=datacrs, zorder=3) plt.clabel(plots['gh'], inline=2, fontsize=20, fmt='%.0f',colors='black') #additional information plt.title('['+gh.attrs['model']+'] '+ str(int(gh['level'].values[0]))+'hPa 位势高度场, '+ str(int(rain.attrs['atime']))+'小时降水', loc='left', fontsize=30) ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public( ax, name='coastline', edgecolor='gray', lw=0.8, zorder=3,alpha=0.5) if add_china: utl.add_china_map_2cartopy_public( ax, name='province', edgecolor='gray', lw=0.5, zorder=3) utl.add_china_map_2cartopy_public( ax, name='nation', edgecolor='black', lw=0.8, zorder=3) utl.add_china_map_2cartopy_public( ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=3,alpha=0.5) # grid lines gl = ax.gridlines( crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=1) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) utl.add_cartopy_background(ax,name='RD') l, b, w, h = ax.get_position().bounds #forecast information bax=plt.axes([l,b+h-0.1,.25,.1],facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initTime = pd.to_datetime( str(gh.coords['forecast_reference_time'].values)).replace(tzinfo=None).to_pydatetime() fcst_time=initTime+timedelta(hours=gh.coords['forecast_period'].values[0]) #发布时间 if(sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if(sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5,'起报时间: '+initTime.strftime("%Y年%m月%d日%H时"),size=15) plt.text(2.5, 5,'预报时间: '+fcst_time.strftime("%Y年%m月%d日%H时"),size=15) plt.text(2.5, 2.5,'预报时效: '+str(int(gh.coords['forecast_period'].values[0]))+'小时'+'(降水'+str(int(gh.coords['forecast_period'].values[0]+12))+'小时)',size=15) plt.text(2.5, 0.5,'www.nmc.cn',size=15) # add color bar if(rain != None): cax=plt.axes([l,b-0.04,w,.02]) cb = plt.colorbar(plots['rain'], cax=cax, orientation='horizontal') cb.ax.tick_params(labelsize='x-large') cb.set_label(str(int(rain.attrs['atime']))+'h precipitation (mm)',size=20) # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[l+w-0.091,b,.1,.2]) small_city=False if(map_extent2[1]-map_extent2[0] < 25): small_city=True if city: utl.add_city_on_map(ax,map_extent=map_extent2,transform=datacrs,zorder=2,size=13,small_city=small_city) utl.add_logo_extra_in_axes(pos=[l-0.02,b+h-0.1,.1,.1],which='nmc', size='Xlarge') # show figure if(output_dir != None): plt.savefig(output_dir+'高度场_降水_预报_'+ '起报时间_'+initTime.strftime("%Y年%m月%d日%H时")+ '预报时效_'+str(int(gh.coords['forecast_period'].values[0]))+'小时'+'.png', dpi=200) if(output_dir == None): plt.show()
def draw_cumulated_precip_evo( rain=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True,city=True,south_China_sea=True, output_dir=None,Global=False): # set font plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # set figure fig = plt.figure(figsize=(16,9)) plotcrs = ccrs.AlbersEqualArea(central_latitude=(map_extent[2]+map_extent[3])/2., central_longitude=(map_extent[0]+map_extent[1])/2., standard_parallels=[30., 60.]) datacrs = ccrs.PlateCarree() ax = plt.axes([0.01,0.1,.98,.84], projection=plotcrs) map_extent2=utl.adjust_map_ratio(ax,map_extent=map_extent,datacrs=datacrs) # define return plots plots = {} # draw mean sea level pressure if rain is not None: x, y = np.meshgrid(rain['lon'], rain['lat']) z=np.squeeze(rain['data'].values) z[z<0.1]=np.nan znan=np.zeros(shape=x.shape) znan[:]=np.nan cmap,norm=dk_ctables.cm_qpf_nws(atime=24) cmap.set_under(color=[0,0,0,0],alpha=0.0) plots['rain'] = ax.pcolormesh( x,y,znan, norm=norm, cmap=cmap, zorder=1,transform=datacrs,alpha=0.5) #additional information plt.title('['+rain.attrs['model']+'] '+ str(int(rain.coords['forecast_period'].values[0])-rain.attrs['t_gap'])+ '至'+str(int(rain.coords['forecast_period'].values[-1]))+'时效累积降水预报', loc='left', fontsize=25) ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public( ax, name='coastline', edgecolor='gray', lw=0.8, zorder=3,alpha=0.5) if add_china: utl.add_china_map_2cartopy_public( ax, name='province', edgecolor='gray', lw=0.5, zorder=3) utl.add_china_map_2cartopy_public( ax, name='nation', edgecolor='black', lw=0.8, zorder=3) utl.add_china_map_2cartopy_public( ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=3,alpha=0.5) # grid lines gl = ax.gridlines( crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=1) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) utl.add_cartopy_background(ax,name='RD') l, b, w, h = ax.get_position().bounds #forecast information initTime = pd.to_datetime( str(rain.coords['forecast_reference_time'].values)).replace(tzinfo=None).to_pydatetime() #发布时间 if(sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if(sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') # add color bar cax=plt.axes([l,b-0.04,w,.02]) cb = plt.colorbar(plots['rain'], cax=cax, orientation='horizontal') cb.ax.tick_params(labelsize='x-large') cb.set_label('Precipitation (mm)',size=20) fcst_time=initTime+timedelta(hours=rain.coords['forecast_period'].values[0]) bax=plt.axes([l,b+h-0.1,.25,.1]) bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) fcst_time1=initTime+timedelta(hours=rain.coords['forecast_period'].values[0]-6) bax.text(2.5, 7.5,'起始时间: '+fcst_time1.strftime("%Y年%m月%d日%H时"),size=15) bax.text(2.5, 0.5,'www.nmc.cn',size=15) valid_fhour=bax.text(2.5, 5,'截至时间: ',size=15) txt_fhour=bax.text(2.5, 2.5,'预报时效: ',size=15) utl.add_logo_extra_in_axes(pos=[l-0.02,b+h-0.1,.1,.1],which='nmc', size='Xlarge') # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[l+w-0.091,b,.1,.2]) small_city=False if(map_extent2[1]-map_extent2[0] < 25): small_city=True if city: utl.add_city_on_map(ax,map_extent=map_extent2,transform=datacrs,zorder=2,size=13,small_city=small_city) def update(frame_number): fcst_time2=initTime+timedelta(hours=rain.coords['forecast_period'].values[frame_number]) valid_fhour.set_text('截至时间: '+fcst_time2.strftime("%Y年%m月%d日%H时")) txt_fhour.set_text('预报时效: '+str(int(rain.coords['forecast_period'].values[frame_number]))+'小时') return ax.pcolormesh( x,y,np.squeeze(z[frame_number,:,:]), norm=norm, cmap=cmap, zorder=1,transform=datacrs,alpha=0.5) nframes=rain['data'].shape[0] animation1 = FuncAnimation(fig, update, frames=nframes,interval=1000) # ffmpegpath = os.path.abspath(r"C:\Users\HEYGY\Desktop\ffmpeg-20200824-3477feb-win64-static\bin\ffmpeg.exe") # import matplotlib # matplotlib.rcParams["animation.ffmpeg_path"] = ffmpegpath # writer = animation.FFMpegWriter() # show figure plt.subplots_adjust(top=1, bottom=0, right=0.93, left=0, hspace=0, wspace=0) plt.margins(0, 0) if(output_dir != None): animation1.save(output_dir+'累积降水演变_'+ '起报时间_'+initTime.strftime("%Y年%m月%d日%H时")+ '预报时效_'+str(int(rain.coords['forecast_period'].values[-1]))+'小时_'+ '['+rain.attrs['model']+'] '+'.gif',writer='pillow') if(output_dir == None): #animation.save('rain.gif', fps=75, writer='imagemagick') plt.show()
def draw_Crosssection_Wind_Temp_RH(cross_rh=None, cross_Temp=None, cross_u=None, cross_v=None, cross_terrain=None, gh=None, h_pos=None, st_point=None, ed_point=None, levels=None, map_extent=(50, 150, 0, 65), model=None, output_dir=None): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) initial_time = pd.to_datetime( str(cross_Temp['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() fcst_time = initial_time + timedelta(hours=gh['forecast_period'].values[0]) fig = plt.figure(1, figsize=(16., 9.)) ax = plt.axes() cross_rh['data'].values[cross_rh['data'].values > 100] = 100 # example 2: use the "fromList() method startcolor = '#1E90FF' #蓝色 midcolor = '#F1F1F1' #白色 endcolor = '#696969' #灰色 cmap2 = col.LinearSegmentedColormap.from_list( 'own2', [startcolor, midcolor, endcolor]) # extra arguments are N=256, gamma=1.0 cm.register_cmap(cmap=cmap2) # we can skip name here as it was already defined rh_contour = ax.contourf(cross_rh['lon'], cross_rh['level'], cross_rh['data'], levels=np.arange(0, 101, 0.5), cmap=cm.get_cmap('own2')) rh_colorbar = fig.colorbar(rh_contour, ticks=[20, 40, 60, 80, 100]) # Plot potential temperature using contour, with some custom labeling Temp_contour = ax.contour(cross_Temp['lon'], cross_Temp['level'], cross_Temp['data'].values, levels=np.arange(-100, 100, 2), colors='#A0522D', linewidths=1) Temp_contour.clabel(np.arange(-100, 100, 2), fontsize=16, colors='#A0522D', inline=1, inline_spacing=8, fmt='%i', rightside_up=True, use_clabeltext=True) Temp_zero_contour = ax.contour(cross_Temp['lon'], cross_Temp['level'], cross_Temp['data'].values, levels=[0], colors='k', linewidths=3) Temp_zero_contour.clabel([0], fontsize=22, colors='k', inline=1, inline_spacing=8, fmt='%i', rightside_up=True, use_clabeltext=True) wind_slc_vert = list(range(0, len(levels), 1)) wind_slc_horz = slice(5, 100, 5) ax.barbs(cross_u['lon'][wind_slc_horz], cross_u['level'][wind_slc_vert], cross_u['t_wind'][wind_slc_vert, wind_slc_horz] * 2.5, cross_v['n_wind'][wind_slc_vert, wind_slc_horz] * 2.5, color='k') startcolor = '#8B4513' #棕色 endcolor = '#DAC2AD' #绿 cmap2 = col.LinearSegmentedColormap.from_list('own3', [endcolor, startcolor]) # extra arguments are N=256, gamma=1.0 cm.register_cmap(cmap=cmap2) terrain_contour = ax.contourf(cross_terrain['lon'], cross_terrain['level'], cross_terrain.values, levels=np.arange(0, 200, 1), cmap=cm.get_cmap('own3'), zorder=100) # Adjust the y-axis to be logarithmic ax.set_yscale('symlog') ax.set_yticklabels(np.arange(levels[0], levels[-1], -100)) ax.set_ylim(levels[0], levels[-1]) ax.set_yticks(np.arange(levels[0], levels[-1], -100)) # Define the CRS and inset axes data_crs = ccrs.PlateCarree() ax_inset = fig.add_axes(h_pos, projection=data_crs) ax_inset.set_extent(map_extent, crs=data_crs) # Plot geopotential height at 500 hPa using xarray's contour wrapper ax_inset.contour(gh['lon'], gh['lat'], np.squeeze(gh['data']), levels=np.arange(500, 600, 4), cmap='inferno') # Plot the path of the cross section endpoints = data_crs.transform_points( ccrs.Geodetic(), *np.vstack([st_point, ed_point]).transpose()[::-1]) ax_inset.scatter(endpoints[:, 0], endpoints[:, 1], c='k', zorder=2) ax_inset.plot(cross_u['lon'], cross_u['lat'], c='k', zorder=2) # Add geographic features ax_inset.coastlines() utl.add_china_map_2cartopy_public(ax_inset, name='province', edgecolor='black', lw=0.8, zorder=105) # Set the titles and axes labels ax_inset.set_title('') ax.set_title('[' + model + '] ' + '温度, 相对湿度, 水平风场', loc='right', fontsize=25) ax.set_ylabel('Pressure (hPa)') ax.set_xlabel('Longitude') rh_colorbar.set_label('Relative Humidity (%)') if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') bax = fig.add_axes([0.10, 0.88, .25, .07], facecolor='#FFFFFFCC') bax.axis('off') #bax.set_yticks([]) #bax.set_xticks([]) bax.axis([0, 10, 0, 10]) plt.text(2.5, 7.5, '起报时间: ' + initial_time.strftime("%Y年%m月%d日%H时"), size=11) plt.text(2.5, 5, '预报时间: ' + fcst_time.strftime("%Y年%m月%d日%H时"), size=11) plt.text(2.5, 2.5, '预报时效: ' + str(int(gh['forecast_period'].values[0])) + '小时', size=11) plt.text(2.5, 0.5, 'www.nmc.cn', size=11) utl.add_logo_extra_in_axes(pos=[0.1, 0.88, .07, .07], which='nmc', size='Xlarge') # show figure if (output_dir != None): plt.savefig(output_dir + '温度_相对湿度_水平风场_预报_' + '起报时间_' + initial_time.strftime("%Y年%m月%d日%H时") + '预报时效_' + str(int(gh['forecast_period'].values[0])) + '小时' + '.png', dpi=200) if (output_dir == None): plt.show()
def draw_gh_uv_mslp(gh=None, uv=None, mslp=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True, city=True, south_China_sea=True, output_dir=None, Global=False): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # draw figure plt.figure(figsize=(16, 9)) # set data projection if (Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea( central_latitude=(map_extent[2] + map_extent[3]) / 2., central_longitude=(map_extent[0] + map_extent[1]) / 2., standard_parallels=[30., 60.]) ax = plt.axes([0.01, 0.1, .98, .84], projection=plotcrs) plt.title('[' + gh.attrs['model'] + '] ' + str(int(gh['level'].values[0])) + 'hPa 位势高度场, ' + str(int(uv['level'].values[0])) + 'hPa 风场, 海平面气压场', loc='left', fontsize=30) datacrs = ccrs.PlateCarree() #adapt to the map ratio map_extent2 = utl.adjust_map_ratio(ax, map_extent=map_extent, datacrs=datacrs) #adapt to the map ratio ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public(ax, name='coastline', edgecolor='gray', lw=0.8, zorder=5, alpha=0.5) if add_china: utl.add_china_map_2cartopy_public(ax, name='province', edgecolor='gray', lw=0.5, zorder=5) utl.add_china_map_2cartopy_public(ax, name='nation', edgecolor='black', lw=0.8, zorder=5) utl.add_china_map_2cartopy_public(ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=5, alpha=0.5) # define return plots plots = {} # draw mean sea level pressure if mslp is not None: x, y = np.meshgrid(mslp['lon'], mslp['lat']) clevs_mslp = np.arange(960, 1065, 5) cmap = guide_cmaps(26) plots['mslp'] = ax.contourf(x, y, np.squeeze(mslp['data']), clevs_mslp, cmap=cmap, alpha=0.8, zorder=1, transform=datacrs) #+画高低压中心 res = mslp['lon'].values[1] - mslp['lon'].values[0] nwindow = int(9.5 / res) mslp_hl = np.ma.masked_invalid(mslp['data'].values).squeeze() local_min, local_max = utl.extrema(mslp_hl, mode='wrap', window=nwindow) #Get location of extrema on grid xmin, xmax, ymin, ymax = map_extent2 lons2d, lats2d = x, y transformed = datacrs.transform_points(datacrs, lons2d, lats2d) x = transformed[..., 0] y = transformed[..., 1] xlows = x[local_min] xhighs = x[local_max] ylows = y[local_min] yhighs = y[local_max] lowvals = mslp_hl[local_min] highvals = mslp_hl[local_max] yoffset = 0.022 * (ymax - ymin) dmin = yoffset #Plot low pressures xyplotted = [] for x, y, p in zip(xlows, ylows, lowvals): if x < xmax - yoffset and x > xmin + yoffset and y < ymax - yoffset and y > ymin + yoffset: dist = [ np.sqrt((x - x0)**2 + (y - y0)**2) for x0, y0 in xyplotted ] if not dist or min(dist) > dmin: #,fontweight='bold' a = ax.text(x, y, 'L', fontsize=28, ha='center', va='center', color='r', fontweight='normal', transform=datacrs) b = ax.text(x, y - yoffset, repr(int(p)), fontsize=14, ha='center', va='top', color='r', fontweight='normal', transform=datacrs) a.set_path_effects([ path_effects.Stroke(linewidth=1.5, foreground='black'), path_effects.SimpleLineShadow(), path_effects.Normal() ]) b.set_path_effects([ path_effects.Stroke(linewidth=1.0, foreground='black'), path_effects.SimpleLineShadow(), path_effects.Normal() ]) xyplotted.append((x, y)) #Plot high pressures xyplotted = [] for x, y, p in zip(xhighs, yhighs, highvals): if x < xmax - yoffset and x > xmin + yoffset and y < ymax - yoffset and y > ymin + yoffset: dist = [ np.sqrt((x - x0)**2 + (y - y0)**2) for x0, y0 in xyplotted ] if not dist or min(dist) > dmin: a = ax.text(x, y, 'H', fontsize=28, ha='center', va='center', color='b', fontweight='normal', transform=datacrs) b = ax.text(x, y - yoffset, repr(int(p)), fontsize=14, ha='center', va='top', color='b', fontweight='normal', transform=datacrs) a.set_path_effects([ path_effects.Stroke(linewidth=1.5, foreground='black'), path_effects.SimpleLineShadow(), path_effects.Normal() ]) b.set_path_effects([ path_effects.Stroke(linewidth=1.0, foreground='black'), path_effects.SimpleLineShadow(), path_effects.Normal() ]) xyplotted.append((x, y)) #-画高低压中心 # draw -hPa wind bards if uv is not None: x, y = np.meshgrid(uv['lon'], uv['lat']) u = np.squeeze(uv['u']) * 2.5 v = np.squeeze(uv['v']) * 2.5 plots['uv'] = ax.barbs(x, y, u.values, v.values, length=6, regrid_shape=regrid_shape, transform=datacrs, fill_empty=False, sizes=dict(emptybarb=0.05), zorder=2) # draw -hPa geopotential height if gh is not None: x, y = np.meshgrid(gh['lon'], gh['lat']) clevs_gh = np.append( np.append( np.arange(0, 480, 4), np.append(np.arange(480, 584, 8), np.arange(580, 604, 4))), np.arange(604, 2000, 8)) linewidths_gh = np.zeros(clevs_gh.shape) + 2 idx_588 = np.where(clevs_gh == 588) linewidths_gh[idx_588[0]] = 4 plots['gh'] = ax.contour(x, y, np.squeeze(gh['data']), clevs_gh, colors='purple', linewidths=linewidths_gh, transform=datacrs, zorder=3) ax.clabel(plots['gh'], inline=1, fontsize=20, fmt='%.0f', colors='black') # grid lines gl = ax.gridlines(crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=4) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) utl.add_cartopy_background(ax, name='RD') #forecast information l, b, w, h = ax.get_position().bounds bax = plt.axes([l, b + h - 0.1, .25, .1], facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initTime = pd.to_datetime(str( gh.coords['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() fcst_time = initTime + timedelta( hours=gh.coords['forecast_period'].values[0]) #发布时间 if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5, '起报时间: ' + initTime.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 5, '预报时间: ' + fcst_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 2.5, '预报时效: ' + str(int(gh.coords['forecast_period'].values[0])) + '小时', size=15) plt.text(2.5, 0.5, 'www.nmc.cn', size=15) # add color bar cax = plt.axes([l, b - 0.04, w, .02]) cb = plt.colorbar(plots['mslp'], cax=cax, orientation='horizontal', ticks=clevs_mslp[:-1], extend='max', extendrect=False) cb.ax.tick_params(labelsize='x-large') cb.set_label('Mean sea level pressure (hPa)', size=20) # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[l + w - 0.091, b, .1, .2]) small_city = False if (map_extent2[1] - map_extent2[0] < 25): small_city = True if city: utl.add_city_on_map(ax, map_extent=map_extent2, transform=datacrs, zorder=6, size=15, small_city=small_city) utl.add_logo_extra_in_axes(pos=[l - 0.02, b + h - 0.1, .1, .1], which='nmc', size='Xlarge') # show figure if (output_dir != None): plt.savefig(output_dir + '最高温度_预报_' + '起报时间_' + initTime.strftime("%Y年%m月%d日%H时") + '预报时效_' + str(gh.coords['forecast_period'].values[0]) + '小时' + '.png', dpi=200, bbox_inches='tight') if (output_dir == None): plt.show()
def draw_sta_skewT(p=None, T=None, Td=None, wind_speed=None, wind_dir=None, u=None, v=None, fcst_info=None, output_dir=None): fig = plt.figure(figsize=(9, 9)) skew = SkewT(fig, rotation=45) plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # Plot the data using normal plotting functions, in this case using # log scaling in Y, as dictated by the typical meteorological plot. skew.plot(p, T, 'r') skew.plot(p, Td, 'g') skew.plot_barbs(p, u, v) skew.ax.set_ylim(1000, 100) skew.ax.set_xlim(-40, 60) # Calculate LCL height and plot as black dot. Because `p`'s first value is # ~1000 mb and its last value is ~250 mb, the `0` index is selected for # `p`, `T`, and `Td` to lift the parcel from the surface. If `p` was inverted, # i.e. start from low value, 250 mb, to a high value, 1000 mb, the `-1` index # should be selected. lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0]) skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black') # Calculate full parcel profile and add to plot as black line prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC') skew.plot(p, prof, 'k', linewidth=2) # Shade areas of CAPE and CIN skew.shade_cin(p, T, prof) skew.shade_cape(p, T, prof) # An example of a slanted line at constant T -- in this case the 0 # isotherm skew.ax.axvline(0, color='c', linestyle='--', linewidth=2) # Add the relevant special lines skew.plot_dry_adiabats() skew.plot_moist_adiabats() skew.plot_mixing_lines() #forecast information bax = plt.axes([0.12, 0.88, .25, .07], facecolor='#FFFFFFCC') bax.axis('off') bax.axis([0, 10, 0, 10]) initTime = pd.to_datetime(str( fcst_info['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5, '起报时间: ' + initTime.strftime("%Y年%m月%d日%H时"), size=11) plt.text(2.5, 5.0, '[' + str(fcst_info.attrs['model']) + '] ' + str(int(fcst_info['forecast_period'].values[0])) + '小时预报探空', size=11) plt.text(2.5, 2.5, '预报点: ' + str(fcst_info.attrs['points']['lon']) + ', ' + str(fcst_info.attrs['points']['lat']), size=11) plt.text(2.5, 0.5, 'www.nmc.cn', size=11) utl.add_logo_extra_in_axes(pos=[0.1, 0.88, .07, .07], which='nmc', size='Xlarge') # Show the plot if (output_dir != None): plt.savefig( output_dir + '时间剖面产品_起报时间_' + str(fcst_info['forecast_reference_time'].values)[0:13] + '_预报时效_' + str(int(fcst_info.attrs['forecast_period'].values)) + '.png', dpi=200, bbox_inches='tight') else: plt.show()
def draw_point_wind(U=None, V=None, model=None, output_dir=None, points=None, time_info=None, extra_info=None): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') initTime = pd.to_datetime(str( time_info['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() # draw figure fig = plt.figure(figsize=(12, 12)) # draw main figure #10米风—————————————————————————————————————— ax = plt.axes([0.1, 0.2, .8, .7]) utl.add_public_title_sta(title=model + '预报 ' + extra_info['point_name'] + ' [' + str(points['lon'][0]) + ',' + str(points['lat'][0]) + ']', initTime=initTime, fontsize=21) for ifhour in time_info['forecast_period'].values: if (ifhour == time_info['forecast_period'].values[0]): uv_t = (initTime + timedelta(hours=ifhour)) else: uv_t = np.append(uv_t, (initTime + timedelta(hours=ifhour))) wsp = (U**2 + V**2)**0.5 ax.plot(uv_t, np.squeeze(wsp), c='#40C4FF', linewidth=3) if (extra_info['drw_thr'] == True): ax.plot([uv_t[0], uv_t[-1]], [11, 11], c='red', label='警戒风速', linewidth=1) ax.barbs(uv_t, wsp, U, V, fill_empty=True, color='gray', barb_increments={ 'half': 2, 'full': 4, 'flag': 20 }) xaxis_intaval = mpl.dates.HourLocator(byhour=(8, 20)) #单位是小时 ax.xaxis.set_major_locator(xaxis_intaval) plt.xlim(uv_t[0], uv_t[-1]) # add legend ax.legend(fontsize=15, loc='upper right') ax.tick_params(length=10) xstklbls = mpl.dates.DateFormatter('%m月%d日%H时') for label in ax.get_xticklabels(): label.set_rotation(30) label.set_horizontalalignment('center') ax.tick_params(axis='y', labelsize=15) ax.tick_params(axis='x', labelsize=15) ax.grid() ax.grid(axis='x', c='black') miloc = mpl.dates.HourLocator(byhour=(11, 14, 17, 23, 2, 5)) #单位是小时 ax.xaxis.set_minor_locator(miloc) ax.grid(axis='x', which='minor') ax.set_ylabel('风速 (m/s)', fontsize=15) utl.add_logo_extra_in_axes(pos=[0.1, 0.8, .1, .1], which='nmc', size='Xlarge') #出图—————————————————————————————————————————————————————————— if (output_dir != None): isExists = os.path.exists(output_dir) if not isExists: os.makedirs(output_dir) output_dir2 = output_dir + model + '_起报时间_' + initTime.strftime( "%Y年%m月%d日%H时") + '/' if (os.path.exists(output_dir2) == False): os.makedirs(output_dir2) plt.savefig(output_dir2 + model + '_' + extra_info['point_name'] + '_' + extra_info['output_head_name'] + initTime.strftime("%Y%m%d%H") + '00' + extra_info['output_tail_name'] + '.jpg', dpi=200, bbox_inches='tight') else: plt.show()
def draw_point_fcst(t2m=None, u10m=None, v10m=None, rn=None, model=None, output_dir=None, points=None, extra_info=None): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') initTime = pd.to_datetime(str( t2m['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() # draw figure fig = plt.figure(figsize=(16, 4.5)) ax_t2m = HostAxes(fig, [0.1, 0.28, .8, .62]) ax_rn = ParasiteAxes(ax_t2m, sharex=ax_t2m) #其他信息 #append axes ax_t2m.parasites.append(ax_rn) #invisible right axis of ax ax_t2m.axis['right'].set_visible(False) ax_t2m.axis['right'].set_visible(False) ax_rn.axis['right'].set_visible(True) ax_rn.axis['right'].major_ticklabels.set_visible(True) ax_rn.axis['right'].label.set_visible(True) #set label for axis ax_t2m.set_ylabel('温度($^\circ$C)', fontsize=100) ax_rn.set_ylabel('降水(mm)', fontsize=100) fig.add_axes(ax_t2m) # draw main figure #2米温度—————————————————————————————————————— if (model == '中央台指导'): model = '智能网格' utl.add_public_title_sta(title=model + '预报 ' + extra_info['point_name'] + ' [' + str(points['lon'][0]) + ',' + str(points['lat'][0]) + ']', initTime=initTime, fontsize=21) for ifhour in t2m['forecast_period'].values: if (ifhour == t2m['forecast_period'].values[0]): t2m_t = (initTime + timedelta(hours=ifhour)) else: t2m_t = np.append(t2m_t, (initTime + timedelta(hours=ifhour))) curve_t2m = ax_t2m.plot(t2m_t, np.squeeze(t2m['data'].values), c='#FF6600', linewidth=3, label='2m温度') ax_t2m.set_xlim(t2m_t[0], t2m_t[-1]) ax_t2m.set_ylim( math.floor(t2m['data'].values.min() / 5) * 5 - 2, math.ceil(t2m['data'].values.max() / 5) * 5) #降水—————————————————————————————————————— for ifhour in rn['forecast_period'].values: if (ifhour == rn['forecast_period'].values[0]): rn_t = (initTime + timedelta(hours=ifhour)) else: rn_t = np.append(rn_t, (initTime + timedelta(hours=ifhour))) mask = (rn['data'] < 999) rn = rn['data'].where(mask) ax_rn.bar(rn_t, np.squeeze(rn.values), width=0.1, color='#00008B', label=str( int(rn['forecast_period'].values[1] - rn['forecast_period'].values[0])) + '小时降水', alpha=0.5) #curve_rn=ax_rn.plot(rn_t, np.squeeze(rn['data'].values), c='#40C4FF',linewidth=3) ax_rn.set_ylim(0, np.nanmax(np.append(10, np.squeeze(rn.values)))) ### xaxis_intaval = mpl.dates.HourLocator(byhour=(8, 20)) #单位是小时 ax_t2m.xaxis.set_major_locator(xaxis_intaval) # add legend ax_t2m.legend(fontsize=15, loc='upper right') ax_t2m.tick_params(length=10) ax_t2m.tick_params(axis='y', labelsize=100) ax_t2m.set_xticklabels([' ']) miloc = mpl.dates.HourLocator(byhour=(8, 11, 14, 17, 20, 23, 2, 5)) #单位是小时 ax_t2m.xaxis.set_minor_locator(miloc) yminorLocator = MultipleLocator(1) #将此y轴次刻度标签设置为1的倍数 ax_t2m.yaxis.set_minor_locator(yminorLocator) ymajorLocator = MultipleLocator(5) #将此y轴次刻度标签设置为1的倍数 ax_t2m.yaxis.set_major_locator(ymajorLocator) ax_t2m.grid(axis='x', which='minor', ls='--') ax_t2m.axis['left'].label.set_fontsize(15) ax_t2m.axis['left'].major_ticklabels.set_fontsize(15) ax_rn.axis['right'].label.set_fontsize(15) ax_rn.axis['right'].major_ticklabels.set_fontsize(15) #10米风—————————————————————————————————————— ax_uv = plt.axes([0.1, 0.16, .8, .12]) for ifhour in u10m['forecast_period'].values: if (ifhour == u10m['forecast_period'].values[0]): uv_t = (initTime + timedelta(hours=ifhour)) else: uv_t = np.append(uv_t, (initTime + timedelta(hours=ifhour))) wsp = (u10m**2 + v10m**2)**0.5 #curve_uv=ax_uv.plot(uv_t, np.squeeze(wsp['data'].values), c='#696969',linewidth=3,label='10m风') ax_uv.barbs(uv_t, np.zeros(len(uv_t)), np.squeeze(u10m['data'].values), np.squeeze(v10m['data'].values), fill_empty=True, color='gray', barb_increments={ 'half': 2, 'full': 4, 'flag': 20 }, length=5.8, linewidth=1.5, zorder=100) ax_uv.set_ylim(-1, 1) ax_uv.set_xlim(uv_t[0], uv_t[-1]) #ax_uv.axis('off') ax_uv.set_yticklabels([' ']) #logo utl.add_logo_extra_in_axes(pos=[0.87, 0.00, .1, .1], which='nmc', size='Xlarge') #开启自适应 xaxis_intaval = mpl.dates.HourLocator(byhour=(8, 20)) #单位是小时 ax_uv.xaxis.set_major_locator(xaxis_intaval) ax_uv.tick_params(length=5, axis='x') ax_uv.tick_params(length=0, axis='y') miloc = mpl.dates.HourLocator(byhour=(8, 11, 14, 17, 20, 23, 2, 5)) #单位是小时 ax_uv.xaxis.set_minor_locator(miloc) ax_uv.grid(axis='x', which='both', ls='--') ax_uv.set_ylabel('10m风', fontsize=15) xstklbls = mpl.dates.DateFormatter('%m月%d日%H时') for label in ax_uv.get_xticklabels(): label.set_rotation(30) label.set_horizontalalignment('center') ax_uv.tick_params(axis='x', labelsize=15) #出图—————————————————————————————————————————————————————————— if (output_dir != None): isExists = os.path.exists(output_dir) if not isExists: os.makedirs(output_dir) output_dir2 = output_dir + model + '_起报时间_' + initTime.strftime( "%Y年%m月%d日%H时") + '/' if (os.path.exists(output_dir2) == False): os.makedirs(output_dir2) plt.savefig(output_dir2 + model + '_' + extra_info['point_name'] + '_' + extra_info['output_head_name'] + initTime.strftime("%Y%m%d%H") + '00' + extra_info['output_tail_name'] + '.jpg', dpi=200, bbox_inches='tight') else: plt.show()
def draw_Station_Snow_Synthetical_Forecast_From_Cassandra( TWC=None, AT=None, u10m=None, v10m=None, u100m=None, v100m=None, gust10m=None, wsp10m=None, wsp100m=None, SNOD1=None, SNOD2=None, SDEN=None, SN06=None, draw_VIS=False, VIS=None, drw_thr=False, time_all=None, model=None, points=None, output_dir=None, extra_info={ 'output_head_name': ' ', 'output_tail_name': ' ', 'point_name': ' ' }): #if(sys.platform[0:3] == 'win'): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') initTime1 = pd.to_datetime(str( TWC['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() initTime2 = pd.to_datetime(str( VIS['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() # draw figure fig = plt.figure(figsize=(12, 16)) # draw main figure #风寒指数 体感温度———————————————————————————————————————————————— ax = plt.axes([0.05, 0.83, .94, .15]) utl.add_public_title_sta(title=model + '预报 ' + extra_info['point_name'] + ' [' + str(points['lon'][0]) + ',' + str(points['lat'][0]) + ']', initTime=initTime1, fontsize=23) for ifhour in TWC['forecast_period'].values: if (ifhour == TWC['forecast_period'].values[0]): TWC_t = (initTime1 + timedelta(hours=ifhour)) else: TWC_t = np.append(TWC_t, (initTime1 + timedelta(hours=ifhour))) #开启自适应 xaxis_intaval = mpl.dates.HourLocator(byhour=(8, 20)) #单位是小时 ax.xaxis.set_major_locator(xaxis_intaval) ax.set_xticklabels([' ']) ax.plot(TWC_t, np.squeeze(TWC), label='风寒指数') ax.plot(TWC_t, np.squeeze(AT), c='#00796B', label='2米体感温度') ax.tick_params(length=10) ax.grid() ax.grid(axis='x', c='black') miloc = mpl.dates.HourLocator(byhour=(11, 14, 17, 23, 2, 5)) #单位是小时 ax.xaxis.set_minor_locator(miloc) ax.grid(axis='x', which='minor') plt.xlim(time_all[0], time_all[-1]) plt.ylim(min([AT.values.min(), TWC.values.min()]), max([AT.values.max(), TWC.values.max()])) ax.legend(fontsize=10, loc='upper right') ax.set_ylabel('2米体感温度 风寒指数 ($^\circ$C)', fontsize=15) #10米风—————————————————————————————————————— ax = plt.axes([0.05, 0.66, .94, .15]) for ifhour in u10m['forecast_period'].values: if (ifhour == u10m['forecast_period'].values[0]): uv10m_t = (initTime1 + timedelta(hours=ifhour)) else: uv10m_t = np.append(uv10m_t, (initTime1 + timedelta(hours=ifhour))) for ifhour in u100m['forecast_period'].values: if (ifhour == u100m['forecast_period'].values[0]): uv100m_t = (initTime1 + timedelta(hours=ifhour)) else: uv100m_t = np.append(uv100m_t, (initTime1 + timedelta(hours=ifhour))) for ifhour in gust10m['forecast_period'].values: if (ifhour == gust10m['forecast_period'].values[0]): gust10m_t = (initTime1 + timedelta(hours=ifhour)) else: gust10m_t = np.append(gust10m_t, (initTime1 + timedelta(hours=ifhour))) ax.plot(uv10m_t, np.squeeze(wsp10m), c='#40C4FF', label='10米风', linewidth=3) ax.plot(uv100m_t, np.squeeze(wsp100m), c='#FF6F00', label='100米风', linewidth=3) ax.plot(gust10m_t, np.squeeze(gust10m['data']), c='#7C4DFF', label='10米阵风', linewidth=3) if (drw_thr == True): ax.plot([uv10m_t[0], uv10m_t[-1]], [5.5, 5.5], c='#4CAE50', label='10米平均风一般影响', linewidth=1) ax.plot([uv10m_t[0], uv10m_t[-1]], [8, 8], c='#FFEB3B', label='10米平均风较大影响', linewidth=1) ax.plot([uv10m_t[0], uv10m_t[-1]], [10.8, 10.8], c='#F44336', label='10米平均风高影响', linewidth=1) ax.plot([gust10m_t[0], gust10m_t[-1]], [10.8, 10.8], c='#4CAE50', label='10米阵风一般影响', dashes=[6, 2], linewidth=1) ax.plot([gust10m_t[0], gust10m_t[-1]], [13.9, 13.9], c='#FFEB3B', label='10米阵风较大影响', dashes=[6, 2], linewidth=1) ax.plot([gust10m_t[0], gust10m_t[-1]], [17.2, 17.2], c='#F44336', label='10米阵风高影响', dashes=[6, 2], linewidth=1) ax.barbs(uv10m_t[0:-1], wsp10m[0:-1], np.squeeze(u10m['data'])[0:-1], np.squeeze(v10m['data'])[0:-1], fill_empty=True, color='gray', barb_increments={ 'half': 2, 'full': 4, 'flag': 20 }) ax.barbs(uv100m_t[0:-1], wsp100m[0:-1], np.squeeze(u100m['data'])[0:-1], np.squeeze(v100m['data'])[0:-1], fill_empty=True, color='gray', barb_increments={ 'half': 2, 'full': 4, 'flag': 20 }) xaxis_intaval = mpl.dates.HourLocator(byhour=(8, 20)) #单位是小时 ax.xaxis.set_major_locator(xaxis_intaval) ax.set_xticklabels([' ']) plt.xlim(time_all[0], time_all[-1]) # add legend ax.legend(fontsize=10, loc='upper right') ax.tick_params(length=10) ax.grid() ax.grid(axis='x', c='black') miloc = mpl.dates.HourLocator(byhour=(11, 14, 17, 23, 2, 5)) #单位是小时 ax.xaxis.set_minor_locator(miloc) ax.grid(axis='x', which='minor') ax.set_ylabel('10米风 100米 风\n' + '风速 (m/s)', fontsize=15) #雪密度—————————————————————————————————————— # draw main figure ax = plt.axes([0.05, 0.49, .94, .15]) for ifhour in SDEN['forecast_period'].values: if (ifhour == SDEN['forecast_period'].values[0]): SDEN_t = (initTime1 + timedelta(hours=ifhour)) else: SDEN_t = np.append(SDEN_t, (initTime1 + timedelta(hours=ifhour))) #开启自适应 xaxis_intaval = mpl.dates.HourLocator(byhour=(8, 20)) #单位是小时 ax.xaxis.set_major_locator(xaxis_intaval) ax.set_xticklabels([' ']) ax.plot(SDEN_t, np.squeeze(SDEN['data']), color='#1E88E5', label='雪密度') #ax.bar(SDEN_t,np.squeeze(SDEN['data']),width=0.12,color='#1E88E5') gap_hour_SDEN = int(SDEN['forecast_period'].values[1] - SDEN['forecast_period'].values[0]) if (drw_thr == True): ax.plot([SDEN_t[0], SDEN_t[-1]], [1 * gap_hour_SDEN, 1 * gap_hour_SDEN], c='#FFEB3B', label=str(gap_hour_SDEN) + '小时降水较大影响', linewidth=1) ax.plot([SDEN_t[0], SDEN_t[-1]], [10 * gap_hour_SDEN, 10 * gap_hour_SDEN], c='#F44336', label=str(gap_hour_SDEN) + '小时降水高影响', linewidth=1) ax.legend(fontsize=10, loc='upper right') ax.tick_params(length=10) ax.grid() ax.grid(axis='x', c='black') miloc = mpl.dates.HourLocator(byhour=(11, 14, 17, 23, 2, 5)) #单位是小时 ax.xaxis.set_minor_locator(miloc) ax.grid(axis='x', which='minor') plt.xlim(time_all[0], time_all[-1]) plt.ylim([ np.squeeze(SDEN['data']).values.min(), np.squeeze(SDEN['data'].values.max()) + 2 ]) ax.set_ylabel('雪密度 (kg m-3)', fontsize=15) #积雪深度—————————————————————————————————————— # draw main figure ax = plt.axes([0.05, 0.32, .94, .15]) for ifhour in SNOD1['forecast_period'].values: if (ifhour == SNOD1['forecast_period'].values[0]): SNOD1_t = (initTime1 + timedelta(hours=ifhour)) else: SNOD1_t = np.append(SNOD1_t, (initTime1 + timedelta(hours=ifhour))) # draw main figure for ifhour in SNOD2['forecast_period'].values: if (ifhour == SNOD2['forecast_period'].values[0]): SNOD2_t = (initTime1 + timedelta(hours=ifhour)) else: SNOD2_t = np.append(SNOD2_t, (initTime1 + timedelta(hours=ifhour))) for ifhour in SN06['forecast_period'].values: if (ifhour == SN06['forecast_period'].values[0]): SN06_t = (initTime1 + timedelta(hours=ifhour)) else: SN06_t = np.append(SN06_t, (initTime1 + timedelta(hours=ifhour))) #开启自适应 xaxis_intaval = mpl.dates.HourLocator(byhour=(8, 20)) #单位是小时 ax.xaxis.set_major_locator(xaxis_intaval) ax.set_xticklabels([' ']) #ax.bar(SNOD1_t,np.squeeze(SNOD1['data']),width=0.20,color='#82B1FF',label='EC预报积雪深度') #ax.bar(SNOD2_t,np.squeeze(SNOD2['data']),width=0.125,color='#2962FF',label='NCEP预报积雪深度') ax.plot(SNOD1_t, np.squeeze(SNOD1['data']), dashes=[6, 2], color='#4B4B4B', linewidth=3, label='EC预报积雪深度') ax.plot(SNOD2_t, np.squeeze(SNOD2['data']), dashes=[6, 2], color='#969696', linewidth=3, label='NCEP预报积雪深度') ax.plot(SN06_t, np.squeeze(SN06['data']), color='#82B1FF', linewidth=2, label='EC预报降雪量') ax.tick_params(length=10) ax.grid() ax.grid(axis='x', c='black') miloc = mpl.dates.HourLocator(byhour=(11, 14, 17, 23, 2, 5)) #单位是小时 ax.xaxis.set_minor_locator(miloc) ax.grid(axis='x', which='minor') plt.xlim(time_all[0], time_all[-1]) plt.ylim(0, 100) ax.legend(fontsize=10, loc='upper right') plt.ylim( min([ np.squeeze(SNOD1['data']).values.min(), np.squeeze(SNOD2['data']).values.min() ]), max([ np.squeeze(SNOD1['data']).values.max(), np.squeeze(SNOD2['data']).values.max() ]) + 5) ax.set_ylabel('积雪深度 (cm)\n' + '6小时降雪量(mm)', fontsize=15) if (draw_VIS == False): xstklbls = mpl.dates.DateFormatter('%m月%d日%H时') ax.xaxis.set_major_formatter(xstklbls) for label in ax.get_xticklabels(): label.set_rotation(30) label.set_horizontalalignment('center') #发布信息———————————————————————————————————————————————— ax = plt.axes([0.05, 0.08, .94, .05]) ax.axis([0, 10, 0, 10]) ax.axis('off') utl.add_logo_extra_in_axes(pos=[0.7, 0.23, .05, .05], which='nmc', size='Xlarge') ax.text(7.5, 33, (initTime1 - timedelta(hours=2)).strftime("%Y年%m月%d日%H时") + '发布', size=15) if (draw_VIS == True): #能见度—————————————————————————————————————— # draw main figure ax = plt.axes([0.05, 0.15, .94, .15]) #VIS=pd.read_csv(dir_all['VIS_SC']+last_file[model]) for ifhour in VIS['forecast_period'].values: if (ifhour == VIS['forecast_period'].values[0]): VIS_t = (initTime2 + timedelta(hours=ifhour)) else: VIS_t = np.append(VIS_t, (initTime2 + timedelta(hours=ifhour))) #开启自适应 xaxis_intaval = mpl.dates.HourLocator(byhour=(8, 20)) #单位是小时 ax.xaxis.set_major_locator(xaxis_intaval) ax.fill_between(VIS_t, np.squeeze(VIS['data']), -100, facecolor='#B3E5FC') ax.fill_between(VIS_t, np.squeeze(VIS['data']), 1, facecolor='#81D4FA') ax.fill_between(VIS_t, np.squeeze(VIS['data']), 3, facecolor='#4FC3F7') ax.fill_between(VIS_t, np.squeeze(VIS['data']), 5, facecolor='#29B6F6') ax.fill_between(VIS_t, np.squeeze(VIS['data']), 10, facecolor='#03A9F4') ax.fill_between(VIS_t, np.squeeze(VIS['data']), 15, facecolor='#039BE5') ax.fill_between(VIS_t, np.squeeze(VIS['data']), 20, facecolor='#0288D1') ax.fill_between(VIS_t, np.squeeze(VIS['data']), 25, facecolor='#0277BD') ax.fill_between(VIS_t, np.squeeze(VIS['data']), 30, facecolor='#01579B') ax.fill_between(VIS_t, np.squeeze(VIS['data']), 100, facecolor='#FFFFFF') ax.plot(VIS_t, np.squeeze(VIS['data'])) if (drw_thr == True): ax.plot([VIS_t[0], VIS_t[-1]], [5, 5], c='#4CAF50', label='能见度一般影响', linewidth=1) ax.plot([VIS_t[0], VIS_t[-1]], [3, 3], c='#FFEB3B', label='能见度较大影响', linewidth=1) ax.plot([VIS_t[0], VIS_t[-1]], [1, 1], c='#F44336', label='能见度高影响', linewidth=1) ax.legend(fontsize=10, loc='upper right') xstklbls = mpl.dates.DateFormatter('%m月%d日%H时') ax.xaxis.set_major_formatter(xstklbls) for label in ax.get_xticklabels(): label.set_rotation(30) label.set_horizontalalignment('center') ax.tick_params(length=10) ax.grid() ax.grid(axis='x', c='black') miloc = mpl.dates.HourLocator(byhour=(11, 14, 17, 23, 2, 5)) #单位是小时 ax.xaxis.set_minor_locator(miloc) ax.grid(axis='x', which='minor') plt.xlim(time_all[0], time_all[-1]) plt.ylim(0, 25) ax.set_ylabel('能见度 (km)', fontsize=15) #发布信息———————————————————————————————————————————————— ax = plt.axes([0.05, 0.08, .94, .05]) ax.axis([0, 10, 0, 10]) ax.axis('off') utl.add_logo_extra_in_axes(pos=[0.7, 0.06, .05, .05], which='nmc', size='Xlarge') ax.text(7.5, 0.1, (initTime2 - timedelta(hours=2)).strftime("%Y年%m月%d日%H时") + '发布', size=15) #出图—————————————————————————————————————————————————————————— if (output_dir != None): isExists = os.path.exists(output_dir) if not isExists: os.makedirs(output_dir) plt.savefig(output_dir + extra_info['output_head_name'] + initTime1.strftime("%Y%m%d%H") + '00' + extra_info['output_tail_name'] + '.jpg', dpi=200, bbox_inches='tight') else: plt.show()
def draw_mslp_rain_snow( rain=None, snow=None,sleet=None,mslp=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True,city=True,south_China_sea=True, output_dir=None,Global=False): # set font plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # set figure plt.figure(figsize=(16,9)) if(Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea(central_latitude=(map_extent[2]+map_extent[3])/2., central_longitude=(map_extent[0]+map_extent[1])/2., standard_parallels=[30., 60.]) ax = plt.axes([0.01,0.1,.98,.84], projection=plotcrs) datacrs = ccrs.PlateCarree() map_extent2=utl.adjust_map_ratio(ax,map_extent=map_extent,datacrs=datacrs) plt.title('['+mslp.attrs['model']+'] '+ '海平面气压, '+ str(rain.attrs['atime'])+'小时降水', loc='left', fontsize=30) #draw data plots = {} if rain is not None: x, y = np.meshgrid(rain['lon'], rain['lat']) z=np.squeeze(rain.values) cmap,norm=dk_ctables.cm_rain_nws(atime=rain.attrs['atime']) #cmap.set_under(color=[0,0,0,0],alpha=0.0) plots['rain'] = ax.pcolormesh( x,y,z, norm=norm, cmap=cmap, zorder=3,transform=datacrs,alpha=0.8) if snow is not None: x, y = np.meshgrid(snow['lon'], snow['lat']) z=np.squeeze(snow.values) cmap,norm=dk_ctables.cm_snow_nws(atime=rain.attrs['atime']) #cmap.set_under(color=[0,0,0,0],alpha=0.0) plots['snow'] = ax.pcolormesh( x,y,z, norm=norm, cmap=cmap, zorder=3,transform=datacrs,alpha=0.8) if sleet is not None: x, y = np.meshgrid(sleet['lon'], sleet['lat']) z=np.squeeze(sleet.values) cmap,norm=dk_ctables.cm_sleet_nws(atime=rain.attrs['atime']) #cmap.set_under(color=[0,0,0,0],alpha=0.0) plots['sleet'] = ax.pcolormesh( x,y,z, norm=norm, cmap=cmap, zorder=3,transform=datacrs,alpha=0.8) if mslp is not None: x, y = np.meshgrid(mslp['lon'], mslp['lat']) clevs_mslp = np.arange(900, 1100,2.5) z=gaussian_filter(np.squeeze(mslp['data']), 5) plots['mslp'] = ax.contour( x, y, z, clevs_mslp, colors='black', linewidths=2, transform=datacrs, zorder=3) plt.clabel(plots['mslp'], inline=1, fontsize=20, fmt='%.0f',colors='black') #additional information ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public( ax, name='coastline', edgecolor='gray', lw=0.8, zorder=1,alpha=0.5) if add_china: utl.add_china_map_2cartopy_public( ax, name='province', edgecolor='gray', lw=0.5, zorder=1) utl.add_china_map_2cartopy_public( ax, name='nation', edgecolor='black', lw=0.8, zorder=1) utl.add_china_map_2cartopy_public( ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=1,alpha=0.5) # grid lines gl = ax.gridlines( crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=1) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) # utl.add_cartopy_background(ax,name='RD') ax.add_feature(cfeature.LAND,color='#F5E19F') ax.add_feature(cfeature.OCEAN) l, b, w, h = ax.get_position().bounds #forecast information bax=plt.axes([l,b+h-0.1,.25,.1],facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initTime = pd.to_datetime( str(mslp.coords['forecast_reference_time'].values)).replace(tzinfo=None).to_pydatetime() fcst_time=initTime+timedelta(hours=mslp.coords['forecast_period'].values[0]) #发布时间 if(sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if(sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5,'起报时间: '+initTime.strftime("%Y年%m月%d日%H时"),size=15) plt.text(2.5, 5,'预报时间: '+fcst_time.strftime("%Y年%m月%d日%H时"),size=15) plt.text(2.5, 2.5,'预报时效: '+str(int(mslp.coords['forecast_period'].values[0]))+'小时',size=15) plt.text(2.5, 0.5,'www.nmc.cn',size=15) # add color bar if(sleet is not None): cax=plt.axes([l-0.03,b-0.04,w/3,.02]) cb = plt.colorbar(plots['sleet'], cax=cax, orientation='horizontal') cb.ax.tick_params(labelsize='x-large') cb.set_label('雨夹雪 (mm)',size=20) if(snow is not None): # cax=plt.axes([l+0.32,b-0.04,w/4,.02]) cax=plt.axes([l+w/3,b-0.04,w/3,.02]) cb = plt.colorbar(plots['snow'], cax=cax, orientation='horizontal') cb.ax.tick_params(labelsize='x-large') cb.set_label('雪 (mm)',size=20) if(rain is not None): # cax=plt.axes([l+0.65,b-0.04,w/4,.02]) cax=plt.axes([l+w*2/3+0.03,b-0.04,w/3,.02]) cb = plt.colorbar(plots['rain'], cax=cax, orientation='horizontal') cb.ax.tick_params(labelsize='x-large') cb.set_label('雨 (mm)',size=20) # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[l+w-0.091,b,.1,.2]) small_city=False if(map_extent2[1]-map_extent2[0] < 25): small_city=True if city: utl.add_city_on_map(ax,map_extent=map_extent2,transform=datacrs,zorder=110,size=13,small_city=small_city) utl.add_logo_extra_in_axes(pos=[l-0.02,b+h-0.1,.1,.1],which='nmc', size='Xlarge') # show figure if(output_dir != None): plt.savefig(output_dir+'海平面气压_降水_预报_'+ '起报时间_'+initTime.strftime("%Y年%m月%d日%H时")+ '预报时效_'+str(int(mslp.coords['forecast_period'].values[0]))+'小时'+'.png', dpi=200,bbox_inches='tight') plt.close() if(output_dir == None): plt.show()
def draw_gh_uv_r6(gh=None, uv=None, r6=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True,city=True,south_China_sea=True, output_dir=None,Global=False): """ Draw -hPa geopotential height contours, -hPa wind barbs and mean sea level pressure filled contours. :param gh: -hPa gh, dictionary: necessary, {'lon': 1D array, 'lat': 1D array, 'data': 2D array} optional, {'clevs': 1D array} :param uv: -hPa u-component and v-component wind, dictionary: necessary, {'lon': 1D array, 'lat': 1D array, 'udata': 2D array, 'vdata': 2D array} :param r6: r6, dictionary: necessary, {'lon': 1D array, 'lat': 1D array, 'data': 2D array} optional, {'clevs': 1D array} :param map_extent: [lonmin, lonmax, latmin, latmax], longitude and latitude range. :param add_china: add china map or not. :param regrid_shape: control the wind barbs density. :return: plots dictionary. :Examples: """ plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # draw figure plt.figure(figsize=(16,9)) # set data projection if(Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea(central_latitude=(map_extent[2]+map_extent[3])/2., central_longitude=(map_extent[0]+map_extent[1])/2., standard_parallels=[30., 60.]) ax = plt.axes([0.01,0.1,.98,.84], projection=plotcrs) plt.title('['+gh['model']+'] '+ gh['lev']+'hPa 位势高度场, '+ uv['lev']+'hPa 风场, 6小时降水', loc='left', fontsize=30) datacrs = ccrs.PlateCarree() #adapt to the map ratio map_extent2=utl.adjust_map_ratio(ax,map_extent=map_extent,datacrs=datacrs) #adapt to the map ratio ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public( ax, name='coastline', edgecolor='gray', lw=0.8, zorder=105,alpha=0.5) if add_china: utl.add_china_map_2cartopy_public( ax, name='province', edgecolor='gray', lw=0.5, zorder=105) utl.add_china_map_2cartopy_public( ax, name='nation', edgecolor='black', lw=0.8, zorder=105) utl.add_china_map_2cartopy_public( ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=105,alpha=0.5) # define return plots plots = {} # draw mean sea level pressure if r6 is not None: x, y = np.meshgrid(r6['lon'], r6['lat']) clevs_r6 = [0.1, 4, 13, 25, 60, 120] plots['r6'] = ax.contourf( x, y, np.squeeze(r6['data']), clevs_r6, colors=["#88F492", "#00A929", "#2AB8FF", "#1202FC", "#FF04F4", "#850C3E"], alpha=0.8, zorder=10, transform=datacrs,extend='max',extendrect=False) # draw -hPa wind bards if uv is not None: x, y = np.meshgrid(uv['lon'], uv['lat']) u = np.squeeze(uv['udata']) * 2.5 v = np.squeeze(uv['vdata']) * 2.5 plots['uv'] = ax.barbs( x, y, u, v, length=6, regrid_shape=regrid_shape, transform=datacrs, fill_empty=False, sizes=dict(emptybarb=0.05), zorder=20) # draw -hPa geopotential height if gh is not None: x, y = np.meshgrid(gh['lon'], gh['lat']) clevs_gh = np.append(np.append(np.arange(0, 480, 4),np.append(np.arange(480, 584, 8), np.arange(580, 604, 4))), np.arange(604, 2000, 8)) plots['gh'] = ax.contour( x, y, np.squeeze(gh['data']), clevs_gh, colors='black', linewidths=2, transform=datacrs, zorder=30) plt.clabel(plots['gh'], inline=1, fontsize=20, fmt='%.0f',colors='black') # grid lines gl = ax.gridlines( crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=40) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) #http://earthpy.org/cartopy_backgroung.html #C:\ProgramData\Anaconda3\Lib\site-packages\cartopy\data\raster\natural_earth ax.background_img(name='RD', resolution='high') #forecast information bax=plt.axes([0.01,0.835,.25,.1],facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initial_time = pd.to_datetime( str(gh['init_time'])).replace(tzinfo=None).to_pydatetime() fcst_time=initial_time+timedelta(hours=gh['fhour']) #发布时间 if(sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN') if(sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5,'起报时间: '+initial_time.strftime("%Y年%m月%d日%H时"),size=15) plt.text(2.5, 5,'预报时间: '+fcst_time.strftime("%Y年%m月%d日%H时"),size=15) plt.text(2.5, 2.5,'预报时效: '+str(gh['fhour'])+'小时',size=15) plt.text(2.5, 0.5,'www.nmc.cn',size=15) # add color bar if(r6 != None): cax=plt.axes([0.11,0.06,.86,.02]) cb = plt.colorbar(plots['r6'], cax=cax, orientation='horizontal', ticks=clevs_r6[:], extend='max',extendrect=False) cb.ax.tick_params(labelsize='x-large') cb.set_label('6h precipitation (mm)',size=20) # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[0.85,0.13,.1,.2]) small_city=False if(map_extent2[1]-map_extent2[0] < 25): small_city=True if city: utl.add_city_on_map(ax,map_extent=map_extent2,transform=datacrs,zorder=110,size=13,small_city=small_city) utl.add_logo_extra_in_axes(pos=[-0.01,0.835,.1,.1],which='nmc', size='Xlarge') # show figure if(output_dir != None): plt.savefig(output_dir+'高度场_风场_降水_预报_'+ '起报时间_'+initial_time.strftime("%Y年%m月%d日%H时")+ '预报时效_'+str(gh['fhour'])+'小时'+'.png', dpi=200) if(output_dir == None): plt.show()
def draw_Time_Crossection_rh_uv_t( rh_2D=None, u_2D=None, v_2D=None,TMP_2D=None, t_range=None,lw_ratio=[16,9],output_dir=None): #set font plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) fig = plt.figure(1, figsize=(lw_ratio[0],lw_ratio[1])) ax = plt.axes() # example 2: use the "fromList() method startcolor = '#1E90FF' #蓝色 midcolor = '#F1F1F1' #白色 endcolor = '#696969' #灰色 cmap2 = col.LinearSegmentedColormap.from_list('own2',['#1E90FF','#94D8F6','#F1F1F1','#BFBFBF','#696969']) rh_contour = ax.contourf(rh_2D['time'].values, rh_2D['level'].values, np.squeeze(rh_2D['data'].values.swapaxes(1,0)), levels=np.arange(0, 101, 0.5), cmap=cmap2,extend='max') rh_colorbar = fig.colorbar(rh_contour,ticks=[20,40,60,80,100]) rh_colorbar.set_label('相对湿度(%)',size=15) ax.barbs(u_2D['time'].values, u_2D['level'].values, np.squeeze(u_2D['data'].values.swapaxes(1,0))*2.5, np.squeeze(v_2D['data'].values.swapaxes(1,0))*2.5, color='k') TMP_contour = ax.contour(TMP_2D['time'].values, TMP_2D['level'].values, np.squeeze(TMP_2D['data'].values.swapaxes(1,0)), levels=np.arange(-100, 40, 5), colors='#F4511E', linewidths=2) TMP_contour.clabel(TMP_contour.levels[1::2], fontsize=15, colors='#F4511E', inline=1, inline_spacing=8, fmt='%i', rightside_up=True, use_clabeltext=True) xstklbls = mpl.dates.DateFormatter('%m月%d日%H时') ax.xaxis.set_major_formatter(xstklbls) for label in ax.get_xticklabels(): label.set_rotation(30) label.set_fontsize(15) label.set_horizontalalignment('right') for label in ax.get_yticklabels(): label.set_fontsize(15) ax.set_yscale('symlog') ax.set_ylabel('高度 (hPa)', fontsize=15) ax.set_yticklabels(np.arange(1000, 50, -100)) ax.set_yticks(np.arange(1000, 50, -100)) ax.set_ylim(rh_2D['level'].values.max(), rh_2D['level'].values.min()) ax.set_xlim([rh_2D['time'].values[0], rh_2D['time'].values[-1]]) #forecast information bax=plt.axes([0.10,0.88,.25,.07],facecolor='#FFFFFFCC') bax.axis('off') bax.axis([0, 10, 0, 10]) initTime = pd.to_datetime( str(rh_2D['forecast_reference_time'].values)).replace(tzinfo=None).to_pydatetime() if(sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if(sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5,'起报时间: '+initTime.strftime("%Y年%m月%d日%H时"),size=11) plt.text(2.5, 5.0,'['+str(rh_2D.attrs['model'])+']'+'模式时间剖面',size=11) plt.text(2.5, 2.5,'预报点: '+str(rh_2D.attrs['points']['lon'])+ ', '+str(rh_2D.attrs['points']['lat']),size=11) plt.text(2.5, 0.5,'www.nmc.cn',size=11) utl.add_logo_extra_in_axes(pos=[0.1,0.88,.07,.07],which='nmc', size='Xlarge') ax.set_title('温度, 相对湿度, 水平风', loc='right', fontsize=23) #出图—————————————————————————————————————————————————————————— if(output_dir != None ): plt.savefig(output_dir+'时间剖面产品_起报时间_'+ str(rh_2D['forecast_reference_time'].values)[0:13]+ '_预报时效_'+str(t_range[0])+'_至_'+str(t_range[1]) +'.png', dpi=200,bbox_inches='tight') plt.close() else: plt.show()
def draw_Crosssection_Wind_Theta_e_Qv(cross_Qv=None, cross_Theta_e=None, cross_u=None, cross_v=None, gh=None, h_pos=None, st_point=None, ed_point=None, levels=None, map_extent=(50, 150, 0, 65), output_dir=None): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) initial_time = pd.to_datetime( str(cross_Theta_e['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() fcst_time = initial_time + timedelta(hours=gh['forecast_period'].values[0]) fig = plt.figure(1, figsize=(16., 9.)) ax = plt.axes() Qv_contour = ax.contourf(cross_Qv['lon'], cross_Qv['level'], cross_Qv.values, levels=np.arange(0, 20, 2), cmap='YlGnBu') Qv_colorbar = fig.colorbar(Qv_contour) # Plot potential temperature using contour, with some custom labeling Theta_e_contour = ax.contour(cross_Theta_e['lon'], cross_Theta_e['level'], cross_Theta_e.values, levels=np.arange(250, 450, 5), colors='k', linewidths=2) Theta_e_contour.clabel(np.arange(250, 450, 5), fontsize=8, colors='k', inline=1, inline_spacing=8, fmt='%i', rightside_up=True, use_clabeltext=True) wind_slc_vert = list(range(0, len(levels), 1)) wind_slc_horz = slice(5, 100, 5) ax.barbs(cross_u['lon'][wind_slc_horz], cross_u['level'][wind_slc_vert], cross_u['t_wind'][wind_slc_vert, wind_slc_horz] * 2.5, cross_v['n_wind'][wind_slc_vert, wind_slc_horz] * 2.5, color='k') # Adjust the y-axis to be logarithmic ax.set_yscale('symlog') ax.set_yticklabels(np.arange(levels[0], levels[-1], -100)) ax.set_ylim(levels[0], levels[-1]) ax.set_yticks(np.arange(levels[0], levels[-1], -100)) # Define the CRS and inset axes data_crs = ccrs.PlateCarree() ax_inset = fig.add_axes(h_pos, projection=data_crs) ax_inset.set_extent(map_extent, crs=data_crs) # Plot geopotential height at 500 hPa using xarray's contour wrapper ax_inset.contour(gh['lon'], gh['lat'], np.squeeze(gh['data']), levels=np.arange(500, 600, 4), cmap='inferno') # Plot the path of the cross section endpoints = data_crs.transform_points( ccrs.Geodetic(), *np.vstack([st_point, ed_point]).transpose()[::-1]) ax_inset.scatter(endpoints[:, 0], endpoints[:, 1], c='k', zorder=2) ax_inset.plot(cross_u['lon'], cross_u['lat'], c='k', zorder=2) # Add geographic features ax_inset.coastlines() utl.add_china_map_2cartopy_public(ax_inset, name='province', edgecolor='black', lw=0.8, zorder=105) # Set the titles and axes labels ax_inset.set_title('') ax.set_title('相当位温, 绝对湿度, 水平风场', loc='right', fontsize=25) ax.set_ylabel('Pressure (hPa)') ax.set_xlabel('Longitude') Qv_colorbar.set_label('Specific Humidity (g/kg)') if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') bax = fig.add_axes([0.10, 0.88, .25, .07], facecolor='#FFFFFFCC') bax.axis('off') #bax.set_yticks([]) #bax.set_xticks([]) bax.axis([0, 10, 0, 10]) plt.text(2.5, 7.5, '起报时间: ' + initial_time.strftime("%Y年%m月%d日%H时"), size=11) plt.text(2.5, 5, '预报时间: ' + fcst_time.strftime("%Y年%m月%d日%H时"), size=11) plt.text(2.5, 2.5, '预报时效: ' + str(int(gh['forecast_period'].values[0])) + '小时', size=11) plt.text(2.5, 0.5, 'www.nmc.cn', size=11) utl.add_logo_extra_in_axes(pos=[0.1, 0.88, .07, .07], which='nmc', size='Xlarge') # show figure if (output_dir != None): plt.savefig(output_dir + '相当位温_绝对湿度_水平风场_预报_' + '起报时间_' + initial_time.strftime("%Y年%m月%d日%H时") + '预报时效_' + str(int(gh['forecast_period'].values[0])) + '小时' + '.png', dpi=200) if (output_dir == None): plt.show()
def draw_T_2m(T_2m=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True, city=True, south_China_sea=True, output_dir=None, Global=False): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # draw figure plt.figure(figsize=(16, 9)) # set data projection if (Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea( central_latitude=(map_extent[2] + map_extent[3]) / 2., central_longitude=(map_extent[0] + map_extent[1]) / 2., standard_parallels=[30., 60.]) ax = plt.axes([0.01, 0.1, .98, .84], projection=plotcrs) plt.title('[' + T_2m['model'] + ']' + ' ' + T_2m['title'], loc='left', fontsize=30) datacrs = ccrs.PlateCarree() #adapt to the map ratio map_extent2 = utl.adjust_map_ratio(ax, map_extent=map_extent, datacrs=datacrs) #adapt to the map ratio ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public(ax, name='coastline', edgecolor='gray', lw=0.8, zorder=105, alpha=0.5) if add_china: utl.add_china_map_2cartopy_public(ax, name='province', edgecolor='gray', lw=0.5, zorder=105) utl.add_china_map_2cartopy_public(ax, name='nation', edgecolor='black', lw=0.8, zorder=105) utl.add_china_map_2cartopy_public(ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=105, alpha=0.5) # define return plots plots = {} # draw mean sea level pressure if T_2m is not None: x, y = np.meshgrid(T_2m['lon'], T_2m['lat']) z = np.squeeze(T_2m['data']) cmap = dk_ctables.cm_temperature_nws() cmap.set_under(color=[0, 0, 0, 0], alpha=0.0) plots['T_2m'] = ax.pcolormesh(x, y, z, cmap=cmap, zorder=100, transform=datacrs, alpha=0.5, vmin=-45, vmax=45) clevs_zero = 0 z = gaussian_filter(z, 5) plots['T_2m_zero'] = ax.contour(x, y, z, clevs_zero, colors='red', linewidths=2, transform=datacrs, zorder=110) # grid lines gl = ax.gridlines(crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=120) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) #http://earthpy.org/cartopy_backgroung.html #C:\ProgramData\Anaconda3\Lib\site-packages\cartopy\data\raster\natural_earth ax.background_img(name='RD', resolution='high') #forecast information bax = plt.axes([0.01, 0.835, .25, .1], facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initial_time = pd.to_datetime(str( T_2m['init_time'])).replace(tzinfo=None).to_pydatetime() fcst_time = initial_time + timedelta(hours=T_2m['fhour']) #发布时间 if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5, '起报时间: ' + initial_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 5, '预报时间: ' + fcst_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 2.5, '预报时效: ' + str(T_2m['fhour']) + '小时', size=15) plt.text(2.5, 0.5, 'www.nmc.cn', size=15) # add color bar if (T_2m != None): cax = plt.axes([0.11, 0.06, .86, .02]) cb = plt.colorbar(plots['T_2m'], cax=cax, orientation='horizontal') cb.ax.tick_params(labelsize='x-large') cb.set_label(u'°C', size=20) # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[0.85, 0.13, .1, .2]) small_city = False if (map_extent2[1] - map_extent2[0] < 25): small_city = True if city: utl.add_city_on_map(ax, map_extent=map_extent2, transform=datacrs, zorder=110, size=13, small_city=small_city) utl.add_logo_extra_in_axes(pos=[-0.01, 0.835, .1, .1], which='nmc', size='Xlarge') # show figure if (output_dir != None): plt.savefig(output_dir + '最低温度_预报_' + '起报时间_' + initial_time.strftime("%Y年%m月%d日%H时") + '预报时效_' + str(T_2m['fhour']) + '小时' + '.png', dpi=200) if (output_dir == None): plt.show()
def draw_Time_Crossection_rh_uv_theta_e(rh_2D=None, u_2D=None, v_2D=None, theta_e_2D=None, t_range=None, output_dir=None): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # # 画图 # Define the figure object and primary axes fig = plt.figure(1, figsize=(16., 9.)) ax = plt.axes() # utl.add_public_title_sta(title=rh_2D.attrs['model']+'模式预报时间剖面',initial_time=rh_2D['forecast_reference_time'].values, fontsize=23) # Plot RH using contourf #rh_contour = ax.contourf(rh_2D['time'].values, rh_2D['level'].values, np.squeeze(rh_2D['data'].values.swapaxes(1,0)), # levels=np.arange(0, 106, 5), cmap='RdBu') rh_contour = ax.contourf(rh_2D['time'].values, rh_2D['level'].values, np.squeeze(rh_2D['data'].values.swapaxes(1, 0)), levels=np.arange(50, 100, 5), cmap='YlGnBu', extend='max', alpha=0.8) rh_colorbar = fig.colorbar(rh_contour) rh_colorbar.set_label('相对湿度(%)', size=15) ax.barbs(u_2D['time'].values, u_2D['level'].values, np.squeeze(u_2D['data'].values.swapaxes(1, 0)) * 2.5, np.squeeze(v_2D['data'].values.swapaxes(1, 0)) * 2.5, color='k') TMP_contour = ax.contour(theta_e_2D['time'].values, theta_e_2D['level'].values, np.squeeze(theta_e_2D.values.swapaxes(1, 0)), levels=np.arange(250, 450, 5), colors='#F4511E', linewidths=2) TMP_contour.clabel(TMP_contour.levels[1::2], fontsize=15, colors='#F4511E', inline=1, inline_spacing=8, fmt='%i', rightside_up=True, use_clabeltext=True) xstklbls = mpl.dates.DateFormatter('%m月%d日%H时') ax.xaxis.set_major_formatter(xstklbls) for label in ax.get_xticklabels(): label.set_rotation(30) label.set_fontsize(15) label.set_horizontalalignment('right') for label in ax.get_yticklabels(): label.set_fontsize(15) ax.set_yscale('symlog') ax.set_ylabel('高度 (hPa)', fontsize=15) ax.set_yticklabels(np.arange(1000, 50, -100)) ax.set_yticks(np.arange(1000, 50, -100)) ax.set_ylim(rh_2D['level'].values.max(), rh_2D['level'].values.min()) ax.set_xlim([rh_2D['time'].values[0], rh_2D['time'].values[-1]]) #forecast information bax = plt.axes([0.10, 0.88, .25, .07], facecolor='#FFFFFFCC') bax.axis('off') bax.axis([0, 10, 0, 10]) initial_time = pd.to_datetime(str( rh_2D['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5, '起报时间: ' + initial_time.strftime("%Y年%m月%d日%H时"), size=11) plt.text(2.5, 5.0, '[' + str(rh_2D.attrs['model']) + ']' + '模式时间剖面', size=11) plt.text(2.5, 2.5, '预报点: ' + str(rh_2D.attrs['points']['lon']) + ', ' + str(rh_2D.attrs['points']['lat']), size=11) plt.text(2.5, 0.5, 'www.nmc.cn', size=11) utl.add_logo_extra_in_axes(pos=[0.1, 0.88, .07, .07], which='nmc', size='Xlarge') ax.set_title('相当位温, 相对湿度, 水平风', loc='right', fontsize=23) #出图—————————————————————————————————————————————————————————— if (output_dir != None): plt.savefig(output_dir + '时间剖面产品_起报时间_' + str(rh_2D['forecast_reference_time'].values)[0:13] + '_预报时效_' + str(t_range[0]) + '_至_' + str(t_range[1]) + '.png', dpi=200, bbox_inches='tight') else: plt.show()
def draw_low_level_wind(uv=None, wsp=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True, city=True, south_China_sea=True, output_dir=None, Global=False): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # draw figure plt.figure(figsize=(16, 9)) # set data projection if (Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea( central_latitude=(map_extent[2] + map_extent[3]) / 2., central_longitude=(map_extent[0] + map_extent[1]) / 2., standard_parallels=[30., 60.]) ax = plt.axes([0.01, 0.1, .98, .84], projection=plotcrs) plt.title('[' + uv['model'] + '] ' + uv['lev'] + ' 风场, 风速', loc='left', fontsize=30) datacrs = ccrs.PlateCarree() #adapt to the map ratio map_extent2 = utl.adjust_map_ratio(ax, map_extent=map_extent, datacrs=datacrs) #adapt to the map ratio ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public(ax, name='coastline', edgecolor='gray', lw=0.8, zorder=105, alpha=0.5) if add_china: utl.add_china_map_2cartopy_public(ax, name='province', edgecolor='gray', lw=0.5, zorder=105) utl.add_china_map_2cartopy_public(ax, name='nation', edgecolor='black', lw=0.8, zorder=105) utl.add_china_map_2cartopy_public(ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=105, alpha=0.5) # define return plots plots = {} # draw mean sea level pressure if wsp is not None: x, y = np.meshgrid(wsp['lon'], wsp['lat']) z = np.squeeze(wsp['data']) cmap = dk_ctables.cm_wind_speed_nws() cmap.set_under(color=[0, 0, 0, 0], alpha=0.0) plots['wsp'] = ax.pcolormesh(x, y, z, cmap=cmap, zorder=90, transform=datacrs, alpha=0.5) # draw -hPa wind bards if uv is not None: x, y = np.meshgrid(uv['lon'], uv['lat']) u = np.squeeze(uv['udata']) * 2.5 v = np.squeeze(uv['vdata']) * 2.5 #plots['uv'] = ax.barbs( # x, y, u, v, length=6, regrid_shape=regrid_shape, # transform=datacrs, fill_empty=False, sizes=dict(emptybarb=0.05), # zorder=100) x, y = np.meshgrid(uv['lon'], uv['lat']) lw = 5 * wsp['data'] / wsp['data'].max() plots['stream'] = ax.streamplot(x, y, uv['udata'], uv['vdata'], density=2, color='r', linewidth=lw, zorder=100, transform=datacrs) spd_rtio = 0.03 for i in range(0, len(uv['lon']) - 1, 10): for j in range(0, len(uv['lat']) - 1, 10): ax.arrow(x[j, i], y[j, i], u[j, i] * spd_rtio, v[j, i] * spd_rtio, color='black', zorder=100, transform=datacrs, width=0.05) #ax.quiver(x[j,i], y[j,i], x[j,i]+u[j,i]*spd_rtio, y[j,i]+v[j,i]*spd_rtio, color='black', zorder=100, transform=datacrs) # grid lines gl = ax.gridlines(crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=40) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) #http://earthpy.org/cartopy_backgroung.html #C:\ProgramData\Anaconda3\Lib\site-packages\cartopy\data\raster\natural_earth ax.background_img(name='RD', resolution='high') #forecast information bax = plt.axes([0.01, 0.835, .25, .1], facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initial_time = pd.to_datetime(str( uv['init_time'])).replace(tzinfo=None).to_pydatetime() fcst_time = initial_time + timedelta(hours=uv['fhour']) #发布时间 if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5, '起报时间: ' + initial_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 5, '预报时间: ' + fcst_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 2.5, '预报时效: ' + str(uv['fhour']) + '小时', size=15) plt.text(2.5, 0.5, 'www.nmc.cn', size=15) # add color bar if (wsp != None): cax = plt.axes([0.11, 0.06, .86, .02]) cb = plt.colorbar(plots['wsp'], cax=cax, orientation='horizontal', extend='max', extendrect=False) cb.ax.tick_params(labelsize='x-large') cb.set_label('(m/s)', size=20) # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[0.85, 0.13, .1, .2]) small_city = False if (map_extent2[1] - map_extent2[0] < 25): small_city = True if city: utl.add_city_on_map(ax, map_extent=map_extent2, transform=datacrs, zorder=110, size=13, small_city=small_city) utl.add_logo_extra_in_axes(pos=[-0.01, 0.835, .1, .1], which='nmc', size='Xlarge') # show figure if (output_dir != None): plt.savefig(output_dir + '低层风_预报_' + '起报时间_' + initial_time.strftime("%Y年%m月%d日%H时") + '预报时效_' + str(uv['fhour']) + '小时' + '.png', dpi=200) if (output_dir == None): plt.show()
def draw_Time_Crossection_rh_uv_Temp(rh_2D=None, u_2D=None, v_2D=None, TMP_2D=None, terrain_2D=None, t_range=None, model=None, output_dir=None): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # # 画图 # Define the figure object and primary axes fig = plt.figure(1, figsize=(16., 9.)) ax = plt.axes() # utl.add_public_title_sta(title=rh_2D.attrs['model']+'模式预报时间剖面',initial_time=rh_2D['forecast_reference_time'].values, fontsize=23) # Plot RH using contourf #rh_contour = ax.contourf(rh_2D['time'].values, rh_2D['level'].values, np.squeeze(rh_2D['data'].values.swapaxes(1,0)), # levels=np.arange(0, 106, 5), cmap='RdBu') startcolor = '#1E90FF' #蓝色 midcolor = '#F1F1F1' #白色 endcolor = '#696969' #灰色 cmap2 = col.LinearSegmentedColormap.from_list( 'own2', [startcolor, midcolor, endcolor]) # extra arguments are N=256, gamma=1.0 cm.register_cmap(cmap=cmap2) rh_2D['data'].values[rh_2D['data'].values > 100] = 100 rh_contour = ax.contourf(rh_2D['time'].values, rh_2D['level'].values, np.squeeze(rh_2D['data'].values.swapaxes(1, 0)), levels=np.arange(0, 101, 0.5), cmap=cm.get_cmap('own2'), extend='max') rh_colorbar = fig.colorbar(rh_contour, ticks=[20, 40, 60, 80, 100]) rh_colorbar.set_label('相对湿度(%)', size=15) ax.barbs(u_2D['time'].values, u_2D['level'].values, np.squeeze(u_2D['data'].values.swapaxes(1, 0)) * 2.5, np.squeeze(v_2D['data'].values.swapaxes(1, 0)) * 2.5, color='k') TMP_contour = ax.contour(TMP_2D['time'].values, TMP_2D['level'].values, np.squeeze(TMP_2D['data'].values.swapaxes(1, 0)), levels=np.arange(-100, 100, 2), colors='#F4511E', linewidths=1) TMP_contour.clabel(TMP_contour.levels[1::2], fontsize=12, colors='#F4511E', inline=1, inline_spacing=8, fmt='%i', rightside_up=True, use_clabeltext=True) TMP_contour_zero = ax.contour(TMP_2D['time'].values, TMP_2D['level'].values, np.squeeze(TMP_2D['data'].values.swapaxes( 1, 0)), levels=[0], colors='k', linewidths=2) TMP_contour_zero.clabel([0], fontsize=22, colors='k', inline=1, inline_spacing=8, fmt='%i', rightside_up=True, use_clabeltext=True) startcolor = '#8B4513' #棕色 endcolor = '#DAC2AD' #绿 cmap2 = col.LinearSegmentedColormap.from_list('own3', [endcolor, startcolor]) # extra arguments are N=256, gamma=1.0 cm.register_cmap(cmap=cmap2) if (terrain_2D.values.max() > 0): terrain_contour = ax.contourf(terrain_2D['time'].values, terrain_2D['level'].values, np.squeeze( terrain_2D.values.swapaxes(1, 0)), levels=np.arange(0, terrain_2D.values.max(), 0.1), cmap=cm.get_cmap('own3'), zorder=100) xstklbls = mpl.dates.DateFormatter('%m月%d日%H时') ax.xaxis.set_major_formatter(xstklbls) for label in ax.get_xticklabels(): label.set_rotation(30) label.set_fontsize(15) label.set_horizontalalignment('right') for label in ax.get_yticklabels(): label.set_fontsize(15) ax.set_yscale('symlog') ax.set_ylabel('高度 (hPa)', fontsize=15) ax.set_yticklabels(np.arange(1000, 50, -100)) ax.set_yticks(np.arange(1000, 50, -100)) ax.set_ylim(rh_2D['level'].values.max(), rh_2D['level'].values.min()) ax.set_xlim([rh_2D['time'].values[0], rh_2D['time'].values[-1]]) #forecast information bax = plt.axes([0.10, 0.88, .25, .07], facecolor='#FFFFFFCC') bax.axis('off') bax.axis([0, 10, 0, 10]) initial_time = pd.to_datetime(str( rh_2D['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5, '起报时间: ' + initial_time.strftime("%Y年%m月%d日%H时"), size=11) plt.text(2.5, 5.0, '[' + str(rh_2D.attrs['model']) + ']' + '模式时间剖面', size=11) plt.text(2.5, 2.5, '预报点: ' + str(rh_2D.attrs['points']['lon']) + ', ' + str(rh_2D.attrs['points']['lat']), size=11) plt.text(2.5, 0.5, 'www.nmc.cn', size=11) utl.add_logo_extra_in_axes(pos=[0.1, 0.88, .07, .07], which='nmc', size='Xlarge') ax.set_title('[' + model + '] ' + '温度, 相对湿度, 水平风', loc='right', fontsize=23) #出图—————————————————————————————————————————————————————————— if (output_dir != None): plt.savefig(output_dir + '时间剖面产品_起报时间_' + str(rh_2D['forecast_reference_time'].values)[0:13] + '_预报时效_' + str(t_range[0]) + '_至_' + str(t_range[1]) + '.png', dpi=200, bbox_inches='tight') else: plt.show()
def box_line_wsp(wsp=None, output_dir=None, points=None, extra_info=None): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') initTime = pd.to_datetime(str( wsp['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() # draw figure fig = plt.figure(figsize=(16, 4.5)) # draw main figure #10米风—————————————————————————————————————— ax = plt.axes([0.1, 0.28, .8, .62]) utl.add_public_title_sta( title=wsp.attrs['model'] + '预报 ' + extra_info['point_name'] + ' [' + str(points['lon'][0]) + ',' + str(points['lat'][0]) + ']', initTime=initTime, fontsize=21) for ifhour in wsp['forecast_period'].values: if (ifhour == wsp['forecast_period'].values[0]): if (ifhour % 12 == 0): uv_t = (initTime + timedelta(hours=ifhour)).strftime('%m月%d日%H时') else: uv_t = ' ' else: if (ifhour % 12 == 0): uv_t = np.append( uv_t, (initTime + timedelta(hours=ifhour)).strftime('%m月%d日%H时')) else: uv_t = np.append(uv_t, ' ') labels = uv_t ax.boxplot(np.transpose(np.squeeze(wsp['data'].values)), labels=labels, meanline=True, showmeans=True, showfliers=False, whis=(0, 100)) warning = np.zeros(len(uv_t)) + 20. warning_t = np.arange(0, len(uv_t)) + 1 ax.plot(warning_t, warning, c='red', label=' ', linewidth=1) ax.set_ylim(0, math.ceil(wsp['data'].values.max() / 2) * 2) #plt.xlim(uv_t[0],uv_t[-1]) # add legend #ax.legend(fontsize=15,loc='upper right') ax.tick_params(length=7) ax.tick_params(axis='y', labelsize=100) for label in ax.get_xticklabels(): label.set_rotation(30) label.set_horizontalalignment('center') ax.tick_params(axis='y', labelsize=15) ax.tick_params(axis='x', labelsize=10) miloc = mpl.dates.HourLocator(byhour=(8, 11, 14, 17, 20, 23, 2, 5)) #单位是小时 ax.xaxis.set_minor_locator(miloc) yminorLocator = MultipleLocator(1) #将此y轴次刻度标签设置为1的倍数 ax.yaxis.set_minor_locator(yminorLocator) ymajorLocator = MultipleLocator(2) #将此y轴次刻度标签设置为1的倍数 ax.yaxis.set_major_locator(ymajorLocator) ax.grid(axis='x', ls='--') for label in ax.get_yticklabels(): label.set_fontsize(15) #ax.axis['left'].major_ticklabels.set_fontsize(15) t_gap = wsp['forecast_period'].values[1] - wsp['forecast_period'].values[0] ax.set_ylabel('风速 (m s$^-$$^1$)', fontsize=15) utl.add_logo_extra_in_axes(pos=[0.87, 0.00, .1, .1], which='nmc', size='Xlarge') #出图—————————————————————————————————————————————————————————— if (output_dir != None): isExists = os.path.exists(output_dir) if not isExists: os.makedirs(output_dir) output_dir2 = output_dir + wsp.attrs[ 'model'] + '_起报时间_' + initTime.strftime("%Y年%m月%d日%H时") + '/' if (os.path.exists(output_dir2) == False): os.makedirs(output_dir2) plt.savefig(output_dir2 + wsp.attrs['model'] + '_' + extra_info['point_name'] + '_' + extra_info['output_head_name'] + initTime.strftime("%Y%m%d%H") + '00' + extra_info['output_tail_name'] + '_风速_箱线图' + '.jpg', dpi=200, bbox_inches='tight') else: plt.show()
def draw_Miller_Composite_Chart(fcst_info=None, u_300=None, v_300=None, u_500=None, v_500=None, u_850=None, v_850=None, pmsl_change=None, hgt_500_change=None, Td_dep_700=None, Td_sfc=None, pmsl=None, lifted_index=None, vort_adv_500_smooth=None, map_extent=(50, 150, 0, 65), add_china=True, city=True, south_China_sea=True, output_dir=None, Global=False): # set font plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # set figure plt.figure(figsize=(16, 9)) if (Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea( central_latitude=(map_extent[2] + map_extent[3]) / 2., central_longitude=(map_extent[0] + map_extent[1]) / 2., standard_parallels=[30., 60.]) datacrs = ccrs.PlateCarree() ax = plt.axes([0.01, 0.1, .98, .84], projection=plotcrs) map_extent2 = utl.adjust_map_ratio(ax, map_extent=map_extent, datacrs=datacrs) #draw data plots = {} lons = fcst_info['lon'] lats = fcst_info['lat'] cs1 = ax.contour(lons, lats, lifted_index, range(-8, -2, 2), transform=ccrs.PlateCarree(), colors='red', linewidths=0.75, linestyles='solid', zorder=7) cs1.clabel(fontsize=10, inline=1, inline_spacing=7, fmt='%i', rightside_up=True, use_clabeltext=True) # Plot Surface pressure falls cs2 = ax.contour(lons, lats, pmsl_change.to('hPa'), range(-10, -1, 4), transform=ccrs.PlateCarree(), colors='k', linewidths=0.75, linestyles='dashed', zorder=6) cs2.clabel(fontsize=10, inline=1, inline_spacing=7, fmt='%i', rightside_up=True, use_clabeltext=True) # Plot 500-hPa height falls cs3 = ax.contour(lons, lats, hgt_500_change, range(-60, -29, 15), transform=ccrs.PlateCarree(), colors='k', linewidths=0.75, linestyles='solid', zorder=5) cs3.clabel(fontsize=10, inline=1, inline_spacing=7, fmt='%i', rightside_up=True, use_clabeltext=True) # Plot surface pressure ax.contourf(lons, lats, pmsl.to('hPa'), range(990, 1011, 20), alpha=0.5, transform=ccrs.PlateCarree(), colors='yellow', zorder=1) # Plot surface dewpoint ax.contourf(lons, lats, Td_sfc.to('degF'), range(65, 76, 10), alpha=0.4, transform=ccrs.PlateCarree(), colors=['green'], zorder=2) # Plot 700-hPa dewpoint depression ax.contourf(lons, lats, Td_dep_700, range(15, 46, 30), alpha=0.5, transform=ccrs.PlateCarree(), colors='tan', zorder=3) # Plot Vorticity Advection ax.contourf(lons, lats, vort_adv_500_smooth, range(5, 106, 100), alpha=0.5, transform=ccrs.PlateCarree(), colors='BlueViolet', zorder=4) # Define a skip to reduce the barb point density skip_300 = (slice(None, None, 12), slice(None, None, 12)) skip_500 = (slice(None, None, 10), slice(None, None, 10)) skip_850 = (slice(None, None, 8), slice(None, None, 8)) x, y = np.meshgrid(fcst_info['lon'], fcst_info['lat']) # 300-hPa wind barbs jet300 = ax.barbs(x[skip_300], y[skip_300], u_300[skip_300].m, v_300[skip_300].m, length=6, transform=ccrs.PlateCarree(), color='green', zorder=10, label='300-hPa Jet Core Winds (m/s)') # 500-hPa wind barbs jet500 = ax.barbs(x[skip_500], y[skip_500], u_500[skip_500].m, v_500[skip_500].m, length=6, transform=ccrs.PlateCarree(), color='blue', zorder=9, label='500-hPa Jet Core Winds (m/s)') # 850-hPa wind barbs jet850 = ax.barbs(x[skip_850], y[skip_850], u_850[skip_850].m, v_850[skip_850].m, length=6, transform=ccrs.PlateCarree(), color='k', zorder=8, label='850-hPa Jet Core Winds (m/s)') #additional information plt.title('[' + fcst_info['model'] + '] ' + 'Miller 综合分析图', loc='left', fontsize=30) ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public(ax, name='coastline', edgecolor='gray', lw=0.8, zorder=105, alpha=0.5) if add_china: utl.add_china_map_2cartopy_public(ax, name='province', edgecolor='gray', lw=0.5, zorder=105) utl.add_china_map_2cartopy_public(ax, name='nation', edgecolor='black', lw=0.8, zorder=105) utl.add_china_map_2cartopy_public(ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=105, alpha=0.5) gl = ax.gridlines(crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=40) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) utl.add_cartopy_background(ax, name='RD') l, b, w, h = ax.get_position().bounds # Legend purple = mpatches.Patch(color='BlueViolet', label='Cyclonic Absolute Vorticity Advection') yellow = mpatches.Patch(color='yellow', label='Surface MSLP < 1010 hPa') green = mpatches.Patch(color='green', label='Surface Td > 65 F') tan = mpatches.Patch(color='tan', label='700 hPa Dewpoint Depression > 15 C') red_line = lines.Line2D([], [], color='red', label='Best Lifted Index (C)') dashed_black_line = lines.Line2D( [], [], linestyle='dashed', color='k', label='12-hr Surface Pressure Falls (hPa)') black_line = lines.Line2D([], [], linestyle='solid', color='k', label='12-hr 500-hPa Height Falls (m)') leg = plt.legend(handles=[ jet300, jet500, jet850, dashed_black_line, black_line, red_line, purple, tan, green, yellow ], loc=3, title='Composite Analysis Valid: ', framealpha=1) leg.set_zorder(100) #forecast information bax = plt.axes([l, b + h - 0.1, .25, .1], facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initTime = pd.to_datetime(str( fcst_info['forecast_reference_time'])).replace( tzinfo=None).to_pydatetime() fcst_time = initTime + timedelta(hours=fcst_info['forecast_period']) #发布时间 if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5, '起报时间: ' + initTime.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 5, '预报时间: ' + fcst_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 2.5, '预报时效: ' + str(fcst_info['forecast_period']) + '小时', size=15) plt.text(2.5, 0.5, 'www.nmc.cn', size=15) # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[l + w - 0.091, b, .1, .2]) small_city = False if (map_extent2[1] - map_extent2[0] < 25): small_city = True if city: utl.add_city_on_map(ax, map_extent=map_extent2, transform=datacrs, zorder=110, size=13, small_city=small_city) utl.add_logo_extra_in_axes(pos=[l - 0.02, b + h - 0.1, .1, .1], which='nmc', size='Xlarge') # show figure if (output_dir != None): plt.savefig(output_dir + 'Miller_综合图_预报_' + '起报时间_' + initTime.strftime("%Y年%m月%d日%H时") + '预报时效_' + str(fcst_info['forecast_period']) + '小时' + '.png', dpi=200, bbox_inches='tight') plt.close() if (output_dir == None): plt.show()
def draw_PV_Div_uv(pv=None, uv=None, div=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True, city=False, south_China_sea=True, output_dir=None, Global=False): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # draw figure plt.figure(figsize=(16, 9)) # set data projection if (Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea( central_latitude=(map_extent[2] + map_extent[3]) / 2., central_longitude=(map_extent[0] + map_extent[1]) / 2., standard_parallels=[30., 60.]) ax = plt.axes([0.01, 0.1, .98, .84], projection=plotcrs) plt.title('[' + pv.attrs['model'] + '] ' + str(int(pv['level'])) + 'hPa 位涡扰动, 风场, 散度', loc='left', fontsize=30) datacrs = ccrs.PlateCarree() #adapt to the map ratio map_extent2 = utl.adjust_map_ratio(ax, map_extent=map_extent, datacrs=datacrs) #adapt to the map ratio ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public(ax, name='coastline', edgecolor='gray', lw=0.8, zorder=5, alpha=0.5) if add_china: utl.add_china_map_2cartopy_public(ax, name='province', edgecolor='gray', lw=0.5, zorder=5) utl.add_china_map_2cartopy_public(ax, name='nation', edgecolor='black', lw=0.8, zorder=5) utl.add_china_map_2cartopy_public(ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=5, alpha=0.5) # define return plots plots = {} # draw mean sea level pressure if div is not None: x, y = np.meshgrid(div['lon'], div['lat']) z = np.squeeze(div['data']) clevs_div = np.arange(-15, 16, 1) # plots['div'] = ax.contourf( # x, y, z*1e5,clevs_div,cmap=plt.cm.PuOr, # transform=datacrs,alpha=0.5, zorder=1,extend='both') cmap = dk_ctables2.ncl_cmaps('hotcolr_19lev') plots['div'] = ax.contourf(x, y, z * 1e5, levels=clevs_div[:], vmin=-15, vmax=15, cmap=cmap, transform=datacrs, alpha=0.5, zorder=1, extend='both') # draw -hPa wind bards if uv is not None: x, y = np.meshgrid(uv['lon'], uv['lat']) u = np.squeeze(uv['u'].values) * 2.5 v = np.squeeze(uv['v'].values) * 2.5 plots['uv'] = ax.barbs(x, y, u, v, length=6, regrid_shape=regrid_shape, transform=datacrs, fill_empty=False, sizes=dict(emptybarb=0.05), zorder=2) # draw -hPa geopotential height if pv is not None: x, y = np.meshgrid(pv['lon'], pv['lat']) clevs_pv = np.arange(4, 25, 1) plots['pv'] = ax.contour(x, y, np.squeeze(pv['data']) * 1e6, clevs_pv, colors='black', linewidths=2, transform=datacrs, zorder=3) plt.clabel(plots['pv'], inline=1, fontsize=20, fmt='%.0f', colors='black') # grid lines gl = ax.gridlines(crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=4) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) utl.add_cartopy_background(ax, name='RD') l, b, w, h = ax.get_position().bounds #forecast information bax = plt.axes([l, b + h - 0.1, .25, .1], facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initTime = pd.to_datetime(str( pv['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() fcst_time = initTime + timedelta(hours=pv['forecast_period'].values[0]) #发布时间 if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5, '起报时间: ' + initTime.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 5, '预报时间: ' + fcst_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 2.5, '预报时效: ' + str(int(pv.coords['forecast_period'].values[0])) + '小时', size=15) plt.text(2.5, 0.5, 'www.nmc.cn', size=15) # add color bar if (div != None): cax = plt.axes([l, b - 0.04, w, .02]) cb = plt.colorbar(plots['div'], cax=cax, orientation='horizontal', ticks=clevs_div[:], extend='both', extendrect=False) cb.ax.tick_params(labelsize='x-large') cb.set_label('Divergence ($10^5$ s$^{-1}$)', size=20) # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[l + w - 0.091, b, .1, .2]) small_city = False if (map_extent2[1] - map_extent2[0] < 25): small_city = True if city: utl.add_city_on_map(ax, map_extent=map_extent2, transform=datacrs, zorder=110, size=13, small_city=small_city) utl.add_logo_extra_in_axes(pos=[l - 0.02, b + h - 0.1, .1, .1], which='nmc', size='Xlarge') # show figure if (output_dir != None): plt.savefig(output_dir + '位涡_风场_散度_预报_' + '起报时间_' + initTime.strftime("%Y年%m月%d日%H时") + '预报时效_' + str(pv.coords['forecast_period'].values[0]) + '小时' + '.png', dpi=200, bbox_inches='tight') plt.close() if (output_dir == None): plt.show()
def draw_Rain_evo( rain=None,fcs_lvl=4, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True,city=True,south_China_sea=True, output_dir=None,Global=False): # set font plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) if(sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if(sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') # set figure plt.figure(figsize=(16,9)) if(Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea(central_latitude=(map_extent[2]+map_extent[3])/2., central_longitude=(map_extent[0]+map_extent[1])/2., standard_parallels=[30., 60.]) ax = plt.axes([0.01,0.1,.98,.84], projection=plotcrs) datacrs = ccrs.PlateCarree() map_extent2=utl.adjust_map_ratio(ax,map_extent=map_extent,datacrs=datacrs) plt.title('['+rain.attrs['model']+'] 预报逐'+ str(rain.attrs['t_gap'])+'小时'+str(fcs_lvl)+'mm降水范围演变', loc='left', fontsize=30) #draw data plots = {} if rain is not None: x, y = np.meshgrid(rain['lon'], rain['lat']) for itime in range(0,len(rain['time'].values)): z=np.squeeze(rain['data'].values[itime,:,:]) z[z<=0.1]=np.nan initTime = pd.to_datetime(str(rain.coords['forecast_reference_time'].values)).replace(tzinfo=None).to_pydatetime() labels=(initTime+timedelta(hours=rain.coords['forecast_period'].values[itime])).strftime("%m月%d日%H时") cmap=mpl.cm.jet per_color=utl.get_part_clev_and_cmap(cmap=cmap,clev_range=[0,len(rain['time'].values)],clev_slt=itime) ax.contourf( x,y,z, levels=[fcs_lvl,800], colors=per_color, zorder=3,transform=datacrs, alpha=0.2+itime*((1-0.2)/len(rain['time'].values))) if(itime == 0): label_handles = [mpatches.Patch(color=per_color.reshape(4), alpha=0.2+itime*((1-0.2)/len(rain['time'].values)), label=labels)] else: label_handles.append(mpatches.Patch(color=per_color.reshape(4),alpha=0.2+itime*((1-0.2)/len(rain['time'].values)), label=labels)) leg = plt.legend(handles=label_handles, loc=3,framealpha=1) #additional information ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public( ax, name='coastline', edgecolor='gray', lw=0.8, zorder=1,alpha=0.5) if add_china: utl.add_china_map_2cartopy_public( ax, name='province', edgecolor='gray', lw=0.5, zorder=1) utl.add_china_map_2cartopy_public( ax, name='nation', edgecolor='black', lw=0.8, zorder=1) utl.add_china_map_2cartopy_public( ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=1,alpha=0.5) # grid lines gl = ax.gridlines( crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=1) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) utl.add_cartopy_background(ax,name='RD') l, b, w, h = ax.get_position().bounds #forecast information bax=plt.axes([l,b+h-0.1,.25,.1],facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initTime = pd.to_datetime( str(rain.coords['forecast_reference_time'].values)).replace(tzinfo=None).to_pydatetime() fcst_time=initTime+timedelta(hours=rain.coords['forecast_period'].values[0]) #发布时间 if(sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if(sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5,'起报时间: '+initTime.strftime("%Y年%m月%d日%H时"),size=15) plt.text(2.5, 5,'起始时间: '+ (initTime+timedelta(hours=rain.coords['forecast_period'].values[0])).strftime("%Y年%m月%d日%H时"),size=15) plt.text(2.5, 2.5,'终止时间: '+ (initTime+timedelta(hours=rain.coords['forecast_period'].values[1])).strftime("%Y年%m月%d日%H时"),size=15) plt.text(2.5, 0.5,'www.nmc.cn',size=15) # add color bar # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[l+w-0.091,b,.1,.2]) small_city=False if(map_extent2[1]-map_extent2[0] < 25): small_city=True if city: utl.add_city_on_map(ax,map_extent=map_extent2,transform=datacrs,zorder=110,size=13,small_city=small_city) utl.add_logo_extra_in_axes(pos=[l-0.02,b+h-0.1,.1,.1],which='nmc', size='Xlarge') # show figure if(output_dir != None): plt.savefig(output_dir+'海平面气压_降水_预报_'+ '起报时间_'+initTime.strftime("%Y年%m月%d日%H时")+ '预报时效_'+str(int(rain.coords['forecast_period'].values[0]))+'小时'+'.png', dpi=200) if(output_dir == None): plt.show()
def draw_gh_uv_wvfl(gh=None, uv=None, wvfl=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True, city=True, south_China_sea=True, output_dir=None, Global=False): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # draw figure plt.figure(figsize=(16, 9)) # set data projection if (Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea( central_latitude=(map_extent[2] + map_extent[3]) / 2., central_longitude=(map_extent[0] + map_extent[1]) / 2., standard_parallels=[30., 60.]) ax = plt.axes([0.01, 0.1, .98, .84], projection=plotcrs) plt.title('[' + gh['model'] + '] ' + gh['lev'] + 'hPa 位势高度场, ' + uv['lev'] + 'hPa 风场, ' + wvfl['lev'] + 'hPa 水汽通量', loc='left', fontsize=30) datacrs = ccrs.PlateCarree() #adapt to the map ratio map_extent2 = utl.adjust_map_ratio(ax, map_extent=map_extent, datacrs=datacrs) #adapt to the map ratio ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public(ax, name='coastline', edgecolor='gray', lw=0.8, zorder=105, alpha=0.5) if add_china: utl.add_china_map_2cartopy_public(ax, name='province', edgecolor='gray', lw=0.5, zorder=105) utl.add_china_map_2cartopy_public(ax, name='nation', edgecolor='black', lw=0.8, zorder=105) utl.add_china_map_2cartopy_public(ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=105, alpha=0.5) # define return plots plots = {} # draw mean sea level pressure if wvfl is not None: x, y = np.meshgrid(wvfl['lon'], wvfl['lat']) z = np.squeeze(wvfl['data']) / 10. #pos=[0, 2, 4, 6, 8, 10, 12, 14, 16, 20, 22] idx_nan = np.where(z < 5) z[idx_nan] = np.nan cmap, norm = gy_ctables.wvfl_ctable() cmap.set_under(color=[0, 0, 0, 0], alpha=0.0) plots['wvfl'] = ax.pcolormesh(x, y, z, cmap=cmap, norm=norm, zorder=100, transform=datacrs, alpha=0.5) # draw -hPa wind bards if uv is not None: x, y = np.meshgrid(uv['lon'], uv['lat']) u = np.squeeze(uv['udata']) * 2.5 v = np.squeeze(uv['vdata']) * 2.5 plots['uv'] = ax.barbs(x, y, u, v, length=6, regrid_shape=regrid_shape, transform=datacrs, fill_empty=False, sizes=dict(emptybarb=0.05), zorder=110) # draw -hPa geopotential height if gh is not None: x, y = np.meshgrid(gh['lon'], gh['lat']) clevs_gh = np.append( np.append( np.arange(0, 480, 4), np.append(np.arange(480, 584, 8), np.arange(580, 604, 4))), np.arange(604, 2000, 8)) plots['gh'] = ax.contour(x, y, np.squeeze(gh['data']), clevs_gh, colors='black', linewidths=2, transform=datacrs, zorder=110) plt.clabel(plots['gh'], inline=1, fontsize=20, fmt='%.0f', colors='black') # grid lines gl = ax.gridlines(crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=40) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) #http://earthpy.org/cartopy_backgroung.html #C:\ProgramData\Anaconda3\Lib\site-packages\cartopy\data\raster\natural_earth ax.background_img(name='RD', resolution='high') #forecast information bax = plt.axes([0.01, 0.835, .25, .1], facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initial_time = pd.to_datetime(str( gh['init_time'])).replace(tzinfo=None).to_pydatetime() fcst_time = initial_time + timedelta(hours=gh['fhour']) #发布时间 if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5, '起报时间: ' + initial_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 5, '预报时间: ' + fcst_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 2.5, '预报时效: ' + str(gh['fhour']) + '小时', size=15) plt.text(2.5, 0.5, 'www.nmc.cn', size=15) # add color bar if (wvfl != None): cax = plt.axes([0.11, 0.06, .86, .02]) cb = plt.colorbar(plots['wvfl'], cax=cax, orientation='horizontal') cb.ax.tick_params(labelsize='x-large') cb.set_label('Water Vapor Flux (0.1g/(cm*hPa*s)', size=20) # cb.set_ticks([0,4,8,12,16,20,24]) # cb.set_ticklabels(['0','4','8','12','16','20','24']) # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[0.85, 0.13, .1, .2]) small_city = False if (map_extent2[1] - map_extent2[0] < 25): small_city = True if city: utl.add_city_on_map(ax, map_extent=map_extent2, transform=datacrs, zorder=110, size=13, small_city=small_city) utl.add_logo_extra_in_axes(pos=[-0.01, 0.835, .1, .1], which='nmc', size='Xlarge') # show figure if (output_dir != None): plt.savefig(output_dir + '位势高度场_风场_水汽通量_预报_' + '起报时间_' + initial_time.strftime("%Y年%m月%d日%H时") + '预报时效_' + str(gh['fhour']) + '小时' + '.png', dpi=200) if (output_dir == None): plt.show()
def draw_cumulated_precip( rain=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True,city=True,south_China_sea=True, output_dir=None,Global=False): # set font plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # set figure fig = plt.figure(figsize=(9,14)) camera = Camera(fig) nframe=rain['data'].shape[0] plotcrs = ccrs.AlbersEqualArea(central_latitude=(map_extent[2]+map_extent[3])/2., central_longitude=(map_extent[0]+map_extent[1])/2., standard_parallels=[30., 60.]) datacrs = ccrs.PlateCarree() ax = plt.axes([0.01,0.1,.98,.84], projection=plotcrs) map_extent2=utl.adjust_map_ratio(ax,map_extent=map_extent,datacrs=datacrs) # define return plots plots = {} # draw mean sea level pressure if rain is not None: x, y = np.meshgrid(rain['lon'], rain['lat']) z=np.squeeze(rain['data'].values) z[z<0.1]=np.nan znan=np.zeros(shape=x.shape) znan[:]=np.nan # cmap,norm=dk_ctables.cm_qpf_nws(atime=None, # pos=np.concatenate(( # np.array([0, 0.1, 0.5, 1]), np.arange(2.5, 25, 2.5), # np.arange(25, 50, 5), np.arange(50, 150, 10), # np.arange(150, 800, 50)))) cmap,norm=dk_ctables.cm_qpf_nws(atime=24) cmap.set_under(color=[0,0,0,0],alpha=0.0) plots['rain'] = ax.pcolormesh( x,y,znan, norm=norm, cmap=cmap, zorder=1,transform=datacrs,alpha=0.5) #additional information plt.title('['+rain.attrs['model']+'] '+ str(int(rain.coords['forecast_period'].values[0]))+'至'+str(int(rain.coords['forecast_period'].values[-1]))+'时效累积降水预报', loc='left', fontsize=30) ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public( ax, name='coastline', edgecolor='gray', lw=0.8, zorder=3,alpha=0.5) if add_china: utl.add_china_map_2cartopy_public( ax, name='province', edgecolor='gray', lw=0.5, zorder=3) utl.add_china_map_2cartopy_public( ax, name='nation', edgecolor='black', lw=0.8, zorder=3) utl.add_china_map_2cartopy_public( ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=3,alpha=0.5) # grid lines gl = ax.gridlines( crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=1) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) utl.add_cartopy_background(ax,name='RD') l, b, w, h = ax.get_position().bounds #forecast information initTime = pd.to_datetime( str(rain.coords['forecast_reference_time'].values)).replace(tzinfo=None).to_pydatetime() #发布时间 if(sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if(sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') # add color bar cax=plt.axes([l,b-0.04,w,.02]) cb = plt.colorbar(plots['rain'], cax=cax, orientation='horizontal') cb.ax.tick_params(labelsize='x-large') cb.set_label('Precipitation (mm)',size=20) fcst_time=initTime+timedelta(hours=rain.coords['forecast_period'].values[0]) bax=plt.axes([l,b+h-0.07,.45,.07]) bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) fcst_time1=initTime+timedelta(hours=rain.coords['forecast_period'].values[0]-6) bax.text(2.5, 7.5,'起始时间: '+fcst_time1.strftime("%Y年%m月%d日%H时"),size=15) bax.text(2.5, 0.5,'www.nmc.cn',size=15) valid_fhour=bax.text(2.5, 5,'截至时间: ',size=15) txt_fhour=bax.text(2.5, 2.5,'预报时效: ',size=15) utl.add_logo_extra_in_axes(pos=[l-0.0,b+h-0.085,.1,.1],which='nmc', size='Xlarge') # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[l+w-0.091,b,.1,.2]) small_city=False if(map_extent2[1]-map_extent2[0] < 25): small_city=True if city: utl.add_city_on_map(ax,map_extent=map_extent2,transform=datacrs,zorder=2,size=13,small_city=small_city) fcst_time2=initTime+timedelta(hours=rain.coords['forecast_period'].values[-1]) valid_fhour.set_text('截至时间: '+fcst_time2.strftime("%Y年%m月%d日%H时")) txt_fhour.set_text('预报时效: '+str(int(rain.coords['forecast_period'].values[-1]))+'小时') ax.pcolormesh( x,y,np.squeeze(z[-1,:,:]), norm=norm, cmap=cmap, zorder=1,transform=datacrs,alpha=0.5) # plt.draw() plt.savefig(output_dir+ '起报时间_'+initTime.strftime("%Y年%m月%d日%H时")+ '预报时效_'+str(int(rain.coords['forecast_period'].values[-1]))+'小时_'+rain.attrs['model']+'.png', dpi=200,bbox_inches='tight')
def OBS_Sounding_GeopotentialHeight(IR=None, Sounding=None, HGT=None, map_extent=None, city=True, south_China_sea=True, output_dir=None, Channel='C009'): #if(sys.platform[0:3] == 'win'): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # draw figure plt.figure(figsize=(16, 9)) plotcrs = ccrs.AlbersEqualArea( central_latitude=(map_extent[2] + map_extent[3]) / 2., central_longitude=(map_extent[0] + map_extent[1]) / 2., standard_parallels=[30., 60.]) # draw main figure ax = plt.axes([0.01, 0.1, .98, .84], projection=plotcrs) datacrs = ccrs.PlateCarree() map_extent2 = adjust_map_ratio(ax, map_extent=map_extent, datacrs=datacrs) # plot map background ax.add_feature(cfeature.OCEAN) add_china_map_2cartopy_public(ax, name='coastline', edgecolor='gray', lw=0.8, zorder=2, alpha=0.5) add_china_map_2cartopy_public(ax, name='nation', edgecolor='black', lw=0.8, zorder=2) add_china_map_2cartopy_public(ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=2, alpha=0.5) # define return plots plots = {} # draw IR if IR is not None: x, y = np.meshgrid(IR['lon'], IR['lat']) z = np.squeeze(IR['image']) if (Channel == 'C009'): cmap = dk_ctables.cm_wv_enhancement() norm, cmap = colortables.get_with_range('WVCIMSS', 160, 300) title_name = '水汽图像' plots['IR'] = ax.pcolormesh(x, y, z, norm=norm, cmap=cmap, zorder=1, transform=datacrs) if (Channel == 'C012'): cmap = dk_ctables.cm_ir_enhancement1() title_name = '红外(10.8微米)' plots['IR'] = ax.pcolormesh(x - 10., y, z, vmin=105., vmax=335.0, cmap=cmap, zorder=1, transform=datacrs) plt.title('FY4A' + title_name + '观测' + ' 探空观测 高度场', loc='left', fontsize=30) if (Sounding is not None): x = np.squeeze(Sounding['lon'].values) y = np.squeeze(Sounding['lat'].values) idx_vld = np.where((Sounding['Wind_angle'].values != np.nan) & (Sounding['Wind_speed'].values != np.nan)) u, v = utl.wind2UV(Winddir=Sounding['Wind_angle'].values[idx_vld], Windsp=Sounding['Wind_speed'].values[idx_vld]) idx_null = np.where((u > 100) | (v > 100)) u[idx_null] = np.nan v[idx_null] = np.nan c_barb = {'C009': 'black', 'C012': 'white'} plots['uv'] = ax.barbs(x, y, u, v, transform=datacrs, fill_empty=False, sizes=dict(emptybarb=0.0), barb_increments={ 'half': 2, 'full': 4, 'flag': 20 }, zorder=2, color=c_barb[Channel], alpha=0.7, lw=1.5, length=7) # draw mean sea level pressure if (HGT is not None): x, y = np.meshgrid(HGT['lon'], HGT['lat']) clevs = np.append(np.arange(480, 584, 8), np.arange(580, 604, 4)) plots_HGT = ax.contour(x, y, ndimage.gaussian_filter(np.squeeze( HGT['data']), sigma=1, order=0), levels=clevs, colors='black', alpha=1, zorder=3, transform=datacrs, linewidths=3) ax.clabel(plots_HGT, inline=1, fontsize=20, fmt='%.0f') ax.contour(x, y, ndimage.gaussian_filter(np.squeeze(HGT['data']), sigma=1, order=0), levels=[588], colors='black', alpha=1, zorder=3, transform=datacrs, linewidths=6) #if city: gl = ax.gridlines(crs=datacrs, linewidth=1, color='gray', alpha=0.5, linestyle='--', zorder=40) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) #utl.add_cartopy_background(ax,name='RD') l, b, w, h = ax.get_position().bounds if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') IR_time = pd.to_datetime( IR.coords['time'].values[0]).to_pydatetime() + timedelta(hours=8) Sounding_time = Sounding['time'][0].to_pydatetime() HGT_initTime = pd.to_datetime( str(HGT.coords['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() HGT_time = HGT_initTime + timedelta( hours=HGT.coords['forecast_period'].values[0]) #logo bax = plt.axes([l, b + h - 0.1, .25, .1], facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) add_logo_extra_in_axes(pos=[l - 0.02, b + h - 0.1, .1, .1], which='nmc', size='Xlarge') bax.text(2.5, 7.5, '卫星图像观测时间: ' + IR_time.strftime("%Y年%m月%d日%H时"), size=12) bax.text(2.5, 5, '探空观测时间: ' + Sounding_time.strftime("%Y年%m月%d日%H时"), size=12) bax.text(2.5, 2.5, '高度场时间: ' + HGT_time.strftime("%Y年%m月%d日%H时"), size=12) bax.text(2.5, 0.5, 'www.nmc.cn', size=12) initial_time = pd.to_datetime(str( IR['time'].values[0])).replace(tzinfo=None).to_pydatetime() #发布时间 if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') # add color bar cax = plt.axes([l, b - 0.04, w, .02]) cb = plt.colorbar(plots['IR'], cax=cax, orientation='horizontal', extend='both', extendrect=False) cb.ax.tick_params(labelsize='x-large') cb.set_label('(K)', size=10) # add south China sea if south_China_sea: add_south_China_sea(pos=[l + w - 0.091, b, .1, .2]) small_city = False if (map_extent2[1] - map_extent2[0] < 25): small_city = True if city: add_city_on_map(ax, map_extent=map_extent2, transform=datacrs, zorder=2, size=16, small_city=small_city) # show figure if (output_dir != None): plt.savefig( output_dir + '卫星' + #'_'+initial_time.strftime("%Y年%m月%d日%H时")+ '卫星观测时间_' + pd.to_datetime(IR['time'].values[0]).strftime("%Y年%m月%d日%H时") + '.png', dpi=200, bbox_inches='tight') plt.close() if (output_dir == None): plt.show()
def draw_wind_temp_according_to_4D_data(sta_fcs_fcst=None, zd_fcst_obs=None, fcst_info=None, map_extent=(50, 150, 0, 65), bkgd_type='satellite', bkgd_level=None, draw_zd=True, output_dir=None): # set font plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # set figure plt.figure(figsize=(16, 9)) plotcrs = ccrs.PlateCarree() ax = plt.axes([0.01, 0.1, .98, .84], projection=plotcrs) if (bkgd_type == 'satellite'): c_city_names = 'black' c_sta_fcst = 'black' c_tile_str = '白色' else: c_city_names = 'black' c_sta_fcst = 'black' c_tile_str = '黑色' datacrs = ccrs.PlateCarree() ax.set_extent(map_extent, crs=datacrs) # draw data plots = {} if (bkgd_type == 'satellite'): request = utl.TDT_img() #卫星图像 if (bkgd_type == 'terrain'): request = utl.TDT_ter() #卫星图像 if (bkgd_type == 'road'): request = utl.TDT() #卫星图像 ax.add_image(request, bkgd_level) # level=10 缩放等级 #cmap=dk_ctables.cm_thetae() plots['t2m'] = ax.scatter(sta_fcs_fcst['lon'], sta_fcs_fcst['lat'], s=1900, c='white', alpha=1, zorder=120) cmap = dk_ctables.cm_temp() cmap.set_under(color=[0, 0, 0, 0], alpha=0.0) plots['t2m'] = ax.scatter(sta_fcs_fcst['lon'], sta_fcs_fcst['lat'], s=1700, c=sta_fcs_fcst['TMP'], vmin=-40, vmax=40, cmap=cmap, alpha=1, zorder=120) for ista in range(0, len(sta_fcs_fcst['lon'])): city_names = sta_fcs_fcst['name'][ista] ax.text(sta_fcs_fcst['lon'][ista] - 0.001, sta_fcs_fcst['lat'][ista], city_names + ' ', family='SimHei', ha='right', va='center', size=24, color=c_city_names, zorder=140) ax.text(sta_fcs_fcst['lon'][ista], sta_fcs_fcst['lat'][ista], '%i' % sta_fcs_fcst['TMP'][ista], family='SimHei', size=24, color='white', zorder=140, ha='center', va='center') plots['uv'] = ax.barbs(np.array(sta_fcs_fcst['lon']) - 0.001, np.array(sta_fcs_fcst['lat']), sta_fcs_fcst['U'], sta_fcs_fcst['V'], barb_increments={ 'half': 2, 'full': 4, 'flag': 20 }, length=12, linewidth=6, transform=datacrs, fill_empty=False, sizes=dict(emptybarb=0.01), zorder=130, color='white') plots['uv'] = ax.barbs(np.array(sta_fcs_fcst['lon']) - 0.001, np.array(sta_fcs_fcst['lat']), sta_fcs_fcst['U'], sta_fcs_fcst['V'], barb_increments={ 'half': 2, 'full': 4, 'flag': 20 }, length=12, linewidth=3, transform=datacrs, fill_empty=False, sizes=dict(emptybarb=0.01), zorder=130, color='black') if (draw_zd is True): plots['uv'] = ax.barbs(zd_fcst_obs['lon'], zd_fcst_obs['lat'], zd_fcst_obs['U'], zd_fcst_obs['V'], barb_increments={ 'half': 2, 'full': 4, 'flag': 20 }, length=10, linewidth=2.6, transform=datacrs, fill_empty=False, sizes=dict(emptybarb=0.01), zorder=100, color=c_sta_fcst, alpha=1) if (zd_fcst_obs['obs_valid'] is True): plots['uv'] = ax.barbs(zd_fcst_obs['lon'], zd_fcst_obs['lat'], zd_fcst_obs['U_obs'], zd_fcst_obs['V_obs'], barb_increments={ 'half': 2, 'full': 4, 'flag': 20 }, length=10, linewidth=2, transform=datacrs, fill_empty=False, sizes=dict(emptybarb=0.01), zorder=100, color='red', alpha=1) #additional information plt.title('基于EC模式降尺度预报 ' + '10米风(红色实况,' + c_tile_str + '预报), ' + '温度(圆形填色及数字)', loc='left', fontsize=20) l, b, w, h = ax.get_position().bounds bax = plt.axes([l, b + h - 0.1, .25, .1], facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initial_time = pd.to_datetime( str(fcst_info['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() fcst_time = initial_time + timedelta( hours=fcst_info['forecast_period'].values[0]) #发布时间 if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5, '起报时间: ' + initial_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 5, '预报时间: ' + fcst_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 2.5, '预报时效: ' + str(int(fcst_info['forecast_period'].values)) + '小时', size=15) plt.text(2.5, 0.5, 'www.nmc.cn', size=15) # add logo utl.add_logo_extra_in_axes(pos=[l - 0.02, b + h - 0.1, .1, .1], which='nmc', size='Xlarge') # add color bar cax = plt.axes([0.25, 0.06, .5, .02]) cb = plt.colorbar(plots['t2m'], cax=cax, orientation='horizontal') cb.ax.tick_params(labelsize='x-large') cb.set_label('温度 ($^\circ$C)', size=20) # show figure if (output_dir != None): plt.savefig(output_dir + 'BSEP_NMC_RFFC_ECMWF_EME_ASC_LNO_P9_' + initial_time.strftime("%Y%m%d%H") + '00' + str(int(fcst_info['forecast_period'].values[0])).zfill(3) + '03.jpg', dpi=200, bbox_inches='tight') if (output_dir == None): plt.show()
def draw_cumulative_precip_and_rain_days(cu_rain=None, days_rain=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True, city=True, south_China_sea=True, output_dir=None, Global=False): # set font plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # set figure plt.figure(figsize=(16, 9)) # plotcrs = ccrs.AlbersEqualArea(central_latitude=(map_extent[2]+map_extent[3])/2., # central_longitude=(map_extent[0]+map_extent[1])/2., standard_parallels=[30., 60.]) plotcrs = ccrs.PlateCarree() datacrs = ccrs.PlateCarree() ax = plt.axes([0.01, 0.1, .98, .84], projection=plotcrs) ax.set_extent(map_extent, crs=datacrs) #map_extent2=utl.adjust_map_ratio(ax,map_extent=map_extent,datacrs=datacrs) # define return plots plots = {} # draw mean sea level pressure #if(os.path.exists('L:/Temp/mask.npy')): # mask=np.load('L:/Temp/mask.npy') #else: #mask=dk_mask.grid_mask_china(cu_rain['lon'], cu_rain['lat']) #np.save('L:/Temp/mask',mask) # draw -hPa geopotential height if days_rain is not None: x, y = np.meshgrid(days_rain['lon'], days_rain['lat']) clevs_days = np.arange(2, np.nanmax(days_rain.values) + 1) z = gaussian_filter(np.squeeze(days_rain.values), 5) #z=z*mask plots['days_rain'] = ax.contour(x, y, z, clevs_days, colors='black', linewidths=2, transform=datacrs, zorder=3) plt_lbs = plt.clabel(plots['days_rain'], inline=2, fontsize=20, fmt='%.0f', colors='black') clip_days = utl.gy_China_maskout(plots['days_rain'], ax, plt_lbs) if cu_rain is not None: x, y = np.meshgrid(cu_rain['lon'], cu_rain['lat']) z = np.squeeze(cu_rain.values) clevs = [50, 100, 200, 300, 400, 500, 600] colors = [ '#6ab4f1', '#0001f6', '#f405ee', '#ffa900', '#fc6408', '#e80000', '#9a0001' ] linewidths = [1, 1, 2, 2, 3, 4, 4] cmap, norm = mpl.colors.from_levels_and_colors(clevs, colors, extend='max') plots['rain'] = ax.contourf(x, y, z, clevs, norm=norm, cmap=cmap, transform=datacrs, extend='max', alpha=0.1) plots['rain2'] = ax.contour(x, y, z, clevs, norm=norm, cmap=cmap, transform=datacrs, linewidths=linewidths) plt.setp(plots['rain2'].collections, path_effects=[ path_effects.SimpleLineShadow(), path_effects.Normal() ]) # plots['rain'] = ax.contourf(x,y,z, # cmap=cmap, zorder=1,transform=datacrs,alpha=0.5) clip_rain = utl.gy_China_maskout(plots['rain'], ax) clip_rain2 = utl.gy_China_maskout(plots['rain2'], ax) #additional information plt.title('过去' + str(int(days_rain.attrs['rn_ndays'])) + '天降水日数, ' + '过去' + str(int(cu_rain.attrs['cu_ndays'])) + '天累积降水量', loc='left', fontsize=30) ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public(ax, name='coastline', edgecolor='gray', lw=0.8, zorder=3, alpha=0.5) if add_china: utl.add_china_map_2cartopy_public(ax, name='province', edgecolor='black', lw=0.5, zorder=3) utl.add_china_map_2cartopy_public(ax, name='nation', edgecolor='black', lw=0.8, zorder=3) utl.add_china_map_2cartopy_public(ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=3, alpha=0.5) stamen_terrain = cimg.Stamen('terrain-background') ax.add_image(stamen_terrain, 6) # grid lines gl = ax.gridlines(crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=1) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) #utl.add_cartopy_background(ax,name='RD') ax.add_feature(cfeature.LAND, color='#F5E19F') ax.add_feature(cfeature.OCEAN) l, b, w, h = ax.get_position().bounds #forecast information bax = plt.axes([l, b + h - 0.05, .27, .05], facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initTime = pd.to_datetime( str(days_rain.coords['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() fcst_time = initTime + timedelta( hours=days_rain.coords['forecast_period'].values[0]) #发布时间 if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(1.5, 5.5, '观测截止时间: ' + initTime.strftime("%Y年%m月%d日%H时"), size=15) plt.text(1.5, 0.5, 'www.nmc.cn', size=18) # # add color bar # if(cu_rain is not None): # cax=plt.axes([l,b-0.04,w,.02]) # cb = plt.colorbar(plots['rain2'], cax=cax, orientation='horizontal') # cb.ax.tick_params(labelsize='x-large') # cb.set_label('累积降水量 (mm)',size=20) font = FontProperties(family='Microsoft YaHei', size=16) ax.legend([mpatches.Patch(color=b) for b in colors], [ '50~100 毫米', '100~200 毫米', '200-300 毫米', '300~400 毫米', '400~500 毫米', '500~600 毫米', '>=600毫米' ], prop=font, loc='lower left') # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[l + w - 0.091, b, .1, .2]) small_city = False #if(map_extent2[1]-map_extent2[0] < 25): # small_city=True if city: utl.add_city_on_map(ax, map_extent=map_extent, transform=datacrs, zorder=2, size=13, small_city=small_city) utl.add_logo_extra_in_axes(pos=[l - 0.01, b + h - 0.05, .06, .05], which='nmc', size='Xlarge') # show figure if (output_dir != None): plt.savefig(output_dir + '总降水_' + '观测时间_' + initTime.strftime("%Y年%m月%d日%H时") + '.png', dpi=200, bbox_inches='tight') plt.close() if (output_dir == None): plt.show()
def draw_gh_uv_VVEL(gh=None, uv=None, VVEL=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True, city=True, south_China_sea=True, output_dir=None, Global=False): plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # draw figure plt.figure(figsize=(16, 9)) # set data projection if (Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea( central_latitude=(map_extent[2] + map_extent[3]) / 2., central_longitude=(map_extent[0] + map_extent[1]) / 2., standard_parallels=[30., 60.]) ax = plt.axes([0.01, 0.1, .98, .84], projection=plotcrs) plt.title('[' + gh.attrs['model'] + '] ' + str(int(gh['level'].values[0])) + 'hPa 位势高度场, ' + str(int(uv['level'].values[0])) + 'hPa 风场和垂直气压速度', loc='left', fontsize=30) datacrs = ccrs.PlateCarree() #adapt to the map ratio map_extent2 = utl.adjust_map_ratio(ax, map_extent=map_extent, datacrs=datacrs) #adapt to the map ratio ax.add_feature(cfeature.OCEAN) utl.add_china_map_2cartopy_public(ax, name='coastline', edgecolor='gray', lw=0.8, zorder=5, alpha=0.5) if add_china: utl.add_china_map_2cartopy_public(ax, name='province', edgecolor='gray', lw=0.5, zorder=5) utl.add_china_map_2cartopy_public(ax, name='nation', edgecolor='black', lw=0.8, zorder=5) utl.add_china_map_2cartopy_public(ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=5, alpha=0.5) # define return plots plots = {} # draw mean sea level pressure if VVEL is not None: x, y = np.meshgrid(VVEL['lon'], VVEL['lat']) clevs_VVEL = [0.1, 4, 13, 25, 60, 120] clevs_VVEL = [ -30, -20, -10, -5, -2.5, -1, -0.5, 0.5, 1, 2.5, 5, 10, 20, 30 ] z = np.squeeze(VVEL['data'] / 10.) cmap, norm = dk_ctables.cm_vertical_velocity_nws(pos=clevs_VVEL) #cmap.set_under(color=[0,0,0,0],alpha=0.0) plots['VVEL'] = ax.pcolormesh(x, y, z, norm=norm, cmap=cmap, zorder=1, transform=datacrs, alpha=0.5) # draw -hPa wind bards if uv is not None: x, y = np.meshgrid(uv['lon'], uv['lat']) u = np.squeeze(uv['u']) * 2.5 v = np.squeeze(uv['v']) * 2.5 plots['uv'] = ax.barbs(x, y, u.values, v.values, length=6, regrid_shape=regrid_shape, transform=datacrs, fill_empty=False, sizes=dict(emptybarb=0.05), zorder=2) # draw -hPa geopotential height if gh is not None: x, y = np.meshgrid(gh['lon'], gh['lat']) clevs_gh = np.append( np.append( np.arange(0, 480, 4), np.append(np.arange(480, 584, 8), np.arange(580, 604, 4))), np.arange(604, 2000, 8)) plots['gh'] = ax.contour(x, y, np.squeeze(gh['data']), clevs_gh, colors='black', linewidths=2, transform=datacrs, zorder=3) plt.clabel(plots['gh'], inline=1, fontsize=20, fmt='%.0f', colors='black') # grid lines gl = ax.gridlines(crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=4) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) utl.add_cartopy_background(ax, name='RD') #forecast information l, b, w, h = ax.get_position().bounds #forecast information bax = plt.axes([l, b + h - 0.1, .25, .1], facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initTime = pd.to_datetime(str( gh.coords['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() fcst_time = initTime + timedelta( hours=gh.coords['forecast_period'].values[0]) #发布时间 if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5, '起报时间: ' + initTime.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 5, '预报时间: ' + fcst_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 2.5, '预报时效: ' + str(int(gh.coords['forecast_period'].values[0])) + '小时', size=15) plt.text(2.5, 0.5, 'www.nmc.cn', size=15) # add color bar if (VVEL != None): cax = plt.axes([l, b - 0.04, w, .02]) cb = plt.colorbar(plots['VVEL'], cax=cax, orientation='horizontal', ticks=clevs_VVEL[:], extend='max', extendrect=False) cb.ax.tick_params(labelsize='x-large') cb.set_label('Vertical Velocity (0.1Pa/s)', size=20) # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[l + w - 0.091, b, .1, .2]) small_city = False if (map_extent2[1] - map_extent2[0] < 25): small_city = True if city: utl.add_city_on_map(ax, map_extent=map_extent2, transform=datacrs, zorder=110, size=13, small_city=small_city) utl.add_logo_extra_in_axes(pos=[l - 0.02, b + h - 0.1, .1, .1], which='nmc', size='Xlarge') # show figure if (output_dir != None): plt.savefig(output_dir + '高度场_风场_垂直气压速度_预报_' + '起报时间_' + initTime.strftime("%Y年%m月%d日%H时") + '预报时效_' + str(gh.coords['forecast_period'].values[0]) + '小时' + '.png', dpi=200, bbox_inches='tight') if (output_dir == None): plt.show()
def draw_mslp_gust10m_uv10m(gust=None, mslp=None, uv10m=None, map_extent=(50, 150, 0, 65), regrid_shape=20, add_china=True, city=True, south_China_sea=True, output_dir=None, Global=False): # set font plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) # set figure plt.figure(figsize=(16, 9)) if (Global == True): plotcrs = ccrs.Robinson(central_longitude=115.) else: plotcrs = ccrs.AlbersEqualArea( central_latitude=(map_extent[2] + map_extent[3]) / 2., central_longitude=(map_extent[0] + map_extent[1]) / 2., standard_parallels=[30., 60.]) datacrs = ccrs.PlateCarree() ax = plt.axes([0.01, 0.1, .98, .84], projection=plotcrs) map_extent2 = utl.adjust_map_ratio(ax, map_extent=map_extent, datacrs=datacrs) #draw data plots = {} if gust is not None: x, y = np.meshgrid(gust['lon'], gust['lat']) z = np.squeeze(gust['data'].values) cmap = dk_ctables.cm_wind_speed_nws() cmap.set_under(color=[0, 0, 0, 0], alpha=0.0) z[z < 7.9] = np.nan plots['gust'] = ax.pcolormesh(x, y, z, cmap=cmap, vmin=7.9, vmax=65, zorder=1, transform=datacrs, alpha=0.5) ax.quiver(x, y, np.squeeze(uv10m['u10m'].values), np.squeeze(uv10m['v10m'].values), transform=datacrs, regrid_shape=40, width=0.001) if mslp is not None: x, y = np.meshgrid(mslp['lon'], mslp['lat']) clevs_mslp = np.arange(900, 1100, 2.5) z = gaussian_filter(np.squeeze(mslp['data']), 5) plots['mslp'] = ax.contour(x, y, z, clevs_mslp, colors='black', linewidths=1, transform=datacrs, zorder=2, alpha=0.5) cl = plt.clabel(plots['mslp'], inline=1, fontsize=15, fmt='%.1f', colors='black') for t in cl: t.set_path_effects([ path_effects.Stroke(linewidth=3, foreground='white'), path_effects.Normal() ]) #+画高低压中心 res = mslp['lon'].values[1] - mslp['lon'].values[0] nwindow = int(9.5 / res) mslp_hl = np.ma.masked_invalid(mslp['data'].values).squeeze() local_min, local_max = utl.extrema(mslp_hl, mode='wrap', window=nwindow) #Get location of extrema on grid xmin, xmax, ymin, ymax = map_extent2 lons2d, lats2d = x, y transformed = datacrs.transform_points(datacrs, lons2d, lats2d) x = transformed[..., 0] y = transformed[..., 1] xlows = x[local_min] xhighs = x[local_max] ylows = y[local_min] yhighs = y[local_max] lowvals = mslp_hl[local_min] highvals = mslp_hl[local_max] yoffset = 0.022 * (ymax - ymin) dmin = yoffset #Plot low pressures xyplotted = [] for x, y, p in zip(xlows, ylows, lowvals): if x < xmax - yoffset and x > xmin + yoffset and y < ymax - yoffset and y > ymin + yoffset: dist = [ np.sqrt((x - x0)**2 + (y - y0)**2) for x0, y0 in xyplotted ] if not dist or min(dist) > dmin: #,fontweight='bold' a = ax.text(x, y, 'L', fontsize=28, ha='center', va='center', color='r', fontweight='normal', transform=datacrs) b = ax.text(x, y - yoffset, repr(int(p)), fontsize=14, ha='center', va='top', color='r', fontweight='normal', transform=datacrs) a.set_path_effects([ path_effects.Stroke(linewidth=1.5, foreground='black'), path_effects.SimpleLineShadow(), path_effects.Normal() ]) b.set_path_effects([ path_effects.Stroke(linewidth=1.0, foreground='black'), path_effects.SimpleLineShadow(), path_effects.Normal() ]) xyplotted.append((x, y)) #Plot high pressures xyplotted = [] for x, y, p in zip(xhighs, yhighs, highvals): if x < xmax - yoffset and x > xmin + yoffset and y < ymax - yoffset and y > ymin + yoffset: dist = [ np.sqrt((x - x0)**2 + (y - y0)**2) for x0, y0 in xyplotted ] if not dist or min(dist) > dmin: a = ax.text(x, y, 'H', fontsize=28, ha='center', va='center', color='b', fontweight='normal', transform=datacrs) b = ax.text(x, y - yoffset, repr(int(p)), fontsize=14, ha='center', va='top', color='b', fontweight='normal', transform=datacrs) a.set_path_effects([ path_effects.Stroke(linewidth=1.5, foreground='black'), path_effects.SimpleLineShadow(), path_effects.Normal() ]) b.set_path_effects([ path_effects.Stroke(linewidth=1.0, foreground='black'), path_effects.SimpleLineShadow(), path_effects.Normal() ]) xyplotted.append((x, y)) #-画高低压中心 #additional information plt.title('[' + mslp.attrs['model'] + '] ' + '海平面气压, ' + '过去' + '%i' % gust.attrs['t_gap'] + '小时10米最大阵风和10米平均风', loc='left', fontsize=30) utl.add_china_map_2cartopy_public(ax, name='coastline', edgecolor='gray', lw=0.8, zorder=3, alpha=0.5) if add_china: utl.add_china_map_2cartopy_public(ax, name='province', edgecolor='gray', lw=0.5, zorder=3) utl.add_china_map_2cartopy_public(ax, name='nation', edgecolor='black', lw=0.8, zorder=3) utl.add_china_map_2cartopy_public(ax, name='river', edgecolor='#74b9ff', lw=0.8, zorder=3, alpha=0.5) # grid lines gl = ax.gridlines(crs=datacrs, linewidth=2, color='gray', alpha=0.5, linestyle='--', zorder=4) gl.xlocator = mpl.ticker.FixedLocator(np.arange(0, 360, 15)) gl.ylocator = mpl.ticker.FixedLocator(np.arange(-90, 90, 15)) #utl.add_cartopy_background(ax,name='RD') ax.add_feature(cfeature.LAND, color='#F5E19F') ax.add_feature(cfeature.OCEAN) l, b, w, h = ax.get_position().bounds #forecast information bax = plt.axes([l, b + h - 0.1, .25, .1], facecolor='#FFFFFFCC') bax.set_yticks([]) bax.set_xticks([]) bax.axis([0, 10, 0, 10]) initTime = pd.to_datetime( str(mslp.coords['forecast_reference_time'].values)).replace( tzinfo=None).to_pydatetime() fcst_time = initTime + timedelta( hours=mslp.coords['forecast_period'].values[0]) #发布时间 if (sys.platform[0:3] == 'lin'): locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8') if (sys.platform[0:3] == 'win'): locale.setlocale(locale.LC_CTYPE, 'chinese') plt.text(2.5, 7.5, '起报时间: ' + initTime.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 5, '预报时间: ' + fcst_time.strftime("%Y年%m月%d日%H时"), size=15) plt.text(2.5, 2.5, '预报时效: ' + str(int(mslp.coords['forecast_period'].values[0])) + '小时', size=15) plt.text(2.5, 0.5, 'www.nmc.cn', size=15) # add color bar if (gust != None): cax = plt.axes([l, b - 0.04, w, .02]) cb = plt.colorbar(plots['gust'], cax=cax, orientation='horizontal', extend='max', ticks=[ 8.0, 10.8, 13.9, 17.2, 20.8, 24.5, 28.5, 32.7, 37, 41.5, 46.2, 51.0, 56.1, 61.3 ]) cb.ax.tick_params(labelsize='x-large') cb.set_label('风速 (m/s)', size=20) # add south China sea if south_China_sea: utl.add_south_China_sea(pos=[l + w - 0.091, b, .1, .2]) small_city = False if (map_extent2[1] - map_extent2[0] < 25): small_city = True if city: utl.add_city_on_map(ax, map_extent=map_extent2, transform=datacrs, zorder=5, size=13, small_city=small_city) utl.add_logo_extra_in_axes(pos=[l - 0.02, b + h - 0.1, .1, .1], which='nmc', size='Xlarge') # show figure if (output_dir != None): plt.savefig(output_dir + '海平面气压_逐6小时最大风速_预报_' + '起报时间_' + initTime.strftime("%Y年%m月%d日%H时") + '预报时效_' + str(mslp.coords['forecast_period'].values[0]) + '小时' + '.png', dpi=200, bbox_inches='tight') plt.close() if (output_dir == None): plt.show()