Ver código fonte

lowercase column schema

dsehnal 3 anos atrás
pai
commit
4c15c93381

+ 13 - 0
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,

+ 35 - 17
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 => {

+ 1 - 1
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'],