In [1]:
from collections import OrderedDict
exp = 'seq,peaks,OSN,0,10,1,FALSE,same,0.5,64,50,0.004,9,FALSE,[1,50],TRUE,TRUE'
imp_score = 'profile/wn'

motifs = OrderedDict([
    ("Oct4-Sox2", "Oct4/m0_p0"),
    ("Oct4", "Oct4/m0_p5"),
    ("Sox2", "Sox2/m0_p1"),
    ("Nanog", "Nanog/m0_p1")
])

gpu = 2  # Set to None if GPU shouldn't be used

motifs_inv = {v:k for k,v in motifs.items()}

Goal

  • Visualize the Oct4-distal enhancer region
In [2]:
# Imports
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
from basepair.imports import *

from basepair.exp.paper.config import *
from basepair.seqmodel import SeqModel
from basepair.BPNet import model2tasks
from basepair.models import seq_bpnet_cropped_extra_seqlen
from basepair.preproc import resize_interval, parse_interval
from basepair.seqmodel import SeqModel
from basepair.utils import unflatten
from genomelake.extractors import FastaExtractor
from concise.preprocessing.sequence import one_hot2string, DNA
from kipoi.utils import unique_list

import pybedtools
from basepair.utils import flatten_list
paper_config()
Using TensorFlow backend.
In [3]:
if gpu is not None:
    create_tf_session(gpu)
In [4]:
# Common paths
model_dir = models_dir / exp
# figures = f"{ddir}/figures/model-evaluation/chipnexus-bpnet/{exp}/known_enhancer_profiles"
figures = Path(f'{ddir}/figures/modisco/{exp}')

!mkdir -p {figures}/known_enhancer_profiles
In [5]:
# Dataspec
ds = DataSpec.load(rdir / 'src/chipnexus/train/seqmodel/ChIP-seq.dataspec.yml')
In [6]:
tasks = ['Oct4', 'Sox2', 'Nanog']
In [7]:
from basepair.modisco.results import MultipleModiscoResult
from basepair.modisco.pattern_instances import (multiple_load_instances, load_instances, filter_nonoverlapping_intervals, 
                                                plot_coocurence_matrix, align_instance_center, dfi2seqlets, annotate_profile)

def shorten_te_pattern(s):
    tf, p = s.split("/", 1)
    return tf + "/" + shorten_pattern(p)

mr = MultipleModiscoResult({t: model_dir / f'deeplift/{t}/out/{imp_score}/modisco.h5'
                           for t in tasks})

centroid_seqlet_matches = {t: pd.read_csv(model_dir / f'deeplift/{t}/out/{imp_score}/centroid_seqlet_matches.csv')
                           for t in tasks}

patterns = [p.trim_seq_ic(0.08) for p in mr.get_all_patterns()
            if shorten_te_pattern(p.name) in list(motifs.values())]
TF-MoDISco is using the TensorFlow backend.
In [8]:
bpnet = SeqModel.from_mdir(model_dir)
WARNING:tensorflow:From /users/avsec/bin/anaconda3/envs/chipnexus/lib/python3.6/site-packages/tensorflow/python/util/deprecation.py:497: calling conv1d (from tensorflow.python.ops.nn_ops) with data_format=NHWC is deprecated and will be removed in a future version.
Instructions for updating:
`NHWC` for data_format is deprecated, use `NWC` instead
2019-04-27 01:28:43,242 [WARNING] From /users/avsec/bin/anaconda3/envs/chipnexus/lib/python3.6/site-packages/tensorflow/python/util/deprecation.py:497: calling conv1d (from tensorflow.python.ops.nn_ops) with data_format=NHWC is deprecated and will be removed in a future version.
Instructions for updating:
`NHWC` for data_format is deprecated, use `NWC` instead
WARNING:tensorflow:From /users/avsec/bin/anaconda3/envs/chipnexus/lib/python3.6/site-packages/tensorflow/contrib/learn/python/learn/datasets/base.py:198: retry (from tensorflow.contrib.learn.python.learn.datasets.base) is deprecated and will be removed in a future version.
Instructions for updating:
Use the retry module or similar alternatives.
2019-04-27 01:28:54,226 [WARNING] From /users/avsec/bin/anaconda3/envs/chipnexus/lib/python3.6/site-packages/tensorflow/contrib/learn/python/learn/datasets/base.py:198: retry (from tensorflow.contrib.learn.python.learn.datasets.base) is deprecated and will be removed in a future version.
Instructions for updating:
Use the retry module or similar alternatives.
In [9]:
for p in patterns:
    p.plot('seq_ic', height=0.4, letter_width=0.15);
    sns.despine(top=True, bottom=True, right=True)
    plt.title(motifs_inv[shorten_te_pattern(p.name)])
    plt.ylim([0,2])

Get predictions and importance scores

In [9]:
from basepair.exp.paper.locus import *
In [10]:
# Generate the right colors
colors = []
for task in tasks:
    colors.append((tf_colors[task], tf_colors[task] + "80"))  # 80 add alpha=0.5
    colors.append(None)
In [11]:
interval = parse_interval("chr17:35503550-35504550")
In [12]:
interval.end - interval.start
Out[12]:
1000
In [62]:
viz_dict, seq, imp_scores = interval_predict(bpnet, ds, interval, tasks, smooth_obs_n=25, neg_rev=False)

xlim = [420, 575]  # Focus only on the 420 - 575 region
viz_dict = filter_tracks(viz_dict, xlim)

