Ver Fonte

mol-model: added parent & coordinate system to Structure

David Sehnal há 6 anos atrás
pai
commit
57f5779531

+ 1 - 1
src/mol-model/structure/query/queries/filters.ts

@@ -38,7 +38,7 @@ export function first(query: StructureQuery): StructureQuery {
         if (sel.kind === 'singletons') {
             if (sel.structure.elementCount > 0) {
                 const u = sel.structure.units[0];
-                const s = Structure.create([u.getChild(SortedArray.ofSingleton(u.elements[0]))]);
+                const s = Structure.create([u.getChild(SortedArray.ofSingleton(u.elements[0]))], ctx.inputStructure);
                 ret.add(s);
             }
         } else {

+ 4 - 4
src/mol-model/structure/query/queries/generators.ts

@@ -168,10 +168,10 @@ function atomGroupsGrouped({ entityTest, chainTest, residueTest, atomTest, group
     };
 }
 
-function getRingStructure(unit: Unit.Atomic, ring: UnitRing) {
+function getRingStructure(unit: Unit.Atomic, ring: UnitRing, inputStructure: Structure) {
     const elements = new Int32Array(ring.length) as any as ElementIndex[];
     for (let i = 0, _i = ring.length; i < _i; i++) elements[i] = unit.elements[ring[i]];
-    return Structure.create([unit.getChild(SortedArray.ofSortedArray(elements))])
+    return Structure.create([unit.getChild(SortedArray.ofSortedArray(elements))], inputStructure);
 }
 
 export function rings(fingerprints?: ArrayLike<UnitRing.Fingerprint>): StructureQuery {
@@ -184,7 +184,7 @@ export function rings(fingerprints?: ArrayLike<UnitRing.Fingerprint>): Structure
                 if (!Unit.isAtomic(u)) continue;
 
                 for (const r of u.rings.all) {
-                    ret.add(getRingStructure(u, r));
+                    ret.add(getRingStructure(u, r, ctx.inputStructure));
                 }
             }
         } else {
@@ -198,7 +198,7 @@ export function rings(fingerprints?: ArrayLike<UnitRing.Fingerprint>): Structure
                 for (const fp of uniqueFps.array) {
                     if (!rings.byFingerprint.has(fp)) continue;
                     for (const r of rings.byFingerprint.get(fp)!) {
-                        ret.add(getRingStructure(u, rings.all[r]));
+                        ret.add(getRingStructure(u, rings.all[r], ctx.inputStructure));
                     }
                 }
             }

+ 4 - 4
src/mol-model/structure/query/queries/internal.ts

@@ -35,7 +35,7 @@ export function atomicSequence(): StructureQuery {
 
             units.push(unit);
         }
-        return StructureSelection.Singletons(inputStructure, new Structure(units));
+        return StructureSelection.Singletons(inputStructure, new Structure(units, inputStructure, ));
     };
 }
 
@@ -54,7 +54,7 @@ export function water(): StructureQuery {
             if (P.entity.type(l) !== 'water') continue;
             units.push(unit);
         }
-        return StructureSelection.Singletons(inputStructure, new Structure(units));
+        return StructureSelection.Singletons(inputStructure, new Structure(units, inputStructure));
     };
 }
 
@@ -84,7 +84,7 @@ export function atomicHet(): StructureQuery {
 
             units.push(unit);
         }
-        return StructureSelection.Singletons(inputStructure, new Structure(units));
+        return StructureSelection.Singletons(inputStructure, new Structure(units, inputStructure));
     };
 }
 
@@ -97,6 +97,6 @@ export function spheres(): StructureQuery {
             if (unit.kind !== Unit.Kind.Spheres) continue;
             units.push(unit);
         }
-        return StructureSelection.Singletons(inputStructure, new Structure(units));
+        return StructureSelection.Singletons(inputStructure, new Structure(units, inputStructure));
     };
 }

+ 1 - 1
src/mol-model/structure/query/selection.ts

@@ -135,7 +135,7 @@ namespace StructureSelection {
                 const { elements } = unit;
                 for (let i = 0, _i = elements.length; i < _i; i++) {
                     // TODO: optimize this somehow???
-                    const s = Structure.create([unit.getChild(SortedArray.ofSingleton(elements[i]))]);
+                    const s = Structure.create([unit.getChild(SortedArray.ofSingleton(elements[i]))], sel.source);
                     fn(s, idx++);
                 }
             }

+ 2 - 2
src/mol-model/structure/query/utils/structure-set.ts

@@ -80,7 +80,7 @@ export function structureIntersect(sA: Structure, sB: Structure): Structure {
         }
     }
 
-    return Structure.create(units);
+    return Structure.create(units, sA.parent || sB.parent);
 }
 
 export function structureSubtract(a: Structure, b: Structure): Structure {
@@ -100,5 +100,5 @@ export function structureSubtract(a: Structure, b: Structure): Structure {
         }
     }
 
-    return Structure.create(units);
+    return Structure.create(units, a.parent || b.parent);
 }

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

@@ -34,6 +34,7 @@ class Structure {
     readonly units: ReadonlyArray<Unit>;
 
     private _props: {
+        parent?: Structure,
         lookup3d?: StructureLookup3D,
         links?: InterUnitBonds,
         crossLinkRestraints?: PairRestraints<CrossLinkRestraint>,
@@ -49,7 +50,14 @@ class Structure {
         transformHash: number,
         elementCount: number,
         polymerResidueCount: number,
-    } = { hashCode: -1, transformHash: -1, elementCount: 0, polymerResidueCount: 0 };
+        coordinateSystem: SymmetryOperator
+    } = {
+        hashCode: -1,
+        transformHash: -1,
+        elementCount: 0,
+        polymerResidueCount: 0,
+        coordinateSystem: SymmetryOperator.Default
+    };
 
     subsetBuilder(isSorted: boolean) {
         return new StructureSubsetBuilder(this, isSorted);
@@ -106,6 +114,14 @@ class Structure {
         return new Structure.ElementLocationIterator(this);
     }
 
+    get parent() {
+        return this._props.parent;
+    }
+
+    get coordinateSystem() {
+        return this._props.coordinateSystem;
+    }
+
     get boundary() {
         return this.lookup3d.boundary;
     }
@@ -174,7 +190,7 @@ class Structure {
         return SortedArray.has(this.unitMap.get(e.unit.id).elements, e.element);
     }
 
-    constructor(units: ArrayLike<Unit>) {
+    private initUnits(units: ArrayLike<Unit>) {
         const map = IntMap.Mutable<Unit>();
         let elementCount = 0;
         let polymerResidueCount = 0;
@@ -188,11 +204,18 @@ class Structure {
             if (u.id < lastId) isSorted = false;
             lastId = u.id;
         }
-        if (!isSorted) sort(units, 0, units.length, cmpUnits, arraySwap)
-        this.unitMap = map;
-        this.units = units as ReadonlyArray<Unit>;
+        if (!isSorted) sort(units, 0, units.length, cmpUnits, arraySwap);
         this._props.elementCount = elementCount;
         this._props.polymerResidueCount = polymerResidueCount;
+        return map;
+    }
+
+    constructor(units: ArrayLike<Unit>, parent: Structure | undefined, coordinateSystem?: SymmetryOperator) {
+        this.unitMap = this.initUnits(units);
+        this.units = units as ReadonlyArray<Unit>;
+        if (parent) this._props.parent = parent;
+        if (coordinateSystem) this._props.coordinateSystem = coordinateSystem;
+        else if (parent) this._props.coordinateSystem = parent.coordinateSystem;
     }
 }
 
@@ -283,7 +306,7 @@ function getUniqueAtomicResidueIndices(structure: Structure): ReadonlyMap<UUID,
 }
 
 namespace Structure {
-    export const Empty = new Structure([]);
+    export const Empty = new Structure([], void 0, void 0);
 
     /** Represents a single structure */
     export interface Loci {
@@ -302,7 +325,9 @@ namespace Structure {
         return a.structure === b.structure
     }
 
-    export function create(units: ReadonlyArray<Unit>): Structure { return new Structure(units); }
+    export function create(units: ReadonlyArray<Unit>, parent: Structure | undefined, coordinateSystem?: SymmetryOperator): Structure {
+        return new Structure(units, parent, coordinateSystem);
+    }
 
     /**
      * Construct a Structure from a model.
@@ -312,7 +337,7 @@ namespace Structure {
      */
     export function ofModel(model: Model): Structure {
         const chains = model.atomicHierarchy.chainAtomSegments;
-        const builder = new StructureBuilder();
+        const builder = new StructureBuilder(void 0, void 0);
 
         for (let c = 0; c < chains.count; c++) {
             const start = chains.offsets[c];
@@ -385,7 +410,9 @@ namespace Structure {
             units.push(u.applyOperator(u.id, op));
         }
 
-        return new Structure(units);
+        const cs = s.coordinateSystem;
+        const newCS = SymmetryOperator.compose(SymmetryOperator.create(cs.name, transform, cs.assembly, cs.ncsId, cs.hkl), cs);
+        return new Structure(units, s, newCS);
     }
 
     export class StructureBuilder {
@@ -405,15 +432,21 @@ namespace Structure {
         }
 
         getStructure(): Structure {
-            return create(this.units);
+            return create(this.units, this.parent, this.coordinateSystem);
         }
 
         get isEmpty() {
             return this.units.length === 0;
         }
+
+        constructor(private parent: Structure | undefined, private coordinateSystem: SymmetryOperator | undefined) {
+
+        }
     }
 
-    export function Builder() { return new StructureBuilder(); }
+    export function Builder(parent: Structure | undefined, coordinateSystem: SymmetryOperator | undefined) {
+        return new StructureBuilder(parent, coordinateSystem);
+    }
 
     export function hashCode(s: Structure) {
         return s.hashCode;

+ 3 - 3
src/mol-model/structure/structure/symmetry.ts

@@ -24,7 +24,7 @@ namespace StructureSymmetry {
             const assembly = ModelSymmetry.findAssembly(models[0], asmName);
             if (!assembly) throw new Error(`Assembly '${asmName}' is not defined.`);
 
-            const assembler = Structure.Builder();
+            const assembler = Structure.Builder(void 0, SymmetryOperator.create(assembly.id, Mat4.identity(), { id: assembly.id, operList: [] }));
 
             const queryCtx = new QueryContext(structure);
 
@@ -137,7 +137,7 @@ function getOperatorsCached333(symmetry: ModelSymmetry) {
 }
 
 function assembleOperators(structure: Structure, operators: ReadonlyArray<SymmetryOperator>) {
-    const assembler = Structure.Builder();
+    const assembler = Structure.Builder(void 0, void 0);
     const { units } = structure;
     for (const oper of operators) {
         for (const unit of units) {
@@ -179,7 +179,7 @@ async function findMatesRadius(ctx: RuntimeContext, structure: Structure, radius
     const operators = getOperatorsCached333(symmetry);
     const lookup = structure.lookup3d;
 
-    const assembler = Structure.Builder();
+    const assembler = Structure.Builder(void 0, void 0);
 
     const { units } = structure;
     const center = Vec3.zero();

+ 1 - 1
src/mol-model/structure/structure/util/subset-builder.ts

@@ -90,7 +90,7 @@ export class StructureSubsetBuilder {
             newUnits[newUnits.length] = child;
         }
 
-        return Structure.create(newUnits);
+        return Structure.create(newUnits, this.parent);
     }
 
     getStructure() {

+ 1 - 1
src/mol-model/structure/structure/util/unique-subset-builder.ts

@@ -85,7 +85,7 @@ export class StructureUniqueSubsetBuilder {
             newUnits[newUnits.length] = child;
         }
 
-        return Structure.create(newUnits);
+        return Structure.create(newUnits, this.parent, this.parent.coordinateSystem);
     }
 
     get isEmpty() {