Spaces:
Running
Running
File size: 7,493 Bytes
c8b3494 51ef30e 1e49f8f 51ef30e c8b3494 51ef30e c8b3494 62d05c0 51ef30e 62d05c0 51ef30e 30603a2 c8b3494 51ef30e c8b3494 51ef30e 62d05c0 21e2ad6 30603a2 21e2ad6 51ef30e c8b3494 51ef30e 62d05c0 30603a2 51ef30e 62d05c0 51ef30e 30603a2 c8b3494 51ef30e 8af7af6 51ef30e d016f1b 51ef30e c8b3494 51ef30e c8b3494 51ef30e 8af7af6 51ef30e d016f1b 51ef30e c8b3494 abb8b9d 51ef30e abb8b9d 51ef30e abb8b9d 51ef30e 8af7af6 51ef30e d016f1b 51ef30e abb8b9d c8b3494 21e2ad6 51ef30e 62d05c0 51ef30e 62d05c0 51ef30e 62d05c0 51ef30e 21e2ad6 51ef30e 21e2ad6 51ef30e | 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 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | {% extends "base.html" %}
{% block content %}
<div class="container py-4">
<!-- Header -->
<div class="mb-4">
<h2 class="fw-bold mb-2">Pure Fuel Generator</h2>
<p class="page-intro-text mb-0">
Generate candidate pure fuel molecules using molecular evolution and rank them based on
cetane number, fuel property constraints, and optional YSI minimisation.
</p>
</div>
<!-- Alerts -->
{% if error %}
<div class="alert alert-danger">
<i class="bi bi-exclamation-triangle me-2"></i>{{ error }}
</div>
{% endif %}
{% if info %}
<div class="alert alert-info">
<i class="bi bi-info-circle me-2"></i>{{ info }}
</div>
{% endif %}
<!-- Configuration form -->
<div class="card card-metric p-4 mb-4">
<h5 class="fw-bold mb-3">Generator Configuration</h5>
<form method="POST" id="gen-form">
<div class="row g-3 align-items-end">
<div class="col-md-4">
<label class="form-label fw-semibold">Optimisation Mode</label>
<select name="mode" id="generatorMode" class="form-select" onchange="toggleTargetCN()">
<option value="target">Target a specific CN</option>
<option value="maximize">Maximise CN</option>
</select>
<div class="form-text">
Choose whether to target a desired CN value or search for the highest CN candidates.
</div>
</div>
<div class="col-md-3" id="targetCnBox">
<label class="form-label fw-semibold">Target CN</label>
<input type="number" step="0.01" name="target_cn" class="form-control" value="50">
<div class="form-text">
CN above 40 is recommended for easier optimisation.
</div>
</div>
<div class="col-md-3">
<label class="form-label fw-semibold">YSI Objective</label>
<div class="form-check mt-2">
<input class="form-check-input" type="checkbox" name="minimize_ysi" id="minimizeYsi">
<label class="form-check-label" for="minimizeYsi">
Minimise YSI
</label>
</div>
<div class="form-text">
Enables multi-objective optimisation for CN and smoke tendency.
</div>
</div>
<div class="col-md-2 text-md-end">
<button id="generate-btn" type="submit" class="btn btn-primary w-100">
Run Generator
</button>
</div>
</div>
<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>
<!-- Run summary -->
{% if run_info %}
<div class="card card-metric p-4 mb-4">
<h5 class="fw-bold mb-3">Generation Summary</h5>
<div class="row g-3">
<div class="col-md-3">
<div class="border rounded-3 p-3 bg-white">
<p class="text-muted small mb-1">Mode</p>
<h6 class="fw-bold mb-0">{{ run_info.mode }}</h6>
</div>
</div>
<div class="col-md-2">
<div class="border rounded-3 p-3 bg-white">
<p class="text-muted small mb-1">Target CN</p>
<h6 class="fw-bold mb-0">
{% if run_info.target_cn is not none %}
{{ run_info.target_cn }}
{% else %}
—
{% endif %}
</h6>
</div>
</div>
<div class="col-md-3">
<div class="border rounded-3 p-3 bg-white">
<p class="text-muted small mb-1">Objective</p>
<h6 class="fw-bold mb-0">{{ run_info.objective }}</h6>
</div>
</div>
<div class="col-md-2">
<div class="border rounded-3 p-3 bg-white">
<p class="text-muted small mb-1">Filtered</p>
<h6 class="fw-bold mb-0">{{ run_info.n_final }}</h6>
</div>
</div>
<div class="col-md-2">
<div class="border rounded-3 p-3 bg-white">
<p class="text-muted small mb-1">Pareto</p>
<h6 class="fw-bold mb-0">{{ run_info.n_pareto }}</h6>
</div>
</div>
</div>
</div>
{% endif %}
<!-- Final filtered candidates -->
{% if final_table %}
<div class="card card-metric p-4 mb-4">
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
<div>
<h5 class="fw-bold mb-1">Best Candidates with Property Constraints</h5>
<p class="text-muted small mb-0">
Candidates ranked after applying fuel property filters.
</p>
</div>
<form method="POST" action="{{ url_for('download_generator_result', result_type='final') }}">
<input type="hidden" name="results_data" value='{{ final_records | tojson }}'>
<button type="submit" class="btn btn-outline-success btn-sm">
Download Filtered CSV
</button>
</form>
</div>
<div class="table-responsive app-table-wrap molecule-table">
{{ final_table | safe }}
</div>
</div>
{% endif %}
<!-- Unfiltered candidates -->
{% if unfiltered_table %}
<div class="card card-metric p-4 mb-4">
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
<div>
<h5 class="fw-bold mb-1">Best Candidates without Property Constraints</h5>
<p class="text-muted small mb-0">
Raw generated candidates before final property filtering.
</p>
</div>
<form method="POST" action="{{ url_for('download_generator_result', result_type='unfiltered') }}">
<input type="hidden" name="results_data" value='{{ unfiltered_records | tojson }}'>
<button type="submit" class="btn btn-outline-secondary btn-sm">
Download Unfiltered CSV
</button>
</form>
</div>
<div class="table-responsive app-table-wrap molecule-table">
{{ unfiltered_table | safe }}
</div>
</div>
{% endif %}
<!-- Pareto front -->
{% if pareto_table %}
<div class="card card-metric p-4 mb-4">
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
<div>
<h5 class="fw-bold mb-1">Pareto Front</h5>
<p class="text-muted small mb-0">
Non-dominated candidates balancing CN accuracy and low YSI.
</p>
</div>
<form method="POST" action="{{ url_for('download_generator_result', result_type='pareto') }}">
<input type="hidden" name="results_data" value='{{ pareto_records | tojson }}'>
<button type="submit" class="btn btn-outline-primary btn-sm">
Download Pareto CSV
</button>
</form>
</div>
<div class="table-responsive app-table-wrap molecule-table">
{{ pareto_table | safe }}
</div>
</div>
{% endif %}
</div>
<script>
const form = document.getElementById("gen-form");
const btn = document.getElementById("generate-btn");
const loading = document.getElementById("loading");
function toggleTargetCN() {
const mode = document.getElementById("generatorMode").value;
const targetBox = document.getElementById("targetCnBox");
if (mode === "maximize") {
targetBox.style.display = "none";
} else {
targetBox.style.display = "block";
}
}
document.addEventListener("DOMContentLoaded", toggleTargetCN);
if (form) {
form.addEventListener("submit", () => {
btn.disabled = true;
loading.style.display = "block";
});
}
</script>
{% endblock %} |