前言:

  • 一般网页可视化风场中的数据都是json格式,而如果我们希望将wrf模式模拟输出的风场数据在网页中进行展示,这就需要先将wrfoutput数据转换为网页可以识别的json格式。

  • 这里主要需要用到json库,主要的实现方式就是将读取的风场风量U,V转换为字典并存到json文件中

  • 同时,由于wrf模拟的数据一般是非等间距的网格,需要先将数据进行插值,插值到等间距的网格,这里可以通过NCL的函数rcm2rgrid_Wrap实现
    举个例子,将模式中设置为兰伯特投影的网格:

    插值为等间距网格:

主要的编程分为两部分:

  • 第一部分通过NCL脚本将wrfout数据转换为等间距网格,并导出为netcdf格式;
  • 第二部分通过python脚本将第一步导出的nc格式进行转换,并保存输出为json格式。

NCL插值脚本1

  • 需要修改的就是路径和变量,我下面展示脚本不仅有风场数据u,v还有降水,海表面压力,气温等,可自行修改
begina = addfile("/Users/WRF/outdata/2022071000/wrfout_d01_2022-07-10_01:00:00","r")lat2d = a->XLAT(0,:,:)lon2d = a->XLONG(0,:,:)lat1d = lat2d(:,0)lon1d = lon2d(0,:)time = wrf_user_getvar(a,"XTIME",-1)u10 = wrf_user_getvar(a,"U10",0)v10 = wrf_user_getvar(a,"V10",0)slp = wrf_user_getvar(a,"slp",0)t2  = wrf_user_getvar(a,"T2",0)td  = wrf_user_getvar(a,"td",0)rainc = wrf_user_getvar(a,"RAINC",0)rainnc = wrf_user_getvar(a,"RAINNC",0)u10@lat2d = lat2du10@lon2d = lon2du10_ip = rcm2rgrid_Wrap(lat2d,lon2d,u10,lat1d,lon1d,0)v10@lat2d = lat2dv10@lon2d = lon2dv10_ip = rcm2rgrid_Wrap(lat2d,lon2d,v10,lat1d,lon1d,0)slp_ip  =   rcm2rgrid_Wrap(lat2d,lon2d,slp,lat1d,lon1d,0)t2_ip  =   rcm2rgrid_Wrap(lat2d,lon2d,t2,lat1d,lon1d,0)td_ip  =   rcm2rgrid_Wrap(lat2d,lon2d,td,lat1d,lon1d,0)rainc_ip  =   rcm2rgrid_Wrap(lat2d,lon2d,rainc,lat1d,lon1d,0)rainnc_ip  =   rcm2rgrid_Wrap(lat2d,lon2d,rainnc,lat1d,lon1d,0)outf = addfile("/Users/wrfout_d01_2022-07-10_01:00:00.nc","c")outf->time =  timeoutf->lat  =  lat2doutf->lon  =  lon2doutf->u10  =  u10_ipoutf->v10  =  v10_ipoutf->slp  =  slp_ipoutf->t2   =  t2_ipoutf->td   =  td_ipoutf->rainc   =  rainc_ipoutf->rainnc  =  rainnc_ipend

上述脚本的缺点在于只能基于模式模拟的经纬度区域进行插值,意思就是说他的经纬度区域是固定的那么大

NCL插值脚本2

NCL还有一个函数可以实现上述过程,就是ESMF_regrid,该函数的优点在于可以实现任意经纬度范围的插值,但是不足在于对于存在高度层的变量,暂时无法进行高度层的数据读取。(也可能我水平有限不知道。。。。)这里也附上脚本:

