Disparate Impact Ratio
${di.toFixed(2)}
Equal Opportunity Diff.
${eod.toFixed(2)}
`;
}
function renderGroupAnalysis(groups, groupMetrics) {
elements.groupTabsContainer.innerHTML = '
Overall ' + groups.map(g => `
${g} `).join('');
const allMetrics = { ...groupMetrics, Overall: calculateMetrics(mergedData, config.fav, config.pa, config.true, config.pred) };
elements.groupContentContainer.innerHTML = ''; // Clear previous
Object.entries(allMetrics).forEach(([group, metrics], index) => {
elements.groupContentContainer.innerHTML += `
Confusion Matrix
Predicted Positive Predicted Negative
Actual Positive ${metrics.tp} ${metrics.fn}
Actual Negative ${metrics.fp} ${metrics.tn}
Performance
Accuracy: ${(metrics.accuracy*100).toFixed(1)}%
Precision: ${(metrics.precision*100).toFixed(1)}%
Recall (TPR): ${(metrics.recall*100).toFixed(1)}%
False Positive Rate: ${(metrics.fpr*100).toFixed(1)}%
Selection Rate: ${(metrics.selectionRate*100).toFixed(1)}%
`;
});
document.querySelectorAll('.aibias-group-tab-btn').forEach(btn => btn.addEventListener('click', (e) => {
document.querySelectorAll('.aibias-group-tab-btn, .aibias-group-content').forEach(el => el.classList.remove('active'));
e.target.classList.add('active');
document.getElementById(`group-content-${e.target.dataset.group}`).classList.add('active');
}));
}
function renderCharts(groups, groupMetrics) {
const chartConfigs = {
accuracy: { title: 'Accuracy', prop: 'accuracy' },
recall: { title: 'True Positive Rate (Recall)', prop: 'recall' },
fpr: { title: 'False Positive Rate', prop: 'fpr' },
selectionRate: { title: 'Selection Rate', prop: 'selectionRate' }
};
elements.chartsContainer.innerHTML = '';
Object.values(charts).forEach(c => c.destroy());
Object.entries(chartConfigs).forEach(([key, conf]) => {
const chartEl = document.createElement('div');
chartEl.className = 'aibias-chart-container';
chartEl.innerHTML = `
`;
elements.chartsContainer.appendChild(chartEl);
charts[key] = new Chart(`chart-${key}`, {
type: 'bar',
data: {
labels: groups,
datasets: [{ label: conf.title, data: groups.map(g => groupMetrics[g][conf.prop]), backgroundColor: 'rgba(23, 162, 184, 0.7)' }]
},
options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, title: { display: true, text: conf.title } } }
});
});
}
// --- Utility ---
window.aibiasShowTab = id => {
document.querySelectorAll('.aibias-tab-content').forEach(c => c.classList.remove('active'));
document.querySelectorAll('.aibias-tab-button').forEach(b => b.classList.remove('active'));
if(id === 'dashboard') {
document.getElementById('aibias-tab-dashboard').classList.add('active');
elements.dashTabBtn.classList.add('active');
} else {
document.getElementById('aibias-tab-setup').classList.add('active');
document.querySelector('.aibias-tab-button[onclick^="aibiasShowTab"]').classList.add('active');
}
};
window.aibiasDownloadPDF = () => {
html2canvas(document.getElementById('aibias-dashboard-output'), { scale: 2 }).then(canvas => {
const pdf = new jspdf.jsPDF({ orientation: 'landscape', unit: 'pt', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const imgWidth = pdfWidth;
const imgHeight = (canvas.height * imgWidth) / canvas.width;
pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, 0, imgWidth, imgHeight);
pdf.save('AI_Bias_Report.pdf');
});
};
});