Pārlūkot izejas kodu

added 'list' column type

TODO handle in writer
Alexander Rose 7 gadi atpakaļ
vecāks
revīzija
13e63cedf4

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

@@ -1,7 +1,8 @@
 /**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2018 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'
@@ -11,6 +12,8 @@ import Table from '../table'
 describe('column', () => {
     const cc = Column.ofConst(10, 2, Column.Schema.int);
     const arr = Column.ofArray({ array: [1, 2, 3, 4], schema: Column.Schema.int });
+    const arrNumberList = Column.ofArray({ array: [[1, 2], [3, 4], [5, 6]], schema: Column.Schema.List<number>() });
+    const arrStringList = Column.ofArray({ array: [['a', 'b'], ['c', 'd'], ['e', 'f']], schema: Column.Schema.List<string>() });
     const arrWindow = Column.window(arr, 1, 3);
 
     const typed = Column.ofArray({ array: new Int32Array([1, 2, 3, 4]), schema: Column.Schema.int });
@@ -30,6 +33,13 @@ describe('column', () => {
         expect(arrWindow.rowCount).toBe(2);
     });
 
+    it('arrList', () => {
+        expect(arrNumberList.rowCount).toBe(3);
+        expect(arrNumberList.value(1)).toEqual([3, 4]);
+        expect(arrStringList.rowCount).toBe(3);
+        expect(arrStringList.value(2)).toEqual(['e', 'f']);
+    });
+
     it('typed', () => {
         expect(typedWindow.value(0)).toBe(2);
         expect(typedWindow.rowCount).toBe(2);

+ 7 - 2
src/mol-data/db/column.ts

@@ -1,7 +1,8 @@
 /**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2018 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'
@@ -22,7 +23,7 @@ interface Column<T> {
 namespace Column {
     export type ArrayCtor<T> = { new(size: number): ArrayLike<T> }
 
-    export type Schema<T = any> = Schema.Str | Schema.Int | Schema.Float | Schema.Coordinate | Schema.Aliased<T> | Schema.Tensor
+    export type Schema<T = any> = Schema.Str | Schema.Int | Schema.Float | Schema.Coordinate | Schema.Aliased<T> | Schema.Tensor | Schema.List<number|string>
 
     export namespace Schema {
         // T also serves as a default value for undefined columns
@@ -35,6 +36,7 @@ namespace Column {
 
         export type Tensor = { '@type': 'tensor', T: Tensors, space: Tensors.Space } & Base<'tensor'>
         export type Aliased<T> = { '@type': 'aliased', T: T } & Base<'str' | 'int'>
+        export type List<T extends number|string> = { '@type': 'list', T: T[] } & Base<'list'>
 
         export const str: Str = { '@type': 'str', T: '', valueType: 'str' };
         export const int: Int = { '@type': 'int', T: 0, valueType: 'int' };
@@ -52,6 +54,9 @@ namespace Column {
             if (typeof defaultValue !== 'undefined') return { ...t, T: defaultValue } as any as Aliased<T>;
             return t as any as Aliased<T>;
         }
+        export function List<T extends number|string>(defaultValue: T[] = []): List<T> {
+            return { '@type': 'list', T: defaultValue, valueType: 'list' }
+        }
     }
 
     export interface ToArrayParams<T> {

+ 9 - 2
src/mol-io/reader/cif/binary/field.ts

@@ -1,7 +1,8 @@
 /**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2018 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 { Column, ColumnHelpers } from 'mol-data/db'
@@ -30,6 +31,10 @@ export default function Field(column: EncodedColumn): Data.Field {
         ? row => data[row]
         : row => { const v = data[row]; return fastParseFloat(v, 0, v.length); };
 
+    const list: Data.Field['list'] = mask
+        ? row => mask[row] === Column.ValueKind.Present ? data[row] : []
+        : row => data[row];
+
     const valueKind: Data.Field['valueKind'] = mask
         ? row => mask[row]
         : row => Column.ValueKind.Present;
@@ -43,6 +48,7 @@ export default function Field(column: EncodedColumn): Data.Field {
         str,
         int,
         float,
+        list,
         valueKind,
         areValuesEqual: (rowA, rowB) => data[rowA] === data[rowB],
         toStringArray: params => ColumnHelpers.createAndFillArray(rowCount, str, params),
@@ -51,6 +57,7 @@ export default function Field(column: EncodedColumn): Data.Field {
             : params => ColumnHelpers.createAndFillArray(rowCount, int, params),
         toFloatArray: isNumeric
             ? params => ColumnHelpers.typedArrayWindow(data, params)
-            : params => ColumnHelpers.createAndFillArray(rowCount, float, params)
+            : params => ColumnHelpers.createAndFillArray(rowCount, float, params),
+        toListArray: params => ColumnHelpers.createAndFillArray(rowCount, list, params)
     };
 }

+ 4 - 1
src/mol-io/reader/cif/data-model.ts

@@ -1,7 +1,8 @@
 /**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2018 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 { Column } from 'mol-data/db'
@@ -67,6 +68,7 @@ export interface Field {
     str(row: number): string,
     int(row: number): number,
     float(row: number): number,
+    list<T extends number|string>(row: number): T[],
 
     valueKind(row: number): Column.ValueKind,
 
@@ -75,6 +77,7 @@ export interface Field {
     toStringArray(params?: Column.ToArrayParams<string>): ReadonlyArray<string>,
     toIntArray(params?: Column.ToArrayParams<number>): ReadonlyArray<number>,
     toFloatArray(params?: Column.ToArrayParams<number>): ReadonlyArray<number>
+    toListArray<T extends number|string>(params?: Column.ToArrayParams<T[]>): ReadonlyArray<T[]>
 }
 
 export function getTensor(category: Category, field: string, space: Tensor.Space, row: number): Tensor {

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

@@ -1,7 +1,8 @@
 /**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2018 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 { Database, Table, Column, ColumnHelpers } from 'mol-data/db'
@@ -23,6 +24,7 @@ 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 'list': return (f, c, k) => createColumn(t, f, f.list, f.toListArray);
         case 'tensor': throw new Error(`Use createTensorColumn instead.`);
     }
 }

+ 11 - 2
src/mol-io/reader/cif/text/field.ts

@@ -1,7 +1,8 @@
 /**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2018 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 { Column, ColumnHelpers } from 'mol-data/db'
@@ -27,6 +28,12 @@ export default function CifTextField(tokens: Tokens, rowCount: number): Data.Fie
         return fastParseFloat(data, indices[2 * row], indices[2 * row + 1]) || 0;
     };
 
+    const list: Data.Field['list'] = <T extends string|number>(row: number) => {
+        const ret = data.substring(indices[2 * row], indices[2 * row + 1]);
+        if (ret === '.' || ret === '?') return [];
+        return ret.split(',') as T[];
+    };
+
     const valueKind: Data.Field['valueKind'] = row => {
         const s = indices[2 * row];
         if (indices[2 * row + 1] - s !== 1) return Column.ValueKind.Present;
@@ -43,10 +50,12 @@ export default function CifTextField(tokens: Tokens, rowCount: number): Data.Fie
         str,
         int,
         float,
+        list,
         valueKind,
         areValuesEqual: TokenColumn.areValuesEqualProvider(tokens),
         toStringArray: params => ColumnHelpers.createAndFillArray(rowCount, str, params),
         toIntArray: params => ColumnHelpers.createAndFillArray(rowCount, int, params),
-        toFloatArray: params => ColumnHelpers.createAndFillArray(rowCount, float, params)
+        toFloatArray: params => ColumnHelpers.createAndFillArray(rowCount, float, params),
+        toListArray: params => ColumnHelpers.createAndFillArray(rowCount, list, params)
     }
 }