flood-adapt 1.0.4__tar.gz → 1.1.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.
Files changed (150) hide show
  1. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/PKG-INFO +3 -3
  2. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/__init__.py +2 -3
  3. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/adapter/fiat_adapter.py +8 -3
  4. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/adapter/sfincs_adapter.py +2 -2
  5. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/adapter/sfincs_offshore.py +1 -1
  6. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/config/fiat.py +1 -1
  7. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/config/gui.py +185 -8
  8. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/database_builder.py +155 -129
  9. flood_adapt-1.1.0/flood_adapt/database_builder/metrics_utils.py +1834 -0
  10. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/database.py +23 -28
  11. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/dbs_benefit.py +0 -26
  12. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/dbs_event.py +2 -2
  13. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/dbs_measure.py +2 -2
  14. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/dbs_scenario.py +0 -24
  15. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/dbs_static.py +4 -4
  16. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/dbs_strategy.py +2 -4
  17. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/dbs_template.py +65 -25
  18. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/flood_adapt.py +63 -12
  19. flood_adapt-1.1.0/flood_adapt/misc/exceptions.py +59 -0
  20. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt.egg-info/PKG-INFO +3 -3
  21. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt.egg-info/SOURCES.txt +2 -22
  22. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt.egg-info/requires.txt +2 -2
  23. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/pyproject.toml +2 -2
  24. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/tests/test_flood_adapt.py +25 -20
  25. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infographics/OSM/config_charts.toml +0 -90
  26. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infographics/OSM/config_people.toml +0 -57
  27. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infographics/OSM/config_risk_charts.toml +0 -121
  28. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infographics/OSM/config_roads.toml +0 -65
  29. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infographics/US_NSI/config_charts.toml +0 -126
  30. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infographics/US_NSI/config_people.toml +0 -60
  31. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infographics/US_NSI/config_risk_charts.toml +0 -121
  32. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infographics/US_NSI/config_roads.toml +0 -65
  33. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infographics/US_NSI/styles.css +0 -45
  34. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infometrics/OSM/metrics_additional_risk_configs.toml +0 -4
  35. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config.toml +0 -143
  36. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config_risk.toml +0 -153
  37. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config.toml +0 -127
  38. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config_risk.toml +0 -57
  39. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infometrics/US_NSI/metrics_additional_risk_configs.toml +0 -4
  40. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config.toml +0 -191
  41. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config_risk.toml +0 -153
  42. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config.toml +0 -178
  43. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config_risk.toml +0 -57
  44. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config.toml +0 -9
  45. flood_adapt-1.0.4/flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config_risk.toml +0 -65
  46. flood_adapt-1.0.4/flood_adapt/misc/exceptions.py +0 -22
  47. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/LICENSE +0 -0
  48. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/README.md +0 -0
  49. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/adapter/__init__.py +0 -0
  50. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/adapter/interface/__init__.py +0 -0
  51. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/adapter/interface/hazard_adapter.py +0 -0
  52. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/adapter/interface/impact_adapter.py +0 -0
  53. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/adapter/interface/model_adapter.py +0 -0
  54. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/adapter/interface/offshore.py +0 -0
  55. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/config/__init__.py +0 -0
  56. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/config/config.py +0 -0
  57. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/config/hazard.py +0 -0
  58. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/config/impacts.py +0 -0
  59. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/config/sfincs.py +0 -0
  60. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/config/site.py +0 -0
  61. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/__init__.py +0 -0
  62. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/default_units/imperial.toml +0 -0
  63. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/default_units/metric.toml +0 -0
  64. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/green_infra_table/green_infra_lookup_table.csv +0 -0
  65. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/black_down_48x48.png +0 -0
  66. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/black_left_48x48.png +0 -0
  67. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/black_right_48x48.png +0 -0
  68. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/black_up_48x48.png +0 -0
  69. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_down.png +0 -0
  70. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_left.png +0 -0
  71. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_right.png +0 -0
  72. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-16_white_up.png +0 -0
  73. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_down.png +0 -0
  74. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_left.png +0 -0
  75. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_right.png +0 -0
  76. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_black_up.png +0 -0
  77. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_white_left.png +0 -0
  78. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/icons8-triangle-arrow-24_white_right.png +0 -0
  79. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/white_down_48x48.png +0 -0
  80. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/white_left_48x48.png +0 -0
  81. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/white_right_48x48.png +0 -0
  82. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/icons/white_up_48x48.png +0 -0
  83. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/infographics/images/ambulance.png +0 -0
  84. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/infographics/images/car.png +0 -0
  85. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/infographics/images/cart.png +0 -0
  86. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/infographics/images/firetruck.png +0 -0
  87. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/infographics/images/hospital.png +0 -0
  88. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/infographics/images/house.png +0 -0
  89. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/infographics/images/info.png +0 -0
  90. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/infographics/images/money.png +0 -0
  91. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/infographics/images/person.png +0 -0
  92. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/infographics/images/school.png +0 -0
  93. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/infographics/images/truck.png +0 -0
  94. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/infographics/images/walking_person.png +0 -0
  95. {flood_adapt-1.0.4/flood_adapt/database_builder/templates/infographics/OSM → flood_adapt-1.1.0/flood_adapt/database_builder/templates/infographics}/styles.css +0 -0
  96. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/database_builder/templates/output_layers/bin_colors.toml +0 -0
  97. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/__init__.py +0 -0
  98. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/dbs_projection.py +0 -0
  99. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/interface/database.py +0 -0
  100. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/interface/element.py +0 -0
  101. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/dbs_classes/interface/static.py +0 -0
  102. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/misc/__init__.py +0 -0
  103. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/misc/database_user.py +0 -0
  104. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/misc/debug_timer.py +0 -0
  105. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/misc/log.py +0 -0
  106. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/misc/path_builder.py +0 -0
  107. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/misc/utils.py +0 -0
  108. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/__init__.py +0 -0
  109. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/benefits/__init__.py +0 -0
  110. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/benefits/benefits.py +0 -0
  111. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/events/__init__.py +0 -0
  112. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/events/event_factory.py +0 -0
  113. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/events/event_set.py +0 -0
  114. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/events/events.py +0 -0
  115. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/events/historical.py +0 -0
  116. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/events/hurricane.py +0 -0
  117. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/events/synthetic.py +0 -0
  118. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/__init__.py +0 -0
  119. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/csv.py +0 -0
  120. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/discharge.py +0 -0
  121. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/forcing.py +0 -0
  122. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/forcing_factory.py +0 -0
  123. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/meteo_handler.py +0 -0
  124. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/netcdf.py +0 -0
  125. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/plotting.py +0 -0
  126. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/rainfall.py +0 -0
  127. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/tide_gauge.py +0 -0
  128. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/time_frame.py +0 -0
  129. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/timeseries.py +0 -0
  130. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/unit_system.py +0 -0
  131. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/waterlevels.py +0 -0
  132. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/forcing/wind.py +0 -0
  133. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/measures/__init__.py +0 -0
  134. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/measures/measure_factory.py +0 -0
  135. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/measures/measures.py +0 -0
  136. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/object_model.py +0 -0
  137. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/output/floodmap.py +0 -0
  138. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/projections/__init__.py +0 -0
  139. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/projections/projections.py +0 -0
  140. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/scenarios/__init__.py +0 -0
  141. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/scenarios/scenarios.py +0 -0
  142. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/strategies/__init__.py +0 -0
  143. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/objects/strategies/strategies.py +0 -0
  144. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/workflows/__init__.py +0 -0
  145. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/workflows/benefit_runner.py +0 -0
  146. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt/workflows/scenario_runner.py +0 -0
  147. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt.egg-info/dependency_links.txt +0 -0
  148. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt.egg-info/not-zip-safe +0 -0
  149. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/flood_adapt.egg-info/top_level.txt +0 -0
  150. {flood_adapt-1.0.4 → flood_adapt-1.1.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: flood-adapt
3
- Version: 1.0.4
3
+ Version: 1.1.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: ====================================================
@@ -714,7 +714,7 @@ Requires-Dist: cht-observations==0.2.1
714
714
  Requires-Dist: cht-tide==0.1.1
715
715
  Requires-Dist: dask==2024.11.2
716
716
  Requires-Dist: numba_celltree==0.2.2
717
- Requires-Dist: fiat-toolbox==0.1.20
717
+ Requires-Dist: fiat-toolbox<0.2.0,>=0.1.22
718
718
  Requires-Dist: fiona<2.0,>=1.0
719
719
  Requires-Dist: geojson<4.0,>=3.0
720
720
  Requires-Dist: geopandas<2.0,>=1.0
@@ -723,7 +723,7 @@ Requires-Dist: hydromt-sfincs==1.2.0
723
723
  Requires-Dist: numpy<2.0,>=1.0
724
724
  Requires-Dist: numpy-financial<2.0,>=1.0
725
725
  Requires-Dist: pandas<3.0,>=2.0
726
- Requires-Dist: plotly<7.0,>=6.0
726
+ Requires-Dist: plotly<6.3,>=6.0
727
727
  Requires-Dist: pydantic<3.0,>=2.0
728
728
  Requires-Dist: pydantic-settings<3.0,>=2.0
729
729
  Requires-Dist: pyogrio<1.0
@@ -1,11 +1,11 @@
1
1
  # has to be here at the start to avoid circular imports
2
- __version__ = "1.0.4"
2
+ __version__ = "1.1.0"
3
3
 
4
4
  from flood_adapt import adapter, database_builder, dbs_classes, objects
5
5
  from flood_adapt.config.config import Settings
6
6
  from flood_adapt.config.site import Site
7
7
  from flood_adapt.flood_adapt import FloodAdapt
8
- from flood_adapt.misc.exceptions import ComponentError, DatabaseError, FloodAdaptError
8
+ from flood_adapt.misc.exceptions import DatabaseError, FloodAdaptError
9
9
  from flood_adapt.misc.log import FloodAdaptLogging
10
10
  from flood_adapt.objects.forcing import unit_system
11
11
 
@@ -21,7 +21,6 @@ __all__ = [
21
21
  "database_builder",
22
22
  "FloodAdaptError",
23
23
  "DatabaseError",
24
- "ComponentError",
25
24
  ]
26
25
 
27
26
  FloodAdaptLogging() # Initialize logging once for the entire package
@@ -205,7 +205,7 @@ class FiatAdapter(IImpactAdapter):
205
205
  self.close_files()
206
206
  if self.model_root.exists():
207
207
  logger.info(f"Deleting {self.model_root}")
208
- shutil.rmtree(self.model_root)
208
+ shutil.rmtree(self.model_root, ignore_errors=True)
209
209
 
210
210
  def fiat_completed(self) -> bool:
211
211
  """Check if fiat has run as expected.
@@ -353,7 +353,7 @@ class FiatAdapter(IImpactAdapter):
353
353
  os.remove(os.path.join(subdir, file))
354
354
 
355
355
  if not os.listdir(subdir):
356
- os.rmdir(subdir)
356
+ shutil.rmtree(subdir, ignore_errors=True)
357
357
 
358
358
  if strict:
359
359
  raise RuntimeError(f"FIAT model failed to run in {path}.")
@@ -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",
@@ -1574,5 +1579,5 @@ class FiatAdapter(IImpactAdapter):
1574
1579
  )
1575
1580
  if simulation_path.exists():
1576
1581
  self.close_files()
1577
- shutil.rmtree(simulation_path)
1582
+ shutil.rmtree(simulation_path, ignore_errors=True)
1578
1583
  logger.info(f"Deleted Delft-FIAT simulation folder: {simulation_path}")
@@ -212,7 +212,7 @@ class SfincsAdapter(IHazardAdapter):
212
212
  os.remove(os.path.join(subdir, file))
213
213
 
214
214
  if not os.listdir(subdir):
215
- os.rmdir(subdir)
215
+ shutil.rmtree(subdir, ignore_errors=True)
216
216
 
217
217
  if strict:
218
218
  raise RuntimeError(f"SFINCS model failed to run in {path}.")
@@ -828,7 +828,7 @@ class SfincsAdapter(IHazardAdapter):
828
828
 
829
829
  if sim_path.parent.exists() and not any(sim_path.parent.iterdir()):
830
830
  # Remove the parent directory `simulations` if it is empty
831
- sim_path.parent.rmdir()
831
+ shutil.rmtree(sim_path.parent, ignore_errors=True)
832
832
 
833
833
  def _run_risk_scenario(self, scenario: Scenario):
834
834
  """Run the whole workflow for a risk scenario.
@@ -97,7 +97,7 @@ class OffshoreSfincsHandler(IOffshoreSfincsHandler, DatabaseUser):
97
97
  sim_path = self._get_simulation_path()
98
98
  # SfincsAdapter.write() doesnt write the bca file apparently so we need to copy the template
99
99
  if sim_path.exists():
100
- shutil.rmtree(sim_path)
100
+ shutil.rmtree(sim_path, ignore_errors=True)
101
101
 
102
102
  with SfincsAdapter(model_root=self.template_path) as _offshore_model:
103
103
  # Load objects, set root & write template model
@@ -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(