diff --git a/src/mol-model/structure/structure/element.ts b/src/mol-model/structure/structure/element.ts index 7d182793309d9163aa212152827bb349c026cb98..3e0ec4ec82004ed7b7d30d7d4a56716a61a35acd 100644 --- a/src/mol-model/structure/structure/element.ts +++ b/src/mol-model/structure/structure/element.ts @@ -254,11 +254,19 @@ namespace StructureElement { } if (loci.elements.length === 0) return MS.struct.generator.empty(); - const sourceIndices = UniqueArray.create<number, number>(); + const sourceIndexMap = new Map<string, UniqueArray<number, number>>(); const el = StructureElement.create(), p = StructureProperties.atom.sourceIndex; for (const e of loci.elements) { const { indices } = e; const { elements } = e.unit; + const opName = e.unit.conformation.operator.name; + + let sourceIndices: UniqueArray<number, number>; + if (sourceIndexMap.has(opName)) sourceIndices = sourceIndexMap.get(opName)!; + else { + sourceIndices = UniqueArray.create<number, number>(); + sourceIndexMap.set(opName, sourceIndices); + } el.unit = e.unit; for (let i = 0, _i = OrderedSet.size(indices); i < _i; i++) { @@ -268,7 +276,20 @@ namespace StructureElement { } } - const xs = sourceIndices.array; + const byOpName: Expression[] = []; + const keys = sourceIndexMap.keys(); + while (true) { + const k = keys.next(); + if (k.done) break; + byOpName.push(getOpNameQuery(k.value, sourceIndexMap.get(k.value)!.array)); + } + + return MS.struct.modifier.union([ + byOpName.length === 1 ? byOpName[0] : MS.struct.combinator.merge.apply(null, byOpName) + ]); + } + + function getOpNameQuery(opName: string, xs: number[]) { sortArray(xs); const ranges: number[] = []; @@ -304,7 +325,7 @@ namespace StructureElement { return MS.struct.generator.atomGroups({ 'atom-test': tests.length > 1 ? MS.core.logic.or.apply(null, tests) : tests[0], - 'group-by': 0 + 'chain-test': MS.core.rel.eq([MS.struct.atomProperty.core.operatorName(), opName]) }); } } diff --git a/src/mol-script/language/symbol-table/structure-query.ts b/src/mol-script/language/symbol-table/structure-query.ts index 1d87ccf8a62a6b4abd7ee496664acb2210752bbc..4f9f7377efb220f0dbb65717677675540095a9d1 100644 --- a/src/mol-script/language/symbol-table/structure-query.ts +++ b/src/mol-script/language/symbol-table/structure-query.ts @@ -249,6 +249,7 @@ const atomProperty = { }), Type.Num, 'Number of bonds (by default only covalent bonds are counted).'), sourceIndex: atomProp(Type.Num, 'Index of the atom/element in the input file.'), + operatorName: atomProp(Type.Str, 'Name of the symmetry operator applied to this element.'), }, topology: { diff --git a/src/mol-script/runtime/query/table.ts b/src/mol-script/runtime/query/table.ts index 7e48327940d58dd3913730897b2a514eb9a566eb..ba1072a587beb9c0c8ed2bf3b83dac130894b7f8 100644 --- a/src/mol-script/runtime/query/table.ts +++ b/src/mol-script/runtime/query/table.ts @@ -206,9 +206,14 @@ const symbols = [ elementRadius: xs['atom-radius'] })(ctx)), D(MolScript.structureQuery.modifier.wholeResidues, (ctx, xs) => Queries.modifiers.wholeResidues(xs[0] as any)(ctx)), + D(MolScript.structureQuery.modifier.union, (ctx, xs) => Queries.modifiers.union(xs[0] as any)(ctx)), D(MolScript.structureQuery.modifier.expandProperty, (ctx, xs) => Queries.modifiers.expandProperty(xs[0] as any, xs['property'])(ctx)), D(MolScript.structureQuery.modifier.exceptBy, (ctx, xs) => Queries.modifiers.exceptBy(xs[0] as any, xs['by'] as any)(ctx)), + // ============= COMBINATORS ================ + + D(MolScript.structureQuery.combinator.merge, (ctx, xs) => Queries.combinators.merge(xs as any)(ctx)), + // ============= ATOM PROPERTIES ================ // ~~~ CORE ~~~ @@ -220,6 +225,7 @@ const symbols = [ D(MolScript.structureQuery.atomProperty.core.y, atomProp(StructureProperties.atom.y)), D(MolScript.structureQuery.atomProperty.core.z, atomProp(StructureProperties.atom.z)), D(MolScript.structureQuery.atomProperty.core.sourceIndex, atomProp(StructureProperties.atom.sourceIndex)), + D(MolScript.structureQuery.atomProperty.core.operatorName, atomProp(StructureProperties.unit.operator_name)), D(MolScript.structureQuery.atomProperty.core.atomKey, (ctx, _) => cantorPairing(ctx.element.unit.id, ctx.element.element)), // TODO: diff --git a/src/mol-script/script/mol-script/symbols.ts b/src/mol-script/script/mol-script/symbols.ts index 43aa954f111bcb83f046ecfb26eec59eaf2b88c6..0c4826f7ffc685e85a84b9617b83188def6a6e06 100644 --- a/src/mol-script/script/mol-script/symbols.ts +++ b/src/mol-script/script/mol-script/symbols.ts @@ -7,7 +7,6 @@ import { UniqueArray } from 'mol-data/generic'; import Expression from '../../language/expression'; import { Argument, MSymbol } from '../../language/symbol'; -//import * as M from './macro' import { MolScriptSymbolTable as MolScript } from '../../language/symbol-table'; import Type from '../../language/type'; @@ -197,6 +196,7 @@ export const SymbolTable = [ Alias(MolScript.structureQuery.atomProperty.core.y, 'atom.y'), Alias(MolScript.structureQuery.atomProperty.core.z, 'atom.z'), Alias(MolScript.structureQuery.atomProperty.core.sourceIndex, 'atom.src-index'), + Alias(MolScript.structureQuery.atomProperty.core.operatorName, 'atom.op-name'), Alias(MolScript.structureQuery.atomProperty.core.atomKey, 'atom.key'), Alias(MolScript.structureQuery.atomProperty.core.bondCount, 'atom.bond-count'), @@ -343,4 +343,4 @@ export function transpileMolScript(expr: Expression) { // if (a.length === b.length) return (a < b) as any; // return a.length - b.length; // }); -//export default [...sortedSymbols, ...NamedArgs.map(a => ':' + a), ...Constants]; \ No newline at end of file +// export default [...sortedSymbols, ...NamedArgs.map(a => ':' + a), ...Constants]; \ No newline at end of file