flood-adapt 1.0.0rc1__py3-none-any.whl → 1.0.2__py3-none-any.whl

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