# instances
dfim = get_instances(patterns, seq, imp_scores, imp_score, centroid_seqlet_matches, motifs, tasks).query('match_weighted_p > .2')
seqlets = dfi2seqlets(dfim, motifs_inv)
seqlets2 = [s.shift(-xlim[0]) for s in seqlets]
In [63]:
print(one_hot2string(seq[:, slice(*xlim)], DNA)[0])  # Get the sequence
GGAGGAACTGGGTGTGGGGAGGTTGTAGCCCGACCCTGCCCCTCCCCCCAGGGAGGTTGAGAGTTCTGGGCAGACGGCAGATGCATAACAAAGGTGCATGATAGCTCTGCCCTGGGGGCAGAGAAGATGGTTGGGGAGGGGTCCCTCTCGTCCTA
In [64]:
fig = plot_tracks(viz_dict,
                  #seqlets=shifted_seqlets,
                  title="{i.chrom}:{i.start}-{i.end}, {i.name}".format(i=interval),
                  fig_height_per_track=0.5,
                  rotate_y=0,
                  fig_width=get_figsize(frac=1)[0],
                  use_spine_subset=True,
                  seqlets=seqlets2,
                  color=colors,
                  ylim=get_ylim(viz_dict, tasks),
                  legend=False)
sns.despine(top=True, right=True, bottom=True)
In [66]:
!mkdir -p {figures}/known_enhancer_profiles/all-motifs
In [67]:
fig.savefig(f"{figures}/known_enhancer_profiles/all-motifs/distal_oct4.pred,imp,imp-counts.pdf")
In [68]:
from basepair.plot.tracks import *

Other enhancers

In [69]:
df_enhancers = pd.read_csv("https://docs.google.com/spreadsheets/d/1nIRLv3tWq_3BjorP_pEAyJKWtVClX6_OrE2waN94ECc/export?gid=0&format=csv")
df_enhancer_intervals = df_enhancers[['Name', 'mm10 coordinates']].dropna()
intervals = [(row.Name, str(row[['mm10 coordinates']].iloc[0]).strip())
             for i, row in df_enhancer_intervals.iterrows()]
In [ ]:
sequences = dict()
for i, (name, interval_str) in enumerate(intervals):
    print(f"{i}/{len(intervals)}", name)
    interval = parse_interval(interval_str)
    viz_dict, seq, imp_scores = interval_predict(bpnet, ds, interval, tasks, smooth_obs_n=25, neg_rev=False)
    dfim = get_instances(patterns, seq, imp_scores, imp_score, centroid_seqlet_matches, motifs, tasks).query('match_weighted_p > .2')
    seqlets = dfi2seqlets(dfim, motifs_inv)
    
    xlim = None
    fig = plot_tracks(viz_dict,
                      #seqlets=shifted_seqlets,
                      title=str_interval(interval, xlim) + name,
                      fig_height_per_track=0.5,
                      rotate_y=0,
                      fig_width=get_figsize(frac=2)[0],
                      use_spine_subset=True,
                      seqlets=seqlets,
                      color=colors,
                      ylim=get_ylim(viz_dict, tasks, True),
                      # seqlet_plot_fn=plot_seqlet_underscore,
                      legend=False)
    sns.despine(top=True, right=True, bottom=True)
    fig.savefig(f"{figures}/known_enhancer_profiles/all-motifs/{name},{interval_str}.1kb.pdf")
    plt.close()
    
    # Figure out the most interesting 150 bp in the entire 1kb region
    # by looking at the total number of counts in the 150 bp window
    from basepair.preproc import moving_average
    # center = np.argmax(moving_average(sum([np.abs(viz_dict[f'{task} Obs']).sum(axis=-1) for task in tasks]), 150))
    center = np.argmax(moving_average(sum([np.abs(viz_dict[f'{task} Imp profile']).sum(axis=-1) for task in tasks]), 150))
    xlim = [center - 75, center + 75]
    seqlets2 = [s.shift(-xlim[0]) for s in seqlets]
    viz_dict2 = filter_tracks(viz_dict, xlim)

    print(str_interval(interval, xlim), name)
    seq_str = one_hot2string(seq[:, slice(*xlim)], DNA)[0]
    print(seq_str)  # Get the sequence
    sequences[f"{name},{interval_str}"] = seq_str
    fig = plot_tracks(viz_dict2,
                      #seqlets=shifted_seqlets,
                      title=str_interval(interval, xlim) + " (" + str(xlim) + ")",
                      fig_height_per_track=0.5,
                      rotate_y=0,
                      fig_width=get_figsize(frac=1)[0],
                      use_spine_subset=True,
                      seqlets=seqlets2,
                      color=colors,
                      ylim=get_ylim(viz_dict2, tasks, True),
                      legend=False)
    sns.despine(top=True, right=True, bottom=True)
    fig.savefig(f"{figures}/known_enhancer_profiles/all-motifs/{name},{interval_str}.150bp.pdf")
    plt.close()
    