load "$NCARG_ROOT/lib/ncarg/nclscripts/esmf/ESMF_regridding.ncl"begina = addfile("/Users/WRF/outdata/2022071000/wrfout_d01_2022-07-10_01:00:00","r")u10 = wrf_user_getvar(a,"U10",0)v10 = wrf_user_getvar(a,"V10",0)slp = wrf_user_getvar(a,"slp",0)t2  = wrf_user_getvar(a,"T2",0)
;  td  = wrf_user_getvar(a,"td",0)rainc = wrf_user_getvar(a,"RAINC",0)rainnc = wrf_user_getvar(a,"RAINNC",0)u10@lat2d = a->XLAT(0,:,:) u10@lon2d = a->XLONG(0,:,:)v10@lat2d = a->XLAT(0,:,:) v10@lon2d = a->XLONG(0,:,:)slp@lat2d = a->XLAT(0,:,:) slp@lon2d = a->XLONG(0,:,:)t2@lat2d = a->XLAT(0,:,:) t2@lon2d = a->XLONG(0,:,:)
;  td@lat2d = a->XLAT(0,:,:)
;  td@lon2d = a->XLONG(0,:,:)rainc@lat2d = a->XLAT(0,:,:) rainc@lon2d = a->XLONG(0,:,:)rainnc@lat2d = a->XLAT(0,:,:) rainnc@lon2d = a->XLONG(0,:,:)lat2d = a->XLAT(0,:,:)lon2d = a->XLONG(0,:,:)lat1d = lat2d(:,0)lon1d = lon2d(0,:)latS = -20latN = 50lonW = 95lonE = 145Opt = TrueOpt@InterpMethod = "bilinear" Opt@ForceOverwrite = True Opt@SrcMask2D = where(.not. ismissing(v10),1,0) Opt@DstGridType = "0.1deg"Opt@DstLLCorner = (/latS, lonW /) Opt@DstURCorner = (/latN, lonE /) u10_regrid = ESMF_regrid(u10,Opt)v10_regrid = ESMF_regrid(v10,Opt)slp_regrid = ESMF_regrid(slp,Opt)t2_regrid = ESMF_regrid(t2,Opt)
;  td_regrid = ESMF_regrid(td,Opt)rainc_regrid = ESMF_regrid(rainc,Opt)rainnc_regrid = ESMF_regrid(rainnc,Opt)time = wrf_user_getvar(a,"XTIME",-1)nlon = dimsizes(v10_regrid&lon)nlat = dimsizes(v10_regrid&lat)ofile = "wrfout_d01_2022-07-10_01:00:00.nc"system("rm -rf "+ofile) fout = addfile(ofile,"c") dimNames = (/"lat", "lon"/)dimSizes = (/nlat, nlon/)dimUnlim = (/False, False/)filedimdef(fout,dimNames,dimSizes,dimUnlim) ;-- define dimensionsfilevardef(fout,"lat",typeof(v10_regrid&lat),getvardims(v10_regrid&lat))filevardef(fout,"lon",typeof(v10_regrid&lon),getvardims(v10_regrid&lon))filevardef(fout,"u10",typeof(u10_regrid),getvardims(u10_regrid))filevardef(fout,"v10",typeof(v10_regrid),getvardims(v10_regrid))filevardef(fout,"slp",typeof(slp_regrid),getvardims(slp_regrid))filevardef(fout,"t2",typeof(t2_regrid),getvardims(t2_regrid))
;  filevardef(fout,"td",typeof(td_regrid),getvardims(td_regrid))filevardef(fout,"rainc",typeof(rainc_regrid),getvardims(rainc_regrid))filevardef(fout,"rainnc",typeof(rainnc_regrid),getvardims(rainnc_regrid))filevarattdef(fout,"lat",v10_regrid&lat) ;-- copy lat attributesfilevarattdef(fout,"lon",v10_regrid&lon) ;-- copy lon attributesfilevarattdef(fout,"u10",u10_regrid)filevarattdef(fout,"v10",v10_regrid)filevarattdef(fout,"slp",slp_regrid)filevarattdef(fout,"t2",t2_regrid)
;  filevarattdef(fout,"td",td_regrid)filevarattdef(fout,"rainc",rainc_regrid)filevarattdef(fout,"rainnc",rainnc_regrid)setfileoption(fout,"DefineMode",False)fout->u10 = (/u10_regrid/)fout->v10 = (/v10_regrid/) fout->slp = (/slp_regrid/) fout->t2 = (/t2_regrid/)
;  fout->td = (/td_regrid/) fout->rainc  = (/rainc_regrid/) fout->rainnc = (/rainnc_regrid/) fout->lat = (/v10_regrid&lat/) ;-- write lat to new netCDF filefout->lon = (/v10_regrid&lon/) ;-- write lon to new netCDF filefout->time =  timeend

