From 720b23c174ecf14ee092e3cbdb85bb57806c355b Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Sat, 28 Oct 2017 13:27:46 +0200 Subject: [PATCH] structure data model --- .../collections/_spec/segmentation.spec.ts | 13 +- .../collections/_spec/sorted-array.spec.ts | 2 +- src/mol-base/collections/column.ts | 25 +++- .../collections/integer/impl/segmentation.ts | 19 ++- .../collections/integer/segmentation.ts | 11 +- .../collections/integer/sorted-array.ts | 4 +- src/mol-data/_spec/atom-set.spec.ts | 30 ++-- src/mol-data/atom-set.ts | 23 ++-- src/mol-data/atom-set/base.ts | 108 +++++++-------- src/mol-data/atom-set/builder.ts | 2 +- src/mol-data/atom-set/properties.ts | 6 + src/mol-data/atom.ts | 21 +++ src/mol-data/model/formats.ts | 4 +- src/mol-data/model/formats/mmcif.ts | 70 +++++++++- .../connected-components.ts => base.ts} | 0 src/mol-data/structure/data.ts | 65 --------- src/mol-data/structure/selectors/common.ts | 47 ------- src/mol-data/structure/selectors/mmcif.ts | 34 ----- .../structure/topology/secondary-structure.ts | 128 ------------------ src/mol-io/reader/{cif/index.ts => cif.ts} | 12 +- src/perf-tests/sets.ts | 11 +- src/script.ts | 9 +- 22 files changed, 258 insertions(+), 386 deletions(-) create mode 100644 src/mol-data/atom-set/properties.ts create mode 100644 src/mol-data/atom.ts rename src/mol-data/structure/{topology/connected-components.ts => base.ts} (100%) delete mode 100644 src/mol-data/structure/data.ts delete mode 100644 src/mol-data/structure/selectors/common.ts delete mode 100644 src/mol-data/structure/selectors/mmcif.ts delete mode 100644 src/mol-data/structure/topology/secondary-structure.ts rename src/mol-io/reader/{cif/index.ts => cif.ts} (53%) diff --git a/src/mol-base/collections/_spec/segmentation.spec.ts b/src/mol-base/collections/_spec/segmentation.spec.ts index 27b3708fd..005b0bbe8 100644 --- a/src/mol-base/collections/_spec/segmentation.spec.ts +++ b/src/mol-base/collections/_spec/segmentation.spec.ts @@ -7,17 +7,26 @@ import OrderedSet from '../integer/ordered-set' import Interval from '../integer/interval' import Segmentation from '../integer/segmentation' -import SortedArray from '../integer/sorted-array' describe('segments', () => { const data = OrderedSet.ofSortedArray([4, 9, 10, 11, 14, 15, 16]); - const segs = Segmentation.create(SortedArray.ofSortedArray([0, 4, 10, 12, 13, 15, 25]), []) + const segs = Segmentation.create([0, 4, 10, 12, 13, 15, 25]); + + it('size', () => expect(Segmentation.count(segs)).toBe(6)); it('project', () => { const p = Segmentation.projectValue(segs, data, 4); expect(p).toBe(Interval.ofBounds(0, 2)) }); + it('map', () => { + const segs = Segmentation.create([1, 2, 3]); + expect(segs.segmentMap).toEqual(new Int32Array([0, 1])); + expect(segs.offset).toEqual(1); + expect(Segmentation.getSegment(segs, 1)).toBe(0); + expect(Segmentation.getSegment(segs, 2)).toBe(1); + }) + it('iteration', () => { const it = Segmentation.segments(segs, data); diff --git a/src/mol-base/collections/_spec/sorted-array.spec.ts b/src/mol-base/collections/_spec/sorted-array.spec.ts index 9a8871e64..7aa731c9d 100644 --- a/src/mol-base/collections/_spec/sorted-array.spec.ts +++ b/src/mol-base/collections/_spec/sorted-array.spec.ts @@ -37,7 +37,7 @@ describe('sortedArray', () => { test('getAt', SortedArray.getAt(a2468, 1), 4); test('areEqual', SortedArray.areEqual(a2468, a2468), true); - test('areEqual1', SortedArray.areEqual(a2468, SortedArray.create([4, 2, 8, 6])), true); + test('areEqual1', SortedArray.areEqual(a2468, SortedArray.ofUnsortedArray([4, 2, 8, 6])), true); test('areEqual2', SortedArray.areEqual(a1234, a2468), false); test('predIndex1', SortedArray.findPredecessorIndex(a1234, 5), 4); diff --git a/src/mol-base/collections/column.ts b/src/mol-base/collections/column.ts index acedf1d92..0a9ec96f6 100644 --- a/src/mol-base/collections/column.ts +++ b/src/mol-base/collections/column.ts @@ -35,6 +35,7 @@ export interface Column<T> { } export function UndefinedColumn<T extends ColumnType>(rowCount: number, type: T): Column<T['@type']> { + const v = type.isString ? '' : 0; const value: Column<T['@type']>['value'] = type.isString ? row => '' : row => 0; return { '@type': type, @@ -44,7 +45,7 @@ export function UndefinedColumn<T extends ColumnType>(rowCount: number, type: T) isValueDefined: row => false, toArray: params => { const { array } = createArray(rowCount, params); - for (let i = 0, _i = array.length; i < _i; i++) array[i] = value(0) + for (let i = 0, _i = array.length; i < _i; i++) array[i] = v; return array; }, stringEquals: (row, value) => !value, @@ -52,6 +53,28 @@ export function UndefinedColumn<T extends ColumnType>(rowCount: number, type: T) } } +export function SingleValueColumn<T extends ColumnType>(v: T['@type'], rowCount: number, type: T): Column<T['@type']> { + const value: Column<T['@type']>['value'] = row => v; + return { + '@type': type, + isDefined: true, + rowCount, + value, + isValueDefined: row => false, + toArray: params => { + const { array } = createArray(rowCount, params); + for (let i = 0, _i = array.length; i < _i; i++) array[i] = v; + return array; + }, + stringEquals: type.isString + ? (row, value) => value === v + : type.isScalar + ? (row, value) => +value === v + : (row, value) => false, + areValuesEqual: (rowA, rowB) => true + } +} + export interface ArrayColumnSpec<T extends ColumnType> { array: ArrayLike<T['@type']>, type: T, diff --git a/src/mol-base/collections/integer/impl/segmentation.ts b/src/mol-base/collections/integer/impl/segmentation.ts index 542b4daf2..e24f4757d 100644 --- a/src/mol-base/collections/integer/impl/segmentation.ts +++ b/src/mol-base/collections/integer/impl/segmentation.ts @@ -10,15 +10,22 @@ import Interval from '../interval' import SortedArray from '../sorted-array' import Segs from '../segmentation' -type Segmentation = { segments: OrderedSet, segmentIndex: ArrayLike<number> } +type Segmentation = { segments: SortedArray, segmentMap: ArrayLike<number>, offset: number, count: number } -export function create(segments: SortedArray, segmentIndex: ArrayLike<number>): Segmentation { - return { segments, segmentIndex }; +export function create(values: ArrayLike<number>): Segmentation { + const segments = SortedArray.ofSortedArray(values); + const min = SortedArray.min(segments), max = SortedArray.max(segments); + const segmentMap = new Int32Array(max - min); + for (let i = 0, _i = values.length - 1; i < _i; i++) { + for (let j = values[i] - min, _j = values[i + 1] - min; j < _j; j++) { + segmentMap[j] = i; + } + } + return { segments, segmentMap, offset: min, count: values.length - 1 }; } -export function getSegment({ segmentIndex }: Segmentation, value: number) { - return segmentIndex[value]; -} +export function count({ count }: Segmentation) { return count; } +export function getSegment({ segmentMap, offset }: Segmentation, value: number) { return segmentMap[value - offset]; } export function projectValue({ segments }: Segmentation, set: OrderedSet, value: number): Interval { const last = OrderedSet.max(segments); diff --git a/src/mol-base/collections/integer/segmentation.ts b/src/mol-base/collections/integer/segmentation.ts index 6225478c9..5d1e6c3bb 100644 --- a/src/mol-base/collections/integer/segmentation.ts +++ b/src/mol-base/collections/integer/segmentation.ts @@ -7,20 +7,25 @@ import Iterator from '../iterator' import Interval from './interval' import OrderedSet from './ordered-set' -import SortedArray from './sorted-array' import * as Impl from './impl/segmentation' namespace Segmentation { export interface Segment { index: number, start: number, end: number } - export const create: (segs: SortedArray, segIndex: ArrayLike<number>) => Segmentation = Impl.create as any; + export const create: (segs: ArrayLike<number>) => Segmentation = Impl.create as any; + export const count: (segs: Segmentation) => number = Impl.count as any; export const getSegment: (segs: Segmentation, value: number) => number = Impl.getSegment as any; export const projectValue: (segs: Segmentation, set: OrderedSet, value: number) => Interval = Impl.projectValue as any; export const segments: (segs: Segmentation, set: OrderedSet, range?: Interval) => Iterator<Segment> = Impl.segments as any; } -interface Segmentation { '@type': 'segmentation' } +interface Segmentation { + '@type': 'segmentation', + readonly segmentMap: ArrayLike<number>, + readonly offset: number, + readonly count: number +} export default Segmentation \ No newline at end of file diff --git a/src/mol-base/collections/integer/sorted-array.ts b/src/mol-base/collections/integer/sorted-array.ts index a98b9a0f9..d30f572c8 100644 --- a/src/mol-base/collections/integer/sorted-array.ts +++ b/src/mol-base/collections/integer/sorted-array.ts @@ -8,9 +8,7 @@ import * as Impl from './impl/sorted-array' import Interval from './interval' namespace SortedArray { - /** Create interval [min, max] */ - export const create: (xs: ArrayLike<number>) => SortedArray = Impl.ofUnsortedArray as any; - /** Create interval [min, max) */ + export const ofUnsortedArray: (xs: ArrayLike<number>) => SortedArray = Impl.ofUnsortedArray as any; export const ofSortedArray: (xs: ArrayLike<number>) => SortedArray = Impl.ofSortedArray as any; export const is: (v: any) => v is Interval = Impl.is as any; diff --git a/src/mol-data/_spec/atom-set.spec.ts b/src/mol-data/_spec/atom-set.spec.ts index f5c1d8e78..2c265acc9 100644 --- a/src/mol-data/_spec/atom-set.spec.ts +++ b/src/mol-data/_spec/atom-set.spec.ts @@ -4,15 +4,15 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import IntTuple from '../../mol-base/collections/integer/tuple' import OrderedSet from '../../mol-base/collections/integer/ordered-set' import AtomSet from '../atom-set' +import Atom from '../atom' describe('atom set', () => { - const p = (i: number, j: number) => IntTuple.create(i, j); + const p = (i: number, j: number) => Atom.create(i, j); - function setToPairs(set: AtomSet): ArrayLike<IntTuple> { - const ret: IntTuple[] = []; + function setToPairs(set: AtomSet): ArrayLike<Atom> { + const ret: Atom[] = []; const it = AtomSet.atoms(set); while (it.hasNext) { ret[ret.length] = it.move(); @@ -23,9 +23,9 @@ describe('atom set', () => { it('singleton pair', () => { const set = AtomSet.create(p(10, 11)); expect(setToPairs(set)).toEqual([p(10, 11)]); - expect(AtomSet.hasAtom(set, p(10, 11))).toBe(true); - expect(AtomSet.hasAtom(set, p(11, 11))).toBe(false); - expect(AtomSet.getAtomAt(set, 0)).toBe(p(10, 11)); + expect(AtomSet.atomHas(set, p(10, 11))).toBe(true); + expect(AtomSet.atomHas(set, p(11, 11))).toBe(false); + expect(AtomSet.atomGetAt(set, 0)).toBe(p(10, 11)); expect(AtomSet.atomCount(set)).toBe(1); }); @@ -42,16 +42,16 @@ describe('atom set', () => { const ret = [p(1, 4), p(1, 6), p(1, 7), p(3, 0), p(3, 1)]; expect(AtomSet.atomCount(set)).toBe(ret.length); expect(setToPairs(set)).toEqual([p(1, 4), p(1, 6), p(1, 7), p(3, 0), p(3, 1)]); - expect(AtomSet.hasAtom(set, p(10, 11))).toBe(false); - expect(AtomSet.hasAtom(set, p(3, 0))).toBe(true); - expect(AtomSet.hasAtom(set, p(1, 7))).toBe(true); + expect(AtomSet.atomHas(set, p(10, 11))).toBe(false); + expect(AtomSet.atomHas(set, p(3, 0))).toBe(true); + expect(AtomSet.atomHas(set, p(1, 7))).toBe(true); for (let i = 0; i < AtomSet.atomCount(set); i++) { - expect(IntTuple.areEqual(AtomSet.getAtomAt(set, i), ret[i])).toBe(true); + expect(Atom.areEqual(AtomSet.atomGetAt(set, i), ret[i])).toBe(true); } }); it('element at / index of', () => { - const control: IntTuple[] = []; + const control: Atom[] = []; const sets = Object.create(null); for (let i = 1; i < 10; i++) { const set = []; @@ -63,11 +63,11 @@ describe('atom set', () => { } const ms = AtomSet.create(sets); for (let i = 0; i < control.length; i++) { - expect(IntTuple.areEqual(AtomSet.getAtomAt(ms, i), control[i])).toBe(true); + expect(Atom.areEqual(AtomSet.atomGetAt(ms, i), control[i])).toBe(true); } for (let i = 0; i < control.length; i++) { - expect(AtomSet.indexOfAtom(ms, control[i])).toBe(i); + expect(AtomSet.atomIndexOf(ms, control[i])).toBe(i); } }); @@ -129,6 +129,7 @@ describe('atom set', () => { const b = AtomSet.create([p(10, 3), p(0, 1), p(0, 6), p(4, 2)]); const c = AtomSet.create([p(1, 3)]); const d = AtomSet.create([p(2, 3)]); + const e = AtomSet.create([p(0, 2)]); expect(setToPairs(AtomSet.subtract(a, a))).toEqual([]); expect(setToPairs(AtomSet.subtract(a, a1))).toEqual([]); expect(setToPairs(AtomSet.subtract(a, b))).toEqual([p(0, 2), p(1, 3)]); @@ -136,6 +137,7 @@ describe('atom set', () => { expect(setToPairs(AtomSet.subtract(a, c))).toEqual([p(0, 1), p(0, 2), p(0, 6)]); expect(setToPairs(AtomSet.subtract(c, a))).toEqual([]); expect(setToPairs(AtomSet.subtract(d, a))).toEqual([p(2, 3)]); + expect(setToPairs(AtomSet.subtract(a, e))).toEqual([p(0, 1), p(0, 6), p(1, 3)]); }); it('union', () => { diff --git a/src/mol-data/atom-set.ts b/src/mol-data/atom-set.ts index d638c30fc..7f3fd55ab 100644 --- a/src/mol-data/atom-set.ts +++ b/src/mol-data/atom-set.ts @@ -6,7 +6,7 @@ import OrderedSet from '../mol-base/collections/integer/ordered-set' import Iterator from '../mol-base/collections/iterator' -import Tuple from '../mol-base/collections/integer/tuple' +import Atom from './atom' import * as Base from './atom-set/base' import createBuilder from './atom-set/builder' @@ -14,22 +14,21 @@ import createBuilder from './atom-set/builder' namespace AtomSet { export const Empty: AtomSet = Base.Empty as any; - export const create: (data: Tuple | ArrayLike<Tuple> | Tuple | { [id: number]: OrderedSet }) => AtomSet = Base.create as any; + export const create: (data: Atom | ArrayLike<Atom> | { [unitId: number]: OrderedSet }) => AtomSet = Base.create as any; - export const units: (set: AtomSet) => OrderedSet = Base.getKeys as any; export const unitCount: (set: AtomSet) => number = Base.keyCount as any; - export const hasUnit: (set: AtomSet, id: number) => boolean = Base.hasKey as any; - export const getUnitId: (set: AtomSet, i: number) => number = Base.getKey as any; + export const unitIds: (set: AtomSet) => OrderedSet = Base.getKeys as any; + export const unitHas: (set: AtomSet, id: number) => boolean = Base.hasKey as any; + export const unitGetId: (set: AtomSet, i: number) => number = Base.getKey as any; - export const getByKey: (set: AtomSet, key: number) => OrderedSet = Base.getByKey as any; - export const getByIndex: (set: AtomSet, i: number) => OrderedSet = Base.getByIndex as any; - - export const hasAtom: (set: AtomSet, x: Tuple) => boolean = Base.hasTuple as any; - export const indexOfAtom: (set: AtomSet, x: Tuple) => number = Base.indexOf as any; - export const getAtomAt: (set: AtomSet, i: number) => Tuple = Base.getAt as any; - export const atoms: (set: AtomSet) => Iterator<Tuple> = Base.values as any; + export const unitGetById: (set: AtomSet, key: number) => OrderedSet = Base.getByKey as any; + export const unitGetByIndex: (set: AtomSet, i: number) => OrderedSet = Base.getByIndex as any; export const atomCount: (set: AtomSet) => number = Base.size as any; + export const atomHas: (set: AtomSet, x: Atom) => boolean = Base.hasAtom as any; + export const atomIndexOf: (set: AtomSet, x: Atom) => number = Base.indexOf as any; + export const atomGetAt: (set: AtomSet, i: number) => Atom = Base.getAt as any; + export const atoms: (set: AtomSet) => Iterator<Atom> = Base.values as any; export const hashCode: (set: AtomSet) => number = Base.hashCode as any; export const areEqual: (a: AtomSet, b: AtomSet) => boolean = Base.areEqual as any; diff --git a/src/mol-data/atom-set/base.ts b/src/mol-data/atom-set/base.ts index eeec45449..e457f8dc9 100644 --- a/src/mol-data/atom-set/base.ts +++ b/src/mol-data/atom-set/base.ts @@ -6,21 +6,21 @@ import OrderedSet from '../../mol-base/collections/integer/ordered-set' import Iterator from '../../mol-base/collections/iterator' -import Tuple from '../../mol-base/collections/integer/tuple' import Interval from '../../mol-base/collections/integer/interval' import { sortArray } from '../../mol-base/collections/sort' import { hash1 } from '../../mol-base/collections/hash-functions' +import Atom from '../atom' /** Long and painful implementation starts here */ export interface AtomSetElements { [id: number]: OrderedSet, offsets: number[], hashCode: number, keys: OrderedSet } -export type AtomSetImpl = Tuple | AtomSetElements +export type AtomSetImpl = Atom | AtomSetElements export const Empty: AtomSetImpl = { offsets: [0], hashCode: 0, keys: OrderedSet.Empty }; -export function create(data: Tuple | ArrayLike<Tuple> | { [id: number]: OrderedSet }): AtomSetImpl { - if (typeof data === 'number' || Tuple.is(data)) return data; - if (isArrayLike(data)) return ofTuples(data); +export function create(data: Atom | ArrayLike<Atom> | { [id: number]: OrderedSet }): AtomSetImpl { + if (typeof data === 'number' || Atom.is(data)) return data; + if (isArrayLike(data)) return ofAtoms(data); return ofObject(data as { [id: number]: OrderedSet }); } @@ -39,42 +39,42 @@ export function keyCount(set: AtomSetImpl): number { } export function hasKey(set: AtomSetImpl, key: number): boolean { - if (typeof set === 'number') return Tuple.fst(set) === key; + if (typeof set === 'number') return Atom.unit(set) === key; return OrderedSet.has((set as AtomSetElements).keys, key); } export function getKey(set: AtomSetImpl, index: number): number { - if (typeof set === 'number') return Tuple.fst(set); + if (typeof set === 'number') return Atom.unit(set); return OrderedSet.getAt((set as AtomSetElements).keys, index); } -export function hasTuple(set: AtomSetImpl, t: Tuple): boolean { - if (typeof set === 'number') return Tuple.areEqual(t, set); - const unit = Tuple.fst(t); +export function hasAtom(set: AtomSetImpl, t: Atom): boolean { + if (typeof set === 'number') return Atom.areEqual(t, set); + const unit = Atom.unit(t); return OrderedSet.has((set as AtomSetElements).keys, unit) - ? OrderedSet.has((set as AtomSetElements)[unit], Tuple.snd(t)) : false; + ? OrderedSet.has((set as AtomSetElements)[unit], Atom.index(t)) : false; } export function getByKey(set: AtomSetImpl, key: number): OrderedSet { if (typeof set === 'number') { - return Tuple.fst(set) === key ? OrderedSet.ofSingleton(Tuple.snd(set)) : OrderedSet.Empty; + return Atom.unit(set) === key ? OrderedSet.ofSingleton(Atom.index(set)) : OrderedSet.Empty; } return OrderedSet.has((set as AtomSetElements).keys, key) ? (set as AtomSetElements)[key] : OrderedSet.Empty; } export function getByIndex(set: AtomSetImpl, index: number): OrderedSet { - if (typeof set === 'number') return index === 0 ? OrderedSet.ofSingleton(Tuple.snd(set)) : OrderedSet.Empty; + if (typeof set === 'number') return index === 0 ? OrderedSet.ofSingleton(Atom.index(set)) : OrderedSet.Empty; const key = OrderedSet.getAt((set as AtomSetElements).keys, index); return (set as AtomSetElements)[key] || OrderedSet.Empty; } -export function getAt(set: AtomSetImpl, i: number): Tuple { +export function getAt(set: AtomSetImpl, i: number): Atom { if (typeof set === 'number') return set; return getAtE(set as AtomSetElements, i); } -export function indexOf(set: AtomSetImpl, t: Tuple) { - if (typeof set === 'number') return Tuple.areEqual(set, t) ? 0 : -1; +export function indexOf(set: AtomSetImpl, t: Atom) { + if (typeof set === 'number') return Atom.areEqual(set, t) ? 0 : -1; return indexOfE(set as AtomSetElements, t); } @@ -85,14 +85,14 @@ export function size(set: AtomSetImpl) { } export function hashCode(set: AtomSetImpl) { - if (typeof set === 'number') return Tuple.hashCode(set); + if (typeof set === 'number') return Atom.hashCode(set); if ((set as AtomSetElements).hashCode !== -1) return (set as AtomSetElements).hashCode; return computeHash((set as AtomSetElements)); } export function areEqual(a: AtomSetImpl, b: AtomSetImpl) { if (typeof a === 'number') { - if (typeof b === 'number') return Tuple.areEqual(a, b); + if (typeof b === 'number') return Atom.areEqual(a, b); return false; } if (typeof b === 'number') return false; @@ -101,7 +101,7 @@ export function areEqual(a: AtomSetImpl, b: AtomSetImpl) { export function areIntersecting(a: AtomSetImpl, b: AtomSetImpl) { if (typeof a === 'number') { - if (typeof b === 'number') return Tuple.areEqual(a, b); + if (typeof b === 'number') return Atom.areEqual(a, b); return areIntersectingNE(a, b as AtomSetElements); } if (typeof b === 'number') return areIntersectingNE(b, a as AtomSetElements); @@ -110,7 +110,7 @@ export function areIntersecting(a: AtomSetImpl, b: AtomSetImpl) { export function intersect(a: AtomSetImpl, b: AtomSetImpl) { if (typeof a === 'number') { - if (typeof b === 'number') return Tuple.areEqual(a, b) ? a : Empty; + if (typeof b === 'number') return Atom.areEqual(a, b) ? a : Empty; return intersectNE(a, b as AtomSetElements); } if (typeof b === 'number') return intersectNE(b, a as AtomSetElements); @@ -119,7 +119,7 @@ export function intersect(a: AtomSetImpl, b: AtomSetImpl) { export function subtract(a: AtomSetImpl, b: AtomSetImpl) { if (typeof a === 'number') { - if (typeof b === 'number') return Tuple.areEqual(a, b) ? Empty : a; + if (typeof b === 'number') return Atom.areEqual(a, b) ? Empty : a; return subtractNE(a, b as AtomSetElements); } if (typeof b === 'number') return subtractEN(a as AtomSetElements, b); @@ -134,7 +134,7 @@ export function unionMany(sets: ArrayLike<AtomSetImpl>) { return findUnion(sets); } -class ElementsIterator implements Iterator<Tuple> { +class ElementsIterator implements Iterator<Atom> { private unit: number = 0; private keyCount: number; private setIndex = -1; @@ -145,8 +145,8 @@ class ElementsIterator implements Iterator<Tuple> { hasNext: boolean = false; move() { - if (!this.hasNext) return Tuple.Zero; - const ret = Tuple.create(this.unit, OrderedSet.getAt(this.currentSet, this.currentIndex++)); + if (!this.hasNext) return Atom.Zero; + const ret = Atom.create(this.unit, OrderedSet.getAt(this.currentSet, this.currentIndex++)); if (this.currentIndex >= this.currentSize) this.advance(); return ret; } @@ -170,12 +170,12 @@ class ElementsIterator implements Iterator<Tuple> { } } -export function values(set: AtomSetImpl): Iterator<Tuple> { - if (typeof set === 'number') return Iterator.Value(set as Tuple); +export function values(set: AtomSetImpl): Iterator<Atom> { + if (typeof set === 'number') return Iterator.Value(set as Atom); return new ElementsIterator(set as AtomSetElements); } -function isArrayLike(x: any): x is ArrayLike<Tuple> { +function isArrayLike(x: any): x is ArrayLike<Atom> { return x && (typeof x.length === 'number' && (x instanceof Array || !!x.buffer)); } @@ -188,7 +188,7 @@ function ofObject(data: { [id: number]: OrderedSet }) { if (!keys.length) return Empty; if (keys.length === 1) { const set = data[keys[0]]; - if (OrderedSet.size(set) === 1) return Tuple.create(keys[0], OrderedSet.getAt(set, 0)); + if (OrderedSet.size(set) === 1) return Atom.create(keys[0], OrderedSet.getAt(set, 0)); } return ofObject1(keys, data); } @@ -197,7 +197,7 @@ function ofObject1(keys: number[], data: { [id: number]: OrderedSet }) { if (keys.length === 1) { const k = keys[0]; const set = data[k]; - if (OrderedSet.size(set) === 1) return Tuple.create(k, OrderedSet.getAt(set, 0)); + if (OrderedSet.size(set) === 1) return Atom.create(k, OrderedSet.getAt(set, 0)); } sortArray(keys); return _createObjectOrdered(OrderedSet.ofSortedArray(keys), data); @@ -207,7 +207,7 @@ function ofObjectOrdered(keys: OrderedSet, data: { [id: number]: OrderedSet }) { if (OrderedSet.size(keys) === 1) { const k = OrderedSet.getAt(keys, 0); const set = data[k]; - if (OrderedSet.size(set) === 1) return Tuple.create(k, OrderedSet.getAt(set, 0)); + if (OrderedSet.size(set) === 1) return Atom.create(k, OrderedSet.getAt(set, 0)); } return _createObjectOrdered(keys, data); } @@ -251,12 +251,12 @@ function normalizeArray(xs: number[]) { return xs; } -function ofTuples(xs: ArrayLike<Tuple>) { +function ofAtoms(xs: ArrayLike<Atom>) { if (xs.length === 0) return Empty; const sets: { [key: number]: number[] } = Object.create(null); for (let i = 0, _i = xs.length; i < _i; i++) { const x = xs[i]; - const u = Tuple.fst(x), v = Tuple.snd(x); + const u = Atom.unit(x), v = Atom.index(x); const set = sets[u]; if (set) set[set.length] = v; else sets[u] = [v]; @@ -286,21 +286,21 @@ function getOffsetIndex(xs: ArrayLike<number>, value: number) { return value < xs[min] ? min - 1 : min; } -function getAtE(set: AtomSetElements, i: number): Tuple { +function getAtE(set: AtomSetElements, i: number): Atom { const { offsets, keys } = set; const o = getOffsetIndex(offsets, i); if (o >= offsets.length - 1) return 0 as any; const k = OrderedSet.getAt(keys, o); const e = OrderedSet.getAt(set[k], i - offsets[o]); - return Tuple.create(k, e); + return Atom.create(k, e); } -function indexOfE(set: AtomSetElements, t: Tuple) { +function indexOfE(set: AtomSetElements, t: Atom) { const { keys } = set; - const u = Tuple.fst(t); + const u = Atom.unit(t); const setIdx = OrderedSet.indexOf(keys, u); if (setIdx < 0) return -1; - const o = OrderedSet.indexOf(set[u], Tuple.snd(t)); + const o = OrderedSet.indexOf(set[u], Atom.index(t)); if (o < 0) return -1; return set.offsets[setIdx] + o; } @@ -332,9 +332,9 @@ function areEqualEE(a: AtomSetElements, b: AtomSetElements) { return true; } -function areIntersectingNE(a: Tuple, b: AtomSetElements) { - const u = Tuple.fst(a); - return OrderedSet.has(b.keys, u) && OrderedSet.has(b[u], Tuple.snd(a)); +function areIntersectingNE(a: Atom, b: AtomSetElements) { + const u = Atom.unit(a); + return OrderedSet.has(b.keys, u) && OrderedSet.has(b[u], Atom.index(a)); } function areIntersectingEE(a: AtomSetElements, b: AtomSetElements) { @@ -350,9 +350,9 @@ function areIntersectingEE(a: AtomSetElements, b: AtomSetElements) { return false; } -function intersectNE(a: Tuple, b: AtomSetElements) { - const u = Tuple.fst(a); - return OrderedSet.has(b.keys, u) && OrderedSet.has(b[u], Tuple.snd(a)) ? a : Empty; +function intersectNE(a: Atom, b: AtomSetElements) { + const u = Atom.unit(a); + return OrderedSet.has(b.keys, u) && OrderedSet.has(b[u], Atom.index(a)) ? a : Empty; } function intersectEE(a: AtomSetElements, b: AtomSetElements) { @@ -377,14 +377,14 @@ function intersectEE(a: AtomSetElements, b: AtomSetElements) { return ofObjectOrdered(OrderedSet.ofSortedArray(keys), ret); } -function subtractNE(a: Tuple, b: AtomSetElements) { - const u = Tuple.fst(a); - return OrderedSet.has(b.keys, u) && OrderedSet.has(b[u], Tuple.snd(a)) ? Empty : a; +function subtractNE(a: Atom, b: AtomSetElements) { + const u = Atom.unit(a); + return OrderedSet.has(b.keys, u) && OrderedSet.has(b[u], Atom.index(a)) ? Empty : a; } -function subtractEN(a: AtomSetElements, b: Tuple): AtomSetImpl { +function subtractEN(a: AtomSetElements, b: Atom): AtomSetImpl { const aKeys = a.keys; - const u = Tuple.fst(b), v = Tuple.snd(b); + const u = Atom.unit(b), v = Atom.index(b); if (!OrderedSet.has(aKeys, u) || !OrderedSet.has(a[u], v)) return a; const set = a[u]; if (OrderedSet.size(set) === 1) { @@ -465,14 +465,14 @@ function unionN(sets: ArrayLike<AtomSetImpl>, eCount: { count: number }) { } eCount.count = countE; if (!countN) return Empty; - if (countN === sets.length) return ofTuples(sets as ArrayLike<Tuple>); + if (countN === sets.length) return ofAtoms(sets as ArrayLike<Atom>); const packed = new Float64Array(countN); let offset = 0; for (let i = 0, _i = sets.length; i < _i; i++) { const s = sets[i]; if (typeof s === 'number') packed[offset++] = s; } - return ofTuples(packed as any); + return ofAtoms(packed as any); } function unionInto(data: { [key: number]: OrderedSet }, a: AtomSetElements) { @@ -485,12 +485,12 @@ function unionInto(data: { [key: number]: OrderedSet }, a: AtomSetElements) { } } -function unionIntoN(data: { [key: number]: OrderedSet }, a: Tuple) { - const u = Tuple.fst(a); +function unionIntoN(data: { [key: number]: OrderedSet }, a: Atom) { + const u = Atom.unit(a); const set = data[u]; if (set) { - data[u] = OrderedSet.union(set, OrderedSet.ofSingleton(Tuple.snd(a))); + data[u] = OrderedSet.union(set, OrderedSet.ofSingleton(Atom.index(a))); } else { - data[u] = OrderedSet.ofSingleton(Tuple.snd(a)); + data[u] = OrderedSet.ofSingleton(Atom.index(a)); } } \ No newline at end of file diff --git a/src/mol-data/atom-set/builder.ts b/src/mol-data/atom-set/builder.ts index d28cbe641..568236286 100644 --- a/src/mol-data/atom-set/builder.ts +++ b/src/mol-data/atom-set/builder.ts @@ -40,7 +40,7 @@ class Builder { sets[k] = OrderedSet.ofSingleton(unit[0]); } else { const set = OrderedSet.ofSortedArray(unit); - const parentSet = AtomSet.getByKey(this.parent, k); + const parentSet = AtomSet.unitGetById(this.parent, k); sets[k] = OrderedSet.areEqual(set, parentSet) ? parentSet : set; } } diff --git a/src/mol-data/atom-set/properties.ts b/src/mol-data/atom-set/properties.ts new file mode 100644 index 000000000..d13a9ee15 --- /dev/null +++ b/src/mol-data/atom-set/properties.ts @@ -0,0 +1,6 @@ +/** + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + diff --git a/src/mol-data/atom.ts b/src/mol-data/atom.ts new file mode 100644 index 000000000..30f225fa7 --- /dev/null +++ b/src/mol-data/atom.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import Tuple from '../mol-base/collections/integer/tuple' + +interface Atom { '@type': Tuple['@type'] } + +namespace Atom { + export const Zero: Atom = Tuple.Zero; + export const create: (unit: number, index: number) => Atom = Tuple.create; + export const is: (x: any) => x is Atom = Tuple.is; + export const unit: (a: Atom) => number = Tuple.fst; + 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; +} + +export default Atom \ No newline at end of file diff --git a/src/mol-data/model/formats.ts b/src/mol-data/model/formats.ts index d0243888b..1f98e96f5 100644 --- a/src/mol-data/model/formats.ts +++ b/src/mol-data/model/formats.ts @@ -4,5 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ +import mmCIF from '../../mol-io/reader/cif/schema/mmcif' -export type RawData = {} \ No newline at end of file +export type RawData = + | { source: 'mmCIF', data: mmCIF } \ No newline at end of file diff --git a/src/mol-data/model/formats/mmcif.ts b/src/mol-data/model/formats/mmcif.ts index 96788f75b..c1cc176dd 100644 --- a/src/mol-data/model/formats/mmcif.ts +++ b/src/mol-data/model/formats/mmcif.ts @@ -4,4 +4,72 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -// TODO: implement interfaces for mmCIF source data format \ No newline at end of file +import { RawData } from '../formats' +import mmCIF from '../../../mol-io/reader/cif/schema/mmcif' +import Model from '../../model' +import Interval from '../../../mol-base/collections/integer/interval' +import Segmentation from '../../../mol-base/collections/integer/segmentation' + +function findModelBounds(data: mmCIF, startIndex: number) { + const num = data.atom_site.pdbx_PDB_model_num; + const atomCount = num.rowCount; + if (!num.isDefined) return Interval.ofBounds(startIndex, atomCount); + let endIndex = startIndex + 1; + while (endIndex < atomCount && num.areValuesEqual(startIndex, endIndex)) endIndex++; + return Interval.ofBounds(startIndex, endIndex); +} + +function segment(data: mmCIF, bounds: Interval) { + const start = Interval.start(bounds), end = Interval.end(bounds); + const residues = [start], chains = [start]; + + const { label_entity_id, auth_asym_id, auth_seq_id, pdbx_PDB_ins_code } = data.atom_site; + + for (let i = start + 1; i < end; i++) { + const newEntity = !label_entity_id.areValuesEqual(i - 1, i); + const newChain = newEntity || !auth_asym_id.areValuesEqual(i - 1, i); + const newResidue = newChain + || !auth_seq_id.areValuesEqual(i - 1, i) + || !pdbx_PDB_ins_code.areValuesEqual(i - 1, i); + + if (newResidue) residues[residues.length] = i; + if (newChain) chains[chains.length] = i; + } + + residues[residues.length] = end; + chains[chains.length] = end; + + return { residues: Segmentation.create(residues), chains: Segmentation.create(chains) }; +} + +function createModel(raw: RawData, data: mmCIF, bounds: Interval): Model { + const segments = segment(data, bounds); + return { + data: raw, + common: 0 as any, + macromolecule: 0 as any, + residues: segments.residues, + chains: segments.chains + }; +} + +function getModels(data: mmCIF): ArrayLike<Model> { + const raw: RawData = { source: 'mmCIF', data }; + const models: Model[] = []; + const atomCount = data.atom_site._rowCount; + let modelStart = 0; + while (modelStart < atomCount) { + const bounds = findModelBounds(data, modelStart); + const model = createModel(raw, data, bounds); + models.push(model); + modelStart = Interval.end(bounds); + } + return models; +} + +export default getModels; + +// function createStructure() { + +// } + diff --git a/src/mol-data/structure/topology/connected-components.ts b/src/mol-data/structure/base.ts similarity index 100% rename from src/mol-data/structure/topology/connected-components.ts rename to src/mol-data/structure/base.ts diff --git a/src/mol-data/structure/data.ts b/src/mol-data/structure/data.ts deleted file mode 100644 index d162fc1b3..000000000 --- a/src/mol-data/structure/data.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. - * - * @author David Sehnal <david.sehnal@gmail.com> - */ - -export type Table<Data> = { rowCount: number } & { [E in keyof Data]: ArrayLike<Data[E]> } -export type DataTable<Data> = { data: any } & Table<Data & { dataIndex: number }> - -export interface Position { x: number, y: number, z: number } -export interface Positions extends Table<Position> {} - -export interface Atom { - name: string, - elementSymbol: string, - altLoc: string | null, -} -export interface Atoms extends DataTable<Atom> { } - -export interface Residue { - key: number, - name: string, - seqNumber: number, - insCode: string | null, - isHet: number -} -export interface Residues extends DataTable<Residue> { } - -export interface Chain { key: number, id: string } -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 - -export interface Structure { - atoms: Atoms, - residues: Residues, - chains: Chains, - entities: Entities -} - -export interface SecondaryStructure { - -} -export interface SecondaryStructures extends Table<SecondaryStructure> { - -} \ No newline at end of file diff --git a/src/mol-data/structure/selectors/common.ts b/src/mol-data/structure/selectors/common.ts deleted file mode 100644 index 76b4c876f..000000000 --- a/src/mol-data/structure/selectors/common.ts +++ /dev/null @@ -1,47 +0,0 @@ -// /** -// * 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 diff --git a/src/mol-data/structure/selectors/mmcif.ts b/src/mol-data/structure/selectors/mmcif.ts deleted file mode 100644 index 08a95c232..000000000 --- a/src/mol-data/structure/selectors/mmcif.ts +++ /dev/null @@ -1,34 +0,0 @@ -// /** -// * 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 diff --git a/src/mol-data/structure/topology/secondary-structure.ts b/src/mol-data/structure/topology/secondary-structure.ts deleted file mode 100644 index 75d1f4b89..000000000 --- a/src/mol-data/structure/topology/secondary-structure.ts +++ /dev/null @@ -1,128 +0,0 @@ -/** - * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -const enum SSF { - None = 0x0, - - // category - DoubleHelix = 0x1, - Helix = 0x2, - Beta = 0x4, - Turn = 0x8, - - // category variant - LeftHanded = 0x10, // helix - RightHanded = 0x20, - - ClassicTurn = 0x40, // turn - InverseTurn = 0x80, - - // sub-category - HelixOther = 0x100, // protein - Helix27 = 0x200, - Helix3Ten = 0x400, - HelixAlpha = 0x800, - HelixGamma = 0x1000, - HelixOmega = 0x2000, - HelixPi = 0x4000, - HelixPolyproline = 0x8000, - - DoubleHelixOther = 0x10000, // nucleic - DoubleHelixZ = 0x20000, - DoubleHelixA = 0x40000, - DoubleHelixB = 0x80000, - - BetaOther = 0x100000, // protein - BetaStrand = 0x200000, // single strand - BetaSheet = 0x400000, // multiple hydrogen bonded strands - BetaBarell = 0x800000, // closed series of sheets - - TurnOther = 0x1000000, // protein - Turn1 = 0x2000000, - Turn2 = 0x4000000, - Turn3 = 0x8000000, - - NA = 0x10000000, // not applicable/available -} -export { SSF as SecondaryStructureFlag } - -export const SecondaryStructureMmcif: { [value: string]: number } = { - HELX_LH_27_P: SSF.Helix | SSF.LeftHanded | SSF.Helix27, // left-handed 2-7 helix (protein) - HELX_LH_3T_P: SSF.Helix | SSF.LeftHanded | SSF.Helix3Ten, // left-handed 3-10 helix (protein) - HELX_LH_AL_P: SSF.Helix | SSF.LeftHanded | SSF.HelixAlpha, // left-handed alpha helix (protein) - HELX_LH_A_N: SSF.DoubleHelix | SSF.LeftHanded | SSF.DoubleHelixA, // left-handed A helix (nucleic acid) - HELX_LH_B_N: SSF.DoubleHelix | SSF.LeftHanded | SSF.DoubleHelixB, // left-handed B helix (nucleic acid) - HELX_LH_GA_P: SSF.Helix | SSF.LeftHanded | SSF.HelixGamma, // left-handed gamma helix (protein) - HELX_LH_N: SSF.DoubleHelix | SSF.LeftHanded, // left-handed helix with type not specified (nucleic acid) - HELX_LH_OM_P: SSF.Helix | SSF.LeftHanded | SSF.HelixOmega, // left-handed omega helix (protein) - HELX_LH_OT_N: SSF.DoubleHelix | SSF.LeftHanded | SSF.DoubleHelixOther, // left-handed helix with type that does not conform to an accepted category (nucleic acid) - HELX_LH_OT_P: SSF.Helix | SSF.LeftHanded | SSF.HelixOther, // left-handed helix with type that does not conform to an accepted category (protein) - HELX_LH_P: SSF.Helix | SSF.LeftHanded, // left-handed helix with type not specified (protein) - HELX_LH_PI_P: SSF.Helix | SSF.LeftHanded | SSF.HelixPi, // left-handed pi helix (protein) - HELX_LH_PP_P: SSF.Helix | SSF.LeftHanded | SSF.HelixPolyproline, // left-handed polyproline helix (protein) - HELX_LH_Z_N: SSF.DoubleHelix | SSF.LeftHanded | SSF.DoubleHelixZ, // left-handed Z helix (nucleic acid) - HELX_N: SSF.DoubleHelix, // helix with handedness and type not specified (nucleic acid) - HELX_OT_N: SSF.DoubleHelix, // helix with handedness and type that do not conform to an accepted category (nucleic acid) - HELX_OT_P: SSF.Helix, // helix with handedness and type that do not conform to an accepted category (protein) - HELX_P: SSF.Helix, // helix with handedness and type not specified (protein) - HELX_RH_27_P: SSF.Helix | SSF.RightHanded | SSF.Helix27, // right-handed 2-7 helix (protein) - HELX_RH_3T_P: SSF.Helix | SSF.RightHanded | SSF.Helix3Ten, // right-handed 3-10 helix (protein) - HELX_RH_AL_P: SSF.Helix | SSF.RightHanded | SSF.HelixAlpha, // right-handed alpha helix (protein) - HELX_RH_A_N: SSF.DoubleHelix | SSF.RightHanded | SSF.DoubleHelixA, // right-handed A helix (nucleic acid) - HELX_RH_B_N: SSF.DoubleHelix | SSF.RightHanded | SSF.DoubleHelixB, // right-handed B helix (nucleic acid) - HELX_RH_GA_P: SSF.Helix | SSF.RightHanded | SSF.HelixGamma, // right-handed gamma helix (protein) - HELX_RH_N: SSF.DoubleHelix | SSF.RightHanded, // right-handed helix with type not specified (nucleic acid) - HELX_RH_OM_P: SSF.Helix | SSF.RightHanded | SSF.HelixOmega, // right-handed omega helix (protein) - HELX_RH_OT_N: SSF.DoubleHelix | SSF.RightHanded | SSF.DoubleHelixOther, // right-handed helix with type that does not conform to an accepted category (nucleic acid) - HELX_RH_OT_P: SSF.Helix | SSF.RightHanded | SSF.HelixOther, // right-handed helix with type that does not conform to an accepted category (protein) - HELX_RH_P: SSF.Helix | SSF.RightHanded, // right-handed helix with type not specified (protein) - HELX_RH_PI_P: SSF.Helix | SSF.RightHanded | SSF.HelixPi, // right-handed pi helix (protein) - HELX_RH_PP_P: SSF.Helix | SSF.RightHanded | SSF.HelixPolyproline, // right-handed polyproline helix (protein) - HELX_RH_Z_N: SSF.DoubleHelix | SSF.RightHanded | SSF.DoubleHelixZ, // right-handed Z helix (nucleic acid) - STRN: SSF.Beta | SSF.BetaStrand, // beta strand (protein) - TURN_OT_P: SSF.Turn | SSF.TurnOther, // turn with type that does not conform to an accepted category (protein) - TURN_P: SSF.Turn, // turn with type not specified (protein) - TURN_TY1P_P: SSF.Turn | SSF.InverseTurn | SSF.Turn1, // type I prime turn (protein) - TURN_TY1_P: SSF.Turn | SSF.ClassicTurn | SSF.Turn1, // type I turn (protein) - TURN_TY2P_P: SSF.Turn | SSF.InverseTurn | SSF.Turn2, // type II prime turn (protein) - TURN_TY2_P: SSF.Turn | SSF.ClassicTurn | SSF.Turn2, // type II turn (protein) - TURN_TY3P_P: SSF.Turn | SSF.InverseTurn | SSF.Turn3, // type III prime turn (protein) - TURN_TY3_P: SSF.Turn | SSF.ClassicTurn | SSF.Turn3, // type III turn (protein) -} - -export const SecondaryStructurePdb: { [value: string]: number } = { - 1: SSF.Helix | SSF.RightHanded | SSF.HelixAlpha, // Right-handed alpha (default) - 2: SSF.Helix | SSF.RightHanded | SSF.HelixOmega, // Right-handed omega - 3: SSF.Helix | SSF.RightHanded | SSF.HelixPi, // Right-handed pi - 4: SSF.Helix | SSF.RightHanded | SSF.HelixGamma, // Right-handed gamma - 5: SSF.Helix | SSF.RightHanded | SSF.Helix3Ten, // Right-handed 310 - 6: SSF.Helix | SSF.LeftHanded | SSF.HelixAlpha, // Left-handed alpha - 7: SSF.Helix | SSF.LeftHanded | SSF.HelixOmega, // Left-handed omega - 8: SSF.Helix | SSF.LeftHanded | SSF.HelixGamma, // Left-handed gamma - 9: SSF.Helix | SSF.Helix27, // 27 ribbon/helix - 10: SSF.Helix | SSF.HelixPolyproline, // Polyproline -} - -export const SecondaryStructureStride: { [value: string]: number } = { - H: SSF.Helix | SSF.HelixAlpha, // Alpha helix - G: SSF.Helix | SSF.Helix3Ten, // 3-10 helix - I: SSF.Helix | SSF.HelixPi, // PI-helix - E: SSF.Beta | SSF.BetaSheet, // Extended conformation - B: SSF.Beta | SSF.BetaStrand, // Isolated bridge - b: SSF.Beta | SSF.BetaStrand, // Isolated bridge - T: SSF.Turn, // Turn - C: SSF.NA, // Coil (none of the above) -} - -export const SecondaryStructureDssp: { [value: string]: number } = { - H: SSF.Helix | SSF.HelixAlpha, // alpha-helix - B: SSF.Beta | SSF.BetaStrand, // residue in isolated beta-bridge - E: SSF.Beta | SSF.BetaSheet, // extended strand, participates in beta ladder - G: SSF.Helix | SSF.Helix3Ten, // 3-helix (310 helix) - I: SSF.Helix | SSF.HelixPi, // 5 helix (pi-helix) - T: SSF.Turn, // hydrogen bonded turn - S: SSF.Turn, // bend -} \ No newline at end of file diff --git a/src/mol-io/reader/cif/index.ts b/src/mol-io/reader/cif.ts similarity index 53% rename from src/mol-io/reader/cif/index.ts rename to src/mol-io/reader/cif.ts index aa10d1ffa..0d44a5482 100644 --- a/src/mol-io/reader/cif/index.ts +++ b/src/mol-io/reader/cif.ts @@ -4,11 +4,11 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import parseText from './text/parser' -import parseBinary from './binary/parser' -import { Block } from './data-model' -import { toTypedFrame as applySchema } from './schema' -import mmCIF from './schema/mmcif' +import parseText from './cif/text/parser' +import parseBinary from './cif/binary/parser' +import { Block } from './cif/data-model' +import { toTypedFrame as applySchema } from './cif/schema' +import mmCIF from './cif/schema/mmcif' export default { parseText, @@ -19,4 +19,4 @@ export default { } } -export * from './data-model' \ No newline at end of file +export * from './cif/data-model' \ No newline at end of file diff --git a/src/perf-tests/sets.ts b/src/perf-tests/sets.ts index 178a9d9fe..4794a55cf 100644 --- a/src/perf-tests/sets.ts +++ b/src/perf-tests/sets.ts @@ -3,7 +3,6 @@ import Tuple from '../mol-base/collections/integer/tuple' import OrdSet from '../mol-base/collections/integer/ordered-set' import AtomSet from '../mol-data/atom-set' import Segmentation from '../mol-base/collections/integer/segmentation' -import SortedArray from '../mol-base/collections/integer/sorted-array' export namespace Iteration { const U = 1000, V = 2500; @@ -38,15 +37,15 @@ export namespace Iteration { export function elementAt() { let s = 0; - for (let i = 0, _i = AtomSet.atomCount(ms); i < _i; i++) s += Tuple.snd(AtomSet.getAtomAt(ms, i)); + for (let i = 0, _i = AtomSet.atomCount(ms); i < _i; i++) s += Tuple.snd(AtomSet.atomGetAt(ms, i)); return s; } export function manual() { let s = 0; - const keys = AtomSet.units(ms); + const keys = AtomSet.unitIds(ms); for (let i = 0, _i = OrdSet.size(keys); i < _i; i++) { - const set = AtomSet.getByKey(ms, OrdSet.getAt(keys, i)); + const set = AtomSet.unitGetById(ms, OrdSet.getAt(keys, i)); for (let j = 0, _j = OrdSet.size(set); j < _j; j++) { s += OrdSet.getAt(set, j); } @@ -57,7 +56,7 @@ export namespace Iteration { export function manual1() { let s = 0; for (let i = 0, _i = AtomSet.unitCount(ms); i < _i; i++) { - const set = AtomSet.getByIndex(ms, i); + const set = AtomSet.unitGetByIndex(ms, i); for (let j = 0, _j = OrdSet.size(set); j < _j; j++) { s += OrdSet.getAt(set, j); } @@ -274,7 +273,7 @@ export namespace Tuples { export function testSegments() { const data = OrdSet.ofSortedArray([4, 9, 10, 11, 14, 15, 16]); - const segs = Segmentation.create(SortedArray.ofSortedArray([0, 4, 10, 12, 13, 15, 25]), []); + const segs = Segmentation.create([0, 4, 10, 12, 13, 15, 25]); const it = Segmentation.segments(segs, data); while (it.hasNext) { diff --git a/src/script.ts b/src/script.ts index 0870d4429..345e177e6 100644 --- a/src/script.ts +++ b/src/script.ts @@ -13,10 +13,12 @@ const readFileAsync = util.promisify(fs.readFile); const writeFileAsync = util.promisify(fs.writeFile); import Gro from './mol-io/reader/gro/parser' -import CIF from './mol-io/reader/cif/index' +import CIF from './mol-io/reader/cif' import Computation from './mol-base/computation' +import createModels from './mol-data/model/formats/mmcif' + // import { toTypedFrame as applySchema } from './reader/cif/schema' import { generateSchema } from './mol-io/reader/cif/schema/utils' @@ -112,6 +114,11 @@ async function runCIF(input: string | Uint8Array) { console.log(mmcif.entity.type.toArray()); console.log(mmcif.pdbx_struct_oper_list.matrix.value(0)); + console.time('createModels'); + const models = createModels(mmcif); + console.timeEnd('createModels'); + console.log(models[0].common); + // const schema = await _dic() // if (schema) { // const mmcif2 = applySchema(schema, data) -- GitLab