flood-adapt 1.0.0rc1__py3-none-any.whl → 1.0.2__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 +1 -1
- flood_adapt/adapter/__init__.py +0 -2
- flood_adapt/adapter/fiat_adapter.py +51 -51
- flood_adapt/adapter/interface/impact_adapter.py +1 -1
- flood_adapt/adapter/sfincs_adapter.py +69 -71
- flood_adapt/adapter/sfincs_offshore.py +5 -6
- flood_adapt/database_builder/database_builder.py +37 -5
- flood_adapt/dbs_classes/database.py +85 -21
- flood_adapt/dbs_classes/dbs_static.py +33 -9
- flood_adapt/dbs_classes/interface/static.py +8 -0
- flood_adapt/flood_adapt.py +28 -24
- flood_adapt/objects/forcing/forcing.py +1 -4
- flood_adapt/objects/forcing/tide_gauge.py +6 -7
- flood_adapt/objects/forcing/timeseries.py +0 -1
- flood_adapt/objects/output/floodmap.py +13 -0
- flood_adapt/workflows/scenario_runner.py +57 -31
- {flood_adapt-1.0.0rc1.dist-info → flood_adapt-1.0.2.dist-info}/LICENSE +69 -46
- {flood_adapt-1.0.0rc1.dist-info → flood_adapt-1.0.2.dist-info}/METADATA +70 -47
- {flood_adapt-1.0.0rc1.dist-info → flood_adapt-1.0.2.dist-info}/RECORD +21 -22
- flood_adapt/workflows/floodmap.py +0 -85
- flood_adapt/workflows/impacts_integrator.py +0 -85
- {flood_adapt-1.0.0rc1.dist-info → flood_adapt-1.0.2.dist-info}/WHEEL +0 -0
- {flood_adapt-1.0.0rc1.dist-info → flood_adapt-1.0.2.dist-info}/top_level.txt +0 -0
flood_adapt/__init__.py
CHANGED
flood_adapt/adapter/__init__.py
CHANGED
|
@@ -40,8 +40,6 @@ from flood_adapt.objects.measures.measures import (
|
|
|
40
40
|
)
|
|
41
41
|
from flood_adapt.objects.projections.projections import Projection
|
|
42
42
|
from flood_adapt.objects.scenarios.scenarios import Scenario
|
|
43
|
-
from flood_adapt.workflows.floodmap import FloodMap
|
|
44
|
-
from flood_adapt.workflows.impacts_integrator import Impacts
|
|
45
43
|
|
|
46
44
|
# Define naming structure for saved files
|
|
47
45
|
_IMPACT_COLUMNS = FiatColumns(
|
|
@@ -72,6 +70,8 @@ _FIAT_COLUMNS: FiatColumns = get_fiat_columns(
|
|
|
72
70
|
fiat_version="0.2.1"
|
|
73
71
|
) # columns of FIAT # TODO add version from config
|
|
74
72
|
|
|
73
|
+
logger = FloodAdaptLogging.getLogger("FiatAdapter")
|
|
74
|
+
|
|
75
75
|
|
|
76
76
|
class FiatAdapter(IImpactAdapter):
|
|
77
77
|
"""
|
|
@@ -102,7 +102,6 @@ class FiatAdapter(IImpactAdapter):
|
|
|
102
102
|
) -> None:
|
|
103
103
|
# TODO should exe_path and delete_crashed_runs be part of the config?
|
|
104
104
|
# Load FIAT template
|
|
105
|
-
self.logger = FloodAdaptLogging.getLogger("FiatAdapter")
|
|
106
105
|
self.config = config
|
|
107
106
|
self.config_base_path = config_base_path
|
|
108
107
|
self.exe_path = exe_path
|
|
@@ -154,16 +153,16 @@ class FiatAdapter(IImpactAdapter):
|
|
|
154
153
|
|
|
155
154
|
def close_files(self):
|
|
156
155
|
"""Close all open files and clean up file handles."""
|
|
157
|
-
loggers = [
|
|
156
|
+
loggers = [logger]
|
|
158
157
|
if self._model is not None:
|
|
159
158
|
loggers.append(self._model.logger)
|
|
160
159
|
|
|
161
|
-
for
|
|
162
|
-
if hasattr(
|
|
163
|
-
for handler in
|
|
160
|
+
for _logger in loggers:
|
|
161
|
+
if hasattr(_logger, "handlers"):
|
|
162
|
+
for handler in _logger.handlers:
|
|
164
163
|
if isinstance(handler, logging.FileHandler):
|
|
165
164
|
handler.close()
|
|
166
|
-
|
|
165
|
+
_logger.removeHandler(handler)
|
|
167
166
|
|
|
168
167
|
def __enter__(self) -> "FiatAdapter":
|
|
169
168
|
return self
|
|
@@ -187,8 +186,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
187
186
|
bool
|
|
188
187
|
True if the FIAT results file exists, False otherwise.
|
|
189
188
|
"""
|
|
190
|
-
impacts_path =
|
|
191
|
-
|
|
189
|
+
impacts_path = self.database.get_impacts_path(scenario_name=scenario.name)
|
|
192
190
|
fiat_results_path = impacts_path.joinpath(
|
|
193
191
|
f"Impacts_detailed_{scenario.name}.csv"
|
|
194
192
|
)
|
|
@@ -206,7 +204,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
206
204
|
"""
|
|
207
205
|
self.close_files()
|
|
208
206
|
if self.model_root.exists():
|
|
209
|
-
|
|
207
|
+
logger.info(f"Deleting {self.model_root}")
|
|
210
208
|
shutil.rmtree(self.model_root)
|
|
211
209
|
|
|
212
210
|
def fiat_completed(self) -> bool:
|
|
@@ -226,7 +224,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
226
224
|
with open(log_file, "r", encoding="cp1252") as f:
|
|
227
225
|
return "Geom calculation are done!" in f.read()
|
|
228
226
|
except Exception as e:
|
|
229
|
-
|
|
227
|
+
logger.error(f"Error while checking if FIAT has run: {e}")
|
|
230
228
|
return False
|
|
231
229
|
|
|
232
230
|
def preprocess(self, scenario: Scenario) -> None:
|
|
@@ -241,7 +239,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
241
239
|
-------
|
|
242
240
|
None
|
|
243
241
|
"""
|
|
244
|
-
|
|
242
|
+
logger.info("Pre-processing Delft-FIAT model")
|
|
245
243
|
# Projection
|
|
246
244
|
projection = self.database.projections.get(scenario.projection)
|
|
247
245
|
self.add_projection(projection)
|
|
@@ -252,19 +250,21 @@ class FiatAdapter(IImpactAdapter):
|
|
|
252
250
|
self.add_measure(measure)
|
|
253
251
|
|
|
254
252
|
# Hazard
|
|
255
|
-
floodmap =
|
|
253
|
+
floodmap = self.database.get_floodmap(scenario.name)
|
|
256
254
|
var = "risk_maps" if floodmap.mode == Mode.risk else "zsmax"
|
|
257
255
|
is_risk = floodmap.mode == Mode.risk
|
|
258
256
|
self.set_hazard(
|
|
259
|
-
map_fn=floodmap.
|
|
260
|
-
map_type=floodmap.
|
|
257
|
+
map_fn=floodmap.paths,
|
|
258
|
+
map_type=floodmap.map_type,
|
|
261
259
|
var=var,
|
|
262
260
|
is_risk=is_risk,
|
|
263
261
|
units=us.UnitTypesLength.meters,
|
|
264
262
|
)
|
|
265
263
|
|
|
266
264
|
# Save any changes made to disk as well
|
|
267
|
-
output_path =
|
|
265
|
+
output_path = (
|
|
266
|
+
self.database.get_impacts_path(scenario_name=scenario.name) / "fiat_model"
|
|
267
|
+
)
|
|
268
268
|
self.write(path_out=output_path)
|
|
269
269
|
|
|
270
270
|
def run(self, scenario) -> None:
|
|
@@ -278,7 +278,9 @@ class FiatAdapter(IImpactAdapter):
|
|
|
278
278
|
-------
|
|
279
279
|
None
|
|
280
280
|
"""
|
|
281
|
-
sim_path =
|
|
281
|
+
sim_path = (
|
|
282
|
+
self.database.get_impacts_path(scenario_name=scenario.name) / "fiat_model"
|
|
283
|
+
)
|
|
282
284
|
|
|
283
285
|
self.preprocess(scenario)
|
|
284
286
|
self.execute(sim_path)
|
|
@@ -333,14 +335,14 @@ class FiatAdapter(IImpactAdapter):
|
|
|
333
335
|
with FloodAdaptLogging.to_file(file_path=fiat_log):
|
|
334
336
|
FiatAdapter._ensure_correct_hash_spacing_in_csv(path)
|
|
335
337
|
|
|
336
|
-
|
|
338
|
+
logger.info(f"Running FIAT in {path}")
|
|
337
339
|
process = subprocess.run(
|
|
338
340
|
args=[Path(exe_path).resolve().as_posix(), "run", "settings.toml"],
|
|
339
341
|
stdout=subprocess.PIPE,
|
|
340
342
|
stderr=subprocess.PIPE,
|
|
341
343
|
text=True,
|
|
342
344
|
)
|
|
343
|
-
|
|
345
|
+
logger.debug(process.stdout)
|
|
344
346
|
|
|
345
347
|
if process.returncode != 0:
|
|
346
348
|
if delete_crashed_runs:
|
|
@@ -356,7 +358,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
356
358
|
if strict:
|
|
357
359
|
raise RuntimeError(f"FIAT model failed to run in {path}.")
|
|
358
360
|
else:
|
|
359
|
-
|
|
361
|
+
logger.error(f"FIAT model failed to run in {path}.")
|
|
360
362
|
|
|
361
363
|
if process.returncode == 0:
|
|
362
364
|
self.read_outputs()
|
|
@@ -454,16 +456,16 @@ class FiatAdapter(IImpactAdapter):
|
|
|
454
456
|
if not self.fiat_completed():
|
|
455
457
|
raise RuntimeError("Delft-FIAT did not run successfully!")
|
|
456
458
|
|
|
457
|
-
|
|
459
|
+
logger.info("Post-processing Delft-FIAT results")
|
|
458
460
|
|
|
459
461
|
if not self.outputs:
|
|
460
462
|
self.read_outputs()
|
|
461
463
|
mode = self.database.events.get(scenario.event).mode
|
|
462
464
|
|
|
463
465
|
# Define scenario output path
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
466
|
+
impacts_output_path = self.database.get_impacts_path(
|
|
467
|
+
scenario_name=scenario.name
|
|
468
|
+
)
|
|
467
469
|
|
|
468
470
|
# Create column mapping to update column names
|
|
469
471
|
name_translation = {}
|
|
@@ -526,7 +528,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
526
528
|
]
|
|
527
529
|
|
|
528
530
|
# Specify the metrics output path
|
|
529
|
-
metrics_outputs_path =
|
|
531
|
+
metrics_outputs_path = impacts_output_path.parent.joinpath(
|
|
530
532
|
f"Infometrics_{scenario.name}.csv"
|
|
531
533
|
)
|
|
532
534
|
self.create_infometrics(metric_config_paths, metrics_outputs_path)
|
|
@@ -543,7 +545,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
543
545
|
)
|
|
544
546
|
self.create_infographics(
|
|
545
547
|
name=scenario.name,
|
|
546
|
-
output_base_path=
|
|
548
|
+
output_base_path=impacts_output_path.parent,
|
|
547
549
|
config_base_path=config_base_path,
|
|
548
550
|
metrics_path=metrics_outputs_path,
|
|
549
551
|
mode=mode,
|
|
@@ -581,7 +583,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
581
583
|
)
|
|
582
584
|
)
|
|
583
585
|
|
|
584
|
-
|
|
586
|
+
logger.info("Delft-FIAT post-processing complete!")
|
|
585
587
|
|
|
586
588
|
# If site config is set to not keep FIAT simulation, delete folder
|
|
587
589
|
if not self.config.save_simulation:
|
|
@@ -605,7 +607,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
605
607
|
|
|
606
608
|
If the measure type is unsupported, a warning is logged.
|
|
607
609
|
"""
|
|
608
|
-
|
|
610
|
+
logger.info(f"Applying impact measure '{measure.name}'")
|
|
609
611
|
if isinstance(measure, Elevate):
|
|
610
612
|
self.elevate_properties(measure)
|
|
611
613
|
elif isinstance(measure, FloodProof):
|
|
@@ -613,7 +615,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
613
615
|
elif isinstance(measure, Buyout):
|
|
614
616
|
self.buyout_properties(measure)
|
|
615
617
|
else:
|
|
616
|
-
|
|
618
|
+
logger.warning(
|
|
617
619
|
f"Skipping unsupported measure type {measure.__class__.__name__}"
|
|
618
620
|
)
|
|
619
621
|
|
|
@@ -633,7 +635,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
633
635
|
economic growth.
|
|
634
636
|
- Population growth is applied to existing objects if specified.
|
|
635
637
|
"""
|
|
636
|
-
|
|
638
|
+
logger.info(
|
|
637
639
|
f"Applying socioeconomic changes from projection '{projection.name}'"
|
|
638
640
|
)
|
|
639
641
|
socio_economic_change = projection.socio_economic_change
|
|
@@ -709,7 +711,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
709
711
|
units : str, optional
|
|
710
712
|
The units of the hazard map. Defaults to us.UnitTypesLength.meters.
|
|
711
713
|
"""
|
|
712
|
-
|
|
714
|
+
logger.info(f"Setting hazard to the {map_type} map {map_fn}")
|
|
713
715
|
# Add the floodmap data to a data catalog with the unit conversion
|
|
714
716
|
wl_current_units = us.UnitfulLength(value=1.0, units=units)
|
|
715
717
|
conversion_factor = wl_current_units.convert(self.model.exposure.unit)
|
|
@@ -745,7 +747,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
745
747
|
ids : Optional[list], default=None
|
|
746
748
|
A list of object IDs to which the economic growth should be applied. If None, the growth is applied to all buildings.
|
|
747
749
|
"""
|
|
748
|
-
|
|
750
|
+
logger.info(f"Applying economic growth of {economic_growth} %.")
|
|
749
751
|
# Get columns that include max damage
|
|
750
752
|
damage_cols = [
|
|
751
753
|
c
|
|
@@ -792,7 +794,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
792
794
|
ids : Optional[list[str]]
|
|
793
795
|
A list of object IDs to filter the updates. If None, the updates are applied to all buildings.
|
|
794
796
|
"""
|
|
795
|
-
|
|
797
|
+
logger.info(f"Applying population growth of {population_growth} %.")
|
|
796
798
|
# Get columns that include max damage
|
|
797
799
|
damage_cols = [
|
|
798
800
|
c
|
|
@@ -852,7 +854,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
852
854
|
If `elevation_type` is 'floodmap' and base flood elevation (bfe) map is not provided.
|
|
853
855
|
If `elevation_type` is not 'floodmap' or 'datum'.
|
|
854
856
|
"""
|
|
855
|
-
|
|
857
|
+
logger.info(
|
|
856
858
|
f"Applying population growth of {population_growth} %, by creating a new development area using the geometries from {area_path} and a ground floor height of {ground_floor_height} {self.model.exposure.unit} above '{elevation_type}'."
|
|
857
859
|
)
|
|
858
860
|
# Get reference type to align with hydromt
|
|
@@ -884,7 +886,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
884
886
|
# Ensure new_devs geom is in the correct CRS
|
|
885
887
|
new_dev_geom = gpd.read_file(area_path)
|
|
886
888
|
if new_dev_geom.crs != self.model.exposure.crs:
|
|
887
|
-
|
|
889
|
+
logger.warning(
|
|
888
890
|
f"New development area geometries are in {new_dev_geom.crs}, but the model is in {self.model.exposure.crs}. Reprojecting geometries."
|
|
889
891
|
)
|
|
890
892
|
new_dev_geom = new_dev_geom.to_crs(self.model.exposure.crs)
|
|
@@ -947,7 +949,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
947
949
|
If the elevation type is not 'floodmap' or 'datum'.
|
|
948
950
|
"""
|
|
949
951
|
area = self._get_area_name(elevate)
|
|
950
|
-
|
|
952
|
+
logger.info(
|
|
951
953
|
f"Elevating '{elevate.property_type}' type properties in '{area}' by {elevate.elevation} relative to '{elevate.elevation.type}'."
|
|
952
954
|
)
|
|
953
955
|
# If ids are given use that as an additional filter
|
|
@@ -995,9 +997,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
995
997
|
|
|
996
998
|
"""
|
|
997
999
|
area = self._get_area_name(buyout)
|
|
998
|
-
|
|
999
|
-
f"Buying-out '{buyout.property_type}' type properties in '{area}'."
|
|
1000
|
-
)
|
|
1000
|
+
logger.info(f"Buying-out '{buyout.property_type}' type properties in '{area}'.")
|
|
1001
1001
|
# Get columns that include max damage
|
|
1002
1002
|
damage_cols = [
|
|
1003
1003
|
c
|
|
@@ -1036,7 +1036,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
1036
1036
|
The FloodProof measure containing the details of the properties to be floodproofed.
|
|
1037
1037
|
"""
|
|
1038
1038
|
area = self._get_area_name(floodproof)
|
|
1039
|
-
|
|
1039
|
+
logger.info(
|
|
1040
1040
|
f"Flood-proofing '{floodproof.property_type}' type properties in '{area}' by {floodproof.elevation}."
|
|
1041
1041
|
)
|
|
1042
1042
|
# If ids are given use that as an additional filter
|
|
@@ -1197,7 +1197,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
1197
1197
|
pd.DataFrame
|
|
1198
1198
|
The updated results table with exceedance probabilities appended.
|
|
1199
1199
|
"""
|
|
1200
|
-
|
|
1200
|
+
logger.info("Calculating exceedance probabilities")
|
|
1201
1201
|
fiat_results_df = ExceedanceProbabilityCalculator(column).append_probability(
|
|
1202
1202
|
self.outputs["table"], threshold, period
|
|
1203
1203
|
)
|
|
@@ -1223,7 +1223,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
1223
1223
|
If a mandatory metric configuration file does not exist.
|
|
1224
1224
|
"""
|
|
1225
1225
|
# Get the metrics configuration
|
|
1226
|
-
|
|
1226
|
+
logger.info("Calculating infometrics")
|
|
1227
1227
|
|
|
1228
1228
|
# Write the metrics to file
|
|
1229
1229
|
# Check if type of metric configuration is available
|
|
@@ -1274,13 +1274,13 @@ class FiatAdapter(IImpactAdapter):
|
|
|
1274
1274
|
mode : Mode, optional
|
|
1275
1275
|
The mode of the infographic, by default Mode.single_event.
|
|
1276
1276
|
"""
|
|
1277
|
-
|
|
1277
|
+
logger.info("Creating infographics")
|
|
1278
1278
|
|
|
1279
1279
|
# Check if infographics config file exists
|
|
1280
1280
|
if mode == Mode.risk:
|
|
1281
1281
|
config_path = config_base_path.joinpath("config_risk_charts.toml")
|
|
1282
1282
|
if not config_path.exists():
|
|
1283
|
-
|
|
1283
|
+
logger.warning(
|
|
1284
1284
|
"Risk infographic cannot be created, since 'config_risk_charts.toml' is not available"
|
|
1285
1285
|
)
|
|
1286
1286
|
return
|
|
@@ -1320,12 +1320,12 @@ class FiatAdapter(IImpactAdapter):
|
|
|
1320
1320
|
# TODO check what happens if aggr_label not in config
|
|
1321
1321
|
|
|
1322
1322
|
if self.config.aggregation[ind].equity is None:
|
|
1323
|
-
|
|
1323
|
+
logger.warning(
|
|
1324
1324
|
f"Cannot calculate equity weighted risk for aggregation label: {aggr_label}, because equity inputs are not available."
|
|
1325
1325
|
)
|
|
1326
1326
|
return
|
|
1327
1327
|
|
|
1328
|
-
|
|
1328
|
+
logger.info(
|
|
1329
1329
|
f"Calculating equity weighted risk for aggregation label: {aggr_label} "
|
|
1330
1330
|
)
|
|
1331
1331
|
metrics = pd.read_csv(metrics_path)
|
|
@@ -1388,7 +1388,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
1388
1388
|
output_path : os.PathLike
|
|
1389
1389
|
The path where the output spatial file will be saved.
|
|
1390
1390
|
"""
|
|
1391
|
-
|
|
1391
|
+
logger.info(f"Saving impacts for aggregation areas type: '{aggr_label}'")
|
|
1392
1392
|
|
|
1393
1393
|
metrics = pd.read_csv(metrics_path)
|
|
1394
1394
|
|
|
@@ -1424,7 +1424,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
1424
1424
|
ValueError
|
|
1425
1425
|
If no building footprints are provided in the configuration.
|
|
1426
1426
|
"""
|
|
1427
|
-
|
|
1427
|
+
logger.info("Calculating impacts at a building footprint scale")
|
|
1428
1428
|
|
|
1429
1429
|
# Read the existing building points
|
|
1430
1430
|
buildings = self.model.exposure.select_objects(
|
|
@@ -1495,7 +1495,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
1495
1495
|
output_path : os.PathLike
|
|
1496
1496
|
The path where the output spatial file will be saved.
|
|
1497
1497
|
"""
|
|
1498
|
-
|
|
1498
|
+
logger.info("Calculating road impacts")
|
|
1499
1499
|
# Read roads spatial file
|
|
1500
1500
|
roads = gpd.read_file(
|
|
1501
1501
|
self.outputs["path"].joinpath(self.config.roads_file_name)
|
|
@@ -1575,4 +1575,4 @@ class FiatAdapter(IImpactAdapter):
|
|
|
1575
1575
|
if simulation_path.exists():
|
|
1576
1576
|
self.close_files()
|
|
1577
1577
|
shutil.rmtree(simulation_path)
|
|
1578
|
-
|
|
1578
|
+
logger.info(f"Deleted Delft-FIAT simulation folder: {simulation_path}")
|
|
@@ -2,8 +2,8 @@ from abc import abstractmethod
|
|
|
2
2
|
|
|
3
3
|
from flood_adapt.adapter.interface.model_adapter import IAdapter
|
|
4
4
|
from flood_adapt.objects.measures.measures import Measure
|
|
5
|
+
from flood_adapt.objects.output.floodmap import FloodMap
|
|
5
6
|
from flood_adapt.objects.projections.projections import Projection
|
|
6
|
-
from flood_adapt.workflows.floodmap import FloodMap
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class IImpactAdapter(IAdapter):
|