5959
6060
6161class StaticRiskTrajectory (RiskTrajectory ):
62- """This class implements static risk trajectories, objects that
62+ """This class implements static risk trajectories: objects that
6363 regroup impacts computations for multiple dates.
6464
65- This class computes risk metrics over a series of snapshots,
66- optionally applying risk discounting. It does not interpolate risk
67- between the snapshot and only provides results for each snapshot.
65+ This class computes risk metrics over a series of `Snapshot` objects,
66+ optionally applying risk discounting, and offers access to the results
67+ in tidy formatted pandas DataFrames.
68+
69+ Contrary to InterpolatedRiskTrajectories, it does not interpolate risk
70+ between the snapshot and only provides results at each snapshot specific
71+ date.
6872
6973 """
7074
@@ -115,7 +119,7 @@ def __init__(
115119 The discount rate to apply to future risk. Defaults to None.
116120 impact_computation_strategy: ImpactComputationStrategy, optional
117121 The method used to calculate the impact from the (Haz,Exp,Vul)
118- of the two snapshots . Defaults to :class:`ImpactCalcComputation`.
122+ for each snapshot . Defaults to :class:`ImpactCalcComputation`.
119123
120124 """
121125 super ().__init__ (
@@ -137,7 +141,11 @@ def impact_computation_strategy(self) -> ImpactComputationStrategy:
137141 @impact_computation_strategy .setter
138142 def impact_computation_strategy (self , value , / ):
139143 if not isinstance (value , ImpactComputationStrategy ):
140- raise ValueError ("Not an interpolation strategy" )
144+ raise ValueError (
145+ "The provided impact computation strategy is not an ImpactComputationStrategy, "
146+ "please refer to the documentation to define your own strategies or stick to the "
147+ "default one"
148+ )
141149
142150 self ._reset_metrics ()
143151 self ._risk_metrics_calculators .impact_computation_strategy = value
@@ -174,6 +182,15 @@ def _generic_metrics(
174182 A tidy formatted dataframe of the risk metric computed for the
175183 different snapshots.
176184
185+ Notes
186+ -----
187+
188+ The computation checks that there are no duplicated rows of results
189+ for the same tuples (Date, Group, Measure, Metric,
190+ [Coordinates for metrics on that level]) and takes the first row in
191+ this case.
192+
193+
177194 Raises
178195 ------
179196 NotImplementedError
@@ -211,7 +228,12 @@ def _generic_metrics(
211228 # When more than 2 snapshots, there might be duplicated rows, we need to remove them.
212229 # Should not be the case in static trajectory, but in any case we really don't want
213230 # duplicated rows, which would mess up some dataframe manipulation down the road.
214- tmp = tmp [~ tmp .index .duplicated (keep = "first" )]
231+ if tmp .index .duplicated ().any ():
232+ LOGGER .warning (
233+ "Duplicated rows were found in the results. Will keep the first one."
234+ )
235+ tmp = tmp [~ tmp .index .duplicated (keep = "first" )]
236+
215237 tmp = tmp .reset_index ()
216238 if self ._all_groups_name not in tmp [GROUP_COL_NAME ].cat .categories :
217239 tmp [GROUP_COL_NAME ] = tmp [GROUP_COL_NAME ].cat .add_categories (
@@ -236,7 +258,8 @@ def eai_metrics(self, **kwargs) -> pd.DataFrame:
236258 Notes
237259 -----
238260
239- This computation may become quite expensive for big areas with high resolution.
261+ This computation may become quite expensive for exposures with many points
262+ (e.g., big areas with high resolution).
240263
241264 """
242265 metric_df = self ._compute_metrics (
0 commit comments