def relabel(residue_contacts, residuelabels):
    """
    Relabel and filter residue contacts according to the residuelabel dictionary. If the labels dictionary is None then
    just return the input residue_contacts

    For example:
        contacts = [
            [0, 'A:ARG:110', 'A:ASN:108'],
            [0, 'A:FOL:200', 'A:ASN:108'],
            [0, 'A:NDP:201', 'A:ASN:108'],
            [1, 'A:ARG:110', 'A:NDP:201']
        ]
        labels = {'A:ARG:110': 'R110', 'A:ASN:108': 'N108', 'A:NDP:201': 'Ligand', 'A:FOL:200': 'Ligand'}
        relabel(contacts, labels)
        # => [(0, 'N108', 'R110'), (0, 'Ligand', 'N108'), (1, 'Ligand', 'R110')]
        relabel(contacts, None)
        # => [
        #      [0, 'A:ARG:110', 'A:ASN:108'],
        #      [0, 'A:FOL:200', 'A:ASN:108'],
        #      [0, 'A:NDP:201', 'A:ASN:108'],
        #      [1, 'A:ARG:110', 'A:NDP:201']
        #    ]

    Parameters
    ----------
    residue_contacts: list of list
        List of residue contacts specified as a framenumber and two residue identifiers
    residuelabels: dict of (str: str)
        Remaps and filters residuelabels, e.g. {"A:ARG:4": "R4"}

    Returns
    -------
    List of tuple
        Remapped and filtered residue-contacts specified as tuple of (int, string, string). Frames are guaranteed
        to be sorted
    """
    if residuelabels is None:
        return residue_contacts

    ret = set()
    for frame, res1, res2 in residue_contacts:
        if res1 in residuelabels and res2 in residuelabels:
            res1 = residuelabels[res1]
            res2 = residuelabels[res2]
            if res1 == res2:
                continue
            if res1 > res2:
                res1, res2 = res2, res1
            ret.add((frame, res1, res2))
    return sorted(list(ret), key=lambda c: c[0])