"use client"; import { useEffect, useState, useRef } from "react"; import { downloadTsv, exportSvgPng } from "@/lib/export-utils"; type StructureMatch = { pdb_id: string; chain: string; description: string; tm_score: number; rmsd: number; seq_identity: number; aligned_length: number; }; export function StructureComparison({ pdbId, chain = "A" }: { pdbId: string; chain?: string }) { const [matches, setMatches] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const svgRef = useRef(null); useEffect(() => { fetch(`/api/backend/api/structure_analysis/compare/${pdbId}?chain=${chain}`) .then(r => r.ok ? r.json() : r.json().then(d => { throw new Error(d.detail); })) .then(d => setMatches(d.matches)) .catch(e => setError(e.message)) .finally(() => setLoading(false)); }, [pdbId, chain]); if (loading) return
Searching structural homologs (PDBeFold)…
; if (error) return
{error}
; return (

Structural Homologs

{matches.length} hits · PDBeFold
TM-score (0→1) TM > 0.5 = same fold
{matches.map((m, i) => (
{m.pdb_id}:{m.chain}
0.5 ? "#00F5D4" : m.tm_score > 0.3 ? "#F59E0B" : "#EF4444", opacity: 0.7, }} />
{m.tm_score.toFixed(3)}
))}
{["PDB", "Chain", "RMSD", "Seq ID%", "Aligned", "Description"].map(h => ( ))} {matches.map((m, i) => ( ))}
{h}
{m.pdb_id} {m.chain} {m.rmsd.toFixed(2)}Å {(m.seq_identity * 100).toFixed(1)}% {m.aligned_length} aa {m.description}
); }