flood-adapt 1.0.6__tar.gz → 1.1.1__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.
Files changed (150) hide show
  1. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/PKG-INFO +13 -124
  2. flood_adapt-1.1.1/README.md +19 -0
  3. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/__init__.py +1 -2
  4. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/adapter/fiat_adapter.py +12 -7
  5. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/adapter/sfincs_adapter.py +20 -23
  6. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/config/fiat.py +1 -1
  7. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/config/gui.py +185 -8
  8. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/config/hazard.py +1 -1
  9. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/database_builder.py +155 -129
  10. flood_adapt-1.1.1/flood_adapt/database_builder/metrics_utils.py +1834 -0
  11. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/database.py +4 -4
  12. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/dbs_static.py +2 -2
  13. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/flood_adapt.py +65 -14
  14. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/misc/utils.py +29 -10
  15. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/plotting.py +4 -4
  16. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/measures/measures.py +3 -1
  17. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/workflows/benefit_runner.py +3 -2
  18. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt.egg-info/PKG-INFO +13 -124
  19. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt.egg-info/SOURCES.txt +2 -22
  20. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt.egg-info/requires.txt +9 -10
  21. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/pyproject.toml +25 -35
  22. flood_adapt-1.0.6/README.md +0 -130
  23. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infographics/OSM/config_charts.toml +0 -90
  24. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infographics/OSM/config_people.toml +0 -57
  25. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infographics/OSM/config_risk_charts.toml +0 -121
  26. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infographics/OSM/config_roads.toml +0 -65
  27. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infographics/US_NSI/config_charts.toml +0 -126
  28. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infographics/US_NSI/config_people.toml +0 -60
  29. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infographics/US_NSI/config_risk_charts.toml +0 -121
  30. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infographics/US_NSI/config_roads.toml +0 -65
  31. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infographics/US_NSI/styles.css +0 -45
  32. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infometrics/OSM/metrics_additional_risk_configs.toml +0 -4
  33. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config.toml +0 -143
  34. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config_risk.toml +0 -153
  35. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config.toml +0 -127
  36. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config_risk.toml +0 -57
  37. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infometrics/US_NSI/metrics_additional_risk_configs.toml +0 -4
  38. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config.toml +0 -191
  39. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config_risk.toml +0 -153
  40. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config.toml +0 -178
  41. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config_risk.toml +0 -57
  42. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config.toml +0 -9
  43. flood_adapt-1.0.6/flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config_risk.toml +0 -65
  44. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/LICENSE +0 -0
  45. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/adapter/__init__.py +0 -0
  46. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/adapter/interface/__init__.py +0 -0
  47. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/adapter/interface/hazard_adapter.py +0 -0
  48. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/adapter/interface/impact_adapter.py +0 -0
  49. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/adapter/interface/model_adapter.py +0 -0
  50. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/adapter/interface/offshore.py +0 -0
  51. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/adapter/sfincs_offshore.py +0 -0
  52. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/config/__init__.py +0 -0
  53. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/config/config.py +0 -0
  54. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/config/impacts.py +0 -0
  55. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/config/sfincs.py +0 -0
  56. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/config/site.py +0 -0
  57. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/__init__.py +0 -0
  58. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/default_units/imperial.toml +0 -0
  59. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/default_units/metric.toml +0 -0
  60. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/green_infra_table/green_infra_lookup_table.csv +0 -0
  61. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/black_down_48x48.png +0 -0
  62. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/black_left_48x48.png +0 -0
  63. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/black_right_48x48.png +0 -0
  64. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/black_up_48x48.png +0 -0
  65. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_down.png +0 -0
  66. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_left.png +0 -0
  67. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_right.png +0 -0
  68. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_up.png +0 -0
  69. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_down.png +0 -0
  70. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_left.png +0 -0
  71. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_right.png +0 -0
  72. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_up.png +0 -0
  73. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_white_left.png +0 -0
  74. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_white_right.png +0 -0
  75. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/white_down_48x48.png +0 -0
  76. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/white_left_48x48.png +0 -0
  77. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/white_right_48x48.png +0 -0
  78. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/icons/white_up_48x48.png +0 -0
  79. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/infographics/images/ambulance.png +0 -0
  80. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/infographics/images/car.png +0 -0
  81. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/infographics/images/cart.png +0 -0
  82. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/infographics/images/firetruck.png +0 -0
  83. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/infographics/images/hospital.png +0 -0
  84. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/infographics/images/house.png +0 -0
  85. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/infographics/images/info.png +0 -0
  86. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/infographics/images/money.png +0 -0
  87. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/infographics/images/person.png +0 -0
  88. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/infographics/images/school.png +0 -0
  89. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/infographics/images/truck.png +0 -0
  90. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/infographics/images/walking_person.png +0 -0
  91. {flood_adapt-1.0.6/flood_adapt/database_builder/templates/infographics/OSM → flood_adapt-1.1.1/flood_adapt/database_builder/templates/infographics}/styles.css +0 -0
  92. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/database_builder/templates/output_layers/bin_colors.toml +0 -0
  93. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/__init__.py +0 -0
  94. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/dbs_benefit.py +0 -0
  95. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/dbs_event.py +0 -0
  96. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/dbs_measure.py +0 -0
  97. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/dbs_projection.py +0 -0
  98. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/dbs_scenario.py +0 -0
  99. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/dbs_strategy.py +0 -0
  100. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/dbs_template.py +0 -0
  101. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/interface/database.py +0 -0
  102. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/interface/element.py +0 -0
  103. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/dbs_classes/interface/static.py +0 -0
  104. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/misc/__init__.py +0 -0
  105. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/misc/database_user.py +0 -0
  106. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/misc/debug_timer.py +0 -0
  107. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/misc/exceptions.py +0 -0
  108. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/misc/log.py +0 -0
  109. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/misc/path_builder.py +0 -0
  110. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/__init__.py +0 -0
  111. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/benefits/__init__.py +0 -0
  112. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/benefits/benefits.py +0 -0
  113. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/events/__init__.py +0 -0
  114. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/events/event_factory.py +0 -0
  115. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/events/event_set.py +0 -0
  116. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/events/events.py +0 -0
  117. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/events/historical.py +0 -0
  118. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/events/hurricane.py +0 -0
  119. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/events/synthetic.py +0 -0
  120. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/__init__.py +0 -0
  121. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/csv.py +0 -0
  122. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/discharge.py +0 -0
  123. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/forcing.py +0 -0
  124. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/forcing_factory.py +0 -0
  125. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/meteo_handler.py +0 -0
  126. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/netcdf.py +0 -0
  127. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/rainfall.py +0 -0
  128. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/tide_gauge.py +0 -0
  129. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/time_frame.py +0 -0
  130. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/timeseries.py +0 -0
  131. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/unit_system.py +0 -0
  132. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/waterlevels.py +0 -0
  133. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/forcing/wind.py +0 -0
  134. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/measures/__init__.py +0 -0
  135. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/measures/measure_factory.py +0 -0
  136. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/object_model.py +0 -0
  137. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/output/floodmap.py +0 -0
  138. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/projections/__init__.py +0 -0
  139. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/projections/projections.py +0 -0
  140. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/scenarios/__init__.py +0 -0
  141. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/scenarios/scenarios.py +0 -0
  142. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/strategies/__init__.py +0 -0
  143. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/objects/strategies/strategies.py +0 -0
  144. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/workflows/__init__.py +0 -0
  145. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt/workflows/scenario_runner.py +0 -0
  146. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt.egg-info/dependency_links.txt +0 -0
  147. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt.egg-info/not-zip-safe +0 -0
  148. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/flood_adapt.egg-info/top_level.txt +0 -0
  149. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/setup.cfg +0 -0
  150. {flood_adapt-1.0.6 → flood_adapt-1.1.1}/tests/test_flood_adapt.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: flood-adapt
