使用表面压力来屏蔽4D NetCDF变量。

huangapple go评论59阅读模式
英文:

use surface pressure to mask 4D netcdf variable

问题

我已经合并了一个3D表面气压场(来自ERA5,从Pa转换为hPa,作为lat、lon和时间的函数)与一个也是作为压力层的函数的4D变量(lat、lon、时间、层级)。

因此,我的netcdf文件有两个字段,温度是4D的:

float t(time, level, latitude, longitude)

表面气压是3D的:

float sp(time, latitude, longitude)

压力维度"level"当然是一个向量:

int level(level)

我想要做的是为温度创建一个掩码,其中压力超过表面气压的所有位置都会被掩盖。

我知道如何使用 nco 使用简单的阈值创建一个掩码:

ncap2 -s 'mask=(level>800)' t_ps.nc mask.nc

但当我尝试使用表面气压时:

ncap2 -s 'mask=(level>sp)' t_ps.nc mask.nc

我会得到错误:

ncap2: ERROR level and template sp share no dimensions

我认为我需要做的是创建一个新的变量,比如 "level3d",它会复制压力 "level" 以成为lat和lon的函数,然后我可以有效地使用它来创建掩码,是的吗?但我不确定如何在维度上做到这一点(我考虑过 cdo enlarge 但无法使其工作)。

顺便说一下,代替发布数据,这是我用来检索数据的Python API脚本:

import cdsapi
c = cdsapi.Client()
c.retrieve(
    'reanalysis-era5-single-levels-monthly-means',
    {
        'format': 'netcdf',
        'product_type': 'monthly_averaged_reanalysis',
        'variable': 'surface_pressure',
        'year': '2020',
        'month': '03',
        'time': '00:00',
    },
    'ps.nc')
    
c.retrieve(
    'reanalysis-era5-pressure-levels-monthly-means',
    {
        'format': 'netcdf',
        'product_type': 'monthly_averaged_reanalysis',
        'variable': 'temperature',
        'pressure_level': [
            '1', '2', '3',
            '5', '7', '10',
            '20', '30', '50',
            '70', '100', '125',
            '150', '175', '200',
            '225', '250', '300',
            '350', '400', '450',
            '500', '550', '600',
            '650', '700', '750',
            '775', '800', '825',
            '850', '875', '900',
            '925', '950', '975',
            '1000',
        ],
        'year': '2020',
        'month': '03',
        'time': '00:00',
    },
    't.nc')

希望这有助于解决你的问题。如果你需要进一步的帮助,请随时告诉我。

英文:

I've merged a 3D surface pressure field (ERA5, converted from Pa to hPa, function of lat,lon and time) with a 4D variable which is also a function of pressure levels (lat,lon,time,level).

So, my netcdf file has two fields, Temperature which is 4D:

float t(time, level, latitude, longitude)

surface pressure, which is 3d:

float sp(time, latitude, longitude)

The pressure dimension "level" is of course a vector:

int level(level)

What I want to do is make a mask for temperature for all locations where the pressure exceeds the surface pressure.

I know how to use nco to make a mask using a simple threshold:

 ncap2 -s 'mask=(level>800)' t_ps.nc mask.nc

But of course when I try to use the surface pressure

ncap2 -s 'mask=(level>sp)' t_ps.nc mask.nc 

I get the error

ncap2: ERROR level and template sp share no dimensions

I think what I need to do is make a new variable like "level3d" which duplicates the pressure "level" to be a function of lat and lon, which I can then use to efficiently make the mask, yes? But I'm not sure how to do this with a dimension (I thought about cdo enlarge but couldn't get it to work).

By the way, instead of posting the data, this is the python api script I used to retrieve it

import cdsapi
c = cdsapi.Client()
c.retrieve(
    'reanalysis-era5-single-levels-monthly-means',
    {
        'format': 'netcdf',
        'product_type': 'monthly_averaged_reanalysis',
        'variable': 'surface_pressure',
        'year': '2020',
        'month': '03',
        'time': '00:00',
    },
    'ps.nc')

