爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 3651|回复: 3

MeteoInfo脚本教程(十六):格点数据运算

[复制链接]

新浪微博达人勋

发表于 2014-12-21 00:20:21 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
数据分析计算也是MeteoInfo重点考虑的功能,主要体现在格点和站点数据的各种数学运算。这里先讲讲格点数据的运算。

我一直认为Java语言有一个重大缺陷,那就是不支持运算符重载,这造成无法用简单的运算符号(比如+, -, *, /)来写公式进行自定义数据类的运算。所以在GridData类中定义了一些方法来进行四则运算:add, sub, mul, div。还需要知道一个重要的类DataMath(在org.meteoinfo.data包中),利用该类可以进行更复杂的运算,比如指数、幂、三角函数运算等等。这样处理也可以完成运算符重载能做的工作,但是公式写起来就没那么简洁明了了。比如如果有运算符重载功能,可以写下面的公式(air是GridData类的对象):
es = 6.112*DataMath.exp(17.67*(air-273.16)/(air-29.65))

没有运算符重载功能只能处理成这样:
es = DataMath.exp(air.sub(273.16).mul(17.67).div(air.sub(29.65))).mul(6.112)

这是题外话,Java的开发人员不认为这是一个缺陷,而且也没有加入运算符重载功能的打算,所以公式写得难看些也只能这样了。