# Write out the fasta file
from concise.utils.fasta import write_fasta
write_fasta(f"{figures}/known_enhancer_profiles/all-motifs/sequences.150bp.new.fa", list(sequences.values()), list(sequences))    
0/53 Klf upstream enhancer
resizing the interval of length 4000 to 1000
chr4:55475385-55475535, . Klf upstream enhancer
GTCTCTCCCTCTGCCCTCCATCTATCCACCATCCATCCATCCATCTATCCATAGACTCATCCCTCTATCCACCCATCTACCCTATCCACCCATCTATTCACCCATTGATCATCTATCATCCTTTATCCTTGGATATACACCAGCCATTAC
1/53 Klf upstream enhancer E1
resizing the interval of length 141 to 1000
chr4:55477925-55478075, . Klf upstream enhancer E1
GGCCCCACTCCCACATCCTATCATACACATTGAAATTCACCCACTTTGCATATCAAATGAGTTATATATAGCTAACTGGGGAGGCCAGTTGCAAAGACAGTTGACATAATGTTACCTTTTGTAGACATTTAATTACACACTCATCAATTT
2/53 Klf upstream enhancer E2
resizing the interval of length 62 to 1000
chr4:55475970-55476120, . Klf upstream enhancer E2
ACCTGCTAACCTTGAATACATTATTATAAGGGAAAGCAGCTGACCAACAAAGTGTGGGGGGTTTCTCCATTTATATGAAGATCAGAGTCGTTAATTCGTGGGGAGAGCTTTTGAGGCCACTTCTAGGAATTTGGCCGGAATTTGACATTG
3/53 Klf upstream enhancer E3
resizing the interval of length 132 to 1000
chr4:55464844-55464994, . Klf upstream enhancer E3
CTCAGCTTGTTCCCTATTCTTCCGTACCCTTTAAAGTCCTCCCAGCTTTTGAATACTAATCACATTCACTAGTCCAAAGTCCTTTGTCATTTTACGCGCTCCCTAGAATAGTCAATTGCATAAAAACAAGGAAGATAATGATCCCTCAGG
4/53 Sox2 downstream enhancer (SCR)
resizing the interval of length 2560 to 1000
chr3:34650315-34650465, . Sox2 downstream enhancer (SCR)
GTCCTACTCGCAGCAGGGCACCCCCGGTATGGCGCTGGGCTCCATGGGCTCTGTGGTCAAGTCCGAGGCCAGCTCCAGCCCCCCCGTGGTTACCTCTTCCTCCCACTCCAGGGCGCCCTGCCAGGCCGGGGACCTCCGGGACATGATCAG
5/53 Sox2 SCR-SRR107 (downstream enhancer)
resizing the interval of length 1536 to 1000
chr3:34757732-34757882, . Sox2 SCR-SRR107 (downstream enhancer)
TGACACCTCCCTCCCGGCTGTTACCCAGGAAGTTGTTTAGCATAGTCCCAGGACTCTGCTAAGGGCAAGTACTGTCATTGTTATTTATTTAGCCCCATTATGCTAACTACCCACCCCTTGCCAAGGTTTCACCACCCAGAAGGTTGGAGG
6/53 Sox2 SCR-SRR111 (downstream enhancer)
resizing the interval of length 1512 to 1000
chr3:34761186-34761336, . Sox2 SCR-SRR111 (downstream enhancer)
CAATTAGGGTTTAAAAAAAGAACCTGGGATGGGCCAGTTGTAAACCCCCTGGAGCTGCCTAGAGGAAGGAGCTGGAGGAGAGCTTAGAAAACAAAGGGGGAGGTCATGGAAACAGACGGGGAGGTCAGACACCTGATCTGCAAGCAGCCC
7/53 Tbx3 intragenic 1
resizing the interval of length 90 to 1000
chr5:119680405-119680555, . Tbx3 intragenic 1
GAATTTGCAATCCAATAGAGAGATGCTAGGGAAAGCTTTGGCTCTAAGCAGCTGGTCTTTCTGGTTTTGTTTTGTTTTAAAGTAGAATTATTACAATAAGAAAAGCTGCCAGTTGGGGGCCTGGCTGGAGAAGGTTGAACACTTGTGATT
8/53 Fgf5 POISED enhancer (in ESCs), intragenic
resizing the interval of length 195 to 1000
chr5:98284175-98284325, . Fgf5 POISED enhancer (in ESCs), intragenic
ATGTTAACAATTTAGCACATTTTAAATAAAACATCACCTCCCACTGTTGGTCTTAGGCAAGGGATTATGTATCAGACTCCCTCTGAGAACAGCTGCTGCAGTTTGGACTGCTGGGGATAGTGCAAATGAACCTCCCCCAGGACATGAGAG
9/53 Tbx3 intragenic 2
resizing the interval of length 227 to 1000
chr5:119683644-119683794, . Tbx3 intragenic 2
TCCAGAGACTATGCTAGATACCACAGGCCCTGCCACCATGGGCTGTGTAACCAGGCTGCTGTTGCTTTGAAACGCGGGACTGAGGGGGCGGGAGGAGTGGTGGCAAACAGGCTTTTGTGTCTAGAGCGACTTTTGTGCAGGCTGGTATGG
10/53 Klf2 upstream enhancer
resizing the interval of length 500 to 1000
chr8:72316409-72316559, . Klf2 upstream enhancer
AAAGGACACAAAGCCAACCAGAAGCAAACAAAACAACCCATTTGAAACTATTCAAAAGACTGAGGCCTGCACAAAGGGCTTAGAGGAGCTAAAAGAAAAGATATGCAGAAAGAGAAAAAACGCATTTCAAAAGCTCCCCCTGGCCATAGG
11/53 Esrrb intragenic
resizing the interval of length 8550 to 1000
chr12:86471172-86471322, . Esrrb intragenic
GATAATCAAAGGCACCTTACTGCTGACAGACCAGTGGCTCCAGGCAGAGGGAAGATGGGGGTCTGATTGAATTTGCTAGCATATCTAAAGGAGGGTTTGTGACTGTCCAGGACGATTAGCCTGCCCTTGGAGCAGAGAGACTGGCAAAGG
12/53 Esrrb intragenic 2
resizing the interval of length 6390 to 1000
chr12:86499020-86499170, . Esrrb intragenic 2
ATGACCTTGAACTGTTGCTCCTTCTGTCCCGGATTCCCAAGGGCTGGCATTACCGGCTGGTATCACCTGATTTACGAGGTTGCTTTCTTTTGCTGGTGGTATTCAACTGCAAAGTTGAGCTATCAAGTCATTGGCAAAGAGGACAAAGCC
13/53 Nanog upstream --> 2 regions
resizing the interval of length 5400 to 1000
chr6:122703011-122703161, . Nanog upstream --> 2 regions
AAGGAAATCTAAAGAAAGAAGAAAAAAGAAACAAAATTGGAAGAGAGAGAGAGAGAGAGTGGTGTAAACAGTGGGTCTGAAGCCTTCGAGGGAGGAGGGCAAGATGCCGCGCTCTGCGTTTCTCCAGCTGGATGTGGACAGAGGTCAACC
14/53 Nr0b1 (Dax1) upstream and intragenic --> 2 regions
resizing the interval of length 6750 to 1000
chrX:86187317-86187467, . Nr0b1 (Dax1) upstream and intragenic --> 2 regions
CCAGGATTTAAATGGCATTCATCTGATGCCACGGTAAGGAATTAAACCTCTGTGCCATAGAGGCCAGCACAAGCAGAATACAAATTAACTGTTAAGTACTCTGACCTACAGGGGATATCTATATCAATCTTCCAAGACCTAGGGTGCATT
/users/avsec/workspace/basepair/basepair/plot/tracks.py:241: UserWarning: Attempting to set identical bottom==top results
in singular transformations; automatically expanding.
bottom=-0.0, top=0.0
  ax.set_ylim(ylim)