3
- Version: 1.0.6
3
+ Version: 1.1.1
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: ====================================================
@@ -705,19 +705,21 @@ Project-URL: Source, https://github.com/Deltares-research/FloodAdapt
705
705
  Classifier: Intended Audience :: Science/Research
706
706
  Classifier: License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
707
707
  Classifier: Topic :: Scientific/Engineering :: Hydrology
708
- Requires-Python: <3.13,>=3.8
708
+ Requires-Python: <3.13,>=3.10
709
709
  Description-Content-Type: text/markdown
710
710
  License-File: LICENSE
711
- Requires-Dist: cht-cyclones==1.0.3
712
- Requires-Dist: cht-meteo==0.3.1
713
- Requires-Dist: cht-observations==0.2.1
714
- Requires-Dist: cht-tide==0.1.1
715
- Requires-Dist: fiat-toolbox==0.1.20
711
+ Requires-Dist: cht-cyclones<2.0,>=1.0.3
712
+ Requires-Dist: cht-meteo<1.0,>=0.3.1
713
+ Requires-Dist: cht-observations<1.0,>=0.2.1
714
+ Requires-Dist: cht-tide<1.0,>=0.1.1
715
+ Requires-Dist: dask==2024.11.2
716
+ Requires-Dist: numba_celltree==0.2.2
717
+ Requires-Dist: fiat-toolbox<0.2.0,>=0.1.22
716
718
  Requires-Dist: fiona<2.0,>=1.0
717
719
  Requires-Dist: geojson<4.0,>=3.0
718
720
  Requires-Dist: geopandas<2.0,>=1.0
719
- Requires-Dist: hydromt-fiat<1.0,>=0.5.5
720
- Requires-Dist: hydromt-sfincs[quadtree]<2.0,>=1.2.2
721
+ Requires-Dist: hydromt-fiat<1.0,>=0.5.9
722
+ Requires-Dist: hydromt-sfincs<2.0,>=1.2.0
721
723
  Requires-Dist: numpy<2.0,>=1.0
