diff --git a/src/mol-base/collections/column.ts b/src/mol-base/collections/column.ts index 39285a46b073378521f35cbd9bd87ba3afa0b370..7118f96d01a9eb1fe7d14650b420e9cd1444831d 100644 --- a/src/mol-base/collections/column.ts +++ b/src/mol-base/collections/column.ts @@ -81,6 +81,18 @@ namespace Column { return arrayColumn(spec); } + export function ofIntArray(array: ArrayLike<number>) { + return arrayColumn({ array, type: Type.int }); + } + + export function ofFloatArray(array: ArrayLike<number>) { + return arrayColumn({ array, type: Type.float }); + } + + export function ofStringArray(array: ArrayLike<string>) { + return arrayColumn({ array, type: Type.str }); + } + export function window<T>(column: Column<T>, start: number, end: number) { return windowColumn(column, start, end); } diff --git a/src/mol-data/model.ts b/src/mol-data/model.ts index 32e3ce7c6560e3445bd6ccec2f4b3397672fa194..72d66a616d7b28579134782c12cef8a116040280 100644 --- a/src/mol-data/model.ts +++ b/src/mol-data/model.ts @@ -9,6 +9,11 @@ import HierarchyProperties from './model/properties/hierarchy' import ConformationProperties from './model/properties/conformation' import UUID from '../mol-base/utils/uuid' +export interface Version { + hierarchy: UUID, + conformation: UUID +} + /** * Interface to the "source data" of the molecule. * @@ -25,10 +30,7 @@ interface Model extends Readonly<{ conformation: ConformationProperties, // used for diffing. - version: { - data: UUID, - conformation: UUID - }, + version: Version, atomCount: number }> { } diff --git a/src/mol-data/model/builders/mmcif.ts b/src/mol-data/model/builders/mmcif.ts index f72e96514a50235e18c57e5c96f7bffdf6e70128..64143337fd8c2a79f5ed774dd8108c670624c137 100644 --- a/src/mol-data/model/builders/mmcif.ts +++ b/src/mol-data/model/builders/mmcif.ts @@ -88,7 +88,7 @@ function createModel(raw: RawData, data: mmCIF, bounds: Interval, previous?: Mod return { ...previous, conformation: getConformation(data, bounds), - version: { data: previous.version.data, conformation: newUUID() } + version: { hierarchy: previous.version.hierarchy, conformation: newUUID() } }; } @@ -104,7 +104,7 @@ function createModel(raw: RawData, data: mmCIF, bounds: Interval, previous?: Mod model_num: data.atom_site.pdbx_PDB_model_num.value(Interval.start(bounds)), hierarchy: { ...hierarchyData, ...hierarchyKeys, ...hierarchySegments }, conformation: getConformation(data, bounds), - version: { data: newUUID(), conformation: newUUID() }, + version: { hierarchy: newUUID(), conformation: newUUID() }, atomCount: Interval.size(bounds) }; } diff --git a/src/mol-data/model/properties/hierarchy.ts b/src/mol-data/model/properties/hierarchy.ts index d77b2bfc53fee0bc5b584efd3317f18cc0fefa95..ac0c96fa37b75749c53bd367949c99e599725226 100644 --- a/src/mol-data/model/properties/hierarchy.ts +++ b/src/mol-data/model/properties/hierarchy.ts @@ -70,12 +70,12 @@ export interface Keys { isMonotonous: boolean, // assign a key to each residue index. - residueKey: ArrayLike<number>, + residueKey: Column<number>, // assign a key to each chain index - chainKey: ArrayLike<number>, + chainKey: Column<number>, // assigne a key to each chain index // also index to the Entities table. - entityKey: ArrayLike<number>, + entityKey: Column<number>, findEntityKey(id: string): number, findChainKey(entityId: string, label_asym_id: string): number, diff --git a/src/mol-data/model/utils/hierarchy-keys.ts b/src/mol-data/model/utils/hierarchy-keys.ts index 96f4306e9394e8e7170bb4b099121952d6405b1e..ae9f9a176f2101f4a5187c04e767a9a8e1bec29b 100644 --- a/src/mol-data/model/utils/hierarchy-keys.ts +++ b/src/mol-data/model/utils/hierarchy-keys.ts @@ -104,9 +104,9 @@ function create(data: Data, segments: Segments): Keys { return { isMonotonous: isMonotonous && checkMonotonous(entityKey) && checkMonotonous(chainKey) && checkMonotonous(residueKey), - residueKey: residueKey, - chainKey: chainKey, - entityKey: entityKey, + residueKey: Column.ofIntArray(residueKey), + chainKey: Column.ofIntArray(chainKey), + entityKey: Column.ofIntArray(entityKey), findEntityKey, findChainKey, findResidueKey diff --git a/src/mol-data/structure.ts b/src/mol-data/structure.ts index 2a71a70378571b8a98e44cc7b287a43d2e29901f..577211510693ecdaac47380505dc95cdc011c62e 100644 --- a/src/mol-data/structure.ts +++ b/src/mol-data/structure.ts @@ -13,7 +13,7 @@ import * as Base from './structure/base' // TODO: do "single model" version of the structure? export interface Structure extends Readonly<{ - units: Readonly<{ [id: number]: Unit }>, + units: { readonly [id: number]: Unit }, atoms: AtomSet }> { } diff --git a/src/mol-data/structure/atom.ts b/src/mol-data/structure/atom.ts index a15da5213b4fba7bd6cfc1f4e3ea234e5aa14ad3..7a6ef43aa18485e03dcee664642c34c2195f0f9c 100644 --- a/src/mol-data/structure/atom.ts +++ b/src/mol-data/structure/atom.ts @@ -5,9 +5,6 @@ */ import Tuple from '../../mol-base/collections/integer/tuple' -import Structure from '../structure' -import Unit from './unit' -import Model from '../model' /** Atom pointer */ interface Atom { '@type': Tuple['@type'] } @@ -20,19 +17,6 @@ namespace Atom { export const index: (a: Atom) => number = Tuple.snd; export const areEqual: (a: Atom, b: Atom) => boolean = Tuple.areEqual; export const hashCode: (a: Atom) => number = Tuple.hashCode; - - /** All the information required to access atom properties */ - export interface Location { - structure: Structure, - unit: Unit, - model: Model, - atomIndex: number, - residueIndex: number, - chainIndex: number - } - - export interface Property<T> { (location: Atom): T } - export interface Predicate extends Property<boolean> { } } export default Atom \ No newline at end of file diff --git a/src/mol-data/structure/property.ts b/src/mol-data/structure/property.ts new file mode 100644 index 0000000000000000000000000000000000000000..70f9a9d7fedc898960dc46b318e2edebe2b76620 --- /dev/null +++ b/src/mol-data/structure/property.ts @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import Structure from '../structure' +import Atom from './atom' +import Unit from './unit' +import Model from '../model' +import Column from '../../mol-base/collections/column' + +/** Atom pointer */ +interface Property<T> { (location: Property.Location): T } + +namespace Property { + export interface Predicate extends Property<boolean> { } + + /** All the information required to access atom properties */ + export interface Location { + structure: Structure, + unit: Unit, + atomIndex: number, + residueIndex: number, + chainIndex: number + } + + export function create(structure?: Structure, unit?: Unit): Location { + return { + structure: structure!, + unit: unit!, + atomIndex: 0, + residueIndex: 0, + chainIndex: 0 + }; + } + + export function update(l: Location, structure: Structure, atom: Atom) { + const u = structure.units[Atom.unit(atom)]; + const i = Atom.index(atom); + l.structure = structure; + l.unit = u; + l.atomIndex = i; + l.residueIndex = u.residueIndex[i]; + l.chainIndex = u.chainIndex[i]; + } + + export function cachedAtomColumn<T>(col: (model: Model) => Column<T>): Property<T> { + let lastUnit: Unit | undefined = void 0; + let cached: ((row: number) => T) | undefined = void 0; + return function (location) { + if (location.unit === lastUnit && !!cached) return cached(location.atomIndex); + lastUnit = location.unit; + cached = col(lastUnit.model).value; + return cached(location.atomIndex); + }; + } + + // TODO: cached versions of other properties. +} + +export default Property \ No newline at end of file diff --git a/src/mol-data/structure/unit.ts b/src/mol-data/structure/unit.ts index ec81e9a7247f6e254bf01adcf6c5154a2267943d..c23c5f6b0ced2ef09f67154393f406f874b6b513 100644 --- a/src/mol-data/structure/unit.ts +++ b/src/mol-data/structure/unit.ts @@ -16,7 +16,11 @@ interface Unit extends Readonly<{ // Determines the operation applied to this unit. // The transform and and inverse are baked into the "getPosition" function - operator: Operator + operator: Operator, + + // Cache residue and chain indices for fast access. + residueIndex: ArrayLike<number>, + chainIndex: ArrayLike<number> }> { // // returns the untransformed position. Used for spatial queries. // getInvariantPosition(atom: number, slot: Vec3): Vec3 @@ -27,7 +31,8 @@ interface Unit extends Readonly<{ namespace Unit { export function create(model: Model, operator: Operator): Unit { - return { id: nextUnitId(), model, operator }; + const h = model.hierarchy; + return { id: nextUnitId(), model, operator, residueIndex: h.residueSegments.segmentMap, chainIndex: h.chainSegments.segmentMap }; } }