Spaces:
Sleeping
Sleeping
File size: 3,608 Bytes
0fcd1da 78e0383 0fcd1da 14da265 78e0383 0fcd1da 78e0383 0fcd1da 14da265 78e0383 0fcd1da 78e0383 14da265 78e0383 14da265 78e0383 14da265 78e0383 14da265 78e0383 14da265 0fcd1da | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | import html
import logging
from typing import List, Tuple
import numpy as np
import pandas as pd
from rdkit import Chem
from rdkit.Chem import Draw
logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())
def _draw_molecule_svg(smiles: str, size: Tuple[int, int]) -> str:
mol = Chem.MolFromSmiles(smiles)
if mol is None:
return f"<pre class='gt4sd-smiles'>{html.escape(smiles)}</pre>"
svg = Draw.MolsToGridImage([mol], molsPerRow=1, subImgSize=size, useSVG=True)
return str(svg).replace("<?xml version='1.0' encoding='iso-8859-1'?>", "")
def _draw_static_grid(
result_df: pd.DataFrame, n_cols: int, size: Tuple[int, int]
) -> str:
columns = [column for column in result_df.columns if column != "SMILES"]
cards = []
for _, row in result_df.iterrows():
smiles = str(row["SMILES"])
details = "".join(
f"<dt>{html.escape(str(column))}</dt>"
f"<dd>{html.escape(str(row[column]))}</dd>"
for column in columns
)
cards.append(
"<section class='gt4sd-molecule-card'>"
f"<div class='gt4sd-molecule-image'>{_draw_molecule_svg(smiles, size)}</div>"
f"<dl class='gt4sd-molecule-details'>{details}</dl>"
"</section>"
)
return f"""
<style>
.gt4sd-molecule-grid {{
display: grid;
grid-template-columns: repeat({max(1, n_cols)}, minmax(180px, 1fr));
gap: 12px;
width: 100%;
max-height: 900px;
overflow: auto;
}}
.gt4sd-molecule-card {{
border: 1px solid #e5e7eb;
border-radius: 6px;
background: #fff;
padding: 12px;
min-width: 0;
}}
.gt4sd-molecule-image svg {{
width: 100%;
max-width: {size[0]}px;
height: auto;
display: block;
margin: 0 auto 8px;
}}
.gt4sd-molecule-details {{
display: grid;
grid-template-columns: max-content minmax(0, 1fr);
gap: 4px 10px;
margin: 0;
font: 13px/1.35 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}}
.gt4sd-molecule-details dt {{ color: #6b7280; font-weight: 600; }}
.gt4sd-molecule-details dd {{ margin: 0; min-width: 0; overflow-wrap: anywhere; }}
.gt4sd-smiles {{ white-space: pre-wrap; overflow-wrap: anywhere; }}
@media (max-width: 720px) {{
.gt4sd-molecule-grid {{ grid-template-columns: 1fr; }}
}}
</style>
<div class='gt4sd-molecule-grid'>
{''.join(cards)}
</div>
"""
def draw_grid_predict(
sequences: List[str], properties: np.array, property_names: List[str], domain: str
) -> str:
"""
Uses RDKit SVGs to draw a HTML grid for the prediction
Args:
sequences: Sequences for which properties are predicted.
properties: Predicted properties. Array of shape (n_samples, n_properties).
names: List of property names
domain: Domain of the prediction (molecules or proteins).
Returns:
HTML to display
"""
if domain not in ["Molecules", "Proteins"]:
raise ValueError(f"Unsupported domain {domain}")
if domain == "Proteins":
converter = lambda x: Chem.MolToSmiles(Chem.MolFromFASTA(x))
else:
converter = lambda x: x
smiles = []
for sequence in sequences:
try:
seq = converter(sequence)
smiles.append(seq)
except Exception:
logger.warning(f"Could not draw sequence {seq}")
result = pd.DataFrame({"SMILES": smiles})
for i, name in enumerate(property_names):
result[name] = properties[:, i]
n_cols = min(3, len(result))
size = (140, 200) if len(result) > 3 else (600, 700)
return _draw_static_grid(result, n_cols=n_cols, size=size)
|