15/53 Esrrb intragenic --> 5 smaller regions
resizing the interval of length 34500 to 1000
chr12:86471192-86471342, . Esrrb intragenic --> 5 smaller regions
ATCACTGCCTGGCCAAGGCTGCAGTTTTTAAAAAGTGATCTTTCACATAAGATTTTGCTTAACCCTTCCTTCAGGAGCTAACAACTGTTTTGTAGATGAGAGAACTAAGGCTAGGTGACCAGAAAGTGTTTCCTAGACCCAGTGGGGGAC
16/53 Tbx3 intragenic 3
resizing the interval of length 2400 to 1000
chr5:119680172-119680322, . Tbx3 intragenic 3
CGCCATGGGCGGCGCCTTCTCTAGCATGGCTGCAGGCATGGGGCCCCTGCTGGCCACAGTATCCGGAGCATCCACCGGCGTCTCAGGCCTAGAATCCACAGCCATGGCCTCGGCTGCCGCAGCGCAGGGACTGTCTGGGGCGTCGGCTGC
17/53 Prdm14 E2 upstream enhancer (part of superenhancer)
resizing the interval of length 412 to 1000
chr1:13075053-13075203, . Prdm14 E2 upstream enhancer (part of superenhancer)
CCCGCAGCACCTTCAGGCAAGTACAATTAGGCAAAGACCTCGGAAAACCCCTGGAGGGTTTCAAAACTTACCCCCTCCCTCAGACTCCAACCTGCTAATCTAATGCTAATCTTTGCTCAGAAACTACAGGTATTTTAACACCAACTAATT
18/53 Prdm14 E3 upstream enhancer (part of superenhancer)
resizing the interval of length 380 to 1000
chr1:13085312-13085462, . Prdm14 E3 upstream enhancer (part of superenhancer)
AACTATGCACTTAGCAGCCCATTTCCCCCACCTGAAAGTACTCTAAGCTCACCCCTTTCTTTGAATAAAACACCTATCAACCTCCAATCCGTTTGCACTGGTTCCACCCAGGCTCCACAGACACACACTCCTCTCTGAACAATGGGTAAG
19/53 Klf2 E1 upstream enhancer (part of superenhancer)
resizing the interval of length 393 to 1000
chr8:72311482-72311632, . Klf2 E1 upstream enhancer (part of superenhancer)
ACAAATTACCCAGCAAGAGCCTCCAGGTGGGAAGGCGGGACAAGGCTTGAAGCTTTCAATTTCCTAAAGGTCTCAAGAGAGGTCTGTGAATAGGAAGGCCACGACCCCCAACCTGCAACGGCTAGGAAATGCAAATTGCAGCTACAATGA
20/53 Klf2 E2 upstream enhancer (part of superenhancer)
resizing the interval of length 400 to 1000
chr8:72316459-72316609, . Klf2 E2 upstream enhancer (part of superenhancer)
AAAGGACACAAAGCCAACCAGAAGCAAACAAAACAACCCATTTGAAACTATTCAAAAGACTGAGGCCTGCACAAAGGGCTTAGAGGAGCTAAAAGAAAAGATATGCAGAAAGAGAAAAAACGCATTTCAAAAGCTCCCCCTGGCCATAGG
21/53 Pou5f1 E1 upstream enhancer (part of superenhancer)
resizing the interval of length 437 to 1000
chr17:35502798-35502948, . Pou5f1 E1 upstream enhancer (part of superenhancer)
ATTTCCCTGCTCTAGTCTAGTGTCCTCCGTGAGTCCATTTAACTGATCACCCAGTCTGTGAGGAGGTGGCTGAACTCACAGTAAGAAAGCTGTGGGGGTCAACGCCTATTGTTTGTTTGTTTTGTTTTAGACAAGGTCTCCTGCTGAGGC
22/53 Pou5f1 E2 upstream enhancer (part of superenhancer)
resizing the interval of length 579 to 1000
chr17:35504207-35504357, . Pou5f1 E2 upstream enhancer (part of superenhancer)
GCCCGACCCTGCCCCTCCCCCCAGGGAGGTTGAGAGTTCTGGGCAGACGGCAGATGCATAACAAAGGTGCATGATAGCTCTGCCCTGGGGGCAGAGAAGATGGTTGGGGAGGGGTCCCTCTCGTCCTAGCCCTTCCTTAATCTGCTATTG
23/53 Pou5f1 E3 upstream enhancer (part of superenhancer)
resizing the interval of length 430 to 1000
chr17:35505321-35505471, . Pou5f1 E3 upstream enhancer (part of superenhancer)
GGGGATTGGGGCTCAGGAGGGGGTTGGGGAGCAGGAAGTTGTCCCCAGGGGAGCCATCCTGGCCCATTCAAGGGTTGAGTACTTGTTTAGGGTTAGAGCTGCCCCCTCTGGGGACCAGGATTGTCCAGCCAAGGCCATTGTCCTGCCCCC
24/53 Sik1 E1 upstream enhancer (part of superenhancer)
resizing the interval of length 451 to 1000
chr17:31803016-31803166, . Sik1 E1 upstream enhancer (part of superenhancer)
CTTGGTCACAGGGACATTTTATTAACAAAGGAGTACTTCCAAAGGAGGAAGTGGGTTGGAGCAGGGCCGAAGGTTATCAATTCAATTCATCACTGCTTTGCAAAGGGCAGGCTTTCTTACTGCAGGTTTTCTAATGCATTTGCATTGAAT
25/53 Sik1 E2 upstream enhancer (part of superenhancer)
resizing the interval of length 467 to 1000
chr17:31806970-31807120, . Sik1 E2 upstream enhancer (part of superenhancer)
CCACCACCTCTGGGTTTGTGGAATCATGGAGACTGAACTCAGAACAACACCCATCTAGGCCAATCCCTCCACCAGCTGACCCACAGGCTTGGTCCCTGATTTCGATTGCTAGTTGAATTTGGAAATTGTCACATTTCCATCAACAAAAGA
26/53 Sik1 E3 upstream enhancer (part of superenhancer)
resizing the interval of length 341 to 1000
chr17:31808544-31808694, . Sik1 E3 upstream enhancer (part of superenhancer)
CTATGCCTAGTGCCCCGGGGCCTTCCCTGTCACTCACTGGAGCCAGGAGTCAACTCCTAGCCTTTCCATTCCCAGCAGAGGCCACTCCCAAGGTCCCCAGCAAGGTCATTTCCTTGTGGTCTTATCCTAACAAAAGAACGGGCCCTCTTG
27/53 Sik1 E6 upstream enhancer (part of superenhancer)
resizing the interval of length 404 to 1000
chr17:31819758-31819908, . Sik1 E6 upstream enhancer (part of superenhancer)
GCTCACAGGCCAGTCCGGTAAGAGCATTTTCGAAACTGAGCTCCAGTTTAAGGAAATGAAGACAAAATCTCCATCACAATGGATTTAGGGTTGGAAGTGCAGTCAAAAGAAATTCCACTCCTGTGATGAAATCCAGAAAACCAAAGGCCT
28/53 Nanog upstream
resizing the interval of length 6000 to 1000
chr6:122702711-122702861, . Nanog upstream
AAGGAAATCTAAAGAAAGAAGAAAAAAGAAACAAAATTGGAAGAGAGAGAGAGAGAGAGTGGTGTAAACAGTGGGTCTGAAGCCTTCGAGGGAGGAGGGCAAGATGCCGCGCTCTGCGTTTCTCCAGCTGGATGTGGACAGAGGTCAACC
29/53 Dppa3 upstream
resizing the interval of length 5500 to 1000
chr6:122624042-122624192, . Dppa3 upstream
AGTAAAAAGGCCCCGCCTCCGCCTAAAGGTGTAGCTCAGGTGAAGCCTGTAATCACTGCTCATTAGCATTAAAGTAGCCTGGGGGTAGACTCGGCTGTATAAAAGGAAACCAGACCCCCCCCCCCCCATTCACAGACTGACTGCTAATTG
30/53 Oct4 proximal enhancer
resizing the interval of length 204 to 1000
chr17:35505434-35505584, . Oct4 proximal enhancer
GGGGATTGGGGCTCAGGAGGGGGTTGGGGAGCAGGAAGTTGTCCCCAGGGGAGCCATCCTGGCCCATTCAAGGGTTGAGTACTTGTTTAGGGTTAGAGCTGCCCCCTCTGGGGACCAGGATTGTCCAGCCAAGGCCATTGTCCTGCCCCC
31/53 Oct4 distal enhancer
resizing the interval of length 205 to 1000
chr17:35504394-35504544, . Oct4 distal enhancer
GCCCGACCCTGCCCCTCCCCCCAGGGAGGTTGAGAGTTCTGGGCAGACGGCAGATGCATAACAAAGGTGCATGATAGCTCTGCCCTGGGGGCAGAGAAGATGGTTGGGGAGGGGTCCCTCTCGTCCTAGCCCTTCCTTAATCTGCTATTG
32/53 Sall1 intragenic
resizing the interval of length 5000 to 1000
chr8:9151277-9151427, . Sall1 intragenic
GAATAGCCCCAGTGAAGAACCACCCATCTAACCACAGCAGTAAGAAACCCGTGGCCAATCGTCGCAAAAGGAGGAGTATGATGGCAATTTTCAAATAAAAAAAAAAATCTGTCACCTGCAGCAGGATGGATTATTTATTTACCTGCTGTG
33/53 reporter-validated regions 1
resizing the interval of length 281 to 1000
chr7:13014713-13014863, . reporter-validated regions 1
GATAAGTGTTTAGGAGCAGCTTTCATATGTAAAAACATTCCTGTAGCCCTGGGCAAGGTCTGCAATTGAAGGAAGGGCCCTTCCTTAATTACCTCTCAAGGCGTCCACACTACCTCAGAATCTGGATCTGCGGGTGGGGGTAGGGGTGTG
34/53 reporter-validated regions 2
resizing the interval of length 206 to 1000
chr9:49751915-49752065, . reporter-validated regions 2
ACACTGTCAAATAGAGGAAACCATTCCACTTTCTAACCTGTTCACATGGAAATGCACCCATTTCTAGGAATCCACACCTCTGGCGGGTGTGTGACCTTGTGTTAGGCTCTCTTCCTGGATTCCATCGGCCAGTTGACAAAAGAAAAGGTC
35/53 reporter-validated regions 3
resizing the interval of length 178 to 1000
chr8:48752476-48752626, . reporter-validated regions 3
CTAATCGGGGAATTAGAAGGGATCCGCCATTGTAATCCTCTCCACCTACTCAAAGTCCCTCCCTGTAATGATTTGTACAATGGAGCCAAGGAAATGCAAATTTGATTGCAGGCGCTTGCCAGCCTCAAGCTATTCATTACTTTTCTTTGA
36/53 reporter-validated regions 4
resizing the interval of length 170 to 1000
chr19:28183351-28183501, . reporter-validated regions 4
CTGCGGGCGTACGCAGGCAGTGATTCTCGGATCTTCTCACAGCACAGAGACAACAATTTCCCAACAAGCACTATCCTTTGTTGTGCAAATAGATGTAGTTTAGAGATAGACCAGTGTCACAATCACTAAATGATGAACAGTATTATCAGG
37/53 reporter-validated regions 5
resizing the interval of length 151 to 1000
chr5:123158550-123158700, . reporter-validated regions 5
GTTGATGGGAGTGCTTAAGAACTAAGTGGAGGGGATGGCCGCTTTGGGAGCCTGTGGGGTGCCAAGATTGTTCACTTCCAAATGTACAGTCTTATGTTAATTTCACCTGGAGCCTATTTATATTGAGGAGTAGTTTCCTCCTGGTCAGCA
38/53 reporter-validated regions 6
resizing the interval of length 146 to 1000
chr4:10932855-10933005, . reporter-validated regions 6
GAAGACACAGCAGGAAGACCTCTCAGCATTCACCAGGATGGTTCAAATTCCTTCCTGTCTTTAGCTCCTGCACAGCAGGCAACTCCTAAAACCTTAGTATTCCATTGTTACTGCCCAGTCCATTGATATCTACAGTCAAACTCATTGTTG
39/53 reporter-validated regions 7
resizing the interval of length 102 to 1000
chr4:57691414-57691564, . reporter-validated regions 7
CCTCTGATCGGGGTGTGGCTGGCATGGATGCCTGGGTGGTCCACTACTCAATCAATAAGCCAGCATGGAGCCATCTTGCCAATTGTTACCACCCCATTGTCTCTTTCATTTGCACCTCCACTCATTTCCCCCTGTAGCCTTCCCACTCAC
40/53 reporter-validated regions 8
resizing the interval of length 98 to 1000
chr8:89004072-89004222, . reporter-validated regions 8
TTAGTCAGGCAACTTGAAGTCAGGCTGGTACAATGAACACCTGTTGAGAAAGCCCATTATTAGGAACTGGGGCTCGGAGCGGAAAGAGCACTGTGAATTAATTTTGAACGCCTCGCAGAATTTTGCATAACAAATGATCTCCGATGGGGG
41/53 reporter-validated regions 9
resizing the interval of length 86 to 1000

