WebashalarForML's picture
Upload 5 files
623a404 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Diamond AI / Results</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<canvas id="canvas3d" style="opacity: 0.8"></canvas>
<div class="atmospheric-grain"></div>
<div class="container animate-up">
<nav style="padding: 0.5rem 0;">
<div class="nav-logo">RESULTS / DASHBOARD</div>
<div class="nav-meta">
<span>STATUS: COMPLETE</span>
</div>
</nav>
<header style="display: flex; justify-content: space-between; align-items: center; margin: 0.5rem 0;">
<div>
<p class="label-mini">Batch Processing Overview</p>
<h1 style="font-size: 2.5rem; line-height: 1;">ANALYTICS <span class="italic">REPORT</span></h1>
</div>
<div style="display: flex; gap: 0.8rem;">
<a href="/" class="btn-launch"
style="text-decoration: none; padding: 0.6rem 1.2rem; font-size: 9px; background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.5); color: white; opacity: 1;">
NEW BATCH</a>
<a href="/download/{{ report_file }}" class="btn-launch"
style="text-decoration: none; padding: 0.6rem 1.2rem; font-size: 9px;">EXPORT DATASET</a>
</div>
</header>
{% if metrics %}
<!-- Single-Screen Dashboard Grid -->
<div class="dashboard-grid">
<!-- Left Column: KPIs + Class Decomposition -->
<div class="dashboard-main">
<!-- KPI Row -->
<div class="kpi-row">
<div class="kpi-card">
<span class="kpi-value">{{ (metrics.accuracy * 100)|round(1) }}%</span>
<span class="kpi-label">ACCURACY</span>
</div>
<div class="kpi-card">
<span class="kpi-value">{{ metrics.f1|round(3) }}</span>
<span class="kpi-label">WEIGHTED F1</span>
</div>
<div class="kpi-card">
<span class="kpi-value">{{ metrics.macro_f1|round(3) }}</span>
<span class="kpi-label">MACRO F1</span>
</div>
</div>
<!-- Class-Wise Table (Compact) -->
<div class="compact-table-section">
<p class="section-label">CLASS-WISE METRICS</p>
<div class="compact-table-wrapper">
<table class="compact-table">
<thead>
<tr>
<th>GRADE</th>
<th>PREC</th>
<th>RECALL</th>
<th>F1</th>
<th>SUP</th>
</tr>
</thead>
<tbody>
{% for item in metrics.class_metrics %}
<tr>
<td class="grade-col">{{ item.label }}</td>
<td>{{ item.precision }}</td>
<td>{{ item.recall }}</td>
<td>{{ item.f1 }}</td>
<td class="sup-col">{{ item.support }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<!-- Right Column: Confusion Matrix -->
<div class="dashboard-sidebar">
<p class="section-label">CONFUSION MATRIX</p>
<div class="cm-compact">
<table class="cm-compact-table">
<thead>
<tr>
<th class="cm-corner">A\P</th>
{% for label in metrics.confusion_matrix.labels %}
<th>{{ label }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row_idx in range(metrics.confusion_matrix.matrix|length) %}
<tr>
<td class="cm-row-label">{{ metrics.confusion_matrix.labels[row_idx] }}</td>
{% for col_idx in range(metrics.confusion_matrix.matrix[row_idx]|length) %}
{% set val = metrics.confusion_matrix.matrix[row_idx][col_idx] %}
<td
class="cm-cell {% if row_idx == col_idx %}cm-diag{% endif %} {% if val == 0 %}cm-zero{% endif %}">
{{ val }}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Summary Cards -->
<div class="summary-mini">
<div class="summary-mini-card">
<span class="summary-mini-label">MACRO F1</span>
<span class="summary-mini-value">{{ metrics.macro_f1|round(3) }}</span>
</div>
<div class="summary-mini-card">
<span class="summary-mini-label">ACCURACY</span>
<span class="summary-mini-value">{{ (metrics.accuracy * 100)|round(1) }}%</span>
</div>
</div>
</div>
</div>
{% endif %}
<!-- Inference Manifest (Expanded by default for immediate access) -->
<section class="manifest-section">
<div class="manifest-header" onclick="toggleManifest()">
<p class="section-label" style="margin: 0;">INFERENCE MANIFEST</p>
<span class="toggle-icon" id="manifest-toggle"></span>
</div>
<div class="manifest-content" id="manifest-content" style="display: block;">
<div class="table-wrapper" style="max-height: 350px; margin-top: 0.5rem;">
<table>
<thead>
<tr>
<th>STONE ID</th>
{% for feature in model_features %}
<th>{{ feature }}</th>
{% endfor %}
<th>AI RESULT</th>
{% for col in out_of_box_cols %}
<th>{{ col }}</th>
{% endfor %}
<th>IMG</th>
</tr>
</thead>
<tbody>
{% for row in report_data %}
<tr>
<td class="stone-id-col">{{ row.L_Code }}</td>
{% for feature in model_features %}
<td style="opacity: 0.7; font-size: 11px;">{{ row[feature] }}</td>
{% endfor %}
<td class="result-col">{{ row.Predicted_FGrdCol }}</td>
{% for col in out_of_box_cols %}
<td style="font-size: 10px;">
{% if row[col] and row[col]|string != 'nan' %}
<span class="badge-oob">{{ row[col] }}</span>
{% else %}
<span style="opacity: 0.2;">-</span>
{% endif %}
</td>
{% endfor %}
<td>
{% if row.Image_Path != 'N/A' %}
<img src="/image/{{ row.Image_Path }}" class="img-thumb"
onclick="openModal(this.src)" alt="Diamond">
{% else %}
<span style="font-size: 8px; opacity: 0.3;">N/A</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</section>
<footer style="margin-top: 1rem; padding-bottom: 1rem; text-align: center;">
<a href="/"
style="font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase; color: white; opacity: 0.5; text-decoration: none;">
NEW BATCH</a>
</footer>
</div>
<!-- Image Viewer Modal -->
<div id="image-modal">
<span class="modal-close" onclick="closeModal()">&times;</span>
<img id="modal-img" src="" alt="Enlarged View">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
function toggleManifest() {
const content = document.getElementById('manifest-content');
const toggle = document.getElementById('manifest-toggle');
if (content.style.display === 'none') {
content.style.display = 'block';
toggle.textContent = '▼';
} else {
content.style.display = 'none';
toggle.textContent = '▶';
}
}
function openModal(src) {
const modal = document.getElementById('image-modal');
const modalImg = document.getElementById('modal-img');
modal.classList.add('active');
modalImg.src = src;
}
function closeModal() {
const modal = document.getElementById('image-modal');
modal.classList.remove('active');
}
document.getElementById('image-modal').onclick = function (e) {
if (e.target === this) closeModal();
};
// Background shader
const vertexShader = `varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`;
const fragmentShader = `
uniform float uTime;
varying vec2 vUv;
vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); }
float snoise(vec2 v){
const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);
vec2 i = floor(v + dot(v, C.yy) );
vec2 x0 = v - i + dot(i, C.xx);
vec2 i1; i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
vec4 x12 = x0.xyxy + C.xxzz; x12.xy -= i1;
i = mod(i, 289.0);
vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) + i.x + vec3(0.0, i1.x, 1.0 ));
vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
m = m*m ; m = m*m ;
vec3 x = 2.0 * fract(p * C.www) - 1.0;
vec3 h = abs(x) - 0.5;
vec3 ox = floor(x + 0.5);
vec3 a0 = x - ox;
m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
vec3 g; g.x = a0.x * x0.x + h.x * x0.y; g.yz = a0.yz * x12.xz + h.yz * x12.yw;
return 130.0 * dot(m, g);
}
void main() {
vec2 uv = vUv;
float n = snoise(uv * 1.5 + uTime * 0.03);
vec3 color = mix(vec3(0.0, 0.0, 0.0), vec3(0.05, 0.02, 0.1), n * 0.5 + 0.5);
gl_FragColor = vec4(color, 1.0);
}
`;
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
const renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('canvas3d'), antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
const geometry = new THREE.PlaneGeometry(2, 2);
const uniforms = { uTime: { value: 0 } };
const material = new THREE.ShaderMaterial({ vertexShader, fragmentShader, uniforms });
scene.add(new THREE.Mesh(geometry, material));
const animate = (t) => {
uniforms.uTime.value = t * 0.001;
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
requestAnimationFrame(animate);
window.onresize = () => renderer.setSize(window.innerWidth, window.innerHeight);
</script>
</body>
</html>