Browse Source

add mol2 symmetry support

- only for spacegroup setting 1
Alexander Rose 3 years ago
parent
commit
22afdffa15

+ 2 - 1
CHANGELOG.md

@@ -6,8 +6,9 @@ Note that since we don't clearly distinguish between a public and private interf
 
 ## [Unreleased]
 
-- Add PDBj as a pdb-provider option
+- Add PDBj as a ``pdb-provider`` option
 - Move Viewer APP to a separate file to allow use without importing light theme & index.html
+- Add symmetry support for mol2 files (only spacegroup setting 1)
 
 ## [v3.0.0-dev.8] - 2021-12-31
 

+ 24 - 2
src/mol-io/reader/mol2/parser.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Zepei Xu <xuzepei19950617@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -259,6 +259,27 @@ async function handleBonds(state: State): Promise<Schema.Mol2Bonds> {
     return ret;
 }
 
+function handleCrysin(state: State) {
+    const { tokenizer } = state;
+
+    while (getTokenString(tokenizer) !== '@<TRIPOS>CRYSIN' && tokenizer.position < tokenizer.data.length) {
+        markLine(tokenizer);
+    }
+
+    markLine(tokenizer);
+    const l = getTokenString(tokenizer);
+    return {
+        a: parseFloat(l.substring(0, 10)),
+        b: parseFloat(l.substring(10, 20)),
+        c: parseFloat(l.substring(20, 30)),
+        alpha: parseFloat(l.substring(30, 40)),
+        beta: parseFloat(l.substring(40, 50)),
+        gamma: parseFloat(l.substring(50, 60)),
+        spaceGroup: parseInt(l.substring(60, 70), 10),
+        setting: parseInt(l.substring(70, 80), 10),
+    };
+}
+
 async function parseInternal(ctx: RuntimeContext, data: string, name: string): Promise<Result<Schema.Mol2File>> {
     const tokenizer = Tokenizer(data);
 
@@ -269,7 +290,8 @@ async function parseInternal(ctx: RuntimeContext, data: string, name: string): P
         handleMolecule(state);
         const atoms = await handleAtoms(state);
         const bonds = await handleBonds(state);
-        structures.push({ molecule: state.molecule, atoms, bonds });
+        const crysin = handleCrysin(state);
+        structures.push({ molecule: state.molecule, atoms, bonds, crysin });
         skipWhitespace(tokenizer);
         while (getTokenString(tokenizer) !== '@<TRIPOS>MOLECULE' && tokenizer.position < tokenizer.data.length) {
             markLine(tokenizer);

+ 14 - 1
src/mol-io/reader/mol2/schema.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -11,6 +11,7 @@ import { Column } from '../../../mol-data/db';
 // @<TRIPOS>MOLECULE
 // @<TRIPOS>ATOM
 // @<TRIPOS>BOND
+// @<TRIPOS>CRYSIN
 //
 // note that the format is not a fixed column format but white space separated
 
@@ -56,10 +57,22 @@ export interface Mol2Bonds {
     status_bits: Column<string>
 }
 
+export interface Mol2Crysin {
+    a: number
+    b: number
+    c: number
+    alpha: number
+    beta: number
+    gamma: number
+    spaceGroup: number
+    setting: number
+}
+
 export interface Mol2Structure {
     molecule: Readonly<Mol2Molecule>,
     atoms: Readonly<Mol2Atoms>,
     bonds: Readonly<Mol2Bonds>
+    crysin: Readonly<Mol2Crysin>
 }
 
 export interface Mol2File {

+ 28 - 4
src/mol-model-formats/structure/mol2.ts

@@ -1,11 +1,11 @@
 /**
- * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
 import { Column, Table } from '../../mol-data/db';
-import { Model } from '../../mol-model/structure/model';
+import { Model, Symmetry } from '../../mol-model/structure/model';
 import { BondType, MoleculeType } from '../../mol-model/structure/model/types';
 import { RuntimeContext, Task } from '../../mol-task';
 import { createModels } from './basic/parser';
@@ -14,16 +14,19 @@ import { ComponentBuilder } from './common/component';
 import { EntityBuilder } from './common/entity';
 import { ModelFormat } from '../format';
 import { IndexPairBonds } from './property/bonds/index-pair';
-import { Mol2File } from '../../mol-io/reader/mol2/schema';
+import { Mol2Crysin, Mol2File } from '../../mol-io/reader/mol2/schema';
 import { AtomPartialCharge } from './property/partial-charge';
 import { Trajectory, ArrayTrajectory } from '../../mol-model/structure';
 import { guessElementSymbolString } from './util';
+import { ModelSymmetry } from './property/symmetry';
+import { Spacegroup, SpacegroupCell } from '../../mol-math/geometry';
+import { Vec3 } from '../../mol-math/linear-algebra';
 
 async function getModels(mol2: Mol2File, ctx: RuntimeContext) {
     const models: Model[] = [];
 
     for (let i = 0, il = mol2.structures.length; i < il; ++i) {
-        const { atoms, bonds, molecule } = mol2.structures[i];
+        const { molecule, atoms, bonds, crysin } = mol2.structures[i];
 
         const A = Column.ofConst('A', atoms.count, Column.Schema.str);
 
@@ -110,6 +113,9 @@ async function getModels(mol2: Mol2File, ctx: RuntimeContext) {
                 type: molecule.charge_type
             });
 
+            const symmetry = getSymmetry(crysin);
+            if (symmetry) ModelSymmetry.Provider.set(first, symmetry);
+
             models.push(first);
         }
     }
@@ -117,6 +123,24 @@ async function getModels(mol2: Mol2File, ctx: RuntimeContext) {
     return new ArrayTrajectory(models);
 }
 
+function getSymmetry(crysin: Mol2Crysin): Symmetry | undefined {
+    // TODO handle `crysin.setting`
+    if (crysin.setting !== 1) return;
+
+    const spaceCell = SpacegroupCell.create(
+        crysin.spaceGroup,
+        Vec3.create(crysin.a, crysin.b, crysin.c),
+        Vec3.scale(Vec3(), Vec3.create(crysin.alpha, crysin.beta, crysin.gamma), Math.PI / 180)
+    );
+
+    return {
+        spacegroup: Spacegroup.create(spaceCell),
+        assemblies: [],
+        isNonStandardCrystalFrame: false,
+        ncsOperators: []
+    };
+}
+
 //
 
 export { Mol2Format };