Spaces:
Running
Running
| // Condition-aware model ranking (client-side mirror of backend/ranking.py). | |
| // | |
| // Given the conditions a user's peptides were generated under, species, enzyme, | |
| // MS protocol, rank the models by how similar their training conditions were. | |
| // Concise, generalizable rule: species dominates, then enzyme, then protocol, each | |
| // only when supplied and matched. Weighted score (species 100 > enzyme 10 > protocol | |
| // 1) so the order is exactly "same species first; among those same enzyme; among | |
| // those same protocol"; ties broken by the model's own AUROC. | |
| import { displayAurocValue, type RealModel } from '../data/models' | |
| export interface RankedModel extends RealModel { | |
| rankScore: number | |
| speciesMatch: boolean | |
| enzymeMatch: boolean | |
| protocolMatch: boolean | |
| } | |
| const norm = (x: string | null | undefined): string => (x ?? '').trim().toLowerCase() | |
| // Loose equality: exact, or one contains the other (handles "trypsin" vs "trypsin | |
| // then flavourzyme", "nano-LC-MS/MS" vs "LC-MS/MS"). | |
| function match(a: string, b: string): boolean { | |
| return !!a && !!b && (a === b || a.includes(b) || b.includes(a)) | |
| } | |
| export interface Conditions { | |
| species?: string | |
| enzyme?: string | |
| protocol?: string | |
| } | |
| export function rankModels(models: RealModel[], c: Conditions): RankedModel[] { | |
| const s = norm(c.species) | |
| const e = norm(c.enzyme) | |
| const p = norm(c.protocol) | |
| return models | |
| .map((m) => { | |
| const sp = match(s, norm(m.speciesKey) || norm(m.species)) | |
| const en = match(e, norm(m.enzyme)) | |
| const pr = match(p, norm(m.msProtocol)) | |
| return { | |
| ...m, | |
| rankScore: 100 * (sp ? 1 : 0) + 10 * (en ? 1 : 0) + 1 * (pr ? 1 : 0), | |
| speciesMatch: sp, | |
| enzymeMatch: en, | |
| protocolMatch: pr, | |
| } | |
| }) | |
| .sort( | |
| (a, b) => | |
| b.rankScore - a.rankScore || | |
| (displayAurocValue(b) ?? 0) - (displayAurocValue(a) ?? 0), | |
| ) | |
| } | |
| // Distinct, sorted option lists for the condition selectors (built from the models). | |
| export function distinctEnzymes(models: RealModel[]): string[] { | |
| return [...new Set(models.map((m) => m.enzyme).filter(Boolean))].sort() | |
| } | |
| export function distinctProtocols(models: RealModel[]): string[] { | |
| return [...new Set(models.map((m) => m.msProtocol).filter(Boolean))].sort() | |
| } | |
| export function distinctSpecies(models: RealModel[]): { key: string; label: string }[] { | |
| const seen = new Map<string, string>() | |
| for (const m of models) if (!seen.has(m.speciesKey)) seen.set(m.speciesKey, m.species) | |
| return [...seen.entries()] | |
| .map(([key, label]) => ({ key, label })) | |
| .sort((a, b) => a.label.localeCompare(b.label)) | |
| } | |