def voc_ap(recall, precision):
    """
    Calculate the AP given the recall and precision array
    1) We calculate a version of the measured
    precision/recall curve with precision monotonically decreasing
    2) We calculate the AP as the area
    under this curve by numerical integration.
    """
    """
    --- Official matlab code VOC2012---
    m_recall=[0 ; recall ; 1];
    m_precision=[0 ; precision ; 0];
    for j=numel(m_precision)-1:-1:1
            m_precision(i)=max(m_precision(j),m_precision(j+1));
    end
    i=find(m_recall(2:end)~=m_recall(1:end-1))+1;
    ap=sum((m_recall(i)-m_recall(i-1)).*m_precision(i));
    """
    recall.insert(0, 0.0)  # insert 0.0 at beginning of list
    recall.append(1.0)  # insert 1.0 at end of list
    m_recall = recall[:]
    precision.insert(0, 0.0)  # insert 0.0 at beginning of list
    precision.append(0.0)  # insert 0.0 at end of list
    m_precision = precision[:]
    """
    This part makes the precision monotonically decreasing
        (goes from the end to the beginning)
        matlab: for i=numel(m_precision)-1:-1:1
                    m_precision(i)=max(m_precision(i),m_precision(i+1));
    """

    for i in range(len(m_precision) - 2, -1, -1):
        m_precision[i] = max(m_precision[i], m_precision[i + 1])
    """
     This part creates a list of indexes where the recall changes
        matlab: i=find(m_recall(2:end)~=m_recall(1:end-1))+1;
    """
    i_list = []
    for i in range(1, len(m_recall)):
        if m_recall[i] != m_recall[i - 1]:
            i_list.append(i)  # if it was matlab would be i + 1
    """
     The Average Precision (AP) is the area under the curve
        (numerical integration)
        matlab: ap=sum((m_recall(i)-m_recall(i-1)).*m_precision(i));
    """
    ap = 0.0
    for i in i_list:
        ap += ((m_recall[i] - m_recall[i - 1]) * m_precision[i])
    return ap, m_recall, m_precision