PS:运行该脚本会生成四个nc文件,分别为:destination_grid_file.nc、source_grid_file.nc、weights_file.nc、wrfout_d01_2022-07-10_01:00:00.nc。其中,wrfout_d01_2022-07-10_01:00:00.nc是我需要的文件,但是其他三个文件如何在运行脚本的过程去掉暂未解决。

python格式转换脚本1

python脚本如下所示:

# -*- coding: utf-8 -*-
"""
Created on %(date)s@author: %(jixianpu)sEmail : 211311040008@hhu.edu.cnintroduction : keep learning althongh walk slowly
""""""
用来读取用ncl插值后的wrfoutput.nc 数据,并生成对应文件名的json格式
"""import pandas as pd
import os
import json
import netCDF4 as nc
import numpy as np
import  datetime
from netCDF4 import Dataset
import argparse
from argparse import RawDescriptionHelpFormatter
import xarray as xr
import sys
import globdate = sys.argv[1]
date = str(date)
frst = sys.argv[2]
step = sys.argv[3]path = r'/Users/WRF/outdata/2022071000/'#只能是已经存在的文件目录且有数据才可以进行读取
start = datetime.datetime.strptime(date,'%Y%m%d%H').strftime("%Y-%m-%d_%H:%M:%S")
end = (datetime.datetime.strptime(date,'%Y%m%d%H')+datetime.timedelta(hours=int(frst))).strftime("%Y-%m-%d_%H:%M:%S")
intp = (datetime.datetime.strptime(date,'%Y%m%d%H')+datetime.timedelta(hours=int(step))).strftime("%Y-%m-%d_%H:%M:%S")
fstart = path+'/wrfout_d01_'+start+'*'
fintp  = path+'/wrfout_d01_'+intp+'*'
fend   = path+'/wrfout_d01_'+end+'*'
file = path+'/*'
filestart = glob.glob(fstart)
fileintp  = glob.glob(fintp)
fileend   = glob.glob(fend)
filelist  = glob.glob(file)
filelist.sort()
rstart = np.array(np.where(np.array(filelist)==filestart))[0][0]
rintp = np.array(np.where(np.array(filelist)==fileintp))[0][0]
rend   = np.array(np.where(np.array(filelist)==fileend))[0][0]
fn = filelist[rstart:rend:rintp]outroot = 'Users/'
for i in fn:uhdr = {"header":{"discipline":0,"disciplineName":"Meteorological products","gribEdition":2,"gribLength":131858,"center":0,"centerName":"WRF OUTPUT","subcenter":0,"refTime":"2014-01-31T00:00:00.000Z","significanceOfRT":1,"significanceOfRTName":"Start of forecast","productStatus":0,"productStatusName":"Operational products","productType":1,"productTypeName":"Forecast products","productDefinitionTemplate":0,"productDefinitionTemplateName":"Analysis/forecast at horizontal level/layer at a point in time","parameterCategory":2,"parameterCategoryName":"Momentum","parameterNumber":2,"parameterNumberName":"U-component_of_wind","parameterUnit":"m.s-1","genProcessType":2,"genProcessTypeName":"Forecast","forecastTime":3,"surface1Type":103,"surface1TypeName":"Specified height level above ground","surface1Value":10,"surface2Type":255,"surface2TypeName":"Missing","surface2Value":0,"gridDefinitionTemplate":0,"gridDefinitionTemplateName":"Latitude_Longitude","numberPoints":65160,"shape":6,"shapeName":"Earth spherical with radius of 6,371,229.0 m","gridUnits":"degrees","resolution":48,"winds":"true","scanMode":0,"nx":360,"ny":181,"basicAngle":0,"subDivisions":0,"lo1":0,"la1":90,"lo2":359,"la2":-90,"dx":1,"dy":1}}vhdr = {"header":{"discipline":0,"disciplineName":"Meteorological products","gribEdition":2,"gribLength":131858,"center":0,"centerName":"WRF OUTPUT","subcenter":0,"refTime":"2014-01-31T00:00:00.000Z","significanceOfRT":1,"significanceOfRTName":"Start of forecast","productStatus":0,"productStatusName":"Operational products","productType":1,"productTypeName":"Forecast products","productDefinitionTemplate":0,"productDefinitionTemplateName":"Analysis/forecast at horizontal level/layer at a point in time","parameterCategory":2,"parameterCategoryName":"Momentum","parameterNumber":3,"parameterNumberName":"V-component_of_wind","parameterUnit":"m.s-1","genProcessType":2,"genProcessTypeName":"Forecast","forecastTime":3,"surface1Type":103,"surface1TypeName":"Specified height level above ground","surface1Value":10,"surface2Type":255,"surface2TypeName":"Missing","surface2Value":0,"gridDefinitionTemplate":0,"gridDefinitionTemplateName":"Latitude_Longitude","numberPoints":65160,"shape":6,"shapeName":"Earth spherical with radius of 6,371,229.0 m","gridUnits":"degrees","resolution":48,"winds":"true","scanMode":0,"nx":360,"ny":181,"basicAngle":0,"subDivisions":0,"lo1":0,"la1":90,"lo2":359,"la2":-90,"dx":1,"dy":1}}data = [uhdr, vhdr]newf = Dataset(i)lat = np.array(newf.variables['lat'])# print(fn,lat)lon = np.array(newf.variables['lon'])dys = np.diff(lat, axis = 0).mean(1)dy = float(dys.mean())dxs = np.diff(lon, axis = 1).mean(0)dx = float(dxs.mean())nx = float(lon.shape[1])ny = float(lat.shape[0])la1 = float(lat[-1, -1])la2 = float(lat[0, 0])lo1 = float(lon[0, 0])lo2 = float(lon[-1, -1])time =(newf.variables['time'])dates = nc.num2date(time[:],units=time.units)dt = pd.to_datetime(np.array(dates, dtype='datetime64[s]')).strftime("%Y%m%d%H%M%S")tms =pd.to_datetime(np.array(dates, dtype='datetime64[s]')).strftime("%Y-%m-%d_%H:%M:%S")for ti, time in enumerate(dt):datestr = (dt[0][:8])timestr = (dt[0][8:10])+'00'dirpath = outroot + dateos.makedirs(dirpath, exist_ok = True)outpath = os.path.join(dirpath, '%s.json' % (i[-19:]))for u0_or_v1 in [0, 1]:h = data[u0_or_v1]['header']h['la1'] = la1h['la2'] = la2h['lo1'] = lo1h['lo2'] = lo2h['nx'] = nxh['ny'] = nyh['dx'] = dxh['dy'] = dyh['forecastTime'] = 0h['refTime'] = tms[0] + '.000Z'h['gribLength'] = 1538 + nx * ny * 2if u0_or_v1 == 0:data[u0_or_v1]['data'] = np.array(newf.variables['u10']).ravel().tolist()elif u0_or_v1 == 1:data[u0_or_v1]['data'] = np.array(newf.variables['v10']).ravel().tolist()if ti == 0:outf = open(outpath, 'w')json.dump(data, outf)outf.close()outf = open(outpath, 'w')json.dump(data, outf)outf.close()

