"""recprec.py

Functions to calculate recall and precision.

Functions:
calc_recall
calc_precision
calc_f
calc_tradeoff_curve

interpolate_precision

"""
import operator

def calc_recall(tp, total):
    """calc_recall(tp, total) -> recall"""
    return float(tp) / total

def calc_precision(tp, all_positive):
    """calc_precision(tp, all_positive) -> precision"""
    return float(tp) / all_positive

def calc_f(recall, precision):
    if not recall and not precision:
        return 0.0
    return 2.*recall*precision/(recall+precision)

def calc_tradeoff_curve(is_true_positive, total, interpolated=0):
    """calc_tradeoff_curve(is_true_positive, total[, interpolated]) -> list of (recall, precision)

    XXX is_true_positive is a list of 1, 0 of whether it's a true positive
    total is the total number of things tested

    """
    if total is None:
        total = len([x for x in is_true_positive if x])
    recprec = []
    num_tp = 0
    for i in range(len(is_true_positive)):
        num_tp += operator.truth(is_true_positive[i])
        rec = calc_recall(num_tp, total)
        prec = calc_precision(num_tp, (i+1))
        recprec.append((rec, prec))
    if interpolated and recprec:
        interp = interpolate_precision([x[1] for x in recprec])
        recprec = [(recprec[i][0], interp[i]) for i in range(len(recprec))]
    return recprec

def interpolate_precision(precs):
    interp = precs[:]
    max_prec = precs[-1]
    for i in range(len(precs)-2, -1, -1):
        max_prec = max(precs[i], max_prec)
        interp[i] = max_prec
    return interp
