From 1f0842fc2a2cf2b18665fd05215855e442feeb22 Mon Sep 17 00:00:00 2001 From: XANTRONIX Industrial Date: Thu, 13 Mar 2025 16:31:41 -0400 Subject: [PATCH] Fix CAPE calculation --- lib/xmet/sounding.py | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/lib/xmet/sounding.py b/lib/xmet/sounding.py index c24e166..6f7d657 100644 --- a/lib/xmet/sounding.py +++ b/lib/xmet/sounding.py @@ -197,6 +197,12 @@ def between(n, a, b): return n > a and n < b class SoundingParameters(): + def __init__(self): + self.lcl = None + self.lfc = None + self.el = None + self.cape = None + @staticmethod def cape(temp_line: Series, moist_adiabat: Series, @@ -212,9 +218,6 @@ class SoundingParameters(): for pair in neighbors: p_env, p_parcel = pair - if not between(p_env, p_el, p_lfc): - continue - t_env = kelvin(temp_line[p_env]) t_parcel = kelvin(moist_adiabat[p_parcel]) gph = pressure_height(p_env) @@ -222,14 +225,14 @@ class SoundingParameters(): if gph_last is not None: gph_delta = gph - gph_last - cape += ((t_parcel - t_env) / t_env) * gph_delta + if between(p_env, p_el, p_lfc): + cape += ((t_parcel - t_env) / t_env) * gph_delta gph_last = gph return 9.8076 * cape - @staticmethod - def from_sounding(sounding: Sounding) -> Self: + def load_sounding(self, sounding: Sounding): temp_line = sounding.follow_temp() dry_adiabat = follow_dry_adiabat(sounding.samples[0].temp, sounding.samples[0].pressure) @@ -241,16 +244,22 @@ class SoundingParameters(): moist_adiabat = follow_moist_adiabat(*lcl) - lfc = moist_adiabat.intersect(temp_line, SeriesIntersection.GREATER) - el = moist_adiabat.intersect(temp_line, SeriesIntersection.LESSER, lfc[1]) + lfc = temp_line.intersect(moist_adiabat, SeriesIntersection.LESSER) + el = temp_line.intersect(moist_adiabat, SeriesIntersection.GREATER, lfc[1]-100) + self.lcl = lcl + self.lfc = lfc + self.el = el + self.cape = SoundingParameters.cape(temp_line, moist_adiabat, lfc, el) + + self.temp_line = temp_line + self.dry_adiabat = dry_adiabat + self.saturated_mr_line = saturated_mr_line + self.moist_adiabat = moist_adiabat + + @staticmethod + def from_sounding(sounding: Sounding) -> Self: params = SoundingParameters() - params.lcl = lcl - params.lfc = lfc - params.el = el - params.cape = SoundingParameters.cape(temp_line, - moist_adiabat, - lfc, - el) + params.load_sounding(sounding) return params