722
724
  Requires-Dist: numpy-financial<2.0,>=1.0
723
725
  Requires-Dist: pandas<3.0,>=2.0
@@ -753,8 +755,6 @@ Requires-Dist: python-dotenv<2.0,>=1.0; extra == "docs"
753
755
  Requires-Dist: folium<1.0,>=0.19.0; extra == "docs"
754
756
  Requires-Dist: mapclassify<3.0,>=2.8.0; extra == "docs"
755
757
  Requires-Dist: contextily; extra == "docs"
756
- Provides-Extra: all
757
- Requires-Dist: flood-adapt[build,dev,docs]; extra == "all"
758
758
 
759
759
  # FloodAdapt
760
760
  FloodAdapt is a decision-support tool that seeks to advance and accelerate flooding-related adaptation planning. It brings rapid, physics-based compound flood and detailed impact modelling into an easy-to-use system, allowing non-expert end-users to evaluate a wide variety of compound events, future conditions, and adaptation options in minutes. FloodAdapt serves as a connector between scientific advances and practitioner needs, improving and increasing the uptake and impact of adaptation research and development.
@@ -772,117 +772,6 @@ Recent developments of the decision-support system include (1) simplifying and p
772
772
 
773
773
  FloodAdapt is currently in an intensive development stage. Independent usage of the repository will be challenging prior to end-of-year 2024. FloodAdapt documentation will be expanded on throughout 2024.
774
774
 
775
- # Installation
775
+ # Getting Started
776
776
 
