An alignment linked to its structure
The spike and
hemoglobin tutorials each
end on a residueMappings layer, which records the structure
residue for each residue of one row. Below, each alignment sits over its PDB
entry in Mol*. A residue hovered in either view lights in the other, and the
line under the structure reports what each lookup returned.
What to hover
The spike set opens on the PRRA insert. Hover the SARS-CoV-2 row: each residue from 14 to 1211 reaches chain A of 6VXX at its position plus 19. Residues 681 to 684 report no coordinates, because 6VXX declares structure residues 696 to 707 in its sequence and resolved none of them. Press HR1 and hover row residues 920 to 970: each one lights on chain A, structure residues 939 to 989. Click a cell to turn the camera to that residue, and click a residue in the structure to scroll the alignment to its column.
The hemoglobin set holds one row per species, alpha and beta concatenated. On the Human row, alpha columns reach chain A of 2HHB and beta columns reach chain B. Residues 1 and 143 are the initiator methionines, which the mature chains lack, and report outside the mapped region. The arc track above the alignment joins the residue pairs in contact between the chains.
The built-in control
Each mapping names one row and one chain. Chains B and C of 6VXX are copies of chain A, and chains C and D of 2HHB are copies of A and B, but no mapping names them. A hover on any of them, or on a glycan, heme or water, reports no row maps here and lights nothing in the alignment. The other rows of each alignment report no mapping onto 6VXX or onto 2HHB.
The viewer also checks each mapping against the loaded row and ignores one computed against a different sequence. This page prints each ignored mapping under the status line, and both sets print none.
Color the structure
The Color the structure by menu paints each residue of a mapped chain with a color read from the alignment column it falls in. A residue with no column is grey: the chains no mapping names, the residues outside a mapped region, and a residue in a column that Hide columns has hidden.
- Column conservation uses the number the Conservation track draws, in five blue steps from variable to conserved.
- Alignment colors uses whichever scheme the Alignment colors menu picks. Choose Hydrophobicity or Buried index and the structure shows where the hydrophobic residues sit: a hydrophobic residue on the surface or a polar one inside the core stands out in a way the sequence alone does not show. BLOSUM62 similarity shades each residue by how like its column it is, so a substitution that the family rarely makes shows as a pale patch.
Both modes count the rows on screen. Collapse a clade in the tree, or show
one subtree, and the page repaints the structure from the rows left. The
page walks each residue of the structure through
rowResidue to its row residue, then asks
schemeResidueColor(model) for the hex color the scheme gives
that residue, or reads model.conservation at the column from
seqPosToVisibleCol.
Put it on your own page
The two bridges are one call each way. structureResidue
takes a row and a 1-based residue and returns the structure residue as a
label_seq_id, with its chain and whether it has coordinates.
rowResidue takes a structure residue and its chain and returns
the row and residue, which applyHighlight
draws. Both return undefined where no mapping covers the
residue. model comes from onModel, and
plugin is the Mol* plugin with the structure loaded:
import { MSAViewer } from 'react-msaview'
import {
StructureElement,
StructureProperties,
StructureSelection,
} from 'molstar/lib/mol-model/structure'
import { Script } from 'molstar/lib/mol-script/script'
function residueLoci(structure, labelSeqId, asymId) {
const selection = Script.getStructureSelection(
Q =>
Q.struct.generator.atomGroups({
'chain-test': Q.core.rel.eq([
Q.struct.atomProperty.macromolecular.label_asym_id(),
asymId,
]),
'residue-test': Q.core.rel.eq([
Q.struct.atomProperty.macromolecular.label_seq_id(),
labelSeqId,
]),
}),
structure,
)
return StructureSelection.toLociWithSourceUnits(selection)
}
function onCellHover(cell) {
const hit = cell?.residue && model.structureResidue(cell.row, cell.residue, '6VXX')
const structure =
plugin.managers.structure.hierarchy.current.structures[0]?.cell.obj?.data
const { lociHighlights } = plugin.managers.interactivity
if (hit && structure) {
const loci = residueLoci(structure, hit.position, hit.structure.asymId)
lociHighlights.highlightOnly({ loci }, false)
} else {
lociHighlights.clearHighlights()
}
}
plugin.behaviors.interaction.hover.subscribe(({ current }) => {
const loc = StructureElement.Loci.is(current.loci)
? StructureElement.Loci.getFirstLocation(current.loci)
: undefined
const hit =
loc &&
model.rowResidue(
'6VXX',
StructureProperties.residue.label_seq_id(loc),
StructureProperties.chain.label_asym_id(loc),
)
if (hit) {
model.applyHighlight('structure', [
{ row: hit.rowName, start: hit.seqPos, end: hit.seqPos },
])
} else {
model.clearHighlight('structure')
}
})
<MSAViewer
msaFilehandle={{ uri: 'spike.afa', locationType: 'UriLocation' }}
residueMappings={layers.residueMappings}
onModel={m => {
model = m
}}
onCellHover={onCellHover}
/>
The page loads these files, all served with
Access-Control-Allow-Origin:
- https://gmod.org/JBrowseMSA/demo/data/spike/spike.afa
- https://gmod.org/JBrowseMSA/demo/data/spike/spike.nwk
- https://gmod.org/JBrowseMSA/demo/data/spike/spike-domains.gff
- https://gmod.org/JBrowseMSA/demo/data/spike/spike-layers.json
- https://files.rcsb.org/download/6VXX.cif
- https://gmod.org/JBrowseMSA/demo/data/hemoglobin/hemoglobin.afa
- https://gmod.org/JBrowseMSA/demo/data/hemoglobin/hemoglobin.nwk
- https://gmod.org/JBrowseMSA/demo/data/hemoglobin/hemoglobin-subunits.gff
- https://gmod.org/JBrowseMSA/demo/data/hemoglobin/hemoglobin-layers.json
- https://files.rcsb.org/download/2HHB.cif