diff --git a/src/tools/climate.py b/src/tools/climate.py new file mode 100644 index 0000000..9589a2b --- /dev/null +++ b/src/tools/climate.py @@ -0,0 +1,79 @@ +from math import log10 + +ABSOLUTE_ZERO_C = -273.15 + + +def celsius_to_fahrenheit(celsius: float) -> float: + return celsius * 9 / 5 + 32 + + +def fahrenheit_to_celsius(fahrenheit: float) -> float: + return (fahrenheit - 32) / 9 * 5 + + +def celsius_to_kelvin(celsius: float) -> float: + return celsius - ABSOLUTE_ZERO_C + + +def kelvin_to_celsius(kelvin: float) -> float: + return kelvin + ABSOLUTE_ZERO_C + + +def fahrenheit_to_kelvin(fahrenheit: float) -> float: + return celsius_to_kelvin(fahrenheit_to_celsius(fahrenheit)) + + +def kelvin_to_fahrenheit(kelvin: float) -> float: + return celsius_to_fahrenheit(kelvin_to_celsius(kelvin)) + + +def saturation_vapor_pressure(temperature: float) -> float: + """ + Saturation vapor pressure for a given temperature (in °C) in hPa + """ + a = 7.5 if temperature >= 0 else 7.6 + b = 237.3 if temperature >= 0 else 240.7 + return 6.1078 * 10 ** ((a * temperature) / (b + temperature)) + + +def vapor_pressure(relative_humidity: float, temperature: float) -> float: + """ + Vapor pressure for a given relative humidity (in %) and temperature (in °C) in hPa + """ + return relative_humidity / 100 * saturation_vapor_pressure(temperature) + + +def relative_humidity(temperature: float, due_point: float) -> float: + """ + Relative humidity for a given temperature (in °C) in and due point (in °C) + """ + return 100 * saturation_vapor_pressure(due_point) / saturation_vapor_pressure(temperature) + + +def absolute_humidity_from_humidity(relative_humidity: float, temperature: float) -> float: + """ + Absolute humidity for a given relative humidity (in %) and temperature (in °C) in g/m³ + """ + mw = 18.016 + rs = 8314.3 + return 10**5 * mw / rs * vapor_pressure(relative_humidity, temperature) / celsius_to_kelvin(temperature) + + +def absolute_humidity_from_due_point(due_point: float, temperature: float) -> float: + """ + Absolute humidity for a given due point (in °C) and temperature (in °C) in g/m³ + """ + mw = 18.016 + rs = 8314.3 + return 10**5 * mw / rs * saturation_vapor_pressure(due_point) / celsius_to_kelvin(temperature) + + +def due_point(relative_humidity: float, temperature: float) -> float: + """ + Due Point for a given relative humidity (in %) and temperature (in °C) in °C + """ + a = 7.5 if temperature >= 0 else 7.6 + b = 237.3 if temperature >= 0 else 240.7 + v = log10(vapor_pressure(relative_humidity, temperature) / 6.1078) + + return b * v / (a - v) diff --git a/src/tools/types.py b/src/tools/types.py index 4632100..ddd56ba 100644 --- a/src/tools/types.py +++ b/src/tools/types.py @@ -35,4 +35,13 @@ class String(str): class List(list): - pass + def moving_window(self, size: int = 2) -> Iterable[List]: + if len(self) % size != 0: + raise ValueError("number of list items must be divisible by size") + + for i in range(len(self) // size): + this_window = List() + for j in range(size): + this_window.append(self[i * size + j]) + + yield this_window