777
- ## Setting up Pixi
778
- To build the environment, manage dependencies and run tasks, FloodAdapt uses [Pixi](https://pixi.sh/latest/), please download and install it by following the instructions on the pixi website.
779
-
780
- Before continuing the installation process, make sure you have access to all required private repositories by ensuring you are in the Teams `FloodAdaptUsers` in the [Deltares](https://github.com/orgs/Deltares/teams/floodadaptusers) and [Deltares-research](https://github.com/orgs/Deltares-research/teams/floodadaptusers) organizations.
781
-
782
- ## Windows
783
- Then run these commands to install FloodAdapt:
784
- ```bash
785
- git clone https://github.com/Deltares-research/FloodAdapt.git
786
- cd FloodAdapt
787
- pixi install
788
- ```
789
- ## Linux
790
- Linux is not supported at the moment, but will be supported in the near future.
791
-
792
- ## Configure database
793
-
794
- #### TODO add section for the DatabaseBuilder.
795
-
796
- FloodAdapt uses a database to store, handle and organize input files, output files and static data. This database needs to be configured the first time you want to use FloodAdapt. Which is done via `flood_adapt/misc/config.py` which contains the `Settings` class to set and validate environment variables, specific to your system.
797
-
798
- To initialize FloodAdapt and configure the database, add the following lines to the top of your script / initialize function to validate and set the environment variables:
799
- ```python
800
- from pathlib import Path
801
- from flood_adapt import Settings
802
-
803
- # Usually ends in `Database` and can contain multiple sites
804
- root = Path("path/to/your/database/root")
805
-
806
- # Specifies which site to use
807
- name = "database_name"
808
-
809
- # Define the paths to the model kernel binaries
810
- sfincs_bin = Path("path/to/your/sfincs/bin.exe")
811
- fiat_bin = Path("path/to/your/fiat/bin.exe")
812
-
813
- # Validate and set environment variables
814
- Settings(
815
- DATABASE_ROOT=root,
816
- DATABASE_NAME=name,
817
- SFINCS_BIN_PATH=sfincs_bin,
818
- FIAT_BIN_PATH=fiat_path,
819
- VALIDATE_BINARIES=True,
820
- )
821
- ```
822
-
823
- ## Developing FloodAdapt
824
-
825
- To contribute to FloodAdapt, you will need to install additional dependencies. To do so, clone the repository and install the development environment:
826
-
827
- ```bash
828
- # Install dev environment
829
- git clone https://github.com/Deltares/FloodAdapt
830
- cd FloodAdapt
831
-
832
- # This will install the required environment and run the tests to verify
833
- pixi run tests
834
- ```
835
-
836
- Alternatively, you can open an interactive shell and have pixi take care of activating and updating your environment.
837
- ```bash
838
- # `activate` the dev environment
839
- pixi shell -e dev
840
-
841
- # Develop
842
- pytest tests/test_x/test_y/test_z.py
843
- python scripts/my_script.py
844
- ...
845
- ```
846
-
847
- ### Adding editable installations to your environment
848
-
849
- To make developing easier and not have to reinstall packages after every change, editable installs exist.
850
- Pixi supports editable installs, but not in the most intuitive way, as they need to be defined as editable in the project specification.
851
-
852
- Example command to add the package `example_package` as an editable install to the default environment:
853
- - go to the non-pixi sections in `pyproject.toml` and comment out the `example_package`. (`[dependencies]` or `[optional-dependencies]`)
854
- - in the pixi section `[tool.pixi.pypi-dependencies]`: add the following line `example_package = {path = "./path/to/example_package", editable = true }`. Note that this path is relative to the root of this project.
855
- - run `pixi update`
856
-
857
- ## Useful pixi commands
858
- ```bash
859
- # Display all pixi commands and options
860
- pixi -h
861
-
862
- # Install a non default pixi environment defined in pyproject.toml
863
- pixi install -e [ENV_NAME]
864
-
865
- # Update environment(s) to the latest allowed by dependency specifications in pyproject.toml
866
- pixi update
867
-
868
- # List all available tasks
869
- pixi task list
870
-
871
- # Run a task in the default environment for that task
872
- pixi run [TASK]
873
-
874
- # Start a shell in the pixi environment
875
- pixi shell -e [ENV_NAME]
876
-
877
- # Add a package to the dependencies
878
- pixi add [PACKAGE]
879
-
880
- # Run a task in a specific environment
881
- pixi run -e [ENV_NAME] [TASK]
882
- ```
883
-
884
- ### Generating the documentation
885
-
886
- We use `quartodoc` to generate our API documentation automatically. If you have the `docs` optional dependency group installed.
887
- you can do this by running `quartodoc build` from the `docs` directory, and it will create the documentation for you.
888
- After this is done, if you wish, you can build and view the documentation locally by running `quarto preview` from the `docs` directory
777
+ Please review our [`developer guide`](DEVELOPER_GUIDE.md) for information on how to install and use FloodAdapt locally.
@@ -0,0 +1,19 @@
1
+ # FloodAdapt
2
+ FloodAdapt is a decision-support tool that seeks to advance and accelerate flooding-related adaptation planning. It brings rapid, physics-based compound flood and detailed impact modelling into an easy-to-use system, allowing non-expert end-users to evaluate a wide variety of compound events, future conditions, and adaptation options in minutes. FloodAdapt serves as a connector between scientific advances and practitioner needs, improving and increasing the uptake and impact of adaptation research and development.
3
+
4
+ To make decisions on flood adaptation, communities need to understand how climate and socio-economic changes will affect flood risk and the risk-reduction potential of various adaptation options. This type of information is usually costly to acquire, and models are often too slow and labor-intensive to evaluate all the scenarios required to understand the impacts and effectiveness of potential adaptation decisions. FloodAdapt addresses this by making rapid, physics-based compound flood modeling and detailed impact modeling accessible to non-expert end-users, allowing them to evaluate a wide variety of compound events, future conditions, and adaptation options in minutes.
5
+
6
+ FloodAdapt was developed as a rapid planning tool with a straightforward graphical user interface for scenario generation, simulation, and visualization of spatial flooding and flooding impacts. Decision-making needs at the community level were central to the design of FloodAdapt. Users can answer planning questions like: “How will potential adaptation options reduce flood impacts?”, “How will those options perform for different types of events, like hurricanes, king tides, or heavy rainfall?”, “Which neighborhoods will benefit most?”, “How will those options hold up in the future?”
7
+
8
+ Users specify what-if scenarios composed of historic or synthetic weather events, climate or socio-economic future projections, and adaptation measures.
9
+ The backend of FloodAdapt leverages the open-source, state-of-the-art process-based compound flood model SFINCS (https://github.com/Deltares/SFINCS) that can accurately predict compound flooding due to surge, rainfall, and river discharge, at a fraction of the computation time typically required by physics-based models. The damage model included in FloodAdapt is the Deltares-developed flood impact assessment tool Delft-FIAT (https://github.com/Deltares/Delft-FIAT). It calculates the flood damages to individual buildings and roads, and – when social vulnerability data is available – aggregates these damages over vulnerability classes.
10
+
11
+ FloodAdapt can greatly support adaptation planning by allowing users to explore many scenarios. It can be used to evaluate flooding and impacts due to compound weather events, like hurricanes, king tides, and rainfall events. Users can evaluate flooding, impacts, and risk considering user-specified projections of sea level rise, precipitation increase, storm frequency increase, population growth, and economic growth. Users can also test out adaptation options, like sea walls, levees, pumps, home elevations, buyouts and floodproofing.
12
+
13
+ Recent developments of the decision-support system include (1) simplifying and partially automating the setup of the SFINCS and Delft-FIAT models, (2) improving the user experience, (3) better supporting adaptation planning with improvements like metrics tables, infographics, better visualizations in the user interface, adding in additional adaptation options to evaluate, and calculating benefits of adaptation options, and (4) incorporating social vulnerability and equity into the evaluation of adaptation options to support equitable adaptation planning.
14
+
15
+ FloodAdapt is currently in an intensive development stage. Independent usage of the repository will be challenging prior to end-of-year 2024. FloodAdapt documentation will be expanded on throughout 2024.
16
+
17
+ # Getting Started
18
+
19
+ Please review our [`developer guide`](DEVELOPER_GUIDE.md) for information on how to install and use FloodAdapt locally.
@@ -1,6 +1,5 @@
1
1
  # has to be here at the start to avoid circular imports
2
-
3
- __version__ = "1.0.6"
2
+ __version__ = "1.1.1"
4
3
 
5
4
  from flood_adapt import adapter, database_builder, dbs_classes, objects
6
5
  from flood_adapt.config.config import Settings
@@ -106,7 +106,7 @@ class FiatAdapter(IImpactAdapter):
106
106
  self.config_base_path = config_base_path
107
107
  self.exe_path = exe_path
108
108
  self.delete_crashed_runs = delete_crashed_runs
109
- self._model_root = str(model_root.resolve())
109
+ self._model_root = model_root.resolve().as_posix()
110
110
  self.fiat_columns = _FIAT_COLUMNS
111
111
  self.impact_columns = _IMPACT_COLUMNS # columns of FA impact output
112
112
 
@@ -135,7 +135,7 @@ class FiatAdapter(IImpactAdapter):
135
135
  def read(self, path: Path) -> None:
136
136
  """Read the fiat model from the current model root."""
137
137
  if Path(self.model.root).resolve() != Path(path).resolve():
138
- self.model.set_root(root=str(path), mode="r")
138
+ self.model.set_root(root=path.as_posix(), mode="r")
139
139
  self.model.read()
140
140
 
141
141
  def write(self, path_out: Union[str, os.PathLike], overwrite: bool = True) -> None:
@@ -148,7 +148,7 @@ class FiatAdapter(IImpactAdapter):
148
148
 
149
149
  write_mode = "w+" if overwrite else "w"
150
150
  with cd(path_out):
151
- self.model.set_root(root=str(path_out), mode=write_mode)
151
+ self.model.set_root(root=path_out.as_posix(), mode=write_mode)
152
152
  self.model.write()
153
153
 
154
154
  def close_files(self):
@@ -717,8 +717,8 @@ class FiatAdapter(IImpactAdapter):
717
717
  conversion_factor = wl_current_units.convert(self.model.exposure.unit)
718
718
 
719
719
  self.model.setup_hazard(
720
- map_fn=map_fn,
721
- map_type=map_type,
720
+ map_fn=[Path(p).as_posix() for p in map_fn],
721
+ map_type=map_type.value,
722
722
  rp=None,
723
723
  crs=None, # change this in new version (maybe to str(floodmap.crs.split(':')[1]))
724
724
  nodata=-999, # change this in new version
@@ -1160,7 +1160,7 @@ class FiatAdapter(IImpactAdapter):
1160
1160
  object_dir=ObjectDir.measure,
1161
1161
  obj_name=measure.name,
1162
1162
  path=measure.polygon_file,
1163
- )
1163
+ ).as_posix()
1164
1164
  else:
1165
1165
  polygon_file = None
1166
1166
 
@@ -1171,7 +1171,7 @@ class FiatAdapter(IImpactAdapter):
1171
1171
  non_building_names=self.config.non_building_names,
1172
1172
  aggregation=measure.aggregation_area_type,
1173
1173
  aggregation_area_name=measure.aggregation_area_name,
1174
- polygon_file=str(polygon_file),
1174
+ polygon_file=polygon_file,
1175
1175
  )
1176
1176
 
1177
1177
  return ids
@@ -1365,6 +1365,11 @@ class FiatAdapter(IImpactAdapter):
1365
1365
  True,
1366
1366
  True,
1367
1367
  ]
