Biofuel-Optimiser / templates /generative.html
carrotcake3's picture
Update templates/generative.html
6c0c71a verified
{% extends "base.html" %}
{% block content %}
<div class="container py-4">
<h3 class="fw-bold mb-4">Molecular Evolution with Genetic Algoritm</h3>
<!-- Input / Config (CLI equivalent of cli.py prompts) -->
<div class="card card-metric p-4 mb-4">
<form method="POST" id="gen-form">
<!-- Optimization Mode -->
<div class="mb-3">
<label class="form-label">Optimisation Mode</label>
<select class="form-select" name="mode" id="mode">
<option value="target" selected>
Target a specific CN value (minimise error from target)
</option>
<option value="maximize">
Maximise CN (find highest possible CN)
</option>
</select>
</div>
<!-- Target CN (only shown for target mode) -->
<div class="mb-3" id="target-cn-block">
<label class="form-label">Enter target CN</label>
<input
type="number"
step="0.1"
name="target_cn"
id="target_cn"
class="form-control"
placeholder="50"
value="50"
required
>
<div class="form-text">
Very low targets can make optimisation challenging; consider CN &gt; 40.
</div>
</div>
<!-- Minimise YSI -->
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="minimize_ysi" id="minimize_ysi">
<label class="form-check-label" for="minimize_ysi">Minimise YSI (y/n)</label>
</div>
<button id="generate-btn" class="btn btn-primary" type="submit">
Run Evolution
</button>
<div id="loading" class="mt-3" style="display:none;">
<div class="spinner-border text-primary" role="status"></div>
<span class="ms-2">Generating molecules… this may take a few minutes.</span>
</div>
</form>
</div>
<!-- Configuration Summary (CLI equivalent printout) -->
{% if run_info %}
<div class="card card-metric p-4 mb-4">
<h5 class="fw-bold mb-3">CONFIGURATION SUMMARY</h5>
<ul class="mb-0">
<li><strong>Mode:</strong> {{ run_info.mode }}</li>
<li><strong>Minimise YSI:</strong> {{ run_info.minimize_ysi }}</li>
<li><strong>Optimisation:</strong>
{% if run_info.minimize_ysi == "Yes" %}
Multi-objective (CN + YSI)
{% else %}
Single-objective (CN only)
{% endif %}
</li>
</ul>
</div>
{% endif %}
<!-- BEST CANDIDATES (CLI equivalent of results.py output) -->
{% if final_table %}
<div class="card card-metric p-4 mb-4">
<h5 class="fw-bold mb-3">BEST CANDIDATES</h5>
<div class="table-responsive">
{{ final_table|safe }}
</div>
{% endif %}
<!-- PARETO FRONT (CLI equivalent) -->
{% if pareto_table %}
<div class="card card-metric p-4 mb-4">
<h5 class="fw-bold mb-3">PARETO FRONT (Non-dominated solutions)</h5>
<div class="table-responsive">
{{ pareto_table|safe }}
</div>
{% endif %}
{% if history %}
<div class="card card-metric p-4 mb-4">
<h5 class="fw-bold mb-3">Evolution Timeline (Sample Structures per Generation)</h5>
<p class="text-muted mb-3">
The top 5 ranked survivor molecules are shown for each generation, based on the optimisation objective.
</p>
{% for h in history %}
<div class="mb-4">
<h6 class="fw-bold mb-2">Generation {{ h.generation }}</h6>
{% if h.samples and h.samples|length > 0 %}
<div class="d-flex flex-wrap gap-3">
{% for s in h.samples %}
<div class="border rounded p-2 text-center" style="width: 260px;">
<div class="badge bg-secondary mb-1">
Rank {{ s.rank }}
</div>
<!-- Molecule name / rank -->
<div class="fw-semibold mb-1">
{{ s.name }}
</div>
<!-- Structure -->
<img
src="{{ url_for('static', filename='generated/' ~ s.img_id) }}"
class="img-fluid"
style="max-width:240px;"
alt="Molecule structure"
/>
<!-- SMILES -->
<div class="mt-2 small text-muted" style="word-break: break-word;">
{{ s.smiles }}
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="text-muted">No valid samples captured for this generation.</div>
{% endif %}
</div>
{% endfor %}
</div>
{% endif %}
{% if error %}
<div class="alert alert-danger">{{ error }}</div>
{% endif %}
</div>
<script>
const form = document.getElementById("gen-form");
const btn = document.getElementById("generate-btn");
const loading = document.getElementById("loading");
const modeSelect = document.getElementById("mode");
const targetBlock = document.getElementById("target-cn-block");
const targetInput = document.getElementById("target_cn");
function syncModeUI() {
const isTarget = (modeSelect.value === "target");
targetBlock.style.display = isTarget ? "block" : "none";
targetInput.required = isTarget;
}
document.addEventListener("DOMContentLoaded", syncModeUI);
modeSelect.addEventListener("change", syncModeUI);
form.addEventListener("submit", () => {
btn.disabled = true;
loading.style.display = "block";
});
</script>
{% endblock %}