def _propagate_pair(pair, go_dict):
    """Propagates a pair of annotations.

    For a given pair of annotation terms, the GO annotations will
    be replaced by a set of their (recursive) child terms (including itself).

    Other types of annotations are left untouched, but converted to a 1-member
    set.

    Parameters
    ----------
    pair : tuple
        A sorted tuples of annotation terms, one for the host and one for
        the pathogen, e.g. ('h@GO:0030133', 'p@IPR009304')
    go_dict : dict
        A dictionary containing the GO hierarchy. Constructed via the
        obo_tools.importOBO() function in the goscripts package.

    Returns
    -------
    tuple
        A sorted tuple of annotation term sets, one for the host and
        one for the pathogen. Each element in the tuple consists of a set of
        terms, e.g. the GO term itself and all of its descendants.
    """

    # create empty list to store the propagated (child) annotations for the
    # two parent annotations in the pair (in same order as original pair)
    propagated_pair = []
    # for both annotations in the pair, propagate through GO hierarchy
    for term in pair:
        # only for GO terms, not IPR
        if 'GO' in term:
            prefix = term[:2]
            go_object = go_dict.get(term[2:])
            # append original annotation if it can't be found in GO dict
            if not go_object:
                propagated_pair.append([term])
            else:
                # store all child terms of parent term in a list
                child_terms = [
                    prefix + i for i in go_object.recursive_children
                ]
                # add parent term itself and remove duplicates
                propagation_set = set(child_terms) | set([term])
                # add propagated annotations to storage list
                propagated_pair.append(propagation_set)
        else:
            # store original term if it's not a GO term
            propagated_pair.append({term})

    # convert the length-2 list of annotation lists (1 for each parent
    # annotation) to a tuple
    # # e.g. ('h@GO:0060384', 'p@GO:0016787') ->
    # ({'h@GO:0098546', 'h@GO:0030553', 'h@GO:0035438', 'h@GO:0030552',
    # 'h@GO:0061507'},
    # {'h@GO:0098546', 'h@GO:0030553', 'h@GO:0035438',# 'h@GO:0030552',
    # 'h@GO:0061507'})
    return tuple(propagated_pair)