resonanzband_untersuchung/heatmap_visualization/js/app.js

125 lines
3.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
/**
* @file js/app.js
* @description Initialisiert die Resonanzband-Heatmap-Anwendung. Lädt Daten von /heatmap und reagiert auf Nutzerinteraktionen.
* @version 1.0.0
*/
/**
* Lädt Heatmap-Daten von der API /heatmap.
* @param {Object} [filters] - optionale Filterparameter { cohort_id, time_window }
* @returns {Promise<Object>} - Promise mit Heatmap-Daten und Metadaten
*/
async function loadHeatmapData(filters = {}) {
try {
const url = new URL('/heatmap', window.location.origin);
Object.entries(filters).forEach(([key, value]) => {
if (value !== undefined && value !== '') {
url.searchParams.append(key, value);
}
});
const response = await fetch(url.toString(), { method: 'GET' });
if (!response.ok) {
throw new Error(`API-Fehler: ${response.status}`);
}
const data = await response.json();
renderHeatmap(data);
} catch (err) {
console.error('Fehler beim Laden der Heatmap-Daten:', err);
renderError(`Fehler beim Laden der Daten: ${err.message}`);
}
}
/**
* Rendert die Heatmap auf Basis der übergebenen Daten.
* @param {Object} data - Heatmap-Datenobjekt
*/
function renderHeatmap(data) {
const canvas = document.getElementById('heatmap-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const matrix = data?.matrix || [];
const rows = matrix.length;
const cols = rows > 0 ? matrix[0].length : 0;
const cellWidth = canvas.width / (cols || 1);
const cellHeight = canvas.height / (rows || 1);
ctx.clearRect(0, 0, canvas.width, canvas.height);
matrix.forEach((row, y) => {
row.forEach((value, x) => {
const color = getColorForValue(value);
ctx.fillStyle = color;
ctx.fillRect(x * cellWidth, y * cellHeight, cellWidth, cellHeight);
});
});
renderMetrics(data);
}
/**
* Zeigt grundlegende Metriken aus den Heatmap-Daten an.
* @param {Object} data - Heatmap-Datenobjekt mit Metadaten
*/
function renderMetrics(data) {
const metricsContainer = document.getElementById('heatmap-metrics');
if (!metricsContainer) return;
const { band_center, band_width, cluster_score } = data || {};
metricsContainer.innerHTML = `
<p>Band Center: ${band_center ?? ''}</p>
<p>Band Width: ${band_width ?? ''}</p>
<p>Cluster Score: ${cluster_score ?? ''}</p>
`;
}
/**
* Berechnet eine Farbskala für Heatmap-Werte.
* @param {number} value - numerischer Intensitätswert (01)
* @returns {string} CSS-Farbwert (rgba)
*/
function getColorForValue(value) {
const v = Math.max(0, Math.min(1, value));
const r = Math.floor(255 * v);
const g = Math.floor(100 * (1 - v));
const b = 150;
return `rgba(${r}, ${g}, ${b}, 0.9)`;
}
/**
* Zeigt eine Fehlermeldung im UI an.
* @param {string} message - Text der Fehlermeldung
*/
function renderError(message) {
const container = document.getElementById('heatmap-container');
if (container) container.innerHTML = `<div class="error">${message}</div>`;
}
/**
* Behandelt Änderungen der Filter und ruft neue Daten ab.
* @param {Event} event - Auslösendes Event
*/
function handleFilterChange(event) {
const form = event.currentTarget.form || document.getElementById('filter-form');
if (!form) return;
const formData = new FormData(form);
const filters = Object.fromEntries(formData.entries());
loadHeatmapData(filters);
}
/**
* Initialisiert die App, bindet Event-Listener und lädt erste Heatmap-Daten.
*/
function initApp() {
const form = document.getElementById('filter-form');
if (form) {
form.addEventListener('change', handleFilterChange);
form.addEventListener('submit', (e) => {
e.preventDefault();
handleFilterChange(e);
});
}
loadHeatmapData();
}
window.addEventListener('load', initApp);