- 积分
- 5344
- 贡献
-
- 精华
- 在线时间
- 小时
- 注册时间
- 2012-8-28
- 最后登录
- 1970-1-1
|
登录后查看更多精彩内容~
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 Masterpiece 于 2020-4-27 20:12 编辑
Python截取不规则区域内格点
做EOF的时候,一般都要区域内的格点进行分析,以避免区域外的信息分担EOF权重。
取区域内的格点的做法是我的舍友涌哥教我的方法,大家可以借鉴一下思路和做法吧!
首先要准备好区域范围的shp文件,文件提供了边界的经纬度,在程序中用shapefile库进行读取:
- sf=shapefile.Reader("D:\\dt\\SC\\Sichuan_province")
- Shapes = sf.shapes()
- boundary = Shapes[0].points
复制代码 第二步就是关键了,这步是用matplotlib根据得到的经纬度点,建立一个path:
- from matplotlib.path import Path
- p= Path(boundary)
复制代码 这时候得到的p就是一个path边界的类变量,其中包含类函数contains_points来判断所给格点是否在区域内。例如:- x=100
- y=30
- p.contains_points([[x,y]])
复制代码 如果这个(100,30)的点在path区域内,within得到值True,反之是False。
并且contains_points可以将复数个位置点以(n x 2)的数组的形式输入,返回一个对应的布尔数组,又例如:
- grid=np.array( [[[100,30],[100,50]],[[100,30],[100,30]]] )
- within=p.contains_points(grid.reshape(4,2))
复制代码 这时类函数返回within得到一个布尔数组: 这时候就可以利用这个布尔数组对numpy数组进行取数了。
比如我要画散点图,那必须知道散点对应的经纬度位置。先利用nc文件的lon、lat信息建立二维的经纬度格点:
- lons, lats = np.meshgrid(lon, lat)
复制代码 这时候lons和lats就是一个(n,m)的数组,对应着每个格点的经度或纬度,以lons为例:
- [[ 0. 2.5 5. ... 352.5 355. 357.5]
- [ 0. 2.5 5. ... 352.5 355. 357.5]
- [ 0. 2.5 5. ... 352.5 355. 357.5]
- ...
- [ 0. 2.5 5. ... 352.5 355. 357.5]
- [ 0. 2.5 5. ... 352.5 355. 357.5]
- [ 0. 2.5 5. ... 352.5 355. 357.5]]
复制代码 然后再利用布尔数组mask,将其中为True的对应格点的经度和纬度返回来,并且做一次坐标投影变换:- grib=np.stack((lons,lats),axis=-1)
- mask=p.contains_points(grib.reshape(lat_num*lon_num,2))
- mask=mask.reshape(lat_num,lon_num)
- x,y=m(lons[mask],lats[mask])
复制代码 这时候在边界内的格点的图上投影坐标x,y就得到了,于是画散点图!
- m.scatter(x,y,s=50, marker='o', color='g', zorder=6)
复制代码 这样就可以在图上标出在区域内的格点位置了。
所以可以使用类似思路将数据提取出来。
开篇图片所使用的代码,以四川省为例。
所用到的文件我放在附件里边。
- import matplotlib.pyplot as plt
- from mpl_toolkits.basemap import Basemap
- import numpy as np
- import netCDF4 as nc
- from matplotlib.path import Path
- import shapefile
- af=nc.Dataset('test.nc')
- lat=af.variables['latitude'][:]
- lon=af.variables['longitude'][:]
- p72=af.variables['p72.162'][0,:,:]/100
- lat_num=len(lat)
- lon_num=len(lon)
- sf=shapefile.Reader("D:\\dt\\SC\\Sichuan_province")
- Shapes = sf.shapes()
- boundary = Shapes[0].points
- p= Path(boundary)
- lons, lats = np.meshgrid(lon, lat)
- grib=np.stack((lons,lats),axis=-1) #变为(n,m,2)的经纬度的点
- mask=p.contains_points(grib.reshape(lat_num*lon_num,2)) #变为(n*m,2)的经纬度的点,否则出错
- # 如果点在路径之内,对应的mask赋值为False,否则为Ture
- mask=mask.reshape(lat_num,lon_num)# 恢复到 (n,m)
- print(lons[mask])
- lon_leftup=90-2.5/2;lat_leftup=40+2.5/2
- lon_rightdown=120+2.5/2;lat_rightdown=20-2.5/2
- fig, ax = plt.subplots(figsize=(14,9))
- m = Basemap(projection='cyl',
- llcrnrlat=lat_rightdown, urcrnrlat=lat_leftup,
- llcrnrlon=lon_leftup, urcrnrlon=lon_rightdown,
- resolution='i')
- m.drawcoastlines(linewidth=0.3, color='black')
- m.readshapefile('D:\\dt\\SC\\Sichuan_province', 'sc', color='k', linewidth=0.6)
- x,y=m(lons[mask],lats[mask])
- m.scatter(x,y,s=50, marker='o', color='g', zorder=6)
- x,y=m(lons[~mask],lats[~mask])
- m.scatter(x,y,s=50, marker='x', color='r', zorder=6)
- parallels = np.arange(20,45,5) #lat
- m.drawparallels(parallels,labels=[True,False,False,False],linewidth=0.6,dashes=[1,4])
- meridians = np.arange(90,125,5) #lon
- m.drawmeridians(meridians,labels=[False,False,False,True],linewidth=0.6,dashes=[1,4])
- plt.yticks(parallels,len(parallels)*[''])
- plt.xticks(meridians,len(meridians)*[''])
- plt.savefig('grid_within.png',dpi=300,bbox_inches='tight')
- plt.show()
复制代码
--所用文件--
grid_within.rar
(136.94 KB, 下载次数: 41)
|
|