flood-adapt 0.3.0__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.
Files changed (139) hide show
  1. flood_adapt/__init__.py +22 -0
  2. flood_adapt/adapter/__init__.py +9 -0
  3. flood_adapt/adapter/fiat_adapter.py +1502 -0
  4. flood_adapt/adapter/interface/__init__.py +0 -0
  5. flood_adapt/adapter/interface/hazard_adapter.py +70 -0
  6. flood_adapt/adapter/interface/impact_adapter.py +36 -0
  7. flood_adapt/adapter/interface/model_adapter.py +89 -0
  8. flood_adapt/adapter/interface/offshore.py +19 -0
  9. flood_adapt/adapter/sfincs_adapter.py +1857 -0
  10. flood_adapt/adapter/sfincs_offshore.py +193 -0
  11. flood_adapt/config/__init__.py +0 -0
  12. flood_adapt/config/config.py +245 -0
  13. flood_adapt/config/fiat.py +219 -0
  14. flood_adapt/config/gui.py +224 -0
  15. flood_adapt/config/sfincs.py +336 -0
  16. flood_adapt/config/site.py +124 -0
  17. flood_adapt/database_builder/__init__.py +0 -0
  18. flood_adapt/database_builder/database_builder.py +2175 -0
  19. flood_adapt/database_builder/templates/default_units/imperial.toml +9 -0
  20. flood_adapt/database_builder/templates/default_units/metric.toml +9 -0
  21. flood_adapt/database_builder/templates/green_infra_table/green_infra_lookup_table.csv +10 -0
  22. flood_adapt/database_builder/templates/icons/black_down_48x48.png +0 -0
  23. flood_adapt/database_builder/templates/icons/black_left_48x48.png +0 -0
  24. flood_adapt/database_builder/templates/icons/black_right_48x48.png +0 -0
  25. flood_adapt/database_builder/templates/icons/black_up_48x48.png +0 -0
  26. flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_down.png +0 -0
  27. flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_left.png +0 -0
  28. flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_right.png +0 -0
  29. flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_up.png +0 -0
  30. flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_down.png +0 -0
  31. flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_left.png +0 -0
  32. flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_right.png +0 -0
  33. flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_up.png +0 -0
  34. flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_white_left.png +0 -0
  35. flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_white_right.png +0 -0
  36. flood_adapt/database_builder/templates/icons/white_down_48x48.png +0 -0
  37. flood_adapt/database_builder/templates/icons/white_left_48x48.png +0 -0
  38. flood_adapt/database_builder/templates/icons/white_right_48x48.png +0 -0
  39. flood_adapt/database_builder/templates/icons/white_up_48x48.png +0 -0
  40. flood_adapt/database_builder/templates/infographics/OSM/config_charts.toml +90 -0
  41. flood_adapt/database_builder/templates/infographics/OSM/config_people.toml +57 -0
  42. flood_adapt/database_builder/templates/infographics/OSM/config_risk_charts.toml +121 -0
  43. flood_adapt/database_builder/templates/infographics/OSM/config_roads.toml +65 -0
  44. flood_adapt/database_builder/templates/infographics/OSM/styles.css +45 -0
  45. flood_adapt/database_builder/templates/infographics/US_NSI/config_charts.toml +126 -0
  46. flood_adapt/database_builder/templates/infographics/US_NSI/config_people.toml +60 -0
  47. flood_adapt/database_builder/templates/infographics/US_NSI/config_risk_charts.toml +121 -0
  48. flood_adapt/database_builder/templates/infographics/US_NSI/config_roads.toml +65 -0
  49. flood_adapt/database_builder/templates/infographics/US_NSI/styles.css +45 -0
  50. flood_adapt/database_builder/templates/infographics/images/ambulance.png +0 -0
  51. flood_adapt/database_builder/templates/infographics/images/car.png +0 -0
  52. flood_adapt/database_builder/templates/infographics/images/cart.png +0 -0
  53. flood_adapt/database_builder/templates/infographics/images/firetruck.png +0 -0
  54. flood_adapt/database_builder/templates/infographics/images/hospital.png +0 -0
  55. flood_adapt/database_builder/templates/infographics/images/house.png +0 -0
  56. flood_adapt/database_builder/templates/infographics/images/info.png +0 -0
  57. flood_adapt/database_builder/templates/infographics/images/money.png +0 -0
  58. flood_adapt/database_builder/templates/infographics/images/person.png +0 -0
  59. flood_adapt/database_builder/templates/infographics/images/school.png +0 -0
  60. flood_adapt/database_builder/templates/infographics/images/truck.png +0 -0
  61. flood_adapt/database_builder/templates/infographics/images/walking_person.png +0 -0
  62. flood_adapt/database_builder/templates/infometrics/OSM/metrics_additional_risk_configs.toml +4 -0
  63. flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config.toml +143 -0
  64. flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config_risk.toml +153 -0
  65. flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config.toml +127 -0
  66. flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config_risk.toml +57 -0
  67. flood_adapt/database_builder/templates/infometrics/US_NSI/metrics_additional_risk_configs.toml +4 -0
  68. flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config.toml +191 -0
  69. flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config_risk.toml +153 -0
  70. flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config.toml +178 -0
  71. flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config_risk.toml +57 -0
  72. flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config.toml +9 -0
  73. flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config_risk.toml +65 -0
  74. flood_adapt/database_builder/templates/mapbox_layers/bin_colors.toml +5 -0
  75. flood_adapt/database_builder.py +16 -0
  76. flood_adapt/dbs_classes/__init__.py +21 -0
  77. flood_adapt/dbs_classes/database.py +716 -0
  78. flood_adapt/dbs_classes/dbs_benefit.py +97 -0
  79. flood_adapt/dbs_classes/dbs_event.py +91 -0
  80. flood_adapt/dbs_classes/dbs_measure.py +103 -0
  81. flood_adapt/dbs_classes/dbs_projection.py +52 -0
  82. flood_adapt/dbs_classes/dbs_scenario.py +150 -0
  83. flood_adapt/dbs_classes/dbs_static.py +261 -0
  84. flood_adapt/dbs_classes/dbs_strategy.py +147 -0
  85. flood_adapt/dbs_classes/dbs_template.py +302 -0
  86. flood_adapt/dbs_classes/interface/database.py +147 -0
  87. flood_adapt/dbs_classes/interface/element.py +137 -0
  88. flood_adapt/dbs_classes/interface/static.py +47 -0
  89. flood_adapt/flood_adapt.py +1371 -0
  90. flood_adapt/misc/__init__.py +0 -0
  91. flood_adapt/misc/database_user.py +16 -0
  92. flood_adapt/misc/log.py +183 -0
  93. flood_adapt/misc/path_builder.py +54 -0
  94. flood_adapt/misc/utils.py +185 -0
  95. flood_adapt/objects/__init__.py +59 -0
  96. flood_adapt/objects/benefits/__init__.py +0 -0
  97. flood_adapt/objects/benefits/benefits.py +61 -0
  98. flood_adapt/objects/events/__init__.py +0 -0
  99. flood_adapt/objects/events/event_factory.py +135 -0
  100. flood_adapt/objects/events/event_set.py +84 -0
  101. flood_adapt/objects/events/events.py +221 -0
  102. flood_adapt/objects/events/historical.py +55 -0
  103. flood_adapt/objects/events/hurricane.py +64 -0
  104. flood_adapt/objects/events/synthetic.py +48 -0
  105. flood_adapt/objects/forcing/__init__.py +0 -0
  106. flood_adapt/objects/forcing/csv.py +68 -0
  107. flood_adapt/objects/forcing/discharge.py +66 -0
  108. flood_adapt/objects/forcing/forcing.py +142 -0
  109. flood_adapt/objects/forcing/forcing_factory.py +182 -0
  110. flood_adapt/objects/forcing/meteo_handler.py +93 -0
  111. flood_adapt/objects/forcing/netcdf.py +40 -0
  112. flood_adapt/objects/forcing/plotting.py +428 -0
  113. flood_adapt/objects/forcing/rainfall.py +98 -0
  114. flood_adapt/objects/forcing/tide_gauge.py +191 -0
  115. flood_adapt/objects/forcing/time_frame.py +77 -0
  116. flood_adapt/objects/forcing/timeseries.py +552 -0
  117. flood_adapt/objects/forcing/unit_system.py +580 -0
  118. flood_adapt/objects/forcing/waterlevels.py +108 -0
  119. flood_adapt/objects/forcing/wind.py +124 -0
  120. flood_adapt/objects/measures/__init__.py +0 -0
  121. flood_adapt/objects/measures/measure_factory.py +92 -0
  122. flood_adapt/objects/measures/measures.py +506 -0
  123. flood_adapt/objects/object_model.py +68 -0
  124. flood_adapt/objects/projections/__init__.py +0 -0
  125. flood_adapt/objects/projections/projections.py +89 -0
  126. flood_adapt/objects/scenarios/__init__.py +0 -0
  127. flood_adapt/objects/scenarios/scenarios.py +22 -0
  128. flood_adapt/objects/strategies/__init__.py +0 -0
  129. flood_adapt/objects/strategies/strategies.py +68 -0
  130. flood_adapt/workflows/__init__.py +0 -0
  131. flood_adapt/workflows/benefit_runner.py +541 -0
  132. flood_adapt/workflows/floodmap.py +85 -0
  133. flood_adapt/workflows/impacts_integrator.py +82 -0
  134. flood_adapt/workflows/scenario_runner.py +69 -0
  135. flood_adapt-0.3.0.dist-info/LICENSE +21 -0
  136. flood_adapt-0.3.0.dist-info/METADATA +183 -0
  137. flood_adapt-0.3.0.dist-info/RECORD +139 -0
  138. flood_adapt-0.3.0.dist-info/WHEEL +5 -0
  139. flood_adapt-0.3.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,224 @@
