Find nearest annotated upstream/downstream donor/acceptor for novel
    donor/acceptors.

    Parameters
    ----------
    annot : pandas.DataFrame
        Dataframe with observed splice junctions (novel and known) with columns
        'chrom', 'first_bp_intron', 'last_bp_intron', 'strand', 'intron_motif',
        'annotated', 'ext_annotated', 'chrom:start', 'chrom:end', 'gene_id',
        'donor', 'acceptor', 'novel_donor', 'novel_acceptor'.

    ext : pandas.DataFrame 
        Dataframe with splice junction information from external database
        containing columns 'gene', 'chrom', 'start', 'end', 'strand',
        'chrom:start', 'chrom:end', 'donor', 'acceptor', 'intron'.

    Returns
    -------
    annot : pandas.DataFrame
        Annotation information with added columns for distance from novel
        donor/acceptor to nearest upstream/downstream donor/acceptor.

def _find_novel_donor_acceptor_dist(annot, ext):
    """Find nearest annotated upstream/downstream donor/acceptor for novel
    donor/acceptors.

    Parameters
    ----------
    annot : pandas.DataFrame
        Dataframe with observed splice junctions (novel and known) with columns
        'chrom', 'first_bp_intron', 'last_bp_intron', 'strand', 'intron_motif',
        'annotated', 'ext_annotated', 'chrom:start', 'chrom:end', 'gene_id',
        'donor', 'acceptor', 'novel_donor', 'novel_acceptor'.

    ext : pandas.DataFrame 
        Dataframe with splice junction information from external database
        containing columns 'gene', 'chrom', 'start', 'end', 'strand',
        'chrom:start', 'chrom:end', 'donor', 'acceptor', 'intron'.

    Returns
    -------
    annot : pandas.DataFrame
        Annotation information with added columns for distance from novel
        donor/acceptor to nearest upstream/downstream donor/acceptor.
    
    """
    pos_donor_to_acceptors = _make_splice_targets_dict(ext, 'donor', '+')
    pos_acceptor_to_donors = _make_splice_targets_dict(ext, 'acceptor', '+')
    neg_donor_to_acceptors = _make_splice_targets_dict(ext, 'donor', '-')
    neg_acceptor_to_donors = _make_splice_targets_dict(ext, 'acceptor', '-')

    annot = copy.deepcopy(annot)
    annot['upstream_donor_dist'] = np.nan
    annot['downstream_donor_dist'] = np.nan
    annot['upstream_acceptor_dist'] = np.nan
    annot['downstream_acceptor_dist'] = np.nan

    juncs = annot[annot.novel_donor & (annot.strand == '+')].index
    up, down = _dist_to_annot_donor_acceptor(annot.ix[juncs], 
                                             pos_acceptor_to_donors,
                                             '+', 
                                             'donor')
    annot.ix[juncs, 'upstream_donor_dist'] = up
    annot.ix[juncs, 'downstream_donor_dist'] = down

    juncs = annot[annot.novel_donor & (annot.strand == '-')].index
    up, down = _dist_to_annot_donor_acceptor(annot.ix[juncs], 
                                             neg_acceptor_to_donors,
                                             '-', 
                                             'donor')
    annot.ix[juncs, 'upstream_donor_dist'] = up
    annot.ix[juncs, 'downstream_donor_dist'] = down

    juncs = annot[annot.novel_acceptor & (annot.strand == '+')].index
    up, down = _dist_to_annot_donor_acceptor(annot.ix[juncs], 
                                             pos_donor_to_acceptors, 
                                             '+', 
                                             'acceptor')
    annot.ix[juncs, 'upstream_acceptor_dist'] = up
    annot.ix[juncs, 'downstream_acceptor_dist'] = down

    juncs = annot[annot.novel_acceptor & (annot.strand == '-')].index
    up, down = _dist_to_annot_donor_acceptor(annot.ix[juncs], 
                                             neg_donor_to_acceptors, 
                                             '-', 
                                             'acceptor')
    annot.ix[juncs, 'upstream_acceptor_dist'] = up
    annot.ix[juncs, 'downstream_acceptor_dist'] = down
    return annot