Skip to content

Commit 3a026cd

Browse files
committed
risk_disc -> risk_disc_rates, fixes return period mechanism
1 parent b4316d7 commit 3a026cd

File tree

5 files changed

+42
-35
lines changed

5 files changed

+42
-35
lines changed

climada/trajectories/interpolated_trajectory.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
ImpactComputationStrategy,
4141
)
4242
from climada.trajectories.snapshot import Snapshot
43-
from climada.trajectories.trajectory import RiskTrajectory
43+
from climada.trajectories.trajectory import DEFAULT_RP, RiskTrajectory
4444
from climada.util import log_level
4545

4646
LOGGER = logging.getLogger(__name__)
@@ -69,16 +69,18 @@ def __init__(
6969
self,
7070
snapshots_list: list[Snapshot],
7171
*,
72+
return_periods: list[int] = DEFAULT_RP,
7273
time_resolution: str = "Y",
7374
all_groups_name: str = "All",
74-
risk_disc: DiscRates | None = None,
75+
risk_disc_rates: DiscRates | None = None,
7576
interpolation_strategy: InterpolationStrategyBase | None = None,
7677
impact_computation_strategy: ImpactComputationStrategy | None = None,
7778
):
7879
super().__init__(
7980
snapshots_list,
81+
return_periods=return_periods,
8082
all_groups_name=all_groups_name,
81-
risk_disc=risk_disc,
83+
risk_disc_rates=risk_disc_rates,
8284
)
8385
self._risk_metrics_up_to_date: bool = False
8486
self.start_date = min([snapshot.date for snapshot in snapshots_list])
@@ -247,8 +249,10 @@ def _generic_metrics(
247249
]
248250
setattr(self, attr_name, tmp)
249251

250-
if self._risk_disc:
251-
return self.npv_transform(getattr(self, attr_name), self._risk_disc)
252+
if self._risk_disc_rates:
253+
return self.npv_transform(
254+
getattr(self, attr_name), self._risk_disc_rates
255+
)
252256

253257
return getattr(self, attr_name)
254258

climada/trajectories/snapshot.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ class Snapshot:
4949
a datetime object or a string representation of a datetime object
5050
with format YYYY-MM-DD.
5151
52-
5352
Attributes
5453
----------
5554
date : datetime

climada/trajectories/static_trajectory.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
ImpactComputationStrategy,
3333
)
3434
from climada.trajectories.snapshot import Snapshot
35-
from climada.trajectories.trajectory import RiskTrajectory
35+
from climada.trajectories.trajectory import DEFAULT_RP, RiskTrajectory
3636
from climada.util import log_level
3737

3838
LOGGER = logging.getLogger(__name__)
@@ -57,14 +57,16 @@ def __init__(
5757
self,
5858
snapshots_list: list[Snapshot],
5959
*,
60+
return_periods: list[int] = DEFAULT_RP,
6061
all_groups_name: str = "All",
61-
risk_disc: DiscRates | None = None,
62+
risk_disc_rates: DiscRates | None = None,
6263
impact_computation_strategy: ImpactComputationStrategy | None = None,
6364
):
6465
super().__init__(
6566
snapshots_list,
67+
return_periods=return_periods,
6668
all_groups_name=all_groups_name,
67-
risk_disc=risk_disc,
69+
risk_disc_rates=risk_disc_rates,
6870
)
6971
self._risk_metrics_calculators = CalcRiskMetricsPoints(
7072
self._snapshots,
@@ -140,8 +142,10 @@ def _generic_metrics(
140142
]
141143
setattr(self, attr_name, tmp)
142144

143-
if self._risk_disc:
144-
return self.npv_transform(getattr(self, attr_name), self._risk_disc)
145+
if self._risk_disc_rates:
146+
return self.npv_transform(
147+
getattr(self, attr_name), self._risk_disc_rates
148+
)
145149

146150
return getattr(self, attr_name)
147151

climada/trajectories/test/test_risk_trajectory.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def test_init_basic(self):
8888
)
8989
self.assertEqual(rt.start_date, self.mock_snapshot1.date)
9090
self.assertEqual(rt.end_date, self.mock_snapshot3.date)
91-
self.assertIsNone(rt._risk_disc)
91+
self.assertIsNone(rt._risk_disc_rates)
9292
self.assertEqual(rt._interpolation_strategy, self.mock_interpolation_strategy)
9393
self.assertEqual(
9494
rt._impact_computation_strategy, self.mock_impact_computation_strategy
@@ -106,13 +106,13 @@ def test_init_with_custom_params(self):
106106
self.snapshots_list,
107107
time_resolution="MS",
108108
all_groups_name="CustomAll",
109-
risk_disc=mock_disc,
109+
risk_disc_rates=mock_disc,
110110
interpolation_strategy=Mock(),
111111
impact_computation_strategy=Mock(),
112112
)
113113
self.assertEqual(rt._time_resolution, "MS")
114114
self.assertEqual(rt._all_groups_name, "CustomAll")
115-
self.assertEqual(rt._risk_disc, mock_disc)
115+
self.assertEqual(rt._risk_disc_rates, mock_disc)
116116

117117
## Test Properties (`@property` and `@setter`)
118118
def test_default_rp_getter_setter(self):
@@ -212,7 +212,7 @@ def test_calc_risk_periods_sorting(self, MockCalcRiskPeriod):
212212
def test_generic_metrics_basic_flow(self, mock_npv_transform, mock_risk_periods):
213213
rt = InterpolatedRiskTrajectory(self.snapshots_list)
214214
rt._all_groups_name = "All" # Ensure default
215-
rt._risk_disc = self.mock_disc_rates # For NPV transform check
215+
rt._risk_disc_rates = self.mock_disc_rates # For NPV transform check
216216

