From 4c15c9338137d04ea69b5a943e88491691a7424e Mon Sep 17 00:00:00 2001 From: dsehnal <david.sehnal@gmail.com> Date: Sat, 2 Apr 2022 20:54:35 +0200 Subject: [PATCH] lowercase column schema --- src/mol-data/db/_spec/table.spec.ts | 13 +++++ src/mol-data/db/column.ts | 52 +++++++++++++------ .../structure/model/properties/common.ts | 2 +- 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/mol-data/db/_spec/table.spec.ts b/src/mol-data/db/_spec/table.spec.ts index d1b15a317..6a5814a42 100644 --- a/src/mol-data/db/_spec/table.spec.ts +++ b/src/mol-data/db/_spec/table.spec.ts @@ -61,6 +61,19 @@ describe('column', () => { }); }); +describe('string column', () => { + const arr = Column.ofArray({ array: ['A', 'b'], schema: Column.Schema.Str({ lowerCase: true }) }); + + it('value', () => { + expect(arr.value(0)).toBe('a'); + expect(arr.value(1)).toBe('b'); + }); + + it('array', () => { + expect(arr.toArray()).toEqual(['a', 'b']); + }); +}); + describe('table', () => { const schema = { x: Column.Schema.int, diff --git a/src/mol-data/db/column.ts b/src/mol-data/db/column.ts index ee7bd67e0..f6079b579 100644 --- a/src/mol-data/db/column.ts +++ b/src/mol-data/db/column.ts @@ -25,38 +25,44 @@ 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 | Schema.List<number|string> + 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 type Base<T extends string> = { valueType: T } - export type Str = { '@type': 'str', T: string } & Base<'str'> + export type Str = { '@type': 'str', T: string, lowerCase?: boolean } & Base<'str'> export type Int = { '@type': 'int', T: number } & Base<'int'> export type Float = { '@type': 'float', T: number } & Base<'float'> export type Coordinate = { '@type': 'coord', T: number } & Base<'float'> export type Tensor = { '@type': 'tensor', T: Tensors.Data, space: Tensors.Space, baseType: Int | Float } & Base<'tensor'> export type Aliased<T> = { '@type': 'aliased', T: T } & Base<T extends string ? 'str' : 'int'> - export type List<T extends number|string> = { '@type': 'list', T: T[], separator: string, itemParse: (x: string) => T } & Base<'list'> + export type List<T extends number | string> = { '@type': 'list', T: T[], separator: string, itemParse: (x: string) => T } & Base<'list'> - export const str: Str = { '@type': 'str', T: '', valueType: 'str' }; + export const str: Str = { '@type': 'str', T: '', valueType: 'str', lowerCase: false }; export const int: Int = { '@type': 'int', T: 0, valueType: 'int' }; export const coord: Coordinate = { '@type': 'coord', T: 0, valueType: 'float' }; export const float: Float = { '@type': 'float', T: 0, valueType: 'float' }; - export function Str(defaultValue = ''): Str { return { '@type': 'str', T: defaultValue, valueType: 'str' }; }; + export function Str(options?: { defaultValue?: string, lowerCase?: boolean }): Str { return { '@type': 'str', T: options?.defaultValue ?? '', lowerCase: !!options?.lowerCase, valueType: 'str' }; }; export function Int(defaultValue = 0): Int { return { '@type': 'int', T: defaultValue, valueType: 'int' }; }; export function Float(defaultValue = 0): Float { return { '@type': 'float', T: defaultValue, valueType: 'float' }; }; export function Tensor(space: Tensors.Space, baseType: Int | Float = float): Tensor { return { '@type': 'tensor', T: space.create(), space, valueType: 'tensor', baseType }; } export function Vector(dim: number, baseType: Int | Float = float): Tensor { return Tensor(Tensors.Vector(dim, baseType['@type'] === 'int' ? Int32Array : Float64Array), baseType); } export function Matrix(rows: number, cols: number, baseType: Int | Float = float): Tensor { return Tensor(Tensors.ColumnMajorMatrix(rows, cols, baseType['@type'] === 'int' ? Int32Array : Float64Array), baseType); } - export function Aliased<T>(t: Str | Int, defaultValue?: T): Aliased<T> { - if (typeof defaultValue !== 'undefined') return { ...t, T: defaultValue } as any as Aliased<T>; + export function Aliased<T>(t: Str | Int, options?: { defaultValue?: T, lowerCase?: boolean }): Aliased<T> { + if (options) { + if (t.valueType === 'str') { + return Str(options as any) as any as Aliased<T>; + } else if (typeof options?.defaultValue === 'number') { + return Int(options.defaultValue as any) as any as Aliased<T>; + } + } return t as any as Aliased<T>; } - export function List<T extends number|string>(separator: string, itemParse: (x: string) => T, defaultValue: T[] = []): List<T> { + export function List<T extends number | string>(separator: string, itemParse: (x: string) => T, defaultValue: T[] = []): List<T> { return { '@type': 'list', T: defaultValue, separator, itemParse, valueType: 'list' }; } } @@ -288,7 +294,9 @@ function lambdaColumn<T extends Column.Schema>({ value, valueKind, areValuesEqua 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'] = schema.valueType === 'str' - ? row => { const v = array[row]; return typeof v === 'string' ? v : '' + v; } + ? (schema as Column.Schema.Str).lowerCase + ? row => { const v = array[row]; return typeof v === 'string' ? v.toLowerCase() : `${v}`.toLowerCase(); } + : row => { const v = array[row]; return typeof v === 'string' ? v : '' + v; } : row => array[row]; const isTyped = ColumnHelpers.isTypedArray(array); @@ -300,15 +308,25 @@ function arrayColumn<T extends Column.Schema>({ array, schema, valueKind }: Colu value, valueKind: valueKind ? valueKind : row => Column.ValueKind.Present, toArray: schema.valueType === '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; - for (let i = 0, _i = end - start; i < _i; i++) { - const v = array[start + i]; - ret[i] = typeof v === 'string' ? v : '' + v; + ? (schema as Column.Schema.Str).lowerCase + ? 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; + for (let i = 0, _i = end - start; i < _i; i++) { + const v = array[start + i]; + ret[i] = typeof v === 'string' ? v.toLowerCase() : `${v}`.toLowerCase(); + } + return ret; + } + : 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; + for (let i = 0, _i = end - start; i < _i; i++) { + const v = array[start + i]; + ret[i] = typeof v === 'string' ? v : '' + v; + } + return ret; } - return ret; - } : isTyped ? params => ColumnHelpers.typedArrayWindow(array, params) as any as ReadonlyArray<T> : params => { diff --git a/src/mol-model/structure/model/properties/common.ts b/src/mol-model/structure/model/properties/common.ts index 7e23ac4fb..2c284a288 100644 --- a/src/mol-model/structure/model/properties/common.ts +++ b/src/mol-model/structure/model/properties/common.ts @@ -17,7 +17,7 @@ export type EntitySubtype = ( 'lipid' | 'peptide-like' ) -export const EntitySubtype = Column.Schema.Aliased<EntitySubtype>(Column.Schema.Str('')); +export const EntitySubtype = Column.Schema.Aliased<EntitySubtype>(Column.Schema.Str()); export interface Entities { data: mmCIF_Database['entity'], -- GitLab