diff --git a/src/mol-base/collections/_spec/column.spec.ts b/src/mol-base/collections/_spec/column.spec.ts
index 5449d7d8ea2f7b925776e98630b64c25880906a9..6f1aa50b6f38997b6608adeb40a511c5d0b2ac95 100644
--- a/src/mol-base/collections/_spec/column.spec.ts
+++ b/src/mol-base/collections/_spec/column.spec.ts
@@ -4,7 +4,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import Column, { isTypedArray } from '../column.1'
+import Column, { isTypedArray } from '../column'
 
 describe('column', () => {
     const cc = Column.ofConst(10, 2, Column.Type.int);
@@ -14,6 +14,8 @@ describe('column', () => {
     const typed = Column.ofArray({ array: new Int32Array([1, 2, 3, 4]), type: Column.Type.int });
     const typedWindow = Column.window(typed, 1, 3);
 
+    const numStr = Column.ofArray({ array: [1, 2] as any, type: Column.Type.str });
+
     it('constant', () => {
         expect(cc.rowCount).toBe(2);
         expect(cc.value(0)).toBe(10);
@@ -31,4 +33,9 @@ describe('column', () => {
         expect(typedWindow.rowCount).toBe(2);
         expect(isTypedArray(typedWindow.toArray())).toBe(true);
     });
+
+    it('numStr', () => {
+        expect(numStr.value(0)).toBe('1');
+        expect(numStr.toArray()).toEqual(['1', '2']);
+    });
 })
\ No newline at end of file
diff --git a/src/mol-base/collections/column.1.ts b/src/mol-base/collections/column.1.ts
deleted file mode 100644
index d851a7c753996599df824a0dbbe9778ed3c074c4..0000000000000000000000000000000000000000
--- a/src/mol-base/collections/column.1.ts
+++ /dev/null
@@ -1,191 +0,0 @@
-/**
- * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-interface Column<T> {
-    readonly '@type': Column.Type,
-    readonly '@array': ArrayLike<any> | undefined,
-
-    readonly isDefined: boolean,
-    readonly rowCount: number,
-    value(row: number): T,
-    valueKind(row: number): Column.ValueKind,
-    toArray(params?: Column.ToArrayParams): ReadonlyArray<T>,
-    stringEquals(row: number, value: string): boolean,
-    areValuesEqual(rowA: number, rowB: number): boolean
-}
-
-namespace Column {
-    export type Type = typeof Type.str | typeof Type.int | typeof Type.float | typeof Type.vector | typeof Type.matrix
-
-    export namespace Type {
-        export const str = { '@type': '' as string, kind: 'str' as 'str' };
-        export const int = { '@type': 0 as number, kind: 'int' as 'int' };
-        export const float = { '@type': 0 as number, kind: 'float' as 'float' };
-        export const vector = { '@type': [] as number[], kind: 'vector' as 'vector' };
-        export const matrix = { '@type': [] as number[][], kind: 'matrix' as 'matrix' };
-    }
-
-    export interface ToArrayParams {
-        array?: { new(size: number): ArrayLike<number> },
-        start?: number,
-        /** Last row (exclusive) */
-        end?: number
-    }
-
-    export interface ArraySpec<T extends Type> {
-        array: ArrayLike<T['@type']>,
-        type: T,
-        valueKind?: (row: number) => ValueKind
-    }
-
-    export const enum ValueKind { Present, NotPresent, Unknown }
-
-    export function Undefined<T extends Type>(rowCount: number, type: T): Column<T['@type']> {
-        return constColumn(type['@type'], rowCount, type, ValueKind.NotPresent);
-    }
-
-    export function ofConst<T extends Type>(v: T['@type'], rowCount: number, type: T): Column<T['@type']> {
-        return constColumn(v, rowCount, type, ValueKind.Present);
-    }
-
-    export function ofArray<T extends Column.Type>(spec: Column.ArraySpec<T>): Column<T['@type']> {
-        return arrayColumn(spec);
-    }
-
-    export function window<T>(column: Column<T>, start: number, end: number) {
-        return windowColumn(column, start, end);
-    }
-
-    /** Makes the column backned by an array. Useful for columns that accessed often. */
-    export function asArrayColumn<T>(c: Column<T>, array?: ToArrayParams['array']): 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 });
-    }
-}
-
-export default Column;
-
-function constColumn<T extends Column.Type>(v: T['@type'], rowCount: number, type: T, valueKind: Column.ValueKind): Column<T['@type']> {
-    const value: Column<T['@type']>['value'] = row => v;
-    return {
-        '@type': type,
-        '@array': void 0,
-        isDefined: valueKind === Column.ValueKind.Present,
-        rowCount,
-        value,
-        valueKind: row => valueKind,
-        toArray: params => {
-            const { array } = createArray(rowCount, params);
-            for (let i = 0, _i = array.length; i < _i; i++) array[i] = v;
-            return array;
-        },
-        stringEquals: type.kind === 'str'
-            ? (row, value) => value === v
-            : type.kind === 'float' || type.kind === 'int'
-                ? (row, value) => +value === v
-                : (row, value) => false,
-        areValuesEqual: (rowA, rowB) => true
-    }
-}
-
-function arrayColumn<T extends Column.Type>({ array, type, valueKind }: Column.ArraySpec<T>): Column<T['@type']> {
-    const rowCount = array.length;
-    const value: Column<T['@type']>['value'] = row => array[row];
-    const isTyped = isTypedArray(array);
-    return {
-        '@type': type,
-        '@array': array,
-        isDefined: true,
-        rowCount,
-        value,
-        valueKind: valueKind ? valueKind : row => Column.ValueKind.Present,
-        toArray: isTyped
-            ? params => typedArrayWindow(array, params) as any as ReadonlyArray<T>
-            : params => {
-                const { start, end } = getArrayBounds(rowCount, params);
-                if (start === 0 && end === array.length) return array as ReadonlyArray<T['@type']>;
-                const ret = new (params && typeof params.array !== 'undefined' ? params.array : (array as any).constructor)(end - start) as any;
-                for (let i = 0, _i = end - start; i < _i; i++) ret[i] = array[start + i];
-                return ret;
-            },
-        stringEquals: type.kind === 'int' || type.kind === 'float'
-            ? (row, value) => (array as any)[row] === +value
-            : type.kind === 'str'
-            ? (row, value) => array[row] === value
-            : (row, value) => false,
-        areValuesEqual: (rowA, rowB) => array[rowA] === array[rowB]
-    }
-}
-
-function windowColumn<T>(column: Column<T>, start: number, end: number) {
-    if (!column.isDefined) return Column.Undefined(end - start, column['@type']);
-    if (column['@array'] && 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 = typedArrayWindow(c['@array'], { start, end });
-    return arrayColumn({ array, type: c['@type'], valueKind: c.valueKind }) as any;
-}
-
-function windowFull<T>(c: Column<T>, start: number, end: number): Column<T> {
-    const v = c.value, vk = c.valueKind, se = c.stringEquals, ave = c.areValuesEqual;
-    const value: Column<T>['value'] = start > 0 ? v : row => v(row + start);
-    const rowCount = end - start;
-    return {
-        '@type': c['@type'],
-        '@array': void 0,
-        isDefined: c.isDefined,
-        rowCount,
-        value,
-        valueKind: start > 0 ? vk : row => vk(row + start),
-        toArray: params => {
-            const { array } = createArray(rowCount, params);
-            for (let i = 0, _i = array.length; i < _i; i++) array[i] = v(i + start);
-            return array;
-        },
-        stringEquals: start > 0 ? se : (row, value) => se(row + start, value),
-        areValuesEqual: start > 0 ? ave : (rowA, rowB) => ave(rowA + start, rowB + start)
-    };
-}
-
-/** A helped function for Column.toArray */
-export function getArrayBounds(rowCount: number, params?: Column.ToArrayParams) {
-    const start = params && typeof params.start !== 'undefined' ? Math.max(Math.min(params.start, rowCount - 1), 0) : 0;
-    const end = params && typeof params.end !== 'undefined' ? Math.min(params.end, rowCount) : rowCount;
-    return { start, end };
-}
-
-/** A helped function for Column.toArray */
-export function createArray(rowCount: number, params?: Column.ToArrayParams) {
-    const c = params && typeof params.array !== 'undefined' ? params.array : Array;
-    const { start, end } = getArrayBounds(rowCount, params);
-    return { array: new c(end - start) as any[], start, end };
-}
-
-/** A helped function for Column.toArray */
-export function fillArrayValues(value: (row: number) => any, target: any[], start: number) {
-    for (let i = 0, _e = target.length; i < _e; i++) target[i] = value(start + i);
-    return target;
-}
-
-/** A helped function for Column.toArray */
-export function createAndFillArray(rowCount: number, value: (row: number) => any, params?: Column.ToArrayParams) {
-    const { array, start } = createArray(rowCount, params);
-    return fillArrayValues(value, array, start);
-}
-
-export function isTypedArray(data: any): boolean {
-    return !!data.buffer && typeof data.byteLength === 'number' && typeof data.BYTES_PER_ELEMENT === 'number';
-}
-
-export function typedArrayWindow(data: any, params?: Column.ToArrayParams): ReadonlyArray<number> {
-    const { constructor, buffer, length, byteOffset, BYTES_PER_ELEMENT } = data;
-    const { start, end } = getArrayBounds(length, params);
-    if (start === 0 && end === length) return data;
-    return new constructor(buffer, byteOffset + BYTES_PER_ELEMENT * start, Math.min(length, end - start));
-}
\ No newline at end of file
diff --git a/src/mol-base/collections/column.ts b/src/mol-base/collections/column.ts
index 4aec52f9e8767f6bf9bf32a232a33d99fb92519c..6139a04f42e12f47dbd34c44e7d3751ddacc24d6 100644
--- a/src/mol-base/collections/column.ts
+++ b/src/mol-base/collections/column.ts
@@ -4,94 +4,119 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-export type ColumnType = typeof ColumnType.str | typeof ColumnType.pooledStr | typeof ColumnType.int | typeof ColumnType.float | typeof ColumnType.vector | typeof ColumnType.matrix
-
-export namespace ColumnType {
-    export const str = { '@type': '' as string, kind: 'str' as 'str', isScalar: false, isString: true };
-    export const pooledStr = { '@type': '' as string, kind: 'pooled-str' as 'pooled-str', isScalar: false, isString: true };
-    export const int = { '@type': 0 as number, kind: 'int' as 'int', isScalar: true, isString: false };
-    export const float = { '@type': 0 as number, kind: 'float' as 'float', isScalar: true, isString: false };
-    export const vector = { '@type': [] as number[], kind: 'vector' as 'vector', isScalar: false, isString: false };
-    export const matrix = { '@type': [] as number[][], kind: 'matrix' as 'matrix', isScalar: false, isString: false };
-}
-
-export interface ToArrayParams {
-    array?: { new(size: number): ArrayLike<number> },
-    /** First row */
-    start?: number,
-    /** Last row (exclusive) */
-    end?: number
-}
+interface Column<T> {
+    readonly '@type': Column.Type,
+    readonly '@array': ArrayLike<any> | undefined,
 
-export interface Column<T> {
-    readonly '@type': ColumnType,
     readonly isDefined: boolean,
     readonly rowCount: number,
     value(row: number): T,
-    isValueDefined(row: number): boolean,
-    toArray(params?: ToArrayParams): ReadonlyArray<T>,
+    valueKind(row: number): Column.ValueKind,
+    toArray(params?: Column.ToArrayParams): ReadonlyArray<T>,
     stringEquals(row: number, value: string): boolean,
     areValuesEqual(rowA: number, rowB: number): boolean
 }
 
-export function UndefinedColumn<T extends ColumnType>(rowCount: number, type: T): Column<T['@type']> {
-    const v = type.isString ? '' : 0;
-    const value: Column<T['@type']>['value'] = type.isString ? row => '' : row => 0;
-    return {
-        '@type': type,
-        isDefined: false,
-        rowCount,
-        value,
-        isValueDefined: row => false,
-        toArray: params => {
-            const { array } = createArray(rowCount, params);
-            for (let i = 0, _i = array.length; i < _i; i++) array[i] = v;
-            return array;
-        },
-        stringEquals: (row, value) => !value,
-        areValuesEqual: (rowA, rowB) => true
+namespace Column {
+    export type Type = typeof Type.str | typeof Type.int | typeof Type.float | typeof Type.vector | typeof Type.matrix
+
+    export namespace Type {
+        export const str = { '@type': '' as string, kind: 'str' as 'str' };
+        export const int = { '@type': 0 as number, kind: 'int' as 'int' };
+        export const float = { '@type': 0 as number, kind: 'float' as 'float' };
+        export const vector = { '@type': [] as number[], kind: 'vector' as 'vector' };
+        export const matrix = { '@type': [] as number[][], kind: 'matrix' as 'matrix' };
+    }
+
+    export interface ToArrayParams {
+        array?: { new(size: number): ArrayLike<number> },
+        start?: number,
+        /** Last row (exclusive) */
+        end?: number
+    }
+
+    export interface ArraySpec<T extends Type> {
+        array: ArrayLike<T['@type']>,
+        type: 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['@type']> {
+        return constColumn(type['@type'], rowCount, type, ValueKind.NotPresent);
+    }
+
+    export function ofConst<T extends Type>(v: T['@type'], rowCount: number, type: T): Column<T['@type']> {
+        return constColumn(v, rowCount, type, ValueKind.Present);
+    }
+
+    export function ofArray<T extends Column.Type>(spec: Column.ArraySpec<T>): Column<T['@type']> {
+        return arrayColumn(spec);
+    }
+
+    export function window<T>(column: Column<T>, start: number, end: number) {
+        return windowColumn(column, start, end);
+    }
+
+    /** Makes the column backned by an array. Useful for columns that accessed often. */
+    export function asArrayColumn<T>(c: Column<T>, array?: ToArrayParams['array']): 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 });
     }
 }
 
-export function ConstColumn<T extends ColumnType>(v: T['@type'], rowCount: number, type: T): Column<T['@type']> {
+export default Column;
+
+function constColumn<T extends Column.Type>(v: T['@type'], rowCount: number, type: T, valueKind: Column.ValueKind): Column<T['@type']> {
     const value: Column<T['@type']>['value'] = row => v;
     return {
         '@type': type,
-        isDefined: true,
+        '@array': void 0,
+        isDefined: valueKind === Column.ValueKind.Present,
         rowCount,
         value,
-        isValueDefined: row => false,
+        valueKind: row => valueKind,
         toArray: params => {
             const { array } = createArray(rowCount, params);
             for (let i = 0, _i = array.length; i < _i; i++) array[i] = v;
             return array;
         },
-        stringEquals: type.isString
+        stringEquals: type.kind === 'str'
             ? (row, value) => value === v
-            : type.isScalar
-            ? (row, value) => +value === v
-            : (row, value) => false,
+            : type.kind === 'float' || type.kind === 'int'
+                ? (row, value) => +value === v
+                : (row, value) => false,
         areValuesEqual: (rowA, rowB) => true
     }
 }
 
-export interface ArrayColumnSpec<T extends ColumnType> {
-    array: ArrayLike<T['@type']>,
-    type: T,
-    isValueDefined?: (row: number) => boolean
-}
-
-export function ArrayColumn<T extends ColumnType>({ array, type, isValueDefined }: ArrayColumnSpec<T>): Column<T['@type']> {
+function arrayColumn<T extends Column.Type>({ array, type, valueKind }: Column.ArraySpec<T>): Column<T['@type']> {
     const rowCount = array.length;
-    const value: Column<T['@type']>['value'] = row => array[row];
+    const value: Column<T['@type']>['value'] = type.kind === 'str'
+        ? row => { const v = array[row]; return typeof v === 'string' ? v : '' + v; }
+        : row => array[row];
+
     const isTyped = isTypedArray(array);
     return {
         '@type': type,
+        '@array': array,
         isDefined: true,
         rowCount,
         value,
-        isValueDefined: isValueDefined ? isValueDefined : row => true,
-        toArray: isTyped
+        valueKind: valueKind ? valueKind : row => Column.ValueKind.Present,
+        toArray: type.kind === 'str'
+            ? params => {
+                const { start, end } = getArrayBounds(rowCount, params);
+                const ret = new (params && typeof params.array !== 'undefined' ? params.array : (array as any).constructor)(end - start) as any;
+                for (let i = 0, _i = end - start; i < _i; i++) {
+                    const v = array[start + i];
+                    ret[i] = typeof v === 'string' ? v : '' + v;
+                }
+                return ret;
+            }
+            : isTyped
             ? params => typedArrayWindow(array, params) as any as ReadonlyArray<T>
             : params => {
                 const { start, end } = getArrayBounds(rowCount, params);
@@ -100,30 +125,56 @@ export function ArrayColumn<T extends ColumnType>({ array, type, isValueDefined
                 for (let i = 0, _i = end - start; i < _i; i++) ret[i] = array[start + i];
                 return ret;
             },
-        stringEquals: type.isScalar
+        stringEquals: type.kind === 'int' || type.kind === 'float'
             ? (row, value) => (array as any)[row] === +value
-            : type.isString
-            ? (row, value) => array[row] === value
+            : type.kind === 'str'
+            ? (row, value) => { const v = array[row]; return typeof v === 'string' ? v === value : +v === +value; }
             : (row, value) => false,
         areValuesEqual: (rowA, rowB) => array[rowA] === array[rowB]
     }
 }
 
-/** Makes the column backned by an array. Useful for columns that accessed often. */
-export function toArrayColumn<T>(c: Column<T>): Column<T> {
-    if (!c.isDefined) return UndefinedColumn(c.rowCount, c['@type']) as any as Column<T>;
-    return ArrayColumn({ array: c.toArray(), type: c['@type'] as any, isValueDefined: c.isValueDefined });
+function windowColumn<T>(column: Column<T>, start: number, end: number) {
+    if (!column.isDefined) return Column.Undefined(end - start, column['@type']);
+    if (column['@array'] && 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 = typedArrayWindow(c['@array'], { start, end });
+    return arrayColumn({ array, type: c['@type'], valueKind: c.valueKind }) as any;
+}
+
+function windowFull<T>(c: Column<T>, start: number, end: number): Column<T> {
+    const v = c.value, vk = c.valueKind, se = c.stringEquals, ave = c.areValuesEqual;
+    const value: Column<T>['value'] = start === 0 ? v : row => v(row + start);
+    const rowCount = end - start;
+    return {
+        '@type': c['@type'],
+        '@array': void 0,
+        isDefined: c.isDefined,
+        rowCount,
+        value,
+        valueKind: start === 0 ? vk : row => vk(row + start),
+        toArray: params => {
+            const { array } = createArray(rowCount, params);
+            for (let i = 0, _i = array.length; i < _i; i++) array[i] = v(i + start);
+            return array;
+        },
+        stringEquals: start === 0 ? se : (row, value) => se(row + start, value),
+        areValuesEqual: start === 0 ? ave : (rowA, rowB) => ave(rowA + start, rowB + start)
+    };
 }
 
 /** A helped function for Column.toArray */
-export function getArrayBounds(rowCount: number, params?: ToArrayParams) {
+export function getArrayBounds(rowCount: number, params?: Column.ToArrayParams) {
     const start = params && typeof params.start !== 'undefined' ? Math.max(Math.min(params.start, rowCount - 1), 0) : 0;
     const end = params && typeof params.end !== 'undefined' ? Math.min(params.end, rowCount) : rowCount;
     return { start, end };
 }
 
 /** A helped function for Column.toArray */
-export function createArray(rowCount: number, params?: ToArrayParams) {
+export function createArray(rowCount: number, params?: Column.ToArrayParams) {
     const c = params && typeof params.array !== 'undefined' ? params.array : Array;
     const { start, end } = getArrayBounds(rowCount, params);
     return { array: new c(end - start) as any[], start, end };
@@ -136,16 +187,16 @@ export function fillArrayValues(value: (row: number) => any, target: any[], star
 }
 
 /** A helped function for Column.toArray */
-export function createAndFillArray(rowCount: number, value: (row: number) => any, params?: ToArrayParams) {
+export function createAndFillArray(rowCount: number, value: (row: number) => any, params?: Column.ToArrayParams) {
     const { array, start } = createArray(rowCount, params);
     return fillArrayValues(value, array, start);
 }
 
-export function isTypedArray(data: any) {
-    return data.buffer && typeof data.byteLength === 'number' && data.BYTES_PER_ELEMENT;
+export function isTypedArray(data: any): boolean {
+    return !!data.buffer && typeof data.byteLength === 'number' && typeof data.BYTES_PER_ELEMENT === 'number';
 }
 
-export function typedArrayWindow(data: any, params?: ToArrayParams): ReadonlyArray<number> {
+export function typedArrayWindow(data: any, params?: Column.ToArrayParams): ReadonlyArray<number> {
     const { constructor, buffer, length, byteOffset, BYTES_PER_ELEMENT } = data;
     const { start, end } = getArrayBounds(length, params);
     if (start === 0 && end === length) return data;
diff --git a/src/mol-io/reader/_spec/column.spec.ts b/src/mol-io/reader/_spec/column.spec.ts
index de51bde201a6d04aa24e1ea169213372a4845aeb..7ce9499de04be3eb1ca50cc9bfa18f3b291cd007 100644
--- a/src/mol-io/reader/_spec/column.spec.ts
+++ b/src/mol-io/reader/_spec/column.spec.ts
@@ -7,7 +7,7 @@
 
 import FixedColumn from '../common/text/column/fixed'
 import TokenColumn from '../common/text/column/token'
-import { ColumnType, typedArrayWindow } from '../../../mol-base/collections/column'
+import Column, { typedArrayWindow } from '../../../mol-base/collections/column'
 
 const lines = [
     '1.123 abc',
@@ -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, ColumnType.float);
-    const col2 = col(5, 4, ColumnType.str);
+    const col1 = col(0, 5, Column.Type.float);
+    const col2 = col(5, 4, Column.Type.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(ColumnType.int);
+    const col1 = col(Column.Type.int);
     it('number', () => {
         expect(col1.value(0)).toBe(3);
         expect(col1.value(1)).toBe(2);
diff --git a/src/mol-io/reader/cif/binary/field.ts b/src/mol-io/reader/cif/binary/field.ts
index d1d1c035a7e3a52d14919815beb1e9cf8047e1cb..1fc47f4a65ce91f06ba752e7097323aef7f36f7e 100644
--- a/src/mol-io/reader/cif/binary/field.ts
+++ b/src/mol-io/reader/cif/binary/field.ts
@@ -4,7 +4,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import * as Column from '../../../../mol-base/collections/column'
+import Column, { isTypedArray, createAndFillArray, typedArrayWindow } from '../../../../mol-base/collections/column'
 import * as Data from '../data-model'
 import { EncodedColumn } from './encoding'
 import decode from './decoder'
@@ -13,14 +13,14 @@ import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../../co
 export default function Field(column: EncodedColumn): Data.Field {
     const mask = column.mask ? decode(column.mask) as number[] : void 0;
     const data = decode(column.data);
-    const isNumeric = Column.isTypedArray(data);
+    const isNumeric = isTypedArray(data);
 
     const str: Data.Field['str'] = isNumeric
         ? mask
-            ? row => mask[row] === Data.ValuePresence.Present ? '' + data[row] : ''
+            ? row => mask[row] === Column.ValueKind.Present ? '' + data[row] : ''
             : row => '' + data[row]
         : mask
-            ? row => mask[row] === Data.ValuePresence.Present ? data[row] : ''
+            ? row => mask[row] === Column.ValueKind.Present ? data[row] : ''
             : row => data[row];
 
     const int: Data.Field['int'] = isNumeric
@@ -31,27 +31,28 @@ export default function Field(column: EncodedColumn): Data.Field {
         ? row => data[row]
         : row => { const v = data[row]; return fastParseFloat(v, 0, v.length); };
 
-    const presence: Data.Field['presence'] = mask
+    const valueKind: Data.Field['valueKind'] = mask
         ? row => mask[row]
-        : row => Data.ValuePresence.Present;
+        : row => Column.ValueKind.Present;
 
     const rowCount = data.length;
 
     return {
+        '@array': data,
         isDefined: true,
         rowCount,
         str,
         int,
         float,
-        presence,
+        valueKind,
         areValuesEqual: (rowA, rowB) => data[rowA] === data[rowB],
         stringEquals: (row, v) => str(row) === v,
-        toStringArray: params => Column.createAndFillArray(rowCount, str, params),
+        toStringArray: params => createAndFillArray(rowCount, str, params),
         toIntArray: isNumeric
-            ? params => Column.typedArrayWindow(data, params)
-            : params => Column.createAndFillArray(rowCount, int, params),
+            ? params => typedArrayWindow(data, params)
+            : params => createAndFillArray(rowCount, int, params),
         toFloatArray: isNumeric
-            ? params => Column.typedArrayWindow(data, params)
-            : params => Column.createAndFillArray(rowCount, float, params)
+            ? params => typedArrayWindow(data, params)
+            : params => createAndFillArray(rowCount, float, params)
     };
 }
\ No newline at end of file
diff --git a/src/mol-io/reader/cif/data-model.ts b/src/mol-io/reader/cif/data-model.ts
index e396f71b7e3bfe8f9bd83d5920321508d7c3db80..2de58e8ad0682bff11e9281e9c64bb4e75cbd431 100644
--- a/src/mol-io/reader/cif/data-model.ts
+++ b/src/mol-io/reader/cif/data-model.ts
@@ -4,7 +4,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import * as Column from '../../../mol-base/collections/column'
+import Column, { createArray } from '../../../mol-base/collections/column'
 
 export interface File {
     readonly name?: string,
@@ -50,12 +50,6 @@ export namespace Category {
     export const Empty: Category = { rowCount: 0, getField(name: string) { return void 0; } };
 }
 
-export const enum ValuePresence {
-    Present = 0,
-    NotSpecified = 1,
-    Unknown = 2
-}
-
 /**
  * Implementation note:
  * Always implement this as a "plain" object so that the functions are "closures"
@@ -63,6 +57,7 @@ export const enum ValuePresence {
  * additional closures.
  */
 export interface Field {
+    readonly '@array': ArrayLike<any> | undefined
     readonly isDefined: boolean,
     readonly rowCount: number,
 
@@ -70,7 +65,7 @@ export interface Field {
     int(row: number): number,
     float(row: number): number,
 
-    presence(row: number): ValuePresence,
+    valueKind(row: number): Column.ValueKind,
 
     areValuesEqual(rowA: number, rowB: number): boolean,
     stringEquals(row: number, value: string): boolean,
@@ -82,19 +77,20 @@ export interface Field {
 
 export function DefaultUndefinedField(rowCount: number): Field {
     return {
+        '@array': void 0,
         isDefined: false,
         rowCount,
         str: row => '',
         int: row => 0,
         float: row => 0,
 
-        presence: row => ValuePresence.NotSpecified,
+        valueKind: row => Column.ValueKind.NotPresent,
         areValuesEqual: (rowA, rowB) => true,
         stringEquals: (row, value) => value === null,
 
-        toStringArray: (p) => Column.createArray(rowCount, p).array,
-        toIntArray: (p) => Column.createArray(rowCount, p).array,
-        toFloatArray: (p) => Column.createArray(rowCount, p).array
+        toStringArray: (p) => createArray(rowCount, p).array,
+        toIntArray: (p) => createArray(rowCount, p).array,
+        toFloatArray: (p) => createArray(rowCount, p).array
     };
 }
 
diff --git a/src/mol-io/reader/cif/schema.ts b/src/mol-io/reader/cif/schema.ts
index b391d05b994ac565ee93517c55a8c3f540c2d320..7d603fc73f3710f279c20c33c7952860768b5087 100644
--- a/src/mol-io/reader/cif/schema.ts
+++ b/src/mol-io/reader/cif/schema.ts
@@ -5,8 +5,7 @@
  */
 
 import * as Data from './data-model'
-import * as Column from '../../../mol-base/collections/column'
-import StringPool from '../../utils/short-string-pool'
+import Column, { createAndFillArray } from '../../../mol-base/collections/column'
 
 /**
  * A schema defines the shape of categories and fields.
@@ -45,60 +44,53 @@ export type TypedCategory<Schema extends CategorySchema> = {
     readonly _rowCount: number,
     readonly _isDefined: boolean,
     readonly _category: Data.Category
-} & { [F in keyof Schema]: Column.Column<Schema[F]['T']> }
+} & { [F in keyof Schema]: Column<Schema[F]['T']> }
 
 export namespace Field {
-    export interface Schema<T> { T: T, ctor: (field: Data.Field, category: Data.Category, key: string) => Column.Column<T>, undefinedField: (c: number) => Data.Field, alias?: string };
+    export interface Schema<T> { T: T, ctor: (field: Data.Field, category: Data.Category, key: string) => Column<T>, undefinedField: (c: number) => Data.Field, alias?: string };
     export interface Spec { undefinedField?: (c: number) => Data.Field, alias?: string }
 
     export function alias(name: string): Schema<any> { return { alias: name } as any; }
-    export function pooledStr(spec?: Spec) { return createSchema(spec, PooledStr); }
     export function str(spec?: Spec) { return createSchema(spec, Str); }
     export function int(spec?: Spec) { return createSchema(spec, Int); }
     export function float(spec?: Spec) { return createSchema(spec, Float); }
     export function vector(rows: number, spec?: Spec) { return createSchema(spec, Vector(rows)); }
     export function matrix(rows: number, cols: number, spec?: Spec) { return createSchema(spec, Matrix(rows, cols)); }
 
-    function create<T>(type: Column.ColumnType, field: Data.Field, value: (row: number) => T, toArray: Column.Column<T>['toArray']): Column.Column<T> {
-        const presence = field.presence;
+    function create<T>(type: Column.Type, field: Data.Field, value: (row: number) => T, toArray: Column<T>['toArray']): Column<T> {
         return {
             '@type': type,
+            '@array': field['@array'],
             isDefined: field.isDefined,
             rowCount: field.rowCount,
             value,
-            isValueDefined: row => presence(row) === Data.ValuePresence.Present,
+            valueKind: field.valueKind,
             stringEquals: field.stringEquals,
             areValuesEqual: field.areValuesEqual,
             toArray
         };
     }
 
-    function PooledStr(field: Data.Field) {
-        const pool = StringPool.create();
-        const value = (row: number) => StringPool.get(pool, field.str(row));
-        const array = (params?: Column.ToArrayParams) => Column.createAndFillArray(field.rowCount, value, params);
-        return create<string>(Column.ColumnType.str, field, value, array);
-    }
-    function Str(field: Data.Field) { return create(Column.ColumnType.str, field, field.str, field.toStringArray); }
-    function Int(field: Data.Field) { return create(Column.ColumnType.int, field, field.int, field.toIntArray); }
-    function Float(field: Data.Field) { return create(Column.ColumnType.float, field, field.float, field.toFloatArray); }
+    function Str(field: Data.Field) { return create(Column.Type.str, field, field.str, field.toStringArray); }
+    function Int(field: Data.Field) { return create(Column.Type.int, field, field.int, field.toIntArray); }
+    function Float(field: Data.Field) { return create(Column.Type.float, field, field.float, field.toFloatArray); }
 
     function Vector(rows: number) {
         return function(field: Data.Field, category: Data.Category, key: string) {
             const value = (row: number) => Data.getVector(category, key, rows, row);
-            return create(Column.ColumnType.vector, field, value, params => Column.createAndFillArray(field.rowCount, value, params));
+            return create(Column.Type.vector, field, value, params => createAndFillArray(field.rowCount, value, params));
         }
     }
 
     function Matrix(rows: number, cols: number) {
         return function(field: Data.Field, category: Data.Category, key: string) {
             const value = (row: number) => Data.getMatrix(category, key, rows, cols, row);
-            return create(Column.ColumnType.matrix, field, value, params => Column.createAndFillArray(field.rowCount, value, params));
+            return create(Column.Type.matrix, field, value, params => createAndFillArray(field.rowCount, value, params));
         }
     }
 
     // spec argument is to allow for specialised implementation for undefined fields
-    function createSchema<T>(spec: Spec | undefined, ctor: (field: Data.Field, category: Data.Category, key: string) => Column.Column<T>): Schema<T> {
+    function createSchema<T>(spec: Spec | undefined, ctor: (field: Data.Field, category: Data.Category, key: string) => Column<T>): Schema<T> {
         return { T: 0 as any, ctor, undefinedField: (spec && spec.undefinedField) || Data.DefaultUndefinedField, alias: spec && spec.alias };
     }
 }
diff --git a/src/mol-io/reader/cif/schema/mmcif.ts b/src/mol-io/reader/cif/schema/mmcif.ts
index 45f31a003d75608660acc7a369a83496caca9605..b317a628481b7292b353517ebdc4f9f04c47b42d 100644
--- a/src/mol-io/reader/cif/schema/mmcif.ts
+++ b/src/mol-io/reader/cif/schema/mmcif.ts
@@ -6,7 +6,6 @@
 
 import { Field, TypedFrame } from '../schema'
 
-const pooledStr = Field.pooledStr();
 const str = Field.str();
 const int = Field.int();
 const float = Field.float();
@@ -58,19 +57,19 @@ const struct_conf = {
     conf_type_id: str,
     id: str,
     pdbx_PDB_helix_id: int,
-    beg_label_comp_id: pooledStr,
-    beg_label_asym_id: pooledStr,
+    beg_label_comp_id: str,
+    beg_label_asym_id: str,
     beg_label_seq_id: int,
-    pdbx_beg_PDB_ins_code: pooledStr,
-    end_label_comp_id: pooledStr,
-    end_label_asym_id: pooledStr,
+    pdbx_beg_PDB_ins_code: str,
+    end_label_comp_id: str,
+    end_label_asym_id: str,
     end_label_seq_id: int,
-    pdbx_end_PDB_ins_code: pooledStr,
-    beg_auth_comp_id: pooledStr,
-    beg_auth_asym_id: pooledStr,
+    pdbx_end_PDB_ins_code: str,
+    beg_auth_comp_id: str,
+    beg_auth_asym_id: str,
     beg_auth_seq_id: int,
-    end_auth_comp_id: pooledStr,
-    end_auth_asym_id: pooledStr,
+    end_auth_comp_id: str,
+    end_auth_asym_id: str,
     end_auth_seq_id: int,
     pdbx_PDB_helix_class: int,
     details: str,
@@ -78,21 +77,21 @@ const struct_conf = {
 }
 
 const struct_sheet_range = {
-    sheet_id: pooledStr,
+    sheet_id: str,
     id: int,
-    beg_label_comp_id: pooledStr,
-    beg_label_asym_id: pooledStr,
+    beg_label_comp_id: str,
+    beg_label_asym_id: str,
     beg_label_seq_id: int,
-    pdbx_beg_PDB_ins_code: pooledStr,
-    end_label_comp_id: pooledStr,
-    end_label_asym_id: pooledStr,
+    pdbx_beg_PDB_ins_code: str,
+    end_label_comp_id: str,
+    end_label_asym_id: str,
     end_label_seq_id: int,
-    pdbx_end_PDB_ins_code: pooledStr,
-    beg_auth_comp_id: pooledStr,
-    beg_auth_asym_id: pooledStr,
+    pdbx_end_PDB_ins_code: str,
+    beg_auth_comp_id: str,
+    beg_auth_asym_id: str,
     beg_auth_seq_id: int,
-    end_auth_comp_id: pooledStr,
-    end_auth_asym_id: pooledStr,
+    end_auth_comp_id: str,
+    end_auth_asym_id: str,
     end_auth_seq_id: int
 }
 
@@ -116,38 +115,38 @@ type BondValueOrder =
 
 const struct_conn = {
     id: str,
-    conn_type_id: pooledStr as Field.Schema<StructConnTypeId>,
+    conn_type_id: str as Field.Schema<StructConnTypeId>,
     pdbx_PDB_id: str,
-    ptnr1_label_asym_id: pooledStr,
-    ptnr1_label_comp_id: pooledStr,
+    ptnr1_label_asym_id: str,
+    ptnr1_label_comp_id: str,
     ptnr1_label_seq_id: int,
-    ptnr1_label_atom_id: pooledStr,
-    pdbx_ptnr1_label_alt_id: pooledStr,
-    pdbx_ptnr1_PDB_ins_code: pooledStr,
-    pdbx_ptnr1_standard_comp_id: pooledStr,
-    ptnr1_symmetry: pooledStr,
-    ptnr2_label_asym_id: pooledStr,
-    ptnr2_label_comp_id: pooledStr,
+    ptnr1_label_atom_id: str,
+    pdbx_ptnr1_label_alt_id: str,
+    pdbx_ptnr1_PDB_ins_code: str,
+    pdbx_ptnr1_standard_comp_id: str,
+    ptnr1_symmetry: str,
+    ptnr2_label_asym_id: str,
+    ptnr2_label_comp_id: str,
     ptnr2_label_seq_id: int,
-    ptnr2_label_atom_id: pooledStr,
-    pdbx_ptnr2_label_alt_id: pooledStr,
-    pdbx_ptnr2_PDB_ins_code: pooledStr,
-    ptnr1_auth_asym_id: pooledStr,
-    ptnr1_auth_comp_id: pooledStr,
+    ptnr2_label_atom_id: str,
+    pdbx_ptnr2_label_alt_id: str,
+    pdbx_ptnr2_PDB_ins_code: str,
+    ptnr1_auth_asym_id: str,
+    ptnr1_auth_comp_id: str,
     ptnr1_auth_seq_id: int,
-    ptnr2_auth_asym_id: pooledStr,
-    ptnr2_auth_comp_id: pooledStr,
+    ptnr2_auth_asym_id: str,
+    ptnr2_auth_comp_id: str,
     ptnr2_auth_seq_id: int,
-    ptnr2_symmetry: pooledStr,
-    pdbx_ptnr3_label_atom_id: pooledStr,
+    ptnr2_symmetry: str,
+    pdbx_ptnr3_label_atom_id: str,
     pdbx_ptnr3_label_seq_id: int,
-    pdbx_ptnr3_label_comp_id: pooledStr,
-    pdbx_ptnr3_label_asym_id: pooledStr,
-    pdbx_ptnr3_label_alt_id: pooledStr,
-    pdbx_ptnr3_PDB_ins_code: pooledStr,
-    details: pooledStr,
+    pdbx_ptnr3_label_comp_id: str,
+    pdbx_ptnr3_label_asym_id: str,
+    pdbx_ptnr3_label_alt_id: str,
+    pdbx_ptnr3_PDB_ins_code: str,
+    details: str,
     pdbx_dist_value: float,
-    pdbx_value_order: pooledStr as Field.Schema<BondValueOrder>
+    pdbx_value_order: str as Field.Schema<BondValueOrder>
 }
 
 const struct_conn_type = {
@@ -157,13 +156,13 @@ const struct_conn_type = {
 }
 
 const chem_comp_bond = {
-    comp_id: pooledStr,
-    pdbx_stereo_config: pooledStr,
+    comp_id: str,
+    pdbx_stereo_config: str,
     pdbx_ordinal: int,
-    pdbx_aromatic_flag: pooledStr as Field.Schema<'Y' | 'N'>,
-    atom_id_1: pooledStr,
-    atom_id_2: pooledStr,
-    value_order: pooledStr as Field.Schema<BondValueOrder>
+    pdbx_aromatic_flag: str as Field.Schema<'Y' | 'N'>,
+    atom_id_1: str,
+    atom_id_2: str,
+    value_order: str as Field.Schema<BondValueOrder>
 }
 
 const pdbx_struct_assembly = {
@@ -191,37 +190,37 @@ const pdbx_struct_oper_list = {
 
 const pdbx_struct_mod_residue = {
     id: int,
-    label_asym_id: pooledStr,
+    label_asym_id: str,
     label_seq_id: int,
-    label_comp_id: pooledStr,
-    auth_asym_id: pooledStr,
+    label_comp_id: str,
+    auth_asym_id: str,
     auth_seq_id: int,
-    auth_comp_id: pooledStr,
-    PDB_ins_code: pooledStr,
-    parent_comp_id: pooledStr,
+    auth_comp_id: str,
+    PDB_ins_code: str,
+    parent_comp_id: str,
     details: str
 }
 
 const atom_site = {
-    group_PDB: pooledStr,
+    group_PDB: str,
     id: int,
-    type_symbol: pooledStr,
-    label_atom_id: pooledStr,
-    label_alt_id: pooledStr,
-    label_comp_id: pooledStr,
-    label_asym_id: pooledStr,
-    label_entity_id: pooledStr,
+    type_symbol: str,
+    label_atom_id: str,
+    label_alt_id: str,
+    label_comp_id: str,
+    label_asym_id: str,
+    label_entity_id: str,
     label_seq_id: int,
-    pdbx_PDB_ins_code: pooledStr,
-    pdbx_formal_charge: pooledStr,
+    pdbx_PDB_ins_code: str,
+    pdbx_formal_charge: str,
     Cartn_x: float,
     Cartn_y: float,
     Cartn_z: float,
     occupancy: float,
     B_iso_or_equiv: float,
-    auth_atom_id: pooledStr,
-    auth_comp_id: pooledStr,
-    auth_asym_id: pooledStr,
+    auth_atom_id: str,
+    auth_comp_id: str,
+    auth_asym_id: str,
     auth_seq_id: int,
     pdbx_PDB_model_num: int
 }
diff --git a/src/mol-io/reader/cif/text/field.ts b/src/mol-io/reader/cif/text/field.ts
index 338bc327ddbffa062d7c7183410e916e14df435b..17454c0d791461a5b81926ed4d30a6b1c48f6930 100644
--- a/src/mol-io/reader/cif/text/field.ts
+++ b/src/mol-io/reader/cif/text/field.ts
@@ -4,7 +4,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import * as Column from '../../../../mol-base/collections/column'
+import Column, { createAndFillArray } from '../../../../mol-base/collections/column'
 import * as TokenColumn from '../../common/text/column/token'
 import { Tokens } from '../../common/text/tokenizer'
 import * as Data from '../data-model'
@@ -27,27 +27,28 @@ export default function CifTextField(tokens: Tokens, rowCount: number): Data.Fie
         return fastParseFloat(data, indices[2 * row], indices[2 * row + 1]) || 0;
     };
 
-    const presence: Data.Field['presence'] = row => {
+    const valueKind: Data.Field['valueKind'] = row => {
         const s = indices[2 * row];
-        if (indices[2 * row + 1] - s !== 1) return Data.ValuePresence.Present;
+        if (indices[2 * row + 1] - s !== 1) return Column.ValueKind.Present;
         const v = data.charCodeAt(s);
-        if (v === 46 /* . */) return Data.ValuePresence.NotSpecified;
-        if (v === 63 /* ? */) return Data.ValuePresence.Unknown;
-        return Data.ValuePresence.Present;
+        if (v === 46 /* . */) return Column.ValueKind.NotPresent;
+        if (v === 63 /* ? */) return Column.ValueKind.Unknown;
+        return Column.ValueKind.Present;
     };
 
     return {
+        '@array': void 0,
         isDefined: true,
         rowCount,
         str,
         int,
         float,
-        presence,
+        valueKind,
         areValuesEqual: TokenColumn.areValuesEqualProvider(tokens),
         stringEquals: (row, v) => {
             const s = indices[2 * row];
             const value = v || '';
-            if (!value && presence(row) !== Data.ValuePresence.Present) return true;
+            if (!value && valueKind(row) !== Column.ValueKind.Present) return true;
             const len = value.length;
             if (len !== indices[2 * row + 1] - s) return false;
             for (let i = 0; i < len; i++) {
@@ -55,8 +56,8 @@ export default function CifTextField(tokens: Tokens, rowCount: number): Data.Fie
             }
             return true;
         },
-        toStringArray: params => Column.createAndFillArray(rowCount, str, params),
-        toIntArray: params => Column.createAndFillArray(rowCount, int, params),
-        toFloatArray: params => Column.createAndFillArray(rowCount, float, params)
+        toStringArray: params => createAndFillArray(rowCount, str, params),
+        toIntArray: params => createAndFillArray(rowCount, int, params),
+        toFloatArray: params => createAndFillArray(rowCount, float, params)
     }
 }
\ No newline at end of file
diff --git a/src/mol-io/reader/common/text/column/fixed.ts b/src/mol-io/reader/common/text/column/fixed.ts
index 0a384f8a46508f89ec4c27d3fe53e9b3e1186b00..26d1c969d0e6dfe57d8f8b36e4435898b6eeb966 100644
--- a/src/mol-io/reader/common/text/column/fixed.ts
+++ b/src/mol-io/reader/common/text/column/fixed.ts
@@ -4,21 +4,19 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { Column, ColumnType, createAndFillArray } from '../../../../../mol-base/collections/column'
+import Column, { createAndFillArray } from '../../../../../mol-base/collections/column'
 import { trimStr, Tokens } from '../tokenizer'
 import { parseIntSkipLeadingWhitespace, parseFloatSkipLeadingWhitespace } from '../number-parser'
-import StringPool from '../../../../utils/short-string-pool'
 
 export default function FixedColumnProvider(lines: Tokens) {
-    return function<T extends ColumnType>(offset: number, width: number, type: T) {
+    return function<T extends Column.Type>(offset: number, width: number, type: T) {
         return FixedColumn(lines, offset, width, type);
     }
 }
 
-export function FixedColumn<T extends ColumnType>(lines: Tokens, offset: number, width: number, type: T): Column<T['@type']> {
+export function FixedColumn<T extends Column.Type>(lines: Tokens, offset: number, width: number, type: T): Column<T['@type']> {
     const { data, indices, count: rowCount } = lines;
     const { kind } = type;
-    const pool = kind === 'pooled-str' ? StringPool.create() : void 0;
 
     const value: Column<T['@type']>['value'] = kind === 'str' ? row => {
         let s = indices[2 * row] + offset, le = indices[2 * row + 1];
@@ -26,12 +24,6 @@ export function FixedColumn<T extends ColumnType>(lines: Tokens, offset: number,
         let e = s + width;
         if (e > le) e = le;
         return trimStr(data, s, e);
-    } : kind === 'pooled-str' ? row => {
-        let s = indices[2 * row] + offset, le = indices[2 * row + 1];
-        if (s >= le) return '';
-        let e = s + width;
-        if (e > le) e = le;
-        return StringPool.get(pool!, trimStr(data, s, e));
     } : kind === 'int' ? row => {
         const s = indices[2 * row] + offset;
         if (s > indices[2 * row + 1]) return 0;
@@ -43,10 +35,11 @@ export function FixedColumn<T extends ColumnType>(lines: Tokens, offset: number,
     };
     return {
         '@type': type,
+        '@array': void 0,
         isDefined: true,
         rowCount,
         value,
-        isValueDefined: row => true,
+        valueKind: row => Column.ValueKind.Present,
         toArray: params => createAndFillArray(rowCount, value, params),
         stringEquals: (row, v) => value(row) === v,
         areValuesEqual: (rowA, rowB) => value(rowA) === value(rowB)
diff --git a/src/mol-io/reader/common/text/column/token.ts b/src/mol-io/reader/common/text/column/token.ts
index 0b8d732b99f6081c99f99007fe7ccdee3cd44815..447752cc195ebccb7db44e0fa74ed1e889ce48ac 100644
--- a/src/mol-io/reader/common/text/column/token.ts
+++ b/src/mol-io/reader/common/text/column/token.ts
@@ -4,37 +4,34 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { Column, ColumnType, createAndFillArray } from '../../../../../mol-base/collections/column'
+import Column, { createAndFillArray } from '../../../../../mol-base/collections/column'
 import { Tokens } from '../tokenizer'
 import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../number-parser'
-import StringPool from '../../../../utils/short-string-pool'
 
 export default function TokenColumnProvider(tokens: Tokens) {
-    return function<T extends ColumnType>(type: T) {
+    return function<T extends Column.Type>(type: T) {
         return TokenColumn(tokens, type);
     }
 }
 
-export function TokenColumn<T extends ColumnType>(tokens: Tokens, type: T): Column<T['@type']> {
+export function TokenColumn<T extends Column.Type>(tokens: Tokens, type: T): Column<T['@type']> {
     const { data, indices, count: rowCount } = tokens;
     const { kind } = type;
-    const pool = kind === 'pooled-str' ? StringPool.create() : void 0;
 
     const value: Column<T['@type']>['value'] =
           kind === 'str'
         ? row => data.substring(indices[2 * row], indices[2 * row + 1])
-        : kind === 'pooled-str'
-        ? row => StringPool.get(pool!, data.substring(indices[2 * row], indices[2 * row + 1]))
         : kind === 'int'
         ? row => fastParseInt(data, indices[2 * row], indices[2 * row + 1]) || 0
         : row => fastParseFloat(data, indices[2 * row], indices[2 * row + 1]) || 0;
 
     return {
         '@type': type,
+        '@array': void 0,
         isDefined: true,
         rowCount,
         value,
-        isValueDefined: row => true,
+        valueKind: row => Column.ValueKind.Present,
         toArray: params => createAndFillArray(rowCount, value, params),
         stringEquals: (row, v) => {
             const s = indices[2 * row];
diff --git a/src/mol-io/reader/gro/parser.ts b/src/mol-io/reader/gro/parser.ts
index f4d28e4b0045270a4287d6942cefd83848f5a5ee..7a849ccc371fa1618955d4a8705700614195564f 100644
--- a/src/mol-io/reader/gro/parser.ts
+++ b/src/mol-io/reader/gro/parser.ts
@@ -7,7 +7,7 @@
 
 import Tokenizer from '../common/text/tokenizer'
 import FixedColumn from '../common/text/column/fixed'
-import { ColumnType, UndefinedColumn } from '../../../mol-base/collections/column'
+import Column from '../../../mol-base/collections/column'
 import * as Schema from './schema'
 import Result from '../result'
 import Computation from '../../../mol-base/computation'
@@ -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 = UndefinedColumn(state.numberOfAtoms, ColumnType.float);
+    const undef = Column.Undefined(state.numberOfAtoms, Column.Type.float);
 
     const ret = {
         count: state.numberOfAtoms,
-        residueNumber: col(0, 5, ColumnType.int),
-        residueName: col(5, 5, ColumnType.pooledStr),
-        atomName: col(10, 5, ColumnType.pooledStr),
-        atomNumber: col(15, 5, ColumnType.int),
-        x: col(pO, pW, ColumnType.float),
-        y: col(pO + pW, pW, ColumnType.float),
-        z: col(pO + 2 * pW, pW, ColumnType.float),
-        vx: hasVelocities ? col(vO, vW, ColumnType.float) : undef,
-        vy: hasVelocities ? col(vO + vW, vW, ColumnType.float) : undef,
-        vz: hasVelocities ? col(vO + 2 * vW, vW, ColumnType.float) : undef,
+        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,
     };
 
     return ret;
diff --git a/src/mol-io/reader/gro/schema.d.ts b/src/mol-io/reader/gro/schema.d.ts
index 981d2906aa620cd40898719bdb9181a47d672fbf..a32f34ee1ecc5ca3c2b5df1bb222b175c023026f 100644
--- a/src/mol-io/reader/gro/schema.d.ts
+++ b/src/mol-io/reader/gro/schema.d.ts
@@ -5,7 +5,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { Column } from '../../../mol-base/collections/column'
+import Column from '../../../mol-base/collections/column'
 
 export interface Header {
     title: string,
diff --git a/src/mol-io/reader/mol2/schema.d.ts b/src/mol-io/reader/mol2/schema.d.ts
index 8284c6f05d565a51b73a580713df5b52046050cd..15a2ca7afff455774e7bed56b72a7914c4a48dda 100644
--- a/src/mol-io/reader/mol2/schema.d.ts
+++ b/src/mol-io/reader/mol2/schema.d.ts
@@ -4,7 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Column } from '../../../mol-base/collections/column'
+import Column from '../../../mol-base/collections/column'
 
 // Full format http://chemyang.ccnu.edu.cn/ccb/server/AIMMS/mol2.pdf
 // there are many records but for now ignore (pass over) all but the following