flood-adapt 0.3.9__py3-none-any.whl → 0.3.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flood_adapt/__init__.py +26 -22
- flood_adapt/adapter/__init__.py +9 -9
- flood_adapt/adapter/fiat_adapter.py +1541 -1541
- flood_adapt/adapter/interface/hazard_adapter.py +70 -70
- flood_adapt/adapter/interface/impact_adapter.py +36 -36
- flood_adapt/adapter/interface/model_adapter.py +89 -89
- flood_adapt/adapter/interface/offshore.py +19 -19
- flood_adapt/adapter/sfincs_adapter.py +1853 -1848
- flood_adapt/adapter/sfincs_offshore.py +187 -193
- flood_adapt/config/config.py +248 -248
- flood_adapt/config/fiat.py +219 -219
- flood_adapt/config/gui.py +331 -331
- flood_adapt/config/sfincs.py +481 -336
- flood_adapt/config/site.py +129 -129
- flood_adapt/database_builder/database_builder.py +2210 -2210
- flood_adapt/database_builder/templates/default_units/imperial.toml +9 -9
- flood_adapt/database_builder/templates/default_units/metric.toml +9 -9
- flood_adapt/database_builder/templates/green_infra_table/green_infra_lookup_table.csv +10 -10
- flood_adapt/database_builder/templates/infographics/OSM/config_charts.toml +90 -90
- flood_adapt/database_builder/templates/infographics/OSM/config_people.toml +57 -57
- flood_adapt/database_builder/templates/infographics/OSM/config_risk_charts.toml +121 -121
- flood_adapt/database_builder/templates/infographics/OSM/config_roads.toml +65 -65
- flood_adapt/database_builder/templates/infographics/OSM/styles.css +45 -45
- flood_adapt/database_builder/templates/infographics/US_NSI/config_charts.toml +126 -126
- flood_adapt/database_builder/templates/infographics/US_NSI/config_people.toml +60 -60
- flood_adapt/database_builder/templates/infographics/US_NSI/config_risk_charts.toml +121 -121
- flood_adapt/database_builder/templates/infographics/US_NSI/config_roads.toml +65 -65
- flood_adapt/database_builder/templates/infographics/US_NSI/styles.css +45 -45
- flood_adapt/database_builder/templates/infometrics/OSM/metrics_additional_risk_configs.toml +4 -4
- flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config.toml +143 -143
- flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config_risk.toml +153 -153
- flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config.toml +127 -127
- flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config_risk.toml +57 -57
- flood_adapt/database_builder/templates/infometrics/US_NSI/metrics_additional_risk_configs.toml +4 -4
- flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config.toml +191 -191
- flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config_risk.toml +153 -153
- flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config.toml +178 -178
- flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config_risk.toml +57 -57
- flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config.toml +9 -9
- flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config_risk.toml +65 -65
- flood_adapt/database_builder/templates/output_layers/bin_colors.toml +5 -5
- flood_adapt/database_builder.py +16 -16
- flood_adapt/dbs_classes/__init__.py +21 -21
- flood_adapt/dbs_classes/database.py +533 -684
- flood_adapt/dbs_classes/dbs_benefit.py +77 -76
- flood_adapt/dbs_classes/dbs_event.py +61 -59
- flood_adapt/dbs_classes/dbs_measure.py +112 -111
- flood_adapt/dbs_classes/dbs_projection.py +34 -34
- flood_adapt/dbs_classes/dbs_scenario.py +137 -137
- flood_adapt/dbs_classes/dbs_static.py +274 -273
- flood_adapt/dbs_classes/dbs_strategy.py +130 -129
- flood_adapt/dbs_classes/dbs_template.py +279 -278
- flood_adapt/dbs_classes/interface/database.py +107 -139
- flood_adapt/dbs_classes/interface/element.py +121 -121
- flood_adapt/dbs_classes/interface/static.py +47 -47
- flood_adapt/flood_adapt.py +1229 -1178
- flood_adapt/misc/database_user.py +16 -16
- flood_adapt/misc/exceptions.py +22 -0
- flood_adapt/misc/log.py +183 -183
- flood_adapt/misc/path_builder.py +54 -54
- flood_adapt/misc/utils.py +185 -185
- flood_adapt/objects/__init__.py +82 -82
- flood_adapt/objects/benefits/benefits.py +61 -61
- flood_adapt/objects/events/event_factory.py +135 -135
- flood_adapt/objects/events/event_set.py +88 -84
- flood_adapt/objects/events/events.py +236 -234
- flood_adapt/objects/events/historical.py +58 -58
- flood_adapt/objects/events/hurricane.py +68 -67
- flood_adapt/objects/events/synthetic.py +46 -50
- flood_adapt/objects/forcing/__init__.py +92 -92
- flood_adapt/objects/forcing/csv.py +68 -68
- flood_adapt/objects/forcing/discharge.py +66 -66
- flood_adapt/objects/forcing/forcing.py +150 -150
- flood_adapt/objects/forcing/forcing_factory.py +182 -182
- flood_adapt/objects/forcing/meteo_handler.py +93 -93
- flood_adapt/objects/forcing/netcdf.py +40 -40
- flood_adapt/objects/forcing/plotting.py +453 -429
- flood_adapt/objects/forcing/rainfall.py +98 -98
- flood_adapt/objects/forcing/tide_gauge.py +191 -191
- flood_adapt/objects/forcing/time_frame.py +90 -90
- flood_adapt/objects/forcing/timeseries.py +564 -564
- flood_adapt/objects/forcing/unit_system.py +580 -580
- flood_adapt/objects/forcing/waterlevels.py +108 -108
- flood_adapt/objects/forcing/wind.py +124 -124
- flood_adapt/objects/measures/measure_factory.py +92 -92
- flood_adapt/objects/measures/measures.py +551 -529
- flood_adapt/objects/object_model.py +74 -68
- flood_adapt/objects/projections/projections.py +103 -103
- flood_adapt/objects/scenarios/scenarios.py +22 -22
- flood_adapt/objects/strategies/strategies.py +89 -89
- flood_adapt/workflows/benefit_runner.py +579 -554
- flood_adapt/workflows/floodmap.py +85 -85
- flood_adapt/workflows/impacts_integrator.py +85 -85
- flood_adapt/workflows/scenario_runner.py +70 -70
- {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/LICENSE +674 -674
- {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/METADATA +867 -865
- flood_adapt-0.3.11.dist-info/RECORD +140 -0
- flood_adapt-0.3.9.dist-info/RECORD +0 -139
- {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/WHEEL +0 -0
- {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/top_level.txt +0 -0
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
from typing import Annotated
|
|
4
|
-
|
|
5
|
-
import pandas as pd
|
|
6
|
-
|
|
7
|
-
from flood_adapt.misc.utils import (
|
|
8
|
-
copy_file_to_output_dir,
|
|
9
|
-
validate_file_extension,
|
|
10
|
-
)
|
|
11
|
-
from flood_adapt.objects.forcing import unit_system as us
|
|
12
|
-
from flood_adapt.objects.forcing.forcing import (
|
|
13
|
-
ForcingSource,
|
|
14
|
-
IDischarge,
|
|
15
|
-
)
|
|
16
|
-
from flood_adapt.objects.forcing.time_frame import TimeFrame
|
|
17
|
-
from flood_adapt.objects.forcing.timeseries import (
|
|
18
|
-
CSVTimeseries,
|
|
19
|
-
SyntheticTimeseries,
|
|
20
|
-
TimeseriesFactory,
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class DischargeConstant(IDischarge):
|
|
25
|
-
source: ForcingSource = ForcingSource.CONSTANT
|
|
26
|
-
|
|
27
|
-
discharge: us.UnitfulDischarge
|
|
28
|
-
|
|
29
|
-
def to_dataframe(self, time_frame: TimeFrame) -> pd.DataFrame:
|
|
30
|
-
time = pd.date_range(
|
|
31
|
-
start=time_frame.start_time,
|
|
32
|
-
end=time_frame.end_time,
|
|
33
|
-
freq=time_frame.time_step,
|
|
34
|
-
name="time",
|
|
35
|
-
)
|
|
36
|
-
data = [self.discharge.value for _ in range(len(time))]
|
|
37
|
-
return pd.DataFrame(index=time, data=data, columns=[self.river.name])
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class DischargeSynthetic(IDischarge):
|
|
41
|
-
source: ForcingSource = ForcingSource.SYNTHETIC
|
|
42
|
-
|
|
43
|
-
timeseries: SyntheticTimeseries
|
|
44
|
-
|
|
45
|
-
def to_dataframe(self, time_frame: TimeFrame) -> pd.DataFrame:
|
|
46
|
-
df = TimeseriesFactory.from_object(self.timeseries).to_dataframe(
|
|
47
|
-
time_frame=time_frame
|
|
48
|
-
)
|
|
49
|
-
df.columns = [self.river.name]
|
|
50
|
-
return df
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
class DischargeCSV(IDischarge):
|
|
54
|
-
source: ForcingSource = ForcingSource.CSV
|
|
55
|
-
|
|
56
|
-
path: Annotated[Path, validate_file_extension([".csv"])]
|
|
57
|
-
|
|
58
|
-
units: us.UnitTypesDischarge = us.UnitTypesDischarge.cms
|
|
59
|
-
|
|
60
|
-
def to_dataframe(self, time_frame: TimeFrame) -> pd.DataFrame:
|
|
61
|
-
return CSVTimeseries.load_file(
|
|
62
|
-
path=self.path, units=us.UnitfulDischarge(value=0, units=self.units)
|
|
63
|
-
).to_dataframe(time_frame=time_frame)
|
|
64
|
-
|
|
65
|
-
def save_additional(self, output_dir: Path | str | os.PathLike) -> None:
|
|
66
|
-
self.path = copy_file_to_output_dir(self.path, Path(output_dir))
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from flood_adapt.misc.utils import (
|
|
8
|
+
copy_file_to_output_dir,
|
|
9
|
+
validate_file_extension,
|
|
10
|
+
)
|
|
11
|
+
from flood_adapt.objects.forcing import unit_system as us
|
|
12
|
+
from flood_adapt.objects.forcing.forcing import (
|
|
13
|
+
ForcingSource,
|
|
14
|
+
IDischarge,
|
|
15
|
+
)
|
|
16
|
+
from flood_adapt.objects.forcing.time_frame import TimeFrame
|
|
17
|
+
from flood_adapt.objects.forcing.timeseries import (
|
|
18
|
+
CSVTimeseries,
|
|
19
|
+
SyntheticTimeseries,
|
|
20
|
+
TimeseriesFactory,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class DischargeConstant(IDischarge):
|
|
25
|
+
source: ForcingSource = ForcingSource.CONSTANT
|
|
26
|
+
|
|
27
|
+
discharge: us.UnitfulDischarge
|
|
28
|
+
|
|
29
|
+
def to_dataframe(self, time_frame: TimeFrame) -> pd.DataFrame:
|
|
30
|
+
time = pd.date_range(
|
|
31
|
+
start=time_frame.start_time,
|
|
32
|
+
end=time_frame.end_time,
|
|
33
|
+
freq=time_frame.time_step,
|
|
34
|
+
name="time",
|
|
35
|
+
)
|
|
36
|
+
data = [self.discharge.value for _ in range(len(time))]
|
|
37
|
+
return pd.DataFrame(index=time, data=data, columns=[self.river.name])
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class DischargeSynthetic(IDischarge):
|
|
41
|
+
source: ForcingSource = ForcingSource.SYNTHETIC
|
|
42
|
+
|
|
43
|
+
timeseries: SyntheticTimeseries
|
|
44
|
+
|
|
45
|
+
def to_dataframe(self, time_frame: TimeFrame) -> pd.DataFrame:
|
|
46
|
+
df = TimeseriesFactory.from_object(self.timeseries).to_dataframe(
|
|
47
|
+
time_frame=time_frame
|
|
48
|
+
)
|
|
49
|
+
df.columns = [self.river.name]
|
|
50
|
+
return df
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class DischargeCSV(IDischarge):
|
|
54
|
+
source: ForcingSource = ForcingSource.CSV
|
|
55
|
+
|
|
56
|
+
path: Annotated[Path, validate_file_extension([".csv"])]
|
|
57
|
+
|
|
58
|
+
units: us.UnitTypesDischarge = us.UnitTypesDischarge.cms
|
|
59
|
+
|
|
60
|
+
def to_dataframe(self, time_frame: TimeFrame) -> pd.DataFrame:
|
|
61
|
+
return CSVTimeseries.load_file(
|
|
62
|
+
path=self.path, units=us.UnitfulDischarge(value=0, units=self.units)
|
|
63
|
+
).to_dataframe(time_frame=time_frame)
|
|
64
|
+
|
|
65
|
+
def save_additional(self, output_dir: Path | str | os.PathLike) -> None:
|
|
66
|
+
self.path = copy_file_to_output_dir(self.path, Path(output_dir))
|
|
@@ -1,150 +1,150 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import os
|
|
3
|
-
from abc import ABC, abstractmethod
|
|
4
|
-
from enum import Enum
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
from typing import Any, ClassVar, List, Type
|
|
7
|
-
|
|
8
|
-
import tomli
|
|
9
|
-
from pydantic import BaseModel, field_serializer
|
|
10
|
-
|
|
11
|
-
from flood_adapt.config.sfincs import RiverModel
|
|
12
|
-
from flood_adapt.misc.log import FloodAdaptLogging
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
### ENUMS ###
|
|
16
|
-
class ForcingType(str, Enum):
|
|
17
|
-
"""Enum class for the different types of forcing parameters.
|
|
18
|
-
|
|
19
|
-
Attributes
|
|
20
|
-
----------
|
|
21
|
-
RAINFALL : The type of forcing parameter for rainfall.
|
|
22
|
-
WIND : The type of forcing parameter for wind.
|
|
23
|
-
DISCHARGE : The type of forcing parameter for discharge.
|
|
24
|
-
WATERLEVEL : The type of forcing parameter for water level.
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
WIND = "WIND"
|
|
28
|
-
RAINFALL = "RAINFALL"
|
|
29
|
-
DISCHARGE = "DISCHARGE"
|
|
30
|
-
WATERLEVEL = "WATERLEVEL"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class ForcingSource(str, Enum):
|
|
34
|
-
"""Enum class for the different sources of forcing parameters."""
|
|
35
|
-
|
|
36
|
-
MODEL = "MODEL" # 'our' hindcast/ sfincs offshore model
|
|
37
|
-
TRACK = "TRACK" # 'our' hindcast/ sfincs offshore model + (shifted) hurricane
|
|
38
|
-
CSV = "CSV" # user provided csv file
|
|
39
|
-
NETCDF = "NETCDF" # user provided netcdf file
|
|
40
|
-
|
|
41
|
-
SYNTHETIC = "SYNTHETIC" # synthetic data
|
|
42
|
-
CONSTANT = "CONSTANT" # synthetic data
|
|
43
|
-
|
|
44
|
-
GAUGED = "GAUGED" # data downloaded from a gauge
|
|
45
|
-
METEO = "METEO" # external hindcast data
|
|
46
|
-
|
|
47
|
-
NONE = "NONE" # no forcing data
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
class IForcing(BaseModel, ABC):
|
|
51
|
-
"""BaseModel describing the expected variables and data types for forcing parameters of hazard model."""
|
|
52
|
-
|
|
53
|
-
class Config:
|
|
54
|
-
arbitrary_types_allowed = True
|
|
55
|
-
|
|
56
|
-
type: ForcingType
|
|
57
|
-
source: ForcingSource
|
|
58
|
-
logger: ClassVar[logging.Logger] = FloodAdaptLogging.getLogger("Forcing")
|
|
59
|
-
|
|
60
|
-
@classmethod
|
|
61
|
-
def load_file(cls, path: Path):
|
|
62
|
-
with open(path, mode="rb") as fp:
|
|
63
|
-
toml_data = tomli.load(fp)
|
|
64
|
-
return cls.load_dict(toml_data)
|
|
65
|
-
|
|
66
|
-
@classmethod
|
|
67
|
-
def load_dict(cls, attrs):
|
|
68
|
-
return cls.model_validate(attrs)
|
|
69
|
-
|
|
70
|
-
def model_dump(self, **kwargs: Any) -> dict[str, Any]:
|
|
71
|
-
"""Override the default model_dump to include class variables `type` and `source`."""
|
|
72
|
-
data = super().model_dump(**kwargs)
|
|
73
|
-
data.update({"type": self.type, "source": self.source})
|
|
74
|
-
return data
|
|
75
|
-
|
|
76
|
-
def save_additional(self, output_dir: Path | str | os.PathLike) -> None:
|
|
77
|
-
"""Save additional data of the forcing."""
|
|
78
|
-
return
|
|
79
|
-
|
|
80
|
-
@field_serializer("path", check_fields=False)
|
|
81
|
-
@classmethod
|
|
82
|
-
def serialize_path(cls, value: Path) -> str:
|
|
83
|
-
"""Serialize filepath-like fields by saving only the filename. It is assumed that the file will be saved in the same directory."""
|
|
84
|
-
return value.name
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
class IDischarge(IForcing):
|
|
88
|
-
type: ForcingType = ForcingType.DISCHARGE
|
|
89
|
-
river: RiverModel
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
class IRainfall(IForcing):
|
|
93
|
-
type: ForcingType = ForcingType.RAINFALL
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class IWind(IForcing):
|
|
97
|
-
type: ForcingType = ForcingType.WIND
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
class IWaterlevel(IForcing):
|
|
101
|
-
type: ForcingType = ForcingType.WATERLEVEL
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
class IForcingFactory:
|
|
105
|
-
@classmethod
|
|
106
|
-
@abstractmethod
|
|
107
|
-
def load_file(cls, toml_file: Path) -> IForcing:
|
|
108
|
-
"""Create a forcing object from a TOML file."""
|
|
109
|
-
...
|
|
110
|
-
|
|
111
|
-
@classmethod
|
|
112
|
-
@abstractmethod
|
|
113
|
-
def load_dict(cls, attrs: dict[str, Any] | IForcing) -> IForcing:
|
|
114
|
-
"""Create a forcing object from a dictionary of attributes."""
|
|
115
|
-
...
|
|
116
|
-
|
|
117
|
-
@classmethod
|
|
118
|
-
@abstractmethod
|
|
119
|
-
def read_forcing(
|
|
120
|
-
cls,
|
|
121
|
-
filepath: Path,
|
|
122
|
-
) -> tuple[Type[IForcing], ForcingType, ForcingSource]:
|
|
123
|
-
"""Extract forcing class, type and source from a TOML file."""
|
|
124
|
-
...
|
|
125
|
-
|
|
126
|
-
@classmethod
|
|
127
|
-
@abstractmethod
|
|
128
|
-
def get_forcing_class(
|
|
129
|
-
cls, type: ForcingType, source: ForcingSource
|
|
130
|
-
) -> Type[IForcing]:
|
|
131
|
-
"""Get the forcing class corresponding to the type and source."""
|
|
132
|
-
...
|
|
133
|
-
|
|
134
|
-
@classmethod
|
|
135
|
-
@abstractmethod
|
|
136
|
-
def list_forcing_types(cls) -> List[ForcingType]:
|
|
137
|
-
"""List all available forcing types."""
|
|
138
|
-
...
|
|
139
|
-
|
|
140
|
-
@classmethod
|
|
141
|
-
@abstractmethod
|
|
142
|
-
def list_forcing_classes(cls) -> List[Type[IForcing]]:
|
|
143
|
-
"""List all available forcing classes."""
|
|
144
|
-
...
|
|
145
|
-
|
|
146
|
-
@classmethod
|
|
147
|
-
@abstractmethod
|
|
148
|
-
def list_forcing_types_and_sources(cls) -> List[tuple[ForcingType, ForcingSource]]:
|
|
149
|
-
"""List all available combinations of forcing types and sources."""
|
|
150
|
-
...
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, ClassVar, List, Type
|
|
7
|
+
|
|
8
|
+
import tomli
|
|
9
|
+
from pydantic import BaseModel, field_serializer
|
|
10
|
+
|
|
11
|
+
from flood_adapt.config.sfincs import RiverModel
|
|
12
|
+
from flood_adapt.misc.log import FloodAdaptLogging
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### ENUMS ###
|
|
16
|
+
class ForcingType(str, Enum):
|
|
17
|
+
"""Enum class for the different types of forcing parameters.
|
|
18
|
+
|
|
19
|
+
Attributes
|
|
20
|
+
----------
|
|
21
|
+
RAINFALL : The type of forcing parameter for rainfall.
|
|
22
|
+
WIND : The type of forcing parameter for wind.
|
|
23
|
+
DISCHARGE : The type of forcing parameter for discharge.
|
|
24
|
+
WATERLEVEL : The type of forcing parameter for water level.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
WIND = "WIND"
|
|
28
|
+
RAINFALL = "RAINFALL"
|
|
29
|
+
DISCHARGE = "DISCHARGE"
|
|
30
|
+
WATERLEVEL = "WATERLEVEL"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ForcingSource(str, Enum):
|
|
34
|
+
"""Enum class for the different sources of forcing parameters."""
|
|
35
|
+
|
|
36
|
+
MODEL = "MODEL" # 'our' hindcast/ sfincs offshore model
|
|
37
|
+
TRACK = "TRACK" # 'our' hindcast/ sfincs offshore model + (shifted) hurricane
|
|
38
|
+
CSV = "CSV" # user provided csv file
|
|
39
|
+
NETCDF = "NETCDF" # user provided netcdf file
|
|
40
|
+
|
|
41
|
+
SYNTHETIC = "SYNTHETIC" # synthetic data
|
|
42
|
+
CONSTANT = "CONSTANT" # synthetic data
|
|
43
|
+
|
|
44
|
+
GAUGED = "GAUGED" # data downloaded from a gauge
|
|
45
|
+
METEO = "METEO" # external hindcast data
|
|
46
|
+
|
|
47
|
+
NONE = "NONE" # no forcing data
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class IForcing(BaseModel, ABC):
|
|
51
|
+
"""BaseModel describing the expected variables and data types for forcing parameters of hazard model."""
|
|
52
|
+
|
|
53
|
+
class Config:
|
|
54
|
+
arbitrary_types_allowed = True
|
|
55
|
+
|
|
56
|
+
type: ForcingType
|
|
57
|
+
source: ForcingSource
|
|
58
|
+
logger: ClassVar[logging.Logger] = FloodAdaptLogging.getLogger("Forcing")
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def load_file(cls, path: Path):
|
|
62
|
+
with open(path, mode="rb") as fp:
|
|
63
|
+
toml_data = tomli.load(fp)
|
|
64
|
+
return cls.load_dict(toml_data)
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def load_dict(cls, attrs):
|
|
68
|
+
return cls.model_validate(attrs)
|
|
69
|
+
|
|
70
|
+
def model_dump(self, **kwargs: Any) -> dict[str, Any]:
|
|
71
|
+
"""Override the default model_dump to include class variables `type` and `source`."""
|
|
72
|
+
data = super().model_dump(**kwargs)
|
|
73
|
+
data.update({"type": self.type, "source": self.source})
|
|
74
|
+
return data
|
|
75
|
+
|
|
76
|
+
def save_additional(self, output_dir: Path | str | os.PathLike) -> None:
|
|
77
|
+
"""Save additional data of the forcing."""
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
@field_serializer("path", check_fields=False)
|
|
81
|
+
@classmethod
|
|
82
|
+
def serialize_path(cls, value: Path) -> str:
|
|
83
|
+
"""Serialize filepath-like fields by saving only the filename. It is assumed that the file will be saved in the same directory."""
|
|
84
|
+
return value.name
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class IDischarge(IForcing):
|
|
88
|
+
type: ForcingType = ForcingType.DISCHARGE
|
|
89
|
+
river: RiverModel
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class IRainfall(IForcing):
|
|
93
|
+
type: ForcingType = ForcingType.RAINFALL
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class IWind(IForcing):
|
|
97
|
+
type: ForcingType = ForcingType.WIND
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class IWaterlevel(IForcing):
|
|
101
|
+
type: ForcingType = ForcingType.WATERLEVEL
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class IForcingFactory:
|
|
105
|
+
@classmethod
|
|
106
|
+
@abstractmethod
|
|
107
|
+
def load_file(cls, toml_file: Path) -> IForcing:
|
|
108
|
+
"""Create a forcing object from a TOML file."""
|
|
109
|
+
...
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
@abstractmethod
|
|
113
|
+
def load_dict(cls, attrs: dict[str, Any] | IForcing) -> IForcing:
|
|
114
|
+
"""Create a forcing object from a dictionary of attributes."""
|
|
115
|
+
...
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
@abstractmethod
|
|
119
|
+
def read_forcing(
|
|
120
|
+
cls,
|
|
121
|
+
filepath: Path,
|
|
122
|
+
) -> tuple[Type[IForcing], ForcingType, ForcingSource]:
|
|
123
|
+
"""Extract forcing class, type and source from a TOML file."""
|
|
124
|
+
...
|
|
125
|
+
|
|
126
|
+
@classmethod
|
|
127
|
+
@abstractmethod
|
|
128
|
+
def get_forcing_class(
|
|
129
|
+
cls, type: ForcingType, source: ForcingSource
|
|
130
|
+
) -> Type[IForcing]:
|
|
131
|
+
"""Get the forcing class corresponding to the type and source."""
|
|
132
|
+
...
|
|
133
|
+
|
|
134
|
+
@classmethod
|
|
135
|
+
@abstractmethod
|
|
136
|
+
def list_forcing_types(cls) -> List[ForcingType]:
|
|
137
|
+
"""List all available forcing types."""
|
|
138
|
+
...
|
|
139
|
+
|
|
140
|
+
@classmethod
|
|
141
|
+
@abstractmethod
|
|
142
|
+
def list_forcing_classes(cls) -> List[Type[IForcing]]:
|
|
143
|
+
"""List all available forcing classes."""
|
|
144
|
+
...
|
|
145
|
+
|
|
146
|
+
@classmethod
|
|
147
|
+
@abstractmethod
|
|
148
|
+
def list_forcing_types_and_sources(cls) -> List[tuple[ForcingType, ForcingSource]]:
|
|
149
|
+
"""List all available combinations of forcing types and sources."""
|
|
150
|
+
...
|