c.retrieve(
    'reanalysis-era5-pressure-levels-monthly-means',
    {
        'format': 'netcdf',
        'product_type': 'monthly_averaged_reanalysis',
        'variable': 'temperature',
        'pressure_level': [
            '1', '2', '3',
            '5', '7', '10',
            '20', '30', '50',
            '70', '100', '125',
            '150', '175', '200',
            '225', '250', '300',
            '350', '400', '450',
            '500', '550', '600',
            '650', '700', '750',
            '775', '800', '825',
            '850', '875', '900',
            '925', '950', '975',
            '1000',
        ],
        'year': '2020',
        'month': '03',
        'time': '00:00',
    },
    't.nc')

答案1

得分: 1

如果我正确理解问题,您应该能够使用CDO来实现这一点,使用aexpr或expr以及clev(这应该使您能够访问压力水平)。如果其中一个变量是表面变量,那么当您混合匹配3D/4D变量时,CDO应该只用它来进行所有垂直层次的计算。我猜NCO要严格得多,需要数据结构完全相同。

以下是可能有效的:

cdo -L -aexpr,'mask=(clev(Temperature)>sp)' infile outfile

英文:

If I understand the question properly, you should be able to do this using CDO, using either aexpr or expr along with clev (which should give you access to the pressure level). If one of the variables is a surface variable then CDO should just use it for calculations for all vertical levels when you mix and matched 3D/4D variables. NCO, I guess, is a lot stricter and requires a 100% identical data structure.

The following is likely to work:

cdo -L -aexpr,'mask=(clev(Temperature)>sp)' infile outfile

答案2

得分: 1

你对NCO行为的诊断基本正确。"broadcast"操作失败,因为levelsp都是数组(不是标量),它们没有共享维度。修复方法是创建并使用一个临时的三维版本的level,类似以下方式:

ncap2 -s 'level_3D[level,latitude,longitude]=level;mask=(level_3D>sp)' t_ps.nc mask.nc
英文:

Your diagnosis of the NCO behavior is essentially correct. The "broadcast"

ncap2 -s 'mask=(level>sp)' t_ps.nc mask.nc

fails because level and sp are arrays (not scalars) that share no dimensions. The fix would be to create and use a temporary 3D version of level with something like

ncap2 -s 'level_3D[level,latitude,longitude]=level;mask=(level_3D>sp)' t_ps.nc mask.nc

答案3

得分: 0

感谢Robert指向了我clev,有了这个,我找到了以下使用enlarge的解决方案。这有点笨拙,也许有人有更简洁的解决方案?这现在直接在我示例API脚本中下载的两个字段上工作。

# 创建3D级别字段
cdo enlarge,t.nc -expr,"l=clev(t)" t.nc level.nc

# 合并在一起
cdo -O merge t.nc ps.nc level.nc t_ps_p.nc

# 创建掩码,###请注意,这里我有一个100的因子将Pa->hPa
cdo setctomiss,0 -expr,'mask=(l*100)<sp' t_ps_p.nc mask.nc

# 掩码数据
cdo mul t.nc mask.nc masked_t.nc
英文:

THANKS so much to Robert for pointing me to clev, with this I found the following solution using enlarge too. It is a bit clunky, maybe someone has a more streamlined solution? This works directly now on the two fields downloaded in my example api script.

# make 3d level field
cdo enlarge,t.nc -expr,&quot;l=clev(t)&quot; t.nc level.nc

# merge together
cdo -O  merge t.nc ps.nc level.nc t_ps_p.nc

# make mask, ###note here I have a 100 factor to change Pa-&gt;hPa
cdo setctomiss,0 -expr,&#39;mask=(l*100)&lt;sp&#39; t_ps_p.nc mask.nc

# mask the data
cdo mul t.nc mask.nc masked_t.nc 

huangapple
  • 本文由 发表于 2023年6月1日 18:45:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76381084.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定