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