flood-adapt 0.3.9__py3-none-any.whl → 0.3.11__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.
Files changed (100) hide show
  1. flood_adapt/__init__.py +26 -22
  2. flood_adapt/adapter/__init__.py +9 -9
  3. flood_adapt/adapter/fiat_adapter.py +1541 -1541
  4. flood_adapt/adapter/interface/hazard_adapter.py +70 -70
  5. flood_adapt/adapter/interface/impact_adapter.py +36 -36
  6. flood_adapt/adapter/interface/model_adapter.py +89 -89
  7. flood_adapt/adapter/interface/offshore.py +19 -19
  8. flood_adapt/adapter/sfincs_adapter.py +1853 -1848
  9. flood_adapt/adapter/sfincs_offshore.py +187 -193
  10. flood_adapt/config/config.py +248 -248
  11. flood_adapt/config/fiat.py +219 -219
  12. flood_adapt/config/gui.py +331 -331
  13. flood_adapt/config/sfincs.py +481 -336
  14. flood_adapt/config/site.py +129 -129
  15. flood_adapt/database_builder/database_builder.py +2210 -2210
  16. flood_adapt/database_builder/templates/default_units/imperial.toml +9 -9
  17. flood_adapt/database_builder/templates/default_units/metric.toml +9 -9
  18. flood_adapt/database_builder/templates/green_infra_table/green_infra_lookup_table.csv +10 -10
  19. flood_adapt/database_builder/templates/infographics/OSM/config_charts.toml +90 -90
  20. flood_adapt/database_builder/templates/infographics/OSM/config_people.toml +57 -57
  21. flood_adapt/database_builder/templates/infographics/OSM/config_risk_charts.toml +121 -121
  22. flood_adapt/database_builder/templates/infographics/OSM/config_roads.toml +65 -65
  23. flood_adapt/database_builder/templates/infographics/OSM/styles.css +45 -45
  24. flood_adapt/database_builder/templates/infographics/US_NSI/config_charts.toml +126 -126
  25. flood_adapt/database_builder/templates/infographics/US_NSI/config_people.toml +60 -60
  26. flood_adapt/database_builder/templates/infographics/US_NSI/config_risk_charts.toml +121 -121
  27. flood_adapt/database_builder/templates/infographics/US_NSI/config_roads.toml +65 -65
  28. flood_adapt/database_builder/templates/infographics/US_NSI/styles.css +45 -45
  29. flood_adapt/database_builder/templates/infometrics/OSM/metrics_additional_risk_configs.toml +4 -4
  30. flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config.toml +143 -143
  31. flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config_risk.toml +153 -153
  32. flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config.toml +127 -127
  33. flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config_risk.toml +57 -57
  34. flood_adapt/database_builder/templates/infometrics/US_NSI/metrics_additional_risk_configs.toml +4 -4
  35. flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config.toml +191 -191
  36. flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config_risk.toml +153 -153
  37. flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config.toml +178 -178
  38. flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config_risk.toml +57 -57
  39. flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config.toml +9 -9
  40. flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config_risk.toml +65 -65
  41. flood_adapt/database_builder/templates/output_layers/bin_colors.toml +5 -5
  42. flood_adapt/database_builder.py +16 -16
  43. flood_adapt/dbs_classes/__init__.py +21 -21
  44. flood_adapt/dbs_classes/database.py +533 -684
  45. flood_adapt/dbs_classes/dbs_benefit.py +77 -76
  46. flood_adapt/dbs_classes/dbs_event.py +61 -59
  47. flood_adapt/dbs_classes/dbs_measure.py +112 -111
  48. flood_adapt/dbs_classes/dbs_projection.py +34 -34
  49. flood_adapt/dbs_classes/dbs_scenario.py +137 -137
  50. flood_adapt/dbs_classes/dbs_static.py +274 -273
  51. flood_adapt/dbs_classes/dbs_strategy.py +130 -129
  52. flood_adapt/dbs_classes/dbs_template.py +279 -278
  53. flood_adapt/dbs_classes/interface/database.py +107 -139
  54. flood_adapt/dbs_classes/interface/element.py +121 -121
  55. flood_adapt/dbs_classes/interface/static.py +47 -47
  56. flood_adapt/flood_adapt.py +1229 -1178
  57. flood_adapt/misc/database_user.py +16 -16
  58. flood_adapt/misc/exceptions.py +22 -0
  59. flood_adapt/misc/log.py +183 -183
  60. flood_adapt/misc/path_builder.py +54 -54
  61. flood_adapt/misc/utils.py +185 -185
  62. flood_adapt/objects/__init__.py +82 -82
  63. flood_adapt/objects/benefits/benefits.py +61 -61
  64. flood_adapt/objects/events/event_factory.py +135 -135
  65. flood_adapt/objects/events/event_set.py +88 -84
  66. flood_adapt/objects/events/events.py +236 -234
  67. flood_adapt/objects/events/historical.py +58 -58
  68. flood_adapt/objects/events/hurricane.py +68 -67
  69. flood_adapt/objects/events/synthetic.py +46 -50
  70. flood_adapt/objects/forcing/__init__.py +92 -92
  71. flood_adapt/objects/forcing/csv.py +68 -68
  72. flood_adapt/objects/forcing/discharge.py +66 -66
  73. flood_adapt/objects/forcing/forcing.py +150 -150
  74. flood_adapt/objects/forcing/forcing_factory.py +182 -182
  75. flood_adapt/objects/forcing/meteo_handler.py +93 -93
  76. flood_adapt/objects/forcing/netcdf.py +40 -40
  77. flood_adapt/objects/forcing/plotting.py +453 -429
  78. flood_adapt/objects/forcing/rainfall.py +98 -98
  79. flood_adapt/objects/forcing/tide_gauge.py +191 -191
  80. flood_adapt/objects/forcing/time_frame.py +90 -90
  81. flood_adapt/objects/forcing/timeseries.py +564 -564
  82. flood_adapt/objects/forcing/unit_system.py +580 -580
  83. flood_adapt/objects/forcing/waterlevels.py +108 -108
  84. flood_adapt/objects/forcing/wind.py +124 -124
  85. flood_adapt/objects/measures/measure_factory.py +92 -92
  86. flood_adapt/objects/measures/measures.py +551 -529
  87. flood_adapt/objects/object_model.py +74 -68
  88. flood_adapt/objects/projections/projections.py +103 -103
  89. flood_adapt/objects/scenarios/scenarios.py +22 -22
  90. flood_adapt/objects/strategies/strategies.py +89 -89
  91. flood_adapt/workflows/benefit_runner.py +579 -554
  92. flood_adapt/workflows/floodmap.py +85 -85
  93. flood_adapt/workflows/impacts_integrator.py +85 -85
  94. flood_adapt/workflows/scenario_runner.py +70 -70
  95. {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/LICENSE +674 -674
  96. {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/METADATA +867 -865
  97. flood_adapt-0.3.11.dist-info/RECORD +140 -0
  98. flood_adapt-0.3.9.dist-info/RECORD +0 -139
  99. {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/WHEEL +0 -0
  100. {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/top_level.txt +0 -0
@@ -1,68 +1,74 @@
1
- import os
2
- from pathlib import Path
3
-
4
- import tomli
5
- import tomli_w
6
- from pydantic import BaseModel, Field
7
-
8
-
9
- class Object(BaseModel):
10
- """Base class for FloodAdapt objects.
11
-
12
- Attributes
13
- ----------
14
- name : str
15
- Name of the object.
16
- description : str
17
- Description of the object. defaults to "".
18
- """
19
-
20
- name: str = Field(
21
- ...,
22
- description="Name of the object.",
23
- min_length=1,
24
- pattern='^[^<>:"/\\\\|?* ]*$',
25
- )
26
- description: str = Field(default="", description="Description of the object.")
27
-
28
- @classmethod
29
- def load_file(cls, file_path: Path | str | os.PathLike) -> "Object":
30
- """Load object from file.
31
-
32
- Parameters
33
- ----------
34
- file_path : Path | str | os.PathLike
35
- Path to the file to load.
36
-
37
- """
38
- with open(file_path, mode="rb") as fp:
39
- toml = tomli.load(fp)
40
- return cls.model_validate(toml)
41
-
42
- def save(self, toml_path: Path | str | os.PathLike) -> None:
43
- """Save object to disk.
44
-
45
- Parameters
46
- ----------
47
- toml_path : Path | str | os.PathLike
48
- Path to the file to save.
49
-
50
- """
51
- self.save_additional(output_dir=Path(toml_path).parent)
52
- with open(toml_path, "wb") as f:
53
- tomli_w.dump(self.model_dump(exclude_none=True), f)
54
-
55
- def save_additional(self, output_dir: Path | str | os.PathLike) -> None:
56
- """Save additional files to database if the object has any and update attrs to reflect the change in file location.
57
-
58
- This method should be overridden if the object has additional files.
59
- """
60
- pass
61
-
62
- def __eq__(self, value):
63
- if not isinstance(value, self.__class__):
64
- # don't attempt to compare against unrelated types
65
- return False
66
- _self = self.model_dump(exclude={"name", "description"}, exclude_none=True)
67
- _other = value.model_dump(exclude={"name", "description"}, exclude_none=True)
68
- return _self == _other
1
+ import os
2
+ import re
3
+ from pathlib import Path
4
+
5
+ import tomli
6
+ import tomli_w
7
+ from pydantic import BaseModel, Field, field_validator
8
+
9
+
10
+ class Object(BaseModel):
11
+ """Base class for FloodAdapt objects.
12
+
13
+ Attributes
14
+ ----------
15
+ name : str
16
+ Name of the object.
17
+ description : str
18
+ Description of the object. defaults to "".
19
+ """
20
+
21
+ name: str = Field(..., description="Name of the object.")
22
+ description: str = Field(default="", description="Description of the object.")
23
+
24
+ @field_validator("name")
25
+ def validate_name(cls, value: str) -> str:
26
+ if not len(value) > 0:
27
+ raise ValueError("Name must be at least one character long.")
28
+ if not re.match(r"^[A-Za-z0-9_-]+$", value):
29
+ raise ValueError(
30
+ "Name can only contain letters, numbers, underscores (_), and hyphens (-)."
31
+ )
32
+ return value
33
+
34
+ @classmethod
35
+ def load_file(cls, file_path: Path | str | os.PathLike) -> "Object":
36
+ """Load object from file.
37
+
38
+ Parameters
39
+ ----------
40
+ file_path : Path | str | os.PathLike
41
+ Path to the file to load.
42
+
43
+ """
44
+ with open(file_path, mode="rb") as fp:
45
+ toml = tomli.load(fp)
46
+ return cls.model_validate(toml)
47
+
48
+ def save(self, toml_path: Path | str | os.PathLike) -> None:
49
+ """Save object to disk.
50
+
51
+ Parameters
52
+ ----------
53
+ toml_path : Path | str | os.PathLike
54
+ Path to the file to save.
55
+
56
+ """
57
+ self.save_additional(output_dir=Path(toml_path).parent)
58
+ with open(toml_path, "wb") as f:
59
+ tomli_w.dump(self.model_dump(exclude_none=True), f)
60
+
61
+ def save_additional(self, output_dir: Path | str | os.PathLike) -> None:
62
+ """Save additional files to database if the object has any and update attrs to reflect the change in file location.
63
+
64
+ This method should be overridden if the object has additional files.
65
+ """
66
+ pass
67
+
68
+ def __eq__(self, value):
69
+ if not isinstance(value, self.__class__):
70
+ # don't attempt to compare against unrelated types
71
+ return False
72
+ _self = self.model_dump(exclude={"name", "description"}, exclude_none=True)
73
+ _other = value.model_dump(exclude={"name", "description"}, exclude_none=True)
74
+ return _self == _other
@@ -1,103 +1,103 @@
1
- import math
2
- import os
3
- from pathlib import Path
4
- from typing import Optional
5
-
6
- from pydantic import BaseModel, Field, model_validator
7
-
8
- from flood_adapt.misc.utils import resolve_filepath, save_file_to_database
9
- from flood_adapt.objects.forcing import unit_system as us
10
- from flood_adapt.objects.object_model import Object
11
-
12
-
13
- class PhysicalProjection(BaseModel):
14
- """The accepted input for a physical projection in FloodAdapt.
15
-
16
- Attributes
17
- ----------
18
- sea_level_rise : us.UnitfulLength
19
- The sea level rise in meters. Default=us.UnitfulLength(0.0, us.UnitTypesLength.meters).
20
- subsidence : us.UnitfulLength
21
- The subsidence in meters. Default=us.UnitfulLength(0.0, us.UnitTypesLength.meters).
22
- rainfall_multiplier : float
23
- The rainfall multiplier. Default = 1.0.
24
- storm_frequency_increase : float
25
- The storm frequency increase as a percentage. Default = 0.0.
26
- """
27
-
28
- sea_level_rise: us.UnitfulLength = us.UnitfulLength(
29
- value=0.0, units=us.UnitTypesLength.meters
30
- )
31
- subsidence: us.UnitfulLength = us.UnitfulLength(
32
- value=0.0, units=us.UnitTypesLength.meters
33
- )
34
- rainfall_multiplier: float = Field(default=1.0, ge=0.0)
35
- storm_frequency_increase: float = 0.0
36
-
37
-
38
- class SocioEconomicChange(BaseModel):
39
- """The accepted input for socio-economic change in FloodAdapt.
40
-
41
- Attributes
42
- ----------
43
- population_growth_existing : float
44
- The population growth percentage of the existing area. default=0.0
45
- economic_growth : float
46
- The economic growth percentage. default=0.0.
47
- population_growth_new : float
48
- The population growth percentage for the new development areas. default=0.0.
49
- new_development_elevation : Optional[us.UnitfulLengthRefValue]
50
- The elevation of the new development areas. default=None.
51
- new_development_shapefile : Optional[str]
52
- The path to the shapefile of the new development areas. default=None.
53
- """
54
-
55
- population_growth_existing: Optional[float] = 0.0
56
- economic_growth: Optional[float] = 0.0
57
-
58
- population_growth_new: Optional[float] = 0.0
59
- new_development_elevation: Optional[us.UnitfulLengthRefValue] = None
60
- new_development_shapefile: Optional[str] = None
61
-
62
- @model_validator(mode="after")
63
- def validate_selection_type(self) -> "SocioEconomicChange":
64
- if not math.isclose(self.population_growth_new or 0.0, 0.0, abs_tol=1e-8):
65
- if self.new_development_shapefile is None:
66
- raise ValueError(
67
- "If `population_growth_new` is non-zero, then `new_development_shapefile` must also be provided."
68
- )
69
- return self
70
-
71
-
72
- class Projection(Object):
73
- """The accepted input for a projection in FloodAdapt.
74
-
75
- A projection is a combination of a physical projection and a socio-economic change.
76
-
77
- Attributes
78
- ----------
79
- name : str
80
- Name of the object.
81
- description : str
82
- Description of the object. defaults to "".
83
- physical_projection : PhysicalProjection
84
- The physical projection model. Contains information about hazard drivers.
85
- socio_economic_change : SocioEconomicChange
86
- The socio-economic change model. Contains information about impact drivers.
87
-
88
- """
89
-
90
- physical_projection: PhysicalProjection = PhysicalProjection()
91
- socio_economic_change: SocioEconomicChange = SocioEconomicChange()
92
-
93
- def save_additional(self, output_dir: Path | str | os.PathLike) -> None:
94
- if self.socio_economic_change.new_development_shapefile:
95
- src_path = resolve_filepath(
96
- "projections",
97
- self.name,
98
- self.socio_economic_change.new_development_shapefile,
99
- )
100
- path = save_file_to_database(src_path, Path(output_dir))
101
-
102
- # Update the shapefile path in the object so it is saved in the toml file as well
103
- self.socio_economic_change.new_development_shapefile = path.name
1
+ import math
2
+ import os
3
+ from pathlib import Path
4
+ from typing import Optional
5
+
6
+ from pydantic import BaseModel, Field, model_validator
7
+
8
+ from flood_adapt.misc.utils import resolve_filepath, save_file_to_database
9
+ from flood_adapt.objects.forcing import unit_system as us
10
+ from flood_adapt.objects.object_model import Object
11
+
12
+
13
+ class PhysicalProjection(BaseModel):
14
+ """The accepted input for a physical projection in FloodAdapt.
15
+
16
+ Attributes
17
+ ----------
18
+ sea_level_rise : us.UnitfulLength
19
+ The sea level rise in meters. Default=us.UnitfulLength(0.0, us.UnitTypesLength.meters).
20
+ subsidence : us.UnitfulLength
21
+ The subsidence in meters. Default=us.UnitfulLength(0.0, us.UnitTypesLength.meters).
22
+ rainfall_multiplier : float
23
+ The rainfall multiplier. Default = 1.0.
24
+ storm_frequency_increase : float
25
+ The storm frequency increase as a percentage. Default = 0.0.
26
+ """
27
+
28
+ sea_level_rise: us.UnitfulLength = us.UnitfulLength(
29
+ value=0.0, units=us.UnitTypesLength.meters
30
+ )
31
+ subsidence: us.UnitfulLength = us.UnitfulLength(
32
+ value=0.0, units=us.UnitTypesLength.meters
33
+ )
34
+ rainfall_multiplier: float = Field(default=1.0, ge=0.0)
35
+ storm_frequency_increase: float = 0.0
36
+
37
+
38
+ class SocioEconomicChange(BaseModel):
39
+ """The accepted input for socio-economic change in FloodAdapt.
40
+
41
+ Attributes
42
+ ----------
43
+ population_growth_existing : float
44
+ The population growth percentage of the existing area. default=0.0
45
+ economic_growth : float
46
+ The economic growth percentage. default=0.0.
47
+ population_growth_new : float
48
+ The population growth percentage for the new development areas. default=0.0.
49
+ new_development_elevation : Optional[us.UnitfulLengthRefValue]
50
+ The elevation of the new development areas. default=None.
51
+ new_development_shapefile : Optional[str]
52
+ The path to the shapefile of the new development areas. default=None.
53
+ """
54
+
55
+ population_growth_existing: Optional[float] = 0.0
56
+ economic_growth: Optional[float] = 0.0
57
+
58
+ population_growth_new: Optional[float] = 0.0
59
+ new_development_elevation: Optional[us.UnitfulLengthRefValue] = None
60
+ new_development_shapefile: Optional[str] = None
61
+
62
+ @model_validator(mode="after")
63
+ def validate_selection_type(self) -> "SocioEconomicChange":
64
+ if not math.isclose(self.population_growth_new or 0.0, 0.0, abs_tol=1e-8):
65
+ if self.new_development_shapefile is None:
66
+ raise ValueError(
67
+ "If `population_growth_new` is non-zero, then `new_development_shapefile` must also be provided."
68
+ )
69
+ return self
70
+
71
+
72
+ class Projection(Object):
73
+ """The accepted input for a projection in FloodAdapt.
74
+
75
+ A projection is a combination of a physical projection and a socio-economic change.
76
+
77
+ Attributes
78
+ ----------
79
+ name : str
80
+ Name of the object.
81
+ description : str
82
+ Description of the object. defaults to "".
83
+ physical_projection : PhysicalProjection
84
+ The physical projection model. Contains information about hazard drivers.
85
+ socio_economic_change : SocioEconomicChange
86
+ The socio-economic change model. Contains information about impact drivers.
87
+
88
+ """
89
+
90
+ physical_projection: PhysicalProjection = PhysicalProjection()
91
+ socio_economic_change: SocioEconomicChange = SocioEconomicChange()
92
+
93
+ def save_additional(self, output_dir: Path | str | os.PathLike) -> None:
94
+ if self.socio_economic_change.new_development_shapefile:
95
+ src_path = resolve_filepath(
96
+ "projections",
97
+ self.name,
98
+ self.socio_economic_change.new_development_shapefile,
99
+ )
100
+ path = save_file_to_database(src_path, Path(output_dir))
101
+
102
+ # Update the shapefile path in the object so it is saved in the toml file as well
103
+ self.socio_economic_change.new_development_shapefile = path.name
@@ -1,22 +1,22 @@
1
- from flood_adapt.objects.object_model import Object
2
-
3
-
4
- class Scenario(Object):
5
- """BaseModel describing the expected variables and data types of a scenario.
6
-
7
- A scenario is a combination of an event, a projection, and a strategy, that all should be saved in the database.
8
-
9
- Attributes
10
- ----------
11
- event : str
12
- The name of the event.
13
- projection : str
14
- The name of the projection.
15
- strategy : str
16
- The name of the strategy.
17
-
18
- """
19
-
20
- event: str
21
- projection: str
22
- strategy: str
1
+ from flood_adapt.objects.object_model import Object
2
+
3
+
4
+ class Scenario(Object):
5
+ """BaseModel describing the expected variables and data types of a scenario.
6
+
7
+ A scenario is a combination of an event, a projection, and a strategy, that all should be saved in the database.
8
+
9
+ Attributes
10
+ ----------
11
+ event : str
12
+ The name of the event.
13
+ projection : str
14
+ The name of the projection.
15
+ strategy : str
16
+ The name of the strategy.
17
+
18
+ """
19
+
20
+ event: str
21
+ projection: str
22
+ strategy: str
@@ -1,89 +1,89 @@
1
- from flood_adapt.objects.measures.measures import (
2
- HazardMeasure,
3
- ImpactMeasure,
4
- Measure,
5
- )
6
- from flood_adapt.objects.object_model import Object
7
-
8
-
9
- class Strategy(Object):
10
- """
11
- Class representing a strategy in FloodAdapt.
12
-
13
- A strategy is a collection of measures that can be applied to a model.
14
-
15
- Attributes
16
- ----------
17
- measures : list[str]
18
- A list of measures associated with the strategy. Should be a list of measure names that are saved in the database.
19
-
20
- """
21
-
22
- measures: list[str]
23
-
24
- _measure_objects: list[Measure] | None = None
25
-
26
- def initialize_measure_objects(self, measures: list[Measure]) -> None:
27
- """Initialize the measure objects associated with this strategy.
28
-
29
- Parameters
30
- ----------
31
- measures : list[Measure]
32
- A list of measure objects to be associated with this strategy. Should be a list of measure objects that are saved in the database.
33
- """
34
- self._measure_objects = measures
35
-
36
- def get_measures(self) -> list[Measure]:
37
- """Get the measures associated with this strategy.
38
-
39
- Note that this method will return the measure objects, not just their names.
40
- The measure objects are initialized using the `initialize_measure_objects` method.
41
-
42
- Returns
43
- -------
44
- measures : list[Measure]
45
- The list of measure objects associated with this strategy.
46
-
47
- Raises
48
- ------
49
- ValueError
50
- If the measure objects have not been initialized.
51
- """
52
- # Get measure paths using a database structure
53
- if self._measure_objects is None:
54
- raise ValueError(
55
- "Measure objects have not been initialized. Call `initialize_measure_objects()` first."
56
- )
57
- return self._measure_objects
58
-
59
- def get_impact_measures(self) -> list[ImpactMeasure]:
60
- return [
61
- measure
62
- for measure in self.get_measures()
63
- if isinstance(measure, ImpactMeasure)
64
- ]
65
-
66
- def get_impact_strategy(self) -> "Strategy":
67
- impact_measures = self.get_impact_measures()
68
- impact_strategy = Strategy(
69
- name=self.name,
70
- measures=[m.name for m in impact_measures],
71
- )
72
- impact_strategy.initialize_measure_objects(impact_measures)
73
- return impact_strategy
74
-
75
- def get_hazard_measures(self) -> list[HazardMeasure]:
76
- return [
77
- measure
78
- for measure in self.get_measures()
79
- if isinstance(measure, HazardMeasure)
80
- ]
81
-
82
- def get_hazard_strategy(self) -> "Strategy":
83
- hazard_measures = self.get_hazard_measures()
84
- hazard_strategy = Strategy(
85
- name=self.name,
86
- measures=[m.name for m in hazard_measures],
87
- )
88
- hazard_strategy.initialize_measure_objects(hazard_measures)
89
- return hazard_strategy
1
+ from flood_adapt.objects.measures.measures import (
2
+ HazardMeasure,
3
+ ImpactMeasure,
4
+ Measure,
5
+ )
6
+ from flood_adapt.objects.object_model import Object
7
+
8
+
9
+ class Strategy(Object):
10
+ """
11
+ Class representing a strategy in FloodAdapt.
12
+
13
+ A strategy is a collection of measures that can be applied to a model.
14
+
15
+ Attributes
16
+ ----------
17
+ measures : list[str]
18
+ A list of measures associated with the strategy. Should be a list of measure names that are saved in the database.
19
+
20
+ """
21
+
22
+ measures: list[str]
23
+
24
+ _measure_objects: list[Measure] | None = None
25
+
26
+ def initialize_measure_objects(self, measures: list[Measure]) -> None:
27
+ """Initialize the measure objects associated with this strategy.
28
+
29
+ Parameters
30
+ ----------
31
+ measures : list[Measure]
32
+ A list of measure objects to be associated with this strategy. Should be a list of measure objects that are saved in the database.
33
+ """
34
+ self._measure_objects = measures
35
+
36
+ def get_measures(self) -> list[Measure]:
37
+ """Get the measures associated with this strategy.
38
+
39
+ Note that this method will return the measure objects, not just their names.
40
+ The measure objects are initialized using the `initialize_measure_objects` method.
41
+
42
+ Returns
43
+ -------
44
+ measures : list[Measure]
45
+ The list of measure objects associated with this strategy.
46
+
47
+ Raises
48
+ ------
49
+ ValueError
50
+ If the measure objects have not been initialized.
51
+ """
52
+ # Get measure paths using a database structure
53
+ if self._measure_objects is None:
54
+ raise ValueError(
55
+ "Measure objects have not been initialized. Call `initialize_measure_objects()` first."
56
+ )
57
+ return self._measure_objects
58
+
59
+ def get_impact_measures(self) -> list[ImpactMeasure]:
60
+ return [
61
+ measure
62
+ for measure in self.get_measures()
63
+ if isinstance(measure, ImpactMeasure)
64
+ ]
65
+
66
+ def get_impact_strategy(self) -> "Strategy":
67
+ impact_measures = self.get_impact_measures()
68
+ impact_strategy = Strategy(
69
+ name=self.name,
70
+ measures=[m.name for m in impact_measures],
71
+ )
72
+ impact_strategy.initialize_measure_objects(impact_measures)
73
+ return impact_strategy
74
+
75
+ def get_hazard_measures(self) -> list[HazardMeasure]:
76
+ return [
77
+ measure
78
+ for measure in self.get_measures()
79
+ if isinstance(measure, HazardMeasure)
80
+ ]
81
+
82
+ def get_hazard_strategy(self) -> "Strategy":
83
+ hazard_measures = self.get_hazard_measures()
84
+ hazard_strategy = Strategy(
85
+ name=self.name,
86
+ measures=[m.name for m in hazard_measures],
87
+ )
88
+ hazard_strategy.initialize_measure_objects(hazard_measures)
89
+ return hazard_strategy