1368
+ metrics_new.loc["Show In Metrics Map", ["EW", "EWEAD", "EWCEAD"]] = [
1369
+ False,
1370
+ True,
1371
+ False,
1372
+ ]
1368
1373
  metrics_new.loc["Long Name", ["EW", "EWEAD", "EWCEAD"]] = [
1369
1374
  "Equity weight",
1370
1375
  "Equity weighted expected annual damage",
@@ -121,7 +121,7 @@ class SfincsAdapter(IHazardAdapter):
121
121
  self.settings = self.database.site.sfincs
122
122
  self.units = self.database.site.gui.units
123
123
  self._model = HydromtSfincsModel(
124
- root=str(model_root.resolve()),
124
+ root=model_root.resolve().as_posix(),
125
125
  mode="r",
126
126
  logger=self._setup_sfincs_logger(model_root),
127
127
  )
@@ -130,7 +130,7 @@ class SfincsAdapter(IHazardAdapter):
130
130
  def read(self, path: Path):
131
131
  """Read the sfincs model from the current model root."""
132
132
  if Path(self._model.root).resolve() != Path(path).resolve():
133
- self._model.set_root(root=str(path), mode="r")
133
+ self._model.set_root(root=path.as_posix(), mode="r")
134
134
  self._model.read()
135
135
 
136
136
  def write(self, path_out: Union[str, os.PathLike], overwrite: bool = True):
@@ -147,7 +147,7 @@ class SfincsAdapter(IHazardAdapter):
147
147
 
148
148
  write_mode = "w+" if overwrite else "w"
149
149
  with cd(path_out):
150
- self._model.set_root(root=str(path_out), mode=write_mode)
150
+ self._model.set_root(root=path_out.as_posix(), mode=write_mode)
151
151
  self._model.write()
152
152
 
153
153
  def close_files(self):
@@ -190,10 +190,16 @@ class SfincsAdapter(IHazardAdapter):
190
190
  True if the model ran successfully, False otherwise.
191
191
 
192
192
  """
193
+ sfincs_bin = Settings().sfincs_bin_path
194
+ if not sfincs_bin or not sfincs_bin.exists():
195
+ raise FileNotFoundError(
196
+ f"SFINCS binary not found at {sfincs_bin}. Please check your settings."
197
+ )
198
+
193
199
  with cd(path):
194
200
  logger.info(f"Running SFINCS in {path}")
195
201
  process = subprocess.run(
196
- str(Settings().sfincs_bin_path),
202
+ sfincs_bin.as_posix(),
197
203
  stdout=subprocess.PIPE,
198
204
  stderr=subprocess.PIPE,
199
205
  text=True,
@@ -563,7 +569,7 @@ class SfincsAdapter(IHazardAdapter):
563
569
  zsmax=floodmap_conversion * zsmax,
564
570
  dep=dem_conversion * dem,
565
571
  hmin=0.01,
566
- floodmap_fn=str(floodmap_fn),
572
+ floodmap_fn=floodmap_fn.as_posix(),
567
573
  )
568
574
 
569
575
  def write_water_level_map(
@@ -803,7 +809,7 @@ class SfincsAdapter(IHazardAdapter):
803
809
  zsmax=floodmap_conversion * zsmax,
804
810
  dep=dem_conversion * dem,
805
811
  hmin=0.01,
806
- floodmap_fn=str(floodmap_fn),
812
+ floodmap_fn=floodmap_fn.as_posix(),
807
813
  )
808
814
 
809
815
  ######################################
@@ -1304,14 +1310,10 @@ class SfincsAdapter(IHazardAdapter):
1304
1310
  )
1305
1311
  return
1306
1312
 
1307
- model_rivers = self._read_river_locations()
1308
- if model_rivers.empty:
1309
- logger.warning(
1310
- "Cannot add discharge forcing: No rivers defined in the sfincs model."
1311
- )
1312
- return
1313
1313
  logger.info(f"Setting discharge forcing for river: {discharge.river.name}")
1314
+
1314
1315
  time_frame = self.get_model_time()
1316
+ model_rivers = self._read_river_locations()
1315
1317
 
1316
1318
  # Check that the river is defined in the model and that the coordinates match
1317
1319
  river_loc = shapely.Point(
@@ -1630,7 +1632,7 @@ class SfincsAdapter(IHazardAdapter):
1630
1632
 
1631
1633
  # Initialize the tropical cyclone
1632
1634
  tc = TropicalCyclone()
1633
- tc.read_track(filename=str(track_forcing.path), fmt="ddb_cyc")
1635
+ tc.read_track(filename=track_forcing.path.as_posix(), fmt="ddb_cyc")
1634
1636
 
1635
1637
  # Alter the track of the tc if necessary
1636
1638
  tc = self._translate_tc_track(
@@ -1709,22 +1711,17 @@ class SfincsAdapter(IHazardAdapter):
1709
1711
 
1710
1712
  def _read_river_locations(self) -> gpd.GeoDataFrame:
1711
1713
  path = self.get_model_root() / "sfincs.src"
1712
- lines = []
1713
- if path.exists():
1714
- with open(path) as f:
1715
- lines = f.readlines()
1714
+
1715
+ with open(path) as f:
1716
+ lines = f.readlines()
1716
1717
  coords = [(float(line.split()[0]), float(line.split()[1])) for line in lines]
1717
1718
  points = [shapely.Point(coord) for coord in coords]
1718
1719
 
1719
1720
  return gpd.GeoDataFrame({"geometry": points}, crs=self._model.crs)
1720
1721
 
1721
1722
  def _read_waterlevel_boundary_locations(self) -> gpd.GeoDataFrame:
1722
- path = self.get_model_root() / "sfincs.bnd"
1723
- lines = []
1724
- if path.exists():
1725
- with open(path) as f:
1726
- lines = f.readlines()
1727
-
1723
+ with open(self.get_model_root() / "sfincs.bnd") as f:
1724
+ lines = f.readlines()
1728
1725
  coords = [(float(line.split()[0]), float(line.split()[1])) for line in lines]
1729
1726
  points = [shapely.Point(coord) for coord in coords]
1730
1727
 
@@ -87,7 +87,7 @@ class FiatModel(BaseModel):
87
87
  config: FiatConfigModel
88
88
 
89
89
  benefits: Optional[BenefitsModel] = None
90
- risk: Optional[RiskModel] = RiskModel()
90
+ risk: RiskModel = RiskModel()
91
91
 
92
92
  @staticmethod
93
93
  def read_toml(path: Path) -> "FiatModel":
@@ -1,5 +1,7 @@
1
+ import re
2
+ from enum import Enum
1
3
  from pathlib import Path
2
- from typing import Optional
4
+ from typing import Any, Literal, Optional, Union
3
5
 
4
6
  import geopandas as gpd
5
7
  import numpy as np
@@ -25,6 +27,7 @@ class Layer(BaseModel):
25
27
 
26
28
  bins: list[float]
27
29
  colors: list[str]
30
+ decimals: Optional[int] = 0
28
31
 
29
32
  @model_validator(mode="after")
30
33
  def check_bins_and_colors(self) -> "Layer":
@@ -42,20 +45,118 @@ class FloodMapLayer(Layer):
42
45
  roads_min_zoom_level: int = 14
43
46
 
44
47
 
45
- class AggregationDmgLayer(Layer):
46
- damage_decimals: Optional[int] = 0
47
-
48
-
49
48
  class FootprintsDmgLayer(Layer):
50
49
  type: DamageType = DamageType.absolute
51
- damage_decimals: Optional[int] = 0
52
- buildings_min_zoom_level: int = 13
53
50
 
54
51
 
55
52
  class BenefitsLayer(Layer):
56
53
  threshold: Optional[float] = None
57
54
 
58
55
 
56
+ class LogicalOperator(str, Enum):
57
+ AND = "and"
58
+ OR = "or"
59
+
60
+
61
+ class FieldName(str, Enum):
62
+ """Enum for valid field names with mapping to dictionary keys."""
63
+
64
+ NAME = "name"
65
+ LONG_NAME = "long_name"
66
+ DESCRIPTION = "description"
67
+
68
+ @property
69
+ def dict_key(self) -> str:
70
+ """Get the actual dictionary key for this field name."""
71
+ mapping = {
72
+ "name": "name",
73
+ "long_name": "Long Name",
74
+ "description": "Description",
75
+ }
76
+ return mapping[self.value]
77
+
78
+
79
+ class FilterCondition(BaseModel):
80
+ """A single filter condition."""
81
+
82
+ field_name: FieldName
83
+ values: list[Any]
84
+ operator: LogicalOperator = (
85
+ LogicalOperator.OR
86
+ ) # How to combine values within this condition
87
+
88
+
89
+ class FilterGroup(BaseModel):
90
+ """A group of filter conditions with logical operators."""
91
+
92
+ conditions: list[FilterCondition]
93
+ operator: LogicalOperator = (
94
+ LogicalOperator.OR
95
+ ) # How to combine conditions within this group
96
+
97
+
98
+ class MetricLayer(Layer):
99
+ type: str
100
+ # Simplified: just a single FilterGroup or FilterCondition
101
+ filters: Union[FilterGroup, FilterCondition] = Field(
102
+ default_factory=lambda: FilterGroup(conditions=[])
103
+ )
104
+
105
+ def matches(self, data_dict: dict) -> bool:
106
+ """Check if the given data dictionary matches the filter criteria."""
107
+ if isinstance(self.filters, FilterCondition):
108
+ return self._evaluate_condition(self.filters, data_dict)
109
+ else: # FilterGroup
110
+ return self._evaluate_filter_group(self.filters, data_dict)
111
+
112
+ def _evaluate_filter_group(self, group: FilterGroup, data_dict: dict) -> bool:
113
+ """Evaluate a single filter group."""
114
+ if not group.conditions:
115
+ return True
116
+
117
+ condition_results = []
118
+ for condition in group.conditions:
119
+ condition_results.append(self._evaluate_condition(condition, data_dict))
120
+
121
+ if group.operator == LogicalOperator.AND:
122
+ return all(condition_results)
123
+ else: # OR
124
+ return any(condition_results)
125
+
126
+ def _evaluate_condition(self, condition: FilterCondition, data_dict: dict) -> bool:
127
+ """Evaluate a single condition."""
128
+ # Use the dict_key property to get the actual dictionary key
129
+ field_value = data_dict.get(condition.field_name.dict_key)
130
+ if field_value is None:
131
+ return False
132
+
133
+ value_matches = [value in field_value for value in condition.values] # noqa: PD011
134
+
135
+ if condition.operator == LogicalOperator.AND:
136
+ return all(value_matches)
137
+ else: # OR
138
+ return any(value_matches)
139
+
140
+
141
+ class AggregationDmgLayer(MetricLayer):
142
+ type: str = "damage"
143
+ filters: FilterGroup = Field(
144
+ default_factory=lambda: FilterGroup(
145
+ conditions=[
146
+ FilterCondition(
147
+ field_name=FieldName.NAME,
148
+ values=[
149
+ "TotalDamageEvent",
150
+ "ExpectedAnnualDamages",
151
+ "TotalDamageRP",
152
+ "EWEAD",
153
+ ],
154
+ )
155
+ ]
156
+ )
157
+ )
158
+
159
+
59
160
  class OutputLayers(BaseModel):
60
161
  """The configuration of the mapbox layers in the gui.
61
162
 
@@ -75,9 +176,84 @@ class OutputLayers(BaseModel):
75
176
  floodmap: FloodMapLayer
76
177
  aggregation_dmg: AggregationDmgLayer
77
178
  footprints_dmg: FootprintsDmgLayer
78
-
179
+ aggregated_metrics: list[MetricLayer] = Field(default_factory=list)
79
180
  benefits: Optional[BenefitsLayer] = None
80
181
 
182
+ def get_aggr_metrics_layers(
183
+ self,
184
+ metrics: list[dict],
185
+ type: Literal["single_event", "risk"] = "single_event",
186
+ rp: Optional[int] = None,
187
+ equity: bool = False,
188
+ ):
189
+ layer_types = [self.aggregation_dmg] + self.aggregated_metrics
190
+ filtered_input_metrics = self._filter_metrics(metrics, type, rp, equity)
191
+ return self._match_metrics_to_layers(filtered_input_metrics, layer_types)
192
+
193
+ def _should_skip_metric(
194
+ self, metric_name: str, rp: Optional[int], equity: bool
195
+ ) -> bool:
196
+ rp_match = re.search(r"RP(\d+)", metric_name)
197
+ y_match = re.search(r"(\d+)Y", metric_name)
198
+ name_match = rp_match or y_match
199
+
200
+ if rp is None:
201
+ if name_match:
202
+ return True
203
+ if not equity and "EW" in metric_name:
204
+ return True
205
+ if equity and "EW" not in metric_name:
206
+ return True
207
+ return False
208
+
209
+ def _process_metric_name(
210
+ self, metric_name: str, rp: Optional[int]
211
+ ) -> tuple[str, bool]:
212
+ rp_match = re.search(r"RP(\d+)", metric_name)
213
+ y_match = re.search(r"(\d+)Y", metric_name)
214
+ name_match = rp_match or y_match
215
+ if rp is not None:
216
+ if name_match:
217
+ extracted_rp = int(name_match.group(1))
218
+ name_check = extracted_rp == int(rp)
219
+ cleaned_name = re.sub(r"(RP\d+|\d+Y)", "", metric_name)
220
+ return cleaned_name.rstrip("_"), name_check
221
+ else:
222
+ return metric_name, False
223
+ return metric_name, True
224
+
225
+ def _filter_metrics(self, metrics, type, rp, equity):
226
+ filtered = []
227
+ for metric in metrics:
228
+ metric_name = metric.get("name", "")
229
+ metric["name_to_show"] = metric_name
230
+ if type == "risk":
231
+ if self._should_skip_metric(metric_name, rp, equity):
232
+ continue
233
+ metric["name_to_show"], name_check = self._process_metric_name(
234
+ metric_name, rp
235
+ )
236
+ if rp is not None and not name_check:
237
+ continue
238
+ filtered.append(metric)
239
+ return filtered
240
+
241
+ def _match_metrics_to_layers(self, metrics, layer_types):
242
+ filtered_metrics = []
243
+ for metric in metrics:
244
+ for layer in layer_types:
245
+ if layer.matches(metric):
246
+ filtered_metrics.append(
247
+ {
248
+ "metric": metric,
249
+ "bins": getattr(layer, "bins", None),
250
+ "colors": getattr(layer, "colors", None),
251
+ "decimals": getattr(layer, "decimals", None),
252
+ }
253
+ )
254
+ break
255
+ return filtered_metrics
256
+
81
257
 
82
258
  class VisualizationLayer(Layer):
83
259
  """The configuration of a layer to visualize in the gui.
@@ -157,6 +333,7 @@ class VisualizationLayers(BaseModel):
157
333
  The layers to visualize.
158
334
  """
159
335
 
336
+ buildings_min_zoom_level: int = 13
160
337
  layers: list[VisualizationLayer] = Field(default_factory=list)
161
338
 
162
339
  def add_layer(
@@ -341,7 +341,7 @@ class SlrScenariosModel(BaseModel):
341
341
  # write html to results folder
342
342
  output_loc.parent.mkdir(parents=True, exist_ok=True)
343
343
  fig.write_html(output_loc)
344
- return str(output_loc)
344
+ return output_loc.as_posix()
345
345
 
346
346
 
347
347
  class FloodModel(BaseModel):