217217
# Mock CalcRiskPeriod instances returned by risk_periods property
218218
mock_calc_period1 = Mock()
@@ -267,7 +267,7 @@ def test_generic_metrics_basic_flow(self, mock_npv_transform, mock_risk_periods)
267267
["group", "date", "measure", "metric", "risk"]
268268
]
269269
# npv_transform should be called with the correctly formatted (concatenated and ordered) DataFrame
270-
# and the risk_disc attribute
270+
# and the risk_disc_rates attribute
271271
mock_npv_transform.assert_called_once()
272272
pd.testing.assert_frame_equal(
273273
mock_npv_transform.call_args[0][0].reset_index(drop=True),

climada/trajectories/trajectory.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,36 +28,34 @@
2828
import pandas as pd
2929

3030
from climada.entity.disc_rates.base import DiscRates
31-
from climada.trajectories.riskperiod import (
32-
ImpactCalcComputation,
33-
ImpactComputationStrategy,
34-
)
3531
from climada.trajectories.snapshot import Snapshot
3632

3733
LOGGER = logging.getLogger(__name__)
3834

35+
DEFAULT_RP = [20, 50, 100]
36+
3937

4038
class RiskTrajectory(ABC):
4139
_grouper = ["measure", "metric"]
4240
"""Results dataframe grouper"""
4341

4442
POSSIBLE_METRICS = []
45-
DEFAULT_RP = [20, 50, 100]
4643

4744
def __init__(
4845
self,
4946
snapshots_list: list[Snapshot],
5047
*,
48+
return_periods: list[int],
5149
all_groups_name: str = "All",
52-
risk_disc: DiscRates | None = None,
50+
risk_disc_rates: DiscRates | None = None,
5351
):
5452
self._reset_metrics()
5553
self._snapshots = snapshots_list
5654
self._all_groups_name = all_groups_name
57-
self._return_periods = self.DEFAULT_RP
55+
self._return_periods = return_periods
5856
self.start_date = min([snapshot.date for snapshot in snapshots_list])
5957
self.end_date = max([snapshot.date for snapshot in snapshots_list])
60-
self._risk_disc = risk_disc
58+
self._risk_disc_rates = risk_disc_rates
6159

6260
def _reset_metrics(self):
6361
for metric in self.POSSIBLE_METRICS:
@@ -103,7 +101,7 @@ def return_periods(self, value, /):
103101
self._return_periods = value
104102

105103
@property
106-
def risk_disc(self) -> DiscRates | None:
104+
def risk_disc_rates(self) -> DiscRates | None:
107105
"""The discount rate applied to compute net present values.
108106
None means no discount rate.
109107
@@ -112,25 +110,27 @@ def risk_disc(self) -> DiscRates | None:
112110
113111
Changing its value resets the metrics.
114112
"""
115-
return self._risk_disc
113+
return self._risk_disc_rates
116114

117-
@risk_disc.setter
118-
def risk_disc(self, value, /):
115+
@risk_disc_rates.setter
116+
def risk_disc_rates(self, value, /):
119117
if not isinstance(value, DiscRates):
120118
raise ValueError("Risk discount needs to be a `DiscRates` object.")
121119

122120
self._reset_metrics()
123-
self._risk_disc = value
121+
self._risk_disc_rates = value
124122

125123
@classmethod
126-
def npv_transform(cls, df: pd.DataFrame, risk_disc: DiscRates) -> pd.DataFrame:
124+
def npv_transform(
125+
cls, df: pd.DataFrame, risk_disc_rates: DiscRates
126+
) -> pd.DataFrame:
127127
"""Apply discount rate to a metric `DataFrame`.
128128
129129
Parameters
130130
----------
131131
df : pd.DataFrame
132132
The `DataFrame` of the metric to discount.
133-
risk_disc : DiscRate
133+
risk_disc_rates : DiscRate
134134
The discount rate to apply.
135135
136136
Returns
@@ -156,15 +156,15 @@ def _npv_group(group, disc):
156156
as_index=False,
157157
group_keys=False,
158158
observed=True,
159-
)["risk"].transform(_npv_group, risk_disc)
159+
)["risk"].transform(_npv_group, risk_disc_rates)
160160
df = df.reset_index()
161161
return df
162162

163163
@staticmethod
164164
def _calc_npv_cash_flows(
165165
cash_flows: pd.DataFrame,
166166
start_date: datetime.date,
167-
disc: DiscRates | None = None,
167+
disc_rates: DiscRates | None = None,
168168
):
169169
"""Apply discount rate to cash flows.
170170
@@ -187,7 +187,7 @@ def _calc_npv_cash_flows(
187187
A dataframe (copy) of `cash_flows` where values are discounted according to `disc`
188188
"""
189189

190-
if not disc:
190+
if not disc_rates:
191191
return cash_flows
192192

193193
if not isinstance(cash_flows.index, pd.DatetimeIndex):
@@ -198,7 +198,7 @@ def _calc_npv_cash_flows(
198198

199199
# Merge with the discount rates based on the year
200200
tmp = df.merge(
201-
pd.DataFrame({"year": disc.years, "rate": disc.rates}),
201+
pd.DataFrame({"year": disc_rates.years, "rate": disc_rates.rates}),
202202
on="year",
203203
how="left",
204204
)

0 commit comments

Comments
 (0)