In [1]:
import sys
import os
sys.path.append(os.path.abspath("/users/amtseng/tfmodisco/src/"))
import numpy as np
import h5py
import matplotlib.pyplot as plt
import motif.read_motifs as read_motifs
import motif.match_motifs as match_motifs
from util import figure_to_vdom_image
import plot.viz_sequence as viz_sequence
import vdom.helpers as vdomh
from IPython.display import display
In [2]:
# Define parameters/fetch arguments
tf_name = os.environ["TFM_TF_NAME"]
multitask_fold = int(os.environ["TFM_MULTITASK_FOLD"])
head = os.environ["TFM_HEAD"]
assert head in ("profile", "count")
if "TFM_TASK_INDEX" in os.environ:
    task_index = int(os.environ["TFM_TASK_INDEX"])
    singletask_fold = int(os.environ["TFM_SINGLETASK_FOLD"])
else:
    task_index = None
    singletask_fold = None
motif_file = os.environ["TFM_MOTIF_FILE"]  # TF-MoDISco motifs
    
print("TF name: %s" % tf_name)
print("Multi-task fold: %s" % multitask_fold)
print("Head: %s" % head)
print("Task index: %s" % task_index)
print("Single-task fold: %s" % singletask_fold)
print("TF-MoDISco motif file: %s" % motif_file)
TF name: MAX
Multi-task fold: 1
Head: count
Task index: 4
Single-task fold: 5
TF-MoDISco motif file: /users/amtseng/tfmodisco/results/reports/tfmodisco_results/cache/multitask_profile_finetune/MAX_multitask_profile_finetune_fold1/MAX_multitask_profile_finetune_task4_fold1_count/all_motifs.h5
In [3]:
# Define paths and constants
base_path = "/users/amtseng/tfmodisco/results/classic_motifs/"

multitask_seqlets_dir = os.path.join(
    base_path, "seqlets", "multitask_profile_finetune",
    "%s_multitask_profile_finetune_fold%s" % (tf_name, multitask_fold)
)

if task_index is None:
    peaks_path = os.path.join(base_path, "peaks", tf_name, "%s_peaks_taskall" % tf_name)
    multitask_seqlets_path = os.path.join(
        multitask_seqlets_dir,
        "%s_seqlets_%s_taskall" % (tf_name, head)
    )
else:
    peaks_path = os.path.join(base_path, "peaks", tf_name, "%s_peaks_task%d" % (tf_name, task_index))
    multitask_seqlets_path = os.path.join(
        multitask_seqlets_dir,
        "%s_seqlets_%s_task%d" % (tf_name, head, task_index)
    )
    
    singletask_seqlets_dir = os.path.join(
        base_path, "seqlets", "singletask_profile_finetune",
        "%s_singletask_profile_finetune_fold%s" % (tf_name, singletask_fold),
        "task_%d" % task_index
    )
    singletask_seqlets_path = os.path.join(
        singletask_seqlets_dir,
        "%s_seqlets_%s_task%d" % (tf_name, head, task_index)
    )

Helper functions

In [4]:
def import_tfmodisco_motifs(motif_file):
    """
    Imports a set of motifs from the saved HDF5.
    Returns a list of motifs as L x 4 arrays, and a parallel list of
    motif names.
    """
    motifs, motif_names = [], []
    with h5py.File(motif_file, "r") as f:
        for key in f.keys():
            motif_names.append(key)
            motifs.append(f[key]["pfm_trimmed"][:])
    return motifs, motif_names
In [5]:
def pfm_to_forward_pwm(pfm):
    """
    Converts PFM to PWM and flips to purine-rich orientation.
    """
    pwm = read_motifs.pfm_to_pwm(pfm)
    if np.sum(pwm[:, [0, 2]]) < 0.5 * np.sum(pwm):
        # Flip to purine-rich version
        pwm = np.flip(pwm, axis=(0, 1))
    return pwm
In [6]:
def show_matched_motifs_table(
    tfm_motifs, tfm_names, bench_type, bench_motifs, bench_scores, matches
):
    """
    Shows a table of motifs from the given matched results.
    `bench_type` is either `dichipmunk`, `homer`, or `meme`.
    `matches` is NumPy array parallel to `bench_motifs`, where
    each entry is the index of the match in `tfm_motifs`, and -1
    if no match was found.
    """
    assert len(matches) == len(bench_motifs)
    assert bench_type in ("dichipmunk", "homer", "meme")
    if bench_type == "dichipmunk":
        score_name = "Supporting sequences"
        bench_name = "DiChIPMunk"
    elif bench_type == "homer":
        score_name = "Log enrichment"
        bench_name = "HOMER"
    else:
        score_name = "E-value"
        bench_name = "MEME"
        
    colgroup = vdomh.colgroup(
        vdomh.col(style={"width": "5%"}),
        vdomh.col(style={"width": "45%"}),
        vdomh.col(style={"width": "5%"}),
        vdomh.col(style={"width": "45%"})
    )
    header = vdomh.thead(
        vdomh.tr(
            vdomh.th("TF-MoDISco motif ID", style={"text-align": "center"}),
            vdomh.th("TF-MoDISco PWM", style={"text-align": "center"}),
            vdomh.th(score_name, style={"text-align": "center"}),
            vdomh.th("%s PWM" % bench_name, style={"text-align": "center"})
        )
    )
    
    # First, show a table of matches
    display(vdomh.p("Matched motifs"))

    body = []
    for bench_index, tfm_index in enumerate(matches):
        if tfm_index == -1:
            continue
        tfm_fig = viz_sequence.plot_weights(
            pfm_to_forward_pwm(tfm_motifs[tfm_index]), figsize=(20, 4), return_fig=True
        )
        tfm_fig.tight_layout()
        bench_fig = viz_sequence.plot_weights(
            pfm_to_forward_pwm(bench_motifs[bench_index]), figsize=(20, 4), return_fig=True
        )
        bench_fig.tight_layout()
        
        body.append(
            vdomh.tr(
                vdomh.td(str(tfm_names[tfm_index])),
                vdomh.td(figure_to_vdom_image(tfm_fig)),
                vdomh.td(str(bench_scores[bench_index])),
                vdomh.td(figure_to_vdom_image(bench_fig))
            )
        )

    display(vdomh.table(colgroup, header, vdomh.tbody(*body)))
    plt.close("all")
    
    # Now, show a table of leftovers
    display(vdomh.p("Motifs without matches"))
    
    tfm_lone_indices = np.setdiff1d(np.arange(len(tfm_motifs)), matches)
    bench_lone_indices = np.where(matches == -1)[0]

    rows = []
    for i in range(max(len(tfm_lone_indices), len(bench_lone_indices))):
        row = []
        if i < len(tfm_lone_indices):
            tfm_fig = viz_sequence.plot_weights(
                pfm_to_forward_pwm(tfm_motifs[tfm_lone_indices[i]]), figsize=(20, 4), return_fig=True
            )
            tfm_fig.tight_layout()
            row.extend([
                vdomh.td(str(tfm_names[tfm_lone_indices[i]])),
                vdomh.td(figure_to_vdom_image(tfm_fig))
            ])
        else:
            row.extend([vdomh.td(), vdomh.td()])
        if i < len(bench_lone_indices):
            bench_fig = viz_sequence.plot_weights(
                pfm_to_forward_pwm(bench_motifs[bench_lone_indices[i]]), figsize=(20, 4), return_fig=True
            )
            bench_fig.tight_layout()
            row.extend([
                vdomh.td(str(bench_scores[bench_lone_indices[i]])),
                vdomh.td(figure_to_vdom_image(bench_fig))
            ])
        else:
            row.extend([vdomh.td(), vdomh.td()])
        rows.append(row)
    body = [vdomh.tr(*row) for row in rows]

    display(vdomh.table(colgroup, header, vdomh.tbody(*body)))
    plt.close("all")

Import motifs

In [7]:
tfm_pfms, tfm_names = import_tfmodisco_motifs(motif_file)
In [8]:
dichipmunk_peak_pfms, dichipmunk_peak_num_seqs = read_motifs.import_dichipmunk_pfms(
    os.path.join(peaks_path, "dichipmunk")
)
dichipmunk_multitask_seqlet_pfms, dichipmunk_multitask_seqlet_num_seqs = read_motifs.import_dichipmunk_pfms(
    os.path.join(multitask_seqlets_path, "dichipmunk")
)

homer_peak_pfms, homer_peak_enrichments = read_motifs.import_homer_pfms(
    os.path.join(peaks_path, "homer")
)
homer_multitask_seqlet_pfms, homer_multitask_seqlet_enrichments = read_motifs.import_homer_pfms(
    os.path.join(multitask_seqlets_path, "homer")
)

meme_peak_pfms, meme_peak_evalues = read_motifs.import_meme_pfms(
    os.path.join(peaks_path, "meme")
)
meme_multitask_seqlet_pfms, meme_multitask_seqlet_evalues = read_motifs.import_meme_pfms(
    os.path.join(multitask_seqlets_path, "meme")
)

if task_index is not None:
    dichipmunk_singletask_seqlet_pfms, dichipmunk_singletask_seqlet_num_seqs = read_motifs.import_dichipmunk_pfms(
        os.path.join(singletask_seqlets_path, "dichipmunk")
    )
    homer_singletask_seqlet_pfms, homer_singletask_seqlet_enrichments = read_motifs.import_homer_pfms(
        os.path.join(singletask_seqlets_path, "homer")
    )
    meme_singletask_seqlet_pfms, meme_singletask_seqlet_evalues = read_motifs.import_meme_pfms(
        os.path.join(singletask_seqlets_path, "meme")
    )

Match benchmarked motifs to TF-MoDISco motifs

DiChIPMunk on peaks

In [9]:
dichipmunk_peak_matches = match_motifs.match_motifs_to_targets(dichipmunk_peak_pfms, tfm_pfms)
show_matched_motifs_table(
    tfm_pfms, tfm_names, "dichipmunk", dichipmunk_peak_pfms, dichipmunk_peak_num_seqs,
    dichipmunk_peak_matches
)

Matched motifs

TF-MoDISco motif IDTF-MoDISco PWMSupporting sequencesDiChIPMunk PWM
0_0
708
0_0
54

Motifs without matches

TF-MoDISco motif IDTF-MoDISco PWMSupporting sequencesDiChIPMunk PWM
0_1
94
0_2
18
1

DiChIPMunk on multi-task seqlets

In [10]:
dichipmunk_multitask_seqlet_matches = match_motifs.match_motifs_to_targets(dichipmunk_multitask_seqlet_pfms, tfm_pfms)
show_matched_motifs_table(
    tfm_pfms, tfm_names, "dichipmunk", dichipmunk_multitask_seqlet_pfms, dichipmunk_multitask_seqlet_num_seqs,
    dichipmunk_multitask_seqlet_matches
)

Matched motifs

TF-MoDISco motif IDTF-MoDISco PWMSupporting sequencesDiChIPMunk PWM
0_0
3201
0_1
290
0_0
93

Motifs without matches

TF-MoDISco motif IDTF-MoDISco PWMSupporting sequencesDiChIPMunk PWM
0_2
19

DiChIPMunk on single-task seqlets

In [11]:
if task_index is not None:
    dichipmunk_singletask_seqlet_matches = match_motifs.match_motifs_to_targets(dichipmunk_singletask_seqlet_pfms, tfm_pfms)
    show_matched_motifs_table(
        tfm_pfms, tfm_names, "dichipmunk", dichipmunk_singletask_seqlet_pfms, dichipmunk_singletask_seqlet_num_seqs,
        dichipmunk_singletask_seqlet_matches
    )

Matched motifs

TF-MoDISco motif IDTF-MoDISco PWMSupporting sequencesDiChIPMunk PWM
0_0
3392
0_2
134

Motifs without matches

TF-MoDISco motif IDTF-MoDISco PWMSupporting sequencesDiChIPMunk PWM
0_1
474
14

HOMER on peaks

In [12]:
homer_peak_matches = match_motifs.match_motifs_to_targets(homer_peak_pfms, tfm_pfms)
show_matched_motifs_table(
    tfm_pfms, tfm_names, "homer", homer_peak_pfms, homer_peak_enrichments,
    homer_peak_matches
)

Matched motifs

TF-MoDISco motif IDTF-MoDISco PWMLog enrichmentHOMER PWM
0_0
-1148.707699
0_1
-351.360073
0_1
-149.491015
0_2
-121.468557
0_1
-114.511209
0_1
-76.675306
0_1
-70.539395
0_0
-58.844333
0_0
-54.646457

Motifs without matches

TF-MoDISco motif IDTF-MoDISco PWMLog enrichmentHOMER PWM
-244.029428
-166.887013
-152.465062
-133.629599
-90.720917
-82.700837
-76.675306
-62.334018
-53.586015
-50.597095
-48.6142
-32.25045

HOMER on multi-task seqlets

In [13]:
homer_multitask_seqlet_matches = match_motifs.match_motifs_to_targets(homer_multitask_seqlet_pfms, tfm_pfms)
show_matched_motifs_table(
    tfm_pfms, tfm_names, "homer", homer_multitask_seqlet_pfms, homer_multitask_seqlet_enrichments,
    homer_multitask_seqlet_matches
)

Matched motifs

TF-MoDISco motif IDTF-MoDISco PWMLog enrichmentHOMER PWM
0_0
-9349.172469
0_1
-1020.51215
0_1
-123.99099
0_1
-122.990197
0_0
-82.149599
0_0
-64.603972
0_1
-56.130874

Motifs without matches

TF-MoDISco motif IDTF-MoDISco PWMLog enrichmentHOMER PWM
0_2
-140.21704
-81.924978
-73.283245
-62.700317
-56.130874
-51.97876
-41.139998
-39.903103

HOMER on single-task seqlets

In [14]:
if task_index is not None:
    homer_singletask_seqlet_matches = match_motifs.match_motifs_to_targets(homer_singletask_seqlet_pfms, tfm_pfms)
    show_matched_motifs_table(
        tfm_pfms, tfm_names, "homer", homer_singletask_seqlet_pfms, homer_singletask_seqlet_enrichments,
        homer_singletask_seqlet_matches
    )

Matched motifs

TF-MoDISco motif IDTF-MoDISco PWMLog enrichmentHOMER PWM
0_0
-9140.273534
0_0
-123.609741
0_2
-86.364604
0_1
-86.364604
0_0
-43.698052

Motifs without matches

TF-MoDISco motif IDTF-MoDISco PWMLog enrichmentHOMER PWM
-1995.149309
-193.363785
-104.703899
-90.891747
-77.435108
-60.129648
-27.678552

MEME on peaks

In [15]:
meme_peak_matches = match_motifs.match_motifs_to_targets(meme_peak_pfms, tfm_pfms)
show_matched_motifs_table(
    tfm_pfms, tfm_names, "meme", meme_peak_pfms, meme_peak_evalues,
    meme_peak_matches
)

Matched motifs

TF-MoDISco motif IDTF-MoDISco PWME-valueMEME PWM
0_0
5.7e-266
0_0
4.5e-067
0_1
5.5e-061
0_0
3.2e-047

Motifs without matches

TF-MoDISco motif IDTF-MoDISco PWME-valueMEME PWM
0_2
1.7e-085
7.3e-071
5.0e-051
3.0e-038
4.2e-016
1.2e-018

MEME on multi-task seqlets

In [16]:
meme_multitask_seqlet_matches = match_motifs.match_motifs_to_targets(meme_multitask_seqlet_pfms, tfm_pfms)
show_matched_motifs_table(
    tfm_pfms, tfm_names, "meme", meme_multitask_seqlet_pfms, meme_multitask_seqlet_evalues,
    meme_multitask_seqlet_matches
)

Matched motifs

TF-MoDISco motif IDTF-MoDISco PWME-valueMEME PWM
0_0
3.8e-1234
0_1
2.3e-118
0_1
2.0e-002
0_0
5.8e-001
0_1
4.2e+004
0_1
5.3e+005

Motifs without matches

TF-MoDISco motif IDTF-MoDISco PWME-valueMEME PWM
0_2
7.8e-006
7.5e+001
2.0e+003
3.7e+005

MEME on single-task seqlets

In [17]:
if task_index is not None:
    meme_singletask_seqlet_matches = match_motifs.match_motifs_to_targets(meme_singletask_seqlet_pfms, tfm_pfms)
    show_matched_motifs_table(
        tfm_pfms, tfm_names, "meme", meme_singletask_seqlet_pfms, meme_singletask_seqlet_evalues,
        meme_singletask_seqlet_matches
    )

Matched motifs

TF-MoDISco motif IDTF-MoDISco PWME-valueMEME PWM
0_0
4.7e-1142
0_1
4.4e-001
0_1
7.7e+002
0_0
3.4e+005

Motifs without matches

TF-MoDISco motif IDTF-MoDISco PWME-valueMEME PWM
0_2
5.2e-246
4.7e-004
1.6e+002
1.4e+003
9.0e+003
1.3e+006