diff --git a/src/mol-data/db/column.ts b/src/mol-data/db/column.ts index be5a2b17113b76fd1bfe3d53e8160a3edacfbdaf..76a893cb9b149267420b39a287ea91a02a2c818e 100644 --- a/src/mol-data/db/column.ts +++ b/src/mol-data/db/column.ts @@ -25,8 +25,6 @@ namespace Column { export type Schema<T = any> = Schema.Str | Schema.Int | Schema.Float | Schema.Coordinate | Schema.Aliased<T> | Schema.Tensor export namespace Schema { - export type Scalar<T = any> = Schema.Str | Schema.Int | Schema.Float | Schema.Coordinate | Schema.Aliased<T> - export type Str = { '@type': 'str', T: string, valueKind: 'str' } export type Int = { '@type': 'int', T: number, valueKind: 'int' } export type Float = { '@type': 'float', T: number, valueKind: 'float' } @@ -44,7 +42,7 @@ namespace Column { export function vector(dim: number): Tensor { return tensor(Tensors.Vector(dim)); } export function matrix(rows: number, cols: number): Tensor { return tensor(Tensors.ColumnMajorMatrix(rows, cols)); } - export function aliased<T>(t: Schema): Aliased<T> { return t as any as Aliased<T>; } + export function aliased<T>(t: Str | Int): Aliased<T> { return t as any as Aliased<T>; } } export interface ToArrayParams<T> { diff --git a/src/mol-io/reader/cif/binary/field.ts b/src/mol-io/reader/cif/binary/field.ts index 89e2c47af7f28c42cd7490d3a4a56bea03a5e855..c3b2ad33faaffda2590d25d08f34b1c4d215218f 100644 --- a/src/mol-io/reader/cif/binary/field.ts +++ b/src/mol-io/reader/cif/binary/field.ts @@ -9,10 +9,6 @@ import * as Data from '../data-model' import { EncodedColumn, decode } from '../../../common/binary-cif' import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../../common/text/number-parser' -function wrap(o: Data.Field) { - return { ...o }; -} - export default function Field(column: EncodedColumn): Data.Field { const mask = column.mask ? decode(column.mask) as number[] : void 0; const data = decode(column.data); @@ -40,7 +36,7 @@ export default function Field(column: EncodedColumn): Data.Field { const rowCount = data.length; - return wrap({ + return { '@array': data, isDefined: true, rowCount, @@ -56,5 +52,5 @@ export default function Field(column: EncodedColumn): Data.Field { toFloatArray: isNumeric ? params => ColumnHelpers.typedArrayWindow(data, params) : params => ColumnHelpers.createAndFillArray(rowCount, float, params) - }); + }; } \ No newline at end of file diff --git a/src/mol-io/reader/cif/schema.ts b/src/mol-io/reader/cif/schema.ts index deb96faffdb3be8a3c3a38e4bbe0beccf5a9141b..8a538d9a363ad431c0f0158f8da0391fd3e61671 100644 --- a/src/mol-io/reader/cif/schema.ts +++ b/src/mol-io/reader/cif/schema.ts @@ -4,8 +4,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Data from './data-model' import { Database, Table, Column, ColumnHelpers } from 'mol-data/db' +import { Tensor } from 'mol-math/linear-algebra' +import * as Data from './data-model' export function toDatabase<Schema extends Database.Schema, Frame extends Database<Schema> = Database<Schema>>(schema: Schema, frame: Data.Frame): Frame { return createDatabase(schema, frame) as Frame; @@ -22,18 +23,13 @@ function getColumnCtor(t: Column.Schema): ColumnCtor { case 'str': return (f, c, k) => createColumn(t, f, f.str, f.toStringArray); case 'int': return (f, c, k) => createColumn(t, f, f.int, f.toIntArray); case 'float': return (f, c, k) => createColumn(t, f, f.float, f.toFloatArray); - case 'tensor': return (f, c, k) => { - const space = t.space; - const value = (row: number) => Data.getTensor(c, k, space, row); - return createColumn(t, f, value, params => ColumnHelpers.createAndFillArray(f.rowCount, value, params)); - } + case 'tensor': throw new Error(`Use createTensorColumn instead.`); } } - function createColumn<T>(schema: Column.Schema, field: Data.Field, value: (row: number) => T, toArray: Column<T>['toArray']): Column<T> { return { - schema: schema, + schema, '@array': field['@array'], isDefined: field.isDefined, rowCount: field.rowCount, @@ -44,6 +40,24 @@ function createColumn<T>(schema: Column.Schema, field: Data.Field, value: (row: }; } +function createTensorColumn(schema: Column.Schema.Tensor, category: Data.Category, key: string): Column<Tensor> { + const space = schema.space; + const first = category.getField(`${key}[1]`) || Column.Undefined(category.rowCount, schema); + const value = (row: number) => Data.getTensor(category, key, space, row); + const toArray: Column<Tensor>['toArray'] = params => ColumnHelpers.createAndFillArray(category.rowCount, value, params) + + return { + schema, + '@array': void 0, + isDefined: first.isDefined, + rowCount: category.rowCount, + value, + valueKind: first.valueKind, + areValuesEqual: (rowA, rowB) => Tensor.areEqualExact(value(rowA), value(rowB)), + toArray + }; +} + class CategoryTable implements Table<any> { // tslint:disable-line:class-name _rowCount: number; _columns: ReadonlyArray<string>; @@ -57,13 +71,17 @@ class CategoryTable implements Table<any> { // tslint:disable-line:class-name this._schema = schema; const cache = Object.create(null); for (const k of fieldKeys) { - const cType = schema[k]; - const ctor = getColumnCtor(cType); Object.defineProperty(this, k, { get: function() { if (cache[k]) return cache[k]; - const field = category.getField(k); - cache[k] = !!field ? ctor(field, category, k) : Column.Undefined(category.rowCount, cType); + const cType = schema[k]; + if (cType.valueKind === 'tensor') { + cache[k] = createTensorColumn(cType, category, k); + } else { + const ctor = getColumnCtor(cType); + const field = category.getField(k); + cache[k] = !!field ? ctor(field, category, k) : Column.Undefined(category.rowCount, cType); + } return cache[k]; }, enumerable: true, diff --git a/src/mol-math/linear-algebra/tensor.ts b/src/mol-math/linear-algebra/tensor.ts index e5a872b9ed58f71a8b4acb992bfbd822cb58275b..3efd39d60ebb057788b8e4bda0e12ff292ea971c 100644 --- a/src/mol-math/linear-algebra/tensor.ts +++ b/src/mol-math/linear-algebra/tensor.ts @@ -75,6 +75,13 @@ export namespace Tensor { return vec; } + export function areEqualExact(a: Tensor, b: Tensor) { + const len = a.length; + if (len !== b.length) return false; + for (let i = 0; i < len; i++) if (a[i] !== b[i]) return false; + return true; + } + function accessors(layout: Layout): { get: Space['get'], set: Space['set'] } { const { dimensions, axisOrderFastToSlow: ao } = layout; switch (dimensions.length) { diff --git a/src/perf-tests/structure.ts b/src/perf-tests/structure.ts index 62c780e59418929245801c1a19cda96e74ed4713..3ae723fc755aa4eae7250d397a0bed8c21113a44 100644 --- a/src/perf-tests/structure.ts +++ b/src/perf-tests/structure.ts @@ -243,8 +243,11 @@ export namespace PropertyAccess { export async function run() { //const { structures, models } = await readCIF('./examples/1cbs_full.bcif'); - const { structures, models } = await readCIF('e:/test/quick/3j3q_full.bcif'); - //const { structures, models } = await readCIF('e:/test/quick/1cbs_updated.cif'); + const { structures, models, mmcif } = await readCIF('e:/test/quick/3j3q_full.bcif'); + //const { structures, models, mmcif } = await readCIF('e:/test/quick/1cbs_updated.cif'); + + console.log(mmcif.pdbx_struct_oper_list.matrix.toArray()); + console.log(mmcif.pdbx_struct_oper_list.vector.toArray()); //const { structures, models } = await readCIF('e:/test/molstar/3j3q.bcif'); @@ -255,8 +258,6 @@ export namespace PropertyAccess { // return; - console.log('parsed'); - console.log(baseline(models[0])); console.log(sumProperty(structures[0], l => l.unit.model.conformation.atomId.value(l.atom))); console.log(sumPropertySegmented(structures[0], l => l.unit.model.conformation.atomId.value(l.atom)));