Skip to content

Commit 57f981b

Browse files
committed
Updates integration tests, factorizes interpolations
1 parent 2a8899c commit 57f981b

File tree

2 files changed

+139
-24
lines changed

2 files changed

+139
-24
lines changed

climada/test/test_trajectories.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
from climada.engine.impact_calc import ImpactCalc
3131
from climada.entity.disc_rates.base import DiscRates
32+
from climada.entity.impact_funcs.base import ImpactFunc
33+
from climada.entity.impact_funcs.impact_func_set import ImpactFuncSet
3234
from climada.test.reusable import (
3335
CATEGORIES,
3436
reusable_minimal_exposures,
@@ -40,6 +42,11 @@
4042
from climada.trajectories.constants import (
4143
AAI_METRIC_NAME,
4244
AAI_PER_GROUP_METRIC_NAME,
45+
CONTRIBUTION_BASE_RISK_NAME,
46+
CONTRIBUTION_EXPOSURE_NAME,
47+
CONTRIBUTION_HAZARD_NAME,
48+
CONTRIBUTION_INTERACTION_TERM_NAME,
49+
CONTRIBUTION_VULNERABILITY_NAME,
4350
COORD_ID_COL_NAME,
4451
DATE_COL_NAME,
4552
EAI_METRIC_NAME,
@@ -520,3 +527,117 @@ def test_interp_trajectory_risk_disc_rate(self):
520527
check_dtype=False,
521528
check_categorical=False,
522529
)
530+
531+
def test_interp_trajectory_risk_contributions(self):
532+
interp_traj = InterpolatedRiskTrajectory(
533+
[self.base_snapshot, self.future_snapshot]
534+
)
535+
expected = pd.DataFrame.from_dict(
536+
# fmt: off
537+
{'index': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
538+
'columns': [DATE_COL_NAME, GROUP_COL_NAME, MEASURE_COL_NAME, METRIC_COL_NAME, UNIT_COL_NAME, RISK_COL_NAME,],
539+
'data': [
540+
[pd.Period(str(2020)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_BASE_RISK_NAME, 'USD', 20.0],
541+
[pd.Period(str(2021)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_BASE_RISK_NAME, 'USD', 20.0],
542+
[pd.Period(str(2022)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_BASE_RISK_NAME, 'USD', 20.0],
543+
[pd.Period(str(2020)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_EXPOSURE_NAME, 'USD', 0.0],
544+
[pd.Period(str(2021)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_EXPOSURE_NAME, 'USD', 50.0],
545+
[pd.Period(str(2022)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_EXPOSURE_NAME, 'USD', 100.0],
546+
[pd.Period(str(2020)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_HAZARD_NAME, 'USD', 0.0],
547+
[pd.Period(str(2021)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_HAZARD_NAME, 'USD', 10.0],
548+
[pd.Period(str(2022)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_HAZARD_NAME, 'USD', 20.0],
549+
[pd.Period(str(2020)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_VULNERABILITY_NAME, 'USD', 0.0],
550+
[pd.Period(str(2021)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_VULNERABILITY_NAME, 'USD', 0.0],
551+
[pd.Period(str(2022)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_VULNERABILITY_NAME, 'USD', 0.0],
552+
[pd.Period(str(2020)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_INTERACTION_TERM_NAME, 'USD', 0.0],
553+
[pd.Period(str(2021)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_INTERACTION_TERM_NAME, 'USD', 25.0],
554+
[pd.Period(str(2022)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_INTERACTION_TERM_NAME, 'USD', 100.0]],
555+
'index_names': [None],
556+
'column_names': [None]},
557+
# fmt: on
558+
orient="tight",
559+
)
560+
pd.testing.assert_frame_equal(
561+
interp_traj.risk_contributions_metrics(),
562+
expected,
563+
check_dtype=False,
564+
check_categorical=False,
565+
)
566+
567+
# With changing vulnerability
568+
hazard = reusable_minimal_hazard()
569+
impfset1 = ImpactFuncSet(
570+
[
571+
ImpactFunc(
572+
haz_type=hazard.haz_type,
573+
intensity_unit=hazard.units,
574+
name="linear",
575+
intensity=np.array([0, 100 / 2, 100]),
576+
mdd=np.array([0, 0.5, 1]),
577+
paa=np.array([1, 1, 1]),
578+
id=1,
579+
),
580+
]
581+
)
582+
impfset2 = ImpactFuncSet(
583+
[
584+
ImpactFunc(
585+
haz_type=hazard.haz_type,
586+
intensity_unit=hazard.units,
587+
name="linear-half-paa",
588+
intensity=np.array([0, 100 / 2, 100]),
589+
mdd=np.array([0, 0.5, 1]),
590+
paa=np.array([0.5, 0.5, 0.5]),
591+
id=1,
592+
)
593+
]
594+
)
595+
base_snapshot = Snapshot(
596+
exposure=reusable_minimal_exposures(),
597+
hazard=hazard,
598+
impfset=impfset1,
599+
date=2020,
600+
)
601+
future_snapshot = Snapshot(
602+
exposure=reusable_minimal_exposures(
603+
increase_value_factor=self.EXP_INCREASE_VALUE_FACTOR,
604+
),
605+
hazard=reusable_minimal_hazard(
606+
intensity_factor=self.HAZ_INCREASE_INTENSITY_FACTOR
607+
),
608+
impfset=impfset2,
609+
date=2022,
610+
)
611+
612+
interp_traj = InterpolatedRiskTrajectory([base_snapshot, future_snapshot])
613+
expected = pd.DataFrame.from_dict(
614+
# fmt: off
615+
{'index': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
616+
'columns': [DATE_COL_NAME, GROUP_COL_NAME, MEASURE_COL_NAME, METRIC_COL_NAME, UNIT_COL_NAME, RISK_COL_NAME,],
617+
'data': [
618+
[pd.Period(str(2020)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_BASE_RISK_NAME, 'USD', 20.0],
619+
[pd.Period(str(2021)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_BASE_RISK_NAME, 'USD', 20.0],
620+
[pd.Period(str(2022)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_BASE_RISK_NAME, 'USD', 20.0],
621+
[pd.Period(str(2020)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_EXPOSURE_NAME, 'USD', 0.0],
622+
[pd.Period(str(2021)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_EXPOSURE_NAME, 'USD', 50.0],
623+
[pd.Period(str(2022)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_EXPOSURE_NAME, 'USD', 100.0],
624+
[pd.Period(str(2020)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_HAZARD_NAME, 'USD', 0.0],
625+
[pd.Period(str(2021)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_HAZARD_NAME, 'USD', 10.0],
626+
[pd.Period(str(2022)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_HAZARD_NAME, 'USD', 20.0],
627+
[pd.Period(str(2020)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_VULNERABILITY_NAME, 'USD', 0.0],
628+
[pd.Period(str(2021)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_VULNERABILITY_NAME, 'USD', -5.0],
629+
[pd.Period(str(2022)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_VULNERABILITY_NAME, 'USD', -10.0],
630+
[pd.Period(str(2020)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_INTERACTION_TERM_NAME, 'USD', 0.0],
631+
[pd.Period(str(2021)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_INTERACTION_TERM_NAME, 'USD', 3.75],
632+
[pd.Period(str(2022)), 'All', NO_MEASURE_VALUE, CONTRIBUTION_INTERACTION_TERM_NAME, 'USD', -10.0]],
633+
'index_names': [None],
634+
'column_names': [None]},
635+
# fmt: on
636+
orient="tight",
637+
)
638+
pd.testing.assert_frame_equal(
639+
interp_traj.risk_contributions_metrics(),
640+
expected,
641+
check_dtype=False,
642+
check_categorical=False,
643+
)

climada/trajectories/riskperiod.py

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -635,54 +635,48 @@ def E1H1V1(self) -> Impact:
635635

636636
### Impact Matrices arrays ####
637637

638+
def _interp_mats(self, start_attr, end_attr) -> list:
639+
"""Helper to reduce repetition in impact matrix interpolation."""
640+
start = getattr(self, start_attr).imp_mat
641+
end = getattr(self, end_attr).imp_mat
642+
return self.interpolation_strategy.interp_over_exposure_dim(
643+
start, end, self.time_points
644+
)
645+
638646
@property
639647
def imp_mats_H0V0(self) -> list:
640648
"""List of `time_points` impact matrices with changing exposure, starting hazard and starting vulnerability."""
641-
return self.interpolation_strategy.interp_over_exposure_dim(
642-
self.E0H0V0.imp_mat, self.E1H0V0.imp_mat, self.time_points
643-
)
649+
return self._interp_mats("E0H0V0", "E1H0V0")
644650

645651
@property
646652
def imp_mats_H1V0(self) -> list:
647653
"""List of `time_points` impact matrices with changing exposure, future hazard and starting vulnerability."""
648-
return self.interpolation_strategy.interp_over_exposure_dim(
649-
self.E0H1V0.imp_mat, self.E1H1V0.imp_mat, self.time_points
650-
)
654+
return self._interp_mats("E0H1V0", "E1H1V0")
651655

652656
@property
653657
def imp_mats_H0V1(self) -> list:
654658
"""List of `time_points` impact matrices with changing exposure, starting hazard and future vulnerability."""
655-
return self.interpolation_strategy.interp_over_exposure_dim(
656-
self.E0H0V1.imp_mat, self.E1H0V1.imp_mat, self.time_points
657-
)
659+
return self._interp_mats("E0H0V1", "E1H0V1")
658660

659661
@property
660662
def imp_mats_H1V1(self) -> list:
661663
"""List of `time_points` impact matrices with changing exposure, future hazard and future vulnerability."""
662-
return self.interpolation_strategy.interp_over_exposure_dim(
663-
self.E0H1V1.imp_mat, self.E1H1V1.imp_mat, self.time_points
664-
)
664+
return self._interp_mats("E0H1V1", "E1H1V1")
665665

666666
@property
667667
def imp_mats_E0H0V0(self) -> list:
668668
"""List of `time_points` impact matrices with base exposure, base hazard and base vulnerability."""
669-
return self.interpolation_strategy.interp_over_exposure_dim(
670-
self.E0H0V0.imp_mat, self.E0H0V0.imp_mat, self.time_points
671-
)
669+
return self._interp_mats("E0H0V0", "E0H0V0")
672670

673671
@property
674672
def imp_mats_E0H1V0(self) -> list:
675673
"""List of `time_points` impact matrices with base exposure, future hazard and base vulnerability."""
676-
return self.interpolation_strategy.interp_over_exposure_dim(
677-
self.E0H1V0.imp_mat, self.E0H1V0.imp_mat, self.time_points
678-
)
674+
return self._interp_mats("E0H1V0", "E0H1V0")
679675

680676
@property
681677
def imp_mats_E0H0V1(self) -> list:
682-
"""List of `time_points` impact matrices with base exposure, future hazard and base vulnerability."""
683-
return self.interpolation_strategy.interp_over_exposure_dim(
684-
self.E0H0V1.imp_mat, self.E0H0V1.imp_mat, self.time_points
685-
)
678+
"""List of `time_points` impact matrices with base exposure, base hazard and base vulnerability."""
679+
return self._interp_mats("E0H0V1", "E0H0V1")
686680

687681
###############################
688682

@@ -720,7 +714,7 @@ def per_date_eai_H1V1(self) -> np.ndarray:
720714
def per_date_eai_E0H0V0(self) -> np.ndarray:
721715
"""Expected annual impacts for base exposure, base hazard and base vulnerability."""
722716
return calc_per_date_eais(
723-
self.imp_mats_E0H0V0, self.snapshot_end.hazard.frequency
717+
self.imp_mats_E0H0V0, self.snapshot_start.hazard.frequency
724718
)
725719

726720
@property
@@ -734,7 +728,7 @@ def per_date_eai_E0H1V0(self) -> np.ndarray:
734728
def per_date_eai_E0H0V1(self) -> np.ndarray:
735729
"""Expected annual impacts for base exposure, future hazard and base vulnerability."""
736730
return calc_per_date_eais(
737-
self.imp_mats_E0H0V1, self.snapshot_end.hazard.frequency
731+
self.imp_mats_E0H0V1, self.snapshot_start.hazard.frequency
738732
)
739733

740734
##################################

0 commit comments

Comments
 (0)