Browse Source

Unified Column.Type with Column.Schema, removed floating point precisions

David Sehnal 7 years ago
parent
commit
29d2523958

+ 1 - 1
src/apps/domain-annotation-server/utils.ts

@@ -20,7 +20,7 @@ function ofSchema(schema: Table.Schema) {
     const fields: Encoder.FieldDefinition[] = [];
     for (const k of Object.keys(schema)) {
         const t = schema[k];
-        const type: any = t.kind === 'str' ? Encoder.FieldType.Str : t.kind === 'int' ? Encoder.FieldType.Int : Encoder.FieldType.Float;
+        const type: any = t.valueKind === 'str' ? Encoder.FieldType.Str : t.valueKind === 'int' ? Encoder.FieldType.Int : Encoder.FieldType.Float;
         fields.push({ name: k, type, value: columnValue(k), valueKind: columnValueKind(k) })
     }
     return fields;

+ 13 - 13
src/mol-data/db/_spec/table.spec.ts

@@ -9,14 +9,14 @@ import Column from '../column'
 import Table from '../table'
 
 describe('column', () => {
-    const cc = Column.ofConst(10, 2, Column.Type.int);
-    const arr = Column.ofArray({ array: [1, 2, 3, 4], type: Column.Type.int });
+    const cc = Column.ofConst(10, 2, Column.Schema.int);
+    const arr = Column.ofArray({ array: [1, 2, 3, 4], schema: Column.Schema.int });
     const arrWindow = Column.window(arr, 1, 3);
 
-    const typed = Column.ofArray({ array: new Int32Array([1, 2, 3, 4]), type: Column.Type.int });
+    const typed = Column.ofArray({ array: new Int32Array([1, 2, 3, 4]), schema: Column.Schema.int });
     const typedWindow = Column.window(typed, 1, 3);
 
-    const numStr = Column.ofArray({ array: [1, 2] as any, type: Column.Type.str });
+    const numStr = Column.ofArray({ array: [1, 2] as any, schema: Column.Schema.str });
 
     it('constant', () => {
         expect(cc.rowCount).toBe(2);
@@ -68,8 +68,8 @@ describe('table', () => {
 
     it('ofColumns', () => {
         const t = Table.ofColumns(schema, {
-            x: Column.ofArray({ array: [10, -1], type: Column.Type.int }),
-            n: Column.ofArray({ array: ['row1', 'row2'], type: Column.Type.str }),
+            x: Column.ofArray({ array: [10, -1], schema: Column.Schema.int }),
+            n: Column.ofArray({ array: ['row1', 'row2'], schema: Column.Schema.str }),
         });
         expect(t.x.toArray()).toEqual([10, -1]);
         expect(t.n.toArray()).toEqual(['row1', 'row2']);
@@ -86,11 +86,11 @@ describe('table', () => {
 
     it('pickColumns', () => {
         const t = Table.ofColumns(schema, {
-            x: Column.ofArray({ array: [10, -1], type: Column.Type.int }),
-            n: Column.ofArray({ array: ['row1', 'row2'], type: Column.Type.str }),
+            x: Column.ofArray({ array: [10, -1], schema: Column.Schema.int }),
+            n: Column.ofArray({ array: ['row1', 'row2'], schema: Column.Schema.str }),
         });
         const s = { x: Column.Schema.int, y: Column.Schema.int };
-        const picked = Table.pickColumns(s, t, { y: Column.ofArray({ array: [3, 4], type: Column.Type.int })});
+        const picked = Table.pickColumns(s, t, { y: Column.ofArray({ array: [3, 4], schema: Column.Schema.int })});
         expect(picked._columns).toEqual(['x', 'y']);
         expect(picked._rowCount).toEqual(2);
         expect(picked.x.toArray()).toEqual([10, -1]);
@@ -99,8 +99,8 @@ describe('table', () => {
 
     it('view', () => {
         const t = Table.ofColumns(schema, {
-            x: Column.ofArray({ array: [10, -1], type: Column.Type.int }),
-            n: Column.ofArray({ array: ['row1', 'row2'], type: Column.Type.str }),
+            x: Column.ofArray({ array: [10, -1], schema: Column.Schema.int }),
+            n: Column.ofArray({ array: ['row1', 'row2'], schema: Column.Schema.str }),
         });
         const s = { x: Column.Schema.int };
         const view = Table.view(t, s, [1]);
@@ -111,8 +111,8 @@ describe('table', () => {
 
     it('sort', () => {
         const t = Table.ofColumns<typeof schema>(schema, {
-            x: Column.ofArray({ array: [10, -1], type: Column.Type.int }),
-            n: Column.ofArray({ array: ['row1', 'row2'], type: Column.Type.str }),
+            x: Column.ofArray({ array: [10, -1], schema: Column.Schema.int }),
+            n: Column.ofArray({ array: ['row1', 'row2'], schema: Column.Schema.str }),
         });
         const { x } = t;
         const sorted = Table.sort(t, (i, j) => x.value(i) - x.value(j))

+ 43 - 66
src/mol-data/db/column.ts

@@ -8,7 +8,7 @@ import * as ColumnHelpers from './column-helpers'
 import { Tensor as Tensors } from 'mol-math/linear-algebra'
 
 interface Column<T> {
-    readonly '@type': Column.Type,
+    readonly _schema: Column.Schema,
     readonly '@array': ArrayLike<any> | undefined,
 
     readonly isDefined: boolean,
@@ -20,53 +20,30 @@ interface Column<T> {
 }
 
 namespace Column {
-    export type Type<T = any> = Type.Str | Type.Int | Type.Float | Type.Tensor | Type.Aliased<T>
     export type ArrayCtor<T> = { new(size: number): ArrayLike<T> }
 
-    export namespace Type {
-        export type Str = { T: string, kind: 'str' }
-        export type Int = { T: number, kind: 'int' }
-        export type Float = { T: number, kind: 'float' }
-        export type Tensor = { T: Tensors, space: Tensors.Space, kind: 'tensor' };
-        export type Aliased<T> = { T: T } & { kind: 'str' | 'int' | 'float' }
-
-        export const str: Str = { T: '', kind: 'str' };
-        export const int: Int = { T: 0, kind: 'int' };
-        export const float: Float = { T: 0, kind: 'float' };
-
-        export function tensor(space: Tensors.Space): Tensor { return { T: space.create(), space, kind: 'tensor' }; }
-        export function aliased<T>(t: Type): Aliased<T> { return t as any as Aliased<T>; }
-    }
-
     export type Schema<T = any> = Schema.Str | Schema.Int | Schema.Float | Schema.Coordinate | Schema.Aliased<T> | Schema.Tensor
 
     export namespace Schema {
-        export interface FloatPrecision {
-            low: number,
-            acceptable: number,
-            full: number
-        }
-
         export type Scalar<T = any> = Schema.Str | Schema.Int | Schema.Float | Schema.Coordinate | Schema.Aliased<T>
 
-        export function FP(full: number, acceptable: number, low: number): FloatPrecision { return { low, full, acceptable }; }
-
-        export type Str = { '@type': 'str', T: string, kind: 'str' }
-        export type Int = { '@type': 'int', T: number, kind: 'int' }
-        export type Float = { '@type': 'float', T: number, kind: 'float', precision: FloatPrecision }
-        export type Coordinate = { '@type': 'coord', T: number, kind: 'float' }
+        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' }
+        export type Coordinate = { '@type': 'coord', T: number, valueKind: 'float' }
 
-        export type Tensor = { '@type': 'tensor', T: Tensors, space: Tensors.Space, kind: 'tensor' };
-        export type Aliased<T> = { '@type': 'aliased', T: T } & { kind: 'str' | 'int' | 'float' }
+        export type Tensor = { '@type': 'tensor', T: Tensors, space: Tensors.Space, valueKind: 'tensor' };
+        export type Aliased<T> = { '@type': 'aliased', T: T, valueKind: 'str' | 'int' }
 
-        export const str: Str = { '@type': 'str', T: '', kind: 'str' };
-        export const int: Int = { '@type': 'int', T: 0, kind: 'int' };
-        export const coord: Coordinate = { '@type': 'coord', T: 0, kind: 'float' };
-        export function float(precision: FloatPrecision): Float { return { '@type': 'float', T: 0, kind: 'float', precision } };
+        export const str: Str = { '@type': 'str', T: '', valueKind: 'str' };
+        export const int: Int = { '@type': 'int', T: 0, valueKind: 'int' };
+        export const coord: Coordinate = { '@type': 'coord', T: 0, valueKind: 'float' };
+        export const float: Float = { '@type': 'float', T: 0, valueKind: 'float' };
 
-        export function tensor(space: Tensors.Space): Tensor { return { '@type': 'tensor', T: space.create(), space, kind: 'tensor' }; }
+        export function tensor(space: Tensors.Space): Tensor { return { '@type': 'tensor', T: space.create(), space, valueKind: 'tensor' }; }
         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>; }
     }
 
@@ -77,53 +54,53 @@ namespace Column {
         end?: number
     }
 
-    export interface LambdaSpec<T extends Type> {
+    export interface LambdaSpec<T extends Schema> {
         value: (row: number) => T['T'],
         rowCount: number,
-        type: T,
+        schema: T,
         valueKind?: (row: number) => ValueKind,
     }
 
-    export interface ArraySpec<T extends Type> {
+    export interface ArraySpec<T extends Schema> {
         array: ArrayLike<T['T']>,
-        type: T,
+        schema: T,
         valueKind?: (row: number) => ValueKind
     }
 
-    export interface MapSpec<S extends Type, T extends Type> {
+    export interface MapSpec<S extends Schema, T extends Schema> {
         f: (v: S['T']) => T['T'],
-        type: T,
+        schema: T,
         valueKind?: (row: number) => ValueKind,
     }
 
     export const enum ValueKind { Present = 0, NotPresent = 1, Unknown = 2 }
 
-    export function Undefined<T extends Type>(rowCount: number, type: T): Column<T['T']> {
-        return constColumn(type['T'], rowCount, type, ValueKind.NotPresent);
+    export function Undefined<T extends Schema>(rowCount: number, schema: T): Column<T['T']> {
+        return constColumn(schema['T'], rowCount, schema, ValueKind.NotPresent);
     }
 
-    export function ofConst<T extends Type>(v: T['T'], rowCount: number, type: T): Column<T['T']> {
+    export function ofConst<T extends Schema>(v: T['T'], rowCount: number, type: T): Column<T['T']> {
         return constColumn(v, rowCount, type, ValueKind.Present);
     }
 
-    export function ofLambda<T extends Type>(spec: LambdaSpec<T>): Column<T['T']> {
+    export function ofLambda<T extends Schema>(spec: LambdaSpec<T>): Column<T['T']> {
         return lambdaColumn(spec);
     }
 
-    export function ofArray<T extends Column.Type>(spec: Column.ArraySpec<T>): Column<T['T']> {
+    export function ofArray<T extends Column.Schema>(spec: Column.ArraySpec<T>): Column<T['T']> {
         return arrayColumn(spec);
     }
 
     export function ofIntArray(array: ArrayLike<number>) {
-        return arrayColumn({ array, type: Type.int });
+        return arrayColumn({ array, schema: Schema.int });
     }
 
     export function ofFloatArray(array: ArrayLike<number>) {
-        return arrayColumn({ array, type: Type.float });
+        return arrayColumn({ array, schema: Schema.float });
     }
 
     export function ofStringArray(array: ArrayLike<string>) {
-        return arrayColumn({ array, type: Type.str });
+        return arrayColumn({ array, schema: Schema.str });
     }
 
     export function window<T>(column: Column<T>, start: number, end: number) {
@@ -150,8 +127,8 @@ namespace Column {
     /** Makes the column backned by an array. Useful for columns that accessed often. */
     export function asArrayColumn<T>(c: Column<T>, array?: ArrayCtor<T>): Column<T> {
         if (c['@array']) return c;
-        if (!c.isDefined) return Undefined(c.rowCount, c['@type']) as any as Column<T>;
-        return arrayColumn({ array: c.toArray({ array }), type: c['@type'] as any, valueKind: c.valueKind });
+        if (!c.isDefined) return Undefined(c.rowCount, c._schema) as any as Column<T>;
+        return arrayColumn({ array: c.toArray({ array }), schema: c._schema, valueKind: c.valueKind });
     }
 }
 
@@ -166,10 +143,10 @@ function createFirstIndexMapOfColumn<T>(c: Column<T>): Map<T, number> {
     return map;
 }
 
-function constColumn<T extends Column.Type>(v: T['T'], rowCount: number, type: T, valueKind: Column.ValueKind): Column<T['T']> {
+function constColumn<T extends Column.Schema>(v: T['T'], rowCount: number, schema: T, valueKind: Column.ValueKind): Column<T['T']> {
     const value: Column<T['T']>['value'] = row => v;
     return {
-        '@type': type,
+        _schema: schema,
         '@array': void 0,
         isDefined: valueKind === Column.ValueKind.Present,
         rowCount,
@@ -184,9 +161,9 @@ function constColumn<T extends Column.Type>(v: T['T'], rowCount: number, type: T
     }
 }
 
-function lambdaColumn<T extends Column.Type>({ value, valueKind, rowCount, type }: Column.LambdaSpec<T>): Column<T['T']> {
+function lambdaColumn<T extends Column.Schema>({ value, valueKind, rowCount, schema }: Column.LambdaSpec<T>): Column<T['T']> {
     return {
-        '@type': type,
+        _schema: schema,
         '@array': void 0,
         isDefined: true,
         rowCount,
@@ -201,21 +178,21 @@ function lambdaColumn<T extends Column.Type>({ value, valueKind, rowCount, type
     }
 }
 
-function arrayColumn<T extends Column.Type>({ array, type, valueKind }: Column.ArraySpec<T>): Column<T['T']> {
+function arrayColumn<T extends Column.Schema>({ array, schema, valueKind }: Column.ArraySpec<T>): Column<T['T']> {
     const rowCount = array.length;
-    const value: Column<T['T']>['value'] = type.kind === 'str'
+    const value: Column<T['T']>['value'] = schema.valueKind === 'str'
         ? row => { const v = array[row]; return typeof v === 'string' ? v : '' + v; }
         : row => array[row];
 
     const isTyped = ColumnHelpers.isTypedArray(array);
     return {
-        '@type': type,
+        _schema: schema,
         '@array': array,
         isDefined: true,
         rowCount,
         value,
         valueKind: valueKind ? valueKind : row => Column.ValueKind.Present,
-        toArray: type.kind === 'str'
+        toArray: schema.valueKind === 'str'
             ? params => {
                 const { start, end } = ColumnHelpers.getArrayBounds(rowCount, params);
                 const ret = new (params && typeof params.array !== 'undefined' ? params.array : (array as any).constructor)(end - start) as any;
@@ -239,14 +216,14 @@ function arrayColumn<T extends Column.Type>({ array, type, valueKind }: Column.A
 }
 
 function windowColumn<T>(column: Column<T>, start: number, end: number) {
-    if (!column.isDefined) return Column.Undefined(end - start, column['@type']);
+    if (!column.isDefined) return Column.Undefined(end - start, column._schema);
     if (!!column['@array'] && ColumnHelpers.isTypedArray(column['@array'])) return windowTyped(column, start, end);
     return windowFull(column, start, end);
 }
 
 function windowTyped<T>(c: Column<T>, start: number, end: number): Column<T> {
     const array = ColumnHelpers.typedArrayWindow(c['@array'], { start, end });
-    return arrayColumn({ array, type: c['@type'], valueKind: c.valueKind }) as any;
+    return arrayColumn({ array, schema: c._schema, valueKind: c.valueKind }) as any;
 }
 
 function windowFull<T>(c: Column<T>, start: number, end: number): Column<T> {
@@ -254,7 +231,7 @@ function windowFull<T>(c: Column<T>, start: number, end: number): Column<T> {
     const value: Column<T>['value'] = start === 0 ? v : row => v(row + start);
     const rowCount = end - start;
     return {
-        '@type': c['@type'],
+        _schema: c._schema,
         '@array': void 0,
         isDefined: c.isDefined,
         rowCount,
@@ -288,7 +265,7 @@ function arrayView<T>(c: Column<T>, map: ArrayLike<number>): Column<T> {
     const array = c['@array']!;
     const ret = new (array as any).constructor(map.length);
     for (let i = 0, _i = map.length; i < _i; i++) ret[i] = array[map[i]];
-    return arrayColumn({ array: ret, type: c['@type'], valueKind: c.valueKind });
+    return arrayColumn({ array: ret, schema: c._schema, valueKind: c.valueKind });
 }
 
 function viewFull<T>(c: Column<T>, map: ArrayLike<number>): Column<T> {
@@ -296,7 +273,7 @@ function viewFull<T>(c: Column<T>, map: ArrayLike<number>): Column<T> {
     const value: Column<T>['value'] = row => v(map[row]);
     const rowCount = map.length;
     return {
-        '@type': c['@type'],
+        _schema: c._schema,
         '@array': void 0,
         isDefined: c.isDefined,
         rowCount,
@@ -318,7 +295,7 @@ function mapToArrayImpl<T, S>(c: Column<T>, f: (v: T) => S, ctor: Column.ArrayCt
 }
 
 function areColumnsEqual(a: Column<any>, b: Column<any>) {
-    if (a.rowCount !== b.rowCount || a.isDefined !== b.isDefined || a['@type'].kind !== b['@type'].kind) return false;
+    if (a.rowCount !== b.rowCount || a.isDefined !== b.isDefined || a._schema.valueKind !== b._schema.valueKind) return false;
     if (!!a['@array'] && !!b['@array']) return areArraysEqual(a, b);
     return areValuesEqual(a, b);
 }

+ 2 - 2
src/mol-data/db/table.ts

@@ -56,7 +56,7 @@ namespace Table {
         for (const k of columns) {
             (ret as any)[k] = Column.ofLambda({
                 rowCount,
-                type: schema[k],
+                schema: schema[k],
                 value: r => rows[r][k],
                 valueKind: r => typeof rows[r][k] === 'undefined' ? Column.ValueKind.NotPresent : Column.ValueKind.Present
             })
@@ -71,7 +71,7 @@ namespace Table {
         ret._columns = columns;
         ret._schema = schema;
         for (const k of columns) {
-            (ret as any)[k] = Column.ofArray({ array: arrays[k], type: schema[k] })
+            (ret as any)[k] = Column.ofArray({ array: arrays[k], schema: schema[k] })
         }
         return ret as R;
     }

+ 3 - 3
src/mol-io/reader/_spec/column.spec.ts

@@ -32,8 +32,8 @@ const linesTokens = (function () {
 
 describe('fixed text column', () => {
     const col = FixedColumn({ data: linesData, indices: linesTokens, count: lines.length });
-    const col1 = col(0, 5, Column.Type.float);
-    const col2 = col(5, 4, Column.Type.str);
+    const col1 = col(0, 5, Column.Schema.float);
+    const col2 = col(5, 4, Column.Schema.str);
     it('number', () => {
         expect(col1.value(0)).toBe(1.123);
         expect(col1.value(1)).toBe(1.0);
@@ -53,7 +53,7 @@ describe('fixed text column', () => {
 describe('token text column', () => {
     const tokensData = '321';
     const col = TokenColumn({ data: tokensData, indices: [0, 1, 1, 2, 2, 3], count: 3 });
-    const col1 = col(Column.Type.int);
+    const col1 = col(Column.Schema.int);
     it('number', () => {
         expect(col1.value(0)).toBe(3);
         expect(col1.value(1)).toBe(2);

+ 6 - 6
src/mol-io/reader/cif/schema.ts

@@ -18,10 +18,10 @@ export function toTable<Schema extends Table.Schema, R extends Table<Schema> = T
 type ColumnCtor = (field: Data.Field, category: Data.Category, key: string) => Column<any>
 
 function getColumnCtor(t: Column.Schema): ColumnCtor {
-    switch (t.kind) {
-        case 'str': return (f, c, k) => createColumn(Column.Type.str, f, f.str, f.toStringArray);
-        case 'int': return (f, c, k) => createColumn(Column.Type.int, f, f.int, f.toIntArray);
-        case 'float': return (f, c, k) => createColumn(Column.Type.float, f, f.float, f.toFloatArray);
+    switch (t.valueKind) {
+        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);
@@ -31,9 +31,9 @@ function getColumnCtor(t: Column.Schema): ColumnCtor {
 }
 
 
-function createColumn<T>(type: Column.Type, field: Data.Field, value: (row: number) => T, toArray: Column<T>['toArray']): Column<T> {
+function createColumn<T>(schema: Column.Schema, field: Data.Field, value: (row: number) => T, toArray: Column<T>['toArray']): Column<T> {
     return {
-        '@type': type,
+        _schema: schema,
         '@array': field['@array'],
         isDefined: field.isDefined,
         rowCount: field.rowCount,

+ 1 - 2
src/mol-io/reader/cif/schema/dic.ts

@@ -7,7 +7,6 @@
 import { Database, Column } from 'mol-data/db'
 
 import Schema = Column.Schema
-import FP = Schema.FP
 
 const str = Schema.str;
 const float = Schema.float;
@@ -56,7 +55,7 @@ const item_units_conversion = {
     from_code: str,
     to_code: str,
     operator: str,
-    factor: float(FP(6, 6, 6))
+    factor: float
 }
 
 // TODO save frame dic schema

+ 10 - 11
src/mol-io/reader/cif/schema/mmcif.ts

@@ -7,7 +7,6 @@
 import { Database, Column } from 'mol-data/db'
 
 import Schema = Column.Schema
-import FP = Schema.FP
 
 const str = Schema.str;
 const int = Schema.int;
@@ -24,7 +23,7 @@ const entity = {
     type: Schema.aliased<EntityType>(str),
     src_method: str,
     pdbx_description: str,
-    formula_weight: float(FP(6, 3, 1)),
+    formula_weight: float,
     pdbx_number_of_molecules: int,
     details: str,
     pdbx_mutation: str,
@@ -39,12 +38,12 @@ const exptl = {
 
 const cell = {
     entry_id: str,
-    length_a: float(FP(6, 6, 6)),
-    length_b: float(FP(6, 6, 6)),
-    length_c: float(FP(6, 6, 6)),
-    angle_alpha: float(FP(6, 6, 6)),
-    angle_beta: float(FP(6, 6, 6)),
-    angle_gamma: float(FP(6, 6, 6)),
+    length_a: float,
+    length_b: float,
+    length_c: float,
+    angle_alpha: float,
+    angle_beta: float,
+    angle_gamma: float,
     Z_PDB: int,
     pdbx_unique_axis: str
 }
@@ -150,7 +149,7 @@ const struct_conn = {
     pdbx_ptnr3_label_alt_id: str,
     pdbx_ptnr3_PDB_ins_code: str,
     details: str,
-    pdbx_dist_value: float(FP(6, 3, 3)),
+    pdbx_dist_value: float,
     pdbx_value_order: Schema.aliased<BondValueOrder>(str)
 }
 
@@ -221,8 +220,8 @@ const atom_site = {
     Cartn_x: Schema.coord,
     Cartn_y: Schema.coord,
     Cartn_z: Schema.coord,
-    occupancy: float(FP(2, 2, 1)),
-    B_iso_or_equiv: float(FP(2, 2, 1)),
+    occupancy: float,
+    B_iso_or_equiv: float,
     auth_atom_id: str,
     auth_comp_id: str,
     auth_asym_id: str,

+ 4 - 4
src/mol-io/reader/common/text/column/fixed.ts

@@ -9,14 +9,14 @@ import { trimStr, Tokens } from '../tokenizer'
 import { parseIntSkipLeadingWhitespace, parseFloatSkipLeadingWhitespace } from '../number-parser'
 
 export default function FixedColumnProvider(lines: Tokens) {
-    return function<T extends Column.Type>(offset: number, width: number, type: T) {
+    return function<T extends Column.Schema>(offset: number, width: number, type: T) {
         return FixedColumn(lines, offset, width, type);
     }
 }
 
-export function FixedColumn<T extends Column.Type>(lines: Tokens, offset: number, width: number, type: T): Column<T['T']> {
+export function FixedColumn<T extends Column.Schema>(lines: Tokens, offset: number, width: number, schema: T): Column<T['T']> {
     const { data, indices, count: rowCount } = lines;
-    const { kind } = type;
+    const { valueKind: kind } = schema;
 
     const value: Column<T['T']>['value'] = kind === 'str' ? row => {
         let s = indices[2 * row] + offset, le = indices[2 * row + 1];
@@ -34,7 +34,7 @@ export function FixedColumn<T extends Column.Type>(lines: Tokens, offset: number
         return parseFloatSkipLeadingWhitespace(data, s, s + width);
     };
     return {
-        '@type': type,
+        _schema: schema,
         '@array': void 0,
         isDefined: true,
         rowCount,

+ 4 - 4
src/mol-io/reader/common/text/column/token.ts

@@ -9,14 +9,14 @@ import { Tokens } from '../tokenizer'
 import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../number-parser'
 
 export default function TokenColumnProvider(tokens: Tokens) {
-    return function<T extends Column.Type>(type: T) {
+    return function<T extends Column.Schema>(type: T) {
         return TokenColumn(tokens, type);
     }
 }
 
-export function TokenColumn<T extends Column.Type>(tokens: Tokens, type: T): Column<T['T']> {
+export function TokenColumn<T extends Column.Schema>(tokens: Tokens, schema: T): Column<T['T']> {
     const { data, indices, count: rowCount } = tokens;
-    const { kind } = type;
+    const { valueKind: kind } = schema;
 
     const value: Column<T['T']>['value'] =
           kind === 'str'
@@ -26,7 +26,7 @@ export function TokenColumn<T extends Column.Type>(tokens: Tokens, type: T): Col
         : row => fastParseFloat(data, indices[2 * row], indices[2 * row + 1]) || 0;
 
     return {
-        '@type': type,
+        _schema: schema,
         '@array': void 0,
         isDefined: true,
         rowCount,

+ 11 - 11
src/mol-io/reader/gro/parser.ts

@@ -106,20 +106,20 @@ async function handleAtoms(state: State): Promise<Schema.Atoms> {
     const vW = state.header.precision.velocity + 4;
 
     const col = FixedColumn(lines);
-    const undef = Column.Undefined(state.numberOfAtoms, Column.Type.float);
+    const undef = Column.Undefined(state.numberOfAtoms, Column.Schema.float);
 
     const ret = {
         count: state.numberOfAtoms,
-        residueNumber: col(0, 5, Column.Type.int),
-        residueName: col(5, 5, Column.Type.str),
-        atomName: col(10, 5, Column.Type.str),
-        atomNumber: col(15, 5, Column.Type.int),
-        x: col(pO, pW, Column.Type.float),
-        y: col(pO + pW, pW, Column.Type.float),
-        z: col(pO + 2 * pW, pW, Column.Type.float),
-        vx: hasVelocities ? col(vO, vW, Column.Type.float) : undef,
-        vy: hasVelocities ? col(vO + vW, vW, Column.Type.float) : undef,
-        vz: hasVelocities ? col(vO + 2 * vW, vW, Column.Type.float) : undef,
+        residueNumber: col(0, 5, Column.Schema.int),
+        residueName: col(5, 5, Column.Schema.str),
+        atomName: col(10, 5, Column.Schema.str),
+        atomNumber: col(15, 5, Column.Schema.int),
+        x: col(pO, pW, Column.Schema.float),
+        y: col(pO + pW, pW, Column.Schema.float),
+        z: col(pO + 2 * pW, pW, Column.Schema.float),
+        vx: hasVelocities ? col(vO, vW, Column.Schema.float) : undef,
+        vy: hasVelocities ? col(vO + vW, vW, Column.Schema.float) : undef,
+        vz: hasVelocities ? col(vO + 2 * vW, vW, Column.Schema.float) : undef,
     };
 
     return ret;

+ 2 - 0
src/mol-io/writer/cif/encoder.ts

@@ -13,6 +13,7 @@ import Encoder from '../encoder'
 // TODO: automatically detect "best encoding" for integer arrays. This could be used for "fixed-point" as well.
 // TODO: add "repeat encoding"? [[1, 2], [1, 2], [1, 2]] --- Repeat ---> [[1, 2], 3]
 // TODO: Add "higher level fields"? (i.e. generalization of repeat)
+// TODO: Add tensor field definition
 
 export const enum FieldType {
     Str, Int, Float
@@ -29,6 +30,7 @@ export type FieldDefinition<Key = any, Data = any> =
     | FieldDefinitionBase<Key, Data> & { type: FieldType.Str, value(key: Key, data: Data): string }
     | FieldDefinitionBase<Key, Data> & { type: FieldType.Int, value(key: Key, data: Data): number }
     | FieldDefinitionBase<Key, Data> & { type: FieldType.Float, value(key: Key, data: Data): number }
+    // TODO: add tensor
 
 export interface FieldFormat {
     // TODO: do we actually need this?

+ 1 - 1
src/mol-model/structure/export/mmcif.ts

@@ -49,7 +49,7 @@ function ofSchema(schema: Table.Schema) {
     for (const k of Object.keys(schema)) {
         const t = schema[k];
         // TODO: matrix/vector/support
-        const type: any = t.kind === 'str' ? Encoder.FieldType.Str : t.kind === 'int' ? Encoder.FieldType.Int : Encoder.FieldType.Float;
+        const type: any = t.valueKind === 'str' ? Encoder.FieldType.Str : t.valueKind === 'int' ? Encoder.FieldType.Int : Encoder.FieldType.Float;
         fields.push({ name: k, type, value: columnValue(k), valueKind: columnValueKind(k) })
     }
     return fields;

+ 2 - 2
src/mol-model/structure/model/formats/mmcif.ts

@@ -40,7 +40,7 @@ function findHierarchyOffsets({ data }: mmCIF_Format, bounds: Interval) {
 
         if (newResidue) residues[residues.length] = i;
         if (newChain) chains[chains.length] = i;
-    }    
+    }
     return { residues, chains };
 }
 
@@ -48,7 +48,7 @@ function createHierarchyData({ data }: mmCIF_Format, bounds: Interval, offsets:
     const { atom_site } = data;
     const start = Interval.start(bounds), end = Interval.end(bounds);
     const atoms = Table.ofColumns(Hierarchy.AtomsSchema, {
-        type_symbol: Column.ofArray({ array: Column.mapToArray(Column.window(atom_site.type_symbol, start, end), ElementSymbol), type: Column.Type.aliased<ElementSymbol>(Column.Type.str) }),
+        type_symbol: Column.ofArray({ array: Column.mapToArray(Column.window(atom_site.type_symbol, start, end), ElementSymbol), schema: Column.Schema.aliased<ElementSymbol>(Column.Schema.str) }),
         label_atom_id: Column.window(atom_site.label_atom_id, start, end),
         auth_atom_id: Column.window(atom_site.auth_atom_id, start, end),
         label_alt_id: Column.window(atom_site.label_alt_id, start, end),

+ 6 - 6
src/perf-tests/column.ts

@@ -40,9 +40,9 @@ export namespace Column {
         const suite = new B.Suite();
         const data = createData(1000);
         const nativeData = [...data as any];
-        const col = C.ofArray({ array: data, type: C.Type.float });
-        const lambda = C.ofLambda({ value: val, rowCount: data.length, type: C.Type.float });
-        const cnst = C.ofConst(10, data.length, C.Type.float);
+        const col = C.ofArray({ array: data, schema: C.Schema.float });
+        const lambda = C.ofLambda({ value: val, rowCount: data.length, schema: C.Schema.float });
+        const cnst = C.ofConst(10, data.length, C.Schema.float);
         suite
             .add('raw', () => raw(data))
             .add('native raw', () => raw(nativeData))
@@ -59,9 +59,9 @@ export namespace Column {
         const suite = new B.Suite();
         const data = createData(10000);
         const nativeData = [...data as any];
-        const col = C.ofArray({ array: data, type: C.Type.float });
-        const lambda = C.ofLambda({ value: val, rowCount: data.length, type: C.Type.float });
-        const cnst = C.ofConst(10, data.length, C.Type.float);
+        const col = C.ofArray({ array: data, schema: C.Schema.float });
+        const lambda = C.ofLambda({ value: val, rowCount: data.length, schema: C.Schema.float });
+        const cnst = C.ofConst(10, data.length, C.Schema.float);
         suite
             .add('raw', () => raw(data))
             .add('native raw', () => raw(nativeData))