Bladeren bron

added Structure.asParent

- refactored structure state handling
- removed Structure.WithChild
Alexander Rose 4 jaren geleden
bovenliggende
commit
42d60420e5

+ 1 - 1
src/extensions/cellpack/model.ts

@@ -414,7 +414,7 @@ export function createStructureFromCellPack(plugin: PluginContext, packing: Cell
         }
 
         if (ctx.shouldUpdate) await ctx.update(`${name} - structure`);
-        const structure = new Structure(units);
+        const structure = Structure.create(units);
         for( let i = 0, il = structure.models.length; i < il; ++i) {
             Model.TrajectoryInfo.set(structure.models[i], { size: il, index: i });
         }

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

@@ -43,7 +43,7 @@ export function atomicSequence(): StructureQuery {
 
             units.push(unit);
         }
-        return StructureSelection.Singletons(inputStructure, new Structure(units, { parent: inputStructure }));
+        return StructureSelection.Singletons(inputStructure, Structure.create(units, { parent: inputStructure }));
     };
 }
 
@@ -62,7 +62,7 @@ export function water(): StructureQuery {
             if (P.entity.type(l) !== 'water') continue;
             units.push(unit);
         }
-        return StructureSelection.Singletons(inputStructure, new Structure(units, { parent: inputStructure }));
+        return StructureSelection.Singletons(inputStructure, Structure.create(units, { parent: inputStructure }));
     };
 }
 
@@ -92,7 +92,7 @@ export function atomicHet(): StructureQuery {
 
             units.push(unit);
         }
-        return StructureSelection.Singletons(inputStructure, new Structure(units, { parent: inputStructure }));
+        return StructureSelection.Singletons(inputStructure, Structure.create(units, { parent: inputStructure }));
     };
 }
 
@@ -105,7 +105,7 @@ export function spheres(): StructureQuery {
             if (unit.kind !== Unit.Kind.Spheres) continue;
             units.push(unit);
         }
-        return StructureSelection.Singletons(inputStructure, new Structure(units, { parent: inputStructure }));
+        return StructureSelection.Singletons(inputStructure, Structure.create(units, { parent: inputStructure }));
     };
 }
 

+ 198 - 188
src/mol-model/structure/structure/structure.ts

