简体   繁体   English

使用Python的NetCDF文件的圆形lat / lon裁剪

[英]Circular lat/lon crop of a NetCDF file with Python

I'm working on a project which imports raw binary radar data from the National Weather Service ftp site to a server. 我正在开发一个项目,将国家气象服务ftp站点的原始二进制雷达数据导入服务器。 Using an the Weather and Climate Toolkit data-export tool, I convert the data into a netCDF file. 使用Weather and Climate Toolkit数据导出工具,我将数据转换为netCDF文件。 The following is the result of a "ncdump -h" command on the .nc file: 以下是.nc文件中“ncdump -h”命令的结果:

netcdf last {
dimensions:
        lat = 800 ;
        lon = 1200 ;
        time = 1 ;
variables:
        double cref(time, lat, lon) ;
                cref:long_name = "Level-III Composite Reflectivity (16 levels / 248 nm)" ;
                cref:missing_value = -999. ;
                cref:units = "dBZ" ;
        double lat(lat) ;
                lat:units = "degrees_north" ;
                lat:spacing = "0.010995604400775773" ;
                lat:datum = "NAD83 - NOAA Standard" ;
        double lon(lon) ;
                lon:units = "degrees_east" ;
                lon:spacing = "0.010983926942902655" ;
                lon:datum = "NAD83 - NOAA Standard" ;
        int time(time) ;
                time:units = "seconds since 1970-1-1" ;

// global attributes:
                :title = "Level-III Composite Reflectivity (16 levels / 248 nm)  22:23:47 UTC  10/20/2016" ;
                :Conventions = "CF-1.0" ;
                :History = "Exported to NetCDF-3 CF-1.0 conventions by the NOAA Weather and Climate Toolkit (version 3.7.9)  \n",
                    "Export Date: Thu Oct 20 16:11:07 EDT 2016" ;
                :geographic_datum_ESRI_PRJ = "GEOGCS[\"GCS_North_American_1983\",DATUM[\"D_North_American_1983\",SPHEROID[\"GRS_1980\",6378137,298.257222101]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.0174532925199433]]" ;
                :geographic_datum_OGC_WKT = "GEOGCS[\"NAD83\", DATUM[\"NAD83\", SPHEROID[\"GRS_1980\", 6378137.0, 298.25722210100002],TOWGS84[0,0,0,0,0,0,0]], PRIMEM[\"Greenwich\", 0.0], UNIT[\"degree\",0.017453292519943295], AXIS[\"Longitude\",EAST], AXIS[\"Latitude\",NORTH]]" ;
}

I want to find the largest entry for the cref variable, which I can do fairly easily with the netCDF4 and numpy libraries in python: 我想找到cref变量的最大条目,我可以很容易地使用python中的netCDF4和numpy库:

import netCDF4
import numpy

netcdf = netCDF4.Dataset("last.nc")
var = netcdf.variables['cref']
print(numpy.nanmax(var))
print(numpy.nanmin(var))

However, I am hoping to filter the netCDF files so the max and min are found only within a certain distance of a given lat/lon. 但是,我希望过滤netCDF文件,以便仅在给定纬度/经度的某个距离内找到最大值和最小值。 In other words, I'm hoping to "crop" a circle of a specified radius around a specified lat/lon. 换句话说,我希望在指定的纬度/经度周围“裁剪”指定半径的圆。 I've found how to crop a square through another SO thread, but can't figure out how a circle would work. 我已经找到了如何通过另一个SO线程裁剪一个方块 ,但无法弄清楚一个圆圈是如何工作的。

I would calculate the distance between the center and each lat/lon pair (2D grid), and use that to construct a mask which you can apply to your data. 我将计算中心与每个纬度/经度对(2D网格)之间的距离,并使用它来构建可应用于数据的蒙版。 Once masked, you can again simply use numpy functions to calculate statistics like max() . 一旦屏蔽,您可以再次使用numpy函数来计算max()等统计信息。

For example, using the haversine() function from https://stackoverflow.com/a/4913653/3581217 , modified to a vectorized version which you can directly apply onto numpy arrays: 例如,使用https://stackoverflow.com/a/4913653/3581217中haversine()函数,修改为可直接应用于numpy数组的矢量化版本:

import numpy as np
import matplotlib.pylab as pl

def haversine(lon1, lat1, lon2, lat2):
    # convert decimal degrees to radians 
    lon1 = np.deg2rad(lon1)
    lon2 = np.deg2rad(lon2)
    lat1 = np.deg2rad(lat1)
    lat2 = np.deg2rad(lat2)

    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2
    c = 2 * np.arcsin(np.sqrt(a)) 
    r = 6371
    return c * r

# Latitude / longitude grid
lat = np.linspace(50,54,16)
lon = np.linspace(6,9,12)

# Center coordinates
clat = 52
clon = 7 

max_dist = 100      # max distance in km

# Calculate distance between center and all other lat/lon pairs
distance = haversine(lon[:,np.newaxis], lat, clon, clat) 

# Mask distance array where distance > max_dist
distance_m = np.ma.masked_greater(distance, max_dist)

# Dummy data
data = np.random.random(size=[lon.size, lat.size])

# Test: set a value outside the max_dist circle to a large value:
data[0,0] = 10

# Mask the data array based on the distance mask
data_m = np.ma.masked_where(distance > max_dist, data)

pl.figure()
pl.subplot(221)
pl.title('distance (km)')
pl.pcolormesh(lon, lat, np.transpose(distance))
pl.colorbar()

pl.subplot(222)
pl.title('distance < max_dist (km)')
pl.pcolormesh(lon, lat, np.transpose(distance_m))
pl.colorbar()

pl.subplot(223)
pl.title('all data; max = {0:.1f}'.format(data.max()))
pl.pcolormesh(lon, lat, np.transpose(data))
pl.colorbar()

pl.subplot(224)
pl.title('masked data; max = {0:.1f}'.format(data_m.max()))
pl.pcolormesh(lon, lat, np.transpose(data_m))
pl.colorbar()

Which results in: 结果如下:

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM