Browse Source

mol-model: added chainGroupId

David Sehnal 5 years ago
parent
commit
b2d2546e39

+ 18 - 2
src/mol-model/structure/structure/structure.ts

@@ -540,7 +540,8 @@ namespace Structure {
             for (let j = 0, jl = structure.units.length; j < jl; ++j) {
                 const u = structure.units[j]
                 const invariantId = u.invariantId + count
-                const newUnit = Unit.create(units.length, invariantId, u.kind, u.model, u.conformation.operator, u.elements)
+                const chainGroupId = u.chainGroupId + count
+                const newUnit = Unit.create(units.length, invariantId, chainGroupId, u.kind, u.model, u.conformation.operator, u.elements)
                 units.push(newUnit)
             }
             count = units.length
@@ -644,6 +645,7 @@ namespace Structure {
         const lookup = GridLookup3D({ x, y, z, indices: SortedArray.ofSortedArray(startIndices) }, gridCellCount);
         const { offset, count, array } = lookup.buckets;
 
+        builder.beginChainGroup();
         for (let i = 0, _i = offset.length; i < _i; i++) {
             const start = offset[i];
             const set: number[] = [];
@@ -655,6 +657,7 @@ namespace Structure {
             }
             builder.addUnit(Unit.Kind.Atomic, model, SymmetryOperator.Default, SortedArray.ofSortedArray(new Int32Array(set)));
         }
+        builder.endChainGroup();
     }
 
     function addCoarseUnits(builder: StructureBuilder, model: Model, elements: CoarseElements, kind: Unit.Kind) {
@@ -685,9 +688,22 @@ namespace Structure {
         private units: Unit[] = [];
         private invariantId = idFactory()
 
+        private chainGroupId = -1;
+        private inChainGroup = false;
+
+        beginChainGroup() {
+            this.chainGroupId++;
+            this.inChainGroup = true;
+        }
+
+        endChainGroup() {
+            this.inChainGroup = false;
+        }
+
         addUnit(kind: Unit.Kind, model: Model, operator: SymmetryOperator, elements: StructureElement.Set, invariantId?: number): Unit {
             if (invariantId === undefined) invariantId = this.invariantId()
-            const unit = Unit.create(this.units.length, invariantId, kind, model, operator, elements);
+            const chainGroupId = this.inChainGroup ? this.chainGroupId : ++this.chainGroupId;
+            const unit = Unit.create(this.units.length, invariantId, chainGroupId, kind, model, operator, elements);
             this.units.push(unit);
             return unit;
         }

+ 18 - 12
src/mol-model/structure/structure/unit.ts

@@ -33,11 +33,11 @@ namespace Unit {
     export function isSpheres(u: Unit): u is Spheres { return u.kind === Kind.Spheres; }
     export function isGaussians(u: Unit): u is Gaussians { return u.kind === Kind.Gaussians; }
 
-    export function create(id: number, invariantId: number, kind: Kind, model: Model, operator: SymmetryOperator, elements: StructureElement.Set): Unit {
+    export function create(id: number, invariantId: number, chainGroupId: number, kind: Kind, model: Model, operator: SymmetryOperator, elements: StructureElement.Set): Unit {
         switch (kind) {
-            case Kind.Atomic: return new Atomic(id, invariantId, model, elements, SymmetryOperator.createMapping(operator, model.atomicConformation, void 0), AtomicProperties());
-            case Kind.Spheres: return createCoarse(id, invariantId, model, Kind.Spheres, elements, SymmetryOperator.createMapping(operator, model.coarseConformation.spheres, getSphereRadiusFunc(model)), CoarseProperties());
-            case Kind.Gaussians: return createCoarse(id, invariantId, model, Kind.Gaussians, elements, SymmetryOperator.createMapping(operator, model.coarseConformation.gaussians, getGaussianRadiusFunc(model)), CoarseProperties());
+            case Kind.Atomic: return new Atomic(id, invariantId, chainGroupId, model, elements, SymmetryOperator.createMapping(operator, model.atomicConformation, void 0), AtomicProperties());
+            case Kind.Spheres: return createCoarse(id, invariantId, chainGroupId, model, Kind.Spheres, elements, SymmetryOperator.createMapping(operator, model.coarseConformation.spheres, getSphereRadiusFunc(model)), CoarseProperties());
+            case Kind.Gaussians: return createCoarse(id, invariantId, chainGroupId, model, Kind.Gaussians, elements, SymmetryOperator.createMapping(operator, model.coarseConformation.gaussians, getGaussianRadiusFunc(model)), CoarseProperties());
         }
     }
 
@@ -98,6 +98,7 @@ namespace Unit {
         readonly id: number,
         /** invariant ID stays the same even if the Operator/conformation changes. */
         readonly invariantId: number,
+        readonly chainGroupId: number,
         readonly elements: StructureElement.Set,
         readonly model: Model,
         readonly conformation: SymmetryOperator.ArrayMapping<ElementIndex>,
@@ -139,6 +140,8 @@ namespace Unit {
 
         readonly id: number;
         readonly invariantId: number;
+        /** Used to identify a single chain split into multiple units. */
+        readonly chainGroupId: number;
         readonly elements: StructureElement.Set;
         readonly model: Model;
         readonly conformation: SymmetryOperator.ArrayMapping<ElementIndex>;
@@ -152,12 +155,12 @@ namespace Unit {
 
         getChild(elements: StructureElement.Set): Unit {
             if (elements.length === this.elements.length) return this;
-            return new Atomic(this.id, this.invariantId, this.model, elements, this.conformation, AtomicProperties());
+            return new Atomic(this.id, this.invariantId, this.chainGroupId, this.model, elements, this.conformation, AtomicProperties());
         }
 
         applyOperator(id: number, operator: SymmetryOperator, dontCompose = false): Unit {
             const op = dontCompose ? operator : SymmetryOperator.compose(this.conformation.operator, operator);
-            return new Atomic(id, this.invariantId, this.model, this.elements, SymmetryOperator.createMapping(op, this.model.atomicConformation, this.conformation.r), this.props);
+            return new Atomic(id, this.invariantId, this.chainGroupId, this.model, this.elements, SymmetryOperator.createMapping(op, this.model.atomicConformation, this.conformation.r), this.props);
         }
 
         get lookup3d() {
@@ -221,9 +224,10 @@ namespace Unit {
             return this.model.atomicHierarchy.residueAtomSegments.index[this.elements[elementIndex]];
         }
 
-        constructor(id: number, invariantId: number, model: Model, elements: StructureElement.Set, conformation: SymmetryOperator.ArrayMapping<ElementIndex>, props: AtomicProperties) {
+        constructor(id: number, invariantId: number, chainGroupId: number, model: Model, elements: StructureElement.Set, conformation: SymmetryOperator.ArrayMapping<ElementIndex>, props: AtomicProperties) {
             this.id = id;
             this.invariantId = invariantId;
+            this.chainGroupId = chainGroupId;
             this.model = model;
             this.elements = elements;
             this.conformation = conformation;
@@ -264,6 +268,7 @@ namespace Unit {
 
         readonly id: number;
         readonly invariantId: number;
+        readonly chainGroupId: number;
         readonly elements: StructureElement.Set;
         readonly model: Model;
         readonly conformation: SymmetryOperator.ArrayMapping<ElementIndex>;
@@ -275,12 +280,12 @@ namespace Unit {
 
         getChild(elements: StructureElement.Set): Unit {
             if (elements.length === this.elements.length) return this as any as Unit /** lets call this an ugly temporary hack */;
-            return createCoarse(this.id, this.invariantId, this.model, this.kind, elements, this.conformation, CoarseProperties());
+            return createCoarse(this.id, this.invariantId, this.chainGroupId, this.model, this.kind, elements, this.conformation, CoarseProperties());
         }
 
         applyOperator(id: number, operator: SymmetryOperator, dontCompose = false): Unit {
             const op = dontCompose ? operator : SymmetryOperator.compose(this.conformation.operator, operator);
-            const ret = createCoarse(id, this.invariantId, this.model, this.kind, this.elements, SymmetryOperator.createMapping(op, this.getCoarseConformation(), this.conformation.r), this.props);
+            const ret = createCoarse(id, this.invariantId, this.chainGroupId, this.model, this.kind, this.elements, SymmetryOperator.createMapping(op, this.getCoarseConformation(), this.conformation.r), this.props);
             // (ret as Coarse<K, C>)._lookup3d = this._lookup3d;
             return ret;
         }
@@ -309,11 +314,12 @@ namespace Unit {
             return this.kind === Kind.Spheres ? this.model.coarseConformation.spheres : this.model.coarseConformation.gaussians;
         }
 
-        constructor(id: number, invariantId: number, model: Model, kind: K, elements: StructureElement.Set, conformation: SymmetryOperator.ArrayMapping<ElementIndex>, props: CoarseProperties) {
+        constructor(id: number, invariantId: number, chainGroupId: number, model: Model, kind: K, elements: StructureElement.Set, conformation: SymmetryOperator.ArrayMapping<ElementIndex>, props: CoarseProperties) {
             this.kind = kind;
             this.objectPrimitive = kind === Kind.Spheres ? 'sphere' : 'gaussian'
             this.id = id;
             this.invariantId = invariantId;
+            this.chainGroupId = chainGroupId;
             this.model = model;
             this.elements = elements;
             this.conformation = conformation;
@@ -337,8 +343,8 @@ namespace Unit {
         };
     }
 
-    function createCoarse<K extends Kind.Gaussians | Kind.Spheres>(id: number, invariantId: number, model: Model, kind: K, elements: StructureElement.Set, conformation: SymmetryOperator.ArrayMapping<ElementIndex>, props: CoarseProperties): Unit {
-        return new Coarse(id, invariantId, model, kind, elements, conformation, props) as any as Unit /** lets call this an ugly temporary hack */;
+    function createCoarse<K extends Kind.Gaussians | Kind.Spheres>(id: number, invariantId: number, chainGroupId: number, model: Model, kind: K, elements: StructureElement.Set, conformation: SymmetryOperator.ArrayMapping<ElementIndex>, props: CoarseProperties): Unit {
+        return new Coarse(id, invariantId, chainGroupId, model, kind, elements, conformation, props) as any as Unit /** lets call this an ugly temporary hack */;
     }
 
     export class Spheres extends Coarse<Kind.Spheres, CoarseSphereConformation> { }