@@ -36,89 +36,38 @@ import { RuntimeContext, Task } from '../../../mol-task';
 import { computeStructureBoundary } from './util/boundary';
 
 class Structure {
-    /** Maps unit.id to unit */
-    readonly unitMap: IntMap<Unit>;
-    /** Maps unit.id to index of unit in units array */
-    readonly unitIndexMap: IntMap<number>;
-    /** Array of all units in the structure, sorted by unit.id */
-    readonly units: ReadonlyArray<Unit>;
-
-    private _props: {
-        parent?: Structure,
-        boundary?: Boundary,
-        lookup3d?: StructureLookup3D,
-        interUnitBonds?: InterUnitBonds,
-        unitSymmetryGroups?: ReadonlyArray<Unit.SymmetryGroup>,
-        unitSymmetryGroupsIndexMap?: IntMap<number>,
-        unitsSortedByVolume?: ReadonlyArray<Unit>;
-        carbohydrates?: Carbohydrates,
-        models?: ReadonlyArray<Model>,
-        model?: Model,
-        masterModel?: Model,
-        representativeModel?: Model,
-        uniqueResidueNames?: Set<string>,
-        uniqueElementSymbols?: Set<ElementSymbol>,
-        entityIndices?: ReadonlyArray<EntityIndex>,
-        uniqueAtomicResidueIndices?: ReadonlyMap<UUID, ReadonlyArray<ResidueIndex>>,
-        serialMapping?: SerialMapping,
-        hashCode: number,
-        /** Hash based on all unit.id values in the structure, reflecting the units transformation */
-        transformHash: number,
-        elementCount: number,
-        bondCount: number,
-        uniqueElementCount: number,
-        atomicResidueCount: number,
-        polymerResidueCount: number,
-        polymerUnitCount: number,
-        coordinateSystem: SymmetryOperator,
-        label: string,
-        propertyData?: any,
-        customProps?: CustomProperties
-    } = {
-        hashCode: -1,
-        transformHash: -1,
-        elementCount: -1,
-        bondCount: -1,
-        uniqueElementCount: -1,
-        atomicResidueCount: -1,
-        polymerResidueCount: -1,
-        polymerUnitCount: -1,
-        coordinateSystem: SymmetryOperator.Default,
-        label: ''
-    };
-
     subsetBuilder(isSorted: boolean) {
         return new StructureSubsetBuilder(this, isSorted);
     }
 
     /** Count of all elements in the structure, i.e. the sum of the elements in the units */
     get elementCount() {
-        return this._props.elementCount;
+        return this.state.elementCount;
     }
 
     /** Count of all bonds (intra- and inter-unit) in the structure */
     get bondCount() {
-        if (this._props.bondCount === -1) {
-            this._props.bondCount = this.interUnitBonds.edgeCount + Bond.getIntraUnitBondCount(this);
+        if (this.state.bondCount === -1) {
+            this.state.bondCount = this.interUnitBonds.edgeCount + Bond.getIntraUnitBondCount(this);
         }
-        return this._props.bondCount;
+        return this.state.bondCount;
     }
 
     get hasCustomProperties() {
-        return !!this._props.customProps && this._props.customProps.all.length > 0;
+        return !!this.state.customProps && this.state.customProps.all.length > 0;
     }
 
     get customPropertyDescriptors() {
-        if (!this._props.customProps) this._props.customProps = new CustomProperties();
-        return this._props.customProps;
+        if (!this.state.customProps) this.state.customProps = new CustomProperties();
+        return this.state.customProps;
     }
 
     /**
      * Property data unique to this instance of the structure.
      */
     get currentPropertyData() {
-        if (!this._props.propertyData) this._props.propertyData = Object.create(null);
-        return this._props.propertyData;
+        if (!this.state.propertyData) this.state.propertyData = Object.create(null);
+        return this.state.propertyData;
     }
 
     /**
@@ -130,31 +79,31 @@ class Structure {
 
     /** Count of all polymer residues in the structure */
     get polymerResidueCount() {
-        if (this._props.polymerResidueCount === -1) {
-            this._props.polymerResidueCount = getPolymerResidueCount(this);
+        if (this.state.polymerResidueCount === -1) {
+            this.state.polymerResidueCount = getPolymerResidueCount(this);
         }
-        return this._props.polymerResidueCount;
+        return this.state.polymerResidueCount;
     }
 
     get polymerUnitCount() {
-        if (this._props.polymerUnitCount === -1) {
-            this._props.polymerUnitCount = getPolymerUnitCount(this);
+        if (this.state.polymerUnitCount === -1) {
+            this.state.polymerUnitCount = getPolymerUnitCount(this);
         }
-        return this._props.polymerUnitCount;
+        return this.state.polymerUnitCount;
     }
 
     get uniqueElementCount() {
-        if (this._props.uniqueElementCount === -1) {
-            this._props.uniqueElementCount = getUniqueElementCount(this);
+        if (this.state.uniqueElementCount === -1) {
+            this.state.uniqueElementCount = getUniqueElementCount(this);
         }
-        return this._props.uniqueElementCount;
+        return this.state.uniqueElementCount;
     }
 
     get atomicResidueCount() {
-        if (this._props.atomicResidueCount === -1) {
-            this._props.atomicResidueCount = getAtomicResidueCount(this);
+        if (this.state.atomicResidueCount === -1) {
+            this.state.atomicResidueCount = getAtomicResidueCount(this);
         }
-        return this._props.atomicResidueCount;
+        return this.state.atomicResidueCount;
     }
 
     /**
@@ -170,15 +119,15 @@ class Structure {
     }
 
     get hashCode() {
-        if (this._props.hashCode !== -1) return this._props.hashCode;
+        if (this.state.hashCode !== -1) return this.state.hashCode;
         return this.computeHash();
     }
 
     /** Hash based on all unit.id values in the structure, reflecting the units transformation */
     get transformHash() {
-        if (this._props.transformHash !== -1) return this._props.transformHash;
-        this._props.transformHash = hashFnv32a(this.units.map(u => u.id));
-        return this._props.transformHash;
+        if (this.state.transformHash !== -1) return this.state.transformHash;
+        this.state.transformHash = hashFnv32a(this.units.map(u => u.id));
+        return this.state.transformHash;
     }
 
     private computeHash() {
@@ -191,7 +140,7 @@ class Structure {
         hash = (31 * hash + this.elementCount) | 0;
         hash = hash1(hash);
         if (hash === -1) hash = 0;
-        this._props.hashCode = hash;
+        this.state.hashCode = hash;
         return hash;
     }
 
@@ -202,12 +151,12 @@ class Structure {
 
     /** The parent or itself in case this is the root */
     get root() {
-        return this._props.parent || this;
+        return this.state.parent || this;
     }
 
     /** The root/top-most parent or `undefined` in case this is the root */
     get parent() {
-        return this._props.parent;
+        return this.state.parent;
     }
 
     /**
@@ -218,81 +167,81 @@ class Structure {
      * by the consumer.
      */
     get coordinateSystem(): SymmetryOperator {
-        return this._props.coordinateSystem;
+        return this.state.coordinateSystem;
     }
 
     get label() {
-        return this._props.label;
+        return this.state.label;
     }
 
     get boundary() {
-        if (this._props.boundary) return this._props.boundary;
-        this._props.boundary = computeStructureBoundary(this);
-        return this._props.boundary;
+        if (this.state.boundary) return this.state.boundary;
+        this.state.boundary = computeStructureBoundary(this);
+        return this.state.boundary;
     }
 
     get lookup3d() {
-        if (this._props.lookup3d) return this._props.lookup3d;
-        this._props.lookup3d = new StructureLookup3D(this);
-        return this._props.lookup3d;
+        if (this.state.lookup3d) return this.state.lookup3d;
+        this.state.lookup3d = new StructureLookup3D(this);
+        return this.state.lookup3d;
     }
 
     get interUnitBonds() {
-        if (this._props.interUnitBonds) return this._props.interUnitBonds;
-        this._props.interUnitBonds = computeInterUnitBonds(this);
-        return this._props.interUnitBonds;
+        if (this.state.interUnitBonds) return this.state.interUnitBonds;
+        this.state.interUnitBonds = computeInterUnitBonds(this);
+        return this.state.interUnitBonds;
     }
 
     get unitSymmetryGroups(): ReadonlyArray<Unit.SymmetryGroup> {
-        if (this._props.unitSymmetryGroups) return this._props.unitSymmetryGroups;
-        this._props.unitSymmetryGroups = StructureSymmetry.computeTransformGroups(this);
-        return this._props.unitSymmetryGroups;
+        if (this.state.unitSymmetryGroups) return this.state.unitSymmetryGroups;
+        this.state.unitSymmetryGroups = StructureSymmetry.computeTransformGroups(this);
+        return this.state.unitSymmetryGroups;
     }
 
     /** Maps unit.id to index of SymmetryGroup in unitSymmetryGroups array */
     get unitSymmetryGroupsIndexMap(): IntMap<number> {
-        if (this._props.unitSymmetryGroupsIndexMap) return this._props.unitSymmetryGroupsIndexMap;
-        this._props.unitSymmetryGroupsIndexMap = Unit.SymmetryGroup.getUnitSymmetryGroupsIndexMap(this.unitSymmetryGroups);
-        return this._props.unitSymmetryGroupsIndexMap;
+        if (this.state.unitSymmetryGroupsIndexMap) return this.state.unitSymmetryGroupsIndexMap;
+        this.state.unitSymmetryGroupsIndexMap = Unit.SymmetryGroup.getUnitSymmetryGroupsIndexMap(this.unitSymmetryGroups);
+        return this.state.unitSymmetryGroupsIndexMap;
     }
 
     /** Array of all units in the structure, sorted by their boundary volume */
     get unitsSortedByVolume(): ReadonlyArray<Unit> {
-        if (this._props.unitsSortedByVolume) return this._props.unitsSortedByVolume;
-        this._props.unitsSortedByVolume = getUnitsSortedByVolume(this);
-        return this._props.unitsSortedByVolume;
+        if (this.state.unitsSortedByVolume) return this.state.unitsSortedByVolume;
+        this.state.unitsSortedByVolume = getUnitsSortedByVolume(this);
+        return this.state.unitsSortedByVolume;
     }
 
     get carbohydrates(): Carbohydrates {
-        if (this._props.carbohydrates) return this._props.carbohydrates;
-        this._props.carbohydrates = computeCarbohydrates(this);
-        return this._props.carbohydrates;
+        if (this.state.carbohydrates) return this.state.carbohydrates;
+        this.state.carbohydrates = computeCarbohydrates(this);
+        return this.state.carbohydrates;
     }
 
     get models(): ReadonlyArray<Model> {
-        if (this._props.models) return this._props.models;
-        this._props.models = getModels(this);
-        return this._props.models;
+        if (this.state.models) return this.state.models;
+        this.state.models = getModels(this);
+        return this.state.models;
     }
 
     get uniqueResidueNames() {
-        return this._props.uniqueResidueNames
-            || (this._props.uniqueResidueNames = getUniqueResidueNames(this));
+        return this.state.uniqueResidueNames
+            || (this.state.uniqueResidueNames = getUniqueResidueNames(this));
     }
 
     get uniqueElementSymbols() {
-        return this._props.uniqueElementSymbols
-            || (this._props.uniqueElementSymbols = getUniqueElementSymbols(this));
+        return this.state.uniqueElementSymbols
+            || (this.state.uniqueElementSymbols = getUniqueElementSymbols(this));
     }
 
     get entityIndices() {
-        return this._props.entityIndices
-            || (this._props.entityIndices = getEntityIndices(this));
+        return this.state.entityIndices
+            || (this.state.entityIndices = getEntityIndices(this));
     }
 
     get uniqueAtomicResidueIndices() {
-        return this._props.uniqueAtomicResidueIndices
-            || (this._props.uniqueAtomicResidueIndices = getUniqueAtomicResidueIndices(this));
+        return this.state.uniqueAtomicResidueIndices
+            || (this.state.uniqueAtomicResidueIndices = getUniqueAtomicResidueIndices(this));
     }
 
     /** Contains only atomic units */
@@ -327,7 +276,7 @@ class Structure {
      * to address elements in a structure.
      */
     get serialMapping() {
-        return this._props.serialMapping || (this._props.serialMapping = getSerialMapping(this));
+        return this.state.serialMapping || (this.state.serialMapping = getSerialMapping(this));
     }
 
     /**
@@ -335,25 +284,25 @@ class Structure {
      * Otherwise throw an exception.
      */
     get model(): Model {
-        if (this._props.model) return this._props.model;
-        if (this._props.representativeModel) return this._props.representativeModel;
-        if (this._props.masterModel) return this._props.masterModel;
+        if (this.state.model) return this.state.model;
+        if (this.state.representativeModel) return this.state.representativeModel;
+        if (this.state.masterModel) return this.state.masterModel;
         const models = this.models;
         if (models.length > 1) {
             throw new Error('The structure is based on multiple models and has neither a master- nor a representative-model.');
         }
-        this._props.model = models[0];
-        return this._props.model;
+        this.state.model = models[0];
+        return this.state.model;
     }
 
     /** The master-model, other models can have bonds to it  */
     get masterModel(): Model | undefined {
-        return this._props.masterModel;
+        return this.state.masterModel;
     }
 
     /** A representative model, e.g. the first model of a trajectory */
     get representativeModel(): Model | undefined {
-        return this._props.representativeModel;
+        return this.state.representativeModel;
     }
 
     hasElement(e: StructureElement.Location) {
@@ -377,51 +326,52 @@ class Structure {
         }
         return Structure.create(units, {
             label: this.label,
-            interUnitBonds: this._props.interUnitBonds,
+            interUnitBonds: this.state.interUnitBonds,
         });
     }
 
-    private initUnits(units: ArrayLike<Unit>) {
-        const unitMap = IntMap.Mutable<Unit>();
-        const unitIndexMap = IntMap.Mutable<number>();
-        let elementCount = 0;
-        let isSorted = true;
-        let lastId = units.length > 0 ? units[0].id : 0;
-        for (let i = 0, _i = units.length; i < _i; i++) {
-            const u = units[i];
-            unitMap.set(u.id, u);
-            elementCount += u.elements.length;
-            if (u.id < lastId) isSorted = false;
-            lastId = u.id;
-        }
-        if (!isSorted) sort(units, 0, units.length, cmpUnits, arraySwap);
-        for (let i = 0, _i = units.length; i < _i; i++) {
-            unitIndexMap.set(units[i].id, i);
-        }
-        this._props.elementCount = elementCount;
-        return { unitMap, unitIndexMap };
+    private _child: Structure | undefined;
+    private _target: Structure | undefined;
+
+    /**
+     * For `structure` with `parent` this returns a proxy that
+     * targets `parent` and has `structure` attached as a child.
+     */
+    asParent(): Structure {
+        return this.parent
+            ? new Structure(this.parent.state, { child: this, target: this.parent })
+            : this;
     }
 
-    constructor(units: ArrayLike<Unit>, props: Structure.Props = {}) {
-        const { unitMap, unitIndexMap } = this.initUnits(units);
-        this.unitMap = unitMap;
-        this.unitIndexMap = unitIndexMap;
-        this.units = units as ReadonlyArray<Unit>;
+    get child(): Structure | undefined {
+        return this._child;
+    }
 
-        if (props.parent) this._props.parent = props.parent.parent || props.parent;
-        if (props.interUnitBonds) this._props.interUnitBonds = props.interUnitBonds;
+    /** Get the proxy target. Usefull for equality checks. */
+    get target(): Structure {
+        return this._target ?? this;
+    }
 
-        if (props.coordinateSystem) this._props.coordinateSystem = props.coordinateSystem;
-        else if (props.parent) this._props.coordinateSystem = props.parent.coordinateSystem;
+    /** Maps unit.id to unit */
+    get unitMap(): IntMap<Unit> {
+        return this.state.unitMap;
+    }
 
-        if (props.label) this._props.label = props.label;
-        else if (props.parent) this._props.label = props.parent.label;
+    /** Maps unit.id to index of unit in units array */
+    get unitIndexMap(): IntMap<number> {
+        return this.state.unitIndexMap;
+    }
 
-        if (props.masterModel) this._props.masterModel = props.masterModel;
-        else if (props.parent) this._props.masterModel = props.parent.masterModel;
+    /** Array of all units in the structure, sorted by unit.id */
+    get units(): ReadonlyArray<Unit> {
+        return this.state.units;
+    }
 
-        if (props.representativeModel) this._props.representativeModel = props.representativeModel;
-        else if (props.parent) this._props.representativeModel = props.parent.representativeModel;
+    constructor(readonly state: Structure.State, asParent?: { child: Structure, target: Structure }) {
+        if (asParent) {
+            this._child = asParent.child;
+            this._target = asParent.target;
+        }
     }
 }
 
@@ -632,7 +582,7 @@ function getSerialMapping(structure: Structure): SerialMapping {
 }
 
 namespace Structure {
-    export const Empty = new Structure([]);
+    export const Empty = create([]);
 
     export interface Props {
         parent?: Structure
@@ -686,8 +636,96 @@ namespace Structure {
         return Loci(structure);
     }
 
-    export function create(units: ReadonlyArray<Unit>, props?: Props): Structure {
-        return new Structure(units, props);
+    export type State = {
+        unitMap: IntMap<Unit>;
+        unitIndexMap: IntMap<number>;
+        units: ReadonlyArray<Unit>;
+
+        parent?: Structure,
+        boundary?: Boundary,
+        lookup3d?: StructureLookup3D,
+        interUnitBonds?: InterUnitBonds,
+        unitSymmetryGroups?: ReadonlyArray<Unit.SymmetryGroup>,
+        unitSymmetryGroupsIndexMap?: IntMap<number>,
+        unitsSortedByVolume?: ReadonlyArray<Unit>;
+        carbohydrates?: Carbohydrates,
+        models?: ReadonlyArray<Model>,
+        model?: Model,
+        masterModel?: Model,
+        representativeModel?: Model,
+        uniqueResidueNames?: Set<string>,
+        uniqueElementSymbols?: Set<ElementSymbol>,
+        entityIndices?: ReadonlyArray<EntityIndex>,
+        uniqueAtomicResidueIndices?: ReadonlyMap<UUID, ReadonlyArray<ResidueIndex>>,
+        serialMapping?: SerialMapping,
+        hashCode: number,
+        transformHash: number,
+        elementCount: number,
+        bondCount: number,
+        uniqueElementCount: number,
+        atomicResidueCount: number,
+        polymerResidueCount: number,
+        polymerUnitCount: number,
+        coordinateSystem: SymmetryOperator,
+        label: string,
+        propertyData?: any,
+        customProps?: CustomProperties
+    }
+
+    export function create(units: ReadonlyArray<Unit>, props: Props = {}): Structure {
+        // init units
+        const unitMap = IntMap.Mutable<Unit>();
+        const unitIndexMap = IntMap.Mutable<number>();
+        let elementCount = 0;
+        let isSorted = true;
+        let lastId = units.length > 0 ? units[0].id : 0;
+        for (let i = 0, _i = units.length; i < _i; i++) {
+            const u = units[i];
+            unitMap.set(u.id, u);
+            elementCount += u.elements.length;
+            if (u.id < lastId) isSorted = false;
+            lastId = u.id;
+        }
+        if (!isSorted) sort(units, 0, units.length, cmpUnits, arraySwap);
+        for (let i = 0, _i = units.length; i < _i; i++) {
+            unitIndexMap.set(units[i].id, i);
+        }
+
+        // initial state
+        const state: Structure.State = {
+            units,
+            unitMap,
+            unitIndexMap,
+
+            hashCode: -1,
+            transformHash: -1,
+            elementCount,
+            bondCount: -1,
+            uniqueElementCount: -1,
+            atomicResidueCount: -1,
+            polymerResidueCount: -1,
+            polymerUnitCount: -1,
+            coordinateSystem: SymmetryOperator.Default,
+            label: ''
+        };
+
+        // handle props
+        if (props.parent) state.parent = props.parent.parent || props.parent;
+        if (props.interUnitBonds) state.interUnitBonds = props.interUnitBonds;
+
+        if (props.coordinateSystem) state.coordinateSystem = props.coordinateSystem;
+        else if (props.parent) state.coordinateSystem = props.parent.coordinateSystem;
+
+        if (props.label) state.label = props.label;
+        else if (props.parent) state.label = props.parent.label;
+
+        if (props.masterModel) state.masterModel = props.masterModel;
+        else if (props.parent) state.masterModel = props.parent.masterModel;
+
+        if (props.representativeModel) state.representativeModel = props.representativeModel;
+        else if (props.parent) state.representativeModel = props.parent.representativeModel;
+
+        return new Structure(state);
     }
 
     export async function ofTrajectory(trajectory: Trajectory, ctx: RuntimeContext): Promise<Structure> {
@@ -893,7 +931,7 @@ namespace Structure {
 
         const cs = s.coordinateSystem;
         const newCS = SymmetryOperator.compose(SymmetryOperator.create(cs.name, transform, cs), cs);
-        return new Structure(units, { parent: s, coordinateSystem: newCS });
+        return create(units, { parent: s, coordinateSystem: newCS });
     }
 
     export class StructureBuilder {
@@ -1227,34 +1265,6 @@ namespace Structure {
 
     export type Index = number;
     export const Index = CustomStructureProperty.createSimple<Index>('index', 'root');
-
-    export const WithChild = {
-        getChild(structure: Structure): Structure | undefined {
-            return (structure as any).__child;
-        },
-        /** Get the proxy target. Usefull for equality checks. */
-        getTarget(structure: Structure): Structure {
-            return (structure as any).__parent || structure;
-        },
-        /**
-         * For `structure` with `parent` this returns a proxy that
-         * targets `parent` and has `structure` attached as a child.
-         */
-        fromStructure(structure: Structure): Structure {
-            if (!structure.parent) return structure;
-
-            return new Proxy(structure.parent, {
-                get: function(target, prop, receiver) {
-                    if (prop === '__child') {
-                        return structure;
-                    } else if (prop === '__parent') {
-                        return structure.parent;
-                    }
-                    return Reflect.get(target, prop, receiver);
-                }
-            });
-        }
-    };
 }
 
 export { Structure };

+ 1 - 3
src/mol-repr/structure/complex-representation.ts

@@ -66,9 +66,7 @@ export function ComplexRepresentation<P extends StructureParams>(label: string,
     }
 
     function getLoci(pickingId?: PickingId) {
-        if (pickingId === undefined) {
-            return Structure.Loci(Structure.WithChild.getTarget(_structure));
-        }
+        if (pickingId === undefined) return Structure.Loci(_structure.target);
         return visual ? visual.getLoci(pickingId) : EmptyLoci;
     }
 

+ 1 - 1
src/mol-repr/structure/representation/ball-and-stick.ts

@@ -53,7 +53,7 @@ export const BallAndStickRepresentationProvider = StructureRepresentationProvide
     defaultSizeTheme: { name: 'physical' },
     isApplicable: (structure: Structure) => structure.elementCount > 0,
     getData: (structure: Structure, props: PD.Values<BallAndStickParams>) => {
-        return props.includeParent ? Structure.WithChild.fromStructure(structure) : structure;
+        return props.includeParent ? structure.asParent() : structure;
     },
     mustRecreate: (oldProps: PD.Values<BallAndStickParams>, newProps: PD.Values<BallAndStickParams>) => {
         return oldProps.includeParent !== newProps.includeParent;

+ 1 - 1
src/mol-repr/structure/representation/ellipsoid.ts

@@ -53,7 +53,7 @@ export const EllipsoidRepresentationProvider = StructureRepresentationProvider({
     defaultSizeTheme: { name: 'uniform' },
     isApplicable: (structure: Structure) => structure.elementCount > 0 && structure.models.some(m => AtomSiteAnisotrop.Provider.isApplicable(m)),
     getData: (structure: Structure, props: PD.Values<EllipsoidParams>) => {
-        return props.includeParent ? Structure.WithChild.fromStructure(structure) : structure;
+        return props.includeParent ? structure.asParent() : structure;
     },
     mustRecreate: (oldProps: PD.Values<EllipsoidParams>, newProps: PD.Values<EllipsoidParams>) => {
         return oldProps.includeParent !== newProps.includeParent;

+ 1 - 1
src/mol-repr/structure/representation/line.ts

@@ -48,7 +48,7 @@ export const LineRepresentationProvider = StructureRepresentationProvider({
     defaultSizeTheme: { name: 'uniform' },
     isApplicable: (structure: Structure) => structure.elementCount > 0,
     getData: (structure: Structure, props: PD.Values<LineParams>) => {
-        return props.includeParent ? Structure.WithChild.fromStructure(structure) : structure;
+        return props.includeParent ? structure.asParent() : structure;
     },
     mustRecreate: (oldProps: PD.Values<LineParams>, newProps: PD.Values<LineParams>) => {
         return oldProps.includeParent !== newProps.includeParent;

+ 1 - 3
src/mol-repr/structure/units-representation.ts

@@ -180,9 +180,7 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct
     }
 
     function getLoci(pickingId?: PickingId) {
-        if (pickingId === undefined) {
-            return Structure.Loci(Structure.WithChild.getTarget(_structure));
-        }
+        if (pickingId === undefined) return Structure.Loci(_structure.target);
         let loci: Loci = EmptyLoci;
         visuals.forEach(({ visual }) => {
             const _loci = visual.getLoci(pickingId);

+ 3 - 3
src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts

@@ -47,7 +47,7 @@ function getInterUnitBondCylinderBuilderProps(structure: Structure, theme: Theme
     let stub: undefined | ((edgeIndex: number) => boolean);
 
     if (props.includeParent) {
-        const child = Structure.WithChild.getChild(structure);
+        const { child } = structure;
         if (!child) throw new Error('expected child to exist');
 
         stub = (edgeIndex: number) => {
@@ -159,7 +159,7 @@ function createInterUnitBondCylinderImpostors(ctx: VisualContext, structure: Str
     const builderProps = getInterUnitBondCylinderBuilderProps(structure, theme, props);
     const m = createLinkCylinderImpostors(ctx, builderProps, props, cylinders);
 
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
     const sphere = Sphere3D.expand(Sphere3D(), (child ?? structure).boundary.sphere, 1 * props.sizeFactor);
     m.setBoundingSphere(sphere);
 
@@ -172,7 +172,7 @@ function createInterUnitBondCylinderMesh(ctx: VisualContext, structure: Structur
     const builderProps = getInterUnitBondCylinderBuilderProps(structure, theme, props);
     const m = createLinkCylinderMesh(ctx, builderProps, props, mesh);
 
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
     const sphere = Sphere3D.expand(Sphere3D(), (child ?? structure).boundary.sphere, 1 * props.sizeFactor);
     m.setBoundingSphere(sphere);
 

+ 1 - 1
src/mol-repr/structure/visual/bond-inter-unit-line.ts

@@ -97,7 +97,7 @@ function createInterUnitBondLines(ctx: VisualContext, structure: Structure, them
 
     const l = createLinkLines(ctx, builderProps, props, lines);
 
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
     const sphere = Sphere3D.expand(Sphere3D(), (child ?? structure).boundary.sphere, 1 * props.sizeFactor);
     l.setBoundingSphere(sphere);
 

+ 3 - 3
src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts

@@ -42,7 +42,7 @@ function getIntraUnitBondCylinderBuilderProps(unit: Unit.Atomic, structure: Stru
     const locB = Bond.Location(structure, unit, undefined, structure, unit, undefined);
 
     if (props.includeParent) {
-        const child = Structure.WithChild.getChild(structure);
+        const { child } = structure;
         if (!child) throw new Error('expected child to exist');
         const childUnit = child.unitMap.get(unit.id);
         if (!childUnit) throw new Error('expected childUnit to exist');
@@ -131,7 +131,7 @@ function createIntraUnitBondCylinderImpostors(ctx: VisualContext, unit: Unit, st
     if (!Unit.isAtomic(unit)) return Cylinders.createEmpty(cylinders);
     if (!unit.bonds.edgeCount) return Cylinders.createEmpty(cylinders);
 
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
     const childUnit = child?.unitMap.get(unit.id);
     if (child && !childUnit) return Cylinders.createEmpty(cylinders);
 
@@ -148,7 +148,7 @@ function createIntraUnitBondCylinderMesh(ctx: VisualContext, unit: Unit, structu
     if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh);
     if (!unit.bonds.edgeCount) return Mesh.createEmpty(mesh);
 
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
     const childUnit = child?.unitMap.get(unit.id);
     if (child && !childUnit) return Mesh.createEmpty(mesh);
 

+ 1 - 2
src/mol-repr/structure/visual/bond-intra-unit-line.ts

@@ -25,12 +25,11 @@ const isBondType = BondType.is;
 function createIntraUnitBondLines(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<IntraUnitBondLineParams>, lines?: Lines) {
     if (!Unit.isAtomic(unit)) return Lines.createEmpty(lines);
 
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
     const childUnit = child?.unitMap.get(unit.id);
     if (child && !childUnit) return Lines.createEmpty(lines);
 
     if (props.includeParent) {
-        const child = Structure.WithChild.getChild(structure);
         if (!child) throw new Error('expected child to exist');
     }
 

+ 1 - 1
src/mol-repr/structure/visual/element-point.ts

@@ -29,7 +29,7 @@ export type ElementPointParams = typeof ElementPointParams
 export function createElementPoint(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<ElementPointParams>, points: Points) {
     // TODO sizeFactor
 
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
     if (child && !child.unitMap.get(unit.id)) return Points.createEmpty(points);
 
     const elements = unit.elements;

+ 1 - 1
src/mol-repr/structure/visual/ellipsoid-mesh.ts

@@ -58,7 +58,7 @@ export interface EllipsoidMeshProps {
 }
 
 export function createEllipsoidMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: EllipsoidMeshProps, mesh?: Mesh): Mesh {
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
     const childUnit = child?.unitMap.get(unit.id);
     if (child && !childUnit) return Mesh.createEmpty(mesh);
 

+ 4 - 4
src/mol-repr/structure/visual/util/bond.ts

@@ -56,7 +56,7 @@ export function makeIntraBondIgnoreTest(structure: Structure, unit: Unit.Atomic,
     const exclude = BondType.fromNames(excludeTypes);
     const allBondTypes = BondType.isAll(include) && BondType.Flag.None === exclude;
 
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
     const childUnit = child?.unitMap.get(unit.id);
     if (child && !childUnit) throw new Error('expected childUnit to exist if child exists');
 
@@ -81,7 +81,7 @@ export function makeInterBondIgnoreTest(structure: Structure, props: BondProps):
     const exclude = BondType.fromNames(excludeTypes);
     const allBondTypes = BondType.isAll(include) && BondType.Flag.None === exclude;
 
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
 
     if (allBondTypes && !ignoreHydrogens && !child) return;
 
@@ -153,7 +153,7 @@ export function getIntraBondLoci(pickingId: PickingId, structureGroup: Structure
         const { structure, group } = structureGroup;
         const unit = group.units[instanceId];
         if (Unit.isAtomic(unit)) {
-            const target = Structure.WithChild.getTarget(structure);
+            const { target } = structure;
             const iA = unit.bonds.a[groupId];
             const iB = unit.bonds.b[groupId];
             return Bond.Loci(target, [
@@ -211,7 +211,7 @@ export function eachIntraBond(loci: Loci, structureGroup: StructureGroup, apply:
 export function getInterBondLoci(pickingId: PickingId, structure: Structure, id: number) {
     const { objectId, groupId } = pickingId;
     if (id === objectId) {
-        const target = Structure.WithChild.getTarget(structure);
+        const { target } = structure;
         const b = structure.interUnitBonds.edges[groupId];
         const uA = structure.unitMap.get(b.unitA);
         const uB = structure.unitMap.get(b.unitB);

+ 4 - 7
src/mol-repr/structure/visual/util/element.ts

@@ -42,7 +42,7 @@ export function makeElementIgnoreTest(structure: Structure, unit: Unit, props: E
     const { atomicNumber } = unit.model.atomicHierarchy.derived.atom;
     const isCoarse = Unit.isCoarse(unit);
 
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
     const childUnit = child?.unitMap.get(unit.id);
     if (child && !childUnit) throw new Error('expected childUnit to exist if child exists');
 
@@ -58,7 +58,7 @@ export function makeElementIgnoreTest(structure: Structure, unit: Unit, props: E
 }
 
 export function createElementSphereMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: ElementSphereMeshProps, mesh?: Mesh): Mesh {
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
     const childUnit = child?.unitMap.get(unit.id);
     if (child && !childUnit) return Mesh.createEmpty(mesh);
 
@@ -113,7 +113,7 @@ export type ElementSphereImpostorProps = {
 } & ElementProps
 
 export function createElementSphereImpostor(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: ElementSphereImpostorProps, spheres?: Spheres): Spheres {
-    const child = Structure.WithChild.getChild(structure);
+    const { child } = structure;
     const childUnit = child?.unitMap.get(unit.id);
     if (child && !childUnit) return Spheres.createEmpty(spheres);
 
@@ -194,10 +194,7 @@ export function getElementLoci(pickingId: PickingId, structureGroup: StructureGr
         const { structure, group } = structureGroup;
         const unit = group.units[instanceId];
         const indices = OrderedSet.ofSingleton(groupId as StructureElement.UnitIndex);
-        return StructureElement.Loci(
-            Structure.WithChild.getTarget(structure),
-            [{ unit, indices }]
-        );
+        return StructureElement.Loci(structure.target, [{ unit, indices }]);
     }
     return EmptyLoci;
 }