UNPKG

molstar

Version:

A comprehensive macromolecular library.

430 lines (429 loc) 17.1 kB
/** * Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import * as ColumnHelpers from './column-helpers'; import { Tensor as Tensors } from '../../mol-math/linear-algebra'; import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../../mol-io/reader/common/text/number-parser'; var Column; (function (Column) { let Schema; (function (Schema) { // T also serves as a default value for undefined columns Schema.str = { '@type': 'str', T: '', valueType: 'str' }; Schema.ustr = { '@type': 'str', T: '', valueType: 'str', transform: 'uppercase' }; Schema.lstr = { '@type': 'str', T: '', valueType: 'str', transform: 'lowercase' }; Schema.int = { '@type': 'int', T: 0, valueType: 'int' }; Schema.coord = { '@type': 'coord', T: 0, valueType: 'float' }; Schema.float = { '@type': 'float', T: 0, valueType: 'float' }; function Str(options) { var _a; return { '@type': 'str', T: (_a = options === null || options === void 0 ? void 0 : options.defaultValue) !== null && _a !== void 0 ? _a : '', transform: options === null || options === void 0 ? void 0 : options.transform, valueType: 'str' }; } Schema.Str = Str; ; function Int(defaultValue = 0) { return { '@type': 'int', T: defaultValue, valueType: 'int' }; } Schema.Int = Int; ; function Float(defaultValue = 0) { return { '@type': 'float', T: defaultValue, valueType: 'float' }; } Schema.Float = Float; ; function Tensor(space, baseType = Schema.float) { return { '@type': 'tensor', T: space.create(), space, valueType: 'tensor', baseType }; } Schema.Tensor = Tensor; function Vector(dim, baseType = Schema.float) { return Tensor(Tensors.Vector(dim, baseType['@type'] === 'int' ? Int32Array : Float64Array), baseType); } Schema.Vector = Vector; function Matrix(rows, cols, baseType = Schema.float) { return Tensor(Tensors.ColumnMajorMatrix(rows, cols, baseType['@type'] === 'int' ? Int32Array : Float64Array), baseType); } Schema.Matrix = Matrix; function Aliased(t) { return t; } Schema.Aliased = Aliased; function List(separator, itemParse, defaultValue = []) { return { '@type': 'list', T: defaultValue, separator, itemParse, valueType: 'list' }; } Schema.List = List; })(Schema = Column.Schema || (Column.Schema = {})); function is(v) { return !!v && !!v.schema && !!v.value; } Column.is = is; Column.ValueKind = { /** Defined value (= 0) */ Present: 0 /* ValueKinds.Present */, /** Expressed in CIF as `.` (= 1) */ NotPresent: 1 /* ValueKinds.NotPresent */, /** Expressed in CIF as `?` (= 2) */ Unknown: 2 /* ValueKinds.Unknown */ }; function Undefined(rowCount, schema) { return constColumn(schema['T'], rowCount, schema, 1 /* ValueKinds.NotPresent */); } Column.Undefined = Undefined; function ofConst(v, rowCount, type) { return constColumn(v, rowCount, type, 0 /* ValueKinds.Present */); } Column.ofConst = ofConst; function ofLambda(spec) { return lambdaColumn(spec); } Column.ofLambda = ofLambda; /** values [min, max] (i.e. include both values) */ function range(min, max) { return ofLambda({ value: i => i + min, rowCount: Math.max(max - min + 1, 0), schema: Schema.int }); } Column.range = range; function ofArray(spec) { return arrayColumn(spec); } Column.ofArray = ofArray; function ofIntArray(array) { return arrayColumn({ array, schema: Schema.int }); } Column.ofIntArray = ofIntArray; function ofFloatArray(array) { return arrayColumn({ array, schema: Schema.float }); } Column.ofFloatArray = ofFloatArray; function ofStringArray(array) { return arrayColumn({ array, schema: Schema.str }); } Column.ofStringArray = ofStringArray; function ofStringAliasArray(array) { return arrayColumn({ array, schema: Schema.Aliased(Schema.str) }); } Column.ofStringAliasArray = ofStringAliasArray; function ofStringListArray(array, separator = ',') { return arrayColumn({ array, schema: Schema.List(separator, x => x) }); } Column.ofStringListArray = ofStringListArray; function ofIntTokens(tokens) { const { count, data, indices } = tokens; return lambdaColumn({ value: (row) => fastParseInt(data, indices[2 * row], indices[2 * row + 1]) || 0, rowCount: count, schema: Schema.int, }); } Column.ofIntTokens = ofIntTokens; function ofFloatTokens(tokens) { const { count, data, indices } = tokens; return lambdaColumn({ value: (row) => fastParseFloat(data, indices[2 * row], indices[2 * row + 1]) || 0, rowCount: count, schema: Schema.float, }); } Column.ofFloatTokens = ofFloatTokens; function ofStringTokens(tokens) { const { count, data, indices } = tokens; return lambdaColumn({ value: (row) => { const ret = data.substring(indices[2 * row], indices[2 * row + 1]); if (ret === '.' || ret === '?') return ''; return ret; }, rowCount: count, schema: Schema.str, }); } Column.ofStringTokens = ofStringTokens; function window(column, start, end) { return windowColumn(column, start, end); } Column.window = window; function view(column, indices, checkIndentity = true) { return columnView(column, indices, checkIndentity); } Column.view = view; /** A map of the 1st occurence of each value. */ function createFirstIndexMap(column) { return createFirstIndexMapOfColumn(column); } Column.createFirstIndexMap = createFirstIndexMap; function createIndexer(column) { return createIndexerOfColumn(column); } Column.createIndexer = createIndexer; function mapToArray(column, f, ctor) { return mapToArrayImpl(column, f, ctor || Array); } Column.mapToArray = mapToArray; function areEqual(a, b) { return areColumnsEqual(a, b); } Column.areEqual = areEqual; function indicesOf(c, test) { return columnIndicesOf(c, test); } Column.indicesOf = indicesOf; /** Makes the column backed by an array. Useful for columns that are accessed often. */ function asArrayColumn(c, array) { if (c.__array) return c; if (!c.isDefined) return Undefined(c.rowCount, c.schema); return arrayColumn({ array: c.toArray({ array }), schema: c.schema, valueKind: c.valueKind }); } Column.asArrayColumn = asArrayColumn; function copyToArray(c, array, offset = 0) { if (!c.isDefined) return; const cArray = c.__array; if (cArray) { for (let i = 0, _i = cArray.length; i < _i; i++) array[offset + i] = cArray[i]; } else { for (let i = 0, _i = c.rowCount; i < _i; i++) array[offset + i] = c.value(i); } } Column.copyToArray = copyToArray; function isIdentity(c) { for (let i = 0, _i = c.rowCount; i < _i; i++) { if (i !== c.value(i)) return false; } return true; } Column.isIdentity = isIdentity; })(Column || (Column = {})); export { Column }; function createFirstIndexMapOfColumn(c) { const map = new Map(); for (let i = 0, _i = c.rowCount; i < _i; i++) { const v = c.value(i); if (!map.has(v)) map.set(c.value(i), i); } return map; } function createIndexerOfColumn(c) { const map = new Map(); for (let i = 0, _i = c.rowCount; i < _i; i++) { const v = c.value(i); if (!map.has(v)) map.set(c.value(i), i); } return v => map.has(v) ? map.get(v) : -1; } function constColumn(v, rowCount, schema, valueKind) { const value = row => v; return { schema: schema, __array: void 0, isDefined: valueKind === 0 /* Column.ValueKinds.Present */, rowCount, value, valueKind: row => valueKind, toArray: params => { const { array } = ColumnHelpers.createArray(rowCount, params); for (let i = 0, _i = array.length; i < _i; i++) array[i] = v; return array; }, areValuesEqual: (rowA, rowB) => true }; } function lambdaColumn({ value, valueKind, areValuesEqual, rowCount, schema }) { return { schema: schema, __array: void 0, isDefined: true, rowCount, value, valueKind: valueKind ? valueKind : row => 0 /* Column.ValueKinds.Present */, toArray: params => { const { array, start } = ColumnHelpers.createArray(rowCount, params); for (let i = 0, _i = array.length; i < _i; i++) array[i] = value(i + start); return array; }, areValuesEqual: areValuesEqual ? areValuesEqual : (rowA, rowB) => value(rowA) === value(rowB) }; } function arrayColumn({ array, schema, valueKind }) { const rowCount = array.length; const defaultValue = schema.T; const value = schema.valueType === 'str' ? schema.transform === 'lowercase' ? row => { const v = array[row]; return typeof v === 'string' ? v.toLowerCase() : `${v !== null && v !== void 0 ? v : defaultValue}`.toLowerCase(); } : schema.transform === 'uppercase' ? row => { const v = array[row]; return typeof v === 'string' ? v.toUpperCase() : `${v !== null && v !== void 0 ? v : defaultValue}`.toUpperCase(); } : row => { const v = array[row]; return typeof v === 'string' ? v : `${v !== null && v !== void 0 ? v : defaultValue}`; } : row => array[row]; const isTyped = ColumnHelpers.isTypedArray(array); return { schema: schema, __array: array, isDefined: true, rowCount, value, valueKind: valueKind ? valueKind : row => 0 /* Column.ValueKinds.Present */, toArray: schema.valueType === 'str' ? schema.transform === 'lowercase' ? params => { const { start, end } = ColumnHelpers.getArrayBounds(rowCount, params); const ret = new (params && typeof params.array !== 'undefined' ? params.array : array.constructor)(end - start); for (let i = 0, _i = end - start; i < _i; i++) { const v = array[start + i]; ret[i] = typeof v === 'string' ? v.toLowerCase() : `${v !== null && v !== void 0 ? v : defaultValue}`.toLowerCase(); } return ret; } : schema.transform === 'uppercase' ? params => { const { start, end } = ColumnHelpers.getArrayBounds(rowCount, params); const ret = new (params && typeof params.array !== 'undefined' ? params.array : array.constructor)(end - start); for (let i = 0, _i = end - start; i < _i; i++) { const v = array[start + i]; ret[i] = typeof v === 'string' ? v.toUpperCase() : `${v !== null && v !== void 0 ? v : defaultValue}`.toUpperCase(); } return ret; } : params => { const { start, end } = ColumnHelpers.getArrayBounds(rowCount, params); const ret = new (params && typeof params.array !== 'undefined' ? params.array : array.constructor)(end - start); for (let i = 0, _i = end - start; i < _i; i++) { const v = array[start + i]; ret[i] = typeof v === 'string' ? v : `${v !== null && v !== void 0 ? v : defaultValue}`; } return ret; } : isTyped ? params => ColumnHelpers.typedArrayWindow(array, params) : params => { const { start, end } = ColumnHelpers.getArrayBounds(rowCount, params); if (start === 0 && end === array.length) return array; const ret = new (params && typeof params.array !== 'undefined' ? params.array : array.constructor)(end - start); for (let i = 0, _i = end - start; i < _i; i++) ret[i] = array[start + i]; return ret; }, areValuesEqual: (rowA, rowB) => array[rowA] === array[rowB] }; } function windowColumn(column, start, end) { if (!column.isDefined) return Column.Undefined(end - start, column.schema); if (start === 0 && end === column.rowCount) return column; if (!!column.__array && ColumnHelpers.isTypedArray(column.__array)) return windowTyped(column, start, end); return windowFull(column, start, end); } function windowTyped(c, start, end) { const array = ColumnHelpers.typedArrayWindow(c.__array, { start, end }); const vk = c.valueKind; return arrayColumn({ array, schema: c.schema, valueKind: row => vk(start + row) }); } function windowFull(c, start, end) { const v = c.value, vk = c.valueKind, ave = c.areValuesEqual; const value = start === 0 ? v : row => v(row + start); const rowCount = end - start; return { schema: c.schema, __array: void 0, isDefined: c.isDefined, rowCount, value, valueKind: start === 0 ? vk : row => vk(row + start), toArray: params => { const { array } = ColumnHelpers.createArray(rowCount, params); for (let i = 0, _i = array.length; i < _i; i++) array[i] = v(i + start); return array; }, areValuesEqual: start === 0 ? ave : (rowA, rowB) => ave(rowA + start, rowB + start) }; } function isIdentity(map, rowCount) { if (map.length !== rowCount) return false; for (let i = 0, _i = map.length; i < _i; i++) { if (map[i] !== i) return false; } return true; } function columnView(c, map, checkIdentity) { if (c.rowCount === 0) return c; if (checkIdentity && isIdentity(map, c.rowCount)) return c; if (!!c.__array && typeof c.value(0) === typeof c.__array[0]) return arrayView(c, map); return viewFull(c, map); } function arrayView(c, map) { const array = c.__array; const ret = new array.constructor(map.length); for (let i = 0, _i = map.length; i < _i; i++) ret[i] = array[map[i]]; const vk = c.valueKind; return arrayColumn({ array: ret, schema: c.schema, valueKind: row => vk(map[row]) }); } function viewFull(c, map) { const v = c.value, vk = c.valueKind, ave = c.areValuesEqual; const value = row => v(map[row]); const rowCount = map.length; return { schema: c.schema, __array: void 0, isDefined: c.isDefined, rowCount, value, valueKind: row => vk(map[row]), toArray: params => { const { array } = ColumnHelpers.createArray(rowCount, params); for (let i = 0, _i = array.length; i < _i; i++) array[i] = v(map[i]); return array; }, areValuesEqual: (rowA, rowB) => ave(map[rowA], map[rowB]) }; } function mapToArrayImpl(c, f, ctor) { const ret = new ctor(c.rowCount); for (let i = 0, _i = c.rowCount; i < _i; i++) ret[i] = f(c.value(i)); return ret; } function areColumnsEqual(a, b) { if (a === b) return true; if (a.rowCount !== b.rowCount || a.isDefined !== b.isDefined || a.schema.valueType !== b.schema.valueType) return false; if (!!a.__array && !!b.__array) return areArraysEqual(a, b); return areValuesEqual(a, b); } function areArraysEqual(a, b) { const xs = a.__array, ys = b.__array; for (let i = 0, _i = a.rowCount; i < _i; i++) { if (xs[i] !== ys[i]) return false; } return true; } function areValuesEqual(a, b) { const va = a.value, vb = b.value; for (let i = 0, _i = a.rowCount; i < _i; i++) { if (va(i) !== vb(i)) return false; } return true; } function columnIndicesOf(c, test) { const ret = [], v = c.value; for (let i = 0, _i = c.rowCount; i < _i; i++) { if (test(v(i))) ret[ret.length] = i; } return ret; }