The raw SDF text as returned by PubChem's PUG-REST SDF operation
The parsed molecule, or undefined if the record has no usable atoms
const molecule = parseSdf(await getStructureSdf(962));
// { atoms: [{ symbol: 'O', x: 0, y: 0, z: 0 }, …], bonds: [{ from: 0, to: 1, order: 1 }, …],
// isPlanar: false }
parseSdf('not a molfile'); // undefined
export function parseSdf(text: string): Molecule | undefined {
const lines = text.split(/\r?\n/);
const countsLine = lines[COUNTS_LINE_INDEX];
if (countsLine === undefined) return undefined;
const atomCount = readIntField(countsLine, 0, 3);
const bondCount = readIntField(countsLine, 3, 6);
if (atomCount === undefined || atomCount <= 0) return undefined;
const atoms = parseAtomBlock(lines, atomCount);
if (atoms.length === 0) return undefined;
const bonds = parseBondBlock(lines, atomCount, bondCount ?? 0);
const firstZ = atoms[0].z;
const isPlanar = atoms.every((atom) => Math.abs(atom.z - firstZ) < PLANAR_EPSILON);
return { atoms, bonds, isPlanar };
}
Parses an MDL SDF / molfile V2000 record into atoms and bonds.
Only the counts line, atom block and bond block are read — charge, isotope and property lines after
M ENDare ignored, as none of them affect a ball-and-stick rendering. Malformed or empty records return undefined rather than throwing, so a caller can fall straight through to its next option.