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

segment iterator

parent 52d2de1a
No related branches found
No related tags found
No related merge requests found
......@@ -275,6 +275,24 @@ describe('ordered set', () => {
testEq('subtract AA', OrderedSet.subtract(arr136, arr136), []);
testEq('subtract AA1', OrderedSet.subtract(arr136, OrderedSet.ofSortedArray([2, 3, 4, 6, 7])), [1]);
testEq('subtract AA2', OrderedSet.subtract(arr136, OrderedSet.ofSortedArray([0, 1, 6])), [3]);
it('segments', () => {
const data = OrderedSet.ofSortedArray([4, 9, 10, 11, 14, 15, 16]);
const segs = OrderedSet.ofSortedArray([0, 4, 10, 12, 13, 15, 25]);
const it = OrderedSet.segments(segs, data);
const t = Object.create(null);
for (let s = it.move(); !it.done; s = it.move()) {
for (let j = s.start; j < s.end; j++) {
const x = t[s.segmentIndex];
const v = OrderedSet.getAt(data, j);
if (!x) t[s.segmentIndex] = [v];
else x[x.length] = v;
}
}
expect(t).toEqual({ 1: [4, 9], 2: [10, 11], 4: [14], 5: [15, 16] });
});
});
......
......@@ -47,7 +47,6 @@ class ArrayIteratorImpl<T> implements Iterator<T> {
this.index = -1;
// try to avoid deoptimization with undefined values
this.lastValue = xs.length > 0 ? xs[0] : void 0 as any;
return this;
}
}
......@@ -71,7 +70,6 @@ class RangeIteratorImpl implements Iterator<number> {
constructor(private min: number, private max: number) {
this.value = min - 1;
this.done = max < min;
return this;
}
}
......
This diff is collapsed.
/**
* Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import IntTuple from '../int-tuple'
import { hash3, hash4 } from '../hash-functions'
type Range = IntTuple
type SortedArray = ArrayLike<number>
type OrderedSetImpl = Range | SortedArray
export const Empty: OrderedSetImpl = IntTuple.pack(0, -1) as any;
export function ofSingleton(value: number): OrderedSetImpl { return IntTuple.pack(value, value) as any; }
export function ofRange(min: number, max: number): OrderedSetImpl { return max < min ? Empty : IntTuple.pack(min, max) as any; }
/** It is the responsibility of the caller to ensure the array is sorted and contains unique values. */
export function ofSortedArray(xs: SortedArray): OrderedSetImpl {
if (!xs.length) return Empty;
// check if the array is just a range
if (xs[xs.length - 1] - xs[0] + 1 === xs.length) return ofRange(xs[0], xs[xs.length - 1]);
return xs as any;
}
export function size(set: OrderedSetImpl) { return typeof set === 'number' ? sizeR(set) : (set as SortedArray).length; }
export function has(set: OrderedSetImpl, x: number) { return typeof set === 'number' ? hasR(set, x) : hasA(set as SortedArray, x); }
export function indexOf(set: OrderedSetImpl, x: number) { return typeof set === 'number' ? indexOfR(set, x) : indexOfA(set as SortedArray, x); }
export function getAt(set: OrderedSetImpl, i: number) { return typeof set === 'number' ? elementAtR(set, i) : (set as SortedArray)[i]; }
export function minValue(set: OrderedSetImpl) { return typeof set === 'number' ? minR(set) : (set as SortedArray)[0]; }
export function maxValue(set: OrderedSetImpl) { return typeof set === 'number' ? maxR(set) : (set as SortedArray)[(set as SortedArray).length - 1]; }
export function hashCode(set: OrderedSetImpl) {
// hash of tuple (size, min, max, mid)
const s = size(set);
if (!s) return 0;
if (s > 2) return hash4(s, getAt(set, 0), getAt(set, s - 1), getAt(set, s >> 1));
return hash3(s, getAt(set, 0), getAt(set, s - 1));
}
// TODO: possibly add more hash functions to allow for multilevel hashing.
export function areEqual(a: OrderedSetImpl, b: OrderedSetImpl) {
if (typeof a === 'number') {
if (typeof b === 'number') return equalRR(a, b);
return false;
} else if (typeof b === 'number') return false;
return equalAA(a as SortedArray, b as SortedArray);
}
export function areIntersecting(a: OrderedSetImpl, b: OrderedSetImpl) {
// if at least one is "range", they must now intersect
if (typeof a === 'number') {
if (typeof b === 'number') return equalRR(a, b) || areRangesIntersecting(a, b);
return areRangesIntersecting(a, b);
}
if (!areRangesIntersecting(a, b)) return false;
else if (typeof b === 'number') return false;
return areIntersectingAA(a as SortedArray, b as SortedArray);
}
/** Check if the 2nd argument is a subset of the 1st */
export function isSubset(set: OrderedSetImpl, toTest: OrderedSetImpl) {
if (!isRangeSubset(set, toTest)) return false;
const testSize = size(toTest);
if (typeof set === 'number' || !testSize) return true;
if (typeof toTest === 'number') return indexOf(set, maxR(toTest)) - indexOf(set, minR(toTest)) + 1 === testSize;
return isSubsetAA(set as SortedArray, toTest as SortedArray);
}
export function getPredIndex(set: OrderedSetImpl, x: number) {
return typeof set === 'number' ? rangeSearchIndex(set, x) : binarySearchPredIndex(set as SortedArray, x);
}
export function getPredIndex1(set: OrderedSetImpl, x: number, start: number, end: number) {
return typeof set === 'number' ? rangeSearchIndex(set, x) : binarySearchPredIndexRange(set as SortedArray, x, start, end);
}
export function getIntervalRange(set: OrderedSetImpl, min: number, max: number, range: { start: number, end: number }) {
const { start, end } = getStartEnd(set, min, max);
range.start = start;
range.end = end;
return range;
}
export function union(a: OrderedSetImpl, b: OrderedSetImpl) {
if (typeof a === 'number') {
if (typeof b === 'number') return unionRR(a, b);
return unionAR(b as SortedArray, a);
} else if (typeof b === 'number') {
return unionAR(a as SortedArray, b);
} else return unionAA(a as SortedArray, b as SortedArray);
}
export function intersect(a: OrderedSetImpl, b: OrderedSetImpl) {
if (typeof a === 'number') {
if (typeof b === 'number') return intersectRR(a, b);
return intersectAR(b as SortedArray, a);
} else if (typeof b === 'number') {
return intersectAR(a as SortedArray, b);
} else {
if (!areRangesIntersecting(a, b)) return Empty;
return intersectAA(a as SortedArray, b as SortedArray);
}
}
export function subtract(a: OrderedSetImpl, b: OrderedSetImpl) {
if (!areRangesIntersecting(a, b)) return a;
if (typeof a === 'number') {
if (typeof b === 'number') return substractRR(a, b);
return subtractRA(a, b as SortedArray);
} else if (typeof b === 'number') {
return subtractAR(a as SortedArray, b);
} else {
return subtractAA(a as SortedArray, b as SortedArray);
}
}
const minR = IntTuple.fst
const maxR = IntTuple.snd
const equalRR = IntTuple.areEqual
const _eR = IntTuple.zero();
function sizeR(set: Range) { IntTuple.unpack(set, _eR); return _eR.snd - _eR.fst + 1; }
function hasR(set: Range, x: number) { IntTuple.unpack(set, _eR); return x >= _eR.fst && x <= _eR.snd; }
function indexOfR(set: Range, x: number) { IntTuple.unpack(set, _eR); return x >= _eR.fst && x <= _eR.snd ? x - _eR.fst : -1; }
function elementAtR(set: Range, i: number) { return IntTuple.fst(set) + i; }
function hasA(set: SortedArray, x: number) { return x >= set[0] && x <= set[set.length - 1] && binarySearch(set, x) >= 0; }
function indexOfA(set: SortedArray, x: number) { return x >= set[0] && x <= set[set.length - 1] ? binarySearch(set, x) : -1; }
function binarySearch(xs: SortedArray, value: number) {
return binarySearchRange(xs, value, 0, xs.length);
}
function binarySearchRange(xs: SortedArray, value: number, start: number, end: number) {
let min = start, max = end - 1;
while (min <= max) {
if (min + 11 > max) {
for (let i = min; i <= max; i++) {
if (value === xs[i]) return i;
}
return -1;
}
const mid = (min + max) >> 1;
const v = xs[mid];
if (value < v) max = mid - 1;
else if (value > v) min = mid + 1;
else return mid;
}
return -1;
}
function binarySearchPredIndex(xs: SortedArray, value: number) {
return binarySearchPredIndexRange(xs, value, 0, xs.length);
}
function binarySearchPredIndexRange(xs: SortedArray, value: number, start: number, end: number) {
let min = start, max = end - 1;
while (min < max) {
const mid = (min + max) >> 1;
const v = xs[mid];
if (value < v) max = mid - 1;
else if (value > v) min = mid + 1;
else return mid;
}
if (min > max) return max + 1;
return xs[min] >= value ? min : min + 1;
}
const _rsiR = IntTuple.zero();
function rangeSearchIndex(r: Range, value: number) {
IntTuple.unpack(r, _rsiR);
if (value < _rsiR.fst) return 0;
if (value > _rsiR.snd) return _rsiR.snd - _rsiR.fst + 1;
return value - _rsiR.fst;
}
const _maxIntRangeRet = { i: 0, j: 0, endA: 0, endB: 0 };
function getMaxIntersectionRange(xs: SortedArray, ys: SortedArray) {
const la = xs.length - 1, lb = ys.length - 1;
_maxIntRangeRet.i = binarySearchPredIndex(xs, ys[0]);
_maxIntRangeRet.j = binarySearchPredIndex(ys, xs[0]);
_maxIntRangeRet.endA = Math.min(binarySearchPredIndex(xs, ys[lb]), la);
_maxIntRangeRet.endB = Math.min(binarySearchPredIndex(ys, xs[la]), lb);
return _maxIntRangeRet;
}
const _startEndRet = { start: 0, end: 0 };
function getStartEnd(set: OrderedSetImpl, min: number, max: number) {
_startEndRet.start = getPredIndex(set, min);
_startEndRet.end = getPredIndex(set, max + 1);
return _startEndRet;
}
function equalAA(a: SortedArray, b: SortedArray) {
if (a === b) return true;
const aSize = a.length;
if (aSize !== b.length || a[0] !== b[0] || a[aSize - 1] !== b[aSize - 1]) return false;
for (let i = 0; i < aSize; i++) {
if (a[i] !== b[i]) return false;
}
return true;
}
function areIntersectingAA(xs: SortedArray, ys: SortedArray) {
if (xs === ys) return true;
let { i, j, endA, endB } = getMaxIntersectionRange(xs, ys);
while (i <= endA && j <= endB) {
const x = xs[i], y = ys[j];
if (x < y) { i++; }
else if (x > y) { j++; }
else return true;
}
return false;
}
function isSubsetAA(a: SortedArray, b: SortedArray) {
if (a === b) return true;
const lenB = b.length;
let { i, j, endA, endB } = getMaxIntersectionRange(a, b);
// must be able to advance by lenB elements
if (endB - j + 1 < lenB || endA - i + 1 < lenB) return false;
let equal = 0;
while (i <= endA && j <= endB) {
const x = a[i], y = b[j];
if (x < y) { i++; }
else if (x > y) { j++; }
else { i++; j++; equal++; }
}
return equal === lenB;
}
function areRangesIntersecting(a: OrderedSetImpl, b: OrderedSetImpl) {
return size(a) > 0 && size(b) > 0 && maxValue(a) >= minValue(b) && minValue(a) <= maxValue(b);
}
function isRangeSubset(a: OrderedSetImpl, b: OrderedSetImpl) {
if (!size(a)) return size(b) === 0;
if (!size(b)) return true;
return minValue(a) <= minValue(b) && maxValue(a) >= maxValue(b);
}
function unionRR(a: Range, b: Range) {
if (IntTuple.areEqual(a, b)) return a;
const sizeA = sizeR(a), sizeB = sizeR(b);
if (!sizeA) return b;
if (!sizeB) return a;
const minA = minR(a), minB = minR(b);
if (areRangesIntersecting(a, b)) return ofRange(Math.min(minA, minB), Math.max(maxR(a), maxR(b)));
let lSize, lMin, rSize, rMin;
if (minR(a) < minR(b)) { lSize = sizeA; lMin = minA; rSize = sizeB; rMin = minB; }
else { lSize = sizeB; lMin = minB; rSize = sizeA; rMin = minA; }
const arr = new Int32Array(sizeA + sizeB);
for (let i = 0; i < lSize; i++) arr[i] = i + lMin;
for (let i = 0; i < rSize; i++) arr[i + lSize] = i + rMin;
return ofSortedArray(arr);
}
const _uAR = IntTuple.zero();
function unionAR(a: SortedArray, b: Range) {
const bSize = size(b);
if (!bSize) return a;
// is the array fully contained in the range?
if (isRangeSubset(b, a)) return b;
IntTuple.unpack(b, _uAR);
const min = _uAR.fst, max = _uAR.snd;
const { start, end } = getStartEnd(a, min, max);
const indices = new Int32Array(start + (a.length - end) + bSize);
let offset = 0;
for (let i = 0; i < start; i++) indices[offset++] = a[i];
for (let i = min; i <= max; i++) indices[offset++] = i;
for (let i = end, _i = a.length; i < _i; i++) indices[offset] = a[i];
return ofSortedArray(indices);
}
function unionAA(a: SortedArray, b: SortedArray) {
if (a === b) return a;
let { i: sI, j: sJ, endA, endB } = getMaxIntersectionRange(a, b);
let i = sI, j = sJ;
let commonCount = 0;
while (i <= endA && j <= endB) {
const x = a[i], y = b[j];
if (x < y) { i++; }
else if (x > y) { j++; }
else { i++; j++; commonCount++; }
}
const lenA = a.length, lenB = b.length;
// A === B || B is subset of A ==> A
if ((commonCount === lenA && commonCount === lenB) || commonCount === lenB) return a;
// A is subset of B ===> B
if (commonCount === lenA) return b;
const resultSize = lenA + lenB - commonCount;
const l = Math.min(a[0], b[0]), r = Math.max(a[lenA - 1], b[lenB - 1]);
// is this just a range?
if (resultSize === r - l + 1) {
return ofRange(l, r);
}
const indices = new Int32Array(lenA + lenB - commonCount);
let offset = 0;
// insert the "prefixes"
for (let k = 0; k < sI; k++) indices[offset++] = a[k];
for (let k = 0; k < sJ; k++) indices[offset++] = b[k];
// insert the common part
i = sI;
j = sJ;
while (i <= endA && j <= endB) {
const x = a[i], y = b[j];
if (x < y) { indices[offset++] = x; i++; }
else if (x > y) { indices[offset++] = y; j++; }
else { indices[offset++] = x; i++; j++; }
}
// insert the "tail"
for (; i < lenA; i++) indices[offset++] = a[i];
for (; j < lenB; j++) indices[offset++] = b[j];
return ofSortedArray(indices);
}
const _iRA = IntTuple.zero(), _iRB = IntTuple.zero();
function intersectRR(a: Range, b: Range) {
if (!areRangesIntersecting(a, b)) return Empty;
if (IntTuple.areEqual(a, b)) return a;
IntTuple.unpack(a, _iRA);
IntTuple.unpack(b, _iRB);
return ofRange(Math.max(_iRA.fst, _iRB.fst), Math.min(_iRA.snd, _iRB.snd));
}
const _iAR = IntTuple.zero();
function intersectAR(a: SortedArray, r: Range) {
if (!size(r)) return Empty;
IntTuple.unpack(r, _iAR);
const { start, end } = getStartEnd(a, _iAR.fst, _iAR.snd);
const resultSize = end - start;
if (!resultSize) return Empty;
const indices = new Int32Array(resultSize);
let offset = 0;
for (let i = start; i < end; i++) {
indices[offset++] = a[i];
}
return ofSortedArray(indices);
}
function intersectAA(a: SortedArray, b: SortedArray) {
if (a === b) return a;
let { i: sI, j: sJ, endA, endB } = getMaxIntersectionRange(a, b);
let i = sI, j = sJ;
let commonCount = 0;
while (i <= endA && j <= endB) {
const x = a[i], y = b[j];
if (x < y) { i++; }
else if (x > y) { j++; }
else { i++; j++; commonCount++; }
}
const lenA = a.length, lenB = b.length;
// no common elements
if (!commonCount) return Empty;
// A === B || B is subset of A ==> B
if ((commonCount === lenA && commonCount === lenB) || commonCount === lenB) return b;
// A is subset of B ==> A
if (commonCount === lenA) return a;
const indices = new Int32Array(commonCount);
let offset = 0;
i = sI;
j = sJ;
while (i <= endA && j <= endB) {
const x = a[i], y = b[j];
if (x < y) { i++; }
else if (x > y) { j++; }
else { indices[offset++] = x; i++; j++; }
}
return ofSortedArray(indices);
}
const _sRA = IntTuple.zero(), _sRB = IntTuple.zero();
function substractRR(a: Range, b: Range) {
if (IntTuple.areEqual(a, b)) return Empty;
IntTuple.unpack(a, _sRA);
IntTuple.unpack(b, _sRB);
if (_sRA.snd < _sRA.fst || _sRB.snd < _sRB.fst) return a;
// is A subset of B? ==> Empty
if (isRangeSubset(b, a)) return Empty;
if (isRangeSubset(a, b)) {
// this splits the interval into two, gotta represent it as a set.
const l = _sRB.fst - _sRA.fst, r = _sRA.snd - _sRB.snd;
if (l <= 0) return ofRange(_sRB.snd + 1, _sRB.snd + r);
if (r <= 0) return ofRange(_sRA.fst, _sRA.fst + l - 1);
const ret = new Int32Array(l + r);
let offset = 0;
for (let i = 0; i < l; i++) ret[offset++] = _sRA.fst + i;
for (let i = 1; i <= r; i++) ret[offset++] = _sRB.snd + i;
return ofSortedArray(ret);
}
// non intersecting ranges are handled by top-level substract.
// at this point, b either contains rA.fst or rA.snd, but not both.
if (_sRA.fst < _sRB.fst) return ofRange(_sRA.fst, _sRB.fst - 1);
return ofRange(_sRB.snd + 1, _sRA.snd);
}
const _sAR = IntTuple.zero();
function subtractAR(a: SortedArray, b: Range) {
IntTuple.unpack(b, _sAR);
// is empty?
if (_sAR.snd < _sAR.fst) return a;
const min = _sAR.fst, max = _sAR.snd;
const { start, end } = getStartEnd(a, min, max);
const resultSize = a.length - (end - start);
// A is subset of B
if (resultSize <= 0) return Empty;
// No common elements
if (resultSize === a.length) return a;
const ret = new Int32Array(resultSize);
let offset = 0;
for (let i = 0; i < start; i++) ret[offset++] = a[i];
for (let i = end, _i = a.length; i < _i; i++) ret[offset++] = a[i];
return ofSortedArray(ret);
}
const _sAR1 = IntTuple.zero();
function subtractRA(a: Range, b: SortedArray) {
IntTuple.unpack(a, _sAR1);
// is empty?
if (_sAR1.snd < _sAR1.fst) return a;
const min = _sAR1.fst, max = _sAR1.snd;
const rSize = max - min + 1;
const { start, end } = getStartEnd(b, min, max);
const commonCount = end - start;
// No common elements.
if (commonCount === 0) return a;
const resultSize = rSize - commonCount;
// A is subset of B
if (resultSize <= 0) return Empty;
const ret = new Int32Array(resultSize);
const li = b.length - 1;
const fst = b[Math.min(start, li)], last = b[Math.min(end, li)];
let offset = 0;
for (let i = min; i < fst; i++) ret[offset++] = i;
for (let i = fst; i <= last; i++) {
if (binarySearchRange(b, i, start, end) < 0) ret[offset++] = i;
}
for (let i = last + 1; i <= max; i++) ret[offset++] = i;
return ofSortedArray(ret);
}
function subtractAA(a: SortedArray, b: SortedArray) {
if (a === b) return Empty;
const lenA = a.length;
let { i: sI, j: sJ, endA, endB } = getMaxIntersectionRange(a, b);
let i = sI, j = sJ;
let commonCount = 0;
while (i <= endA && j <= endB) {
const x = a[i], y = b[j];
if (x < y) { i++; }
else if (x > y) { j++; }
else { i++; j++; commonCount++; }
}
// A isnt intersecting B ===> A
if (!commonCount) return a;
// A === B || A is subset of B ===> Empty
if (commonCount >= lenA) return Empty;
const indices = new Int32Array(lenA - commonCount);
let offset = 0;
// insert the "prefix"
for (let k = 0; k < sI; k++) indices[offset++] = a[k];
i = sI;
j = sJ;
while (i <= endA && j <= endB) {
const x = a[i], y = b[j];
if (x < y) { indices[offset++] = x; i++; }
else if (x > y) { j++; }
else { i++; j++; }
}
// insert the "tail"
for (; i < lenA; i++) indices[offset++] = a[i];
return ofSortedArray(indices);
}
\ 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 Iterator from '../iterator'
import OrderedSet from '../ordered-set'
class SegmentIterator implements Iterator<{ segmentIndex: number } & OrderedSet.IndexRange> {
private segmentRange = OrderedSet.IndexRange();
private setRange = OrderedSet.IndexRange();
private value = { segmentIndex: 0, start: 0, end: 0 };
private last: number = 0;
[Symbol.iterator]() { return new SegmentIterator(this.segments, this.set); };
done: boolean = false;
next() {
const value = this.move();
return { value, done: this.done }
}
move() {
this.done = this.segmentRange.end <= this.segmentRange.start || this.setRange.end <= this.setRange.start;
while (!this.done) {
if (!this.updateValue()) {
this.updateSegmentRange();
} else {
this.value.segmentIndex = this.segmentRange.start++;
break;
}
}
return this.value;
}
private getSegmentIndex(value: number) {
if (value >= this.last) return -1;
return OrderedSet.getPredIndex(this.segments, value - 1);
}
private updateValue() {
const segmentEnd = OrderedSet.getAt(this.segments, this.segmentRange.start + 1);
const end = OrderedSet.getPredIndex1(this.set, segmentEnd, this.setRange.start, this.setRange.end);
this.value.start = this.setRange.start;
this.value.end = end;
this.setRange.start = end;
return end > this.value.start;
}
private updateSegmentRange() {
const min = OrderedSet.getAt(this.set, this.setRange.start), max = OrderedSet.getAt(this.set, this.setRange.end - 1);
this.segmentRange.start = this.getSegmentIndex(min);
this.segmentRange.end = this.getSegmentIndex(max) + 1;
this.done = this.segmentRange.end <= this.segmentRange.start || this.setRange.end <= this.setRange.start;
}
constructor(private segments: OrderedSet, private set: OrderedSet) {
this.last = OrderedSet.max(segments);
this.setRange.end = OrderedSet.size(set);
this.updateSegmentRange();
}
}
function createIterator(segments: OrderedSet, set: OrderedSet) {
return new SegmentIterator(segments, set);
}
export default createIterator
\ No newline at end of file
......@@ -4,7 +4,16 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
import OrderedSet from '../mol-base/collections/ordered-set'
interface Conformation {
x: ArrayLike<number>,
y: ArrayLike<number>,
z: ArrayLike<number>,
// Assign a secondary structure type to each residue.
secondaryStructureType: ArrayLike<any>,
secondaryStructureAtomOffsets: OrderedSet
}
export default Conformation
......@@ -6,7 +6,25 @@
// TODO: define property accessor intefaces, graphs, spatial lookups and what have you.
import * as Formats from './model/formats'
import CommonInterface from './model/interfaces/common'
import MacromoleculeInterface from './model/interfaces/common'
import OrderedSet from '../mol-base/collections/ordered-set'
interface Model {
data: Formats.RawData,
common: CommonInterface,
macromolecule: MacromoleculeInterface
// Atom offsets of the "i-th chain" stored as a closed-open range [chainOffsets[i], chainOffsets[i + 1])
chainSegments: OrderedSet,
// Atom offsets of the "i-th residue" stored as a closed-open range [residueOffsets[i], residueOffsets[i + 1])
residueSegments: OrderedSet,
// Mapping from a residue index to chain index
residueChainIndex: ArrayLike<number>,
// Mapping from an atom into to residue index
atomResidueIndex: ArrayLike<number>
}
export default Model
/**
* Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
export type RawData = {}
\ No newline at end of file
......@@ -4,4 +4,8 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
// TODO: define basic hierarchy, sec. structure. etc.
\ No newline at end of file
interface Common {
}
export default Common
\ No newline at end of file
......@@ -4,4 +4,8 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
// TODO: map parts of mmCIF schema to create interfaces
\ No newline at end of file
interface Macromolecule {
}
export default Macromolecule
\ No newline at end of file
......@@ -234,4 +234,14 @@ export namespace Build {
}
}
Build.run();
\ No newline at end of file
export function testSegments() {
const data = OrdSet.ofSortedArray([4, 9, 10, 11, 14, 15, 16]);
const segs = OrdSet.ofSortedArray([0, 4, 10, 12, 13, 15, 25]);
const it = OrdSet.segments(segs, data);
for (let s = it.move(); !it.done; s = it.move()) {
for (let j = s.start; j < s.end; j++) {
console.log(`${s.segmentIndex}: ${OrdSet.getAt(data, j)}`);
}
}
}
\ No newline at end of file
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