Plot the individual locus using all the datapoints

In [132]:
class PlotTrackWRug:
    def __init__(self, xlim):
        self.xlim = xlim

    def __call__(self, arr, ax, legend=False, ylim=None, color=None, track=None):
        """Tracks with a rug plot for '*Obs*' tracks
        """
        import collections
        from concise.utils.pwm import seqlogo
        seqlen = self.xlim[1] - self.xlim[0]
        
        sl = slice(self.xlim[0], self.xlim[1])
        if arr.shape[1] == 4:
            # plot seqlogo
            seqlogo(arr[sl], ax=ax)
        elif arr.shape[1] == 2:
            # plot both strands
            if color is not None:
                assert isinstance(color, collections.Sequence)
                c1 = color[0]
                c2 = color[1]
            else:
                c1, c2 = None, None

            if 'Obs' in track:
                y_smooth = moving_average(arr, n=50)
                ax.plot(np.arange(1, seqlen + 1), y_smooth[sl,0], label='pos', color=c1)
                ax.plot(np.arange(1, seqlen + 1), y_smooth[sl,1], label='neg', color=c2)

                # Rugs
                rug_pos = np.where(arr[sl, 0]>=1)[0] + 1
                rug_neg = np.where(arr[sl, 1]>=1)[0] + 1
                sns.rugplot(rug_pos, color=c1, alpha=0.3, ax=ax, height=.1)
                sns.rugplot(rug_neg, color=c2, alpha=0.3, ax=ax, height=.1)
            else:
                ax.plot(np.arange(1, seqlen + 1), arr[sl, 0], label='pos', color=c1)
                ax.plot(np.arange(1, seqlen + 1), arr[sl, 1], label='neg', color=c2)

            if legend:
                ax.legend()
        else:
            raise ValueError(f"Don't know how to plot array with shape[1] != {arr.shape[1]}. Valid values are: 1,2 or 4.")
        if ylim is not None:
            ax.set_ylim(ylim)
        ax.set_xlim([0, seqlen])

Oct4 enhancer

In [ ]:
interval_predict??
In [127]:
interval = parse_interval("chr17:35503550-35504550")

viz_dict, seq, imp_scores = interval_predict(bpnet, ds, interval, tasks, smooth_obs_n=0, neg_rev=False, incl_pred=True)
viz_dict_smooth = {k: moving_average(v, n=50) if 'Obs'in k else v for k,v in viz_dict.items()}

xlim = [450, 570]  # Focus only on the 420 - 575 region
# viz_dict = filter_tracks(viz_dict, xlim)

# instances
dfim = get_instances(patterns, seq, imp_scores, imp_score, centroid_seqlet_matches, motifs, tasks).query('match_weighted_p > .2')
seqlets = dfi2seqlets(dfim, motifs_inv)
seqlets2 = [s.shift(-xlim[0]) for s in seqlets]
In [122]:
print(one_hot2string(seq[:, slice(*xlim)], DNA)[0])  # Get the sequence
CGACCCTGCCCCTCCCCCCAGGGAGGTTGAGAGTTCTGGGCAGACGGCAGATGCATAACAAAGGTGCATGATAGCTCTGCCCTGGGGGCAGAGAAGATGGTTGGGGAGGGGTCCCTCTCG
In [128]:
# Generate the right colors
colors = []
for task in tasks:
    colors.append((tf_colors[task], tf_colors[task] + "80"))  # 80 add alpha=0.5
    colors.append((tf_colors[task], tf_colors[task] + "80"))  # 80 add alpha=0.5
    colors.append(None)
In [129]:
fig = plot_tracks(viz_dict,
                  title=str_interval(interval, xlim),
                  fig_height_per_track=0.5,
                  rotate_y=0,
                  fig_width=get_figsize(frac=.5)[0],
                  use_spine_subset=True,
                  seqlets=seqlets2,
                  color=colors,
                  ylim=get_ylim(viz_dict_smooth, tasks, profile_per_tf=True, neg_rev=False),
                  legend=False,
                  plot_track_fn=PlotTrackWRug(xlim))
sns.despine(top=True, right=True, bottom=True)
fig.savefig(f"{figures}/known_enhancer_profiles/Oct4-distal-enhancer.150bp.pdf")

Other enhancers

In [133]:
def plot_track_w_rug(arr, ax, legend=False, ylim=None, color=None, track=None):
    """Tracks with a rug plot for '*Obs*' tracks
    """
    import collections
    from concise.utils.pwm import seqlogo
    seqlen = len(arr)
    if arr.shape[1] == 4:
        # plot seqlogo
        seqlogo(arr, ax=ax)
    elif arr.shape[1] == 2:
        # plot both strands
        if color is not None:
            assert isinstance(color, collections.Sequence)
            c1 = color[0]
            c2 = color[1]
        else:
            c1, c2 = None, None
        
        if 'Obs' in track:
            y_smooth = moving_average(arr, n=50)
            ax.plot(np.arange(1, seqlen + 1), y_smooth[:,0], label='pos', color=c1)
            ax.plot(np.arange(1, seqlen + 1), y_smooth[:,1], label='neg', color=c2)
            
            # Rugs
            rug_pos = np.where(arr[:, 0]>=1)[0] + 1
            rug_neg = np.where(arr[:, 1]>=1)[0] + 1
            sns.rugplot(rug_pos, color=c1, alpha=0.3, ax=ax, height=.1)
            sns.rugplot(rug_neg, color=c2, alpha=0.3, ax=ax, height=.1)
        else:
            ax.plot(np.arange(1, seqlen + 1), arr[:, 0], label='pos', color=c1)
            ax.plot(np.arange(1, seqlen + 1), arr[:, 1], label='neg', color=c2)
        
        if legend:
            ax.legend()
    else:
        raise ValueError(f"Don't know how to plot array with shape[1] != {arr.shape[1]}. Valid values are: 1,2 or 4.")
    if ylim is not None:
        ax.set_ylim(ylim)
    ax.set_xlim([0, seqlen])
In [134]:
# chr1:136680205-136680605 (known Zfp281 enhancer) 
# chr1:180924752-180925152 (known Letfy1 enhancer) 
intervals = [
    ('known Zfp281 enhancer', 'chr1:136680205-136680605'),
    ('known Letfy1 enhancer', 'chr1:180924752-180925152'),
]
In [73]:
i = 0
name, int_str = intervals[i]
interval = parse_interval(int_str)
viz_dict, seq, imp_scores = interval_predict(bpnet, ds, interval, tasks, smooth_obs_n=0, neg_rev=False, incl_pred=True)
# viz_dict = {k:v for k,v in viz_dict.items() if 'Imp' not in k}  # remove importance scores

xlim= [0, 1000]
# xlim = [420, 575]  # Focus only on the 420 - 575 region
# viz_dict = filter_tracks(viz_dict, xlim)

# instances
dfim = get_instances(patterns, seq, imp_scores, imp_score, centroid_seqlet_matches, motifs, tasks).query('match_weighted_p > .2')
seqlets = dfi2seqlets(dfim, motifs_inv)
seqlets2 = [s.shift(-xlim[0]) for s in seqlets]

# for computing the y axis
viz_dict_smooth = {k: moving_average(v, n=50) if 'Obs'in k else v for k,v in viz_dict.items()}
resizing the interval of length 400 to 1000
In [74]:
fig = plot_tracks(viz_dict,
                  #seqlets=shifted_seqlets,
                  title=name + " {i.chrom}:{i.start}-{i.end}, {i.name}".format(i=interval),
                  fig_height_per_track=0.5,
                  rotate_y=0,
                  fig_width=get_figsize(frac=.7)[0],
                  use_spine_subset=True,
                  seqlets=seqlets2,
                  color=colors,
                  ylim=get_ylim(viz_dict_smooth, tasks, profile_per_tf=True, neg_rev=False),
                  plot_track_fn=plot_track_w_rug,
                  legend=False)
