hydropd / website /src /components /ModelDetail.tsx
rikardsaqe's picture
User fixes + full Impeccable critique pass
4548710 verified
Raw
History Blame Contribute Delete
3.03 kB
import {
classifierLabel,
featureSetLabel,
TRAINING_META,
type RealModel,
} from '../data/models'
function metric(v: number | null): string {
return v == null ? 'n/a' : v.toFixed(3)
}
// Expandable per-model detail: paper + config + metrics + caveats.
// Shared by the Benchmarking leaderboard and the Detectability model picker.
export default function ModelDetail({ m }: { m: RealModel }) {
return (
<div className="detail-panel">
{m.paperTitle && (
<p style={{ marginBottom: 12 }}>
<strong>Source paper:</strong> {m.paperTitle}
{m.paperLink && (
<>
{' '}
·{' '}
<a href={m.paperLink} target="_blank" rel="noreferrer">
link ↗
</a>
</>
)}
</p>
)}
<dl className="detail-grid">
<dt>Dataset</dt>
<dd>
<span className="mono">{m.code}</span> ({m.hcode})
{m.rawMaterial && <> · {m.rawMaterial}</>}
</dd>
<dt>Species</dt>
<dd>
{m.species}
{m.taxId && <> · tax {m.taxId}</>}
</dd>
<dt>Enzyme</dt>
<dd>{m.enzyme}</dd>
<dt>Proteome</dt>
<dd>
{m.proteome}{' '}
{m.proteomeApprox && (
<span className="badge badge-muted" title="Approximate / homolog-level proteome">
approximate
</span>
)}
</dd>
<dt>Classifier</dt>
<dd>{classifierLabel(m.bestModel)}</dd>
<dt>Feature set</dt>
<dd>{featureSetLabel(m.bestFeatureSet)}</dd>
<dt>Cross-validation</dt>
<dd>{TRAINING_META.cv}</dd>
<dt>Negatives</dt>
<dd>{TRAINING_META.negatives}</dd>
<dt>Positives</dt>
<dd>{m.nPos.toLocaleString()}</dd>
<dt>Metrics</dt>
<dd>
<div className="chip-list">
<span className="badge badge-accent">AUROC {metric(m.calibAuroc)}</span>
<span className="badge">AUPRC {metric(m.calibAuprc)}</span>
<span className="badge">MCC {metric(m.calibMcc)}</span>
<span className="badge">F1 {metric(m.calibF1)}</span>
<span className="badge">Brier {metric(m.brier)}</span>
<span className="badge">ECE {metric(m.ece)}</span>
</div>
<div className="muted" style={{ fontSize: '0.75rem', marginTop: 4 }}>
Grid AUROC {metric(m.gridAuroc)} · tuned CV AUROC {metric(m.tunedCvAuroc)}.
AUROC/AUPRC are out-of-fold calibration values.
</div>
</dd>
{m.flags.length > 0 && (
<>
<dt>Caveats</dt>
<dd>
<ul style={{ margin: 0, paddingLeft: 18 }}>
{m.flags.map((fl, i) => (
<li key={i} style={{ fontSize: 'var(--text-sm)' }}>
{fl}
</li>
))}
</ul>
</dd>
</>
)}
</dl>
</div>
)
}