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.
- flood_adapt/__init__.py +22 -0
- flood_adapt/adapter/__init__.py +9 -0
- flood_adapt/adapter/fiat_adapter.py +1502 -0
- flood_adapt/adapter/interface/__init__.py +0 -0
- flood_adapt/adapter/interface/hazard_adapter.py +70 -0
- flood_adapt/adapter/interface/impact_adapter.py +36 -0
- flood_adapt/adapter/interface/model_adapter.py +89 -0
- flood_adapt/adapter/interface/offshore.py +19 -0
- flood_adapt/adapter/sfincs_adapter.py +1857 -0
- flood_adapt/adapter/sfincs_offshore.py +193 -0
- flood_adapt/config/__init__.py +0 -0
- flood_adapt/config/config.py +245 -0
- flood_adapt/config/fiat.py +219 -0
- flood_adapt/config/gui.py +224 -0
- flood_adapt/config/sfincs.py +336 -0
- flood_adapt/config/site.py +124 -0
- flood_adapt/database_builder/__init__.py +0 -0
- flood_adapt/database_builder/database_builder.py +2175 -0
- flood_adapt/database_builder/templates/default_units/imperial.toml +9 -0
- flood_adapt/database_builder/templates/default_units/metric.toml +9 -0
- flood_adapt/database_builder/templates/green_infra_table/green_infra_lookup_table.csv +10 -0
- flood_adapt/database_builder/templates/icons/black_down_48x48.png +0 -0
- flood_adapt/database_builder/templates/icons/black_left_48x48.png +0 -0
- flood_adapt/database_builder/templates/icons/black_right_48x48.png +0 -0
- flood_adapt/database_builder/templates/icons/black_up_48x48.png +0 -0
- flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_down.png +0 -0
- flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_left.png +0 -0
- flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_right.png +0 -0
- flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_up.png +0 -0
- flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_down.png +0 -0
- flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_left.png +0 -0
- flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_right.png +0 -0
- flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_up.png +0 -0
- flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_white_left.png +0 -0
- flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_white_right.png +0 -0
- flood_adapt/database_builder/templates/icons/white_down_48x48.png +0 -0
- flood_adapt/database_builder/templates/icons/white_left_48x48.png +0 -0
- flood_adapt/database_builder/templates/icons/white_right_48x48.png +0 -0
- flood_adapt/database_builder/templates/icons/white_up_48x48.png +0 -0
- flood_adapt/database_builder/templates/infographics/OSM/config_charts.toml +90 -0
- flood_adapt/database_builder/templates/infographics/OSM/config_people.toml +57 -0
- flood_adapt/database_builder/templates/infographics/OSM/config_risk_charts.toml +121 -0
- flood_adapt/database_builder/templates/infographics/OSM/config_roads.toml +65 -0
- flood_adapt/database_builder/templates/infographics/OSM/styles.css +45 -0
- flood_adapt/database_builder/templates/infographics/US_NSI/config_charts.toml +126 -0
- flood_adapt/database_builder/templates/infographics/US_NSI/config_people.toml +60 -0
- flood_adapt/database_builder/templates/infographics/US_NSI/config_risk_charts.toml +121 -0
- flood_adapt/database_builder/templates/infographics/US_NSI/config_roads.toml +65 -0
- flood_adapt/database_builder/templates/infographics/US_NSI/styles.css +45 -0
- flood_adapt/database_builder/templates/infographics/images/ambulance.png +0 -0
- flood_adapt/database_builder/templates/infographics/images/car.png +0 -0
- flood_adapt/database_builder/templates/infographics/images/cart.png +0 -0
- flood_adapt/database_builder/templates/infographics/images/firetruck.png +0 -0
- flood_adapt/database_builder/templates/infographics/images/hospital.png +0 -0
- flood_adapt/database_builder/templates/infographics/images/house.png +0 -0
- flood_adapt/database_builder/templates/infographics/images/info.png +0 -0
- flood_adapt/database_builder/templates/infographics/images/money.png +0 -0
- flood_adapt/database_builder/templates/infographics/images/person.png +0 -0
- flood_adapt/database_builder/templates/infographics/images/school.png +0 -0
- flood_adapt/database_builder/templates/infographics/images/truck.png +0 -0
- flood_adapt/database_builder/templates/infographics/images/walking_person.png +0 -0
- flood_adapt/database_builder/templates/infometrics/OSM/metrics_additional_risk_configs.toml +4 -0
- flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config.toml +143 -0
- flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config_risk.toml +153 -0
- flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config.toml +127 -0
- flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config_risk.toml +57 -0
- flood_adapt/database_builder/templates/infometrics/US_NSI/metrics_additional_risk_configs.toml +4 -0
- flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config.toml +191 -0
- flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config_risk.toml +153 -0
- flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config.toml +178 -0
- flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config_risk.toml +57 -0
- flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config.toml +9 -0
- flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config_risk.toml +65 -0
- flood_adapt/database_builder/templates/mapbox_layers/bin_colors.toml +5 -0
- flood_adapt/database_builder.py +16 -0
- flood_adapt/dbs_classes/__init__.py +21 -0
- flood_adapt/dbs_classes/database.py +716 -0
- flood_adapt/dbs_classes/dbs_benefit.py +97 -0
- flood_adapt/dbs_classes/dbs_event.py +91 -0
- flood_adapt/dbs_classes/dbs_measure.py +103 -0
- flood_adapt/dbs_classes/dbs_projection.py +52 -0
- flood_adapt/dbs_classes/dbs_scenario.py +150 -0
- flood_adapt/dbs_classes/dbs_static.py +261 -0
- flood_adapt/dbs_classes/dbs_strategy.py +147 -0
- flood_adapt/dbs_classes/dbs_template.py +302 -0
- flood_adapt/dbs_classes/interface/database.py +147 -0
- flood_adapt/dbs_classes/interface/element.py +137 -0
- flood_adapt/dbs_classes/interface/static.py +47 -0
- flood_adapt/flood_adapt.py +1371 -0
- flood_adapt/misc/__init__.py +0 -0
- flood_adapt/misc/database_user.py +16 -0
- flood_adapt/misc/log.py +183 -0
- flood_adapt/misc/path_builder.py +54 -0
- flood_adapt/misc/utils.py +185 -0
- flood_adapt/objects/__init__.py +59 -0
- flood_adapt/objects/benefits/__init__.py +0 -0
- flood_adapt/objects/benefits/benefits.py +61 -0
- flood_adapt/objects/events/__init__.py +0 -0
- flood_adapt/objects/events/event_factory.py +135 -0
- flood_adapt/objects/events/event_set.py +84 -0
- flood_adapt/objects/events/events.py +221 -0
- flood_adapt/objects/events/historical.py +55 -0
- flood_adapt/objects/events/hurricane.py +64 -0
- flood_adapt/objects/events/synthetic.py +48 -0
- flood_adapt/objects/forcing/__init__.py +0 -0
- flood_adapt/objects/forcing/csv.py +68 -0
- flood_adapt/objects/forcing/discharge.py +66 -0
- flood_adapt/objects/forcing/forcing.py +142 -0
- flood_adapt/objects/forcing/forcing_factory.py +182 -0
- flood_adapt/objects/forcing/meteo_handler.py +93 -0
- flood_adapt/objects/forcing/netcdf.py +40 -0
- flood_adapt/objects/forcing/plotting.py +428 -0
- flood_adapt/objects/forcing/rainfall.py +98 -0
- flood_adapt/objects/forcing/tide_gauge.py +191 -0
- flood_adapt/objects/forcing/time_frame.py +77 -0
- flood_adapt/objects/forcing/timeseries.py +552 -0
- flood_adapt/objects/forcing/unit_system.py +580 -0
- flood_adapt/objects/forcing/waterlevels.py +108 -0
- flood_adapt/objects/forcing/wind.py +124 -0
- flood_adapt/objects/measures/__init__.py +0 -0
- flood_adapt/objects/measures/measure_factory.py +92 -0
- flood_adapt/objects/measures/measures.py +506 -0
- flood_adapt/objects/object_model.py +68 -0
- flood_adapt/objects/projections/__init__.py +0 -0
- flood_adapt/objects/projections/projections.py +89 -0
- flood_adapt/objects/scenarios/__init__.py +0 -0
- flood_adapt/objects/scenarios/scenarios.py +22 -0
- flood_adapt/objects/strategies/__init__.py +0 -0
- flood_adapt/objects/strategies/strategies.py +68 -0
- flood_adapt/workflows/__init__.py +0 -0
- flood_adapt/workflows/benefit_runner.py +541 -0
- flood_adapt/workflows/floodmap.py +85 -0
- flood_adapt/workflows/impacts_integrator.py +82 -0
- flood_adapt/workflows/scenario_runner.py +69 -0
- flood_adapt-0.3.0.dist-info/LICENSE +21 -0
- flood_adapt-0.3.0.dist-info/METADATA +183 -0
- flood_adapt-0.3.0.dist-info/RECORD +139 -0
- flood_adapt-0.3.0.dist-info/WHEEL +5 -0
- flood_adapt-0.3.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1371 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any, List, Optional, Type, Union
|
|
4
|
+
|
|
5
|
+
import geopandas as gpd
|
|
6
|
+
import numpy as np
|
|
7
|
+
import pandas as pd
|
|
8
|
+
from cht_cyclones.tropical_cyclone import TropicalCyclone
|
|
9
|
+
from fiat_toolbox.infographics.infographics_factory import InforgraphicFactory
|
|
10
|
+
from fiat_toolbox.metrics_writer.fiat_read_metrics_file import MetricsFileReader
|
|
11
|
+
from hydromt_sfincs.quadtree import QuadtreeGrid
|
|
12
|
+
|
|
13
|
+
from flood_adapt.config.site import Site
|
|
14
|
+
from flood_adapt.dbs_classes.database import Database
|
|
15
|
+
from flood_adapt.misc.log import FloodAdaptLogging
|
|
16
|
+
from flood_adapt.objects.benefits.benefits import Benefit
|
|
17
|
+
from flood_adapt.objects.events.event_factory import (
|
|
18
|
+
EventFactory,
|
|
19
|
+
)
|
|
20
|
+
from flood_adapt.objects.events.event_set import EventSet
|
|
21
|
+
from flood_adapt.objects.events.events import (
|
|
22
|
+
Event,
|
|
23
|
+
Mode,
|
|
24
|
+
Template,
|
|
25
|
+
)
|
|
26
|
+
from flood_adapt.objects.forcing import unit_system as us
|
|
27
|
+
from flood_adapt.objects.forcing.csv import read_csv as _read_csv
|
|
28
|
+
from flood_adapt.objects.forcing.forcing import (
|
|
29
|
+
ForcingType,
|
|
30
|
+
IForcing,
|
|
31
|
+
)
|
|
32
|
+
from flood_adapt.objects.forcing.forcing_factory import ForcingFactory
|
|
33
|
+
from flood_adapt.objects.forcing.plotting import (
|
|
34
|
+
plot_forcing as _plot_forcing,
|
|
35
|
+
)
|
|
36
|
+
from flood_adapt.objects.forcing.tide_gauge import TideGauge
|
|
37
|
+
from flood_adapt.objects.forcing.time_frame import TimeFrame
|
|
38
|
+
from flood_adapt.objects.measures.measures import (
|
|
39
|
+
Buyout,
|
|
40
|
+
Elevate,
|
|
41
|
+
FloodProof,
|
|
42
|
+
FloodWall,
|
|
43
|
+
GreenInfrastructure,
|
|
44
|
+
Measure,
|
|
45
|
+
Pump,
|
|
46
|
+
)
|
|
47
|
+
from flood_adapt.objects.projections.projections import Projection
|
|
48
|
+
from flood_adapt.objects.scenarios.scenarios import Scenario
|
|
49
|
+
from flood_adapt.objects.strategies.strategies import Strategy
|
|
50
|
+
from flood_adapt.workflows.impacts_integrator import Impacts
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class FloodAdapt:
|
|
54
|
+
database: Database
|
|
55
|
+
|
|
56
|
+
def __init__(self, database_path: Path) -> None:
|
|
57
|
+
"""Initialize the FloodAdapt class with a database path.
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
database_path : Path
|
|
62
|
+
The path to the database file.
|
|
63
|
+
"""
|
|
64
|
+
self.database = Database(
|
|
65
|
+
database_path=database_path.parent, database_name=database_path.name
|
|
66
|
+
)
|
|
67
|
+
self.logger = FloodAdaptLogging.getLogger()
|
|
68
|
+
|
|
69
|
+
# Measures
|
|
70
|
+
def get_measures(self) -> dict[str, Any]:
|
|
71
|
+
"""
|
|
72
|
+
Get all measures from the database.
|
|
73
|
+
|
|
74
|
+
Returns
|
|
75
|
+
-------
|
|
76
|
+
dict[str, Any]
|
|
77
|
+
A dictionary containing all measures.
|
|
78
|
+
Includes keys: 'name', 'description', 'path', 'last_modification_date', 'objects'
|
|
79
|
+
Each value is a list of the corresponding attribute for each measure.
|
|
80
|
+
"""
|
|
81
|
+
return self.database.measures.list_objects()
|
|
82
|
+
|
|
83
|
+
def get_measure(self, name: str) -> Measure:
|
|
84
|
+
"""
|
|
85
|
+
Get a measure from the database by name.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
name : str
|
|
90
|
+
The name of the measure to retrieve.
|
|
91
|
+
|
|
92
|
+
Returns
|
|
93
|
+
-------
|
|
94
|
+
Measure
|
|
95
|
+
The measure object with the given name.
|
|
96
|
+
|
|
97
|
+
Raises
|
|
98
|
+
------
|
|
99
|
+
ValueError
|
|
100
|
+
If the measure with the given name does not exist.
|
|
101
|
+
"""
|
|
102
|
+
return self.database.measures.get(name)
|
|
103
|
+
|
|
104
|
+
def create_measure(self, attrs: dict[str, Any], type: str = None) -> Measure:
|
|
105
|
+
"""Create a measure from a dictionary of attributes and a type string.
|
|
106
|
+
|
|
107
|
+
Parameters
|
|
108
|
+
----------
|
|
109
|
+
attrs : dict[str, Any]
|
|
110
|
+
Dictionary of attributes for the measure.
|
|
111
|
+
type : str
|
|
112
|
+
Type of measure to create.
|
|
113
|
+
|
|
114
|
+
Returns
|
|
115
|
+
-------
|
|
116
|
+
Measure
|
|
117
|
+
Measure object.
|
|
118
|
+
"""
|
|
119
|
+
if type == "elevate_properties":
|
|
120
|
+
return Elevate(**attrs)
|
|
121
|
+
elif type == "buyout_properties":
|
|
122
|
+
return Buyout(**attrs)
|
|
123
|
+
elif type == "floodproof_properties":
|
|
124
|
+
return FloodProof(**attrs)
|
|
125
|
+
elif type in ["floodwall", "thin_dam", "levee"]:
|
|
126
|
+
return FloodWall(**attrs)
|
|
127
|
+
elif type in ["pump", "culvert"]:
|
|
128
|
+
return Pump(**attrs)
|
|
129
|
+
elif type in ["water_square", "total_storage", "greening"]:
|
|
130
|
+
return GreenInfrastructure(**attrs)
|
|
131
|
+
else:
|
|
132
|
+
raise ValueError(f"Invalid measure type: {type}")
|
|
133
|
+
|
|
134
|
+
def save_measure(self, measure: Measure, overwrite: bool = False) -> None:
|
|
135
|
+
"""Save an event object to the database.
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
measure : Measure
|
|
140
|
+
The measure object to save.
|
|
141
|
+
|
|
142
|
+
Raises
|
|
143
|
+
------
|
|
144
|
+
ValueError
|
|
145
|
+
If the event object is not valid.
|
|
146
|
+
"""
|
|
147
|
+
self.database.measures.save(measure, overwrite=overwrite)
|
|
148
|
+
|
|
149
|
+
def edit_measure(self, measure: Measure) -> None:
|
|
150
|
+
"""Edit an event object in the database.
|
|
151
|
+
|
|
152
|
+
Parameters
|
|
153
|
+
----------
|
|
154
|
+
measure : Measure
|
|
155
|
+
The measure object to edit.
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
Raises
|
|
159
|
+
------
|
|
160
|
+
ValueError
|
|
161
|
+
If the event object does not exist.
|
|
162
|
+
"""
|
|
163
|
+
self.database.measures.edit(measure)
|
|
164
|
+
|
|
165
|
+
def delete_measure(self, name: str) -> None:
|
|
166
|
+
"""Delete an event from the database.
|
|
167
|
+
|
|
168
|
+
Parameters
|
|
169
|
+
----------
|
|
170
|
+
name : str
|
|
171
|
+
The name of the event to delete.
|
|
172
|
+
|
|
173
|
+
Raises
|
|
174
|
+
------
|
|
175
|
+
ValueError
|
|
176
|
+
If the event does not exist.
|
|
177
|
+
"""
|
|
178
|
+
self.database.measures.delete(name)
|
|
179
|
+
|
|
180
|
+
def copy_measure(self, old_name: str, new_name: str, new_description: str) -> None:
|
|
181
|
+
"""Copy an event in the database.
|
|
182
|
+
|
|
183
|
+
Parameters
|
|
184
|
+
----------
|
|
185
|
+
old_name : str
|
|
186
|
+
The name of the event to copy.
|
|
187
|
+
new_name : str
|
|
188
|
+
The name of the new event.
|
|
189
|
+
new_description : str
|
|
190
|
+
The description of the new event
|
|
191
|
+
"""
|
|
192
|
+
self.database.measures.copy(old_name, new_name, new_description)
|
|
193
|
+
|
|
194
|
+
def calculate_polygon_area(self, gdf: gpd.GeoDataFrame, site: Site) -> float:
|
|
195
|
+
"""
|
|
196
|
+
Calculate the area of a polygon from a GeoDataFrame.
|
|
197
|
+
|
|
198
|
+
Parameters
|
|
199
|
+
----------
|
|
200
|
+
gdf : gpd.GeoDataFrame
|
|
201
|
+
A GeoDataFrame containing the polygon geometry.
|
|
202
|
+
site : Site
|
|
203
|
+
An instance of Site representing the site information.
|
|
204
|
+
|
|
205
|
+
Returns
|
|
206
|
+
-------
|
|
207
|
+
float: The area of the polygon in the specified units.
|
|
208
|
+
"""
|
|
209
|
+
return GreenInfrastructure.calculate_polygon_area(gdf=gdf, site=site)
|
|
210
|
+
|
|
211
|
+
def calculate_volume(
|
|
212
|
+
self,
|
|
213
|
+
area: us.UnitfulArea,
|
|
214
|
+
height: us.UnitfulHeight = us.UnitfulHeight(
|
|
215
|
+
value=0.0, units=us.UnitTypesLength.meters
|
|
216
|
+
),
|
|
217
|
+
percent_area: float = 100.0,
|
|
218
|
+
) -> float:
|
|
219
|
+
"""
|
|
220
|
+
Calculate the volume of green infrastructure based on the given area, height, and percent area.
|
|
221
|
+
|
|
222
|
+
Parameters
|
|
223
|
+
----------
|
|
224
|
+
area : float
|
|
225
|
+
The area of the green infrastructure in square units.
|
|
226
|
+
height : float
|
|
227
|
+
The height of the green infrastructure in units. Defaults to 0.0.
|
|
228
|
+
percent_area : float
|
|
229
|
+
The percentage of the area to be considered. Defaults to 100.0.
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
Returns
|
|
233
|
+
-------
|
|
234
|
+
float: The calculated volume of the green infrastructure.
|
|
235
|
+
"""
|
|
236
|
+
return GreenInfrastructure.calculate_volume(
|
|
237
|
+
area=area, height=height, percent_area=percent_area
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
def get_green_infra_table(self, measure_type: str) -> pd.DataFrame:
|
|
241
|
+
"""Return a table with different types of green infrastructure measures and their infiltration depths.
|
|
242
|
+
|
|
243
|
+
Parameters
|
|
244
|
+
----------
|
|
245
|
+
measure_type : str
|
|
246
|
+
The type of green infrastructure measure.
|
|
247
|
+
|
|
248
|
+
Returns
|
|
249
|
+
-------
|
|
250
|
+
pd.DataFrame
|
|
251
|
+
A table with different types of green infrastructure measures and their infiltration depths.
|
|
252
|
+
|
|
253
|
+
"""
|
|
254
|
+
return self.database.static.get_green_infra_table(measure_type)
|
|
255
|
+
|
|
256
|
+
# Strategies
|
|
257
|
+
def get_strategies(self) -> dict[str, Any]:
|
|
258
|
+
"""
|
|
259
|
+
Get all strategies from the database.
|
|
260
|
+
|
|
261
|
+
Returns
|
|
262
|
+
-------
|
|
263
|
+
dict[str, Any]
|
|
264
|
+
A dictionary containing all strategies.
|
|
265
|
+
Includes keys: 'name', 'description', 'path', 'last_modification_date', 'objects'
|
|
266
|
+
Each value is a list of the corresponding attribute for each strategy.
|
|
267
|
+
"""
|
|
268
|
+
return self.database.strategies.list_objects()
|
|
269
|
+
|
|
270
|
+
def get_strategy(self, name: str) -> Strategy:
|
|
271
|
+
"""
|
|
272
|
+
Get a strategy from the database by name.
|
|
273
|
+
|
|
274
|
+
Parameters
|
|
275
|
+
----------
|
|
276
|
+
name : str
|
|
277
|
+
The name of the strategy to retrieve.
|
|
278
|
+
|
|
279
|
+
Returns
|
|
280
|
+
-------
|
|
281
|
+
Strategy
|
|
282
|
+
The strategy object with the given name.
|
|
283
|
+
|
|
284
|
+
Raises
|
|
285
|
+
------
|
|
286
|
+
ValueError
|
|
287
|
+
If the strategy with the given name does not exist.
|
|
288
|
+
"""
|
|
289
|
+
return self.database.strategies.get(name)
|
|
290
|
+
|
|
291
|
+
def create_strategy(self, attrs: dict[str, Any]) -> Strategy:
|
|
292
|
+
"""Create a new strategy object.
|
|
293
|
+
|
|
294
|
+
Parameters
|
|
295
|
+
----------
|
|
296
|
+
attrs : dict[str, Any]
|
|
297
|
+
The attributes of the strategy object to create. Should adhere to the Strategy schema.
|
|
298
|
+
|
|
299
|
+
Returns
|
|
300
|
+
-------
|
|
301
|
+
Strategy
|
|
302
|
+
The strategy object
|
|
303
|
+
|
|
304
|
+
Raises
|
|
305
|
+
------
|
|
306
|
+
ValueError
|
|
307
|
+
If the strategy with the given name does not exist.
|
|
308
|
+
If attrs does not adhere to the Strategy schema.
|
|
309
|
+
"""
|
|
310
|
+
return Strategy(**attrs)
|
|
311
|
+
|
|
312
|
+
def save_strategy(self, strategy: Strategy) -> None:
|
|
313
|
+
"""
|
|
314
|
+
Save a strategy object to the database.
|
|
315
|
+
|
|
316
|
+
Parameters
|
|
317
|
+
----------
|
|
318
|
+
strategy : Strategy
|
|
319
|
+
The strategy object to save.
|
|
320
|
+
|
|
321
|
+
Raises
|
|
322
|
+
------
|
|
323
|
+
ValueError
|
|
324
|
+
If the strategy object is not valid.
|
|
325
|
+
If the strategy object already exists.
|
|
326
|
+
"""
|
|
327
|
+
self.database.strategies.save(strategy)
|
|
328
|
+
|
|
329
|
+
def delete_strategy(self, name: str) -> None:
|
|
330
|
+
"""
|
|
331
|
+
Delete a strategy from the database.
|
|
332
|
+
|
|
333
|
+
Parameters
|
|
334
|
+
----------
|
|
335
|
+
name : str
|
|
336
|
+
The name of the strategy to delete.
|
|
337
|
+
|
|
338
|
+
Raises
|
|
339
|
+
------
|
|
340
|
+
ValueError
|
|
341
|
+
If the strategy does not exist.
|
|
342
|
+
"""
|
|
343
|
+
self.database.strategies.delete(name)
|
|
344
|
+
|
|
345
|
+
# Events
|
|
346
|
+
def get_events(self) -> dict[str, Any]:
|
|
347
|
+
"""Get all events from the database.
|
|
348
|
+
|
|
349
|
+
Returns
|
|
350
|
+
-------
|
|
351
|
+
dict[str, Any]
|
|
352
|
+
A dictionary containing all events.
|
|
353
|
+
Includes keys: 'name', 'description', 'path', 'last_modification_date', 'objects'
|
|
354
|
+
Each value is a list of the corresponding attribute for each benefit.
|
|
355
|
+
"""
|
|
356
|
+
return self.database.events.list_objects()
|
|
357
|
+
|
|
358
|
+
def get_event(self, name: str) -> Event | EventSet:
|
|
359
|
+
"""Get an event from the database by name.
|
|
360
|
+
|
|
361
|
+
Parameters
|
|
362
|
+
----------
|
|
363
|
+
name : str
|
|
364
|
+
The name of the event to retrieve.
|
|
365
|
+
|
|
366
|
+
Returns
|
|
367
|
+
-------
|
|
368
|
+
Event | EventSet
|
|
369
|
+
The event with the given name.
|
|
370
|
+
|
|
371
|
+
Raises
|
|
372
|
+
------
|
|
373
|
+
ValueError
|
|
374
|
+
If the event with the given name does not exist.
|
|
375
|
+
"""
|
|
376
|
+
return self.database.events.get(name)
|
|
377
|
+
|
|
378
|
+
def get_event_mode(self, name: str) -> Mode:
|
|
379
|
+
"""Get the mode of an event from the database by name.
|
|
380
|
+
|
|
381
|
+
Parameters
|
|
382
|
+
----------
|
|
383
|
+
name : str
|
|
384
|
+
|
|
385
|
+
Returns
|
|
386
|
+
-------
|
|
387
|
+
Mode
|
|
388
|
+
The mode of the event with the given name, either `risk` or `single_event`.
|
|
389
|
+
"""
|
|
390
|
+
return self.database.events.get(name).mode
|
|
391
|
+
|
|
392
|
+
def create_event(self, attrs: dict[str, Any] | Event) -> Event:
|
|
393
|
+
"""Create a event object from a dictionary of attributes.
|
|
394
|
+
|
|
395
|
+
Parameters
|
|
396
|
+
----------
|
|
397
|
+
attrs : Event [str, Any]
|
|
398
|
+
Dictionary of attributes
|
|
399
|
+
|
|
400
|
+
Returns
|
|
401
|
+
-------
|
|
402
|
+
Event
|
|
403
|
+
Depending on attrs.template an event object.
|
|
404
|
+
Can be of type: Synthetic, Historical, Hurricane.
|
|
405
|
+
"""
|
|
406
|
+
return EventFactory.load_dict(attrs)
|
|
407
|
+
|
|
408
|
+
def create_event_set(
|
|
409
|
+
self, attrs: dict[str, Any] | EventSet, sub_events: list[Event]
|
|
410
|
+
) -> EventSet:
|
|
411
|
+
"""Create a event set object from a dictionary of attributes.
|
|
412
|
+
|
|
413
|
+
Parameters
|
|
414
|
+
----------
|
|
415
|
+
attrs : EventSet [str, Any]
|
|
416
|
+
Dictionary of attributes
|
|
417
|
+
sub_events : list[Event]
|
|
418
|
+
List of events in the event set
|
|
419
|
+
|
|
420
|
+
Returns
|
|
421
|
+
-------
|
|
422
|
+
EventSet
|
|
423
|
+
EventSet object
|
|
424
|
+
"""
|
|
425
|
+
return EventSet(**attrs, sub_events=sub_events)
|
|
426
|
+
|
|
427
|
+
@staticmethod
|
|
428
|
+
def list_forcings() -> list[Type[IForcing]]:
|
|
429
|
+
return ForcingFactory.list_forcings()
|
|
430
|
+
|
|
431
|
+
@staticmethod
|
|
432
|
+
def get_allowed_forcings(template: Template) -> dict[str, List[str]]:
|
|
433
|
+
return EventFactory.get_allowed_forcings(template)
|
|
434
|
+
|
|
435
|
+
def save_event(self, event: Event) -> None:
|
|
436
|
+
"""Save an event object to the database.
|
|
437
|
+
|
|
438
|
+
Parameters
|
|
439
|
+
----------
|
|
440
|
+
event : Event
|
|
441
|
+
The event object to save.
|
|
442
|
+
|
|
443
|
+
Raises
|
|
444
|
+
------
|
|
445
|
+
ValueError
|
|
446
|
+
If the event object is not valid.
|
|
447
|
+
"""
|
|
448
|
+
self.database.events.save(event)
|
|
449
|
+
|
|
450
|
+
def save_timeseries_csv(self, name: str, event: Event, df: pd.DataFrame) -> None:
|
|
451
|
+
"""Save timeseries data to a csv file.
|
|
452
|
+
|
|
453
|
+
Parameters
|
|
454
|
+
----------
|
|
455
|
+
name : str
|
|
456
|
+
Name of the event
|
|
457
|
+
event : Event
|
|
458
|
+
Event object
|
|
459
|
+
df : pd.DataFrame
|
|
460
|
+
Dataframe of timeseries data
|
|
461
|
+
"""
|
|
462
|
+
self.database.write_to_csv(name, event, df)
|
|
463
|
+
|
|
464
|
+
def edit_event(self, event: Event) -> None:
|
|
465
|
+
"""Edit an event object in the database.
|
|
466
|
+
|
|
467
|
+
Parameters
|
|
468
|
+
----------
|
|
469
|
+
event : Event
|
|
470
|
+
The event object to edit.
|
|
471
|
+
|
|
472
|
+
Raises
|
|
473
|
+
------
|
|
474
|
+
ValueError
|
|
475
|
+
If the event object does not exist.
|
|
476
|
+
If the event is used in a scenario.
|
|
477
|
+
"""
|
|
478
|
+
self.database.events.edit(event)
|
|
479
|
+
|
|
480
|
+
def delete_event(self, name: str) -> None:
|
|
481
|
+
"""Delete an event from the database.
|
|
482
|
+
|
|
483
|
+
Parameters
|
|
484
|
+
----------
|
|
485
|
+
name : str
|
|
486
|
+
The name of the event to delete.
|
|
487
|
+
|
|
488
|
+
Raises
|
|
489
|
+
------
|
|
490
|
+
ValueError
|
|
491
|
+
If the event does not exist.
|
|
492
|
+
If the event is used in a scenario.
|
|
493
|
+
"""
|
|
494
|
+
self.database.events.delete(name)
|
|
495
|
+
|
|
496
|
+
def copy_event(self, old_name: str, new_name: str, new_description: str) -> None:
|
|
497
|
+
"""Copy an event in the database.
|
|
498
|
+
|
|
499
|
+
Parameters
|
|
500
|
+
----------
|
|
501
|
+
old_name : str
|
|
502
|
+
The name of the event to copy.
|
|
503
|
+
new_name : str
|
|
504
|
+
The name of the new event.
|
|
505
|
+
new_description : str
|
|
506
|
+
The description of the new event
|
|
507
|
+
"""
|
|
508
|
+
self.database.events.copy(old_name, new_name, new_description)
|
|
509
|
+
|
|
510
|
+
def check_higher_level_usage(self, name: str) -> list[str]:
|
|
511
|
+
"""Check if an event is used in a scenario.
|
|
512
|
+
|
|
513
|
+
Parameters
|
|
514
|
+
----------
|
|
515
|
+
name : str
|
|
516
|
+
name of the event to be checked
|
|
517
|
+
|
|
518
|
+
Returns
|
|
519
|
+
-------
|
|
520
|
+
list[str]
|
|
521
|
+
list of scenario names where the event is used
|
|
522
|
+
|
|
523
|
+
"""
|
|
524
|
+
return self.database.events.check_higher_level_usage(name)
|
|
525
|
+
|
|
526
|
+
def download_wl_data(
|
|
527
|
+
self,
|
|
528
|
+
tide_gauge: TideGauge,
|
|
529
|
+
time: TimeFrame,
|
|
530
|
+
units: us.UnitTypesLength,
|
|
531
|
+
out_path: str,
|
|
532
|
+
) -> pd.DataFrame:
|
|
533
|
+
"""Download water level data from a station or tide gauge.
|
|
534
|
+
|
|
535
|
+
Parameters
|
|
536
|
+
----------
|
|
537
|
+
tide_gauge : TideGauge
|
|
538
|
+
Tide gauge object to download data from
|
|
539
|
+
time: TimeFrame
|
|
540
|
+
Time model object containing start and end time
|
|
541
|
+
units : UnitTypesLength
|
|
542
|
+
Units that data the returned data will be converted to
|
|
543
|
+
out_path : str
|
|
544
|
+
Path to save the data to
|
|
545
|
+
"""
|
|
546
|
+
return tide_gauge.get_waterlevels_in_time_frame(
|
|
547
|
+
time=time,
|
|
548
|
+
units=units,
|
|
549
|
+
out_path=Path(out_path),
|
|
550
|
+
)
|
|
551
|
+
|
|
552
|
+
def read_csv(self, csvpath: Union[str, os.PathLike]) -> pd.DataFrame:
|
|
553
|
+
"""Read a csv file into a pandas DataFrame.
|
|
554
|
+
|
|
555
|
+
Parameters
|
|
556
|
+
----------
|
|
557
|
+
csvpath : Union[str, os.PathLike]
|
|
558
|
+
Path to the csv file
|
|
559
|
+
|
|
560
|
+
Returns
|
|
561
|
+
-------
|
|
562
|
+
pd.DataFrame
|
|
563
|
+
DataFrame containing the data from the csv file
|
|
564
|
+
"""
|
|
565
|
+
return _read_csv(csvpath)
|
|
566
|
+
|
|
567
|
+
def plot_forcing(
|
|
568
|
+
self, event: Event, forcing_type: ForcingType
|
|
569
|
+
) -> tuple[str, Optional[List[Exception]]]:
|
|
570
|
+
"""Plot forcing data for an event.
|
|
571
|
+
|
|
572
|
+
Parameters
|
|
573
|
+
----------
|
|
574
|
+
event : Event
|
|
575
|
+
The event object
|
|
576
|
+
forcing_type : ForcingType
|
|
577
|
+
The type of forcing data to plot
|
|
578
|
+
"""
|
|
579
|
+
return _plot_forcing(event, self.database.site, forcing_type)
|
|
580
|
+
|
|
581
|
+
def save_cyclone_track(self, event: Event, track: TropicalCyclone):
|
|
582
|
+
"""Save cyclone track data to the event folder.
|
|
583
|
+
|
|
584
|
+
Parameters
|
|
585
|
+
----------
|
|
586
|
+
event : Event
|
|
587
|
+
The event object
|
|
588
|
+
track : TropicalCyclone
|
|
589
|
+
The cyclone track data
|
|
590
|
+
"""
|
|
591
|
+
self.database.write_cyc(event, track)
|
|
592
|
+
|
|
593
|
+
def get_cyclone_track_by_index(self, index: int) -> TropicalCyclone:
|
|
594
|
+
return self.database.static.get_cyclone_track_database().get_track(index)
|
|
595
|
+
|
|
596
|
+
# Projections
|
|
597
|
+
def get_projections(self) -> dict[str, Any]:
|
|
598
|
+
"""
|
|
599
|
+
Get all projections from the database.
|
|
600
|
+
|
|
601
|
+
Returns
|
|
602
|
+
-------
|
|
603
|
+
dict[str, Any]
|
|
604
|
+
A dictionary containing all projections.
|
|
605
|
+
Includes keys: 'name', 'description', 'path', 'last_modification_date', 'objects'
|
|
606
|
+
Each value is a list of the corresponding attribute for each projection.
|
|
607
|
+
"""
|
|
608
|
+
return self.database.projections.list_objects()
|
|
609
|
+
|
|
610
|
+
def get_projection(self, name: str) -> Projection:
|
|
611
|
+
"""Get a projection from the database by name.
|
|
612
|
+
|
|
613
|
+
Parameters
|
|
614
|
+
----------
|
|
615
|
+
name : str
|
|
616
|
+
The name of the projection to retrieve.
|
|
617
|
+
|
|
618
|
+
Returns
|
|
619
|
+
-------
|
|
620
|
+
Projection
|
|
621
|
+
The projection object with the given name.
|
|
622
|
+
|
|
623
|
+
Raises
|
|
624
|
+
------
|
|
625
|
+
ValueError
|
|
626
|
+
If the projection with the given name does not exist.
|
|
627
|
+
"""
|
|
628
|
+
return self.database.projections.get(name)
|
|
629
|
+
|
|
630
|
+
def create_projection(self, attrs: dict[str, Any]) -> Projection:
|
|
631
|
+
"""Create a new projection object.
|
|
632
|
+
|
|
633
|
+
Parameters
|
|
634
|
+
----------
|
|
635
|
+
attrs : dict[str, Any]
|
|
636
|
+
The attributes of the projection object to create. Should adhere to the Projection schema.
|
|
637
|
+
|
|
638
|
+
Returns
|
|
639
|
+
-------
|
|
640
|
+
Projection
|
|
641
|
+
The projection object created from the attributes.
|
|
642
|
+
|
|
643
|
+
Raises
|
|
644
|
+
------
|
|
645
|
+
ValueError
|
|
646
|
+
If the attributes do not adhere to the Projection schema.
|
|
647
|
+
"""
|
|
648
|
+
return Projection(**attrs)
|
|
649
|
+
|
|
650
|
+
def save_projection(self, projection: Projection) -> None:
|
|
651
|
+
"""Save a projection object to the database.
|
|
652
|
+
|
|
653
|
+
Parameters
|
|
654
|
+
----------
|
|
655
|
+
projection : Projection
|
|
656
|
+
The projection object to save.
|
|
657
|
+
|
|
658
|
+
Raises
|
|
659
|
+
------
|
|
660
|
+
ValueError
|
|
661
|
+
If the projection object is not valid.
|
|
662
|
+
"""
|
|
663
|
+
self.database.projections.save(projection)
|
|
664
|
+
|
|
665
|
+
def edit_projection(self, projection: Projection) -> None:
|
|
666
|
+
"""Edit a projection object in the database.
|
|
667
|
+
|
|
668
|
+
Parameters
|
|
669
|
+
----------
|
|
670
|
+
projection : Projection
|
|
671
|
+
The projection object to edit.
|
|
672
|
+
|
|
673
|
+
Raises
|
|
674
|
+
------
|
|
675
|
+
ValueError
|
|
676
|
+
If the projection object does not exist.
|
|
677
|
+
"""
|
|
678
|
+
self.database.projections.edit(projection)
|
|
679
|
+
|
|
680
|
+
def delete_projection(self, name: str) -> None:
|
|
681
|
+
"""Delete a projection from the database.
|
|
682
|
+
|
|
683
|
+
Parameters
|
|
684
|
+
----------
|
|
685
|
+
name : str
|
|
686
|
+
The name of the projection to delete.
|
|
687
|
+
|
|
688
|
+
Raises
|
|
689
|
+
------
|
|
690
|
+
ValueError
|
|
691
|
+
If the projection does not exist.
|
|
692
|
+
If the projection is used in a scenario.
|
|
693
|
+
"""
|
|
694
|
+
self.database.projections.delete(name)
|
|
695
|
+
|
|
696
|
+
def copy_projection(
|
|
697
|
+
self, old_name: str, new_name: str, new_description: str
|
|
698
|
+
) -> None:
|
|
699
|
+
"""Copy a projection in the database.
|
|
700
|
+
|
|
701
|
+
Parameters
|
|
702
|
+
----------
|
|
703
|
+
old_name : str
|
|
704
|
+
The name of the projection to copy.
|
|
705
|
+
new_name : str
|
|
706
|
+
The name of the new projection.
|
|
707
|
+
new_description : str
|
|
708
|
+
The description of the new projection
|
|
709
|
+
"""
|
|
710
|
+
self.database.projections.copy(old_name, new_name, new_description)
|
|
711
|
+
|
|
712
|
+
def get_slr_scn_names(
|
|
713
|
+
self,
|
|
714
|
+
) -> list:
|
|
715
|
+
"""
|
|
716
|
+
Get all sea level rise scenario names from the database.
|
|
717
|
+
|
|
718
|
+
Returns
|
|
719
|
+
-------
|
|
720
|
+
list
|
|
721
|
+
List of scenario names
|
|
722
|
+
"""
|
|
723
|
+
return self.database.static.get_slr_scn_names()
|
|
724
|
+
|
|
725
|
+
def interp_slr(self, slr_scenario: str, year: float) -> float:
|
|
726
|
+
"""
|
|
727
|
+
Interpolate sea level rise for a given scenario and year.
|
|
728
|
+
|
|
729
|
+
Parameters
|
|
730
|
+
----------
|
|
731
|
+
slr_scenario : str
|
|
732
|
+
The name of the sea level rise scenario.
|
|
733
|
+
year : float
|
|
734
|
+
The year to interpolate sea level rise for.
|
|
735
|
+
|
|
736
|
+
Returns
|
|
737
|
+
-------
|
|
738
|
+
float
|
|
739
|
+
The interpolated sea level rise for the given scenario and year.
|
|
740
|
+
"""
|
|
741
|
+
return self.database.interp_slr(slr_scenario, year)
|
|
742
|
+
|
|
743
|
+
def plot_slr_scenarios(self) -> str:
|
|
744
|
+
"""
|
|
745
|
+
Plot sea level rise scenarios.
|
|
746
|
+
|
|
747
|
+
Returns
|
|
748
|
+
-------
|
|
749
|
+
str
|
|
750
|
+
The path to the html plot of the sea level rise scenarios.
|
|
751
|
+
"""
|
|
752
|
+
return self.database.plot_slr_scenarios()
|
|
753
|
+
|
|
754
|
+
# Scenarios
|
|
755
|
+
def get_scenarios(self) -> dict[str, Any]:
|
|
756
|
+
"""Get all scenarios from the database.
|
|
757
|
+
|
|
758
|
+
Returns
|
|
759
|
+
-------
|
|
760
|
+
dict[str, Any]
|
|
761
|
+
A dictionary containing all scenarios.
|
|
762
|
+
Includes keys: 'name', 'description', 'path', 'last_modification_date', 'objects'.
|
|
763
|
+
Each value is a list of the corresponding attribute for each scenario.
|
|
764
|
+
"""
|
|
765
|
+
return self.database.scenarios.list_objects()
|
|
766
|
+
|
|
767
|
+
def get_scenario(self, name: str) -> Scenario:
|
|
768
|
+
"""Get a scenario from the database by name.
|
|
769
|
+
|
|
770
|
+
Parameters
|
|
771
|
+
----------
|
|
772
|
+
name : str
|
|
773
|
+
The name of the scenario to retrieve.
|
|
774
|
+
|
|
775
|
+
Returns
|
|
776
|
+
-------
|
|
777
|
+
Scenario
|
|
778
|
+
The scenario object with the given name.
|
|
779
|
+
|
|
780
|
+
Raises
|
|
781
|
+
------
|
|
782
|
+
ValueError
|
|
783
|
+
If the scenario with the given name does not exist.
|
|
784
|
+
"""
|
|
785
|
+
return self.database.scenarios.get(name)
|
|
786
|
+
|
|
787
|
+
def create_scenario(self, attrs: dict[str, Any]) -> Scenario:
|
|
788
|
+
"""Create a new scenario object.
|
|
789
|
+
|
|
790
|
+
Parameters
|
|
791
|
+
----------
|
|
792
|
+
attrs : dict[str, Any]
|
|
793
|
+
The attributes of the scenario object to create. Should adhere to the Scenario schema.
|
|
794
|
+
|
|
795
|
+
Returns
|
|
796
|
+
-------
|
|
797
|
+
Scenario
|
|
798
|
+
The scenario object created from the attributes.
|
|
799
|
+
|
|
800
|
+
Raises
|
|
801
|
+
------
|
|
802
|
+
ValueError
|
|
803
|
+
If the attributes do not adhere to the Scenario schema.
|
|
804
|
+
"""
|
|
805
|
+
return Scenario(**attrs)
|
|
806
|
+
|
|
807
|
+
def save_scenario(self, scenario: Scenario) -> tuple[bool, str]:
|
|
808
|
+
"""Save the scenario to the database.
|
|
809
|
+
|
|
810
|
+
Parameters
|
|
811
|
+
----------
|
|
812
|
+
scenario : Scenario
|
|
813
|
+
The scenario to save.
|
|
814
|
+
|
|
815
|
+
Returns
|
|
816
|
+
-------
|
|
817
|
+
bool
|
|
818
|
+
Whether the scenario was saved successfully.
|
|
819
|
+
str
|
|
820
|
+
The error message if the scenario was not saved successfully.
|
|
821
|
+
"""
|
|
822
|
+
try:
|
|
823
|
+
self.database.scenarios.save(scenario)
|
|
824
|
+
return True, ""
|
|
825
|
+
except Exception as e:
|
|
826
|
+
return False, str(e)
|
|
827
|
+
|
|
828
|
+
def edit_scenario(self, scenario: Scenario) -> None:
|
|
829
|
+
"""Edit a scenario object in the database.
|
|
830
|
+
|
|
831
|
+
Parameters
|
|
832
|
+
----------
|
|
833
|
+
scenario : Scenario
|
|
834
|
+
The scenario object to edit.
|
|
835
|
+
|
|
836
|
+
Raises
|
|
837
|
+
------
|
|
838
|
+
ValueError
|
|
839
|
+
If the scenario object does not exist.
|
|
840
|
+
"""
|
|
841
|
+
self.database.scenarios.edit(scenario)
|
|
842
|
+
|
|
843
|
+
def delete_scenario(self, name: str) -> None:
|
|
844
|
+
"""Delete a scenario from the database.
|
|
845
|
+
|
|
846
|
+
Parameters
|
|
847
|
+
----------
|
|
848
|
+
name : str
|
|
849
|
+
The name of the scenario to delete.
|
|
850
|
+
|
|
851
|
+
Raises
|
|
852
|
+
------
|
|
853
|
+
ValueError
|
|
854
|
+
If the scenario does not exist.
|
|
855
|
+
"""
|
|
856
|
+
self.database.scenarios.delete(name)
|
|
857
|
+
|
|
858
|
+
def run_scenario(self, name: Union[str, list[str]]) -> None:
|
|
859
|
+
"""Run a scenario.
|
|
860
|
+
|
|
861
|
+
Parameters
|
|
862
|
+
----------
|
|
863
|
+
name : Union[str, list[str]]
|
|
864
|
+
The name(s) of the scenario to run.
|
|
865
|
+
|
|
866
|
+
Raises
|
|
867
|
+
------
|
|
868
|
+
ValueError
|
|
869
|
+
If the scenario does not exist.
|
|
870
|
+
"""
|
|
871
|
+
self.database.run_scenario(name)
|
|
872
|
+
|
|
873
|
+
# Outputs
|
|
874
|
+
def get_outputs(
|
|
875
|
+
self,
|
|
876
|
+
) -> dict[str, Any]:
|
|
877
|
+
"""Get all completed scenarios from the database.
|
|
878
|
+
|
|
879
|
+
Returns
|
|
880
|
+
-------
|
|
881
|
+
dict[str, Any]
|
|
882
|
+
A dictionary containing all scenarios.
|
|
883
|
+
Includes keys: 'name', 'description', 'path', 'last_modification_date', 'objects'
|
|
884
|
+
Each value is a list of the corresponding attribute for each output.
|
|
885
|
+
"""
|
|
886
|
+
return self.database.get_outputs()
|
|
887
|
+
|
|
888
|
+
def get_topobathy_path(self) -> str:
|
|
889
|
+
"""
|
|
890
|
+
Return the path of the topobathy tiles in order to create flood maps with water level maps.
|
|
891
|
+
|
|
892
|
+
Returns
|
|
893
|
+
-------
|
|
894
|
+
str
|
|
895
|
+
The path to the topobathy file.
|
|
896
|
+
|
|
897
|
+
"""
|
|
898
|
+
return self.database.get_topobathy_path()
|
|
899
|
+
|
|
900
|
+
def get_index_path(self) -> str:
|
|
901
|
+
"""
|
|
902
|
+
Return the path of the index tiles which are used to connect each water level cell with the topobathy tiles.
|
|
903
|
+
|
|
904
|
+
Returns
|
|
905
|
+
-------
|
|
906
|
+
str
|
|
907
|
+
The path to the index file.
|
|
908
|
+
"""
|
|
909
|
+
return self.database.get_index_path()
|
|
910
|
+
|
|
911
|
+
def get_depth_conversion(self) -> float:
|
|
912
|
+
"""
|
|
913
|
+
Return the flood depth conversion that is need in the gui to plot the flood map.
|
|
914
|
+
|
|
915
|
+
Returns
|
|
916
|
+
-------
|
|
917
|
+
float
|
|
918
|
+
The flood depth conversion.
|
|
919
|
+
"""
|
|
920
|
+
return self.database.get_depth_conversion()
|
|
921
|
+
|
|
922
|
+
def get_max_water_level(self, name: str, rp: int = None) -> np.ndarray:
|
|
923
|
+
"""
|
|
924
|
+
Return the maximum water level for the given scenario.
|
|
925
|
+
|
|
926
|
+
Parameters
|
|
927
|
+
----------
|
|
928
|
+
name : str
|
|
929
|
+
The name of the scenario.
|
|
930
|
+
rp : int, optional
|
|
931
|
+
The return period of the water level, by default None
|
|
932
|
+
|
|
933
|
+
Returns
|
|
934
|
+
-------
|
|
935
|
+
np.ndarray
|
|
936
|
+
2D gridded map with the maximum waterlevels for each cell.
|
|
937
|
+
"""
|
|
938
|
+
return self.database.get_max_water_level(name, rp)
|
|
939
|
+
|
|
940
|
+
def get_building_footprints(self, name: str) -> gpd.GeoDataFrame:
|
|
941
|
+
"""
|
|
942
|
+
Return a geodataframe of the impacts at the footprint level.
|
|
943
|
+
|
|
944
|
+
Parameters
|
|
945
|
+
----------
|
|
946
|
+
name : str
|
|
947
|
+
The name of the scenario.
|
|
948
|
+
|
|
949
|
+
Returns
|
|
950
|
+
-------
|
|
951
|
+
gpd.GeoDataFrame
|
|
952
|
+
The impact footprints for the scenario.
|
|
953
|
+
"""
|
|
954
|
+
return self.database.get_building_footprints(name)
|
|
955
|
+
|
|
956
|
+
def get_aggregation(self, name: str) -> dict[str, gpd.GeoDataFrame]:
|
|
957
|
+
"""
|
|
958
|
+
Return a dictionary with the aggregated impacts as geodataframes.
|
|
959
|
+
|
|
960
|
+
Parameters
|
|
961
|
+
----------
|
|
962
|
+
name : str
|
|
963
|
+
The name of the scenario.
|
|
964
|
+
|
|
965
|
+
Returns
|
|
966
|
+
-------
|
|
967
|
+
dict[str, gpd.GeoDataFrame]
|
|
968
|
+
The aggregated impacts for the scenario.
|
|
969
|
+
"""
|
|
970
|
+
return self.database.get_aggregation(name)
|
|
971
|
+
|
|
972
|
+
def get_roads(self, name: str) -> gpd.GeoDataFrame:
|
|
973
|
+
"""
|
|
974
|
+
Return a geodataframe of the impacts at roads.
|
|
975
|
+
|
|
976
|
+
Parameters
|
|
977
|
+
----------
|
|
978
|
+
name : str
|
|
979
|
+
The name of the scenario.
|
|
980
|
+
|
|
981
|
+
Returns
|
|
982
|
+
-------
|
|
983
|
+
gpd.GeoDataFrame
|
|
984
|
+
The impacted roads for the scenario.
|
|
985
|
+
"""
|
|
986
|
+
return self.database.get_roads(name)
|
|
987
|
+
|
|
988
|
+
def get_obs_point_timeseries(self, name: str) -> gpd.GeoDataFrame:
|
|
989
|
+
"""Return the HTML strings of the water level timeseries for the given scenario.
|
|
990
|
+
|
|
991
|
+
Parameters
|
|
992
|
+
----------
|
|
993
|
+
name : str
|
|
994
|
+
The name of the scenario.
|
|
995
|
+
|
|
996
|
+
Returns
|
|
997
|
+
-------
|
|
998
|
+
str
|
|
999
|
+
The HTML strings of the water level timeseries
|
|
1000
|
+
"""
|
|
1001
|
+
# Get the impacts objects from the scenario
|
|
1002
|
+
scenario = self.database.scenarios.get(name)
|
|
1003
|
+
hazard = Impacts(scenario).hazard
|
|
1004
|
+
|
|
1005
|
+
# Check if the scenario has run
|
|
1006
|
+
if not hazard.has_run:
|
|
1007
|
+
raise ValueError(
|
|
1008
|
+
f"Scenario {name} has not been run. Please run the scenario first."
|
|
1009
|
+
)
|
|
1010
|
+
|
|
1011
|
+
output_path = self.database.scenarios.output_path.joinpath(hazard.name)
|
|
1012
|
+
gdf = self.database.static.get_obs_points()
|
|
1013
|
+
gdf["html"] = [
|
|
1014
|
+
str(output_path.joinpath("Flooding", f"{station}_timeseries.html"))
|
|
1015
|
+
for station in gdf.name
|
|
1016
|
+
]
|
|
1017
|
+
|
|
1018
|
+
return gdf
|
|
1019
|
+
|
|
1020
|
+
def get_infographic(self, name: str) -> str:
|
|
1021
|
+
"""Return the HTML string of the infographic for the given scenario.
|
|
1022
|
+
|
|
1023
|
+
Parameters
|
|
1024
|
+
----------
|
|
1025
|
+
name : str
|
|
1026
|
+
The name of the scenario.
|
|
1027
|
+
|
|
1028
|
+
Returns
|
|
1029
|
+
-------
|
|
1030
|
+
str
|
|
1031
|
+
The HTML string of the infographic.
|
|
1032
|
+
"""
|
|
1033
|
+
# Get the impacts objects from the scenario
|
|
1034
|
+
database = self.database
|
|
1035
|
+
scn = database.scenarios.get(name)
|
|
1036
|
+
impact = Impacts(scenario=scn)
|
|
1037
|
+
event_mode = self.database.events.get(scn.event).mode
|
|
1038
|
+
|
|
1039
|
+
# Check if the scenario has run
|
|
1040
|
+
if not impact.has_run_check():
|
|
1041
|
+
raise ValueError(
|
|
1042
|
+
f"Scenario {name} has not been run. Please run the scenario first."
|
|
1043
|
+
)
|
|
1044
|
+
|
|
1045
|
+
config_path = database.static_path.joinpath("templates", "infographics")
|
|
1046
|
+
output_path = database.scenarios.output_path.joinpath(impact.name)
|
|
1047
|
+
metrics_outputs_path = output_path.joinpath(f"Infometrics_{impact.name}.csv")
|
|
1048
|
+
|
|
1049
|
+
infographic_path = InforgraphicFactory.create_infographic_file_writer(
|
|
1050
|
+
infographic_mode=event_mode,
|
|
1051
|
+
scenario_name=impact.name,
|
|
1052
|
+
metrics_full_path=metrics_outputs_path,
|
|
1053
|
+
config_base_path=config_path,
|
|
1054
|
+
output_base_path=output_path,
|
|
1055
|
+
).get_infographics_html()
|
|
1056
|
+
|
|
1057
|
+
return infographic_path
|
|
1058
|
+
|
|
1059
|
+
def get_infometrics(self, name: str) -> pd.DataFrame:
|
|
1060
|
+
"""Return the metrics for the given scenario.
|
|
1061
|
+
|
|
1062
|
+
Parameters
|
|
1063
|
+
----------
|
|
1064
|
+
name : str
|
|
1065
|
+
The name of the scenario.
|
|
1066
|
+
|
|
1067
|
+
Returns
|
|
1068
|
+
-------
|
|
1069
|
+
pd.DataFrame
|
|
1070
|
+
|
|
1071
|
+
Raises
|
|
1072
|
+
------
|
|
1073
|
+
FileNotFoundError
|
|
1074
|
+
If the metrics file does not exist.
|
|
1075
|
+
"""
|
|
1076
|
+
# Create the infographic path
|
|
1077
|
+
metrics_path = self.database.scenarios.output_path.joinpath(
|
|
1078
|
+
name,
|
|
1079
|
+
f"Infometrics_{name}.csv",
|
|
1080
|
+
)
|
|
1081
|
+
|
|
1082
|
+
# Check if the file exists
|
|
1083
|
+
if not metrics_path.exists():
|
|
1084
|
+
raise FileNotFoundError(
|
|
1085
|
+
f"The metrics file for scenario {name}({str(metrics_path)}) does not exist."
|
|
1086
|
+
)
|
|
1087
|
+
|
|
1088
|
+
# Read the metrics file
|
|
1089
|
+
return MetricsFileReader(str(metrics_path)).read_metrics_from_file(
|
|
1090
|
+
include_long_names=True,
|
|
1091
|
+
include_description=True,
|
|
1092
|
+
include_metrics_table_selection=True,
|
|
1093
|
+
)
|
|
1094
|
+
|
|
1095
|
+
# Static
|
|
1096
|
+
@staticmethod
|
|
1097
|
+
def read_database(
|
|
1098
|
+
database_path: Union[str, os.PathLike], site_name: str
|
|
1099
|
+
) -> Database:
|
|
1100
|
+
"""Given a path and a site name returns a IDatabase object.
|
|
1101
|
+
|
|
1102
|
+
Parameters
|
|
1103
|
+
----------
|
|
1104
|
+
database_path : Union[str, os.PathLike]
|
|
1105
|
+
path to database
|
|
1106
|
+
site_name : str
|
|
1107
|
+
name of the site
|
|
1108
|
+
|
|
1109
|
+
Returns
|
|
1110
|
+
-------
|
|
1111
|
+
IDatabase
|
|
1112
|
+
"""
|
|
1113
|
+
return Database(database_path, site_name)
|
|
1114
|
+
|
|
1115
|
+
def get_aggregation_areas(
|
|
1116
|
+
self,
|
|
1117
|
+
) -> dict[str, gpd.GeoDataFrame]:
|
|
1118
|
+
"""Get a list of the aggregation areas that are provided in the site configuration.
|
|
1119
|
+
|
|
1120
|
+
These are expected to much the ones in the FIAT model.
|
|
1121
|
+
|
|
1122
|
+
Returns
|
|
1123
|
+
-------
|
|
1124
|
+
dict[str, GeoDataFrame]
|
|
1125
|
+
list of geodataframes with the polygons defining the aggregation areas
|
|
1126
|
+
"""
|
|
1127
|
+
return self.database.static.get_aggregation_areas()
|
|
1128
|
+
|
|
1129
|
+
def get_obs_points(
|
|
1130
|
+
self,
|
|
1131
|
+
) -> gpd.GeoDataFrame:
|
|
1132
|
+
"""Get the observation points specified in the site.toml.
|
|
1133
|
+
|
|
1134
|
+
These are also added to the flood hazard model. They are used as marker locations to plot water level time series in the output tab.
|
|
1135
|
+
|
|
1136
|
+
Returns
|
|
1137
|
+
-------
|
|
1138
|
+
gpd.GeoDataFrame
|
|
1139
|
+
gpd.GeoDataFrame with observation points from the site.toml.
|
|
1140
|
+
"""
|
|
1141
|
+
return self.database.static.get_obs_points()
|
|
1142
|
+
|
|
1143
|
+
def get_model_boundary(
|
|
1144
|
+
self,
|
|
1145
|
+
) -> gpd.GeoDataFrame:
|
|
1146
|
+
"""Get the model boundary that is used in SFINCS.
|
|
1147
|
+
|
|
1148
|
+
Returns
|
|
1149
|
+
-------
|
|
1150
|
+
GeoDataFrame
|
|
1151
|
+
GeoDataFrame with the model boundary
|
|
1152
|
+
"""
|
|
1153
|
+
return self.database.static.get_model_boundary()
|
|
1154
|
+
|
|
1155
|
+
def get_model_grid(
|
|
1156
|
+
self,
|
|
1157
|
+
) -> QuadtreeGrid:
|
|
1158
|
+
"""Get the model grid that is used in SFINCS.
|
|
1159
|
+
|
|
1160
|
+
Returns
|
|
1161
|
+
-------
|
|
1162
|
+
QuadtreeGrid
|
|
1163
|
+
QuadtreeGrid with the model grid
|
|
1164
|
+
"""
|
|
1165
|
+
return self.database.static.get_model_grid()
|
|
1166
|
+
|
|
1167
|
+
def get_svi_map(
|
|
1168
|
+
self,
|
|
1169
|
+
) -> Union[gpd.GeoDataFrame, None]:
|
|
1170
|
+
"""Get the SVI map that are used in Fiat.
|
|
1171
|
+
|
|
1172
|
+
Returns
|
|
1173
|
+
-------
|
|
1174
|
+
gpd.GeoDataFrame
|
|
1175
|
+
gpd.GeoDataFrames with the SVI map, None if not available
|
|
1176
|
+
"""
|
|
1177
|
+
if self.database.site.fiat.config.svi:
|
|
1178
|
+
return self.database.static.get_static_map(
|
|
1179
|
+
self.database.site.fiat.config.svi.geom
|
|
1180
|
+
)
|
|
1181
|
+
else:
|
|
1182
|
+
return None
|
|
1183
|
+
|
|
1184
|
+
def get_static_map(self, path: Union[str, Path]) -> Union[gpd.GeoDataFrame, None]:
|
|
1185
|
+
"""Get a static map from the database.
|
|
1186
|
+
|
|
1187
|
+
Parameters
|
|
1188
|
+
----------
|
|
1189
|
+
path : Union[str, Path]
|
|
1190
|
+
path to the static map
|
|
1191
|
+
|
|
1192
|
+
Returns
|
|
1193
|
+
-------
|
|
1194
|
+
gpd.gpd.GeoDataFrame
|
|
1195
|
+
gpd.GeoDataFrame with the static map
|
|
1196
|
+
"""
|
|
1197
|
+
try:
|
|
1198
|
+
return self.database.static.get_static_map(path)
|
|
1199
|
+
except Exception:
|
|
1200
|
+
return None
|
|
1201
|
+
|
|
1202
|
+
def get_buildings(self) -> gpd.GeoDataFrame:
|
|
1203
|
+
"""Get the buildings exposure that are used in Fiat.
|
|
1204
|
+
|
|
1205
|
+
Returns
|
|
1206
|
+
-------
|
|
1207
|
+
gpd.GeoDataFrame
|
|
1208
|
+
gpd.GeoDataFrames with the buildings from FIAT exposure
|
|
1209
|
+
"""
|
|
1210
|
+
return self.database.static.get_buildings()
|
|
1211
|
+
|
|
1212
|
+
def get_property_types(self) -> list:
|
|
1213
|
+
"""Get the property types that are used in the exposure.
|
|
1214
|
+
|
|
1215
|
+
Returns
|
|
1216
|
+
-------
|
|
1217
|
+
list
|
|
1218
|
+
list of property types
|
|
1219
|
+
"""
|
|
1220
|
+
return self.database.static.get_property_types()
|
|
1221
|
+
|
|
1222
|
+
def get_hazard_measure_types(self):
|
|
1223
|
+
"""Get list of all implemented hazard measure types."""
|
|
1224
|
+
raise NotImplementedError
|
|
1225
|
+
|
|
1226
|
+
def get_impact_measure_types(self):
|
|
1227
|
+
"""Get list of all implemented impact measure types."""
|
|
1228
|
+
raise NotImplementedError
|
|
1229
|
+
|
|
1230
|
+
def get_event_templates(self):
|
|
1231
|
+
"""Get list of all implemented event templates."""
|
|
1232
|
+
raise NotImplementedError
|
|
1233
|
+
|
|
1234
|
+
# Benefits
|
|
1235
|
+
def get_benefits(self) -> dict[str, Any]:
|
|
1236
|
+
"""Get all benefits from the database.
|
|
1237
|
+
|
|
1238
|
+
Returns
|
|
1239
|
+
-------
|
|
1240
|
+
dict[str, Any]
|
|
1241
|
+
A dictionary containing all benefits.
|
|
1242
|
+
Includes keys: 'name', 'description', 'path', 'last_modification_date', 'objects'
|
|
1243
|
+
Each value is a list of the corresponding attribute for each benefit.
|
|
1244
|
+
"""
|
|
1245
|
+
# sorting and filtering either with PyQt table or in the API
|
|
1246
|
+
return self.database.benefits.list_objects()
|
|
1247
|
+
|
|
1248
|
+
def get_benefit(self, name: str) -> Benefit:
|
|
1249
|
+
"""Get a benefit from the database by name.
|
|
1250
|
+
|
|
1251
|
+
Parameters
|
|
1252
|
+
----------
|
|
1253
|
+
name : str
|
|
1254
|
+
The name of the benefit to retrieve.
|
|
1255
|
+
|
|
1256
|
+
Returns
|
|
1257
|
+
-------
|
|
1258
|
+
Benefit
|
|
1259
|
+
The benefit object with the given name. See [Benefit](/api_ref/) for details.
|
|
1260
|
+
|
|
1261
|
+
Raises
|
|
1262
|
+
------
|
|
1263
|
+
ValueError
|
|
1264
|
+
If the benefit with the given name does not exist.
|
|
1265
|
+
"""
|
|
1266
|
+
return self.database.benefits.get(name)
|
|
1267
|
+
|
|
1268
|
+
def create_benefit(self, attrs: dict[str, Any]) -> Benefit:
|
|
1269
|
+
"""Create a new benefit object.
|
|
1270
|
+
|
|
1271
|
+
Parameters
|
|
1272
|
+
----------
|
|
1273
|
+
attrs : dict[str, Any]
|
|
1274
|
+
The attributes of the benefit object to create. Should adhere to the Benefit schema.
|
|
1275
|
+
"""
|
|
1276
|
+
return Benefit(**attrs)
|
|
1277
|
+
|
|
1278
|
+
def save_benefit(self, benefit: Benefit) -> None:
|
|
1279
|
+
"""Save a benefit object to the database.
|
|
1280
|
+
|
|
1281
|
+
Parameters
|
|
1282
|
+
----------
|
|
1283
|
+
benefit : Benefit
|
|
1284
|
+
The benefit object to save.
|
|
1285
|
+
|
|
1286
|
+
Raises
|
|
1287
|
+
------
|
|
1288
|
+
ValueError
|
|
1289
|
+
If the benefit object is not valid.
|
|
1290
|
+
"""
|
|
1291
|
+
self.database.benefits.save(benefit)
|
|
1292
|
+
|
|
1293
|
+
def edit_benefit(self, benefit: Benefit) -> None:
|
|
1294
|
+
"""Edit a benefit object in the database.
|
|
1295
|
+
|
|
1296
|
+
Parameters
|
|
1297
|
+
----------
|
|
1298
|
+
benefit : Benefit
|
|
1299
|
+
The benefit object to edit.
|
|
1300
|
+
|
|
1301
|
+
Raises
|
|
1302
|
+
------
|
|
1303
|
+
ValueError
|
|
1304
|
+
If the benefit object does not exist.
|
|
1305
|
+
"""
|
|
1306
|
+
self.database.benefits.edit(benefit)
|
|
1307
|
+
|
|
1308
|
+
def delete_benefit(self, name: str) -> None:
|
|
1309
|
+
"""Delete a benefit object from the database.
|
|
1310
|
+
|
|
1311
|
+
Parameters
|
|
1312
|
+
----------
|
|
1313
|
+
name : str
|
|
1314
|
+
The name of the benefit object to delete.
|
|
1315
|
+
|
|
1316
|
+
Raises
|
|
1317
|
+
------
|
|
1318
|
+
ValueError
|
|
1319
|
+
If the benefit object does not exist.
|
|
1320
|
+
"""
|
|
1321
|
+
self.database.benefits.delete(name)
|
|
1322
|
+
|
|
1323
|
+
def check_benefit_scenarios(self, benefit: Benefit) -> pd.DataFrame:
|
|
1324
|
+
"""Return a dataframe with the scenarios needed for this benefit assessment run.
|
|
1325
|
+
|
|
1326
|
+
Parameters
|
|
1327
|
+
----------
|
|
1328
|
+
benefit : Benefit
|
|
1329
|
+
The benefit object to check.
|
|
1330
|
+
|
|
1331
|
+
Returns
|
|
1332
|
+
-------
|
|
1333
|
+
pd.DataFrame
|
|
1334
|
+
A dataframe with the scenarios needed for this benefit assessment run.
|
|
1335
|
+
"""
|
|
1336
|
+
return self.database.check_benefit_scenarios(benefit)
|
|
1337
|
+
|
|
1338
|
+
def create_benefit_scenarios(self, benefit: Benefit):
|
|
1339
|
+
"""Create the benefit scenarios.
|
|
1340
|
+
|
|
1341
|
+
Parameters
|
|
1342
|
+
----------
|
|
1343
|
+
benefit : Benefit
|
|
1344
|
+
The benefit object to create scenarios for.
|
|
1345
|
+
"""
|
|
1346
|
+
self.database.create_benefit_scenarios(benefit)
|
|
1347
|
+
|
|
1348
|
+
def run_benefit(self, name: Union[str, list[str]]) -> None:
|
|
1349
|
+
"""Run the benefit assessment.
|
|
1350
|
+
|
|
1351
|
+
Parameters
|
|
1352
|
+
----------
|
|
1353
|
+
name : Union[str, list[str]]
|
|
1354
|
+
The name of the benefit object to run.
|
|
1355
|
+
"""
|
|
1356
|
+
self.database.run_benefit(name)
|
|
1357
|
+
|
|
1358
|
+
def get_aggregation_benefits(self, name: str) -> dict[str, gpd.GeoDataFrame]:
|
|
1359
|
+
"""Get the aggregation benefits for a benefit assessment.
|
|
1360
|
+
|
|
1361
|
+
Parameters
|
|
1362
|
+
----------
|
|
1363
|
+
name : str
|
|
1364
|
+
The name of the benefit assessment.
|
|
1365
|
+
|
|
1366
|
+
Returns
|
|
1367
|
+
-------
|
|
1368
|
+
gpd.GeoDataFrame
|
|
1369
|
+
The aggregation benefits for the benefit assessment.
|
|
1370
|
+
"""
|
|
1371
|
+
return self.database.get_aggregation_benefits(name)
|