Skip to content
Snippets Groups Projects
Commit 4492bd61 authored by David Sehnal's avatar David Sehnal
Browse files

Working on structure data model

parent 01380f7c
No related branches found
No related tags found
No related merge requests found
......@@ -32,6 +32,20 @@ export interface Chains extends DataTable<Chain> { }
export interface Entity { key: number, id: string }
export interface Entities extends DataTable<Entity> { }
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>,
order: ArrayLike<number>,
flags: ArrayLike<number>,
count: number
}> { }
export type SourceData =
| { kind: 'mmCIF', data: any } // TODO
| { kind: 'custom', data: any } // TODO
......
......@@ -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]> }
}
\ No newline at end of file
/**
* Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { Selector } from './model'
const set = {};
export type Selectors = Selector.Set<typeof set>
\ No newline at end of file
// /**
// * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info.
// *
// * @author David Sehnal <david.sehnal@gmail.com>
// */
// import { Selector } from '../model'
// //import * as Data from '../data'
// //import { Vec3 } from '../../utils/linear-algebra'
// export const atom = {
// name: Selector((m, u) => {
// const unit = m.units[u].structure;
// const atoms = unit.atoms;
// const name = unit.data.atoms.name;
// return a => name[atoms[a]];
// }),
// // position: Selector<Vec3>((m, u) => {
// // const unit = m.units[u].structure;
// // const atoms = unit.atoms;
// // const { positions: { x, y, z } } = m.conformation[u];
// // const { operator: { transform } } = unit;
// // return (atom, position) => {
// // const a = atoms[atom];
// // const p = position || Vec3.zero();
// // Vec3.set(p, x[a], y[a], z[a]);
// // return Vec3.transformMat4(p, p, transform);
// // };
// // }),
// // inversePosition: Selector<Vec3>((m, u) => {
// // const unit = m.structure[u];
// // const atoms = unit.atoms;
// // const { positions: { x, y, z } } = m.conformation[u];
// // const { operator: { inverse } } = unit;
// // return (atom, position) => {
// // const a = atoms[atom];
// // const p = position || Vec3.zero();
// // Vec3.set(p, x[a], y[a], z[a]);
// // return Vec3.transformMat4(p, p, inverse);
// // };
// // })
// }
// export const residue = {
// }
\ No newline at end of file
// /**
// * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info.
// *
// * @author David Sehnal <david.sehnal@gmail.com>
// */
// import { Model, Unit, PropertyGetterProvider } from '../model'
// import * as Data from '../data'
// //import { Vec3 } from '../../utils/linear-algebra'
// // function provider<T>(p: (model: Model) => Property<T>): PropertyProvider<T> {
// // return p;
// // }
// function atomPropertyProvider<T>(property: (ps: Model['structure']['properties']) => ArrayLike<T>): PropertyGetterProvider<T> {
// return m => {
// const a = m.structure.properties.atoms;
// const p = property(m.structure.properties);
// return ({ unit, atom }) => p[a[unit][atom]];
// };
// }
// function unitStructureProvider<T>(p: (structure: Unit.Structure, data: Data.Structure, atom: number) => T): PropertyGetterProvider<T> {
// return m => {
// const units = m.structure.units;
// const data = m.structure.properties.data;
// return ({ unit, atom }) => p(units[unit], data[unit], atom);
// };
// }
// export const atom_site = {
// label_atom_id: atomPropertyProvider(ps => ps.),
// label_comp_id: unitStructureProvider((u, d, a) => d.residues.name[u.atomResidue[a]])
// }
\ No newline at end of file
......@@ -572,8 +572,7 @@ export namespace Vec3 {
export function transformMat4(out: number[], a: number[], m: number[]) {
let x = a[0], y = a[1], z = a[2],
w = m[3] * x + m[7] * y + m[11] * z + m[15];
w = w || 1.0;
w = (m[3] * x + m[7] * y + m[11] * z + m[15]) || 1.0;
out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment