Spaces:
Running
Running
Zhaohan Meng
commited on
Update app.py
Browse files
app.py
CHANGED
|
@@ -137,12 +137,10 @@ def visualize_attention(model, feats, drug_idx: Optional[int] = None) -> str:
|
|
| 137 |
"""
|
| 138 |
Render a Protein β Drug cross-attention heat-map and, optionally, a
|
| 139 |
Top-30 protein-residue table for a chosen drug-token index.
|
| 140 |
-
|
| 141 |
The token index shown on the x-axis (and accepted via *drug_idx*) is **the
|
| 142 |
position of that token in the *original* drug sequence**, *after* the
|
| 143 |
tokeniser but *before* any pruning or truncation (1-based in the labels,
|
| 144 |
0-based for the function argument).
|
| 145 |
-
|
| 146 |
Returns
|
| 147 |
-------
|
| 148 |
html : str
|
|
@@ -178,6 +176,7 @@ def visualize_attention(model, feats, drug_idx: Optional[int] = None) -> str:
|
|
| 178 |
d_indices_full = d_indices_full[: attn.size(1)]
|
| 179 |
attn = attn[: len(p_tokens_full), : len(d_tokens_full)]
|
| 180 |
|
|
|
|
| 181 |
# ββ adaptive sparsity pruning βββββββββββββββββββββββββββββββββββββββββββ
|
| 182 |
thr = attn.max().item() * 0.05
|
| 183 |
row_keep = (attn.max(dim=1).values > thr)
|
|
@@ -237,7 +236,7 @@ def visualize_attention(model, feats, drug_idx: Optional[int] = None) -> str:
|
|
| 237 |
|
| 238 |
# βββββββββββββββββββββ Top-30 tabel βββββββββββββββββββββ
|
| 239 |
table_html = ""
|
| 240 |
-
if drug_idx is not None:
|
| 241 |
# map original 0-based drug_idx β current column position
|
| 242 |
if (drug_idx + 1) in d_indices:
|
| 243 |
col_pos = d_indices.index(drug_idx + 1)
|
|
@@ -254,8 +253,8 @@ def visualize_attention(model, feats, drug_idx: Optional[int] = None) -> str:
|
|
| 254 |
res_row = "".join(f"<td>{p_tokens[i]}</td>" for i in topk)
|
| 255 |
pos_row = "".join(f"<td>{p_indices[i]}</td>"for i in topk)
|
| 256 |
|
| 257 |
-
drug_tok_text =
|
| 258 |
-
orig_idx =
|
| 259 |
|
| 260 |
# 1) build the header row: leading βRankβ, then 1β¦30
|
| 261 |
header_cells = (
|
|
@@ -274,7 +273,7 @@ def visualize_attention(model, feats, drug_idx: Optional[int] = None) -> str:
|
|
| 274 |
"background:#f7f7f7; text-align:center;'>Residue</th>"
|
| 275 |
+ "".join(
|
| 276 |
f"<td style='border:1px solid #ccc; padding:6px; "
|
| 277 |
-
f"text-align:center'>{
|
| 278 |
for i in topk
|
| 279 |
)
|
| 280 |
)
|
|
@@ -285,7 +284,7 @@ def visualize_attention(model, feats, drug_idx: Optional[int] = None) -> str:
|
|
| 285 |
"background:#f7f7f7; text-align:center;'>Position</th>"
|
| 286 |
+ "".join(
|
| 287 |
f"<td style='border:1px solid #ccc; padding:6px; "
|
| 288 |
-
f"text-align:center'>{
|
| 289 |
for i in topk
|
| 290 |
)
|
| 291 |
)
|
|
@@ -397,29 +396,24 @@ button, .gr-button { font-family: Inter,sans-serif; font-weight: 600; }
|
|
| 397 |
.link-btn.project{background:linear-gradient(to right,#10b981,#059669);}
|
| 398 |
.link-btn.arxiv {background:linear-gradient(to right,#ef4444,#dc2626);}
|
| 399 |
.link-btn.github {background:linear-gradient(to right,#3b82f6,#2563eb);}
|
| 400 |
-
|
| 401 |
/* make *all* gradio buttons a bit taller */
|
| 402 |
.gr-button { min-height: 10px !important; }
|
| 403 |
-
|
| 404 |
/* now target just our two big action buttons */
|
| 405 |
#extract-btn, #inference-btn {
|
| 406 |
width: 5px !important;
|
| 407 |
min-height: 36px !important;
|
| 408 |
margin-top: 12px !important;
|
| 409 |
}
|
| 410 |
-
|
| 411 |
/* and make clear button full width but shorter */
|
| 412 |
#clear-btn {
|
| 413 |
width: 10px !important;
|
| 414 |
min-height: 36px !important;
|
| 415 |
margin-top: 12px !important;
|
| 416 |
}
|
| 417 |
-
|
| 418 |
#input-card label {
|
| 419 |
font-weight: 600 !important; /* make the text bold */
|
| 420 |
color: var(--text) !important; /* use your standard text color */
|
| 421 |
}
|
| 422 |
-
|
| 423 |
.card {
|
| 424 |
background: var(--card);
|
| 425 |
border: 1px solid var(--border);
|
|
@@ -429,7 +423,6 @@ button, .gr-button { font-family: Inter,sans-serif; font-weight: 600; }
|
|
| 429 |
margin: 0 auto 32px;
|
| 430 |
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
|
| 431 |
}
|
| 432 |
-
|
| 433 |
#guidelines-card h2 {
|
| 434 |
font-size: 1.4rem;
|
| 435 |
margin-bottom: 16px;
|
|
@@ -453,7 +446,9 @@ button, .gr-button { font-family: Inter,sans-serif; font-weight: 600; }
|
|
| 453 |
|
| 454 |
with gr.Blocks(css=css) as demo:
|
| 455 |
# βββββββββββββ Title βββββββββββββ
|
| 456 |
-
gr.Markdown(
|
|
|
|
|
|
|
| 457 |
|
| 458 |
# βββββββββββββ Project Links βββββββββββββ
|
| 459 |
gr.Markdown("""
|
|
@@ -477,22 +472,18 @@ with gr.Blocks(css=css) as demo:
|
|
| 477 |
based on 3D structures from
|
| 478 |
<a href="https://alphafold.ebi.ac.uk" target="_blank">AlphaFold DB</a> or the
|
| 479 |
<a href="https://www.rcsb.org" target="_blank">Protein Data Bank (PDB)</a>.</li>
|
| 480 |
-
|
| 481 |
<li><strong>If you only have an amino acid sequence or a UniProt ID,</strong>
|
| 482 |
you must first visit the
|
| 483 |
<a href="https://www.rcsb.org" target="_blank">Protein Data Bank (PDB)</a>
|
| 484 |
or <a href="https://alphafold.ebi.ac.uk" target="_blank">AlphaFold DB</a>
|
| 485 |
to search and download the corresponding <code>.cif</code> or <code>.pdb</code> file.</li>
|
| 486 |
-
|
| 487 |
<li><strong>Drug input supports both SELFIES and SMILES:</strong><br>
|
| 488 |
You can enter a SELFIES string directly, or paste a SMILES string.
|
| 489 |
SMILES will be automatically converted to SELFIES using
|
| 490 |
<a href="https://github.com/aspuru-guzik-group/selfies" target="_blank">SELFIES encoder</a>.
|
| 491 |
If conversion fails, a red error message will be displayed.</li>
|
| 492 |
-
|
| 493 |
<li>Optionally enter a <strong>1-based</strong> drug atom or substructure index
|
| 494 |
-
to highlight the Top-
|
| 495 |
-
|
| 496 |
<li>After inference, you can use the
|
| 497 |
βDownload PDFβ link to export a high-resolution vector version.</li>
|
| 498 |
</ul>
|
|
@@ -565,4 +556,4 @@ with gr.Blocks(css=css) as demo:
|
|
| 565 |
)
|
| 566 |
|
| 567 |
if __name__ == "__main__":
|
| 568 |
-
demo.launch(server_name="0.0.0.0", server_port=7860, share=True)
|
|
|
|
| 137 |
"""
|
| 138 |
Render a Protein β Drug cross-attention heat-map and, optionally, a
|
| 139 |
Top-30 protein-residue table for a chosen drug-token index.
|
|
|
|
| 140 |
The token index shown on the x-axis (and accepted via *drug_idx*) is **the
|
| 141 |
position of that token in the *original* drug sequence**, *after* the
|
| 142 |
tokeniser but *before* any pruning or truncation (1-based in the labels,
|
| 143 |
0-based for the function argument).
|
|
|
|
| 144 |
Returns
|
| 145 |
-------
|
| 146 |
html : str
|
|
|
|
| 176 |
d_indices_full = d_indices_full[: attn.size(1)]
|
| 177 |
attn = attn[: len(p_tokens_full), : len(d_tokens_full)]
|
| 178 |
|
| 179 |
+
orig_attn = attn.clone()
|
| 180 |
# ββ adaptive sparsity pruning βββββββββββββββββββββββββββββββββββββββββββ
|
| 181 |
thr = attn.max().item() * 0.05
|
| 182 |
row_keep = (attn.max(dim=1).values > thr)
|
|
|
|
| 236 |
|
| 237 |
# βββββββββββββββββββββ Top-30 tabel βββββββββββββββββββββ
|
| 238 |
table_html = ""
|
| 239 |
+
if drug_idx is not None and 0 <= drug_idx < orig_attn.size(1):
|
| 240 |
# map original 0-based drug_idx β current column position
|
| 241 |
if (drug_idx + 1) in d_indices:
|
| 242 |
col_pos = d_indices.index(drug_idx + 1)
|
|
|
|
| 253 |
res_row = "".join(f"<td>{p_tokens[i]}</td>" for i in topk)
|
| 254 |
pos_row = "".join(f"<td>{p_indices[i]}</td>"for i in topk)
|
| 255 |
|
| 256 |
+
drug_tok_text = d_tokens_full[col_pos]
|
| 257 |
+
orig_idx = d_indices_full[col_pos]
|
| 258 |
|
| 259 |
# 1) build the header row: leading βRankβ, then 1β¦30
|
| 260 |
header_cells = (
|
|
|
|
| 273 |
"background:#f7f7f7; text-align:center;'>Residue</th>"
|
| 274 |
+ "".join(
|
| 275 |
f"<td style='border:1px solid #ccc; padding:6px; "
|
| 276 |
+
f"text-align:center'>{p_tokens_full[i]}</td>"
|
| 277 |
for i in topk
|
| 278 |
)
|
| 279 |
)
|
|
|
|
| 284 |
"background:#f7f7f7; text-align:center;'>Position</th>"
|
| 285 |
+ "".join(
|
| 286 |
f"<td style='border:1px solid #ccc; padding:6px; "
|
| 287 |
+
f"text-align:center'>{p_indices_full[i]}</td>"
|
| 288 |
for i in topk
|
| 289 |
)
|
| 290 |
)
|
|
|
|
| 396 |
.link-btn.project{background:linear-gradient(to right,#10b981,#059669);}
|
| 397 |
.link-btn.arxiv {background:linear-gradient(to right,#ef4444,#dc2626);}
|
| 398 |
.link-btn.github {background:linear-gradient(to right,#3b82f6,#2563eb);}
|
|
|
|
| 399 |
/* make *all* gradio buttons a bit taller */
|
| 400 |
.gr-button { min-height: 10px !important; }
|
|
|
|
| 401 |
/* now target just our two big action buttons */
|
| 402 |
#extract-btn, #inference-btn {
|
| 403 |
width: 5px !important;
|
| 404 |
min-height: 36px !important;
|
| 405 |
margin-top: 12px !important;
|
| 406 |
}
|
|
|
|
| 407 |
/* and make clear button full width but shorter */
|
| 408 |
#clear-btn {
|
| 409 |
width: 10px !important;
|
| 410 |
min-height: 36px !important;
|
| 411 |
margin-top: 12px !important;
|
| 412 |
}
|
|
|
|
| 413 |
#input-card label {
|
| 414 |
font-weight: 600 !important; /* make the text bold */
|
| 415 |
color: var(--text) !important; /* use your standard text color */
|
| 416 |
}
|
|
|
|
| 417 |
.card {
|
| 418 |
background: var(--card);
|
| 419 |
border: 1px solid var(--border);
|
|
|
|
| 423 |
margin: 0 auto 32px;
|
| 424 |
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
|
| 425 |
}
|
|
|
|
| 426 |
#guidelines-card h2 {
|
| 427 |
font-size: 1.4rem;
|
| 428 |
margin-bottom: 16px;
|
|
|
|
| 446 |
|
| 447 |
with gr.Blocks(css=css) as demo:
|
| 448 |
# βββββββββββββ Title βββββββββββββ
|
| 449 |
+
gr.Markdown(
|
| 450 |
+
"<h1 style='text-align: center;'>Token-level Visualiser for Drug-Target Interaction</h1>"
|
| 451 |
+
)
|
| 452 |
|
| 453 |
# βββββββββββββ Project Links βββββββββββββ
|
| 454 |
gr.Markdown("""
|
|
|
|
| 472 |
based on 3D structures from
|
| 473 |
<a href="https://alphafold.ebi.ac.uk" target="_blank">AlphaFold DB</a> or the
|
| 474 |
<a href="https://www.rcsb.org" target="_blank">Protein Data Bank (PDB)</a>.</li>
|
|
|
|
| 475 |
<li><strong>If you only have an amino acid sequence or a UniProt ID,</strong>
|
| 476 |
you must first visit the
|
| 477 |
<a href="https://www.rcsb.org" target="_blank">Protein Data Bank (PDB)</a>
|
| 478 |
or <a href="https://alphafold.ebi.ac.uk" target="_blank">AlphaFold DB</a>
|
| 479 |
to search and download the corresponding <code>.cif</code> or <code>.pdb</code> file.</li>
|
|
|
|
| 480 |
<li><strong>Drug input supports both SELFIES and SMILES:</strong><br>
|
| 481 |
You can enter a SELFIES string directly, or paste a SMILES string.
|
| 482 |
SMILES will be automatically converted to SELFIES using
|
| 483 |
<a href="https://github.com/aspuru-guzik-group/selfies" target="_blank">SELFIES encoder</a>.
|
| 484 |
If conversion fails, a red error message will be displayed.</li>
|
|
|
|
| 485 |
<li>Optionally enter a <strong>1-based</strong> drug atom or substructure index
|
| 486 |
+
to highlight the Top-30 interacting protein residues.</li>
|
|
|
|
| 487 |
<li>After inference, you can use the
|
| 488 |
βDownload PDFβ link to export a high-resolution vector version.</li>
|
| 489 |
</ul>
|
|
|
|
| 556 |
)
|
| 557 |
|
| 558 |
if __name__ == "__main__":
|
| 559 |
+
demo.launch(server_name="0.0.0.0", server_port=7860, share=True)
|