|
@@ -11,7 +11,6 @@ import { LigandEncoder } from '../ligand-encoder';
|
|
|
|
|
|
// specification: http://c4.cabrillo.edu/404/ctfile.pdf
|
|
|
// SDF wraps MOL and allows for multiple molecules per file as well as additional properties
|
|
|
-// TODO add support for stereo/chiral flags, add charges
|
|
|
export class MolEncoder extends LigandEncoder {
|
|
|
_writeCategory<Ctx>(category: Category<Ctx>, context?: Ctx) {
|
|
|
// use separate builder because we still need to write Counts and Bonds line
|
|
@@ -25,19 +24,25 @@ export class MolEncoder extends LigandEncoder {
|
|
|
// 3rd lines must be present and can contain comments
|
|
|
StringBuilder.writeSafe(this.builder, `${name}\n ${this.encoder}\n\n`);
|
|
|
|
|
|
- const bondMap = this.componentData.entries.get(name)!;
|
|
|
+ const atomMap = this.componentAtomData.entries.get(name)!;
|
|
|
+ const bondMap = this.componentBondData.entries.get(name)!;
|
|
|
let bondCount = 0;
|
|
|
+ let chiral = false;
|
|
|
|
|
|
// traverse once to determine all actually present atoms
|
|
|
const atoms = this.getAtoms(instance, source);
|
|
|
for (let i1 = 0, il = atoms.length; i1 < il; i1++) {
|
|
|
const atom = atoms[i1];
|
|
|
+ const { charge, stereo_config } = atomMap.map.get(atom.label_atom_id)!;
|
|
|
StringBuilder.writePadLeft(ctab, atom.Cartn_x.toFixed(4), 10);
|
|
|
StringBuilder.writePadLeft(ctab, atom.Cartn_y.toFixed(4), 10);
|
|
|
StringBuilder.writePadLeft(ctab, atom.Cartn_z.toFixed(4), 10);
|
|
|
StringBuilder.whitespace1(ctab);
|
|
|
StringBuilder.writePadRight(ctab, atom.type_symbol, 2);
|
|
|
- StringBuilder.writeSafe(ctab, ' 0 0 0 0 0 0 0 0 0 0 0 0\n');
|
|
|
+ StringBuilder.writeSafe(ctab, ' 0');
|
|
|
+ StringBuilder.writeIntegerPadLeft(ctab, this.mapCharge(charge), 3);
|
|
|
+ StringBuilder.writeSafe(ctab, ' 0 0 0 0 0 0 0 0 0 0\n');
|
|
|
+ if (stereo_config !== 'N') chiral = true;
|
|
|
|
|
|
bondMap.map.get(atom.label_atom_id)!.forEach((v, k) => {
|
|
|
const i2 = atoms.findIndex(e => e.label_atom_id === k);
|
|
@@ -56,7 +61,7 @@ export class MolEncoder extends LigandEncoder {
|
|
|
// write counts line
|
|
|
StringBuilder.writeIntegerPadLeft(this.builder, atoms.length, 3);
|
|
|
StringBuilder.writeIntegerPadLeft(this.builder, bondCount, 3);
|
|
|
- StringBuilder.writeSafe(this.builder, ' 0 0 0 0 0 0 0 0 0\n');
|
|
|
+ StringBuilder.writeSafe(this.builder, ` 0 0 ${chiral ? 1 : 0} 0 0 0 0 0 0\n`);
|
|
|
|
|
|
StringBuilder.writeSafe(this.builder, StringBuilder.getString(ctab));
|
|
|
StringBuilder.writeSafe(this.builder, StringBuilder.getString(bonds));
|
|
@@ -64,6 +69,19 @@ export class MolEncoder extends LigandEncoder {
|
|
|
StringBuilder.writeSafe(this.builder, 'M END\n');
|
|
|
}
|
|
|
|
|
|
+ private mapCharge(raw: number): number {
|
|
|
+ // 0 = uncharged or value other than these, 1 = +3, 2 = +2, 3 = +1, 4 = doublet radical, 5 = -1, 6 = -2, 7 = -3
|
|
|
+ switch (raw) {
|
|
|
+ case 3: return 1;
|
|
|
+ case 2: return 2;
|
|
|
+ case 1: return 3;
|
|
|
+ case -1: return 5;
|
|
|
+ case -2: return 6;
|
|
|
+ case -3: return 7;
|
|
|
+ default: return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
protected writeFullCategory<Ctx>(sb: StringBuilder, category: Category<Ctx>, context?: Ctx) {
|
|
|
const { instance, source } = getCategoryInstanceData(category, context);
|
|
|
const fields = instance.fields;
|