上述脚本为Linux系统下运行,运行方式如下:

python  xx.py 起报时间 时常 间隔

举个例子:
我的wrfout数据名称如下:

python  convert_to_json.py 2022071000 12 06

根据你需要的模式起始时间,起报的时长(小时)以及预报的时间间隔(小时)进行自动化转换。

python 格式转换脚本2

当然,这里也准备了一个windows下的简易脚本,转换出的信息也比较简单,

# -*- coding: utf-8 -*-
"""
Created on %(date)s@author: %(jixianpu)sEmail : 211311040008@hhu.edu.cnintroduction : keep learning althongh walk slowly
"""from __future__ import print_function, unicode_literals
import pandas as pd
import os
import json
import netCDF4 as nc
import numpy as np
import  datetime
from netCDF4 import Dataset
import argparse
from argparse import RawDescriptionHelpFormatter
import xarray as xr# parser = argparse.ArgumentParser(description = """
# """, formatter_class = RawDescriptionHelpFormatter)args = r'J:/wrf自动化/wrfout_d01_2022-07-10_01_00_00.nc'outroot = r'D:/'uhdr = {"header":{"nx":360,"ny":181,"max":11,}}data = [uhdr]
newf = Dataset(args)
lat = np.array(newf.variables['lat'])
lon = np.array(newf.variables['lon'])u10 = np.array(newf.variables['u10'])
v10 = np.array(newf.variables['v10'])# indx = u10>1000# u10[indx] = np.nan
# v10[indx] = np.nanw10 = np.nanmax(np.sqrt(u10*u10+v10*v10))dys = np.diff(lat, axis = 0).mean(1)
dy =    float(dys.mean())
print('Latitude Error:', np.abs((dy / dys) - 1).max())
print('Latitude Sum Error:', (dy / dys - 1).sum())
dxs = np.diff(lon, axis = 1).mean(0)
dx =    float(dxs.mean())
print('Longitude Error:', np.abs(dx / dxs - 1).max())
print('Longitude Sum Error:', (dx / dxs - 1).sum())nx =    float(lon.shape[1])
ny =    float(lat.shape[0])la1 =    float(lat[-1, -1])
la2 =   float(lat[0, 0])
lo1 =   float(lon[0, 0])
lo2 =   float(lon[-1, -1])time =(newf.variables['time'])dates = nc.num2date(time[:],units=time.units)dt = pd.to_datetime(np.array(dates, dtype='datetime64[s]')).strftime("%Y%m%d%H%M%S")ds= {"nx":360,"ny":181,"max":11,# "lo1":0,# "la1":90,# "lo2":359,# "la2":-90,# "dx":1,# "dy":1,# "parameterUnit":"m.s-1",'data':{}}ds['max']   =    float(w10)
ds['nx']    =    (nx)
ds['ny']    =    (ny)for ti, time in enumerate(dt):#2012/02/07/0100Z/wind/surface/level/orthographic=-74.01,4.38,29184datestr = (dt[0][:8])timestr = (dt[0][8:10])+'00'print('Add "#' + datestr + '/' + timestr + 'Z/wind/surface/level/orthographic" to url to see this time')dirpath = os.path.join('D:', *datestr.split('/'))os.makedirs(dirpath, exist_ok = True)outpath = os.path.join(dirpath, '%s-wind-surface-level-gfs-1.0.json' % (timestr,))udata=u10.ravel()data[0]['data']=[]for i in range(len(udata)):data[0]['data'].append([u10.ravel().tolist()[i],v10.ravel().tolist()[i]])ds['data'] = data[0]['data']outf = open(outpath, 'w')
json.dump(ds,outf)
outf.close()

这个脚本正常放在编辑器里面运行即可。
运行完结束,会在你的输出路径下生成一个文件夹:

里面有个json数据:

数据信息比较简单,只有nx(经度的大小),ny(纬度的大小)以及最大值:

ok,以上就是完整的过程,最终将得到的json数据通过.js脚本运行就可以部署到网页上了,简单试了一下,大概如下图所示,可以根据需要自行更改设置:

水平有限,本人对于NCL脚本不太熟悉,可能有些代码写的比较复杂,欢迎指正!!!

                     一个努力学习python的ocean er水平有限,欢迎指正!!!欢迎评论、收藏、点赞、转发、关注。关注我不后悔,记录学习进步的过程~~

python--转换wrf输出的风场数据为网页可视化的json格式相关推荐

  1. Python之基础详解(八):必备,以制作交易收盘价走趋图为例,来可视化处理json格式的文件

    在这里,我们将会用json模块来处理json格式文件.Pygal提供了一个适合初学者使用的绘图工具,我们在这里将使用它来对收盘价数据进行可视化,以帮助我们掌握基础技能.(本文所需要的文件都在资源中,记 ...

  2. 把php数据转成json格式转换,php将从数据库中获得的数据转换成json格式并输出的方法...

    php将从数据库中获得的数据转换成json格式并输出的方法 如下所示: header('content-type:application/json;charset=utf8'); $results = ...

  3. 老鱼Python数据分析——篇十五:“选股宝”使用API下载JSON格式数据

    从页面读取数据每次都需要定位HTML标签,那么有没有更简洁的办法呢? 当然有,那就是找到页面数据的来源,分析哪些数据是我们想要的,直接通过WebAPI来获得数据. 我使用的是360极速浏览器,按F12 ...

  4. Python采集黄色软件剧本杀数据并做可视化

    前言 大家早好.午好.晚好吖 ❤ ~ "剧本杀" 是玩家到实景场馆,体验推理性质的项目. 剧本杀的规则是,玩家先选择人物,阅读人物对应剧本,搜集线索后找出活动里隐藏的真凶. 剧本杀 ...

  5. 【Python】采集剧本杀店家数据信息,可视化演示

    前言 哈喽啊,友友们 有喜欢玩桌游或者剧本杀的吗 其实我自己对这个不太感兴趣哈哈,但是也玩过 正好又有朋友约着出去,就是不知道哪家店更值得去 所以趁着还有几天就用python来采集一些 店家的数据信息 ...

  6. python每行输出5个数据_12个流行的Python数据可视化库总结

    总结了10个不同领域的 Python 数据可视化库,有常用的,也有比较小众的. 1. matplotlib matplotlib是Python数据可视化库的OG.尽管它已有十多年的历史,但仍然是Pyt ...

  7. python每行输出10个数据_python 如何重复地在一行输出数据?

    你的位置: 问答吧 -> Linux 编程 -> 问题详情 python 如何重复地在一行输出数据? 我希望 python 的输出结果只在一行上不断地刷新显示,要实现两点: 一.输出结果1 ...

  8. Python爬取某宝菠萝数据,并可视化分析销量

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. 以下文章来源于志斌的python笔记 ,作者 志斌 Python爬虫.数据分析.网站开发等案例教程 ...

  9. python爬虫案例:采集股票数据并制作可视化柱图~

    前言 嗨喽!大家好呀,这里是魔王~ 雪球,聪明的投资者都在这里 - 4300万投资者都在用的投资社区, 沪深港美全球市场实时行情,股票基金债券免费资讯,与投资高手实战交流. 模块使用 requests ...

最新文章

  1. 2020年,这些学者归国任教
  2. win10 修改win登录logo_技巧:分享自己使用Win10过程中,一些实用小技巧
  3. python教程下载视频-python怎么下载视频
  4. centos7下使用yum安装mysql并创建用户,数据库以及设置远程访问
  5. Juniper防火墙命令行查错工具snoop的使用
  6. [leetcode]111.二叉树的最小深度
  7. cmd长ping记录日志和时间_Gin 框架系列 — 路由中间件:日志记录
  8. .NET Core 1.0发布:微软开源跨平台大布局序幕
  9. jsp源码oracle数据库,JSP与oracle数据库交互案例
  10. Android 系统(207)---如何自学 Android?
  11. Linux内存带宽的一些测试笔记
  12. 基于matlab的升压斩波实验,升降压斩波电路matlab仿真
  13. css3之背景属性之background-size
  14. linux下修改文件权限.
  15. Linux kali 安装 qq Tim
  16. GIF Movie Gear逆向实战+注册代码+补丁
  17. 常用视频像素格式 YUV422 YUV420
  18. 初学vue,模仿个静态网站
  19. Cant open /dev/sdb1exclusively.Mounted filesystem
  20. nuxt+tsx项目 class报错

热门文章

  1. 浙江公务员考试申论指导作答的思路与方法
  2. 大家给推荐个4k显示器吧,码农,不玩游戏,护眼第一。
  3. 网络路由与交换技术常见命令1(Cisco)
  4. Android代码安装apk程序
  5. php图片上传为base64,php实现base64图片上传方式实例代码
  6. [LeetCode] 157. Read N Characters Given Read4
  7. Spring cloud alibaba--Feign微服务调用组件
  8. STM32实战(1):搭建模板工程
  9. P3387 【模板】缩点 洛谷 java题解 连通图+拓扑排序
  10. 微信企业支付(一)注意