@@ -788,7 +788,7 @@ def calc_freq_curve(self, return_per=None):
788788 if return_per is not None :
789789 warnings .warn (
790790 "Calculating the frequency curve on user-specified return periods is deprecated. "
791- "Use ImpactFreqCurve.extrapolate () instead." ,
791+ "Use ImpactFreqCurve.calc_freq_curve().interpolate () instead." ,
792792 DeprecationWarning ,
793793 stacklevel = 2 ,
794794 )
@@ -2287,19 +2287,28 @@ def plot(self, axis=None, log_frequency=False, **kwargs):
22872287 -------
22882288 matplotlib.axes.Axes
22892289 """
2290-
2291- return self ._plot (
2292- self .return_per ,
2293- self .impact ,
2294- axis ,
2295- log_frequency ,
2296- self .frequency_unit ,
2297- self .unit ,
2298- self .label ,
2299- ** kwargs ,
2290+ # check frequency unit
2291+ return_period_unit = u_dt .convert_frequency_unit_to_time_unit (
2292+ self .frequency_unit
23002293 )
23012294
2302- def extrapolate (
2295+ if not axis :
2296+ _ , axis = plt .subplots (1 , 1 )
2297+ axis .set_title (self .label )
2298+ axis .set_ylabel ("Impact (" + self .unit + ")" )
2299+
2300+ if log_frequency :
2301+ axis .set_xlabel (f"Exceedance frequency ({ self .frequency_unit } )" )
2302+ axis .set_xscale ("log" )
2303+ axis .plot (self .return_per ** - 1 , self .impact , ** kwargs )
2304+
2305+ else :
2306+ axis .set_xlabel (f"Return period ({ return_period_unit } )" )
2307+ axis .plot (self .return_per , self .impact , ** kwargs )
2308+
2309+ return axis
2310+
2311+ def interpolate (
23032312 self ,
23042313 return_periods ,
23052314 * ,
@@ -2310,7 +2319,7 @@ def extrapolate(
23102319 bin_decimals = None ,
23112320 y_asymptotic = 0.0 ,
23122321 ):
2313- """Extrapolate impact frequency curve with different interpolation and extrapolation options .
2322+ """Interpolate and extrapolate impact frequency curve using different methods .
23142323
23152324 Parameters
23162325 ----------
@@ -2348,8 +2357,8 @@ def extrapolate(
23482357
23492358 Returns
23502359 -------
2351- np.array
2352- array of exceeded impacts at given return periods
2360+ ImpactFreqCurve
2361+ impact frequency curve with inter- and extrapolated values
23532362
23542363 See Also
23552364 --------
@@ -2363,7 +2372,7 @@ def extrapolate(
23632372 impacts = np .squeeze (np .array (self .impact )[sorted_idxs ])
23642373 rps = np .asarray (self .return_per )[sorted_idxs ]
23652374 frequency = np .diff (1 / np .array (rps )[::- 1 ], prepend = 0 )[::- 1 ]
2366- return u_interp .preprocess_and_interpolate_ev (
2375+ impact_interpolated = u_interp .preprocess_and_interpolate_ev (
23672376 exceedance_frequency ,
23682377 None ,
23692378 frequency ,
@@ -2376,154 +2385,10 @@ def extrapolate(
23762385 bin_decimals = bin_decimals ,
23772386 )
23782387
2379- def plot_extrapolate (
2380- self ,
2381- * ,
2382- return_periods = None ,
2383- axis = None ,
2384- log_frequency = False ,
2385- kwargs_interp = None ,
2386- ** kwargs ,
2387- ):
2388- """Plot impact frequency curve with interpolation and extrapolation options.
2389-
2390- Parameters
2391- ----------
2392- return_periods : Iterable[float], optional
2393- Return period values to plot, e.g. np.linspace(5, 500, 1000) to plot between 5 and
2394- 500 years. If None, the plot range defined between 0.5*min(data_return_periods) and
2395- 1.2*max(data_return_periods), where data_return_periods are the return period values
2396- extracted from the impact object's data. Defaults to None.
2397- axis : matplotlib.axes.Axes, optional
2398- axis to use
2399- log_frequency : boolean, optional
2400- plot logarithmioc exceedance frequency on x-axis
2401- kwargs_interp : dict, optional
2402- dict with (key, value) pairs to handle inter- and extrapolation behaviour, e.g.
2403- {"method": "extrapolate"}. Default is {"method": "interpolate", "log_frequency": True,
2404- "log_impact": True, "min_impact": 0, "bin_decimals": None}. Available options are
2405- method : str, optional
2406- Method to interpolate to new return periods. Currently available are
2407- "interpolate", "extrapolate", "extrapolate_constant" and "stepfunction". If set
2408- to "interpolate", return periods outside the range of the Impact object's observed
2409- return periods will be assigned NaN. If set to "extrapolate_constant" or
2410- "stepfunction", return periods larger than the Impact object's observed return
2411- periods will be assigned the largest impact, and return periods smaller than the
2412- Impact object's observed return periods will be assigned 0. If set to
2413- "extrapolate", exceedance impacts will be extrapolated (and interpolated). The
2414- extrapolation to large return periods uses the two highest impacts of the centroid
2415- and their return periods and extends the interpolation between these points to the
2416- given return period (similar for small return periods). Defauls to "interpolate".
2417- min_impact : float, optional
2418- Minimum threshold to filter the impact. Defaults to 0.
2419- log_frequency : bool, optional
2420- If set to True, (cummulative) frequency values are converted to log scale before
2421- inter- and extrapolation. Defaults to True.
2422- log_impact : bool, optional
2423- If set to True, impact values are converted to log scale before
2424- inter- and extrapolation. Defaults to True.
2425- bin_decimals : int, optional
2426- Number of decimals to group and bin impact values. Binning results in smoother
2427- (and coarser) interpolation and more stable extrapolation. For more details and
2428- sensible values for bin_decimals, see Notes. If None, values are not binned.
2429- Defaults to None.
2430- y_asymptotic : float, optional
2431- Has no effect if method is "interpolate". Else, if data size < 2 or if method
2432- is set to "extrapolate_constant" or "stepfunction", it provides return value for
2433- exceeded impact for return periods smaller than the data range. Defaults to 0.
2434- kwargs : dict, optional
2435- arguments for plot matplotlib function, e.g. color='b'
2436-
2437- Returns
2438- -------
2439- matplotlib.axes.Axes
2440-
2441- See Also
2442- --------
2443- climada.engine.impact.ImpactFreqCurve.extrapolate:
2444- extrapolation method used in the plotting function
2445- util.interpolation.preprocess_and_interpolate_ev :
2446- inter- and extrapolation method
2447- """
2448- if kwargs_interp is None :
2449- kwargs_interp = {}
2450- kwargs_interp = {
2451- "method" : "interpolate" ,
2452- "log_frequency" : True ,
2453- "log_impact" : True ,
2454- "min_impact" : 0.0 ,
2455- "bin_decimals" : None ,
2456- "y_asymptotic" : 0.0 ,
2457- } | kwargs_interp
2458-
2459- if return_periods is None :
2460- return_periods = np .linspace (
2461- 0.5 * min (self .return_per ), 1.2 * max (self .return_per ), 500
2462- )
2463-
2464- impacts = self .extrapolate (return_periods , ** kwargs_interp )
2465-
2466- # check frequency unit
2467- return_period_unit = u_dt .convert_frequency_unit_to_time_unit (
2468- self .frequency_unit
2388+ return ImpactFreqCurve (
2389+ return_per = return_periods ,
2390+ impact = impact_interpolated ,
2391+ unit = self .unit ,
2392+ frequency_unit = self .frequency_unit ,
2393+ label = self .label ,
24692394 )
2470-
2471- if not axis :
2472- _ , axis = plt .subplots (1 , 1 )
2473- axis .set_title (self .label )
2474- axis .set_ylabel ("Impact (" + self .unit + ")" )
2475- if log_frequency :
2476- axis .set_xlabel (f"Exceedance frequency ({ self .frequency_unit } )" )
2477- axis .set_xscale ("log" )
2478- x_vals = return_periods ** - 1
2479- else :
2480- axis .set_xlabel (f"Return period ({ return_period_unit } )" )
2481- x_vals = return_periods
2482-
2483- # plot extrapolated data as dashed line
2484- if kwargs_interp ["method" ] == "interpolate" :
2485- axis .plot (x_vals , impacts , linestyle = "-" , ** kwargs )
2486- else :
2487- kwargs_copy = kwargs .copy ()
2488- color = kwargs_copy .pop ("color" , None )
2489- min_rp = min (self .return_per )
2490- max_rp = max (self .return_per )
2491- mask = (return_periods >= min_rp ) & (return_periods <= max_rp )
2492-
2493- line_data = axis .plot (
2494- x_vals [mask ], impacts [mask ], linestyle = "-" , color = color , ** kwargs_copy
2495- )[0 ]
2496- color = line_data .get_color ()
2497- axis .plot (x_vals , impacts , linestyle = "--" , color = color , ** kwargs_copy )
2498-
2499- return axis
2500-
2501- @staticmethod
2502- def _plot (
2503- return_per ,
2504- impact ,
2505- axis ,
2506- log_frequency ,
2507- frequency_unit ,
2508- unit ,
2509- title ,
2510- ** kwargs ,
2511- ):
2512- """
2513- private function to plot an impact's exceedance frequency curve
2514- """
2515- # check frequency unit
2516- return_period_unit = u_dt .convert_frequency_unit_to_time_unit (frequency_unit )
2517-
2518- if not axis :
2519- _ , axis = plt .subplots (1 , 1 )
2520- axis .set_title (title )
2521- axis .set_ylabel ("Impact (" + unit + ")" )
2522- if log_frequency :
2523- axis .set_xlabel (f"Exceedance frequency ({ frequency_unit } )" )
2524- axis .set_xscale ("log" )
2525- axis .plot (return_per ** - 1 , impact , ** kwargs )
2526- else :
2527- axis .set_xlabel (f"Return period ({ return_period_unit } )" )
2528- axis .plot (return_per , impact , ** kwargs )
2529- return axis
0 commit comments