【问题标题】:Getting a "ValueError: zero-size array to reduction operation minimum which has no identity" when using metpy cape_cin function使用metpy cape_cin函数时获取“ValueError:零大小数组到没有身份的减少操作最小值”
【发布时间】:2023-05-05 04:59:01
【问题描述】:

我正在尝试使用metpy 的 cape_cin 和 get_layer 函数计算指定层中的 cape 和 cin。我为从 NCDC 服务器访问的 RAP 垂直配置文件执行此操作,用于 3 种不同的包裹类型(ML、MU 和 SB)。当我尝试计算 mu 和 sb 配置文件时出现此错误ValueError: zero-size array to reduction operation minimum which has no identity,但不适用于 ml 配置文件......即使我以完全相同的方式计算层:

首先,我必须从 RAP 垂直剖面创建压力、温度、露点和高度的垂直剖面:

from datetime import datetime, timedelta   
from siphon.catalog import TDSCatalog
from siphon.ncss import NCSS
import numpy as np
from metpy.units import units
import cartopy.crs as ccrs
from metpy.calc import (dewpoint_from_relative_humidity, mixed_parcel, most_unstable_parcel, parcel_profile, pressure_to_height_std, lcl, height_to_pressure_std, get_layer, cape_cin)

year=2019
month=5
day=23
hour=0

cenlat = 34.91269
cenlon = -98.21048

time_start = datetime(year, month, day, hour, 0) #specified time
hour = time_start.hour
if hour < 10:
    hour = '0'+str(hour)
day = time_start.day
if day < 10:
    day = '0'+str(day)
month = time_start.month
if month < 10:
    month = '0'+str(month)

cat = TDSCatalog('https://www.ncdc.noaa.gov/thredds/catalog/model-rap130-old/'+str(time_start.year)+str(month)+'/'+str(time_start.year)+str(month)+str(day)+'/catalog.html?dataset=rap130-old/'+str(time_start.year)+str(month)+'/'+str(time_start.year)+str(month)+str(day)+'/rap_130_'+str(time_start.year)+str(month)+str(day)+'_'+str(hour)+'00_000.grb2')
latest_ds = list(cat.datasets.values())[0]
print(latest_ds.access_urls)
ncss = NCSS(latest_ds.access_urls['NetcdfSubset'])

query = ncss.query()
query.variables('Pressure_surface').variables('Geopotential_height_isobaric').variables('Geopotential_height_surface').variables('Relative_humidity_isobaric').variables('Temperature_isobaric').variables('Dewpoint_temperature_height_above_ground').variables('Temperature_height_above_ground').variables
query.add_lonlat().lonlat_box(cenlon-2.1, cenlon +2.1, cenlat-2.1, cenlat+2.1)
data1 = ncss.get_data(query)
dlev = data1.variables['Geopotential_height_isobaric'].dimensions[1]
dlat = data1.variables['Geopotential_height_isobaric'].dimensions[2]
dlon = data1.variables['Geopotential_height_isobaric'].dimensions[3]

SFCP = (np.asarray(data1.variables['Pressure_surface'][:])/100.) * units('hPa')
hgt = np.asarray(data1.variables['Geopotential_height_isobaric'][:]) * units('meter')
sfc_hgt = np.asarray(data1.variables['Geopotential_height_surface'][:]) * units('meter')
Temp_up = np.asarray(data1.variables['Temperature_isobaric'][:]) * units('kelvin')
RH_up = np.asarray(data1.variables['Relative_humidity_isobaric'][:])
Td = (np.asarray(data1.variables['Dewpoint_temperature_height_above_ground'][:]) * units('kelvin')).to('degC')
T = np.asarray(data1.variables['Temperature_height_above_ground'][:]) * units('kelvin')

# Get the dimension data
lats_r = data1.variables[dlat][:]
lons_r= data1.variables[dlon][:]
lev = (np.asarray(data1.variables[dlev][:])/100.) * units('hPa')