1
+ from pathlib import Path
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel, Field
5
+ from tomli import load as load_toml
6
+
7
+ from flood_adapt.config.fiat import DamageType
8
+ from flood_adapt.objects.forcing import unit_system as us
9
+
10
+
11
+ class MapboxLayersModel(BaseModel):
12
+ """The configuration of the mapbox layers in the gui.
13
+
14
+ Attributes
15
+ ----------
16
+ buildings_min_zoom_level : int
17
+ The minimum zoom level for the buildings layer.
18
+ flood_map_depth_min : float
19
+ The minimum depth for the flood map layer.
20
+ flood_map_zbmax : float
21
+ The maximum depth for the flood map layer.
22
+ flood_map_bins : list[float]
23
+ The bins for the flood map layer.
24
+ flood_map_colors : list[str]
25
+ The colors for the flood map layer.
26
+ aggregation_dmg_bins : list[float]
27
+ The bins for the aggregation damage layer.
28
+ aggregation_dmg_colors : list[str]
29
+ The colors for the aggregation damage layer.
30
+ footprints_dmg_type : DamageType
31
+ The type of damage for the footprints layer.
32
+ footprints_dmg_bins : list[float]
33
+ The bins for the footprints layer.
34
+ footprints_dmg_colors : list[str]
35
+ The colors for the footprints layer.
36
+ svi_bins : Optional[list[float]]
37
+ The bins for the SVI layer.
38
+ svi_colors : Optional[list[str]]
39
+ The colors for the SVI layer.
40
+ benefits_bins : list[float]
41
+ The bins for the benefits layer.
42
+ benefits_colors : list[str]
43
+ The colors for the benefits layer.
44
+ benefits_threshold : Optional[float], default=None
45
+ The threshold for the benefits layer.
46
+ damage_decimals : Optional[int], default=0
47
+ The number of decimals for the damage layer.
48
+
49
+ """
50
+
51
+ buildings_min_zoom_level: int = 13
52
+ flood_map_depth_min: float
53
+ flood_map_zbmax: float
54
+ flood_map_bins: list[float]
55
+ flood_map_colors: list[str]
56
+ aggregation_dmg_bins: list[float]
57
+ aggregation_dmg_colors: list[str]
58
+ footprints_dmg_type: DamageType = DamageType.absolute
59
+ footprints_dmg_bins: list[float]
60
+ footprints_dmg_colors: list[str]
61
+ svi_bins: Optional[list[float]] = Field(default_factory=list)
62
+ svi_colors: Optional[list[str]] = Field(default_factory=list)
63
+ benefits_bins: list[float]
64
+ benefits_colors: list[str]
65
+ benefits_threshold: Optional[float] = None
66
+ damage_decimals: Optional[int] = 0
67
+
68
+
69
+ class VisualizationLayersModel(BaseModel):
70
+ """The configuration of the layers you might want to visualize in the gui.
71
+
72
+ Attributes
73
+ ----------
74
+ default_bin_number : int
75
+ The default number of bins for the visualization layers.
76
+ default_colors : list[str]
77
+ The default colors for the visualization layers.
78
+ layer_names : list[str]
79
+ The names of the layers to visualize.
80
+ layer_long_names : list[str]
81
+ The long names of the layers to visualize.
82
+ layer_paths : list[str]
83
+ The paths to the layers to visualize.
84
+ field_names : list[str]
85
+ The field names of the layers to visualize.
86
+ bins : Optional[list[list[float]]]
87
+ The bins for the layers to visualize.
88
+ colors : Optional[list[list[str]]]
89
+ The colors for the layers to visualize.
90
+ """
91
+
92
+ # TODO add check for default_bin_number and default_colors to have the same length
93
+ default_bin_number: int
94
+ default_colors: list[str]
95
+ layer_names: list[str] = Field(default_factory=list)
96
+ layer_long_names: list[str] = Field(default_factory=list)
97
+ layer_paths: list[str] = Field(default_factory=list)
98
+ field_names: list[str] = Field(default_factory=list)
99
+ bins: Optional[list[list[float]]] = Field(default_factory=list)
100
+ colors: Optional[list[list[str]]] = Field(default_factory=list)
101
+
102
+
103
+ class GuiUnitModel(BaseModel):
104
+ """The unit system used in the GUI.
105
+
106
+ Attributes
107
+ ----------
108
+ default_length_units : us.UnitTypesLength
109
+ The length units used in the GUI.
110
+ default_distance_units : us.UnitTypesLength
111
+ The distance units used in the GUI.
112
+ default_area_units : us.UnitTypesArea
113
+ The area units used in the GUI.
114
+ default_volume_units : us.UnitTypesVolume
115
+ The volume units used in the GUI.
116
+ default_velocity_units : us.UnitTypesVelocity
117
+ The velocity units used in the GUI.
118
+ default_direction_units : us.UnitTypesDirection
119
+ The direction units used in the GUI.
120
+ default_discharge_units : us.UnitTypesDischarge
121
+ The discharge units used in the GUI.
122
+ default_intensity_units : us.UnitTypesIntensity
123
+ The intensity units used in the GUI.
124
+ default_cumulative_units : us.UnitTypesLength
125
+ The cumulative units used in the GUI.
126
+ """
127
+
128
+ default_length_units: us.UnitTypesLength
129
+ default_distance_units: us.UnitTypesLength
130
+ default_area_units: us.UnitTypesArea
131
+ default_volume_units: us.UnitTypesVolume
132
+ default_velocity_units: us.UnitTypesVelocity
133
+ default_direction_units: us.UnitTypesDirection
134
+ default_discharge_units: us.UnitTypesDischarge
135
+ default_intensity_units: us.UnitTypesIntensity
136
+ default_cumulative_units: us.UnitTypesLength
137
+
138
+ @staticmethod
139
+ def imperial() -> "GuiUnitModel":
140
+ return GuiUnitModel(
141
+ default_length_units=us.UnitTypesLength.feet,
142
+ default_distance_units=us.UnitTypesLength.miles,
143
+ default_area_units=us.UnitTypesArea.sf,
144
+ default_volume_units=us.UnitTypesVolume.cf,
145
+ default_velocity_units=us.UnitTypesVelocity.mph,
146
+ default_direction_units=us.UnitTypesDirection.degrees,
147
+ default_discharge_units=us.UnitTypesDischarge.cfs,
148
+ default_intensity_units=us.UnitTypesIntensity.inch_hr,
149
+ default_cumulative_units=us.UnitTypesLength.inch,
150
+ )
151
+
152
+ @staticmethod
153
+ def metric() -> "GuiUnitModel":
154
+ return GuiUnitModel(
155
+ default_length_units=us.UnitTypesLength.meters,
156
+ default_distance_units=us.UnitTypesLength.meters,
157
+ default_area_units=us.UnitTypesArea.m2,
158
+ default_volume_units=us.UnitTypesVolume.m3,
159
+ default_velocity_units=us.UnitTypesVelocity.mps,
160
+ default_direction_units=us.UnitTypesDirection.degrees,
161
+ default_discharge_units=us.UnitTypesDischarge.cms,
162
+ default_intensity_units=us.UnitTypesIntensity.mm_hr,
163
+ default_cumulative_units=us.UnitTypesLength.millimeters,
164
+ )
165
+
166
+
167
+ class SyntheticTideModel(BaseModel):
168
+ """Configuration for the synthetic tide.
169
+
170
+ Parameters
171
+ ----------
172
+ harmonic_amplitude : us.UnitfulLength
173
+ The amplitude of the tide harmonic relative to the datum.
174
+ datum : str
175
+ The datum to which the harmonic amplitude is relative.
176
+ Should be a datum defined in `site.sfincs.waterlevels.datums`
177
+ """
178
+
179
+ harmonic_amplitude: us.UnitfulLength
180
+ datum: str
181
+
182
+
183
+ class PlottingModel(BaseModel):
184
+ """
185
+ The configuration of the plotting in the gui.
186
+
187
+ Attributes
188
+ ----------
189
+ excluded_datums : list[str]
190
+ A list of datums that will be excluded from the forcing plot in event windows.
191
+ synthetic_tide : SyntheticTideModel
192
+ The configuration of the synthetic tide.
193
+ """
194
+
195
+ synthetic_tide: SyntheticTideModel
196
+ excluded_datums: list[str] = Field(default_factory=list)
197
+
198
+
199
+ class GuiModel(BaseModel):
200
+ """The accepted input for the variable gui in Site.
201
+
202
+ Attributes
203
+ ----------
204
+ units : GuiUnitModel
205
+ The unit system used in the GUI.
206
+ mapbox_layers : MapboxLayersModel
207
+ The configuration of the mapbox layers in the GUI.
208
+ visualization_layers : VisualizationLayersModel
209
+ The configuration of the visualization layers in the GUI.
210
+ plotting : PlottingModel
211
+ The configuration for creating hazard forcing plots.
212
+ """
213
+
214
+ units: GuiUnitModel
215
+ mapbox_layers: MapboxLayersModel
216
+ visualization_layers: VisualizationLayersModel
217
+ plotting: PlottingModel
218
+
219
+ @staticmethod
220
+ def read_toml(path: Path) -> "GuiModel":
221
+ with open(path, mode="rb") as fp:
222
+ toml_contents = load_toml(fp)
223
+
224
+ return GuiModel(**toml_contents)
@@ -0,0 +1,336 @@
1
+ import math
2
+ from enum import Enum
3
+ from pathlib import Path
4
+ from typing import Optional, Union
5
+
6
+ from pydantic import AfterValidator, BaseModel, Field, model_validator
7
+ from tomli import load as load_toml
8
+ from typing_extensions import Annotated
9
+
10
+ from flood_adapt.objects.forcing import unit_system as us
11
+ from flood_adapt.objects.forcing.tide_gauge import TideGauge
12
+ from flood_adapt.objects.forcing.timeseries import Scstype
13
+
14
+
15
+ def ensure_ascii(s: str):
16
+ assert s.isascii()
17
+ return s
18
+
19
+
20
+ AsciiStr = Annotated[str, AfterValidator(ensure_ascii)]
21
+
22
+
23
+ class Cstype(str, Enum):
24
+ """The accepted input for the variable cstype in Site."""
25
+
26
+ projected = "projected"
27
+ spherical = "spherical"
28
+
29
+
30
+ class SCSModel(BaseModel):
31
+ """Class describing the accepted input for the variable scs.
32
+
33
+ Includes the file with the non-dimensional SCS rainfall curves in the site folder and the SCS rainfall curve type.
34
+
35
+ Attributes
36
+ ----------
37
+ file : str
38
+ The path to the SCS rainfall curves file.
39
+ type : Scstype
40
+ The type of the SCS rainfall curve.
41
+ """
42
+
43
+ file: str
44
+ type: Scstype
45
+
46
+
47
+ class RiverModel(BaseModel):
48
+ """Model that describes the accepted input for the variable river in Site.
49
+
50
+ Attributes
51
+ ----------
52
+ name : str
53
+ The name of the river.
54
+ description : Optional[str], default=None
55
+ description of the river.
56
+ mean_discharge : us.UnitfulDischarge
57
+ The mean discharge of the river.
58
+ x_coordinate : float
59
+ The x coordinate of the river.
60
+ y_coordinate : float
61
+ The y coordinate of the river.
62
+ """
63
+
64
+ name: str
65
+ description: Optional[str] = None
66
+ mean_discharge: us.UnitfulDischarge
67
+ x_coordinate: float
68
+ y_coordinate: float
69
+
70
+
71
+ class ObsPointModel(BaseModel):
72
+ """The accepted input for the variable obs_point in Site.
73
+
74
+ obs_points is used to define output locations in the hazard model, which will be plotted in the user interface.
75
+
76
+ Attributes
77
+ ----------
78
+ name : Union[int, AsciiStr]
79
+ The name of the observation point.
80
+ description : Optional[str], default=""
81
+ The description of the observation point.
82
+ ID : Optional[int], default=None
83
+ The ID of the observation point.
84
+ file : Optional[str], default=None
85
+ The path to the observation point data file.
86
+ """
87
+
88
+ name: Union[int, AsciiStr]
89
+ description: Optional[str] = ""
90
+ ID: Optional[int] = (
91
+ None # if the observation station is also a tide gauge, this ID should be the same as for obs_station
92
+ )
93
+ file: Optional[str] = None # for locally stored data
94
+ lat: float
95
+ lon: float
96
+
97
+
98
+ class FloodFrequencyModel(BaseModel):
99
+ """The accepted input for the variable flood_frequency in Site."""
100
+
101
+ flooding_threshold: us.UnitfulLength
102
+
103
+
104
+ class DemModel(BaseModel):
105
+ """The accepted input for the variable dem in Site.
106
+
107
+ Attributes
108
+ ----------
109
+ filename : str
110
+ The path to the digital elevation model file.
111
+ units : us.UnitTypesLength
112
+ The units of the digital elevation model file.
113
+ """
114
+
115
+ filename: str
116
+ units: us.UnitTypesLength
117
+
118
+
119
+ class FloodmapType(str, Enum):
120
+ """The accepted input for the variable floodmap in Site."""
121
+
122
+ water_level = "water_level"
123
+ water_depth = "water_depth"
124
+
125
+
126
+ class DatumModel(BaseModel):
127
+ """
128
+ The accepted input for the variable datums in WaterlevelReferenceModel.
129
+
130
+ Attributes
131
+ ----------
132
+ name : str
133
+ The name of the vertical reference model.
134
+ height : us.UnitfulLength
135
+ The height of the vertical reference model relative to the main reference.
136
+ """
137
+
138
+ name: str
139
+ height: us.UnitfulLength
140
+
141
+
142
+ class WaterlevelReferenceModel(BaseModel):
143
+ """The accepted input for the variable water_level in Site.
144
+
145
+ Waterlevels timeseries are calculated from user input, assumed to be relative to the `reference` vertical reference model.
146
+
147
+ For plotting in the GUI, the `reference` vertical reference model is used as the main zero-reference, all values are relative to this.
148
+ All other vertical reference models are plotted as dashed lines.
149
+
150
+ Attributes
151
+ ----------
152
+ reference : str
153
+ The name of the vertical reference model that is used as the main zero-reference.
154
+ datums : list[DatumModel]
155
+ The vertical reference models that are used to calculate the waterlevels timeseries.
156
+ The datums are used to calculate the waterlevels timeseries, which are relative to the `reference` vertical reference model.
157
+ """
158
+
159
+ reference: str
160
+ datums: list[DatumModel] = Field(default_factory=list)
161
+
162
+ def get_datum(self, name: str) -> DatumModel:
163
+ for datum in self.datums:
164
+ if datum.name == name:
165
+ return datum
166
+ raise ValueError(f"Could not find datum with name {name}")
167
+
168
+ @model_validator(mode="after")
169
+ def main_reference_should_be_in_datums_and_eq_zero(self):
170
+ if self.reference not in [datum.name for datum in self.datums]:
171
+ raise ValueError(f"Reference {self.reference} not in {self.datums}")
172
+ if not math.isclose(
173
+ self.get_datum(self.reference).height.value, 0, abs_tol=1e-6
174
+ ):
175
+ raise ValueError(f"Reference {self.reference} height is not zero")
176
+ return self
177
+
178
+ @model_validator(mode="after")
179
+ def all_datums_should_have_unique_names(self):
180
+ datum_names = [datum.name for datum in self.datums]
181
+ if len(set(datum_names)) != len(datum_names):
182
+ raise ValueError(f"Duplicate datum names found: {datum_names}")
183
+ return self
184
+
185
+
186
+ class CycloneTrackDatabaseModel(BaseModel):
187
+ """The accepted input for the variable cyclone_track_database in Site.
188
+
189
+ Attributes
190
+ ----------
191
+ file : str
192
+ The path to the cyclone track database file.
193
+ """
194
+
195
+ file: str
196
+
197
+
198
+ class SlrScenariosModel(BaseModel):
199
+ """The accepted input for the variable slr_scenarios.
200
+
201
+ Attributes
202
+ ----------
203
+ file : str
204
+ The path to the sea level rise scenarios file.
205
+ relative_to_year : int
206
+ The year to which the sea level rise scenarios are relative.
207
+ """
208
+
209
+ file: str
210
+ relative_to_year: int
211
+
212
+
213
+ class FloodModel(BaseModel):
214
+ """The accepted input for the variable overland_model and offshore_model in Site.
215
+
216
+ Attributes
217
+ ----------
218
+ name : str
219
+ The name of the directory in `static/templates/<directory>` that contains the template model files.
220
+ reference : str
221
+ The name of the vertical reference model that is used as the reference datum. Should be defined in water_level.datums.
222
+ vertical_offset : Optional[us.UnitfulLength], default = None
223
+ The vertical offset of the vertical reference model relative to the main reference.
224
+ Given that the height of the vertical reference model is often determined by external sources,
225
+ this vertical offset can be used to correct systematic over-/underestimation of a vertical reference model.
226
+ """
227
+
228
+ name: str
229
+ reference: str
230
+
231
+ # this used to be water_level_offset from events
232
+ vertical_offset: Optional[us.UnitfulLength] = None
233
+
234
+
235
+ class SfincsConfigModel(BaseModel):
236
+ """The expected variables and data types of attributes of the SfincsConfig class.
237
+
238
+ Attributes
239
+ ----------
240
+ csname : str
241
+ The name of the CS model.
242
+ cstype : Cstype
243
+ Cstype of the CS model. must be either "projected" or "spherical".
244
+ version : Optional[str], default = None
245
+ The version of the CS model. If None, the version is not specified.
246
+ offshore_model : Optional[FloodModel], default = None
247
+ The offshore model. If None, the offshore model is not specified.
248
+ overland_model : FloodModel
249
+ The overland model. This is the main model used for the simulation.
250
+ floodmap_units : us.UnitTypesLength
251
+ The units used for the output floodmap. Sfincs always produces in metric units, this is used to convert the floodmap to the correct units.
252
+ save_simulation : Optional[bool], default = False
253
+ Whether to keep or delete the simulation files after the simulation is finished and all output files are created.
254
+ If True, the simulation files are kept. If False, the simulation files are deleted.
255
+ """
256
+
257
+ csname: str
258
+ cstype: Cstype
259
+ version: Optional[str] = None
260
+ offshore_model: Optional[FloodModel] = None
261
+ overland_model: FloodModel
262
+ floodmap_units: us.UnitTypesLength
263
+ save_simulation: Optional[bool] = False
264
+
265
+
266
+ class SfincsModel(BaseModel):
267
+ """The expected variables and data types of attributes of the Sfincs class.
268
+
269
+ Attributes
270
+ ----------
271
+ config : SfincsConfigModel
272
+ The configuration of the Sfincs model.
273
+ water_level : WaterlevelReferenceModel
274
+ The collection of all datums and the main reference datum.
275
+ dem : DemModel
276
+ The digital elevation model.
277
+ flood_frequency : FloodFrequencyModel, default = FloodFrequencyModel()
278
+ The flood frequency model.
279
+ slr : SlrScenariosModel
280
+ Specification of the sea level rise scenarios.
281
+ cyclone_track_database : CycloneTrackDatabaseModel, optional, default = None
282
+ The cyclone track database model.
283
+ scs : SCSModel, optional, default = None
284
+ The SCS model.
285
+ tide_gauge : TideGauge, optional, default = None
286
+ The tide gauge model.
287
+ river : list[RiverModel], optional, default = None
288
+ The river model.
289
+ obs_point : list[ObsPointModel], optional, default = None
290
+ The observation point model.
291
+ """
292
+
293
+ config: SfincsConfigModel
294
+ water_level: WaterlevelReferenceModel
295
+ cyclone_track_database: Optional[CycloneTrackDatabaseModel] = None
296
+ slr_scenarios: Optional[SlrScenariosModel] = None
297
+ scs: Optional[SCSModel] = None # optional for the US to use SCS rainfall curves
298
+ dem: DemModel
299
+
300
+ flood_frequency: FloodFrequencyModel = FloodFrequencyModel(
301
+ flooding_threshold=us.UnitfulLength(value=0.0, units=us.UnitTypesLength.meters)
302
+ ) # TODO we dont actually use this anywhere?
303
+
304
+ tide_gauge: Optional[TideGauge] = None
305
+ river: Optional[list[RiverModel]] = None
306
+ obs_point: Optional[list[ObsPointModel]] = None
307
+
308
+ @staticmethod
309
+ def read_toml(path: Path) -> "SfincsModel":
310
+ with open(path, mode="rb") as fp:
311
+ toml_contents = load_toml(fp)
312
+
313
+ return SfincsModel(**toml_contents)
314
+
315
+ @model_validator(mode="after")
316
+ def ensure_references_exist(self):
317
+ datum_names = [d.name for d in self.water_level.datums]
318
+
319
+ if self.config.overland_model.reference not in datum_names:
320
+ raise ValueError(
321
+ f"Could not find reference `{self.config.overland_model.reference}` in available datums: {datum_names}."
322
+ )
323
+
324
+ if self.config.offshore_model is not None:
325
+ if self.config.offshore_model.reference not in datum_names:
326
+ raise ValueError(
327
+ f"Could not find reference `{self.config.offshore_model.reference}` in available datums: {datum_names}."
328
+ )
329
+
330
+ if self.tide_gauge is not None:
331
+ if self.tide_gauge.reference not in datum_names:
332
+ raise ValueError(
333
+ f"Could not find reference `{self.tide_gauge.reference}` in available datums: {datum_names}."
334
+ )
335
+
336
+ return self
@@ -0,0 +1,124 @@
1
+ import os
2
+ from pathlib import Path
3
+ from typing import Literal, Union
4
+
5
+ import tomli
6
+ import tomli_w
7
+ from pydantic import BaseModel, Field
8
+
9
+ from flood_adapt.config.fiat import FiatModel
10
+ from flood_adapt.config.gui import GuiModel
11
+ from flood_adapt.config.sfincs import SfincsModel
12
+
13
+
14
+ class StandardObjectModel(BaseModel):
15
+ """The accepted input for the variable standard_object in Site."""
16
+
17
+ events: list[str] = Field(default_factory=list)
18
+ projections: list[str] = Field(default_factory=list)
19
+ strategies: list[str] = Field(default_factory=list)
20
+
21
+
22
+ class Site(BaseModel):
23
+ """The expected variables and data types of attributes of the Site class.
24
+
25
+ Attributes
26
+ ----------
27
+ name : str
28
+ Name of the site.
29
+ description : str, default=""
30
+ Description of the site.
31
+ lat : float
32
+ Latitude of the site.
33
+ lon : float
34
+ Longitude of the site.
35
+ standard_objects : StandardObjectModel, default=StandardObjectModel()
36
+ Standard objects of the site.
37
+ gui : GuiModel
38
+ GUI model of the site.
39
+ sfincs : SfincsModel
40
+ SFincs model of the site.
41
+ fiat : FiatModel
42
+ Fiat model of the site.
43
+ """
44
+
45
+ name: str
46
+ description: str = ""
47
+ lat: float
48
+ lon: float
49
+ standard_objects: StandardObjectModel = StandardObjectModel()
50
+
51
+ gui: GuiModel
52
+ sfincs: SfincsModel
53
+ fiat: FiatModel
54
+
55
+ def save(
56
+ self,
57
+ filepath: Union[str, os.PathLike],
58
+ sfincs: str = "sfincs.toml",
59
+ fiat: str = "fiat.toml",
60
+ gui: str = "gui.toml",
61
+ ) -> None:
62
+ """Write toml file from model object."""
63
+ parent_folder = Path(filepath).parent
64
+ config_dict = {
65
+ "name": self.name,
66
+ "description": self.description,
67
+ "lat": self.lat,
68
+ "lon": self.lon,
69
+ "components": {},
70
+ }
71
+
72
+ if self.sfincs is not None:
73
+ config_dict["components"]["sfincs"] = sfincs
74
+ with open(parent_folder / sfincs, "wb") as f:
75
+ tomli_w.dump(self.sfincs.model_dump(exclude_none=True), f)
76
+
77
+ if self.fiat is not None:
78
+ config_dict["components"]["fiat"] = fiat
79
+ with open(parent_folder / fiat, "wb") as f:
80
+ tomli_w.dump(self.fiat.model_dump(exclude_none=True), f)
81
+
82
+ if self.gui is not None:
83
+ config_dict["components"]["gui"] = gui
84
+ with open(parent_folder / gui, "wb") as f:
85
+ tomli_w.dump(self.gui.model_dump(exclude_none=True), f)
86
+
87
+ with open(filepath, "wb") as f:
88
+ tomli_w.dump(config_dict, f)
89
+
90
+ @staticmethod
91
+ def load_file(filepath: Union[str, os.PathLike]) -> "Site":
92
+ """Create Site from toml file."""
93
+ return SiteBuilder.load_file(Path(filepath))
94
+
95
+
96
+ class SiteBuilder(BaseModel):
97
+ """Pydantic model that reads the site configuration file and builds the site model.
98
+
99
+ Note that the components are not required, as the site may not have all of them.
100
+ Second, note that the components are assumed to be the file names of the component configs, located in the same directory as the site configuration file.
101
+ """
102
+
103
+ name: str
104
+ description: str = ""
105
+ lat: float
106
+ lon: float
107
+ components: dict[Literal["sfincs", "fiat", "gui"], str]
108
+
109
+ @staticmethod
110
+ def load_file(file_path: Path) -> "Site":
111
+ with open(file_path, "rb") as f:
112
+ model_dict = tomli.load(f)
113
+
114
+ toml_dir = file_path.parent
115
+ if (sfincs_config := model_dict["components"].get("sfincs")) is not None:
116
+ model_dict["sfincs"] = SfincsModel.read_toml(toml_dir / sfincs_config)
117
+
118
+ if (gui_config := model_dict["components"].get("gui")) is not None:
119
+ model_dict["gui"] = GuiModel.read_toml(toml_dir / gui_config)
120
+
121
+ if (fiat_config := model_dict["components"].get("fiat")) is not None:
122
+ model_dict["fiat"] = FiatModel.read_toml(toml_dir / fiat_config)
123
+
124
+ return Site(**model_dict)
File without changes