IgFold2D is a small, dependency-free JavaScript widget that renders a 2D proteomap of an Ig-fold domain — residues placed at canonical positions on a folded-lace grid indexed by the IgStrand universal numbering scheme (Tawfeeq et al., PLOS Comput Biol 2025).
This document is written for the iCn3D maintainer to evaluate integration. It covers what the widget needs as input, what existing iCn3D code already produces it, and three integration paths from lightest (no iCn3D change) to deepest (a new iCn3D panel).
Two JSON inputs plus optional source metadata:
{
"name": "IgV split A/A' (CD8-like)",
"rows": 36,
"cols": 14,
"left_cells": [ ... ], // grid cells: position, fill, borders, kind
"right_labels": [ ... ], // strand letters, sheet headers, CDR labels
"number_map": { "13,4": 6547, ... }, // (row,col) → IgStrand number
"chain": [ [25,1], [24,1], ..., null, ... ], // ordered cells along chain
"loop_hints": { ... } // optional waypoints for ambiguous loops
}
Templates are hand-crafted once per Ig variant (IgV, IgC1, IgC2, IgI, FN3, …) and shipped as JSON in templates/. The repo currently ships IgV-split-AAprime.json; more will come in v0.2.
[
{ "residue": "Q", "igstrand": 1544, "uniprot": 22, "pdb": 1 },
{ "residue": "F", "igstrand": 1545, "uniprot": 23, "pdb": 2 },
{ "residue": "R", "igstrand": 1546, "uniprot": 24, "pdb": 3 },
...
]
This is the piece iCn3D already produces — see icn3dnode/refnum.js:
node refnum.js [PDB or UniProt IDs]outputs a JSON file containing Ig domain detection, templates, and reference numbers.
The widget consumes a flat list of {residue, igstrand, uniprot, pdb} triplets per residue. A small adapter is all that’s needed to bridge refnum.js output to this format — see the assignment file for the expected shape.
{
"uniprot": { "id": "P01732", "version": 1, "url": "..." },
"pdb": { "id": "1CD8", "chain": "A", "url": "..." },
"alphafold": { "id": "AF-P01732-F1", "version": 4, "url": "..." }
}
When a user views an Ig domain in iCn3D, surface a link to the public widget:
// In iCn3D, somewhere in the structure-info panel:
const url = `https://vizomics.org/proteomaps?pdb=${pdbId}&chain=${chain}`;
panel.appendChild(makeLink('View 2D Proteomap', url));
The widget at vizomics.org/proteomaps would accept query params and load the appropriate assignment from a static cache (or, in v0.3, compute it live by calling refnum.js on the backend).
Pros: no iCn3D code change. Cons: leaves iCn3D context.
iCn3D adds a new dialog/tab “2D Proteomap” that loads the widget inline:
<div id="proteomap-panel"></div>
<script src="https://cdn.jsdelivr.net/gh/vizomics/igfold2d/src/igfold2d.js"></script>
<script>
// After iCn3D loads structure and computes IgStrand numbering with refnum:
IgFold2D.render({
container: '#proteomap-panel',
template: igfoldTemplate, // load from /templates/*.json
assignment: refnumOutput, // from refnum.js, transformed
sources: { uniprot: {...}, pdb: {...} }
});
</script>
The widget has no dependencies — no jQuery, no Three.js, no build step. It exposes a single global IgFold2D (also a CommonJS export) and renders pure SVG into a <div>. Total ~430 lines, ~13 KB minified.
Pros: tight integration; user stays in iCn3D. Cons: iCn3D needs to add a panel and the refnum→assignment adapter.
The richest integration: clicking a cell in 2D highlights the residue in 3D (and vice versa), so users navigate the structure through the proteomap.
// Listen to clicks in IgFold2D
proteomapContainer.addEventListener('cellclick', e => {
const cell = e.detail.cell;
if (cell.pdb && cell.pdb.pos) {
// Tell iCn3D to highlight this residue
icn3dui.icn3d.opts['selection'] = `chain ${cell.pdb.chain} resi ${cell.pdb.pos}`;
icn3dui.icn3d.draw();
}
});
// And the reverse: when iCn3D selects residues, highlight matching cells
icn3dui.on('selectionChange', selected => {
selected.forEach(resi => {
proteomapWidget.highlight(resi); // accepts UniProt #, PDB #, IgStrand #, or Excel
});
});
The widget API supports this natively. See docs/api.md for the full event reference.
For an MVP, Path B is the sweet spot — the iCn3D dev adds one panel, calls refnum.js (already there), passes the output through a small adapter to IgFold2D. Path C can come later by listening to existing iCn3D events.
The only piece of glue code:
// Adapter: transform refnum.js output to IgFold2D assignment format
function refnumToAssignment(refnumJson, chain) {
return refnumJson.domains[0].residues.map(r => ({
residue: r.aa, // single-letter amino acid
igstrand: r.igs, // IgStrand number
uniprot: r.uniprot_pos, // UniProt position
pdb: r.pdb_pos // PDB position
}));
}
The exact field names depend on the current refnum.js output JSON shape — happy to align on naming convention.
examples/browser-widget/index.html directly in a browser, no setupdocs/topology-rules.mddocs/igstrand-spec.mddocs/api.mdFeedback, issues, integration questions: open an issue at github.com/vizomics/igfold2d/issues or contact Philippe Youkharibache.