flood-adapt 1.1.5__tar.gz → 2.0.0__tar.gz
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-1.1.5 → flood_adapt-2.0.0}/PKG-INFO +2 -2
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/__init__.py +1 -1
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/adapter/fiat_adapter.py +57 -29
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/adapter/sfincs_adapter.py +164 -93
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/config/hazard.py +1 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/database_builder.py +41 -46
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/database.py +57 -76
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/dbs_scenario.py +1 -2
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/interface/database.py +8 -31
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/events/events.py +0 -57
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/forcing.py +1 -46
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt.egg-info/PKG-INFO +2 -2
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt.egg-info/requires.txt +1 -1
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/pyproject.toml +19 -19
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/LICENSE +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/README.md +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/adapter/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/adapter/interface/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/adapter/interface/hazard_adapter.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/adapter/interface/impact_adapter.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/adapter/interface/model_adapter.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/adapter/interface/offshore.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/adapter/sfincs_offshore.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/config/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/config/config.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/config/fiat.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/config/gui.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/config/impacts.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/config/sfincs.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/config/site.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/metrics_utils.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/default_units/imperial.toml +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/default_units/metric.toml +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/green_infra_table/green_infra_lookup_table.csv +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/black_down_48x48.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/black_left_48x48.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/black_right_48x48.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/black_up_48x48.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_down.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_left.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_right.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_up.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_down.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_left.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_right.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_up.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_white_left.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_white_right.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/white_down_48x48.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/white_left_48x48.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/white_right_48x48.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/icons/white_up_48x48.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/images/ambulance.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/images/car.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/images/cart.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/images/firetruck.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/images/hospital.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/images/house.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/images/info.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/images/money.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/images/person.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/images/school.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/images/truck.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/images/walking_person.png +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/infographics/styles.css +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/database_builder/templates/output_layers/bin_colors.toml +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/dbs_benefit.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/dbs_event.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/dbs_measure.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/dbs_projection.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/dbs_static.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/dbs_strategy.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/dbs_template.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/interface/element.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/dbs_classes/interface/static.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/flood_adapt.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/misc/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/misc/database_user.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/misc/debug_timer.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/misc/exceptions.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/misc/log.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/misc/path_builder.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/misc/utils.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/benefits/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/benefits/benefits.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/events/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/events/event_factory.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/events/event_set.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/events/historical.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/events/hurricane.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/events/synthetic.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/csv.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/discharge.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/forcing_factory.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/meteo_handler.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/netcdf.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/plotting.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/rainfall.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/tide_gauge.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/time_frame.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/timeseries.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/unit_system.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/waterlevels.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/forcing/wind.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/measures/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/measures/measure_factory.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/measures/measures.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/object_model.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/output/floodmap.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/projections/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/projections/projections.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/scenarios/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/scenarios/scenarios.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/strategies/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/objects/strategies/strategies.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/workflows/__init__.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/workflows/benefit_runner.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt/workflows/scenario_runner.py +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt.egg-info/SOURCES.txt +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt.egg-info/dependency_links.txt +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt.egg-info/not-zip-safe +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/flood_adapt.egg-info/top_level.txt +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/setup.cfg +0 -0
- {flood_adapt-1.1.5 → flood_adapt-2.0.0}/tests/test_flood_adapt.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: flood-adapt
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: A software package support system which can be used to assess the benefits and costs of flood resilience measures
|
|
5
5
|
Author-email: Gundula Winter <Gundula.Winter@deltares.nl>, Panos Athanasiou <Panos.Athanasiou@deltares.nl>, Frederique de Groen <Frederique.deGroen@deltares.nl>, Tim de Wilde <Tim.deWilde@deltares.nl>, Julian Hofer <Julian.Hofer@deltares.nl>, Daley Adrichem <Daley.Adrichem@deltares.nl>, Luuk Blom <Luuk.Blom@deltares.nl>
|
|
6
6
|
License: ====================================================
|
|
@@ -717,7 +717,7 @@ Requires-Dist: fiona<2.0,>=1.0
|
|
|
717
717
|
Requires-Dist: geojson<4.0,>=3.0
|
|
718
718
|
Requires-Dist: geopandas<2.0,>=1.0
|
|
719
719
|
Requires-Dist: hydromt-fiat<1.0,>=0.5.9
|
|
720
|
-
Requires-Dist: hydromt-sfincs<2.0,>=1.2.2
|
|
720
|
+
Requires-Dist: hydromt-sfincs[quadtree]<2.0,>=1.2.2
|
|
721
721
|
Requires-Dist: numpy<2.0,>=1.0
|
|
722
722
|
Requires-Dist: numpy-financial<2.0,>=1.0
|
|
723
723
|
Requires-Dist: pandas<3.0,>=2.0
|
|
@@ -258,7 +258,7 @@ class FiatAdapter(IImpactAdapter):
|
|
|
258
258
|
map_type=floodmap.map_type,
|
|
259
259
|
var=var,
|
|
260
260
|
is_risk=is_risk,
|
|
261
|
-
units=
|
|
261
|
+
units=self.database.site.sfincs.config.floodmap_units,
|
|
262
262
|
)
|
|
263
263
|
|
|
264
264
|
# Save any changes made to disk as well
|
|
@@ -489,7 +489,10 @@ class FiatAdapter(IImpactAdapter):
|
|
|
489
489
|
fiat_results_path = impacts_output_path.joinpath(
|
|
490
490
|
f"Impacts_detailed_{scenario.name}.csv"
|
|
491
491
|
)
|
|
492
|
-
|
|
492
|
+
try:
|
|
493
|
+
self.outputs["table"].to_csv(fiat_results_path, index=False)
|
|
494
|
+
except Exception as e:
|
|
495
|
+
logger.error(f"Error while saving detailed impacts file csv: {e}")
|
|
493
496
|
|
|
494
497
|
# Add exceedance probabilities if needed (only for risk)
|
|
495
498
|
if mode == Mode.risk:
|
|
@@ -500,13 +503,16 @@ class FiatAdapter(IImpactAdapter):
|
|
|
500
503
|
)
|
|
501
504
|
with open(config_path, mode="rb") as fp:
|
|
502
505
|
config = tomli.load(fp)["flood_exceedance"]
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
506
|
+
try:
|
|
507
|
+
self.add_exceedance_probability(
|
|
508
|
+
column=config[
|
|
509
|
+
"column"
|
|
510
|
+
], # TODO check how to the correct version of column
|
|
511
|
+
threshold=config["threshold"],
|
|
512
|
+
period=config["period"],
|
|
513
|
+
)
|
|
514
|
+
except Exception as e:
|
|
515
|
+
logger.error(f"Error while adding exceedance probabilities: {e}")
|
|
510
516
|
|
|
511
517
|
# Create the infometrics files
|
|
512
518
|
if mode == Mode.risk:
|
|
@@ -531,7 +537,10 @@ class FiatAdapter(IImpactAdapter):
|
|
|
531
537
|
metrics_outputs_path = impacts_output_path.parent.joinpath(
|
|
532
538
|
f"Infometrics_{scenario.name}.csv"
|
|
533
539
|
)
|
|
534
|
-
|
|
540
|
+
try:
|
|
541
|
+
self.create_infometrics(metric_config_paths, metrics_outputs_path)
|
|
542
|
+
except Exception as e:
|
|
543
|
+
logger.error(f"Error while creating infometrics: {e}")
|
|
535
544
|
|
|
536
545
|
# Get paths of created aggregated infometrics
|
|
537
546
|
aggr_metrics_paths = list(
|
|
@@ -543,20 +552,28 @@ class FiatAdapter(IImpactAdapter):
|
|
|
543
552
|
config_base_path = self.database.static_path.joinpath(
|
|
544
553
|
"templates", "Infographics"
|
|
545
554
|
)
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
555
|
+
try:
|
|
556
|
+
self.create_infographics(
|
|
557
|
+
name=scenario.name,
|
|
558
|
+
output_base_path=impacts_output_path.parent,
|
|
559
|
+
config_base_path=config_base_path,
|
|
560
|
+
metrics_path=metrics_outputs_path,
|
|
561
|
+
mode=mode,
|
|
562
|
+
)
|
|
563
|
+
except Exception as e:
|
|
564
|
+
logger.error(f"Error while creating infographics: {e}")
|
|
553
565
|
|
|
554
566
|
# Calculate equity based damages
|
|
555
567
|
if mode == Mode.risk:
|
|
556
568
|
for file in aggr_metrics_paths:
|
|
557
569
|
# Load metrics
|
|
558
570
|
aggr_label = file.stem.split(f"{metrics_outputs_path.stem}_")[-1]
|
|
559
|
-
|
|
571
|
+
try:
|
|
572
|
+
self.add_equity(aggr_label=aggr_label, metrics_path=file)
|
|
573
|
+
except Exception as e:
|
|
574
|
+
logger.error(
|
|
575
|
+
f"Error while calculating equity metrics for {aggr_label}: {e}"
|
|
576
|
+
)
|
|
560
577
|
|
|
561
578
|
# Save aggregated metrics to shapefiles
|
|
562
579
|
for file in aggr_metrics_paths:
|
|
@@ -564,24 +581,35 @@ class FiatAdapter(IImpactAdapter):
|
|
|
564
581
|
output_path = impacts_output_path.joinpath(
|
|
565
582
|
f"Impacts_aggregated_{scenario.name}_{aggr_label}.gpkg"
|
|
566
583
|
)
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
584
|
+
try:
|
|
585
|
+
self.save_aggregation_spatial(
|
|
586
|
+
aggr_label=aggr_label, metrics_path=file, output_path=output_path
|
|
587
|
+
)
|
|
588
|
+
except Exception as e:
|
|
589
|
+
logger.error(
|
|
590
|
+
f"Error while saving aggregation spatial for {aggr_label}: {e}"
|
|
591
|
+
)
|
|
570
592
|
|
|
571
593
|
# Merge points data to building footprints
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
594
|
+
try:
|
|
595
|
+
self.save_building_footprints(
|
|
596
|
+
output_path=impacts_output_path.joinpath(
|
|
597
|
+
f"Impacts_building_footprints_{scenario.name}.gpkg"
|
|
598
|
+
)
|
|
575
599
|
)
|
|
576
|
-
|
|
600
|
+
except Exception as e:
|
|
601
|
+
logger.error(f"Error while saving building footprints: {e}")
|
|
577
602
|
|
|
578
603
|
# Create a roads spatial file
|
|
579
604
|
if self.config.roads_file_name:
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
605
|
+
try:
|
|
606
|
+
self.save_roads(
|
|
607
|
+
output_path=impacts_output_path.joinpath(
|
|
608
|
+
f"Impacts_roads_{scenario.name}.gpkg"
|
|
609
|
+
)
|
|
583
610
|
)
|
|
584
|
-
|
|
611
|
+
except Exception as e:
|
|
612
|
+
logger.error(f"Error while saving roads spatial file: {e}")
|
|
585
613
|
|
|
586
614
|
logger.info("Delft-FIAT post-processing complete!")
|
|
587
615
|
|
|
@@ -15,12 +15,12 @@ import plotly.express as px
|
|
|
15
15
|
import pyproj
|
|
16
16
|
import shapely
|
|
17
17
|
import xarray as xr
|
|
18
|
+
import xugrid as xu
|
|
18
19
|
from cht_cyclones.tropical_cyclone import TropicalCyclone
|
|
19
20
|
from cht_tide.read_bca import SfincsBoundary
|
|
20
21
|
from cht_tide.tide_predict import predict
|
|
21
22
|
from hydromt_sfincs import SfincsModel as HydromtSfincsModel
|
|
22
23
|
from hydromt_sfincs.quadtree import QuadtreeGrid
|
|
23
|
-
from numpy import matlib
|
|
24
24
|
from shapely.affinity import translate
|
|
25
25
|
|
|
26
26
|
from flood_adapt.adapter.interface.hazard_adapter import IHazardAdapter
|
|
@@ -308,9 +308,9 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
308
308
|
):
|
|
309
309
|
raise RuntimeError("SFINCS was not run successfully!")
|
|
310
310
|
|
|
311
|
+
self.write_water_level_map(scenario)
|
|
311
312
|
self.write_floodmap_geotiff(scenario)
|
|
312
313
|
self.plot_wl_obs(scenario)
|
|
313
|
-
self.write_water_level_map(scenario)
|
|
314
314
|
|
|
315
315
|
def set_timing(self, time: TimeFrame):
|
|
316
316
|
"""Set model reference times."""
|
|
@@ -386,20 +386,27 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
386
386
|
def get_model_root(self) -> Path:
|
|
387
387
|
return Path(self._model.root)
|
|
388
388
|
|
|
389
|
-
def get_mask(self):
|
|
389
|
+
def get_mask(self) -> xr.DataArray:
|
|
390
390
|
"""Get mask with inactive cells from model."""
|
|
391
|
-
mask = self._model.
|
|
391
|
+
mask = self._model.mask
|
|
392
392
|
return mask
|
|
393
393
|
|
|
394
|
-
def get_bedlevel(self):
|
|
394
|
+
def get_bedlevel(self) -> xr.DataArray:
|
|
395
395
|
"""Get bed level from model."""
|
|
396
396
|
self._model.read_results()
|
|
397
397
|
zb = self._model.results["zb"]
|
|
398
|
+
# Convert bed level from meters to floodmap units
|
|
399
|
+
conversion = us.UnitfulLength(
|
|
400
|
+
value=1.0, units=us.UnitTypesLength.meters
|
|
401
|
+
).convert(self.settings.config.floodmap_units)
|
|
402
|
+
zb = zb * conversion
|
|
403
|
+
zb.attrs["units"] = self.settings.config.floodmap_units.value
|
|
398
404
|
return zb
|
|
399
405
|
|
|
400
406
|
def get_model_boundary(self) -> gpd.GeoDataFrame:
|
|
401
407
|
"""Get bounding box from model."""
|
|
402
|
-
|
|
408
|
+
boundary = self._model.region[["geometry"]]
|
|
409
|
+
return boundary
|
|
403
410
|
|
|
404
411
|
def get_model_grid(self) -> QuadtreeGrid:
|
|
405
412
|
"""Get grid from model.
|
|
@@ -411,6 +418,15 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
411
418
|
"""
|
|
412
419
|
return self._model.quadtree
|
|
413
420
|
|
|
421
|
+
def get_finest_res(self) -> float:
|
|
422
|
+
"""Get the finest resolution of the model grid."""
|
|
423
|
+
if self._model.grid_type == "quadtree":
|
|
424
|
+
res0 = self._model.quadtree.dx
|
|
425
|
+
res = res0 / 2**self._model.quadtree.nr_refinement_levels
|
|
426
|
+
else:
|
|
427
|
+
res = self._model.res[0]
|
|
428
|
+
return res
|
|
429
|
+
|
|
414
430
|
# Forcing properties
|
|
415
431
|
@property
|
|
416
432
|
def waterlevels(self) -> xr.Dataset | xr.DataArray | None:
|
|
@@ -543,7 +559,7 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
543
559
|
sim_path : Path, optional
|
|
544
560
|
Path to the simulation folder, by default None.
|
|
545
561
|
"""
|
|
546
|
-
logger.info("Writing flood maps to geotiff")
|
|
562
|
+
logger.info("Writing flood maps to geotiff.")
|
|
547
563
|
results_path = self._get_result_path(scenario)
|
|
548
564
|
sim_path = sim_path or self._get_simulation_path(scenario)
|
|
549
565
|
demfile = self.database.static_path / "dem" / self.settings.dem.filename
|
|
@@ -560,13 +576,8 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
560
576
|
|
|
561
577
|
floodmap_fn = results_path / f"FloodMap_{scenario.name}.tif"
|
|
562
578
|
|
|
563
|
-
# convert zsmax from meters to floodmap units
|
|
564
|
-
floodmap_conversion = us.UnitfulLength(
|
|
565
|
-
value=1.0, units=us.UnitTypesLength.meters
|
|
566
|
-
).convert(self.settings.config.floodmap_units)
|
|
567
|
-
|
|
568
579
|
utils.downscale_floodmap(
|
|
569
|
-
zsmax=
|
|
580
|
+
zsmax=zsmax,
|
|
570
581
|
dep=dem_conversion * dem,
|
|
571
582
|
hmin=0.01,
|
|
572
583
|
floodmap_fn=floodmap_fn.as_posix(),
|
|
@@ -582,7 +593,23 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
582
593
|
|
|
583
594
|
with SfincsAdapter(model_root=sim_path) as model:
|
|
584
595
|
zsmax = model._get_zsmax()
|
|
585
|
-
zsmax
|
|
596
|
+
if hasattr(zsmax, "ugrid"):
|
|
597
|
+
# First write netcdf with quadtree water levels
|
|
598
|
+
zsmax.to_netcdf(results_path / "max_water_level_map_qt.nc")
|
|
599
|
+
# Rasterize to regular grid with the finest resolution
|
|
600
|
+
zsmax = self._rasterize_quadtree(zsmax)
|
|
601
|
+
# Add CRS to the rasterized xarray
|
|
602
|
+
zsmax = zsmax.rio.write_crs(model._model.config["epsg"])
|
|
603
|
+
# Save as a Cloud Optimized GeoTIFF (COG)
|
|
604
|
+
zsmax.rio.to_raster(
|
|
605
|
+
results_path / "max_water_level_map.tif",
|
|
606
|
+
driver="COG",
|
|
607
|
+
compress="deflate",
|
|
608
|
+
dtype="float32",
|
|
609
|
+
nodata=np.nan,
|
|
610
|
+
OVERVIEW_RESAMPLING="nearest",
|
|
611
|
+
tags={"units": self.settings.config.floodmap_units.value},
|
|
612
|
+
)
|
|
586
613
|
|
|
587
614
|
def plot_wl_obs(
|
|
588
615
|
self,
|
|
@@ -727,83 +754,117 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
727
754
|
|
|
728
755
|
TODO: make this robust and more efficient for bigger datasets.
|
|
729
756
|
"""
|
|
757
|
+
# Check if the scenario is a risk scenario
|
|
730
758
|
event: EventSet = self.database.events.get(scenario.event, load_all=True)
|
|
731
759
|
if not isinstance(event, EventSet):
|
|
732
760
|
raise ValueError("This function is only available for risk scenarios.")
|
|
761
|
+
logger.info("Calculating flood risk maps, this may take some time.")
|
|
733
762
|
|
|
763
|
+
# Get the simulation paths and result path
|
|
734
764
|
result_path = self._get_result_path(scenario)
|
|
735
765
|
sim_paths = [
|
|
736
766
|
self._get_simulation_path(scenario, sub_event=sub_event)
|
|
737
767
|
for sub_event in event._events
|
|
738
768
|
]
|
|
739
769
|
|
|
770
|
+
# Get the required return periods for flood maps
|
|
771
|
+
floodmap_rp = self.database.site.fiat.risk.return_periods
|
|
772
|
+
|
|
773
|
+
# Get the frequencies for each sub-event
|
|
774
|
+
frequencies = [sub_event.frequency for sub_event in event.sub_events]
|
|
740
775
|
phys_proj = self.database.projections.get(
|
|
741
776
|
scenario.projection
|
|
742
777
|
).physical_projection
|
|
743
778
|
|
|
744
|
-
|
|
745
|
-
frequencies = [sub_event.frequency for sub_event in event.sub_events]
|
|
746
|
-
|
|
747
|
-
# adjust storm frequency for hurricane events
|
|
779
|
+
# adjust storm frequency for hurricane events if provided in the projection
|
|
748
780
|
if not math.isclose(phys_proj.storm_frequency_increase, 0, abs_tol=1e-9):
|
|
749
781
|
storminess_increase = phys_proj.storm_frequency_increase / 100.0
|
|
750
782
|
for ii, event in enumerate(event._events):
|
|
751
783
|
if event.template == Template.Hurricane:
|
|
752
784
|
frequencies[ii] = frequencies[ii] * (1 + storminess_increase)
|
|
753
785
|
|
|
786
|
+
# Read static mask and bed level from the first simulation path
|
|
754
787
|
with SfincsAdapter(model_root=sim_paths[0]) as dummymodel:
|
|
755
788
|
# read mask and bed level
|
|
756
789
|
mask = dummymodel.get_mask()
|
|
757
790
|
zb = dummymodel.get_bedlevel()
|
|
758
791
|
|
|
792
|
+
# Read the max water level maps from each simulation path
|
|
759
793
|
zs_maps = []
|
|
760
794
|
for simulation_path in sim_paths:
|
|
761
795
|
# read zsmax data from overland sfincs model
|
|
762
796
|
with SfincsAdapter(model_root=simulation_path) as sim:
|
|
763
797
|
zsmax = sim._get_zsmax().load()
|
|
764
|
-
zs_maps.append(zsmax)
|
|
798
|
+
zs_maps.append(zsmax.values)
|
|
765
799
|
|
|
766
|
-
#
|
|
767
|
-
|
|
800
|
+
# Calculate return period flood maps
|
|
801
|
+
# All units are in the floodmap units
|
|
768
802
|
rp_flood_maps = self.calc_rp_maps(
|
|
769
803
|
floodmaps=zs_maps,
|
|
770
804
|
frequencies=frequencies,
|
|
771
|
-
zb=zb,
|
|
772
|
-
mask=mask,
|
|
805
|
+
zb=zb.values,
|
|
806
|
+
mask=mask.values,
|
|
773
807
|
return_periods=floodmap_rp,
|
|
774
808
|
)
|
|
775
809
|
|
|
810
|
+
# For each return period, save water level and flood depth maps
|
|
776
811
|
for ii, rp in enumerate(floodmap_rp):
|
|
777
|
-
|
|
778
|
-
zs_rp_single =
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
812
|
+
# Prepare data array for the return period flood map
|
|
813
|
+
zs_rp_single = xr.DataArray(
|
|
814
|
+
rp_flood_maps[ii],
|
|
815
|
+
name="zsmax",
|
|
816
|
+
attrs={"units": self.settings.config.floodmap_units.value},
|
|
817
|
+
)
|
|
818
|
+
# If model is quadtree, write the quadtree netcdf with water levels since it is needed for visualizations
|
|
819
|
+
if self._model.grid_type == "quadtree":
|
|
820
|
+
# Use mask grid
|
|
821
|
+
zs_rp_single = xu.UgridDataArray.from_data(
|
|
822
|
+
zs_rp_single, grid=mask.grid, facet="face"
|
|
823
|
+
)
|
|
824
|
+
# Save to netcdf
|
|
825
|
+
zs_rp_single.to_netcdf(
|
|
826
|
+
result_path / f"RP_{rp:04d}_max_water_level_map_qt.nc"
|
|
827
|
+
)
|
|
828
|
+
# Rasterize to regular grid with the finest resolution
|
|
829
|
+
zs_rp_single = self._rasterize_quadtree(zs_rp_single)
|
|
830
|
+
# Prepare regular grid water level map
|
|
831
|
+
elif self._model.grid_type == "regular":
|
|
832
|
+
# Create a DataArray with the mask coordinates
|
|
833
|
+
zs_rp_single = xr.DataArray(
|
|
834
|
+
zs_rp_single,
|
|
835
|
+
dims=("y", "x"),
|
|
836
|
+
coords={"y": mask.y, "x": mask.x},
|
|
837
|
+
name="zsmax",
|
|
838
|
+
)
|
|
839
|
+
else:
|
|
840
|
+
raise ValueError("unsupported sfincs model type")
|
|
841
|
+
# Write COG geotiff with water levels
|
|
842
|
+
zs_rp_single = zs_rp_single.rio.write_crs(self._model.crs)
|
|
843
|
+
fn_rp = result_path / f"RP_{rp:04d}_max_water_level_map.tif"
|
|
844
|
+
zs_rp_single.transpose("y", "x").rio.to_raster(
|
|
845
|
+
fn_rp,
|
|
846
|
+
driver="COG",
|
|
847
|
+
compress="deflate",
|
|
848
|
+
dtype="float32",
|
|
849
|
+
nodata=np.nan,
|
|
850
|
+
OVERVIEW_RESAMPLING="nearest",
|
|
851
|
+
tags={"units": self.settings.config.floodmap_units.value},
|
|
852
|
+
)
|
|
853
|
+
|
|
786
854
|
# dem file for high resolution flood depth map
|
|
787
855
|
demfile = self.database.static_path / "dem" / self.settings.dem.filename
|
|
856
|
+
# convert dem from dem units to floodmap units
|
|
857
|
+
dem_conversion = us.UnitfulLength(
|
|
858
|
+
value=1.0, units=self.settings.dem.units
|
|
859
|
+
).convert(self.settings.config.floodmap_units)
|
|
788
860
|
|
|
789
861
|
# writing the geotiff to the scenario results folder
|
|
790
862
|
with SfincsAdapter(model_root=sim_paths[0]) as dummymodel:
|
|
791
863
|
dem = dummymodel._model.data_catalog.get_rasterdataset(demfile)
|
|
792
|
-
|
|
793
|
-
floodmap_fn = fn_rp.with_suffix(".tif")
|
|
794
|
-
|
|
795
|
-
# convert dem from dem units to floodmap units
|
|
796
|
-
dem_conversion = us.UnitfulLength(
|
|
797
|
-
value=1.0, units=self.settings.dem.units
|
|
798
|
-
).convert(self.settings.config.floodmap_units)
|
|
799
|
-
|
|
800
|
-
# convert zsmax from meters to floodmap units
|
|
801
|
-
floodmap_conversion = us.UnitfulLength(
|
|
802
|
-
value=1.0, units=us.UnitTypesLength.meters
|
|
803
|
-
).convert(self.settings.config.floodmap_units)
|
|
864
|
+
floodmap_fn = result_path / f"RP_{rp:04d}_FloodMap.tif"
|
|
804
865
|
|
|
805
866
|
utils.downscale_floodmap(
|
|
806
|
-
zsmax=
|
|
867
|
+
zsmax=zs_rp_single,
|
|
807
868
|
dep=dem_conversion * dem,
|
|
808
869
|
hmin=0.01,
|
|
809
870
|
floodmap_fn=floodmap_fn.as_posix(),
|
|
@@ -1525,9 +1586,9 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
1525
1586
|
if isinstance(event, EventSet):
|
|
1526
1587
|
map_fn = []
|
|
1527
1588
|
for rp in self.database.site.fiat.risk.return_periods:
|
|
1528
|
-
map_fn.append(results_path / f"RP_{rp:04d}
|
|
1589
|
+
map_fn.append(results_path / f"RP_{rp:04d}_max_water_level_map.tif")
|
|
1529
1590
|
elif isinstance(event, Event):
|
|
1530
|
-
map_fn = [results_path / "max_water_level_map.
|
|
1591
|
+
map_fn = [results_path / "max_water_level_map.tif"]
|
|
1531
1592
|
else:
|
|
1532
1593
|
raise ValueError(f"Unsupported mode: {event.mode}")
|
|
1533
1594
|
|
|
@@ -1541,7 +1602,14 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
1541
1602
|
"""Read zsmax file and return absolute maximum water level over entire simulation."""
|
|
1542
1603
|
self._model.read_results()
|
|
1543
1604
|
zsmax = self._model.results["zsmax"].max(dim="timemax")
|
|
1544
|
-
|
|
1605
|
+
|
|
1606
|
+
# Convert from meters to floodmap units
|
|
1607
|
+
floodmap_conversion = us.UnitfulLength(
|
|
1608
|
+
value=1.0, units=us.UnitTypesLength.meters
|
|
1609
|
+
).convert(self.settings.config.floodmap_units)
|
|
1610
|
+
zsmax = zsmax * floodmap_conversion
|
|
1611
|
+
zsmax.attrs["units"] = self.settings.config.floodmap_units.value
|
|
1612
|
+
|
|
1545
1613
|
return zsmax
|
|
1546
1614
|
|
|
1547
1615
|
def _get_zs_points(self):
|
|
@@ -1571,6 +1639,21 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
1571
1639
|
)
|
|
1572
1640
|
return df, gdf
|
|
1573
1641
|
|
|
1642
|
+
def _rasterize_quadtree(self, zsmax: xu.UgridDataArray) -> xr.DataArray:
|
|
1643
|
+
"""Rasterize the zsmax UgridDataArray to a regular grid."""
|
|
1644
|
+
xmin, ymin, xmax, ymax = zsmax.ugrid.bounds["mesh2d"]
|
|
1645
|
+
d = self.get_finest_res()
|
|
1646
|
+
x = np.arange(xmin + 0.5 * d, xmax, d)
|
|
1647
|
+
y = np.arange(ymax - 0.5 * d, ymin, -d)
|
|
1648
|
+
# Create a template DataArray with the desired x and y coordinates
|
|
1649
|
+
template = xr.DataArray(
|
|
1650
|
+
np.zeros((len(y), len(x))),
|
|
1651
|
+
coords={"y": y, "x": x},
|
|
1652
|
+
dims=("y", "x"),
|
|
1653
|
+
)
|
|
1654
|
+
zsmax = zsmax.ugrid.rasterize_like(template)
|
|
1655
|
+
return zsmax
|
|
1656
|
+
|
|
1574
1657
|
def _create_spw_file_from_track(
|
|
1575
1658
|
self,
|
|
1576
1659
|
track_forcing: Union[RainfallTrack, WindTrack],
|
|
@@ -1810,12 +1893,12 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
1810
1893
|
|
|
1811
1894
|
@staticmethod
|
|
1812
1895
|
def calc_rp_maps(
|
|
1813
|
-
floodmaps: list[
|
|
1896
|
+
floodmaps: list[np.ndarray],
|
|
1814
1897
|
frequencies: list[float],
|
|
1815
|
-
zb:
|
|
1816
|
-
mask:
|
|
1898
|
+
zb: np.ndarray,
|
|
1899
|
+
mask: np.ndarray,
|
|
1817
1900
|
return_periods: list[float],
|
|
1818
|
-
) -> list[
|
|
1901
|
+
) -> list[np.ndarray]:
|
|
1819
1902
|
"""
|
|
1820
1903
|
Calculate return period (RP) flood maps from a set of flood simulation results.
|
|
1821
1904
|
|
|
@@ -1824,26 +1907,25 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
1824
1907
|
using exceedance probabilities and handles masked or dry cells appropriately.
|
|
1825
1908
|
|
|
1826
1909
|
Args:
|
|
1827
|
-
floodmaps (list[
|
|
1910
|
+
floodmaps (list[np.ndarray]): List of water level maps (NumPy arrays), one for each simulation.
|
|
1828
1911
|
frequencies (list[float]): List of frequencies (probabilities of occurrence) corresponding to each floodmap.
|
|
1829
1912
|
zb (np.ndarray): Array of bed elevations for each grid cell.
|
|
1830
|
-
mask (
|
|
1913
|
+
mask (np.ndarray): Mask indicating valid (1) and invalid (0) grid cells.
|
|
1831
1914
|
return_periods (list[float]): List of return periods (in years) for which to generate hazard maps.
|
|
1832
1915
|
|
|
1833
1916
|
Returns
|
|
1834
1917
|
-------
|
|
1835
|
-
list[
|
|
1836
|
-
|
|
1918
|
+
list[np.ndarray]: List of NumPy arrays, each representing the hazard map for a given return period.
|
|
1919
|
+
Each array contains water levels (meters) for the corresponding return period.
|
|
1837
1920
|
"""
|
|
1838
|
-
floodmaps =
|
|
1839
|
-
# Check that all floodmaps have the same shape
|
|
1921
|
+
floodmaps = [np.asarray(fm) for fm in floodmaps]
|
|
1922
|
+
# Check that all floodmaps have the same shape
|
|
1840
1923
|
first_shape = floodmaps[0].shape
|
|
1841
|
-
first_dims = floodmaps[0].dims
|
|
1842
1924
|
for i, floodmap in enumerate(floodmaps):
|
|
1843
|
-
if floodmap.shape != first_shape
|
|
1925
|
+
if floodmap.shape != first_shape:
|
|
1844
1926
|
raise ValueError(
|
|
1845
|
-
f"Floodmap at index {i} does not match the shape
|
|
1846
|
-
f"Expected shape {first_shape}
|
|
1927
|
+
f"Floodmap at index {i} does not match the shape of the first floodmap. "
|
|
1928
|
+
f"Expected shape {first_shape}, got shape {floodmap.shape}."
|
|
1847
1929
|
)
|
|
1848
1930
|
|
|
1849
1931
|
# Check that zb and mask have the same shape
|
|
@@ -1863,22 +1945,21 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
1863
1945
|
f"Floodmap shape: {first_shape}, zb shape: {zb.shape}, mask shape: {mask.shape}."
|
|
1864
1946
|
)
|
|
1865
1947
|
|
|
1866
|
-
#
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1948
|
+
# If input is 2D, reshape to 1D for processing and then reshape back to 2D
|
|
1949
|
+
reshape_needed = False
|
|
1950
|
+
if zb.ndim == 2:
|
|
1951
|
+
reshape_needed = True
|
|
1952
|
+
shape_orig = zb.shape
|
|
1953
|
+
n_cells = zb.size
|
|
1954
|
+
floodmaps = [fm.reshape(n_cells) for fm in floodmaps]
|
|
1955
|
+
zb = zb.reshape(n_cells)
|
|
1956
|
+
mask = mask.reshape(n_cells)
|
|
1876
1957
|
# 1a: make a table of all water levels and associated frequencies
|
|
1877
|
-
zs =
|
|
1958
|
+
zs = np.stack(floodmaps, axis=0)
|
|
1878
1959
|
# Get the indices of columns with all NaN values
|
|
1879
1960
|
nan_cells = np.where(np.all(np.isnan(zs), axis=0))[0]
|
|
1880
1961
|
# fill nan values with minimum bed levels in each grid cell, np.interp cannot ignore nan values
|
|
1881
|
-
zs =
|
|
1962
|
+
zs = np.where(np.isnan(zs), np.tile(zb, (zs.shape[0], 1)), zs)
|
|
1882
1963
|
# Get table of frequencies
|
|
1883
1964
|
freq = np.tile(frequencies, (zs.shape[1], 1)).transpose()
|
|
1884
1965
|
|
|
@@ -1886,7 +1967,7 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
1886
1967
|
# (i.e. each h-value should be linked to the same p-values as in step 1a)
|
|
1887
1968
|
sort_index = zs.argsort(axis=0)
|
|
1888
1969
|
sorted_prob = np.flipud(np.take_along_axis(freq, sort_index, axis=0))
|
|
1889
|
-
sorted_zs = np.flipud(np.take_along_axis(zs
|
|
1970
|
+
sorted_zs = np.flipud(np.take_along_axis(zs, sort_index, axis=0))
|
|
1890
1971
|
|
|
1891
1972
|
# 1c: Compute exceedance probabilities of water depths
|
|
1892
1973
|
# Method: accumulate probabilities from top to bottom
|
|
@@ -1902,23 +1983,19 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
1902
1983
|
# h(T) = interp1 (log(T*), h*, log(T))
|
|
1903
1984
|
# in which t* and h* are the values from the table and T is the return period (T) of interest
|
|
1904
1985
|
# The resulting T-year water depths for all grids combined form the T-year hazard map
|
|
1905
|
-
rp_da = xr.DataArray(rp_zs, dims=zs.dims)
|
|
1906
|
-
|
|
1907
|
-
# no_data_value = -999 # in SFINCS
|
|
1908
|
-
# sorted_zs = xr.where(sorted_zs == no_data_value, np.nan, sorted_zs)
|
|
1909
1986
|
|
|
1910
1987
|
valid_cells = np.where(mask == 1)[
|
|
1911
1988
|
0
|
|
1912
1989
|
] # only loop over cells where model is not masked
|
|
1913
|
-
h =
|
|
1914
|
-
|
|
1990
|
+
h = np.tile(
|
|
1991
|
+
zb, (len(return_periods), 1)
|
|
1915
1992
|
) # if not flooded (i.e. not in valid_cells) revert to bed_level, read from SFINCS results so it is the minimum bed level in a grid cell
|
|
1916
1993
|
|
|
1917
1994
|
for jj in valid_cells: # looping over all non-masked cells.
|
|
1918
1995
|
# linear interpolation for all return periods to evaluate
|
|
1919
1996
|
h[:, jj] = np.interp(
|
|
1920
1997
|
np.log10(return_periods),
|
|
1921
|
-
np.log10(
|
|
1998
|
+
np.log10(rp_zs[::-1, jj]),
|
|
1922
1999
|
sorted_zs[::-1, jj],
|
|
1923
2000
|
left=0,
|
|
1924
2001
|
)
|
|
@@ -1935,16 +2012,10 @@ class SfincsAdapter(IHazardAdapter):
|
|
|
1935
2012
|
|
|
1936
2013
|
rp_maps = []
|
|
1937
2014
|
for ii, rp in enumerate(return_periods):
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
if
|
|
1942
|
-
|
|
1943
|
-
da = da.unstack()
|
|
1944
|
-
# Reorder dimensions if needed
|
|
1945
|
-
if set(da.dims) == {"y", "x"} and da.dims != ("y", "x"):
|
|
1946
|
-
da = da.transpose("y", "x")
|
|
1947
|
-
# #create single nc
|
|
1948
|
-
rp_maps.append(da)
|
|
2015
|
+
rp_maps.append(h[ii, :])
|
|
2016
|
+
|
|
2017
|
+
if reshape_needed:
|
|
2018
|
+
# Reshape back to 2D if needed
|
|
2019
|
+
rp_maps = [rp_map.reshape(shape_orig) for rp_map in rp_maps]
|
|
1949
2020
|
|
|
1950
2021
|
return rp_maps
|