TO DO: Add logit bounds
    Determine ROC enrichment factor (EF) and 95% confidence intervals (CI) at input false positive fraction (fpf)
    None is returned if fpf is undefined given the total no. of decoys
    :param ef_structure: list [(id, best_score, best_query, status, gamma), ..., ]
    gamma is 1 if the score of the molecule is better than the false positive threshold and 0 otherwise
    :param fpf: float
    :return (fpf, EF, EF - CI, EF + CI) or None: tuple or None

def calculate_ef(ef_structure, fpf, diff = None, include_intervals = None):
    """
    TO DO: Add logit bounds
    Determine ROC enrichment factor (EF) and 95% confidence intervals (CI) at input false positive fraction (fpf)
    None is returned if fpf is undefined given the total no. of decoys
    :param ef_structure: list [(id, best_score, best_query, status, gamma), ..., ]
    gamma is 1 if the score of the molecule is better than the false positive threshold and 0 otherwise
    :param fpf: float
    :return (fpf, EF, EF - CI, EF + CI) or None: tuple or None
    """

    # set variables
    n = len([x for x in ef_structure if x[3] == '0'])          # no of decoys
    p = len([x for x in ef_structure if x[3] == '1'])          # no of actives


    if not fpf:
        fpf = float(1) / n

    # calculate tpf at fpf threshold tpf = E(gamma)a
    actives, decoys = splitter(ef_structure)
    tpf = 0
    for mol in actives:
        gamma = mol[4]
        tpf += gamma
    tpf = (1. / p) * tpf

    # calculate enrichment factor (ef)
    ef = tpf / fpf

    if diff:
        # active & decoy variances are independently determined in the difference calculations
        return ef, tpf
    elif include_intervals:
        # standard error
        if ef != 0:
            efvar_a, efvar_d, s2 = calculate_ef_var(tpf, fpf)
            se = (1 / fpf) * ((efvar_a / p) + s2 * (efvar_d / n) ) ** 0.5

            # 95% confidence interval
            ci = se * stats.t.ppf(1 - 0.025, n + p - 1)

            # bounds
            lower = ef - ci
            upper = ef + ci

            # dumb limit checking (ADD LOGIT FUNCTION)
            if lower < 0:
                lower = 0.0
            if upper > 1 / fpf:
                upper = 1 / fpf

            return (fpf, ef, lower, upper)
        else:
            # when the ef is 0, there's problems with taking its logarithm. This is a
            # temporary work around put in place 2/12/15.
            return(fpf, ef, 0, 0)
    else:
        decoy_threshold = int(round(n * fpf))   # number of decoys corresponding to fpf
        return (decoy_threshold, ef)