Spaces:
Runtime error
Runtime error
File size: 7,958 Bytes
965f144 | 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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | {% extends "base.html" %}
{% block title %}Molecule Analyzer β MoleSight AI{% endblock %}
{% block content %}
<div class="page-header fade-up">
<h1>Molecule <span class="accent">Analyzer</span></h1>
<div class="sub">Compute physicochemical properties Β· Lipinski / Veber / Ghose rule assessment Β· 2D structure rendering</div>
</div>
<div class="grid-2 fade-up">
<!-- Input panel -->
<div>
<div class="card" style="margin-bottom:1rem">
<div class="card-title">SMILES Input</div>
<form method="POST" action="{{ url_for('main.analyze') }}">
<div class="form-group">
<label class="form-label" for="smiles-input">SMILES String</label>
<input id="smiles-input" name="smiles" class="form-input"
placeholder="e.g. CC(=O)Oc1ccccc1C(=O)O"
value="{{ smiles_input }}" autocomplete="off"/>
</div>
<div style="margin-bottom:1rem">
<div class="form-label">Quick Examples</div>
<div class="example-pills">
{% for name, smi in examples %}
<span class="pill" data-smiles="{{ smi }}">{{ name }}</span>
{% endfor %}
</div>
</div>
<button type="submit" class="btn btn-primary">⬑ Analyze Molecule</button>
</form>
</div>
{% if error %}
<div class="alert alert-error fade-up">β {{ error }}</div>
{% endif %}
{% if result %}
<!-- Property table -->
<div class="card fade-up" style="margin-bottom:1rem">
<div class="card-title">Physicochemical Properties</div>
<table class="prop-table">
<thead>
<tr><th>Property</th><th>Value</th><th>Threshold</th></tr>
</thead>
<tbody>
{% set p = result.props %}
<tr><td>Formula</td><td class="val">{{ p.formula }}</td><td>β</td></tr>
<tr><td>Mol. Weight (Da)</td><td class="val">{{ p.mw }}</td><td>≤500 (Ro5)</td></tr>
<tr><td>LogP</td><td class="val">{{ p.logp }}</td><td>≤5 (Ro5)</td></tr>
<tr><td>H-Bond Donors</td><td class="val">{{ p.hbd }}</td><td>≤5 (Ro5)</td></tr>
<tr><td>H-Bond Acceptors</td><td class="val">{{ p.hba }}</td><td>≤10 (Ro5)</td></tr>
<tr><td>TPSA (Γ
Β²)</td><td class="val">{{ p.tpsa }}</td><td>≤140 (Veber)</td></tr>
<tr><td>Rotatable Bonds</td><td class="val">{{ p.rotbonds }}</td><td>≤10 (Veber)</td></tr>
<tr><td>Heavy Atoms</td><td class="val">{{ p.heavy_atoms }}</td><td>20β70 (Ghose)</td></tr>
<tr><td>Aromatic Rings</td><td class="val">{{ p.aromatic_rings }}</td><td>β</td></tr>
<tr><td>FspΒ³</td><td class="val">{{ p.fsp3 }}</td><td>>0.25 preferred</td></tr>
<tr><td>QED Score</td><td class="val" style="color:var(--amber)">{{ p.qed }}</td><td>0β1 (higher=better)</td></tr>
</tbody>
</table>
</div>
<!-- Rule assessments -->
<div class="card fade-up">
<div class="card-title">Rule Assessments</div>
<div style="margin-bottom:.75rem">
<div style="display:flex;align-items:center;gap:.5rem;margin-bottom:.4rem">
<span style="font-size:.7rem;color:var(--muted);text-transform:uppercase;letter-spacing:.08em">Lipinski Ro5</span>
{% if result.lipinski.passed %}
<span class="tag tag-green">β PASS</span>
{% else %}
<span class="tag tag-red">{{ result.lipinski.violations }} violation{{ 's' if result.lipinski.violations != 1 }}</span>
{% endif %}
</div>
<div class="rule-grid">
{% for rule, passed in result.lipinski.rules.items() %}
<div class="rule-item {{ 'rule-pass' if passed else 'rule-fail' }}">
<span class="rule-check">{{ 'β' if passed else 'β' }}</span>
<span style="font-size:.7rem;color:{{ 'var(--g1)' if passed else 'var(--red)' }}">{{ rule }}</span>
</div>
{% endfor %}
</div>
</div>
<div style="margin-bottom:.75rem">
<div style="display:flex;align-items:center;gap:.5rem;margin-bottom:.4rem">
<span style="font-size:.7rem;color:var(--muted);text-transform:uppercase;letter-spacing:.08em">Veber Rules</span>
{% if result.veber.passed %}
<span class="tag tag-green">β PASS</span>
{% else %}
<span class="tag tag-amber">{{ result.veber.violations }} violation{{ 's' if result.veber.violations != 1 }}</span>
{% endif %}
</div>
<div class="rule-grid">
{% for rule, passed in result.veber.rules.items() %}
<div class="rule-item {{ 'rule-pass' if passed else 'rule-fail' }}">
<span class="rule-check">{{ 'β' if passed else 'β' }}</span>
<span style="font-size:.7rem;color:{{ 'var(--g1)' if passed else 'var(--red)' }}">{{ rule }}</span>
</div>
{% endfor %}
</div>
</div>
<div>
<div style="display:flex;align-items:center;gap:.5rem;margin-bottom:.4rem">
<span style="font-size:.7rem;color:var(--muted);text-transform:uppercase;letter-spacing:.08em">Ghose Filter</span>
{% if result.ghose.passed %}
<span class="tag tag-green">β PASS</span>
{% else %}
<span class="tag tag-amber">{{ result.ghose.violations }} violation{{ 's' if result.ghose.violations != 1 }}</span>
{% endif %}
</div>
<div class="rule-grid">
{% for rule, passed in result.ghose.rules.items() %}
<div class="rule-item {{ 'rule-pass' if passed else 'rule-fail' }}">
<span class="rule-check">{{ 'β' if passed else 'β' }}</span>
<span style="font-size:.7rem;color:{{ 'var(--g1)' if passed else 'var(--red)' }}">{{ rule }}</span>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
</div>
<!-- Right panel: structure + radar -->
<div>
{% if result %}
<!-- 2D Structure -->
<div class="card fade-up" style="margin-bottom:1rem">
<div class="card-title">2D Structure Rendering</div>
{% if result.svg_img %}
<div class="mol-svg">
{{ result.svg_img | safe }}
</div>
{% else %}
<div class="mol-placeholder">
<span>π¬ RDKit not available β structure not rendered</span>
</div>
{% endif %}
</div>
<!-- Radar -->
<div class="card fade-up">
<div class="card-title">Drug-Likeness Profile (Radar)</div>
<div id="chart-radar" class="plotly-wrap" style="min-height:320px"></div>
</div>
{% else %}
<!-- Placeholder info -->
<div class="card fade-up" style="border-style:dashed;margin-bottom:1rem">
<div style="text-align:center;padding:2rem;color:var(--muted)">
<div style="font-size:3rem;margin-bottom:.75rem">⬑</div>
<div style="font-size:.85rem">Enter a SMILES string and click <strong style="color:var(--g1)">Analyze Molecule</strong> to compute properties.</div>
</div>
</div>
<div class="card fade-up">
<div class="card-title">About the Rules</div>
<div style="font-size:.78rem;color:var(--text);line-height:1.7">
<p style="margin-bottom:.6rem"><strong style="color:var(--g1)">Lipinski's Rule of Five</strong> β MW ≤500, LogP ≤5, HBD ≤5, HBA ≤10. Predicts oral bioavailability.</p>
<p style="margin-bottom:.6rem"><strong style="color:var(--g2)">Veber Rules</strong> β TPSA ≤140 Γ
Β² and RotBonds ≤10. Predicts good oral absorption in rats.</p>
<p><strong style="color:var(--amber)">Ghose Filter</strong> β Tighter constraints on MW, LogP, and heavy atom count for lead-like molecules.</p>
</div>
</div>
{% endif %}
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
</script>
{% endblock %}
|