# Set up our array of latitude and longitude values and transform to the desired projection.
flon = float(cenlon)
flat = float(cenlat)
crs = ccrs.PlateCarree()
crlons, crlats = np.meshgrid(lons_r[:]*1000, lats_r[:]*1000)
trlatlons = crs.transform_points(ccrs.LambertConformal(central_longitude=265, central_latitude=25, standard_parallels=(25.,25.)),crlons,crlats)
trlons = trlatlons[:,:,0]
trlats = trlatlons[:,:,1]
dlon = np.abs(trlons - cenlon)
dlat = np.abs(trlats - cenlat)
ilon = np.where(dlon == np.min(dlon)) #position in the dlon array with minimal difference between gridpoint lon and input lon
ilat = np.where(dlat == np.min(dlat)) #position in the dlat array with minimal difference between gridpoint lat and input lat

Tdc_up = dewpoint_from_relative_humidity(Temp_up[0,:,ilat[0][0], ilon[1][0]],RH_up[0,:,ilat[0][0], ilon[1][0]]/100)

p_sounding = np.sort(np.append(lev, SFCP[0,ilat[0][0], ilon[1][0]]))
ind = np.where(p_sounding >= SFCP[0,ilat[0][0], ilon[1][0]])[0][0]
hgt_sounding = np.insert(hgt[0,:,ilat[0][0], ilon[1][0]].magnitude, ind, sfc_hgt[0,ilat[0][0], ilon[1][0]].magnitude) * hgt.units
T_sounding = (np.insert(Temp_up[0,:,ilat[0][0], ilon[1][0]].magnitude, ind, T[0,0,ilat[0][0], ilon[1][0]].magnitude) * T.units).to(Tdc_up.units)
Td_sounding = np.insert(Tdc_up.magnitude, ind, Td[0,0,ilat[0][0], ilon[1][0]].magnitude) * Tdc_up.units
p_skewt = p_sounding[p_sounding <= SFCP[0,ilat[0][0], ilon[1][0]]]
hgt_skewt = hgt_sounding[p_sounding <= SFCP[0,ilat[0][0], ilon[1][0]]]
T_skewt = T_sounding[p_sounding <= SFCP[0,ilat[0][0], ilon[1][0]]]
Td_skewt = Td_sounding[p_sounding <= SFCP[0,ilat[0][0], ilon[1][0]]]

AGLhgts = hgt_skewt[::-1]-hgt_skewt[-1]

接下来,我使用 mixed_pa​​rcel、most_unstable 和 parcel_profile 函数为每种宗地类型创建垂直剖面,并计算我要计算 cape_cin 的层的 etop 和底部的压力值(LCL 到 LCL+2km):

ml_p, ml_T, ml_Td = mixed_parcel(np.flip(p_skewt), np.flip(T_skewt), np.flip(Td_skewt))
ml_profile = parcel_profile(p_skewt[::-1], ml_T, ml_Td)
ml_profile = (ml_profile - 273.15*units('kelvin')).magnitude*units('degC')

mu_p, mu_T, mu_Td, mu_index = most_unstable_parcel(np.flip(p_skewt), np.flip(T_skewt), np.flip(Td_skewt))
mu_profile = parcel_profile(p_skewt[::-1], mu_T, mu_Td)
mu_profile = (mu_profile - 273.15*units('kelvin')).magnitude*units('degC')

#Note: sbpcl_profile will have the exact same values of p_skewt, T_skewt, and Td_skewt in pprof below:
pprof = parcel_profile(p_skewt[::-1], T_skewt[-1], Td_skewt[-1])
pprof = (pprof - 273.15*units('kelvin')).magnitude*units('degC')

mllcl = lcl(ml_p, ml_T, ml_Td)
mllcl_h = pressure_to_height_std(mllcl[0]) - hgt_skewt[-1]

mulcl = lcl(mu_p, mu_T, mu_Td)
mulcl_h = pressure_to_height_std(mulcl[0]) - hgt_skewt[-1]

sblcl = lcl(p_skewt[-1], T_skewt[-1], Td_skewt[-1])
sblcl_h = pressure_to_height_std(sblcl[0]) - hgt_skewt[-1]

mllcl2000 = mllcl_h + 2*units('kilometer')
mulcl2000 = mulcl_h + 2*units('kilometer')
sblcl2000 = sblcl_h + 2*units('kilometer')
mllcl2000_p = height_to_pressure_std(mllcl2000)
mulcl2000_p = height_to_pressure_std(mulcl2000)
sblcl2000_p = height_to_pressure_std(sblcl2000)

