diff --git a/src/mol-model/structure/query/queries/internal.ts b/src/mol-model/structure/query/queries/internal.ts index 23b495f72a26920add9f871533c740b841b7242d..fecbf7d10bc2a533ed62e0d50912799ea1d5c568 100644 --- a/src/mol-model/structure/query/queries/internal.ts +++ b/src/mol-model/structure/query/queries/internal.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Segmentation } from '../../../../mol-data/int'; +import { Segmentation, SortedArray } from '../../../../mol-data/int'; import StructureElement from '../../../../mol-model/structure/structure/element'; import { StructureProperties as P, Unit } from '../../structure'; import Structure from '../../structure/structure'; @@ -12,6 +12,8 @@ import { StructureQuery } from '../query'; import { StructureSelection } from '../selection'; import { QueryContext } from '../context'; import { LinkType } from '../../model/types'; +import { BundleElement, Bundle } from '../../structure/element/bundle'; +import { UnitIndex } from '../../structure/element/element'; export function defaultLinkTest(ctx: QueryContext) { return LinkType.isCovalent(ctx.atomicLink.type); @@ -105,4 +107,23 @@ export function spheres(): StructureQuery { } return StructureSelection.Singletons(inputStructure, new Structure(units, { parent: inputStructure })); }; +} + +export function bundleElementImpl(groupedUnits: number[][], ranges: number[], set: number[]): BundleElement { + return { + groupedUnits: groupedUnits as any as SortedArray<number>[], + ranges: ranges as any as SortedArray<UnitIndex>, + set: set as any as SortedArray<UnitIndex> + }; +} + +export function bundleGenerator(elements: BundleElement[]): StructureQuery { + return ctx => { + const bundle: Bundle = { + hash: ctx.inputStructure.hashCode, + elements + }; + + return StructureSelection.Sequence(ctx.inputStructure, [Bundle.toStructure(bundle, ctx.inputStructure)]); + }; } \ No newline at end of file diff --git a/src/mol-model/structure/structure/element/bundle.ts b/src/mol-model/structure/structure/element/bundle.ts index b750308df22518ca0aaa64309c95bde947ea2e05..b222894267daaf4f7958d1aceea3efb3728dd989 100644 --- a/src/mol-model/structure/structure/element/bundle.ts +++ b/src/mol-model/structure/structure/element/bundle.ts @@ -12,8 +12,10 @@ import { hashFnv32a, hash2 } from '../../../../mol-data/util'; import SortedRanges from '../../../../mol-data/int/sorted-ranges'; import { UnitIndex } from './element'; import { Loci } from './loci'; +import Expression from '../../../../mol-script/language/expression'; +import { MolScriptBuilder as MS } from '../../../../mol-script/language/builder'; -interface BundleElement { +export interface BundleElement { /** * Array (sorted by first element in sub-array) of * arrays of `Unit.id`s that share the same `Unit.invariantId` @@ -192,6 +194,21 @@ export namespace Bundle { return Structure.create(units, { parent }) } + + function elementToExpression(e: BundleElement): Expression { + return MS.internal.generator.bundleElement({ + groupedUnits: MS.core.type.list(e.groupedUnits.map(u => MS.core.type.list(u))), + ranges: MS.core.type.list(e.ranges), + set: MS.core.type.list(e.set), + }) + } + + export function toExpression(bundle: Bundle): Expression { + return MS.internal.generator.bundle({ + elements: MS.core.type.list(bundle.elements.map(elementToExpression)) + }); + } + export function areEqual(a: Bundle, b: Bundle) { if (a.elements.length !== b.elements.length) return false for (let i = 0, il = a.elements.length; i < il; ++i) { diff --git a/src/mol-script/language/builder.ts b/src/mol-script/language/builder.ts index c114c0ff6307c5c2ed36ad44a35ff7a01a82c288..16038e3837ddc1f39468220af151a7a1dc252197 100644 --- a/src/mol-script/language/builder.ts +++ b/src/mol-script/language/builder.ts @@ -11,6 +11,7 @@ import { MolScriptSymbolTable as SymbolTable } from './symbol-table' export namespace MolScriptBuilder { export const core = SymbolTable.core; export const struct = SymbolTable.structureQuery; + export const internal = SymbolTable.internal; /** Atom-name constructor */ export function atomName(s: string) { return struct.type.atomName([s]); } diff --git a/src/mol-script/language/symbol-table.ts b/src/mol-script/language/symbol-table.ts index 3dec8616fedebe9973a69385ca78da09092d2020..b8fde22ab30653331273d04ba027a6a649221489 100644 --- a/src/mol-script/language/symbol-table.ts +++ b/src/mol-script/language/symbol-table.ts @@ -6,10 +6,11 @@ import core from './symbol-table/core' import structureQuery from './symbol-table/structure-query' +import internal from './symbol-table/internal' import { normalizeTable, symbolList } from './helpers' import { MSymbol } from './symbol' -const MolScriptSymbolTable = { core, structureQuery }; +const MolScriptSymbolTable = { core, structureQuery, internal }; normalizeTable(MolScriptSymbolTable); diff --git a/src/mol-script/language/symbol-table/internal.ts b/src/mol-script/language/symbol-table/internal.ts new file mode 100644 index 0000000000000000000000000000000000000000..d034334841a2b14989588e189195b3893e7cc809 --- /dev/null +++ b/src/mol-script/language/symbol-table/internal.ts @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2019 Mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import Type from '../type' +import * as Struct from './structure-query' +import { Arguments, Argument } from '../symbol' +import { symbol } from '../helpers' + +const generator = { + '@header': 'Generators', + + bundleElement: symbol(Arguments.Dictionary({ + // TODO: should we use more universal unit keys? (i.e. based on chain and "operator name") + groupedUnits: Argument(Type.Any), // SortedArray<number>[], + set: Argument(Type.Any), // SortedArray<UnitIndex> + ranges: Argument(Type.Any) // SortedArray<UnitIndex> + }), Type.Any), // returns BundleElement + + bundle: symbol(Arguments.Dictionary({ + elements: Argument(Type.Any) // BundleElement[] + }), Struct.Types.ElementSelectionQuery, 'A selection with single structure containing represented by the bundle.'), +} + +export default { + '@header': 'Internal Queries', + generator +} \ No newline at end of file diff --git a/src/mol-script/runtime/query/table.ts b/src/mol-script/runtime/query/table.ts index bf45a8836896209acf9bb1f08b4e8fc490cc2d0c..6c1bcf4414f50cc422320c9ce90e5eb0b7f89677 100644 --- a/src/mol-script/runtime/query/table.ts +++ b/src/mol-script/runtime/query/table.ts @@ -15,6 +15,7 @@ import { VdwRadius, AtomWeight, AtomNumber } from '../../../mol-model/structure/ import { cantorPairing } from '../../../mol-data/util'; import C = QuerySymbolRuntime.Const import D = QuerySymbolRuntime.Dynamic +import { bundleElementImpl, bundleGenerator } from '../../../mol-model/structure/query/queries/internal'; const symbols = [ // ============= TYPES ============= @@ -320,6 +321,12 @@ const symbols = [ // ============= BOND PROPERTIES ================ D(MolScript.structureQuery.linkProperty.order, (ctx, xs) => ctx.atomicLink.order), D(MolScript.structureQuery.linkProperty.flags, (ctx, xs) => ctx.atomicLink.type), + + + //////////////////////////////////// + // Internal + D(MolScript.internal.generator.bundleElement, (ctx, xs) => bundleElementImpl(xs.groupedUnits(ctx), xs.ranges(ctx), xs.set(ctx))), + D(MolScript.internal.generator.bundle, (ctx, xs) => bundleGenerator(xs.elements(ctx))), ]; function atomProp(p: (e: StructureElement.Location) => any): (ctx: QueryContext, _: any) => any {