Browse Source

add Structure.atomicResidueCount & SerialMapping.getSerialIndex

Alexander Rose 5 years ago
parent
commit
74c8e512a7
1 changed files with 44 additions and 6 deletions
  1. 44 6
      src/mol-model/structure/structure/structure.ts

+ 44 - 6
src/mol-model/structure/structure/structure.ts

@@ -5,7 +5,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { IntMap, SortedArray, Iterator, Segmentation, Interval } from '../../../mol-data/int'
+import { IntMap, SortedArray, Iterator, Segmentation, Interval, OrderedSet } from '../../../mol-data/int'
 import { UniqueArray } from '../../../mol-data/generic'
 import { SymmetryOperator } from '../../../mol-math/geometry/symmetry-operator'
 import { Model, ElementIndex } from '../model'
@@ -59,6 +59,7 @@ class Structure {
         elementCount: number,
         bondCount: number,
         uniqueElementCount: number,
+        atomicResidueCount: number,
         polymerResidueCount: number,
         polymerUnitCount: number,
         coordinateSystem: SymmetryOperator,
@@ -71,6 +72,7 @@ class Structure {
         elementCount: -1,
         bondCount: -1,
         uniqueElementCount: -1,
+        atomicResidueCount: -1,
         polymerResidueCount: -1,
         polymerUnitCount: -1,
         coordinateSystem: SymmetryOperator.Default,
@@ -140,6 +142,13 @@ class Structure {
         return this._props.uniqueElementCount;
     }
 
+    get atomicResidueCount() {
+        if (this._props.atomicResidueCount === -1) {
+            this._props.atomicResidueCount = getAtomicResidueCount(this)
+        }
+        return this._props.atomicResidueCount;
+    }
+
     /** Coarse structure, defined as Containing less than twice as many elements as polymer residues */
     get isCoarse() {
         const ec = this.elementCount
@@ -253,7 +262,8 @@ class Structure {
     }
 
     get entityIndices() {
-        return this._props.entityIndices || (this._props.entityIndices = getEntityIndices(this));
+        return this._props.entityIndices
+            || (this._props.entityIndices = getEntityIndices(this));
     }
 
     get uniqueAtomicResidueIndices() {
@@ -470,16 +480,38 @@ function getPolymerUnitCount(structure: Structure): number {
     return polymerUnitCount
 }
 
+function getAtomicResidueCount(structure: Structure): number {
+    const { units } = structure
+    let atomicResidueCount = 0
+    for (let i = 0, _i = units.length; i < _i; i++) {
+        const unit = units[i]
+        if (!Unit.isAtomic(unit)) continue
+        const { elements, residueIndex } = unit
+        let idx = -1
+        let prevIdx = -1
+        for (let j = 0, jl = elements.length; j < jl; ++j) {
+            idx = residueIndex[elements[j]]
+            if (idx !== prevIdx) {
+                atomicResidueCount += 1
+                prevIdx = idx
+            }
+        }
+    }
+    return atomicResidueCount
+}
+
 interface SerialMapping {
-    /** Cumulative count of elements for each unit */
+    /** Cumulative count of preceding elements for each unit */
     cumulativeUnitElementCount: ArrayLike<number>
     /** Unit index for each serial element in the structure */
     unitIndices: ArrayLike<number>
     /** Element index for each serial element in the structure */
     elementIndices: ArrayLike<ElementIndex>
+    /** Get serial index of element in the structure */
+    getSerialIndex: (unit: Unit, element: ElementIndex) => Structure.SerialIndex
 }
 function getSerialMapping(structure: Structure): SerialMapping {
-    const { units, elementCount } = structure
+    const { units, elementCount, unitIndexMap } = structure
     const cumulativeUnitElementCount = new Uint32Array(units.length)
     const unitIndices = new Uint32Array(elementCount)
     const elementIndices = new Uint32Array(elementCount) as unknown as ElementIndex[]
@@ -493,7 +525,13 @@ function getSerialMapping(structure: Structure): SerialMapping {
         }
         m += elements.length
     }
-    return { cumulativeUnitElementCount, unitIndices, elementIndices }
+    return {
+        cumulativeUnitElementCount,
+        unitIndices,
+        elementIndices,
+
+        getSerialIndex: (unit, element) => cumulativeUnitElementCount[unitIndexMap.get(unit.id)] + OrderedSet.indexOf(unit.elements, element) as Structure.SerialIndex
+    }
 }
 
 namespace Structure {
@@ -776,7 +814,7 @@ namespace Structure {
         return hashString(s.units.map(u => Unit.conformationId(u)).join('|'))
     }
 
-    // TODO: there should be a version that property supports partitioned units
+    // TODO: there should be a version that properly supports partitioned units
     export function areUnitAndIndicesEqual(a: Structure, b: Structure) {
         if (a === b) return true;