加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

EOF 分析实例:学习和使用ferret

(2011-11-08 01:26:18)
标签:

eof

ferret

分类: 学术科研
采用与前一篇文章相同的数据,这次改用ferret进行EOF分析。

1. 导入要分析的数据:
在ferret中输入命令
    use tsw, slp, ustrw, vstrw
察看数据属性:
    show data
ferret会显示当前打开的数据文件及其中所包含的数据变量的列表和信息。这些数据文件中只有一个处于当前激活状态,在列表中标记为(default),它所包含的数据变量可以直接访问。非激活状态的数据文件中的变量不能直接使用,而需要以var[d=file]的形式访问。其中var是变量名,file是数据文件名。要改变当前激活的数据文件,使用set data file或set data n,其中file为数据文件名,n为数据文件的编号。

2. 设定时间和空间范围
    set reg/x=110s:70w/y=20s:60n/t=1-Jan-3500:31-Dec-3600
reg是region的简写。set命令用于设置属性,region是要设置的对象,/后面分隔的是不同的属性。ferret中的经纬度可以用110e,70w,20s,60n这样的写法表示,同时也支持用负数表示西经和南纬。时间的写法必须按照dd-mmm-yyyy的格式来写。这样设置了时空范围以后,下面的所有操作都是限定在这个范围内进行的。

3. 使用etopo地形数据将陆地点设为无效数据
3.1 首先打开etopo120数据:
    use etopo120
show data显示
    5> ./etopo120.cdf  (default)
    name     title                             I         J         K         L
    ROSE     RELIEF OF THE SURFACE OF THE EA  1:180     1:90      ...       ...
说明其中有一个名为rose的变量。

3.2 将水深数据插值到其他数据的网格上:
首先需要获取tsw等数据的网格信息:
   show grid tsw
显示
   name       axis              # pts   start                end
   LON       LONGITUDE           48mr   112.5E               71.25W
   LAT       LATITUDE            21 i   16.7S                57.52N
   normal    Z
   TIME1     TIME              1212 i   31-JAN-3500 12:00    31-DEC-3600 12:00
说明其x、y、z、t坐标轴的名字分别为lon、lat、normal和time1. 我们用已有的坐标轴建立网格:
   define grid/x=lon/y=lat p86grid
define命令用来定义坐标轴(axis)、网格(grid)等。坐标轴和网格都是特殊形式的变量,其中网格是定义在2-4个坐标轴的基础上的。这里使用坐标轴lon和lat定义了网格p86grid。

接下来将etopo数据插值到p86grid网格上。ferret中的插值相当简单,采用一种叫做regridding的机制:
    let roseinterp=rose[d=5,g=p86grid]
这里用到了let命令,它的作用是定义新的变量。这样定义的变量不属于任何数据文件,因此可以随时使用。roseinterp就是新变量的名字,等号后面是赋值表达式。
    rose[d=5,g=p86grid]
这种形式是对变量的附加描述,指明该变量来源的数据文件编号为5,网格为p86grid。这样就完成了插值。
事实上,现在ferret还没有进行实际的插值操作,它只是将新的网格信息以变量描述的形式保存下来,而只有当真正需要使用新变量roseinterp的值的时候才会进行插值计算。

3.3 设置陆地点为无效数据
利用if-then-else语句来实现区域条件赋值,即把水深大于0的点设为无效数据,而小于0的数据则保留:
    let tswmasked=if roseinterp gt 0 then (-999) else tsw[d=1]
if-then-else结构按条件返回不同的值。例如
    let a = if b gt c then d else e
判断b gt c的真假(gt是大于的意思),如果为真,则返回d,否则返回e,而a接收其返回值。这种条件赋值是面向矩阵元素的,也就是要求b、c、d、e的形状相同,对于矩阵中每一个对应位置的元素,分别进行判断和选择,最终a的形状也与bcde相同。

这里是利用roseinterp变量是否大于零来判断,大于零的地方新变量的值设为-999(ferret中负数常量应该加括
号),其他地方新变量的值等于编号为1的数据文件中的tsw变量。因为我们会同时用到不同数据文件中的变量,因此应该总是指定变量的来源。

下面将-999设为无效数据:
   set var/bad=-999 tswmasked
ferret中的默认无效值是-1e34,但可以给变量任意指定无效值。通过改变变量tswmasked的bad属性即可完成。
这样tswmasked变量中就保存了去掉陆地点的数据。

4. 计算异常
    let tswann=tswmasked-tswmasked[t=1-Jan-3500:31-Dec-3600@ave]
这里的变量描述用到了变换(transform)@ave。ferret中以@ave开头的就是变换,写在某个坐标轴的后面,表示对这个坐标轴进行一定的操作。上面的@ave就是平均,t=1-Jan-3500:31-Dec-3600@ave表示对3500年1月1日到3600年12月31日的时间范围进行平均。

5. 计算EOF
ferret中函数eof_space用于EOF分析,它的语法为:
   let eofs=eof_space(tswann, 20, 0.8)
其中第一个参数就是要分析的数据,是一个三维(xyt)的数据,第二个参数是最低计算到多少方差贡献的eof,如果想要得到方差贡献不小于0.2的eof,就写20;第三个参量一般取0.8.返回的结果也是一个三维矩阵,其中第三维表示不同的eof。

相应的eof_tfunc函数用来计算时间系数(PC),而eof_stat函数返回满足最低方差贡献要求的eof的个数、特征值、方差贡献等统计量:
   let pcs=eof_tfunc(tswann, 20,0.8)
   let sta=eof_stat(tswann,20,0.8)
ferret不会马上计算eof,而是把变量的表达式保存下来,在需要使用它的值(如画图)的时候才真正进行计算。

6. 保存结果到nc文件
   set var/title='eofs' eofs; set var/title='time functions' pcs; set var/title='statistics' sta
   save/file=eofresult.nc eofs,pcs,sta
同一行内写多个命令要用分号分开,而一个命令分在多行书写要在每行末尾加;\。
save命令是用来将数据写入文件的,除了nc,ferret还支持很多其他格式。

可见ferret处理海洋大气数据也是相当方便的。它的变量其实只是保存了一个表达式,真正要使用变量值的时候才会进行计算。这样一般来讲会节省时间和内存。但似乎每次使用变量值的时候都会重新计算,而不是第一次计算之后把结果保存下来,下次再使用的时候直接从内存调用。对于eof这样比较消耗时间的操作,这样做似乎不是很好。

上面从第三步开始的操作就只针对tsw变量了,要对每个变量都进行eof分析,需要重复步骤3-6. 可以写脚本文件用循环来完成。

ferret的另一个主要特点就是它的方便又强大的绘图功能。下一步会介绍使用ferret绘制eof的结果图,其中会包含ferret脚本文件的写法。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有