Skip to content

Commit

Permalink
598 adaptation calculate impact adaptation option for time horizon (#617
Browse files Browse the repository at this point in the history
)

* run_net_present_impact method

* chore/rename variable

* chore/remove unrelated uncertainty files

* calculate net present impact for all options

* chore/docstrings

* create net_present_value factor

* add test get_net_present_value_factor

* run black

* run black again

* Update tests/analysis/adaptation/test_adaptation_option_collection.py

Co-authored-by: Carles S. Soriano Pérez <carles.sorianoperez@deltares.nl>

* Update ra2ce/analysis/adaptation/adaptation_option.py

Co-authored-by: Carles S. Soriano Pérez <carles.sorianoperez@deltares.nl>

* chore/remove unncessary imports

* chore/remove parenthesis

* chore/fix test

---------

Co-authored-by: Carles S. Soriano Pérez <carles.sorianoperez@deltares.nl>
  • Loading branch information
MatthiasHauthDeltares and Carsopre authored Dec 6, 2024
1 parent a055326 commit 9096b12
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 2 deletions.
7 changes: 6 additions & 1 deletion ra2ce/analysis/adaptation/adaptation_option.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@ def calculate_cost(year) -> float:

return sum(calculate_cost(_year) for _year in range(0, round(time_horizon), 1))

def calculate_impact(self, benefit_graph: GeoDataFrame) -> GeoDataFrame:
def calculate_impact(
self, benefit_graph: GeoDataFrame, net_present_value_factor: float
) -> GeoDataFrame:
"""
Calculate the impact of the adaptation option.
Expand All @@ -150,4 +152,7 @@ def calculate_impact(self, benefit_graph: GeoDataFrame) -> GeoDataFrame:
_option_cols = benefit_graph.filter(regex=f"{self.id}_").columns
benefit_graph[f"{self.id}_impact"] = benefit_graph[_option_cols].sum(axis=1)

# convert event impact into time-horizon impact
benefit_graph[f"{self.id}_impact"] *= net_present_value_factor

return benefit_graph
20 changes: 19 additions & 1 deletion ra2ce/analysis/adaptation/adaptation_option_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

from dataclasses import dataclass, field

import numpy as np
from geopandas import GeoDataFrame

from ra2ce.analysis.adaptation.adaptation_option import AdaptationOption
Expand Down Expand Up @@ -91,6 +92,19 @@ def from_config(

return _collection

def get_net_present_value_factor(self) -> float:
"""
Calculate the net present value factor for the entire time horizon. To be multiplied to the event impact to
obtain the net present value.
"""
_years_array = np.arange(0, self.time_horizon)
_frequency_per_year = (
self.initial_frequency + _years_array * self.climate_factor
)
_discount = (1 + self.discount_rate) ** _years_array
_ratio = _frequency_per_year / _discount
return _ratio.sum()

def calculate_options_unit_cost(self) -> dict[AdaptationOption, float]:
"""
Calculate the unit cost for all adaptation options.
Expand All @@ -116,7 +130,11 @@ def calculation_options_impact(self, benefit_graph: GeoDataFrame) -> GeoDataFram
Returns:
NetworkFile: The calculated impact of all adaptation options.
"""
net_present_value_factor = self.get_net_present_value_factor()

for _option in self.all_options:
benefit_graph = _option.calculate_impact(benefit_graph)
benefit_graph = _option.calculate_impact(
benefit_graph, net_present_value_factor
)

return benefit_graph
2 changes: 2 additions & 0 deletions tests/analysis/adaptation/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ def get_losses_section(analysis: AnalysisLossesEnum) -> AnalysisSectionLosses:
adaptation_options=AdaptationOptionCases.config_cases,
discount_rate=0.025,
time_horizon=20,
climate_factor=0.00036842,
initial_frequency=0.01,
)

_analysis_data = AnalysisConfigData(
Expand Down
19 changes: 19 additions & 0 deletions tests/analysis/adaptation/test_adaptation_option_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,22 @@ def test_calculate_options_unit_cost(
# 3. Verify expectations.
assert isinstance(_result, dict)
assert all(_option in _result for _option in _collection.adaptation_options)

def test_calculate_correct_get_net_present_value_factor(
self,
valid_adaptation_config: tuple[AnalysisInputWrapper, AnalysisConfigWrapper],
):
# 1. Define test data.
_config_wrapper = valid_adaptation_config[1]
assert isinstance(_config_wrapper, AnalysisConfigWrapper)
_collection = AdaptationOptionCollection.from_config(_config_wrapper)

# 2. Run test.
_result = _collection.get_net_present_value_factor()

# 3. Verify expectations.
assert isinstance(_result, float)
assert _result == pytest.approx(0.2109011023, rel=1e-9)



0 comments on commit 9096b12

Please sign in to comment.