计算完所有这些后,我使用 get_layer 函数创建压力、温度、露点和地块温度的数组,我需要计算 cape_cin,然后去计算感兴趣层中的实际 cape_cin 值:

ml_LCL_CAPE_layer = get_layer(p_skewt, T_skewt, Td_skewt, ml_profile[::-1], bottom = mllcl[0], depth = mllcl[0] - mllcl2000_p)
mu_LCL_CAPE_layer = get_layer(p_skewt, T_skewt, Td_skewt, mu_profile[::-1], bottom = mulcl[0], depth = mulcl[0] - mulcl2000_p)
sb_LCL_CAPE_layer = get_layer(p_skewt, T_skewt, Td_skewt, pprof[::-1], bottom = sblcl[0], depth = sblcl[0] - sblcl2000_p)

mlLCLCAPE = cape_cin(ml_LCL_CAPE_layer[0], ml_LCL_CAPE_layer[1], ml_LCL_CAPE_layer[2], ml_LCL_CAPE_layer[3])
muLCLCAPE = cape_cin(mu_LCL_CAPE_layer[0], mu_LCL_CAPE_layer[1], mu_LCL_CAPE_layer[2], mu_LCL_CAPE_layer[3])
sbLCLCAPE = cape_cin(sb_LCL_CAPE_layer[0], sb_LCL_CAPE_layer[1], sb_LCL_CAPE_layer[2], sb_LCL_CAPE_layer[3])

mlLCLCAPEcin = mlLCLCAPE[0] + mlLCLCAPE[1]
muLCLCAPEcin = muLCLCAPE[0] + muLCLCAPE[1]
sbLCLCAPEcin = sbLCLCAPE[0] + sbLCLCAPE[1]

3 个 get_layer 函数中每一个的压力、温度、露点和地块温度的数组似乎都填充了正确的值,并且每种地块类型的这 4 个数组都是相同的形状。上面的 mlLCLCAPEcin 计算给出了正确的输出(99.26 j/kg - 当我在 SkewT 上绘制它时验证),但 MU 和 SB 配置文件的完全相同的计算给出了上面提到的错误。我正在使用 Metpy v 1.1,并尝试使用不同的位置和来自不同预测时间的输出,但仍然遇到相同的问题。

【问题讨论】:

  • 请编辑问题以将其限制为具有足够详细信息的特定问题,以确定适当的答案。
  • 我将首先仔细检查您在 mu_LCL_CAPE_layersb_LCL_CAPE_layer 的层中实际获得的内容。我的第一个猜测是它们是空的。如果这没有为您指明正确的方向,请务必编辑您的问题,以包含完整、独立、最小版本的代码,以便重现:*.com/help/minimal-reproducible-example
  • 我仔细检查了数组对于 mu 和 sb 计算是否为空。我已经编辑了上面的问题,并包含了重现该区域所需的最少代码量。感谢您的指导。

标签: python arrays valueerror metpy


【解决方案1】:

如果我修复上面的示例代码(存在一些名称问题和一些索引问题):

T_sounding = (np.insert(Temp_up[0,:,ilat[0][0], ilon[1][0]].magnitude, ind, Temp_up[0,0,ilat[0][0], ilon[1][0]].magnitude) * Temp_up.units).to(Tdc_up.units)
Td_sounding = np.insert(Tdc_up.magnitude, ind, Tdc_up[0].magnitude) * Tdc_up.units

我现在没有遇到任何错误。如果我上面的修复无法为您解决,那么了解您是否正在运行最新的 MetPy 1.1 会很有帮助。

【讨论】:

  • 我使用的是 MetPy 1.1。修复后这也适用于我——但是我意识到我在 1/8 发布的包含代码的帖子中犯了一个错误。 T 和 Td 应该包含在我从 RAP 数据中查询的变量中(它们用于温度/露点高度 AGL)——所以 T_sounding 和 Td_sounding 名称/索引问题只是我在发布最小版本时意外忘记了它们代码(尽管在某种程度上这些可能仍然是问题?)。很抱歉对此造成的所有困惑 - 我再次更新了原始问题以包含此信息。
  • 好的,这是为我复制的,让我看看...
  • 我还没有机会深入研究,但我很确定这是 MetPy 中的一个错误。我已经打开了一个问题并将其标记为下一个版本:github.com/Unidata/MetPy/issues/2315
最近更新 更多