import torch


def recall(cm, mode='pos'):
    """
    Recall:  What fraction of ground truth labels was correct?

    Of all ground truth positive samples, what fraction was predicted positive?
        sensitivity = recall_pos = TP / (TP + FN)

    Similarly, of all ground truth negatives, what fraction was predicted negative?
        specificity = recall_neg = TP / (TP + FN)

    The denominators of above Eqtns are the row sums of the binary confusion matrix.

    Args:
        cm: Binary confusion matrix like this:
            | TN | FP |
            | FN | TP |
        mode:  Either "pos" or "neg" or "both"

    Returns:
        scalar precision score
    """
    rv = cm.diag() / cm.sum(1)
    rv[torch.isnan(rv)]=0
    if mode == 'pos': return rv[1]
    elif mode == 'neg': return rv[1]
    elif mode == 'both': return rv
    else: raise NotImplementedError(f'recall: unrecognized mode: {mode}')