Skip to content

Commit b3329ab

Browse files
committed
[fix.perception.rho.D8+] 1GRM offered its entire 300 KB mmCIF file as a ligand name
The ligand selector's first option on 1GRM was the whole deposited file — 300,821 characters — and it travelled from there into the ligand panel header and the properties cockpit header, so the app rendered a crystallographic file where a residue name belongs. The cause is not a bad label, it is an INVALID LOCATION. StructureProperties.residue.key came back undefined for that entry, and chain.auth_asym_id then returned the raw file. Every property read off that location is garbage rather than merely wrong. What the first attempt got wrong, and the reason it is written down: I guarded `comp`, and the result was "?undefined · <the whole file>" — the corruption simply moved to the next field. Guarding a symptom field by field chases it around the struct; asking whether the LOCATION is valid answers it once. A location that cannot yield a residue key is not addressing a residue, so the group does not enter the list at all. Verified: 1GRM now offers FVA · A:1 and FVA · B:1 (9 atoms each) and the cockpit reads MW 129 · LogP -0.0, and the deposited-ligand structures are unchanged.
1 parent c7e7cea commit b3329ab

1 file changed

Lines changed: 15 additions & 1 deletion

File tree

‎src/chemistry.backend.perception.rdkit-wasm.editable/semantic-focus.ts‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,27 @@ export function getLigandFocusTargets(structure: Structure): readonly LigandFocu
125125
location.unit = entry.unit;
126126
location.element = entry.unit.elements[unitIndex];
127127
const residueKey = StructureProperties.residue.key(location);
128+
// A location that cannot yield a residue key is not addressing a residue, and
129+
// every other property read off it is garbage rather than merely wrong.
130+
// Measured on 1GRM: residue.key came back undefined and chain.auth_asym_id
131+
// returned the ENTIRE 300,821-character mmCIF file, which travelled into the
132+
// ligand selector, the ligand panel header and the properties cockpit header.
133+
// The group is simply not a ligand residue and must not enter the list.
134+
//
135+
// Note what the first attempt got wrong: guarding `comp` produced
136+
// "?undefined · <the whole file>" — the corruption just moved to the next
137+
// field. Guarding a symptom field by field chases it; asking whether the
138+
// LOCATION is valid answers it once.
139+
if (typeof residueKey !== 'number' || !Number.isFinite(residueKey)) continue;
128140
const id = `${entry.unit.model.id}:${residueKey}`;
129141
let group = groups.get(id);
130142
if (!group) {
131143
const comp = StructureProperties.atom.label_comp_id(location);
132144
const chain = StructureProperties.chain.auth_asym_id(location) || StructureProperties.chain.label_asym_id(location);
133145
const seq = StructureProperties.residue.auth_seq_id(location);
134-
group = { label: `${comp} · ${chain || '—'}:${seq}`, units: new Map() };
146+
// Belt and braces behind the location check above.
147+
const safeComp = /^[A-Za-z0-9]{1,5}$/.test(comp) ? comp : `?${residueKey}`;
148+
group = { label: `${safeComp} · ${chain || '—'}:${seq}`, units: new Map() };
135149
groups.set(id, group);
136150
}
137151
let unit = group.units.get(entry.unit.id);

0 commit comments

Comments
 (0)