下面是一个利用NCEP数据计算水汽通量散度的脚本,包含了比较多的格点运算。

  1. #-----------------------------------------------------
  2. # Author: Yaqiang Wang
  3. # Date: 2014-12-20
  4. # Purpose: Calculate water vapor flux
  5. # Note: Sample
  6. #-----------------------------------------------------
  7. #---- Import classes
  8. print 'Import classes...'
  9. from org.meteoinfo.layout import MapLayout
  10. from org.meteoinfo.data import DataMath
  11. from org.meteoinfo.data.mapdata import MapDataManage
  12. from org.meteoinfo.data.meteodata import MeteoDataInfo, DrawMeteoData
  13. from org.meteoinfo.legend import LegendManage, LegendType
  14. from org.meteoinfo.layout import LegendStyles
  15. from org.meteoinfo.global import Extent
  16. import os.path
  17. from java.text import SimpleDateFormat
  18. from java.awt import Color
  19. from javax.swing import JFrame

  20. #---- Set directories
  21. print 'Set directories...'
  22. baseDir = 'D:/MyProgram/Distribution/java/MeteoInfo/MeteoInfo'
  23. dataDir = 'D:/Temp/nc'
  24. mapDir = os.path.join(baseDir, 'map')

  25. #---- Create MapLayout object
  26. mapLayout = MapLayout()
  27. mapFrame = mapLayout.getActiveMapFrame()
  28. layoutMap = mapLayout.getActiveLayoutMap()

  29. #---- Load country layer
  30. print 'Load country layer...'
  31. countryLayer = MapDataManage.loadLayer(os.path.join(mapDir, 'country1.shp'))
  32. lb = countryLayer.getLegendScheme().getLegendBreaks().get(0)
  33. lb.setDrawFill(False)
  34. lb.setOutlineColor(Color.blue)
  35. mapFrame.addLayer(countryLayer)

  36. #---- Open netCDF data files
  37. print 'Open netCDF data files...'
  38. dataAir = MeteoDataInfo()
  39. dataUwnd = MeteoDataInfo()
  40. dataVwnd = MeteoDataInfo()
  41. dataRhum = MeteoDataInfo()
  42. dataAir.openNetCDFData(os.path.join(dataDir, 'air.2011.nc'))
  43. dataUwnd.openNetCDFData(os.path.join(dataDir, 'uwnd.2011.nc'))
  44. dataVwnd.openNetCDFData(os.path.join(dataDir, 'vwnd.2011.nc'))
  45. dataRhum.openNetCDFData(os.path.join(dataDir, 'rhum.2011.nc'))

  46. #---- Calculation
  47. #---- Set date to June 23
  48. #tIdx = 171
  49. tIdx = 173
  50. dataAir.setTimeIndex(tIdx);
  51. dataUwnd.setTimeIndex(tIdx);
  52. dataVwnd.setTimeIndex(tIdx);
  53. dataRhum.setTimeIndex(tIdx);

  54. #---- Set level to 700hPa
  55. lIdx = 3
  56. dataAir.setLevelIndex(lIdx);
  57. dataUwnd.setLevelIndex(lIdx);
  58. dataVwnd.setLevelIndex(lIdx);
  59. dataRhum.setLevelIndex(lIdx);

  60. #---- Get grid data
  61. print 'Get grid data...'
  62. air = dataAir.getGridData('air')
  63. uwnd = dataUwnd.getGridData('uwnd')
  64. vwnd = dataVwnd.getGridData('vwnd')
  65. rhum = dataRhum.getGridData('rhum')

  66. #---- Calculate
  67. print 'Calculation...'
  68. prs = 700
  69. g = 9.8
  70. es = DataMath.exp(air.sub(273.16).mul(17.67).div(air.sub(29.65))).mul(6.112)
  71. #es = 6.112*DataMath.exp(17.67*(air-273.16)/(air-29.65))
  72. qs = es.mul(0.62197).div(DataMath.sub(prs, es.mul(0.378)))
  73. #qs = 0.62197*es/(prs-0.378*es)
  74. q = qs.mul(rhum).div(100)
  75. #q = qs*rhum/100
  76. qhdivg = DataMath.hdivg(q.mul(uwnd).div(g), q.mul(vwnd).div(g))
  77. #qhdivg = DataMath.Hdivg(q*uwnd/g,q*vwnd/g)
  78. qv = rhum.mul(es).div(100)
  79. #qv = rhum*es/100
  80. uv = DataMath.magnitude(uwnd, vwnd)
  81. #uv = DataMath.Magnitude(uwnd, vwnd)
  82. uvq = uv.mul(qv).div(9.8*1000)
  83. #uvq = uv*qv/(9.8*1000)

  84. #---- Create data layer
  85. print 'Create data layer...'
  86. dataLayer = DrawMeteoData.createShadedLayer(qhdivg, "WaterVaporFlux", "Flux", False)

  87. #---- Add layer
  88. print 'Add layers...'
  89. mapFrame.addLayer(dataLayer)
  90. mapFrame.moveLayer(dataLayer, 0)
  91. #---- Zoom data
  92. mapLayout.getActiveLayoutMap().zoomToExtentLonLatEx(Extent(0,360,-90.1,90.1))
  93. #---- Set MapLayout
  94. format = SimpleDateFormat('yyyy-MM-dd')
  95. aTime = dataAir.getDataInfo().getTimes().get(tIdx)
  96. mapLayout.addText('Water Vapor Flux Divergence - ' + format.format(aTime), 320, 30, 'Arial', 16)
  97. aLegend = mapLayout.addLegend(650, 100)
  98. aLegend.setLegendStyle(LegendStyles.Bar_Vertical)
  99. aLegend.setLegendLayer(dataLayer)
  100. layoutMap.setGridXDelt(60)
  101. layoutMap.setGridYDelt(30)
  102. layoutMap.setDrawGridLine(False)
  103. mapLayout.paintGraphics()

  104. frame = JFrame('MeteoInfo Script Sample', size = (750, 530))
  105. frame.add(mapLayout)
  106. frame.visible = True
  107. print 'Finished!'


Image00096.png

本帖被以下淘专辑推荐:

密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2014-12-21 09:18:34 | 显示全部楼层
呵呵,王老师
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 成长值: 19710
发表于 2014-12-21 21:54:05 | 显示全部楼层
王老师,您的软件是否能后台事先设置好一些默认设置,然后前台写的代码能尽量的简洁?
如果能做成像GrADS那样能用简单的脚本就可以绘制常用的图,我想王老师的软件肯定会更受欢迎。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2014-12-21 22:02:22 | 显示全部楼层
兰溪之水 发表于 2014-12-21 21:54
王老师,您的软件是否能后台事先设置好一些默认设置,然后前台写的代码能尽量的简洁?
如果能做成像GrADS ...

最早C#版MeteoInfo专门设计了一个MIApp类就是想封装一些常用功能,让脚本更简单些。不过这也是双刃剑,首先牺牲了灵活性,再者不利于用户真正了解MeteoInfo库的结构和功能。

当然,可能很多人不愿意学习复杂的东西,以后也会考虑在Java版中做这样的常用功能封装类。
密码修改失败请联系微信:mofangbao
您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表