def losses_by_period(losses, return_periods, num_events=None, eff_time=None):
    """
    :param losses: array of simulated losses
    :param return_periods: return periods of interest
    :param num_events: the number of events (>= to the number of losses)
    :param eff_time: investigation_time * ses_per_logic_tree_path
    :returns: interpolated losses for the return periods, possibly with NaN

    NB: the return periods must be ordered integers >= 1. The interpolated
    losses are defined inside the interval min_time < time < eff_time
    where min_time = eff_time /num_events. Outside the interval they
    have NaN values. Here is an example:

    >>> losses = [3, 2, 3.5, 4, 3, 23, 11, 2, 1, 4, 5, 7, 8, 9, 13]
    >>> losses_by_period(losses, [1, 2, 5, 10, 20, 50, 100], 20)
    array([ nan,  nan,  0. ,  3.5,  8. , 13. , 23. ])

    If num_events is not passed, it is inferred from the number of losses;
    if eff_time is not passed, it is inferred from the longest return period.
    """
    if len(losses) == 0:  # zero-curve
        return numpy.zeros(len(return_periods))
    if num_events is None:
        num_events = len(losses)
    elif num_events < len(losses):
        raise ValueError(
            'There are not enough events (%d) to compute the loss curve '
            'from %d losses' % (num_events, len(losses)))
    if eff_time is None:
        eff_time = return_periods[-1]
    losses = numpy.sort(losses)
    num_zeros = num_events - len(losses)
    if num_zeros:
        losses = numpy.concatenate(
            [numpy.zeros(num_zeros, losses.dtype), losses])
    periods = eff_time / numpy.arange(num_events, 0., -1)
    rperiods = [rp if periods[0] <= rp <= periods[-1] else numpy.nan
                for rp in return_periods]
    curve = numpy.interp(numpy.log(rperiods), numpy.log(periods), losses)
    return curve
def losses_by_period ( losses , return_periods , num_events = None , eff_time = None ) : if len ( losses ) == 0 : return numpy . zeros ( len ( return_periods ) ) if num_events is None : num_events = len ( losses ) elif num_events < len ( losses ) : raise ValueError ( 'There are not enough events (%d) to compute the loss curve ' 'from %d losses' % ( num_events , len ( losses ) ) ) if eff_time is None : eff_time = return_periods [ - 1 ] losses = numpy . sort ( losses ) num_zeros = num_events - len ( losses ) if num_zeros : losses = numpy . concatenate ( [ numpy . zeros ( num_zeros , losses . dtype ) , losses ] ) periods = eff_time / numpy . arange ( num_events , 0. , - 1 ) rperiods = [ rp if periods [ 0 ] <= rp <= periods [ - 1 ] else numpy . nan for rp in return_periods ] curve = numpy . interp ( numpy . log ( rperiods ) , numpy . log ( periods ) , losses ) return curve
:param losses: array of simulated losses
    :param return_periods: return periods of interest
    :param num_events: the number of events (>= to the number of losses)
    :param eff_time: investigation_time * ses_per_logic_tree_path
    :returns: interpolated losses for the return periods, possibly with NaN

    NB: the return periods must be ordered integers >= 1. The interpolated
    losses are defined inside the interval min_time < time < eff_time
    where min_time = eff_time /num_events. Outside the interval they
    have NaN values. Here is an example:

    >>> losses = [3, 2, 3.5, 4, 3, 23, 11, 2, 1, 4, 5, 7, 8, 9, 13]
    >>> losses_by_period(losses, [1, 2, 5, 10, 20, 50, 100], 20)
    array([ nan,  nan,  0. ,  3.5,  8. , 13. , 23. ])

    If num_events is not passed, it is inferred from the number of losses;
    if eff_time is not passed, it is inferred from the longest return period.