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.
Files changed (100) hide show
  1. flood_adapt/__init__.py +26 -22
  2. flood_adapt/adapter/__init__.py +9 -9
  3. flood_adapt/adapter/fiat_adapter.py +1541 -1541
  4. flood_adapt/adapter/interface/hazard_adapter.py +70 -70
  5. flood_adapt/adapter/interface/impact_adapter.py +36 -36
  6. flood_adapt/adapter/interface/model_adapter.py +89 -89
  7. flood_adapt/adapter/interface/offshore.py +19 -19
  8. flood_adapt/adapter/sfincs_adapter.py +1853 -1848
  9. flood_adapt/adapter/sfincs_offshore.py +187 -193
  10. flood_adapt/config/config.py +248 -248
  11. flood_adapt/config/fiat.py +219 -219
  12. flood_adapt/config/gui.py +331 -331
  13. flood_adapt/config/sfincs.py +481 -336
  14. flood_adapt/config/site.py +129 -129
  15. flood_adapt/database_builder/database_builder.py +2210 -2210
  16. flood_adapt/database_builder/templates/default_units/imperial.toml +9 -9
  17. flood_adapt/database_builder/templates/default_units/metric.toml +9 -9
  18. flood_adapt/database_builder/templates/green_infra_table/green_infra_lookup_table.csv +10 -10
  19. flood_adapt/database_builder/templates/infographics/OSM/config_charts.toml +90 -90
  20. flood_adapt/database_builder/templates/infographics/OSM/config_people.toml +57 -57
  21. flood_adapt/database_builder/templates/infographics/OSM/config_risk_charts.toml +121 -121
  22. flood_adapt/database_builder/templates/infographics/OSM/config_roads.toml +65 -65
  23. flood_adapt/database_builder/templates/infographics/OSM/styles.css +45 -45
  24. flood_adapt/database_builder/templates/infographics/US_NSI/config_charts.toml +126 -126
  25. flood_adapt/database_builder/templates/infographics/US_NSI/config_people.toml +60 -60
  26. flood_adapt/database_builder/templates/infographics/US_NSI/config_risk_charts.toml +121 -121
  27. flood_adapt/database_builder/templates/infographics/US_NSI/config_roads.toml +65 -65
  28. flood_adapt/database_builder/templates/infographics/US_NSI/styles.css +45 -45
  29. flood_adapt/database_builder/templates/infometrics/OSM/metrics_additional_risk_configs.toml +4 -4
  30. flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config.toml +143 -143
  31. flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config_risk.toml +153 -153
  32. flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config.toml +127 -127
  33. flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config_risk.toml +57 -57
  34. flood_adapt/database_builder/templates/infometrics/US_NSI/metrics_additional_risk_configs.toml +4 -4
  35. flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config.toml +191 -191
  36. flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config_risk.toml +153 -153
  37. flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config.toml +178 -178
  38. flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config_risk.toml +57 -57
  39. flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config.toml +9 -9
  40. flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config_risk.toml +65 -65
  41. flood_adapt/database_builder/templates/output_layers/bin_colors.toml +5 -5
  42. flood_adapt/database_builder.py +16 -16
  43. flood_adapt/dbs_classes/__init__.py +21 -21
  44. flood_adapt/dbs_classes/database.py +533 -684
  45. flood_adapt/dbs_classes/dbs_benefit.py +77 -76
  46. flood_adapt/dbs_classes/dbs_event.py +61 -59
  47. flood_adapt/dbs_classes/dbs_measure.py +112 -111
  48. flood_adapt/dbs_classes/dbs_projection.py +34 -34
  49. flood_adapt/dbs_classes/dbs_scenario.py +137 -137
  50. flood_adapt/dbs_classes/dbs_static.py +274 -273
  51. flood_adapt/dbs_classes/dbs_strategy.py +130 -129
  52. flood_adapt/dbs_classes/dbs_template.py +279 -278
  53. flood_adapt/dbs_classes/interface/database.py +107 -139
  54. flood_adapt/dbs_classes/interface/element.py +121 -121
  55. flood_adapt/dbs_classes/interface/static.py +47 -47
  56. flood_adapt/flood_adapt.py +1229 -1178
  57. flood_adapt/misc/database_user.py +16 -16
  58. flood_adapt/misc/exceptions.py +22 -0
  59. flood_adapt/misc/log.py +183 -183
  60. flood_adapt/misc/path_builder.py +54 -54
  61. flood_adapt/misc/utils.py +185 -185
  62. flood_adapt/objects/__init__.py +82 -82
  63. flood_adapt/objects/benefits/benefits.py +61 -61
  64. flood_adapt/objects/events/event_factory.py +135 -135
  65. flood_adapt/objects/events/event_set.py +88 -84
  66. flood_adapt/objects/events/events.py +236 -234
  67. flood_adapt/objects/events/historical.py +58 -58
  68. flood_adapt/objects/events/hurricane.py +68 -67
  69. flood_adapt/objects/events/synthetic.py +46 -50
  70. flood_adapt/objects/forcing/__init__.py +92 -92
  71. flood_adapt/objects/forcing/csv.py +68 -68
  72. flood_adapt/objects/forcing/discharge.py +66 -66
  73. flood_adapt/objects/forcing/forcing.py +150 -150
  74. flood_adapt/objects/forcing/forcing_factory.py +182 -182
  75. flood_adapt/objects/forcing/meteo_handler.py +93 -93
  76. flood_adapt/objects/forcing/netcdf.py +40 -40
  77. flood_adapt/objects/forcing/plotting.py +453 -429
  78. flood_adapt/objects/forcing/rainfall.py +98 -98
  79. flood_adapt/objects/forcing/tide_gauge.py +191 -191
  80. flood_adapt/objects/forcing/time_frame.py +90 -90
  81. flood_adapt/objects/forcing/timeseries.py +564 -564
  82. flood_adapt/objects/forcing/unit_system.py +580 -580
  83. flood_adapt/objects/forcing/waterlevels.py +108 -108
  84. flood_adapt/objects/forcing/wind.py +124 -124
  85. flood_adapt/objects/measures/measure_factory.py +92 -92
  86. flood_adapt/objects/measures/measures.py +551 -529
  87. flood_adapt/objects/object_model.py +74 -68
  88. flood_adapt/objects/projections/projections.py +103 -103
  89. flood_adapt/objects/scenarios/scenarios.py +22 -22
  90. flood_adapt/objects/strategies/strategies.py +89 -89
  91. flood_adapt/workflows/benefit_runner.py +579 -554
  92. flood_adapt/workflows/floodmap.py +85 -85
  93. flood_adapt/workflows/impacts_integrator.py +85 -85
  94. flood_adapt/workflows/scenario_runner.py +70 -70
  95. {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/LICENSE +674 -674
  96. {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/METADATA +867 -865
  97. flood_adapt-0.3.11.dist-info/RECORD +140 -0
  98. flood_adapt-0.3.9.dist-info/RECORD +0 -139
  99. {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/WHEEL +0 -0
  100. {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/top_level.txt +0 -0
flood_adapt/config/gui.py CHANGED
@@ -1,331 +1,331 @@
1
- from pathlib import Path
2
- from typing import Optional
3
-
4
- import geopandas as gpd
5
- import numpy as np
6
- import pandas as pd
7
- import tomli
8
- from pydantic import BaseModel, Field, model_validator
9
-
10
- from flood_adapt.config.fiat import DamageType
11
- from flood_adapt.objects.forcing import unit_system as us
12
-
13
-
14
- class Layer(BaseModel):
15
- """
16
- Base class for layers in the GUI.
17
-
18
- Attributes
19
- ----------
20
- bins : list[float]
21
- The bins for the layer.
22
- colors : list[str]
23
- The colors for the layer.
24
- """
25
-
26
- bins: list[float]
27
- colors: list[str]
28
-
29
- @model_validator(mode="after")
30
- def check_bins_and_colors(self) -> "Layer":
31
- """Check that the bins and colors have the same length."""
32
- if (len(self.bins) + 1) != len(self.colors):
33
- raise ValueError(
34
- f"Number of bins ({len(self.bins)}) must be one less than number of colors ({len(self.colors)})"
35
- )
36
- return self
37
-
38
-
39
- class FloodMapLayer(Layer):
40
- zbmax: float
41
- depth_min: float
42
-
43
-
44
- class AggregationDmgLayer(Layer):
45
- damage_decimals: Optional[int] = 0
46
-
47
-
48
- class FootprintsDmgLayer(Layer):
49
- type: DamageType = DamageType.absolute
50
- damage_decimals: Optional[int] = 0
51
- buildings_min_zoom_level: int = 13
52
-
53
-
54
- class BenefitsLayer(Layer):
55
- threshold: Optional[float] = None
56
-
57
-
58
- class OutputLayers(BaseModel):
59
- """The configuration of the mapbox layers in the gui.
60
-
61
- Attributes
62
- ----------
63
- floodmap : FloodMapLayer
64
- The configuration of the floodmap layer.
65
- aggregation_dmg : AggregationDmgLayer
66
- The configuration of the aggregation damage layer.
67
- footprints_dmg : FootprintsDmgLayer
68
- The configuration of the footprints damage layer.
69
-
70
- benefits : BenefitsLayer
71
- The configuration of the benefits layer.
72
- """
73
-
74
- floodmap: FloodMapLayer
75
- aggregation_dmg: AggregationDmgLayer
76
- footprints_dmg: FootprintsDmgLayer
77
-
78
- benefits: Optional[BenefitsLayer] = None
79
-
80
-
81
- class VisualizationLayer(Layer):
82
- """The configuration of a layer to visualize in the gui.
83
-
84
- name : str
85
- The name of the layer to visualize.
86
- long_name : str
87
- The long name of the layer to visualize.
88
- path : str
89
- The path to the layer data to visualize.
90
- field_name : str
91
- The field names of the layer to visualize.
92
- decimals : Optional[int]
93
- The number of decimals to use for the layer to visualize. default is None.
94
- """
95
-
96
- name: str
97
- long_name: str
98
- path: str
99
- field_name: str
100
- decimals: Optional[int] = None
101
-
102
-
103
- _DEFAULT_BIN_NR = 4
104
-
105
-
106
- def interpolate_hex_colors(
107
- start_hex="#FFFFFF", end_hex="#860000", number_bins=_DEFAULT_BIN_NR
108
- ):
109
- """
110
- Interpolate between two hex colors and returns a list of number_bins hex color codes.
111
-
112
- Parameters
113
- ----------
114
- start_hex : str
115
- Starting color in hex format (e.g., "#FFFFFF").
116
- end_hex : str
117
- Ending color in hex format (e.g., "#000000").
118
- number_bins : int
119
- Number of colors to generate between the start and end colors.
120
-
121
- Returns
122
- -------
123
- list[str]
124
- List of hex color codes interpolated between the start and end colors.
125
- """
126
-
127
- def hex_to_rgb(hex_color):
128
- hex_color = hex_color.lstrip("#")
129
- return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4))
130
-
131
- def rgb_to_hex(rgb_color):
132
- return "#{:02X}{:02X}{:02X}".format(*rgb_color)
133
-
134
- start_rgb = hex_to_rgb(start_hex)
135
- end_rgb = hex_to_rgb(end_hex)
136
-
137
- interpolated_colors = []
138
- for i in range(number_bins):
139
- ratio = i / (number_bins - 1) if number_bins > 1 else 0
140
- interpolated_rgb = tuple(
141
- int(start + (end - start) * ratio) for start, end in zip(start_rgb, end_rgb)
142
- )
143
- interpolated_colors.append(rgb_to_hex(interpolated_rgb))
144
-
145
- return interpolated_colors
146
-
147
-
148
- class VisualizationLayers(BaseModel):
149
- """The configuration of the layers you might want to visualize in the gui.
150
-
151
- Attributes
152
- ----------
153
- default : Layer
154
- The default layer settings the visualization layers.
155
- layers : list[VisualizationLayer]
156
- The layers to visualize.
157
- """
158
-
159
- layers: list[VisualizationLayer] = Field(default_factory=list)
160
-
161
- def add_layer(
162
- self,
163
- name: str,
164
- long_name: str,
165
- path: str,
166
- field_name: str,
167
- database_path: Path,
168
- decimals: Optional[int] = None,
169
- bins: Optional[list[float]] = None,
170
- colors: Optional[list[str]] = None,
171
- ) -> None:
172
- if not Path(path).is_absolute():
173
- raise ValueError(f"Path {path} must be absolute.")
174
-
175
- data = gpd.read_file(path)
176
- if field_name not in data.columns:
177
- raise ValueError(
178
- f"Field name {field_name} not found in data. Available fields: {data.columns.tolist()}"
179
- )
180
-
181
- if bins is None:
182
- _, _bins = pd.qcut(
183
- data[field_name], _DEFAULT_BIN_NR, retbins=True, duplicates="drop"
184
- )
185
- bins = _bins.tolist()[1:-1]
186
-
187
- if decimals is None:
188
- non_zero_bins = [abs(b) for b in bins if b != 0]
189
- min_non_zero = min(non_zero_bins) if non_zero_bins else 1
190
- decimals = max(int(-np.floor(np.log10(min_non_zero))), 0)
191
-
192
- if colors is None:
193
- nr_bins = len(bins) + 1
194
- colors = interpolate_hex_colors(number_bins=nr_bins)
195
-
196
- relative_path = Path(path).relative_to(database_path / "static")
197
- self.layers.append(
198
- VisualizationLayer(
199
- bins=bins,
200
- colors=colors,
201
- name=name,
202
- long_name=long_name,
203
- path=relative_path.as_posix(),
204
- field_name=field_name,
205
- decimals=decimals,
206
- )
207
- )
208
-
209
-
210
- class GuiUnitModel(BaseModel):
211
- """The unit system used in the GUI.
212
-
213
- Attributes
214
- ----------
215
- default_length_units : us.UnitTypesLength
216
- The length units used in the GUI.
217
- default_distance_units : us.UnitTypesLength
218
- The distance units used in the GUI.
219
- default_area_units : us.UnitTypesArea
220
- The area units used in the GUI.
221
- default_volume_units : us.UnitTypesVolume
222
- The volume units used in the GUI.
223
- default_velocity_units : us.UnitTypesVelocity
224
- The velocity units used in the GUI.
225
- default_direction_units : us.UnitTypesDirection
226
- The direction units used in the GUI.
227
- default_discharge_units : us.UnitTypesDischarge
228
- The discharge units used in the GUI.
229
- default_intensity_units : us.UnitTypesIntensity
230
- The intensity units used in the GUI.
231
- default_cumulative_units : us.UnitTypesLength
232
- The cumulative units used in the GUI.
233
- """
234
-
235
- default_length_units: us.UnitTypesLength
236
- default_distance_units: us.UnitTypesLength
237
- default_area_units: us.UnitTypesArea
238
- default_volume_units: us.UnitTypesVolume
239
- default_velocity_units: us.UnitTypesVelocity
240
- default_direction_units: us.UnitTypesDirection
241
- default_discharge_units: us.UnitTypesDischarge
242
- default_intensity_units: us.UnitTypesIntensity
243
- default_cumulative_units: us.UnitTypesLength
244
-
245
- @staticmethod
246
- def imperial() -> "GuiUnitModel":
247
- return GuiUnitModel(
248
- default_length_units=us.UnitTypesLength.feet,
249
- default_distance_units=us.UnitTypesLength.miles,
250
- default_area_units=us.UnitTypesArea.sf,
251
- default_volume_units=us.UnitTypesVolume.cf,
252
- default_velocity_units=us.UnitTypesVelocity.mph,
253
- default_direction_units=us.UnitTypesDirection.degrees,
254
- default_discharge_units=us.UnitTypesDischarge.cfs,
255
- default_intensity_units=us.UnitTypesIntensity.inch_hr,
256
- default_cumulative_units=us.UnitTypesLength.inch,
257
- )
258
-
259
- @staticmethod
260
- def metric() -> "GuiUnitModel":
261
- return GuiUnitModel(
262
- default_length_units=us.UnitTypesLength.meters,
263
- default_distance_units=us.UnitTypesLength.meters,
264
- default_area_units=us.UnitTypesArea.m2,
265
- default_volume_units=us.UnitTypesVolume.m3,
266
- default_velocity_units=us.UnitTypesVelocity.mps,
267
- default_direction_units=us.UnitTypesDirection.degrees,
268
- default_discharge_units=us.UnitTypesDischarge.cms,
269
- default_intensity_units=us.UnitTypesIntensity.mm_hr,
270
- default_cumulative_units=us.UnitTypesLength.millimeters,
271
- )
272
-
273
-
274
- class SyntheticTideModel(BaseModel):
275
- """Configuration for the synthetic tide.
276
-
277
- Parameters
278
- ----------
279
- harmonic_amplitude : us.UnitfulLength
280
- The amplitude of the tide harmonic relative to the datum.
281
- datum : str
282
- The datum to which the harmonic amplitude is relative.
283
- Should be a datum defined in `site.sfincs.waterlevels.datums`
284
- """
285
-
286
- harmonic_amplitude: us.UnitfulLength
287
- datum: str
288
-
289
-
290
- class PlottingModel(BaseModel):
291
- """
292
- The configuration of the plotting in the gui.
293
-
294
- Attributes
295
- ----------
296
- excluded_datums : list[str]
297
- A list of datums that will be excluded from the forcing plot in event windows.
298
- synthetic_tide : SyntheticTideModel
299
- The configuration of the synthetic tide.
300
- """
301
-
302
- synthetic_tide: SyntheticTideModel
303
- excluded_datums: list[str] = Field(default_factory=list)
304
-
305
-
306
- class GuiModel(BaseModel):
307
- """The accepted input for the variable gui in Site.
308
-
309
- Attributes
310
- ----------
311
- units : GuiUnitModel
312
- The unit system used in the GUI.
313
- output_layers : OutputLayers
314
- The configuration of the mapbox layers in the GUI.
315
- visualization_layers : VisualizationLayers
316
- The configuration of the visualization layers in the GUI.
317
- plotting : PlottingModel
318
- The configuration for creating hazard forcing plots.
319
- """
320
-
321
- units: GuiUnitModel
322
- output_layers: OutputLayers
323
- visualization_layers: VisualizationLayers
324
- plotting: PlottingModel
325
-
326
- @staticmethod
327
- def read_toml(path: Path) -> "GuiModel":
328
- with open(path, mode="rb") as fp:
329
- toml_contents = tomli.load(fp)
330
-
331
- return GuiModel(**toml_contents)
1
+ from pathlib import Path
2
+ from typing import Optional
3
+
4
+ import geopandas as gpd
5
+ import numpy as np
6
+ import pandas as pd
7
+ import tomli
8
+ from pydantic import BaseModel, Field, model_validator
9
+
10
+ from flood_adapt.config.fiat import DamageType
11
+ from flood_adapt.objects.forcing import unit_system as us
12
+
13
+
14
+ class Layer(BaseModel):
15
+ """
16
+ Base class for layers in the GUI.
17
+
18
+ Attributes
19
+ ----------
20
+ bins : list[float]
21
+ The bins for the layer.
22
+ colors : list[str]
23
+ The colors for the layer.
24
+ """
25
+
26
+ bins: list[float]
27
+ colors: list[str]
28
+
29
+ @model_validator(mode="after")
30
+ def check_bins_and_colors(self) -> "Layer":
31
+ """Check that the bins and colors have the same length."""
32
+ if (len(self.bins) + 1) != len(self.colors):
33
+ raise ValueError(
34
+ f"Number of bins ({len(self.bins)}) must be one less than number of colors ({len(self.colors)})"
35
+ )
36
+ return self
37
+
38
+
39
+ class FloodMapLayer(Layer):
40
+ zbmax: float
41
+ depth_min: float
42
+
43
+
44
+ class AggregationDmgLayer(Layer):
45
+ damage_decimals: Optional[int] = 0
46
+
47
+
48
+ class FootprintsDmgLayer(Layer):
49
+ type: DamageType = DamageType.absolute
50
+ damage_decimals: Optional[int] = 0
51
+ buildings_min_zoom_level: int = 13
52
+
53
+
54
+ class BenefitsLayer(Layer):
55
+ threshold: Optional[float] = None
56
+
57
+
58
+ class OutputLayers(BaseModel):
59
+ """The configuration of the mapbox layers in the gui.
60
+
61
+ Attributes
62
+ ----------
63
+ floodmap : FloodMapLayer
64
+ The configuration of the floodmap layer.
65
+ aggregation_dmg : AggregationDmgLayer
66
+ The configuration of the aggregation damage layer.
67
+ footprints_dmg : FootprintsDmgLayer
68
+ The configuration of the footprints damage layer.
69
+
70
+ benefits : BenefitsLayer
71
+ The configuration of the benefits layer.
72
+ """
73
+
74
+ floodmap: FloodMapLayer
75
+ aggregation_dmg: AggregationDmgLayer
76
+ footprints_dmg: FootprintsDmgLayer
77
+
78
+ benefits: Optional[BenefitsLayer] = None
79
+
80
+
81
+ class VisualizationLayer(Layer):
82
+ """The configuration of a layer to visualize in the gui.
83
+
84
+ name : str
85
+ The name of the layer to visualize.
86
+ long_name : str
87
+ The long name of the layer to visualize.
88
+ path : str
89
+ The path to the layer data to visualize.
90
+ field_name : str
91
+ The field names of the layer to visualize.
92
+ decimals : Optional[int]
93
+ The number of decimals to use for the layer to visualize. default is None.
94
+ """
95
+
96
+ name: str
97
+ long_name: str
98
+ path: str
99
+ field_name: str
100
+ decimals: Optional[int] = None
101
+
102
+
103
+ _DEFAULT_BIN_NR = 4
104
+
105
+
106
+ def interpolate_hex_colors(
107
+ start_hex="#FFFFFF", end_hex="#860000", number_bins=_DEFAULT_BIN_NR
108
+ ):
109
+ """
110
+ Interpolate between two hex colors and returns a list of number_bins hex color codes.
111
+
112
+ Parameters
113
+ ----------
114
+ start_hex : str
115
+ Starting color in hex format (e.g., "#FFFFFF").
116
+ end_hex : str
117
+ Ending color in hex format (e.g., "#000000").
118
+ number_bins : int
119
+ Number of colors to generate between the start and end colors.
120
+
121
+ Returns
122
+ -------
123
+ list[str]
124
+ List of hex color codes interpolated between the start and end colors.
125
+ """
126
+
127
+ def hex_to_rgb(hex_color):
128
+ hex_color = hex_color.lstrip("#")
129
+ return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4))
130
+
131
+ def rgb_to_hex(rgb_color):
132
+ return "#{:02X}{:02X}{:02X}".format(*rgb_color)
133
+
134
+ start_rgb = hex_to_rgb(start_hex)
135
+ end_rgb = hex_to_rgb(end_hex)
136
+
137
+ interpolated_colors = []
138
+ for i in range(number_bins):
139
+ ratio = i / (number_bins - 1) if number_bins > 1 else 0
140
+ interpolated_rgb = tuple(
141
+ int(start + (end - start) * ratio) for start, end in zip(start_rgb, end_rgb)
142
+ )
143
+ interpolated_colors.append(rgb_to_hex(interpolated_rgb))
144
+
145
+ return interpolated_colors
146
+
147
+
148
+ class VisualizationLayers(BaseModel):
149
+ """The configuration of the layers you might want to visualize in the gui.
150
+
151
+ Attributes
152
+ ----------
153
+ default : Layer
154
+ The default layer settings the visualization layers.
155
+ layers : list[VisualizationLayer]
156
+ The layers to visualize.
157
+ """
158
+
159
+ layers: list[VisualizationLayer] = Field(default_factory=list)
160
+
161
+ def add_layer(
162
+ self,
163
+ name: str,
164
+ long_name: str,
165
+ path: str,
166
+ field_name: str,
167
+ database_path: Path,
168
+ decimals: Optional[int] = None,
169
+ bins: Optional[list[float]] = None,
170
+ colors: Optional[list[str]] = None,
171
+ ) -> None:
172
+ if not Path(path).is_absolute():
173
+ raise ValueError(f"Path {path} must be absolute.")
174
+
175
+ data = gpd.read_file(path)
176
+ if field_name not in data.columns:
177
+ raise ValueError(
178
+ f"Field name {field_name} not found in data. Available fields: {data.columns.tolist()}"
179
+ )
180
+
181
+ if bins is None:
182
+ _, _bins = pd.qcut(
183
+ data[field_name], _DEFAULT_BIN_NR, retbins=True, duplicates="drop"
184
+ )
185
+ bins = _bins.tolist()[1:-1]
186
+
187
+ if decimals is None:
188
+ non_zero_bins = [abs(b) for b in bins if b != 0]
189
+ min_non_zero = min(non_zero_bins) if non_zero_bins else 1
190
+ decimals = max(int(-np.floor(np.log10(min_non_zero))), 0)
191
+
192
+ if colors is None:
193
+ nr_bins = len(bins) + 1
194
+ colors = interpolate_hex_colors(number_bins=nr_bins)
195
+
196
+ relative_path = Path(path).relative_to(database_path / "static")
197
+ self.layers.append(
198
+ VisualizationLayer(
199
+ bins=bins,
200
+ colors=colors,
201
+ name=name,
202
+ long_name=long_name,
203
+ path=relative_path.as_posix(),
204
+ field_name=field_name,
205
+ decimals=decimals,
206
+ )
207
+ )
208
+
209
+
210
+ class GuiUnitModel(BaseModel):
211
+ """The unit system used in the GUI.
212
+
213
+ Attributes
214
+ ----------
215
+ default_length_units : us.UnitTypesLength
216
+ The length units used in the GUI.
217
+ default_distance_units : us.UnitTypesLength
218
+ The distance units used in the GUI.
219
+ default_area_units : us.UnitTypesArea
220
+ The area units used in the GUI.
221
+ default_volume_units : us.UnitTypesVolume
222
+ The volume units used in the GUI.
223
+ default_velocity_units : us.UnitTypesVelocity
224
+ The velocity units used in the GUI.
225
+ default_direction_units : us.UnitTypesDirection
226
+ The direction units used in the GUI.
227
+ default_discharge_units : us.UnitTypesDischarge
228
+ The discharge units used in the GUI.
229
+ default_intensity_units : us.UnitTypesIntensity
230
+ The intensity units used in the GUI.
231
+ default_cumulative_units : us.UnitTypesLength
232
+ The cumulative units used in the GUI.
233
+ """
234
+
235
+ default_length_units: us.UnitTypesLength
236
+ default_distance_units: us.UnitTypesLength
237
+ default_area_units: us.UnitTypesArea
238
+ default_volume_units: us.UnitTypesVolume
239
+ default_velocity_units: us.UnitTypesVelocity
240
+ default_direction_units: us.UnitTypesDirection
241
+ default_discharge_units: us.UnitTypesDischarge
242
+ default_intensity_units: us.UnitTypesIntensity
243
+ default_cumulative_units: us.UnitTypesLength
244
+
245
+ @staticmethod
246
+ def imperial() -> "GuiUnitModel":
247
+ return GuiUnitModel(
248
+ default_length_units=us.UnitTypesLength.feet,
249
+ default_distance_units=us.UnitTypesLength.miles,
250
+ default_area_units=us.UnitTypesArea.sf,
251
+ default_volume_units=us.UnitTypesVolume.cf,
252
+ default_velocity_units=us.UnitTypesVelocity.mph,
253
+ default_direction_units=us.UnitTypesDirection.degrees,
254
+ default_discharge_units=us.UnitTypesDischarge.cfs,
255
+ default_intensity_units=us.UnitTypesIntensity.inch_hr,
256
+ default_cumulative_units=us.UnitTypesLength.inch,
257
+ )
258
+
259
+ @staticmethod
260
+ def metric() -> "GuiUnitModel":
261
+ return GuiUnitModel(
262
+ default_length_units=us.UnitTypesLength.meters,
263
+ default_distance_units=us.UnitTypesLength.meters,
264
+ default_area_units=us.UnitTypesArea.m2,
265
+ default_volume_units=us.UnitTypesVolume.m3,
266
+ default_velocity_units=us.UnitTypesVelocity.mps,
267
+ default_direction_units=us.UnitTypesDirection.degrees,
268
+ default_discharge_units=us.UnitTypesDischarge.cms,
269
+ default_intensity_units=us.UnitTypesIntensity.mm_hr,
270
+ default_cumulative_units=us.UnitTypesLength.millimeters,
271
+ )
272
+
273
+
274
+ class SyntheticTideModel(BaseModel):
275
+ """Configuration for the synthetic tide.
276
+
277
+ Parameters
278
+ ----------
279
+ harmonic_amplitude : us.UnitfulLength
280
+ The amplitude of the tide harmonic relative to the datum.
281
+ datum : str
282
+ The datum to which the harmonic amplitude is relative.
283
+ Should be a datum defined in `site.sfincs.waterlevels.datums`
284
+ """
285
+
286
+ harmonic_amplitude: us.UnitfulLength
287
+ datum: str
288
+
289
+
290
+ class PlottingModel(BaseModel):
291
+ """
292
+ The configuration of the plotting in the gui.
293
+
294
+ Attributes
295
+ ----------
296
+ excluded_datums : list[str]
297
+ A list of datums that will be excluded from the forcing plot in event windows.
298
+ synthetic_tide : SyntheticTideModel
299
+ The configuration of the synthetic tide.
300
+ """
301
+
302
+ synthetic_tide: SyntheticTideModel
303
+ excluded_datums: list[str] = Field(default_factory=list)
304
+
305
+
306
+ class GuiModel(BaseModel):
307
+ """The accepted input for the variable gui in Site.
308
+
309
+ Attributes
310
+ ----------
311
+ units : GuiUnitModel
312
+ The unit system used in the GUI.
313
+ output_layers : OutputLayers
314
+ The configuration of the mapbox layers in the GUI.
315
+ visualization_layers : VisualizationLayers
316
+ The configuration of the visualization layers in the GUI.
317
+ plotting : PlottingModel
318
+ The configuration for creating hazard forcing plots.
319
+ """
320
+
321
+ units: GuiUnitModel
322
+ output_layers: OutputLayers
323
+ visualization_layers: VisualizationLayers
324
+ plotting: PlottingModel
325
+
326
+ @staticmethod
327
+ def read_toml(path: Path) -> "GuiModel":
328
+ with open(path, mode="rb") as fp:
329
+ toml_contents = tomli.load(fp)
330
+
331
+ return GuiModel(**toml_contents)