Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better implementation of maps_freq: convert ts_types to TsType in EvalSetup and modify usage in code #1267

Draft
wants to merge 10 commits into
base: main-dev
Choose a base branch
from
41 changes: 40 additions & 1 deletion pyaerocom/aeroval/setupclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
import os
import sys
from datetime import timedelta
from enum import Enum
from functools import cached_property
from getpass import getuser
from pathlib import Path
from typing import Annotated, Literal

from pyaerocom.aeroval.glob_defaults import VarWebInfo, VarWebScaleAndColormap
from pyaerocom.tstype import TsType

if sys.version_info >= (3, 11):
from typing import Self
Expand All @@ -24,6 +26,7 @@
field_serializer,
field_validator,
)
from pydantic.functional_validators import AfterValidator

from pyaerocom import __version__, const
from pyaerocom.aeroval.aux_io_helpers import ReadAuxHandler
Expand All @@ -40,6 +43,11 @@
logger = logging.getLogger(__name__)


def convert_freq_str_to_tstype(freq: str):
if isinstance(freq, str):
return TsType(freq)


class OutputPaths(BaseModel):
"""
Setup class for output paths of json files and co-located data
Expand Down Expand Up @@ -110,10 +118,33 @@ def get_json_output_dirs(self, assert_exists=True):
return out


class MapFreqChoices(Enum):
hourly = TsType("hourly")
daily = TsType("daily")
monthly = TsType("monthly")
yearly = TsType("yearly")
coarsest = TsType("coarsest") # special attention needed as not a valid ts_type on it's own


class ModelMapsSetup(BaseModel):
maps_freq: Literal["hourly", "daily", "monthly", "yearly", "coarsest"] = "coarsest"
# Pydantic ConfigDict
model_config = ConfigDict(use_enum_values=True)

# Class attributes
maps_freq: Literal[
"hourly", "daily", "monthly", "yearly", "coarsest"
] | MapFreqChoices = Field(default=MapFreqChoices.coarsest, validate_default=True)
maps_res_deg: PositiveInt = 5

# TODO: Turn all ts_type attributes into TsType here instead of converting them later in the code
@field_validator("maps_freq", mode="before")
@classmethod
def transform(cls, freq: str | TsType) -> TsType:
if isinstance(freq, str):
return TsType(freq)
else:
return freq


class CAMS2_83Setup(BaseModel):
use_cams2_83: bool = False
Expand Down Expand Up @@ -394,6 +425,14 @@ def modelmaps_opts(self) -> ModelMapsSetup:
}
return ModelMapsSetup(**model_args)

@field_validator("modelmaps_opts", mode="after")
@classmethod
def validate_modelmaps_opts_coarsest(cls, modelmaps_opts: ModelMapsSetup):
if modelmaps_opts.maps_freq == MapFreqChoices.coarsest:
freq = min(TsType(fq) for fq in cls.time_cfg.freqs)
freq = min(freq, cls.time_cfg.main_freq)
modelmaps_opts.maps_freq = freq

@computed_field
@cached_property
def cams2_83_cfg(self) -> CAMS2_83Setup:
Expand Down
4 changes: 4 additions & 0 deletions pyaerocom/tstype.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
General helper methods for the pyaerocom library.
"""

import json
import logging
import re

Expand Down Expand Up @@ -415,3 +416,6 @@ def __str__(self):

def __repr__(self):
return self.val

def to_json(self):
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4)
Loading