sns.despine(top=True, right=True, bottom=True)
# fig.savefig(f"{figures}/known_enhancer_profiles/Oct4-distal-enhancer.150bp.pdf")
In [75]:
i = 1
name, int_str = intervals[i]
interval = parse_interval(int_str)
viz_dict, seq, imp_scores = interval_predict(bpnet, ds, interval, tasks, smooth_obs_n=0, neg_rev=False, incl_pred=True)
# viz_dict = {k:v for k,v in viz_dict.items() if 'Imp' not in k}  # remove importance scores
xlim= [0, 1000]
# xlim = [420, 575]  # Focus only on the 420 - 575 region
# viz_dict = filter_tracks(viz_dict, xlim)

# instances
dfim = get_instances(patterns, seq, imp_scores, imp_score, centroid_seqlet_matches, motifs, tasks).query('match_weighted_p > .2')
seqlets = dfi2seqlets(dfim, motifs_inv)
seqlets2 = [s.shift(-xlim[0]) for s in seqlets]

# for computing the y axis
viz_dict_smooth = {k: moving_average(v, n=50) if 'Obs'in k else v for k,v in viz_dict.items()}
resizing the interval of length 400 to 1000
In [76]:
fig = plot_tracks(viz_dict,
                  #seqlets=shifted_seqlets,
                  title=name + " {i.chrom}:{i.start}-{i.end}, {i.name}".format(i=interval),
                  fig_height_per_track=0.5,
                  rotate_y=0,
                  fig_width=get_figsize(frac=.7)[0],
                  use_spine_subset=True,
                  seqlets=seqlets2,
                  color=colors,
                  ylim=get_ylim(viz_dict_smooth, tasks, profile_per_tf=True, neg_rev=False),
                  plot_track_fn=plot_track_w_rug,
                  legend=False)
sns.despine(top=True, right=True, bottom=True)
# fig.savefig(f"{figures}/known_enhancer_profiles/Oct4-distal-enhancer.150bp.pdf")

Without importance scores

In [139]:
# Generate the right colors
colors = []
for task in tasks:
    colors.append((tf_colors[task], tf_colors[task] + "80"))  # 80 add alpha=0.5
    colors.append((tf_colors[task], tf_colors[task] + "80"))  # 80 add alpha=0.5
In [140]:
from basepair.preproc import shift_interval
In [141]:
i = 0
name, int_str = intervals[i]
interval = shift_interval(parse_interval(int_str), 200)
viz_dict, seq, imp_scores = interval_predict(bpnet, ds, interval, tasks, smooth_obs_n=0, neg_rev=False, incl_pred=True)
viz_dict = {k:v for k,v in viz_dict.items() if 'Imp' not in k}  # remove importance scores

xlim= [0, 1000]

# for computing the y axis
viz_dict_smooth = {k: moving_average(v, n=50) if 'Obs'in k else v for k,v in viz_dict.items()}
resizing the interval of length 400 to 1000
In [142]:
fig = plot_tracks(viz_dict,
                  #seqlets=shifted_seqlets,
                  title=name + " {i.chrom}:{i.start}-{i.end}, {i.name}".format(i=interval),
                  fig_height_per_track=0.3,
                  rotate_y=0,
                  fig_width=get_figsize(frac=.6)[0],
                  use_spine_subset=True,
                  color=colors,
                  ylim=get_ylim(viz_dict_smooth, tasks, profile_per_tf=True, neg_rev=False),
                  plot_track_fn=plot_track_w_rug,
                  legend=False)
sns.despine(top=True, right=True, bottom=True)
fig.savefig(f"{figures}/known_enhancer_profiles/{name}.pred-vs-obs.1kb.pdf")
In [143]:
i = 1
name, int_str = intervals[i]
interval = shift_interval(parse_interval(int_str), -200)
viz_dict, seq, imp_scores = interval_predict(bpnet, ds, interval, tasks, smooth_obs_n=0, neg_rev=False, incl_pred=True)
viz_dict = {k:v for k,v in viz_dict.items() if 'Imp' not in k}  # remove importance scores

xlim= [0, 1000]

# for computing the y axis
viz_dict_smooth = {k: moving_average(v, n=50) if 'Obs'in k else v for k,v in viz_dict.items()}
resizing the interval of length 400 to 1000
In [144]:
figures
Out[144]:
PosixPath('/users/avsec/workspace/basepair/data/figures/modisco/seq,peaks,OSN,0,10,1,FALSE,same,0.5,64,50,0.004,9,FALSE,[1,50],TRUE,TRUE')
In [145]:
fig = plot_tracks(viz_dict,
                  #seqlets=shifted_seqlets,
                  title=name + " {i.chrom}:{i.start}-{i.end}, {i.name}".format(i=interval),
                  fig_height_per_track=0.3,
                  rotate_y=0,
                  fig_width=get_figsize(frac=.6)[0],
                  use_spine_subset=True,
                  color=colors,
                  ylim=get_ylim(viz_dict_smooth, tasks, profile_per_tf=True, neg_rev=False),
                  plot_track_fn=plot_track_w_rug,
                  legend=False)
sns.despine(top=True, right=True, bottom=True)
fig.savefig(f"{figures}/known_enhancer_profiles/{name}.pred-vs-obs.1kb.pdf")