Source code for emodpy_malaria.weather.weather_variable
#!/usr/bin/env python3
"""
Weather variable module implement functionality for working with weather variables.
"""
from __future__ import annotations
from enum import Enum
from typing import Any, Dict, Iterable, List, NoReturn, Union
[docs]
class WeatherVariable(Enum):
"""Weather variables required by EMOD."""
# TODO: Consider whether ground temperature.
AIR_TEMPERATURE = "airtemp"
RELATIVE_HUMIDITY = "humidity"
RAINFALL = "rainfall"
LAND_TEMPERATURE = "landtemp"
def __hash__(self):
"""Hash method for a WeatherVariable object."""
return hash(self.name + self.value)
[docs]
@classmethod
def list(cls, exclude: Union[WeatherVariable, List[WeatherVariable]] = None) -> List[WeatherVariable]:
"""
List of all weather variables or a subset if 'exclude' argument is used.
Args:
exclude: (Optional) List of weather variables to be excluded.
Returns:
List of all or a subset of weather variables.
"""
exclude = exclude or []
exclude = [exclude] if isinstance(exclude, WeatherVariable) else exclude
if not isinstance(exclude, List) or len(exclude) > 0 and not isinstance(exclude[0], WeatherVariable):
raise TypeError("Exclude variable tpy is not a list of WeatherVariable.")
items = [cls.AIR_TEMPERATURE, cls.RELATIVE_HUMIDITY, cls.RAINFALL, cls.LAND_TEMPERATURE]
return [t for t in items if t not in exclude]
[docs]
@classmethod
def validate_types(cls,
value_dict: Dict[WeatherVariable, Any],
value_types: Union[Any, List[Any]] = None) -> NoReturn:
"""
Validate dictionary keys are of type WeatherVariable and values are of specified type.
Args:
value_dict: Dictionary to be validated.
value_types: Dictionary value types.
Returns:
None
"""
if value_dict is None:
return
if not isinstance(value_dict, Dict): # Main object must be a dict
raise TypeError("Not a dictionary.")
for variable, item in value_dict.items():
if not isinstance(variable, WeatherVariable): # Keys must be WeatherVariable
raise TypeError("Keys are not of WeatherVariable type.")
if value_types is not None:
value_types: Union[Any, List[Any]] = value_types if isinstance(value_types, Iterable) else [value_types]
type_ok = [tp is None and item is None for tp in value_types if not tp] # is None if specified
type_ok.extend([isinstance(item, tp) for tp in value_types if tp]) # is instance of a type
if all([not t for t in type_ok]): # if all type tests are false
raise TypeError(f"Values must be of type {str(value_types)}.")