diff --git a/src/mol-model/structure/model/properties/custom/descriptor.ts b/src/mol-model/structure/model/properties/custom/descriptor.ts index d86dd94a6fa415db073a466c0493b776854bd575..fd60c265dc356c5f86a44dbf370aa915794b5633 100644 --- a/src/mol-model/structure/model/properties/custom/descriptor.ts +++ b/src/mol-model/structure/model/properties/custom/descriptor.ts @@ -6,14 +6,22 @@ import { CifWriter } from 'mol-io/writer/cif' import { CifExportContext } from '../../../export/mmcif'; +import { QuerySymbolRuntime } from 'mol-script/runtime/query/compiler'; -interface ModelPropertyDescriptor { +interface ModelPropertyDescriptor<Symbols extends { [name: string]: QuerySymbolRuntime } = { }> { readonly isStatic: boolean, readonly name: string, cifExport: { categories: CifWriter.Category<CifExportContext>[] - } + }, + + // TODO: add aliases when lisp-like mol-script is done + symbols?: Symbols +} + +function ModelPropertyDescriptor<Desc extends ModelPropertyDescriptor>(desc: Desc) { + return desc; } export { ModelPropertyDescriptor } \ No newline at end of file diff --git a/src/mol-script/language/symbol.ts b/src/mol-script/language/symbol.ts index de9b536655c7689782e4b84b11edad833aa69fc3..bb935ee6f90b46f622459b68fe982eae660a58e1 100644 --- a/src/mol-script/language/symbol.ts +++ b/src/mol-script/language/symbol.ts @@ -74,6 +74,17 @@ export function MSymbol<A extends Arguments, T extends Type>(name: string, args: return symbol; } +export function CustomPropSymbol<T extends Type>(namespace: string, name: string, type: T, description?: string) { + const symbol: MSymbol<Arguments<{}>, T> = function(args: ExpressionArguments<Arguments<{}>['@type']>) { + return Expression.Apply(Expression.Symbol(symbol.id), args as any); + } as any; + symbol.info = { namespace, name, description }; + symbol.id = `${namespace}.${name}`; + symbol.args = Arguments.None; + symbol.type = type; + return symbol; +} + export function isSymbol(x: any): x is MSymbol { const s = x as MSymbol; return typeof s === 'function' && !!s.info && !!s.args && typeof s.info.namespace === 'string' && !!s.type; diff --git a/src/mol-script/runtime/query/compiler.ts b/src/mol-script/runtime/query/compiler.ts index 63598bb4c420865970b6e460213f5a5091fa3912..aa3c6b65263172f15b6c2f37321788f4f1b146f0 100644 --- a/src/mol-script/runtime/query/compiler.ts +++ b/src/mol-script/runtime/query/compiler.ts @@ -5,7 +5,7 @@ */ import Expression from '../../language/expression'; -import { QueryContext, QueryFn, Structure } from 'mol-model/structure'; +import { QueryContext, QueryFn, Structure, ModelPropertyDescriptor } from 'mol-model/structure'; import { MSymbol } from '../../language/symbol'; export class QueryRuntimeTable { @@ -15,6 +15,14 @@ export class QueryRuntimeTable { this.map.set(runtime.symbol.id, runtime); } + addCustomProp(desc: ModelPropertyDescriptor) { + if (!desc.symbols) return; + + for (const k of Object.keys(desc.symbols)) { + this.addSymbol((desc.symbols as any)[k]); + } + } + getRuntime(id: string) { return this.map.get(id); } diff --git a/src/mol-script/runtime/query/table.ts b/src/mol-script/runtime/query/table.ts index d5c4217d74a0c2dd107a7b509a8b9f3a4b320f0a..e0d555655a2369e68a413f601558c95047766169 100644 --- a/src/mol-script/runtime/query/table.ts +++ b/src/mol-script/runtime/query/table.ts @@ -30,6 +30,10 @@ const symbols = [ C(MolScript.core.rel.lte, (ctx, v) => v[0](ctx) <= v[1](ctx)), C(MolScript.core.rel.gr, (ctx, v) => v[0](ctx) > v[1](ctx)), C(MolScript.core.rel.gre, (ctx, v) => v[0](ctx) >= v[1](ctx)), + C(MolScript.core.rel.inRange, (ctx, v) => { + const x = v[0](ctx); + return x >= v[1](ctx) && x <= v[2](ctx); + }), // ============= TYPES ================ C(MolScript.structureQuery.type.elementSymbol, (ctx, v) => ElementSymbol(v[0](ctx))), @@ -46,16 +50,6 @@ const symbols = [ // ============= ATOM PROPERTIES ================ D(MolScript.structureQuery.atomProperty.macromolecular.label_comp_id, (ctx, _) => StructureProperties.residue.label_comp_id(ctx.element)), D(MolScript.structureQuery.atomProperty.core.elementSymbol, (ctx, _) => StructureProperties.atom.type_symbol(ctx.element)) - - // Symbol(MolQL.core.rel.neq, staticAttr)((env, v) => v[0](env) !== v[1](env)), - // Symbol(MolQL.core.rel.lt, staticAttr)((env, v) => v[0](env) < v[1](env)), - // Symbol(MolQL.core.rel.lte, staticAttr)((env, v) => v[0](env) <= v[1](env)), - // Symbol(MolQL.core.rel.gr, staticAttr)((env, v) => v[0](env) > v[1](env)), - // Symbol(MolQL.core.rel.gre, staticAttr)((env, v) => v[0](env) >= v[1](env)), - // Symbol(MolQL.core.rel.inRange, staticAttr)((env, v) => { - // const x = v[0](env); - // return x >= v[1](env) && x <= v[2](env) - // }), ]; (function () { diff --git a/src/perf-tests/mol-script.ts b/src/perf-tests/mol-script.ts index 104c6c1949383142a133d76c5a259a6c71dcfd01..5f6cfcc9ead8c6322b2a1a6bb21e113c3cd4edb1 100644 --- a/src/perf-tests/mol-script.ts +++ b/src/perf-tests/mol-script.ts @@ -1,7 +1,9 @@ import { MolScriptBuilder } from 'mol-script/language/builder'; -import { compile } from 'mol-script/runtime/query/compiler'; -import { QueryContext, Structure, StructureQuery } from 'mol-model/structure'; +import { compile, QuerySymbolRuntime, DefaultQueryRuntimeTable } from 'mol-script/runtime/query/compiler'; +import { QueryContext, Structure, StructureQuery, ModelPropertyDescriptor } from 'mol-model/structure'; import { readCifFile, getModelsAndStructure } from '../apps/structure-info/model'; +import { CustomPropSymbol } from 'mol-script/language/symbol'; +import Type from 'mol-script/language/type'; // import Examples from 'mol-script/script/mol-script/examples' // import { parseMolScript } from 'mol-script/script/mol-script/parser' @@ -27,6 +29,21 @@ const compiled = compile<number>(expr); const result = compiled(new QueryContext(Structure.Empty)); console.log(result); +const CustomProp = ModelPropertyDescriptor({ + name: 'test_prop', + isStatic: true, + cifExport: { categories: [ ]}, + symbols: { + residueIndex: QuerySymbolRuntime.Dynamic(CustomPropSymbol('custom.test-prop', 'residue-index', Type.Num), ctx => { + const e = ctx.element; + //console.log(e.element, e.unit.model.atomicHierarchy.residueAtomSegments.index[e.element]) + return e.unit.model.atomicHierarchy.residueAtomSegments.index[e.element]; + }) + } +}); + +DefaultQueryRuntimeTable.addCustomProp(CustomProp); + async function testQ() { const frame = await readCifFile('e:/test/quick/1cbs_updated.cif'); const { structure } = await getModelsAndStructure(frame); @@ -36,10 +53,11 @@ async function testQ() { MolScriptBuilder.struct.atomProperty.core.elementSymbol(), MolScriptBuilder.es('C') ]), - 'residue-test': MolScriptBuilder.core.rel.eq([ - MolScriptBuilder.struct.atomProperty.macromolecular.label_comp_id(), - 'REA' - ]) + // 'residue-test': MolScriptBuilder.core.rel.eq([ + // MolScriptBuilder.struct.atomProperty.macromolecular.label_comp_id(), + // 'REA' + // ]) + 'residue-test': MolScriptBuilder.core.rel.inRange([CustomProp.symbols.residueIndex.symbol(), 1, 5]) }); const compiled = compile<StructureQuery>(expr);