import { useState } from 'react' import Card from '../components/Card' import Button from '../components/Button' import Field from '../components/Field' import SequenceInput from '../components/SequenceInput' import TaxIdInput from '../components/TaxIdInput' import { CLASSIFIER_OPTIONS, DEFAULT_TRAINING_CONFIG, FEATURE_SET_OPTIONS, SPLIT_OPTIONS, SAMPLE_PEPTIDES, type TrainingConfig, type TrainingResult, } from '../data/mockData' import { trainDetectability } from '../lib/api' export default function DetectabilityTraining() { const [input, setInput] = useState('') const [taxId, setTaxId] = useState('') const [useDefaults, setUseDefaults] = useState(true) const [cfg, setCfg] = useState(DEFAULT_TRAINING_CONFIG) const [training, setTraining] = useState(false) const [result, setResult] = useState(null) const [live, setLive] = useState(false) const [downloadUrl, setDownloadUrl] = useState(null) const [dataUrl, setDataUrl] = useState(null) const [errorMsg, setErrorMsg] = useState(null) const canRun = input.trim().length > 0 && taxId.length > 0 && !training function set(k: K, v: TrainingConfig[K]) { setUseDefaults(false) setCfg((c) => ({ ...c, [k]: v })) } // Pfly is a coupled choice: picking it in either the classifier or the feature-set // dropdown keeps the other in sync (and de-selecting it restores the default). function setClassifier(v: string) { setUseDefaults(false) setCfg((c) => ({ ...c, classifier: v, featureSet: v === 'pfly' ? 'pfly' : c.featureSet === 'pfly' ? DEFAULT_TRAINING_CONFIG.featureSet : c.featureSet, })) } function setFeatureSet(v: string) { setUseDefaults(false) setCfg((c) => ({ ...c, featureSet: v, classifier: v === 'pfly' ? 'pfly' : c.classifier === 'pfly' ? DEFAULT_TRAINING_CONFIG.classifier : c.classifier, })) } function toggleDefaults(on: boolean) { setUseDefaults(on) if (on) setCfg(DEFAULT_TRAINING_CONFIG) } async function train() { setTraining(true) setResult(null) setErrorMsg(null) setDownloadUrl(null) setDataUrl(null) try { const out = await trainDetectability(input, taxId, cfg) setResult(out.result) setLive(out.live) setDownloadUrl(out.downloadUrl) setDataUrl(out.dataUrl) setErrorMsg(out.error ?? null) } finally { setTraining(false) } } return (

Train a Detectability Model

Give detected peptides and a species tax ID, pick your specs or use the defaults, and train a model. Then download the model and processed data.

setInput(SAMPLE_PEPTIDES)} /> toggleDefaults(e.target.checked)} /> Use defaults } >
set('folds', Number(e.target.value))} />
{!canRun && !training && (

Add positive peptides and a species tax ID to train.

)}
{training ? (
Training model… computing features, sampling k-mer negatives, and running cross-validation.
) : result == null ? (
Train a model to see cross-validation metrics and per-fold results.
) : ( <>

{live ? 'Live training' : 'Offline preview'} {' '} {live ? 'Trained on the server: assign proteins, sample negatives, protein-grouped CV.' : 'Illustrative numbers; the training backend is not reachable.'}

{errorMsg && (

Backend could not train on this input: {errorMsg}

)}
{result.rocAuc.toFixed(3)}
Mean ROC-AUC ({cfg.folds}-fold CV)
{result.prAuc.toFixed(3)}
Mean PR-AUC
{result.nPositives}
Positives
{result.nNegatives}
Negatives (sampled)
{result.folds.map((f) => ( ))}
Fold ROC-AUC PR-AUC # train # test
Fold {f.fold} {f.rocAuc.toFixed(3)} {f.prAuc.toFixed(3)} {f.nTrain} {f.nTest}
{downloadUrl ? ( ) : ( )} {dataUrl && ( )}
{dataUrl && (

The processed dataset has one row per peptide (your detected peptides + sampled negatives) with its assigned protein, bioactivity / cytotoxicity / allergen screening, and the full feature matrix (physicochemical + PepBERT + ESM2 embeddings).

)} )}
) }