|
@@ -5,22 +5,32 @@
|
|
|
*/
|
|
|
|
|
|
import * as Data from './data'
|
|
|
+import { Selectors } from './selectors'
|
|
|
import { Vec3, Mat4 } from '../utils/linear-algebra'
|
|
|
|
|
|
+let _uid = 0;
|
|
|
+/** Model-related unique identifiers */
|
|
|
+export function getUid() { return _uid++; }
|
|
|
|
|
|
/** Unit = essentially a list of residues (usually a chain) */
|
|
|
export interface Unit extends Readonly<{
|
|
|
+ operator: Unit.Operator,
|
|
|
/** The static part (essentially residue annotations) */
|
|
|
- structre: Unit.Structure,
|
|
|
+ structure: Unit.Structure,
|
|
|
/** 3D arrangement that often changes with time. */
|
|
|
- conformation: Unit.Conformation
|
|
|
+ conformation: Unit.Conformation,
|
|
|
+ /** Position of i-th atom. Special function for this because it's the only one that depends on "operator" */
|
|
|
+ atomPosition(i: number, p: Vec3): Vec3,
|
|
|
+ /** Property access */
|
|
|
+ selectors: Selectors
|
|
|
}> { }
|
|
|
|
|
|
export namespace Unit {
|
|
|
export interface Structure extends Readonly<{
|
|
|
+ /** A globally unique identifier for this instance (to easily determine unique structures within a model) */
|
|
|
+ id: number,
|
|
|
+ /** Source data for this structure */
|
|
|
data: Data.Structure,
|
|
|
- /** A globally unique number for this instance (to easily determine unique structures within a model) */
|
|
|
- key: number,
|
|
|
/** Reference to the data.entities table */
|
|
|
entity: number,
|
|
|
/** Reference to the data.chains table */
|
|
@@ -29,32 +39,40 @@ export namespace Unit {
|
|
|
residues: ArrayLike<number>,
|
|
|
/** Offsets of atoms in the residue layer. start = offsets[i], endExclusive = offsets[i + 1] */
|
|
|
atomOffsets: ArrayLike<number>,
|
|
|
+ /** Indices into data.atoms table */
|
|
|
+ atoms: ArrayLike<number>
|
|
|
/** Index of a residue in the corresponding residues array. */
|
|
|
- atomResidue: number
|
|
|
+ atomResidue: ArrayLike<number>
|
|
|
}> { }
|
|
|
|
|
|
- export interface Bonds extends Readonly<{
|
|
|
- /**
|
|
|
- * Where bonds for atom A start and end.
|
|
|
- * Start at idx, end at idx + 1
|
|
|
- */
|
|
|
- offset: ArrayLike<number>,
|
|
|
- neighbor: ArrayLike<number>,
|
|
|
+ export interface Conformation extends Readonly<{
|
|
|
+ /** A globally unique identifier for this instance (to easily determine unique structures within a model) */
|
|
|
+ id: number,
|
|
|
|
|
|
- order: ArrayLike<number>,
|
|
|
- flags: ArrayLike<number>,
|
|
|
+ positions: Data.Positions,
|
|
|
|
|
|
- count: number
|
|
|
- }> { }
|
|
|
+ /** Per residue secondary structure assignment. */
|
|
|
+ secondaryStructure: Data.SecondaryStructures,
|
|
|
|
|
|
- export interface Conformation extends Readonly<{
|
|
|
- positions: Data.Positions
|
|
|
- spatialLookup: any, // TODO
|
|
|
- boundingSphere: { readonly center: Vec3, readonly radius: number },
|
|
|
- secodaryStructure: Data.SecondaryStructures,
|
|
|
- bonds: Bonds
|
|
|
+ '@spatialLookup': any, // TODO
|
|
|
+ '@boundingSphere': Readonly<{ center: Vec3, radius: number }>,
|
|
|
+ '@bonds': Data.Bonds
|
|
|
}> { }
|
|
|
|
|
|
+ export namespace Conformation {
|
|
|
+ export function spatialLookup(conformation: Conformation): any {
|
|
|
+ throw 'not implemented'
|
|
|
+ }
|
|
|
+
|
|
|
+ export function boundingSphere(conformation: Conformation): any {
|
|
|
+ throw 'not implemented'
|
|
|
+ }
|
|
|
+
|
|
|
+ export function bonds(conformation: Conformation): any {
|
|
|
+ throw 'not implemented'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
export type OperatorKind =
|
|
|
| { kind: 'identity' }
|
|
|
| { kind: 'symmetry', id: string, hkl: Vec3 }
|
|
@@ -66,31 +84,38 @@ export namespace Unit {
|
|
|
inverse: Mat4
|
|
|
}> { }
|
|
|
|
|
|
- export interface Lookup3D {
|
|
|
+ export interface SpatialLookup {
|
|
|
// TODO
|
|
|
}
|
|
|
}
|
|
|
|
|
|
export interface Model extends Readonly<{
|
|
|
- index: number,
|
|
|
+ units: Unit[],
|
|
|
+
|
|
|
+ structure: { [id: number]: Unit.Structure },
|
|
|
+ conformation: { [id: number]: Unit.Conformation },
|
|
|
|
|
|
- structure: Model.Structure,
|
|
|
- conformation: Model.Conformation
|
|
|
+ '@unitLookup'?: Unit.SpatialLookup,
|
|
|
+ /** bonds between units */
|
|
|
+ '@unitBonds'?: Data.Bonds
|
|
|
}> { }
|
|
|
|
|
|
export namespace Model {
|
|
|
- // TODO: model residues between units
|
|
|
- // use a map of map of bonds?
|
|
|
+ export function unitLookup(model: Model): Unit.SpatialLookup {
|
|
|
+ throw 'not implemented';
|
|
|
+ }
|
|
|
|
|
|
- export interface Structure extends Readonly<{
|
|
|
- operators: Unit.Operator[],
|
|
|
- units: Unit.Structure[]
|
|
|
- }> { }
|
|
|
+ export function unitBonds(model: Model): Data.Bonds {
|
|
|
+ throw 'not implemented';
|
|
|
+ }
|
|
|
|
|
|
- export interface Conformation extends Readonly<{
|
|
|
- units: Unit.Conformation[],
|
|
|
- spatialLookup: Unit.Lookup3D
|
|
|
- }> { }
|
|
|
+ export function join(a: Model, b: Model): Model {
|
|
|
+ return {
|
|
|
+ units: [...a.units, ...b.units],
|
|
|
+ structure: { ...a.structure, ...b.structure },
|
|
|
+ conformation: { ...a.conformation, ...b.conformation }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
export namespace Atom {
|
|
@@ -100,30 +125,49 @@ export namespace Atom {
|
|
|
* a both number[] and Float64Array(), making it much
|
|
|
* more efficient than storing an array of objects.
|
|
|
*/
|
|
|
- export type Reference = number
|
|
|
- export interface Location { unit: number, atom: number }
|
|
|
+ export type PackedReference = number
|
|
|
+ export interface Reference { unit: number, atom: number }
|
|
|
+ export type Selection = ArrayLike<PackedReference>
|
|
|
|
|
|
const { _uint32, _float64 } = (function() {
|
|
|
const data = new ArrayBuffer(8);
|
|
|
return { _uint32: new Uint32Array(data), _float64: new Float64Array(data) };
|
|
|
}());
|
|
|
|
|
|
- export function emptyLocation(): Location { return { unit: 0, atom: 0 }; }
|
|
|
+ export function emptyLocation(): Reference { return { unit: 0, atom: 0 }; }
|
|
|
|
|
|
- export function getRef(location: Location) {
|
|
|
+ export function packRef(location: Reference) {
|
|
|
_uint32[0] = location.unit;
|
|
|
_uint32[1] = location.atom;
|
|
|
return _float64[0];
|
|
|
}
|
|
|
|
|
|
- export function getLocation(ref: Reference) {
|
|
|
- return updateLocation(ref, emptyLocation());
|
|
|
+ export function unpackRef(ref: PackedReference) {
|
|
|
+ return updateRef(ref, emptyLocation());
|
|
|
}
|
|
|
|
|
|
- export function updateLocation(ref: Reference, location: Location): Location {
|
|
|
+ export function updateRef(ref: PackedReference, location: Reference): Reference {
|
|
|
_float64[0] = ref;
|
|
|
location.unit = _uint32[0];
|
|
|
location.atom = _uint32[1];
|
|
|
return location;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+export interface Selector<T> {
|
|
|
+ '@type': T,
|
|
|
+ create(m: Model, u: number): (a: number, v?: T) => T
|
|
|
+}
|
|
|
+
|
|
|
+export function Selector<T>(create: (m: Model, u: number) => (a: number, v?: T) => T): Selector<T> {
|
|
|
+ return { create } as Selector<T>;
|
|
|
+}
|
|
|
+
|
|
|
+export namespace Selector {
|
|
|
+ export type Field<T> = (a: number, v?: T) => T;
|
|
|
+
|
|
|
+ export type Category = { [s: string]: Selector<any> };
|
|
|
+ export type Unit<C extends Category> = { [F in keyof C]: Field<C[F]['@type']> }
|
|
|
+
|
|
|
+ export type Set<S extends { [n: string]: Category }> = { [C in keyof S]: Unit<S[C]> }
|
|
|
+}
|