diff --git a/src/otoole/results/result_package.py b/src/otoole/results/result_package.py index 9c200f1..c961d5e 100644 --- a/src/otoole/results/result_package.py +++ b/src/otoole/results/result_package.py @@ -775,8 +775,8 @@ def calc_crf(df: pd.DataFrame, operational_life: pd.Series) -> pd.Series: return numerator / denominator - if discount_rate_idv.empty: - raise ValueError("Cannot calculate CRF due to missing discount rate data") + if discount_rate_idv.empty or operational_life.empty: + raise ValueError("Cannot calculate PV Annuity due to missing data") if not regions and not technologies: return pd.DataFrame( @@ -826,6 +826,10 @@ def pv_annuity( param PvAnnuity{r in REGION, t in TECHNOLOGY} := (1 - (1 + DiscountRate[r])^(-(OperationalLife[r,t]))) * (1 + DiscountRate[r]) / DiscountRate[r]; """ + + if discount_rate.empty or operational_life.empty: + raise ValueError("Cannot calculate PV Annuity due to missing data") + if regions and technologies: index = pd.MultiIndex.from_product( [regions, technologies], names=["REGION", "TECHNOLOGY"] @@ -876,6 +880,11 @@ def discount_factor( (1 + DiscountRate[r]) ^ (y - min{yy in YEAR} min(yy) + 0.5); """ + if discount_rate.empty: + raise ValueError( + "Cannot calculate discount factor due to missing discount rate" + ) + if regions and years: discount_rate["YEAR"] = [years] discount_factor = discount_rate.explode("YEAR").reset_index(level="REGION") @@ -920,6 +929,11 @@ def discount_factor_storage( (1 + DiscountRateStorage[r,s]) ^ (y - min{yy in YEAR} min(yy) + 0.0); """ + if discount_rate_storage.empty: + raise ValueError( + "Cannot calculate discount_factor_storage due to missing discount rate" + ) + if regions and years: index = pd.MultiIndex.from_product( [regions, storages, years], names=["REGION", "STORAGE", "YEAR"] diff --git a/tests/conftest.py b/tests/conftest.py index b6f8353..d22edb5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -101,6 +101,15 @@ def discount_rate_idv_empty(): return df +@fixture +def discount_rate_storage_empty(): + df = pd.DataFrame( + data=[], + columns=["REGION", "STORAGE", "VALUE"], + ).set_index(["REGION", "STORAGE"]) + return df + + @fixture def emission_activity_ratio(): df = pd.DataFrame( diff --git a/tests/results/test_results_package.py b/tests/results/test_results_package.py index 9bcbd5e..418599c 100644 --- a/tests/results/test_results_package.py +++ b/tests/results/test_results_package.py @@ -698,7 +698,7 @@ def test_pva(self, region, discount_rate, operational_life): assert_frame_equal(actual, expected) - def test_pva_null(self, discount_rate): + def test_pva_null(self, discount_rate, operational_life): actual = pv_annuity([], [], discount_rate, operational_life) @@ -709,6 +709,15 @@ def test_pva_null(self, discount_rate): assert_frame_equal(actual, expected) + def test_pva_empty_discount_rate( + self, region, discount_rate_empty, operational_life + ): + technologies = ["GAS_EXTRACTION", "DUMMY"] + regions = region["VALUE"].to_list() + + with raises(ValueError): + pv_annuity(regions, technologies, discount_rate_empty, operational_life) + class TestDiscountFactor: def test_df_start(self, region, year, discount_rate): @@ -785,6 +794,13 @@ def test_df_null(self, discount_rate): assert_frame_equal(actual, expected) + def test_df_empty_discount_rate(self, region, year, discount_rate_empty): + regions = region["VALUE"].to_list() + years = year["VALUE"].to_list() + + with raises(ValueError): + discount_factor(regions, years, discount_rate_empty, 1.0) + class TestDiscountFactorStorage: def test_dfs_start(self, region, year, discount_rate_storage): @@ -870,6 +886,18 @@ def test_df_null(self, discount_rate_storage): assert_frame_equal(actual, expected) + def test_df_storage_empty_discount_rate( + self, region, year, discount_rate_storage_empty + ): + storages = ["DAM"] + regions = region["VALUE"].to_list() + years = year["VALUE"].to_list() + + with raises(ValueError): + discount_factor_storage( + regions, storages, years, discount_rate_storage_empty, 1.0 + ) + class TestResultsPackage: def test_results_package_init(self):