/**
* Quality tab: per-class quality bars, error-type distribution, the quality
* funnel, cross-run quality trend, and sketch-based distributions.
* Every aggregate-query panel surfaces its provenance badge.
*/
import { useMemo } from 'react';
import Box from '@mui/material/Box';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Typography from '@mui/material/Typography';
import type { ErrorType, EvaluationRunInfo } from '../../types/megaeval';
import {
fmtCompact,
getRunDistributions,
getRunFunnel,
queryEvaluations,
searchErrors,
} from '../../services/megaeval';
import { usePoll } from '../../services/labeleval';
import { ErrorNote, HBar, LoadingBox, SectionCard, fmtNum, fmtPct } from '../labeleval/shared';
import { HeadCell } from '../help/InfoTip';
import {
ERROR_TYPE_COLORS,
ExactnessTag,
HistogramSparkline,
PctBarCell,
QueryBadge,
rowNum,
rowStr,
} from './shared';
// ---------------------------------------------------------------- per-class quality
function QualityByClass({ runId, refreshKey }: { runId: string; refreshKey: number }) {
const q = usePoll(
() =>
queryEvaluations({
evaluation_id: runId,
group_by: ['class'],
metrics: ['n', 'precision', 'recall', 'f1', 'mean_iou'],
}),
null,
[runId, refreshKey]
);
return (
}
sx={{ flex: '1 1 460px' }}
>
{q.error ? : null}
{q.loading && !q.data ? : null}
{q.data ? (
Class
{[...q.data.rows]
.sort((a, b) => b.n - a.n)
.map((row) => (
{rowStr(row, 'class')}
{fmtCompact(row.n)}
{fmtPct(rowNum(row, 'f1'))}
{fmtNum(rowNum(row, 'mean_iou'), 3)}
))}
) : null}
);
}
// ---------------------------------------------------------------- error distribution
const ERROR_TYPE_ORDER: ErrorType[] = ['FN', 'FP', 'LOCALIZATION', 'ANOMALY', 'LOW_CONF'];
function ErrorDistribution({ runId, refreshKey }: { runId: string; refreshKey: number }) {
const res = usePoll(() => searchErrors({ run_id: runId }), null, [runId, refreshKey]);
const byType = res.data?.by_type ?? {};
const total = ERROR_TYPE_ORDER.reduce((acc, t) => acc + (byType[t] ?? 0), 0);
const max = Math.max(1, ...ERROR_TYPE_ORDER.map((t) => byType[t] ?? 0));
const ERROR_TERM_KEYS: Record = {
FN: 'error_fn',
FP: 'error_fp',
LOCALIZATION: 'error_localization',
ANOMALY: 'reason_anomaly',
LOW_CONF: 'error_low_conf',
};
return (
{res.error ? : null}
{res.loading && !res.data ? : null}
{res.data ? (
<>
{fmtCompact(res.data.matched_errors)} potential errors indexed (exact)
{ERROR_TYPE_ORDER.map((t) => {
const count = byType[t] ?? 0;
return (
0 ? fmtPct(count / total) : '—'})`}
/>
);
})}
>
) : null}
);
}
// ---------------------------------------------------------------- quality funnel
function QualityFunnel({ runId, refreshKey }: { runId: string; refreshKey: number }) {
const funnel = usePoll(() => getRunFunnel(runId), null, [runId, refreshKey]);
const stages = funnel.data?.stages ?? [];
const max = stages.length ? Math.max(...stages.map((s) => s.count)) : 1;
const est = funnel.data?.estimated_precision ?? null;
return (
{funnel.error ? : null}
{funnel.loading && !funnel.data ? : null}
{funnel.data ? (
<>
{stages.map((s) => (
))}
{est && est.estimate !== null ? (
Estimated precision {fmtPct(est.estimate)}
{est.ci_low !== null && est.ci_high !== null
? ` (95% CI ${fmtPct(est.ci_low)}–${fmtPct(est.ci_high)}${
est.n_reviewed !== null ? `, n=${est.n_reviewed.toLocaleString()} reviewed` : ''
})`
: ''}
) : null}
>
) : null}
);
}
// ---------------------------------------------------------------- quality trend
const TREND_SERIES: Array<{ key: 'precision' | 'recall' | 'safety_recall'; label: string; color: string }> = [
{ key: 'precision', label: 'precision', color: '#4fc3f7' },
{ key: 'recall', label: 'recall', color: '#66bb6a' },
{ key: 'safety_recall', label: 'safety recall', color: '#ffa726' },
];
function QualityTrend({ runs }: { runs: EvaluationRunInfo[] }) {
const published = useMemo(
() =>
runs
.filter((r) => r.status === 'published')
.sort((a, b) => (a.created_at ?? '').localeCompare(b.created_at ?? '')),
[runs]
);
const width = 520;
const height = 150;
const padL = 40;
const padB = 30;
const padT = 10;
const values = published.flatMap((r) =>
TREND_SERIES.map((s) => r.headline[s.key]).filter((v): v is number => v !== null && v !== undefined)
);
const lo = values.length ? Math.max(0, Math.min(...values) - 0.05) : 0;
const hi = values.length ? Math.min(1, Math.max(...values) + 0.02) : 1;
const xFor = (i: number) =>
padL + (published.length <= 1 ? (width - padL) / 2 : (i / (published.length - 1)) * (width - padL - 10));
const yFor = (v: number) => padT + (1 - (v - lo) / Math.max(1e-9, hi - lo)) * (height - padT - padB);
return (
{published.length < 2 ? (
{published.length === 0
? 'No published runs yet.'
: 'Only one published run — launch another run to see the trend.'}
) : null}
{published.length >= 1 ? (
<>
{TREND_SERIES.map((s) => (
{s.label}
))}
>
) : null}
);
}
// ---------------------------------------------------------------- distributions (sketches)
function DistributionsCard({ runId, refreshKey }: { runId: string; refreshKey: number }) {
const dist = usePoll(() => getRunDistributions(runId), null, [runId, refreshKey]);
const d = dist.data;
return (
Distributions
}
help="Population-scale distributions from mergeable sketches: confidence and IoU histograms come from fixed-bin quantile sketches (p10/p50/p90 markers), container cardinality from a HyperLogLog. Approximate by design — exact counts shown alongside where available."
sx={{ flex: '1 1 320px' }}
>
{dist.error ? : null}
{dist.loading && !d ? : null}
{d ? (
{d.confidence ? (
Confidence — approximate (sketch)
) : null}
{d.iou ? (
IoU — approximate (sketch)
) : null}
Containers (HLL)
{d.containers_hll_estimate === null ? '—' : fmtCompact(d.containers_hll_estimate)}
Containers (exact)
{d.containers_exact === null ? '—' : fmtCompact(d.containers_exact)}
{d.note}
) : null}
);
}
// ---------------------------------------------------------------- tab
export default function QualityTab({
runId,
runs,
refreshKey,
}: {
runId: string;
runs: EvaluationRunInfo[];
refreshKey: number;
}) {
return (
);
}