Browse Source

wip, seconadry structure export, updated sec. struct data model

David Sehnal 6 years ago
parent
commit
dc59cb88dc

+ 4 - 10
src/apps/structure-info/model.ts

@@ -13,8 +13,6 @@ import { Model, Structure, Element, Unit, Format, StructureProperties } from 'mo
 // import { Run, Progress } from 'mol-task'
 import { OrderedSet } from 'mol-data/int';
 import { openCif, downloadCif } from './helpers';
-import { BitFlags } from 'mol-util';
-import { SecondaryStructureType } from 'mol-model/structure/model/types';
 import { UnitRings } from 'mol-model/structure/structure/unit/rings';
 import { Vec3 } from 'mol-math/linear-algebra';
 
@@ -51,21 +49,17 @@ export function residueLabel(model: Model, rI: number) {
 export function printSecStructure(model: Model) {
     console.log('\nSecondary Structure\n=============');
     const { residues } = model.atomicHierarchy;
-    const { type, key } = model.properties.secondaryStructure;
+    const { index, elements } = model.properties.secondaryStructure;
 
     const count = residues._rowCount;
     let rI = 0;
     while (rI < count) {
         let start = rI;
-        while (rI < count && key[start] === key[rI]) rI++;
+        while (rI < count && index[start] === index[rI]) rI++;
         rI--;
 
-        if (BitFlags.has(type[start], SecondaryStructureType.Flag.Beta)) {
-            console.log(`Sheet: ${residueLabel(model, start)} - ${residueLabel(model, rI)} (key ${key[start]})`);
-        } else if (BitFlags.has(type[start], SecondaryStructureType.Flag.Helix)) {
-            console.log(`Helix: ${residueLabel(model, start)} - ${residueLabel(model, rI)} (key ${key[start]})`);
-        }
-
+        const e = elements[index[start]];
+        if (e.kind !== 'none') console.log(`${e.kind}: ${residueLabel(model, start)} - ${residueLabel(model, rI)}`);
         rI++;
     }
 }

+ 5 - 0
src/mol-model/structure/export/categories/secondary-structure.ts

@@ -0,0 +1,5 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */

+ 12 - 0
src/mol-model/structure/export/mmcif.ts

@@ -33,17 +33,29 @@ function _entity({ model, structure }: CifExportContext): CifCategory {
 }
 
 const Categories = [
+    // Basics
     copy_mmCif_category('entry'),
     copy_mmCif_category('exptl'),
     _entity,
+
+    // Symmetry
     copy_mmCif_category('cell'),
     copy_mmCif_category('symmetry'),
+
+    // Assemblies
     copy_mmCif_category('pdbx_struct_assembly'),
     copy_mmCif_category('pdbx_struct_assembly_gen'),
     copy_mmCif_category('pdbx_struct_oper_list'),
+
+    // Secondary structure
+    // TODO
+
+    // Misc
     // TODO: filter for actual present residues?
     copy_mmCif_category('chem_comp'),
     copy_mmCif_category('atom_sites'),
+
+    // Atoms
     _atom_site
 ];
 

+ 40 - 18
src/mol-model/structure/model/formats/mmcif/secondary-structure.ts

@@ -13,13 +13,15 @@ import { Column } from 'mol-data/db';
 
 export function getSecondaryStructureMmCif(data: mmCIF_Database, hierarchy: AtomicHierarchy): SecondaryStructure {
     const map: SecondaryStructureMap = new Map();
-    addHelices(data.struct_conf, map);
+    const elements: SecondaryStructure.Element[] = [{ kind: 'none' }];
+    addHelices(data.struct_conf, map, elements);
     // must add Helices 1st because of 'key' value assignment.
-    addSheets(data.struct_sheet_range, map, data.struct_conf._rowCount);
+    addSheets(data.struct_sheet_range, map, data.struct_conf._rowCount, elements);
 
     const secStruct: SecondaryStructureData = {
         type: new Int32Array(hierarchy.residues._rowCount) as any,
-        key: new Int32Array(hierarchy.residues._rowCount) as any
+        index: new Int32Array(hierarchy.residues._rowCount) as any,
+        elements
     };
 
     if (map.size > 0) assignSecondaryStructureRanges(hierarchy, map, secStruct);
@@ -32,34 +34,45 @@ type SecondaryStructureEntry = {
     endSeqNumber: number,
     endInsCode: string | null,
     type: SecondaryStructureType,
-    key: number
+    index: number
 }
 type SecondaryStructureMap = Map<string, Map<number, SecondaryStructureEntry>>
-type SecondaryStructureData = { type: SecondaryStructureType[], key: number[] }
+type SecondaryStructureData = { type: SecondaryStructureType[], index: number[], elements: SecondaryStructure.Element[]  }
 
-function addHelices(cat: mmCIF['struct_conf'], map: SecondaryStructureMap) {
+function addHelices(cat: mmCIF['struct_conf'], map: SecondaryStructureMap, elements: SecondaryStructure.Element[]) {
     if (!cat._rowCount) return;
 
     const { beg_label_asym_id, beg_label_seq_id, pdbx_beg_PDB_ins_code } = cat;
     const { end_label_seq_id, pdbx_end_PDB_ins_code } = cat;
-    const { pdbx_PDB_helix_class, conf_type_id } = cat;
+    const { pdbx_PDB_helix_class, conf_type_id, details } = cat;
 
     for (let i = 0, _i = cat._rowCount; i < _i; i++) {
-        const type =  pdbx_PDB_helix_class.valueKind(i) === Column.ValueKind.Present
+        const type =  SecondaryStructureType.create(pdbx_PDB_helix_class.valueKind(i) === Column.ValueKind.Present
             ? SecondaryStructureType.SecondaryStructurePdb[pdbx_PDB_helix_class.value(i)]
             : conf_type_id.valueKind(i) === Column.ValueKind.Present
             ? SecondaryStructureType.SecondaryStructureMmcif[conf_type_id.value(i)]
-            : SecondaryStructureType.Flag.NA
-
+            : SecondaryStructureType.Flag.NA);
+
+        const element: SecondaryStructure.Helix = {
+            kind: 'helix',
+            flags: type,
+            type_id: pdbx_PDB_helix_class.valueKind(i) === Column.ValueKind.Present
+                ? pdbx_PDB_helix_class.value(i) : conf_type_id.valueKind(i) === Column.ValueKind.Present
+                ? conf_type_id.value(i) : 'HELIX_P',
+            helix_class: pdbx_PDB_helix_class.value(i),
+            details: details.valueKind(i) === Column.ValueKind.Present ? details.value(i) : void 0
+        };
         const entry: SecondaryStructureEntry = {
             startSeqNumber: beg_label_seq_id.value(i),
             startInsCode: pdbx_beg_PDB_ins_code.value(i),
             endSeqNumber: end_label_seq_id.value(i),
             endInsCode: pdbx_end_PDB_ins_code.value(i),
-            type: SecondaryStructureType.create(type),
-            key: i + 1
+            type,
+            index: elements.length
         };
 
+        elements[elements.length] = element;
+
         const asymId = beg_label_asym_id.value(i)!;
         if (map.has(asymId)) {
             map.get(asymId)!.set(entry.startSeqNumber, entry);
@@ -69,7 +82,7 @@ function addHelices(cat: mmCIF['struct_conf'], map: SecondaryStructureMap) {
     }
 }
 
-function addSheets(cat: mmCIF['struct_sheet_range'], map: SecondaryStructureMap, sheetCount: number) {
+function addSheets(cat: mmCIF['struct_sheet_range'], map: SecondaryStructureMap, sheetCount: number, elements: SecondaryStructure.Element[]) {
     if (!cat._rowCount) return;
 
     const { beg_label_asym_id, beg_label_seq_id, pdbx_beg_PDB_ins_code } = cat;
@@ -88,15 +101,25 @@ function addSheets(cat: mmCIF['struct_sheet_range'], map: SecondaryStructureMap,
             sheet_id_key.set(id, key);
         }
 
+        const type = SecondaryStructureType.create(SecondaryStructureType.Flag.Beta | SecondaryStructureType.Flag.BetaSheet);
+        const element: SecondaryStructure.Sheet = {
+            kind: 'sheet',
+            flags: type,
+            sheet_id: id,
+            symmetry: void 0
+        }
         const entry: SecondaryStructureEntry = {
             startSeqNumber: beg_label_seq_id.value(i),
             startInsCode: pdbx_beg_PDB_ins_code.value(i),
             endSeqNumber: end_label_seq_id.value(i),
             endInsCode: pdbx_end_PDB_ins_code.value(i),
-            type: SecondaryStructureType.create(SecondaryStructureType.Flag.Beta | SecondaryStructureType.Flag.BetaSheet),
-            key
+            type,
+            index: elements.length
         };
 
+        elements[elements.length] = element;
+
+
         const asymId = beg_label_asym_id.value(i)!;
         if (map.has(asymId)) {
             map.get(asymId)!.set(entry.startSeqNumber, entry);
@@ -110,14 +133,13 @@ function addSheets(cat: mmCIF['struct_sheet_range'], map: SecondaryStructureMap,
 
 function assignSecondaryStructureEntry(hierarchy: AtomicHierarchy, entry: SecondaryStructureEntry, resStart: number, resEnd: number, data: SecondaryStructureData) {
     const { label_seq_id, pdbx_PDB_ins_code } = hierarchy.residues;
-    const { endSeqNumber, endInsCode, type, key } = entry;
+    const { endSeqNumber, endInsCode, index, type } = entry;
 
     let rI = resStart;
     while (rI < resEnd) {
         const seqNumber = label_seq_id.value(rI);
-
         data.type[rI] = type;
-        data.key[rI] = key;
+        data.index[rI] = index;
 
         if ((seqNumber > endSeqNumber) ||
             (seqNumber === endSeqNumber && pdbx_PDB_ins_code.value(rI) === endInsCode)) {

+ 28 - 3
src/mol-model/structure/model/properties/seconday-structure.ts

@@ -8,10 +8,35 @@ import { SecondaryStructureType } from '../types';
 
 /** Secondary structure "indexed" by residues. */
 interface SecondaryStructure {
-    // assign flags to each residue
     readonly type: ArrayLike<SecondaryStructureType>,
-    /** unique value for each "element". This is because single sheet is speficied by multiple records. */
-    readonly key: ArrayLike<number>
+
+    /** index into the elements array */
+    readonly index: ArrayLike<number>,
+    /** indexed by key */
+    readonly elements: ReadonlyArray<SecondaryStructure.Element>
+}
+
+namespace SecondaryStructure {
+    export type Element = None | Helix | Sheet
+
+    export interface None {
+        kind: 'none'
+    }
+
+    export interface Helix {
+        kind: 'helix',
+        flags: SecondaryStructureType,
+        type_id: string, // TODO: use aliased type?
+        helix_class: string,
+        details?: string
+    }
+
+    export interface Sheet {
+        kind: 'sheet',
+        flags: SecondaryStructureType,
+        sheet_id: string,
+        symmetry?: string
+    }
 }
 
 export { SecondaryStructure }

+ 1 - 1
src/mol-model/structure/structure/properties.ts

@@ -59,7 +59,7 @@ const residue = {
 
     // Properties
     secondary_structure_type: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.properties.secondaryStructure.type[l.unit.residueIndex[l.element]]),
-    secondary_structure_key: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.properties.secondaryStructure.key[l.unit.residueIndex[l.element]]),
+    secondary_structure_key: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.properties.secondaryStructure.index[l.unit.residueIndex[l.element]]),
 }
 
 const chain = {