diff --git a/src/mol-data/int/map.ts b/src/mol-data/int/map.ts index 4d75644ed6f43ff7f6c801358745438c91f88c3b..30725a89c49238468e858c85cb88c65f3b3062e4 100644 --- a/src/mol-data/int/map.ts +++ b/src/mol-data/int/map.ts @@ -28,16 +28,6 @@ namespace IntMap { return iterableToArray(map.keys()); } - export function ofObj<T>(obj: { [key: number]: T }): IntMap<T> { - const keys = Object.keys(obj); - const ret = new Map<number, T>(); - for (let i = 0, _i = keys.length; i < _i; i++) { - const k = keys[i]; - ret.set(+k, obj[k as any]); - } - return ret as IntMap<T>; - } - export function Mutable<T>(): Mutable<T> { return new Map<number, T>() as Mutable<T>; } @@ -45,6 +35,27 @@ namespace IntMap { export function asImmutable<T>(map: IntMap<T>): IntMap<T> { return map; } + + export function copy<T>(map: IntMap<T>): Mutable<T> { + const ret = Mutable<T>(); + const it = map.keys(); + while (true) { + const { done, value } = it.next(); + if (done) break; + ret.set(value, map.get(value)); + } + return ret; + } + + export function addFrom<T>(map: Mutable<T>, src: IntMap<T>) { + const it = src.keys(); + while (true) { + const { done, value } = it.next(); + if (done) break; + map.set(value, src.get(value)); + } + return map; + } } export default IntMap; \ No newline at end of file diff --git a/src/mol-model/structure/query/generators.ts b/src/mol-model/structure/query/generators.ts index 305488104df685fbfc81f9779cc712d0970e7bc2..e8d8ab6469692124e43ac8eaf7a846b612e4ac2f 100644 --- a/src/mol-model/structure/query/generators.ts +++ b/src/mol-model/structure/query/generators.ts @@ -45,7 +45,7 @@ function atomGroupsLinear(atomTest: Atom.Predicate): Query { for (let i = 0, _i = unitIds.length; i < _i; i++) { const unitId = unitIds[i]; - l.unit = units[unitId]; + l.unit = units.get(unitId); const set = AtomSet.unitGetByIndex(atoms, i); builder.beginUnit(); @@ -69,7 +69,7 @@ function atomGroupsSegmented({ entityTest, chainTest, residueTest, atomTest }: A for (let i = 0, _i = unitIds.length; i < _i; i++) { const unitId = unitIds[i]; - const unit = units[unitId]; + const unit = units.get(unitId); l.unit = unit; const set = AtomSet.unitGetByIndex(atoms, i); @@ -160,7 +160,7 @@ function atomGroupsGrouped({ entityTest, chainTest, residueTest, atomTest, group for (let i = 0, _i = unitIds.length; i < _i; i++) { const unitId = unitIds[i]; - const unit = units[unitId]; + const unit = units.get(unitId); l.unit = unit; const set = AtomSet.unitGetByIndex(atoms, i); diff --git a/src/mol-model/structure/query/query.ts b/src/mol-model/structure/query/query.ts index 20c569b6d96b66351c2aca3fb2837f056bb47c49..001f1e0e79b3082011d3b60baecfa2a67e88befa 100644 --- a/src/mol-model/structure/query/query.ts +++ b/src/mol-model/structure/query/query.ts @@ -7,5 +7,7 @@ import { Structure } from '../structure' import Selection from './selection' +// TODO: Query { (s: Structure): Computation<Selection> } + interface Query { (s: Structure): Selection } export default Query \ No newline at end of file diff --git a/src/mol-model/structure/query/selection.ts b/src/mol-model/structure/query/selection.ts index c1e0f9fb179d72184e14e492c440bf7d60e6c0b5..8aec9b363f73b2d7e3db98e7732f6dff4ba861eb 100644 --- a/src/mol-model/structure/query/selection.ts +++ b/src/mol-model/structure/query/selection.ts @@ -6,6 +6,7 @@ import Iterator from 'mol-data/iterator' import { HashSet } from 'mol-data/util' +import { IntMap } from 'mol-data/int' import { Structure, Atom, AtomSet } from '../structure' type Selection = @@ -105,20 +106,18 @@ export default Selection function unionUnits(xs: Structure[]): Structure['units'] { let prev = xs[0].units; - let sameModel = true; + let sameUnits = true; for (let i = 1, _i = xs.length; i < _i; i++) { - if (xs[i].units !== prev) sameModel = false; + if (xs[i].units !== prev) sameUnits = false; } - if (sameModel) return prev; + if (sameUnits) return prev; - let ret: any = { ...prev }; + const ret = IntMap.copy(prev); for (let i = 1, _i = xs.length; i < _i; i++) { const units = xs[i].units; - if (units !== prev) { - const keys = Object.keys(units); - for (let j = 0; j < keys.length; j++) ret[keys[j]] = (units as any)[keys[j]]; - } - prev = xs[i]; + if (units !== prev) IntMap.addFrom(ret, units); + prev = units; } + return ret; } diff --git a/src/mol-model/structure/structure/atom.ts b/src/mol-model/structure/structure/atom.ts index 217bbb1eb581c5d869c3c91f70d100e8c598fa8f..55a88dcb633af95e0242d38dae0750397e6c708a 100644 --- a/src/mol-model/structure/structure/atom.ts +++ b/src/mol-model/structure/structure/atom.ts @@ -29,7 +29,7 @@ namespace Atom { export interface Predicate extends Property<boolean> { } export function updateLocation(structure: Structure, l: Location, atom: Atom) { - l.unit = structure.units[unit(atom)]; + l.unit = structure.units.get(unit(atom)); l.atom = index(atom); return l; } diff --git a/src/mol-model/structure/structure/structure.ts b/src/mol-model/structure/structure/structure.ts index 0434bcf8a300b761c7c046fee0410497d641010f..42b97a86832f85524aaa7a63fd4b0008559d0295 100644 --- a/src/mol-model/structure/structure/structure.ts +++ b/src/mol-model/structure/structure/structure.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { OrderedSet, Iterator } from 'mol-data/int' +import { OrderedSet, Iterator, IntMap } from 'mol-data/int' import { UniqueArray } from 'mol-data/util' import SymmetryOperator from 'mol-math/geometry/symmetry-operator' import { Model, Format } from '../model' @@ -14,14 +14,14 @@ import Atom from './atom' interface Structure extends Readonly<{ - units: { readonly [id: number]: Unit }, + units: IntMap<Unit>, atoms: AtomSet }> { } namespace Structure { - export const Empty = { units: {}, atoms: AtomSet.Empty }; + export const Empty: Structure = { units: IntMap.Empty, atoms: AtomSet.Empty }; - export function create(units: Structure['units'], atoms: AtomSet): Structure { + export function create(units: IntMap<Unit>, atoms: AtomSet): Structure { return { units, atoms }; } @@ -36,8 +36,7 @@ namespace Structure { for (let c = 0; c < chains.count; c++) { const unit = Unit.create(model, SymmetryOperator.Default); - builder.addUnit(unit); - builder.setAtoms(unit.id, OrderedSet.ofBounds(chains.segments[c], chains.segments[c + 1])); + builder.add(unit, OrderedSet.ofBounds(chains.segments[c], chains.segments[c + 1])); } return builder.getStructure(); @@ -52,12 +51,12 @@ namespace Structure { } class BuilderImpl implements Builder { - private units = Object.create(null); + private units = IntMap.Mutable<Unit>(); private atoms = AtomSet.Generator(); atomCount = 0; add(unit: Unit, atoms: OrderedSet) { this.addUnit(unit); this.setAtoms(unit.id, atoms); } - addUnit(unit: Unit) { this.units[unit.id] = unit; } + addUnit(unit: Unit) { this.units.set(unit.id, unit); } setAtoms(unitId: number, atoms: OrderedSet) { this.atoms.add(unitId, atoms); this.atomCount += OrderedSet.size(atoms); } getStructure(): Structure { return this.atomCount > 0 ? Structure.create(this.units, this.atoms.getSet()) : Empty; } } @@ -72,9 +71,11 @@ namespace Structure { } export function getModels(s: Structure) { + const { units, atoms } = s; const arr = UniqueArray.create<Model['id'], Model>(); - for (const k of Object.keys(s.units)) { - const u = s.units[+k]; + const ids = AtomSet.unitIds(atoms); + for (let i = 0; i < ids.length; i++) { + const u = units.get(ids[i]); UniqueArray.add(arr, u.model.id, u.model); } return arr.array; diff --git a/src/mol-model/structure/structure/symmetry.ts b/src/mol-model/structure/structure/symmetry.ts index fa1ca3ab1749e4d88b8a6742c04885be94f9e639..ec8de5d4d65548816e97c02f2e7b965ab1237d7b 100644 --- a/src/mol-model/structure/structure/symmetry.ts +++ b/src/mol-model/structure/structure/symmetry.ts @@ -34,7 +34,7 @@ function buildAssemblyImpl(structure: Structure, name: string) { for (const oper of g.operators) { for (let uI = 0, _uI = unitIds.length; uI < _uI; uI++) { - const unit = units[unitIds[uI]]; + const unit = units.get(unitIds[uI]); assembler.add(Unit.create(unit.model, oper), AtomSet.unitGetByIndex(atoms, uI)); } } diff --git a/src/perf-tests/structure.ts b/src/perf-tests/structure.ts index d0f9286bcfa152dfd8dc521708c4659546d53e0a..204ac9df92c9617de2cf7bb227e0d7d7d9b33208 100644 --- a/src/perf-tests/structure.ts +++ b/src/perf-tests/structure.ts @@ -74,7 +74,7 @@ export namespace PropertyAccess { let s = 0; for (let i = 0, _i = unitIds.length; i < _i; i++) { - l.unit = units[unitIds[i]]; + l.unit = units.get(unitIds[i]); const set = AtomSet.unitGetByIndex(atoms, i); @@ -96,7 +96,7 @@ export namespace PropertyAccess { let vA = 0, cC = 0, rC = 0; for (let i = 0, _i = unitIds.length; i < _i; i++) { - const unit = units[unitIds[i]]; + const unit = units.get(unitIds[i]); l.unit = unit; const set = AtomSet.unitGetByIndex(atoms, i); @@ -134,7 +134,7 @@ export namespace PropertyAccess { let s = 0; for (let i = 0, _i = unitIds.length; i < _i; i++) { - const unit = units[unitIds[i]]; + const unit = units.get(unitIds[i]); l.unit = unit; const set = AtomSet.unitGetByIndex(atoms, i); const residuesIt = Segmentation.transientSegments(unit.hierarchy.residueSegments, set); @@ -155,7 +155,7 @@ export namespace PropertyAccess { const l = Atom.Location(); while (atomsIt.hasNext) { const a = atomsIt.move(); - l.unit = units[Atom.unit(a)]; + l.unit = units.get(Atom.unit(a)); l.atom = Atom.index(a); s += p(l); } @@ -200,7 +200,7 @@ export namespace PropertyAccess { for (let i = 0, _i = unitIds.length; i < _i; i++) { const unitId = unitIds[i]; - const unit = units[unitId]; + const unit = units.get(unitId); const set = AtomSet.unitGetByIndex(atoms, i); //const { residueIndex, chainIndex } = unit; const p = unit.conformation.atomId.value;