Ver Fonte

propagate atoms only if present

JonStargaryen há 4 anos atrás
pai
commit
9043e4c8e1
2 ficheiros alterados com 45 adições e 34 exclusões
  1. 1 1
      src/mol-io/writer/sdf.ts
  2. 44 33
      src/mol-io/writer/sdf/encoder.ts

+ 1 - 1
src/mol-io/writer/sdf.ts

@@ -17,7 +17,7 @@ export namespace SdfWriter {
     }
 
     export function createEncoder(params?: EncoderParams): Encoder {
-        const { encoderName = 'mol*', metaInformation = false, hydrogens = true } = params || {};
+        const { encoderName = 'mol*', metaInformation = false, hydrogens = false } = params || {};
         return new SdfEncoder(encoderName, metaInformation, hydrogens);
     }
 }

+ 44 - 33
src/mol-io/writer/sdf/encoder.ts

@@ -17,6 +17,8 @@ export class SdfEncoder implements Encoder<string> {
     private encoded = false;
     private error = false;
     private componentData: ComponentBond;
+    readonly isBinary = false;
+    binaryEncodingProvider = void 0;
 
     setComponentBondData(componentData: ComponentBond) {
         this.componentData = componentData;
@@ -74,7 +76,6 @@ export class SdfEncoder implements Encoder<string> {
         const fields = this.getSortedFields(instance);
         const label_atom_id = this.getField(instance, 'label_atom_id');
         const label_comp_id = this.getField(instance, 'label_comp_id');
-        const fieldCount = fields.length;
 
         // write header
         const name = label_comp_id.value(source[0].keys().move(), source[0].data, 0) as string;
@@ -83,7 +84,43 @@ export class SdfEncoder implements Encoder<string> {
         const bondMap = this.componentData.entries.get(name)!;
         let bondCount = 0;
 
+        // traverse once to determine all actually present atoms
+        const atoms = this.getAtoms(source, fields, label_atom_id, ctab);
+
+        atoms.forEach((av, ak) => {
+            const { id } = this.split(ak);
+            bondMap.map.get(ak)!.forEach((bv, bk) => {
+                const { id: partnerId, label: partnerLabel } = this.split(bk);
+                if (id <= partnerId && atoms.has(bk) && !this.skipHydrogen(partnerLabel)) {
+                    const { order } = bv;
+                    StringBuilder.writeIntegerPadLeft(bonds, id, 3);
+                    StringBuilder.writeIntegerPadLeft(bonds, partnerId, 3);
+                    StringBuilder.writeIntegerPadLeft(bonds, order, 3);
+                    StringBuilder.writeSafe(bonds, '  0  0  0  0\n'); 
+                    // TODO 2nd value: Single bonds: 0 = not stereo, 1 = Up, 4 = Either, 6 = Down, 
+                    // Double bonds: 0 = Use x-, y-, z-coords from atom block to determine cis or trans, 3 = Cis or trans (either) double bond
+                    bondCount++;
+                }
+            });
+        });
+
+        // write counts line
+        // 'Important specifications here relate to the number of atoms, bonds, and atom lists, the chiral flag setting, and the Ctab version.'
+        StringBuilder.writeIntegerPadLeft(this.builder, rowCount, 3);
+        StringBuilder.writeIntegerPadLeft(this.builder, bondCount, 3);
+        StringBuilder.write(this.builder, '  0     0  0  0  0  0  0999 V2000\n'); // TODO 2nd value: chiral flag: 0=not chiral, 1=chiral 
+
+        StringBuilder.writeSafe(this.builder, StringBuilder.getString(ctab));
+        StringBuilder.writeSafe(this.builder, StringBuilder.getString(bonds));
+        StringBuilder.writeSafe(this.builder, StringBuilder.getString(charges)); // TODO charges
+        
+        StringBuilder.writeSafe(this.builder, 'M  END\n');
+    }
+
+    private getAtoms(source: any, fields: Field<any, any>[], label_atom_id: Field<any, any>, ctab: StringBuilder): Map<string, { id: number, label: string }> {
+        const atoms = new Map<string, any>();
         let index = 0;
+
         for (let _c = 0; _c < source.length; _c++) {
             const src = source[_c];
             const data = src.data;
@@ -93,50 +130,27 @@ export class SdfEncoder implements Encoder<string> {
             const it = src.keys();
             while (it.hasNext)  {
                 const key = it.move();
-                for (let _f = 0; _f < fieldCount; _f++) {
+                for (let _f = 0, _fl = fields.length; _f < _fl; _f++) {
                     const f: Field<any, any> = fields[_f]!;
                     const val = f.value(key, data, index);
                     if (f.name === 'type_symbol') {
-                        const lai = label_atom_id.value(key, data, index) as string;
-                        const { id, label } = this.split(lai);
+                        const val = label_atom_id.value(key, data, index) as string;
+                        const lai = this.split(val);
+                        const { label } = lai;
                         if (this.skipHydrogen(label)) {
                             continue;
                         }
-
-                        bondMap.map.get(lai)!.forEach((v, k) => {
-                            const { id: partnerId, label: partnerLabel } = this.split(k);
-                            if (id <= partnerId && !this.skipHydrogen(partnerLabel)) {
-                                const { order } = v;
-                                StringBuilder.writeIntegerPadLeft(bonds, id, 3);
-                                StringBuilder.writeIntegerPadLeft(bonds, partnerId, 3);
-                                StringBuilder.writeIntegerPadLeft(bonds, order, 3);
-                                StringBuilder.writeSafe(bonds, '  0  0  0  0\n'); 
-                                // TODO 2nd value: Single bonds: 0 = not stereo, 1 = Up, 4 = Either, 6 = Down, 
-                                // Double bonds: 0 = Use x-, y-, z-coords from atom block to determine cis or trans, 3 = Cis or trans (either) double bond
-                                bondCount++;
-                            }
-                        });
+                        atoms.set(val, lai);
                     }
                     this.writeValue(ctab, val, f.type);
                 }
                 
                 StringBuilder.writeSafe(ctab, '  0  0  0  0  0  0  0  0  0  0  0  0\n');
-
                 index++;
             }
         }
 
-        // write counts line
-        // 'Important specifications here relate to the number of atoms, bonds, and atom lists, the chiral flag setting, and the Ctab version.'
-        StringBuilder.writeIntegerPadLeft(this.builder, rowCount, 3);
-        StringBuilder.writeIntegerPadLeft(this.builder, bondCount, 3);
-        StringBuilder.write(this.builder, '  0     0  0  0  0  0  0999 V2000\n'); // TODO 2nd value: chiral flag: 0=not chiral, 1=chiral 
-
-        StringBuilder.writeSafe(this.builder, StringBuilder.getString(ctab));
-        StringBuilder.writeSafe(this.builder, StringBuilder.getString(bonds));
-        StringBuilder.writeSafe(this.builder, StringBuilder.getString(charges)); // TODO charges
-        
-        StringBuilder.writeSafe(this.builder, 'M  END\n');
+        return atoms;
     }
 
     private skipHydrogen(label: string) {
@@ -193,9 +207,6 @@ export class SdfEncoder implements Encoder<string> {
         return instance.fields.find(f => f.name === name)!;
     }
 
-    readonly isBinary = false;
-    binaryEncodingProvider = void 0;
-
     encode() {
         // write meta-information, do so after ctab
         if (this.error || this.metaInformation) {