From dc4e6f3423ebd01df86a7188988ef9cc23b31348 Mon Sep 17 00:00:00 2001 From: XANTRONIX Industrial <xan@xantronix.com> Date: Mon, 24 Feb 2025 17:25:18 -0500 Subject: [PATCH] Initial commit of sounding.py --- lib/xmet/sounding.py | 66 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 lib/xmet/sounding.py diff --git a/lib/xmet/sounding.py b/lib/xmet/sounding.py new file mode 100644 index 0000000..62b8529 --- /dev/null +++ b/lib/xmet/sounding.py @@ -0,0 +1,66 @@ +import datetime +import shapely + +LAPSE_RATE_DRY = 9.8 / 1000 # degrees C per 1000m +LAPSE_RATE_MOIST = 4.0 / 1000 + +MIXING_RATIO_CONST = 621.97 + +class SoundingSample(): + __slots__ = ( + 'id', 'sounding_id', 'elapsed', 'pressure', 'pressure_qa', + 'height', 'height_qa', 'temp', 'temp_qa', 'humidity', + 'dewpoint', 'wind_dir', 'wind_speed' + ) + + id: int + sounding_id: int + elapsed: int + pressure: float + pressure_qa: str + height: float + height_qa: str + temp: float + temp_qa: str + humidity: float + dewpoint: float + wind_dir: float + wind_speed: float + + def vapor_pressure(self) -> float: + return 6.11 * 10 * ( + (7.5 * self.dewpoint) / (237.3 * self.dewpoint) + ) + + def saturated_vapor_pressure(self) -> float: + return 6.11 * 10 * ( + (7.5 * self.temp) / (237.3 * self.temp) + ) + + def mixing_ratio(self) -> float: + e = self.vapor_pressure() + + return 621.97 * (e / (self.pressure - e)) + + def saturated_mixing_ratio(self) -> float: + es = self.saturated_vapor_pressure() + + return 621.97 * (es / (self.pressure - es)) + + def is_saturated(self) -> bool: + return self.humidity >= 100.0 + +class Sounding(): + __slots__ = ( + 'id', 'station', 'timestamp_observed', 'timestamp_released', + 'data_source_pressure', 'data_source_other', 'samples', 'coord' + ) + + id: int + station: str + timestamp_observed: datetime.datetime + timestamp_released: datetime.datetime + data_source_pressure: str + data_source_other: str + coord: shapely.Point + samples: list[SoundingSample]