Преглед на файлове

FTR: Add formal charges during model creation

This implementation takes into account both the property and atom block
cases and makes sure the latter is ignored if the first one is present.
ptourlas преди 3 години
родител
ревизия
cb76b53a1b
променени са 2 файла, в които са добавени 69 реда и са изтрити 7 реда
  1. 39 4
      src/mol-io/reader/mol/parser.ts
  2. 30 3
      src/mol-model-formats/structure/mol.ts

+ 39 - 4
src/mol-io/reader/mol/parser.ts

@@ -63,6 +63,45 @@ export interface MolFile {
     nnn         (INVERSION/RETENTION FLAG, 63-66)
     eee         (EXACT CHANGE FLAG, 66-69)
 */
+
+/**
+ * @param key - The value found at the atom block.
+ * @returns The actual formal charge based on the mapping.
+ */
+export function formalChargeMapper(key: string) {
+    let chg = 0;
+    switch (key) {
+        case '7':
+            chg = -3;
+            break;
+        case '6':
+            chg = -2;
+            break;
+        case '5':
+            chg = -1;
+            break;
+        case '0':
+            chg = 0;
+            break;
+        case '3':
+            chg = 1;
+            break;
+        case '2':
+            chg = 2;
+            break;
+        case '1':
+            chg = 3;
+            break;
+        case '4':
+            chg = 0;
+            break;
+        default:
+            console.error(`Value to be mapped is outside the 0-7 range!`);
+            break;
+    }
+    return chg;
+}
+
 export function handleAtoms(tokenizer: Tokenizer, count: number): MolFile['atoms'] {
     const x = TokenBuilder.create(tokenizer.data, count * 2);
     const y = TokenBuilder.create(tokenizer.data, count * 2);
@@ -147,12 +186,8 @@ export function handleFormalCharges(tokenizer: Tokenizer, lineStart: number): Mo
 
         Tokenizer.trim(tokenizer, lineStart + offset, lineStart + offset + 4);
         TokenBuilder.addUnchecked(atomIdx, tokenizer.tokenStart, tokenizer.tokenEnd);
-        console.log('id', Tokenizer.getTokenString(tokenizer));
-
         Tokenizer.trim(tokenizer, lineStart + offset + 4, lineStart + offset + 8);
         TokenBuilder.addUnchecked(charge, tokenizer.tokenStart, tokenizer.tokenEnd);
-        console.log('chg', Tokenizer.getTokenString(tokenizer));
-
     }
 
     /*

+ 30 - 3
src/mol-model-formats/structure/mol.ts

@@ -7,7 +7,7 @@
  */
 
 import { Column, Table } from '../../mol-data/db';
-import { MolFile } from '../../mol-io/reader/mol/parser';
+import { MolFile, formalChargeMapper } from '../../mol-io/reader/mol/parser';
 import { MoleculeType } from '../../mol-model/structure/model/types';
 import { RuntimeContext, Task } from '../../mol-task';
 import { createModels } from './basic/parser';
@@ -19,13 +19,40 @@ import { IndexPairBonds } from './property/bonds/index-pair';
 import { Trajectory } from '../../mol-model/structure';
 
 export async function getMolModels(mol: MolFile, format: ModelFormat<any> | undefined, ctx: RuntimeContext) {
-    const { atoms, bonds } = mol;
+    const { atoms, bonds, formalCharges } = mol;
 
     const MOL = Column.ofConst('MOL', mol.atoms.count, Column.Schema.str);
     const A = Column.ofConst('A', mol.atoms.count, Column.Schema.str);
     const type_symbol = Column.asArrayColumn(atoms.type_symbol);
     const seq_id = Column.ofConst(1, atoms.count, Column.Schema.int);
 
+    const computedFormalCharges: Column<number> = Column.ofLambda({
+        value: (row: number) => {
+            if (formalCharges) {
+                const numOfCharges = formalCharges.atomIdx.rowCount;
+                /*
+                    Scan the list of formal charges from the properties
+                    block. If one of them has an atom index that matches the
+                    current row return the corresponding charge.
+                */
+                for (let i = 0; i < numOfCharges; i++) {
+                    if ((formalCharges.atomIdx.value(i) - 1) === row) {
+                        return formalCharges.charge.value(i);
+                    }
+                }
+                /*
+                    If the M CHG property is present, every charge in the atom
+                    block is treated as zero.
+                */
+                return 0;
+            }
+            const idx = atoms.formal_charge.value(row).toString();
+            return formalChargeMapper(idx);
+        },
+        rowCount: atoms.formal_charge.rowCount,
+        schema: atoms.formal_charge.schema,
+    });
+
     const atom_site = Table.ofPartialColumns(BasicSchema.atom_site, {
         auth_asym_id: A,
         auth_atom_id: type_symbol,
@@ -46,7 +73,7 @@ export async function getMolModels(mol: MolFile, format: ModelFormat<any> | unde
         type_symbol,
 
         pdbx_PDB_model_num: Column.ofConst(1, atoms.count, Column.Schema.int),
-        pdbx_formal_charge: Column.asArrayColumn(atoms.formal_charge)
+        pdbx_formal_charge: computedFormalCharges
     }, atoms.count);
 
     const entityBuilder = new EntityBuilder();