diff --git a/src/mol-model/structure/query/context.ts b/src/mol-model/structure/query/context.ts index 5c1f09357c7c564f7d1a4ae4dcf846b281d8af34..019624412b20a90cf3a29ce183ea252d513b0144 100644 --- a/src/mol-model/structure/query/context.ts +++ b/src/mol-model/structure/query/context.ts @@ -8,6 +8,7 @@ import { Structure, StructureElement, Unit } from '../structure'; import { now } from '../../../mol-util/now'; import { ElementIndex } from '../model'; import { Link } from '../structure/unit/links'; +import { LinkType } from '../model/types'; export interface QueryContextView { readonly element: StructureElement; @@ -16,7 +17,7 @@ export interface QueryContextView { export class QueryContext implements QueryContextView { private currentElementStack: StructureElement[] = []; - private currentAtomicLinkStack: Link.Location<Unit.Atomic>[] = []; + private currentAtomicLinkStack: QueryContextLinkInfo<Unit.Atomic>[] = []; private currentStructureStack: Structure[] = []; private inputStructureStack: Structure[] = []; @@ -30,7 +31,7 @@ export class QueryContext implements QueryContextView { currentStructure: Structure = void 0 as any; /** Current link between atoms */ - readonly atomicLink: Link.Location<Unit.Atomic> = Link.Location() as Link.Location<Unit.Atomic>; + readonly atomicLink = QueryContextLinkInfo.empty<Unit.Atomic>(); setElement(unit: Unit, e: ElementIndex) { this.element.unit = unit; @@ -49,13 +50,13 @@ export class QueryContext implements QueryContextView { pushCurrentLink() { if (this.atomicLink) this.currentAtomicLinkStack.push(this.atomicLink); - (this.atomicLink as Link.Location<Unit.Atomic>) = Link.Location() as Link.Location<Unit.Atomic>; + (this.atomicLink as QueryContextLinkInfo<Unit.Atomic>) = QueryContextLinkInfo.empty(); return this.atomicLink; } popCurrentLink() { if (this.currentAtomicLinkStack.length > 0) { - (this.atomicLink as Link.Location<Unit.Atomic>) = this.currentAtomicLinkStack.pop()!; + (this.atomicLink as QueryContextLinkInfo<Unit.Atomic>) = this.currentAtomicLinkStack.pop()!; } else { (this.atomicLink as any) = void 0; } @@ -94,4 +95,16 @@ export class QueryContext implements QueryContextView { } export interface QueryPredicate { (ctx: QueryContext): boolean } -export interface QueryFn<T = any> { (ctx: QueryContext): T } \ No newline at end of file +export interface QueryFn<T = any> { (ctx: QueryContext): T } + +export interface QueryContextLinkInfo<U extends Unit = Unit> { + link: Link.Location<U>, + type: LinkType, + order: number +} + +export namespace QueryContextLinkInfo { + export function empty<U extends Unit = Unit>(): QueryContextLinkInfo<U> { + return { link: Link.Location() as Link.Location<U>, type: LinkType.Flag.None, order: 0 }; + } +} \ No newline at end of file diff --git a/src/mol-model/structure/query/queries/filters.ts b/src/mol-model/structure/query/queries/filters.ts index f0ca68108ff5369307e398cc09d0ee12aab403ee..f4531fb298f86c152fb17f32095470ecc1b6b31f 100644 --- a/src/mol-model/structure/query/queries/filters.ts +++ b/src/mol-model/structure/query/queries/filters.ts @@ -15,6 +15,7 @@ import { checkStructureMaxRadiusDistance, checkStructureMinMaxDistance } from '. import Structure from '../../structure/structure'; import StructureElement from '../../structure/element'; import { SortedArray } from '../../../../mol-data/int'; +import { defaultLinkTest } from './internal'; export function pick(query: StructureQuery, pred: QueryPredicate): StructureQuery { return ctx => { @@ -231,12 +232,13 @@ interface IsConnectedToCtx { queryCtx: QueryContext, input: Structure, target: Structure, - bondTest: QueryFn<boolean>, + linkTest: QueryFn<boolean>, tElement: StructureElement } function checkConnected(ctx: IsConnectedToCtx, structure: Structure) { - const { queryCtx, input, target, bondTest, tElement } = ctx; + const { queryCtx, input, target, linkTest, tElement } = ctx; + const atomicLink = queryCtx.atomicLink; const interLinks = input.links; for (const unit of structure.units) { @@ -244,11 +246,11 @@ function checkConnected(ctx: IsConnectedToCtx, structure: Structure) { const inputUnit = input.unitMap.get(unit.id) as Unit.Atomic; - const { offset, b } = inputUnit.links; + const { offset, b, edgeProps: { flags, order } } = inputUnit.links; const linkedUnits = interLinks.getLinkedUnits(unit); const luCount = linkedUnits.length; - queryCtx.atomicLink.aUnit = inputUnit; + atomicLink.link.aUnit = inputUnit; const srcElements = unit.elements; const inputElements = inputUnit.elements; @@ -256,29 +258,33 @@ function checkConnected(ctx: IsConnectedToCtx, structure: Structure) { for (let i = 0 as StructureElement.UnitIndex, _i = srcElements.length; i < _i; i++) { const inputIndex = SortedArray.indexOf(inputElements, srcElements[i]) as StructureElement.UnitIndex; - queryCtx.atomicLink.aIndex = inputIndex; - queryCtx.atomicLink.bUnit = inputUnit; + atomicLink.link.aIndex = inputIndex; + atomicLink.link.bUnit = inputUnit; tElement.unit = unit; for (let l = offset[inputIndex], _l = offset[inputIndex + 1]; l < _l; l++) { tElement.element = inputElements[b[l]]; if (!target.hasElement(tElement)) continue; - queryCtx.atomicLink.bIndex = b[l] as StructureElement.UnitIndex; - if (bondTest(queryCtx)) return true; + atomicLink.link.bIndex = b[l] as StructureElement.UnitIndex; + atomicLink.type = flags[l]; + atomicLink.order = order[l]; + if (linkTest(queryCtx)) return true; } for (let li = 0; li < luCount; li++) { const lu = linkedUnits[li]; tElement.unit = lu.unitB; - queryCtx.atomicLink.bUnit = lu.unitB; + atomicLink.link.bUnit = lu.unitB; const bElements = lu.unitB.elements; const bonds = lu.getBonds(inputIndex); for (let bi = 0, _bi = bonds.length; bi < _bi; bi++) { const bond = bonds[bi]; tElement.element = bElements[bond.indexB]; if (!target.hasElement(tElement)) continue; - queryCtx.atomicLink.bIndex = bond.indexB; - if (bondTest(queryCtx)) return true; + atomicLink.link.bIndex = bond.indexB; + atomicLink.type = bond.flag; + atomicLink.order = bond.order; + if (linkTest(queryCtx)) return true; } } } @@ -290,16 +296,12 @@ function checkConnected(ctx: IsConnectedToCtx, structure: Structure) { export interface IsConnectedToParams { query: StructureQuery, target: StructureQuery, - bondTest?: QueryFn<boolean>, + linkTest?: QueryFn<boolean>, disjunct: boolean, invert: boolean } -function defaultBondTest(ctx: QueryContext) { - return true; -} - -export function isConnectedTo({ query, target, disjunct, invert, bondTest }: IsConnectedToParams): StructureQuery { +export function isConnectedTo({ query, target, disjunct, invert, linkTest }: IsConnectedToParams): StructureQuery { return ctx => { const targetSel = target(ctx); if (StructureSelection.isEmpty(targetSel)) return targetSel; @@ -310,7 +312,7 @@ export function isConnectedTo({ query, target, disjunct, invert, bondTest }: IsC queryCtx: ctx, input: ctx.inputStructure, target: StructureSelection.unionStructure(targetSel), - bondTest: bondTest || defaultBondTest, + linkTest: linkTest || defaultLinkTest, tElement: StructureElement.create() } diff --git a/src/mol-model/structure/query/queries/internal.ts b/src/mol-model/structure/query/queries/internal.ts index f1aa68f7999017a1750f374db39f71b9eace6aeb..625f4f5dd00f443edcf6489b6d1974658ebd5ee9 100644 --- a/src/mol-model/structure/query/queries/internal.ts +++ b/src/mol-model/structure/query/queries/internal.ts @@ -10,6 +10,12 @@ import { StructureProperties as P, Unit } from '../../structure'; import Structure from '../../structure/structure'; import { StructureQuery } from '../query'; import { StructureSelection } from '../selection'; +import { QueryContext } from '../context'; +import { LinkType } from '../../model/types'; + +export function defaultLinkTest(ctx: QueryContext) { + return LinkType.isCovalent(ctx.atomicLink.type); +} export function atomicSequence(): StructureQuery { return ctx => { diff --git a/src/mol-model/structure/query/queries/modifiers.ts b/src/mol-model/structure/query/queries/modifiers.ts index 96f3151b12ae065e5221a6055ba6ae5923aaa665..93c4ba8214d177091e55b26d9013385d762ea4d5 100644 --- a/src/mol-model/structure/query/queries/modifiers.ts +++ b/src/mol-model/structure/query/queries/modifiers.ts @@ -15,6 +15,7 @@ import { structureIntersect, structureSubtract } from '../utils/structure-set'; import { UniqueArray } from '../../../../mol-data/generic'; import { StructureSubsetBuilder } from '../../structure/util/subset-builder'; import StructureElement from '../../structure/element'; +import { defaultLinkTest } from './internal'; function getWholeResidues(ctx: QueryContext, source: Structure, structure: Structure) { const builder = source.subsetBuilder(true); @@ -298,13 +299,13 @@ export function expandProperty(query: StructureQuery, property: QueryFn): Struct export interface IncludeConnectedParams { query: StructureQuery, - bondTest?: QueryFn<boolean>, + linkTest?: QueryFn<boolean>, layerCount: number, wholeResidues: boolean } -export function includeConnected({ query, layerCount, wholeResidues, bondTest }: IncludeConnectedParams): StructureQuery { - const bt = bondTest || defaultBondTest; +export function includeConnected({ query, layerCount, wholeResidues, linkTest }: IncludeConnectedParams): StructureQuery { + const bt = linkTest || defaultLinkTest; const lc = Math.max(layerCount, 0); return ctx => { const builder = StructureSelection.UniqueBuilder(ctx.inputStructure); @@ -323,19 +324,21 @@ export function includeConnected({ query, layerCount, wholeResidues, bondTest }: } } -function includeConnectedStep(ctx: QueryContext, bondTest: QueryFn<boolean>, wholeResidues: boolean, structure: Structure) { - const expanded = expandConnected(ctx, structure, bondTest); +function includeConnectedStep(ctx: QueryContext, linkTest: QueryFn<boolean>, wholeResidues: boolean, structure: Structure) { + const expanded = expandConnected(ctx, structure, linkTest); if (wholeResidues) return getWholeResidues(ctx, ctx.inputStructure, expanded); return expanded; } -function expandConnected(ctx: QueryContext, structure: Structure, bondTest: QueryFn<boolean>) { +function expandConnected(ctx: QueryContext, structure: Structure, linkTest: QueryFn<boolean>) { const inputStructure = ctx.inputStructure; const interLinks = inputStructure.links; const builder = new StructureUniqueSubsetBuilder(inputStructure); const processedUnits = new Set<number>(); + const atomicLink = ctx.atomicLink; + // Process intra unit links for (const unit of structure.units) { processedUnits.add(unit.id); @@ -351,22 +354,24 @@ function expandConnected(ctx: QueryContext, structure: Structure, bondTest: Quer } const inputUnit = inputStructure.unitMap.get(unit.id) as Unit.Atomic; - const { offset: intraLinkOffset, b: intraLinkB } = inputUnit.links; + const { offset: intraLinkOffset, b: intraLinkB, edgeProps: { flags, order } } = inputUnit.links; // Process intra unit links - ctx.atomicLink.aUnit = inputUnit; - ctx.atomicLink.bUnit = inputUnit; + atomicLink.link.aUnit = inputUnit; + atomicLink.link.bUnit = inputUnit; for (let i = 0, _i = unit.elements.length; i < _i; i++) { // add the current element builder.addToUnit(unit.id, unit.elements[i]); const srcIndex = SortedArray.indexOf(inputUnit.elements, unit.elements[i]); - ctx.atomicLink.aIndex = srcIndex as StructureElement.UnitIndex; + atomicLink.link.aIndex = srcIndex as StructureElement.UnitIndex; // check intra unit links for (let lI = intraLinkOffset[srcIndex], _lI = intraLinkOffset[srcIndex + 1]; lI < _lI; lI++) { - ctx.atomicLink.bIndex = intraLinkB[lI] as StructureElement.UnitIndex; - if (bondTest(ctx)) { + atomicLink.link.bIndex = intraLinkB[lI] as StructureElement.UnitIndex; + atomicLink.type = flags[lI]; + atomicLink.order = order[lI]; + if (linkTest(ctx)) { builder.addToUnit(unit.id, inputUnit.elements[intraLinkB[lI]]); } } @@ -376,15 +381,17 @@ function expandConnected(ctx: QueryContext, structure: Structure, bondTest: Quer for (const linkedUnit of interLinks.getLinkedUnits(inputUnit)) { if (processedUnits.has(linkedUnit.unitB.id)) continue; - ctx.atomicLink.bUnit = linkedUnit.unitB; + atomicLink.link.bUnit = linkedUnit.unitB; for (const aI of linkedUnit.linkedElementIndices) { // check if the element is in the expanded structure if (!SortedArray.has(unit.elements, inputUnit.elements[aI])) continue; - ctx.atomicLink.aIndex = aI; + atomicLink.link.aIndex = aI; for (const bond of linkedUnit.getBonds(aI)) { - ctx.atomicLink.bIndex = bond.indexB; - if (bondTest(ctx)) { + atomicLink.link.bIndex = bond.indexB; + atomicLink.type = bond.flag; + atomicLink.order = bond.order; + if (linkTest(ctx)) { builder.addToUnit(linkedUnit.unitB.id, linkedUnit.unitB.elements[bond.indexB]); } } @@ -395,8 +402,4 @@ function expandConnected(ctx: QueryContext, structure: Structure, bondTest: Quer return builder.getStructure(); } -function defaultBondTest(ctx: QueryContext) { - return true; -} - // TODO: unionBy (skip this one?), cluster \ No newline at end of file diff --git a/src/mol-model/structure/structure/unit/rings/compute.ts b/src/mol-model/structure/structure/unit/rings/compute.ts index 112b305b592b2d0a2dc3bb3339fd90a3921940e1..5adb72fa14cfe76e206c88910b9f1ec5b89deb98 100644 --- a/src/mol-model/structure/structure/unit/rings/compute.ts +++ b/src/mol-model/structure/structure/unit/rings/compute.ts @@ -153,7 +153,7 @@ function addRing(state: State, a: number, b: number) { function findRings(state: State, from: number) { const { bonds, startVertex, endVertex, visited, queue, pred } = state; - const { b: neighbor, edgeProps: { flags: bondFlags }, offset } = bonds; + const { b: neighbor, edgeProps: { flags: linkFlags }, offset } = bonds; visited[from] = 1; queue[0] = from; let head = 0, size = 1; @@ -165,7 +165,7 @@ function findRings(state: State, from: number) { for (let i = start; i < end; i++) { const b = neighbor[i]; - if (b < startVertex || b >= endVertex || !LinkType.isCovalent(bondFlags[i])) continue; + if (b < startVertex || b >= endVertex || !LinkType.isCovalent(linkFlags[i])) continue; const other = b - startVertex; diff --git a/src/mol-script/language/symbol-table/structure-query.ts b/src/mol-script/language/symbol-table/structure-query.ts index c2b04dedc007cf87cfc8801283c56f94fef8787e..0def93ba0010d4e3269bb5b4060709dacdc7de5b 100644 --- a/src/mol-script/language/symbol-table/structure-query.ts +++ b/src/mol-script/language/symbol-table/structure-query.ts @@ -13,8 +13,8 @@ export namespace Types { export const ElementSymbol = Type.Value('Structure', 'ElementSymbol'); export const AtomName = Type.Value('Structure', 'AtomName'); - export const BondFlag = Type.OneOf('Structure', 'BondFlag', Type.Str, ['covalent', 'metallic', 'ion', 'hydrogen', 'sulfide', 'computed', 'aromatic']); - export const BondFlags = Core.Types.Flags(BondFlag, 'BondFlags'); + export const LinkFlag = Type.OneOf('Structure', 'LinkFlag', Type.Str, ['covalent', 'metallic', 'ion', 'hydrogen', 'sulfide', 'computed', 'aromatic']); + export const LinkFlags = Core.Types.Flags(LinkFlag, 'LinkFlags'); export const SecondaryStructureFlag = Type.OneOf('Structure', 'SecondaryStructureFlag', Type.Str, ['alpha', 'beta', '3-10', 'pi', 'sheet', 'strand', 'helix', 'turn', 'none']); export const SecondaryStructureFlags = Core.Types.Flags(SecondaryStructureFlag, 'SecondaryStructureFlag'); @@ -45,10 +45,10 @@ const type = { Types.EntityType, `Create normalized representation of entity type: ${Type.oneOfValues(Types.EntityType).join(', ')}.`), - bondFlags: symbol( - Arguments.List(Types.BondFlag), - Types.BondFlags, - `Create bond flags representation from a list of strings. Allowed flags: ${Type.oneOfValues(Types.BondFlag).join(', ')}.`), + linkFlags: symbol( + Arguments.List(Types.LinkFlag), + Types.LinkFlags, + `Create link flags representation from a list of strings. Allowed flags: ${Type.oneOfValues(Types.LinkFlag).join(', ')}.`), ringFingerprint: symbol( Arguments.List(Types.ElementSymbol, { nonEmpty: true }), @@ -146,8 +146,8 @@ const modifier = { includeConnected: symbol(Arguments.Dictionary({ 0: Argument(Types.ElementSelectionQuery), - 'bond-test': Argument(Type.Bool, { isOptional: true, defaultValue: 'true for covalent bonds' as any }), - 'layer-count': Argument(Type.Num, { isOptional: true, defaultValue: 1, description: 'Number of bonded layers to include.' }), + 'link-test': Argument(Type.Bool, { isOptional: true, defaultValue: 'true for covalent links' as any }), + 'layer-count': Argument(Type.Num, { isOptional: true, defaultValue: 1, description: 'Number of linked layers to include.' }), 'as-whole-residues': Argument(Type.Bool, { isOptional: true }) }), Types.ElementSelectionQuery, 'Pick all atom sets that are connected to the target.'), @@ -195,8 +195,8 @@ const filter = { isConnectedTo: symbol(Arguments.Dictionary({ 0: Argument(Types.ElementSelectionQuery), target: Argument(Types.ElementSelectionQuery), - 'bond-test': Argument(Type.Bool, { isOptional: true, defaultValue: 'true for covalent bonds' as any }), - disjunct: Argument(Type.Bool, { isOptional: true, defaultValue: true, description: 'If true, there must exist a bond to an atom that lies outside the given atom set to pass test.' }), + 'link-test': Argument(Type.Bool, { isOptional: true, defaultValue: 'true for covalent links' as any }), + disjunct: Argument(Type.Bool, { isOptional: true, defaultValue: true, description: 'If true, there must exist a link to an atom that lies outside the given atom set to pass test.' }), invert: Argument(Type.Bool, { isOptional: true, defaultValue: false, description: 'If true, return atom sets that are not connected.' }) }), Types.ElementSelectionQuery, 'Pick all atom sets that are connected to the target.'), } @@ -248,10 +248,10 @@ const atomProperty = { atomKey: atomProp(Type.AnyValue, 'Unique value for each atom. Main use case is grouping of atoms.'), - bondCount: symbol(Arguments.Dictionary({ + linkCount: symbol(Arguments.Dictionary({ 0: Argument(Types.ElementReference, { isOptional: true, defaultValue: 'slot.current-atom' }), - flags: Argument(Types.BondFlags, { isOptional: true, defaultValue: 'covalent' as any }), - }), Type.Num, 'Number of bonds (by default only covalent bonds are counted).'), + flags: Argument(Types.LinkFlags, { isOptional: true, defaultValue: 'covalent' as any }), + }), Type.Num, 'Number of links (by default only covalent links 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.'), @@ -306,18 +306,18 @@ const atomProperty = { } } -const bondProperty = { - '@header': 'Bond Properties', +const linkProperty = { + '@header': 'Link Properties', - flags: bondProp(Types.BondFlags), - order: bondProp(Type.Num) + flags: linkProp(Types.LinkFlags), + order: linkProp(Type.Num) } function atomProp(type: Type, description?: string) { return symbol(Arguments.Dictionary({ 0: Argument(Types.ElementReference, { isOptional: true, defaultValue: 'slot.current-atom' }) }), type, description); } -function bondProp(type: Type, description?: string) { +function linkProp(type: Type, description?: string) { return symbol(Arguments.None, type, description); } @@ -331,5 +331,5 @@ export default { combinator, atomSet, atomProperty, - bondProperty + linkProperty } \ 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 6ca3a8807d58f780018ef39f45c0b5249733a09a..ffae01e9a0dd412728826f55061d05e64c7f96a8 100644 --- a/src/mol-script/runtime/query/table.ts +++ b/src/mol-script/runtime/query/table.ts @@ -7,7 +7,7 @@ import { MolScriptSymbolTable as MolScript } from '../../language/symbol-table'; import { DefaultQueryRuntimeTable, QuerySymbolRuntime, QueryRuntimeArguments } from './compiler'; import { Queries, StructureProperties, StructureElement, QueryContext } from '../../../mol-model/structure'; -import { ElementSymbol } from '../../../mol-model/structure/model/types'; +import { ElementSymbol, LinkType } from '../../../mol-model/structure/model/types'; import { SetUtils } from '../../../mol-util/set'; import toUpperCase from '../../../mol-util/upper-case'; import { VdwRadius, AtomWeight, AtomNumber } from '../../../mol-model/structure/model/properties/atomic'; @@ -173,9 +173,17 @@ const symbols = [ // ============= TYPES ================ C(MolScript.structureQuery.type.elementSymbol, (ctx, v) => ElementSymbol(v[0](ctx))), C(MolScript.structureQuery.type.atomName, (ctx, v) => toUpperCase(v[0](ctx))), + C(MolScript.structureQuery.type.linkFlags, (ctx, xs) => { + let ret: LinkType = LinkType.Flag.None; + if (typeof xs.length === 'number') { + for (let i = 0, _i = xs.length; i < _i; i++) ret = linkFlag(ret, xs[i](ctx)); + } else { + for (const k of Object.keys(xs)) ret = linkFlag(ret, xs[k](ctx)); + } + return ret; + }), // TODO: - // C(MolScript.structureQuery.type.bondFlags, (ctx, v) => StructureRuntime.BondProperties.createFlags(env, v)), // C(MolScript.structureQuery.type.secondaryStructureFlags, (ctx, v) => StructureRuntime.AtomProperties.createSecondaryStructureFlags(env, v)), // C(MolScript.structureQuery.type.entityType, (ctx, v) => StructureRuntime.Common.entityType(v[0](ctx))), // C(MolScript.structureQuery.type.ringFingerprint, (ctx, v) => StructureRuntime.Common.ringFingerprint(env, v as any)), @@ -205,7 +213,7 @@ const symbols = [ target: xs['target'] as any, disjunct: xs['disjunct'] as any, invert: xs['invert'] as any, - bondTest: xs['bond-test'] + linkTest: xs['link-test'] })(ctx)), // ============= GENERATORS ================ @@ -233,7 +241,7 @@ const symbols = [ D(MolScript.structureQuery.modifier.exceptBy, (ctx, xs) => Queries.modifiers.exceptBy(xs[0] as any, xs['by'] as any)(ctx)), D(MolScript.structureQuery.modifier.includeConnected, (ctx, xs) => Queries.modifiers.includeConnected({ query: xs[0] as any, - bondTest: xs['bond-test'], + linkTest: xs['link-test'], wholeResidues: !!(xs['as-whole-residues'] && xs['as-whole-residues'](ctx)), layerCount: (xs['layer-count'] && xs['layer-count'](ctx)) || 1 })(ctx)), @@ -308,12 +316,27 @@ const symbols = [ D(MolScript.structureQuery.atomProperty.macromolecular.chemCompType, atomProp(StructureProperties.residue.chem_comp_type)), // ============= BOND PROPERTIES ================ + D(MolScript.structureQuery.linkProperty.order, (ctx, xs) => ctx.atomicLink.order), + D(MolScript.structureQuery.linkProperty.flags, (ctx, xs) => ctx.atomicLink.type), ]; function atomProp(p: (e: StructureElement) => any): (ctx: QueryContext, _: any) => any { return (ctx, _) => p(ctx.element); } +function linkFlag(current: LinkType, f: string): LinkType { + switch (f.toLowerCase()) { + case 'covalent': return current | LinkType.Flag.Covalent; + case 'metallic': return current | LinkType.Flag.MetallicCoordination; + case 'ion': return current | LinkType.Flag.Ionic; + case 'hydrogen': return current | LinkType.Flag.Hydrogen; + case 'sulfide': return current | LinkType.Flag.Sulfide; + case 'aromatic': return current | LinkType.Flag.Aromatic; + case 'computed': return current | LinkType.Flag.Computed; + default: return current; + } +} + (function () { for (const s of symbols) { DefaultQueryRuntimeTable.addSymbol(s); diff --git a/src/mol-script/script/mol-script/examples.ts b/src/mol-script/script/mol-script/examples.ts index 1f689f1d3697c9f3a447d9fcdfe1f606312bd8c9..41928547c4f2e4fb72b1d8722150d88a9f489bf9 100644 --- a/src/mol-script/script/mol-script/examples.ts +++ b/src/mol-script/script/mol-script/examples.ts @@ -10,7 +10,7 @@ // sel.atom.res // :target (sel.atom.res (= atom.label_comp_id HEM)) // ;; default bond test allows only covalent bonds -// :bond-test true +// :link-test true // :disjunct true)` // }, { // name: 'All C or N atoms in ALA residues', @@ -46,8 +46,8 @@ // value: `(sel.atom.include-connected // (sel.atom.res (= atom.label_comp_id HEM)) // ;; default bond test allows only covalent bonds -// ;; another option is to use :bond-test true to allow any connection -// :bond-test (bond.is metallic covalent) +// ;; another option is to use :link-test true to allow any connection +// :link-test (bond.is metallic covalent) // :layer-count 2 // :as-whole-residues true)` // }, { diff --git a/src/mol-script/script/mol-script/symbols.ts b/src/mol-script/script/mol-script/symbols.ts index 2018030dcd72c9f37c3f67184634457e599655bd..9e17f88446e4caee7328cba46e9d0449ace79db0 100644 --- a/src/mol-script/script/mol-script/symbols.ts +++ b/src/mol-script/script/mol-script/symbols.ts @@ -90,7 +90,7 @@ export const SymbolTable = [ Alias(MolScript.structureQuery.type.authResidueId, 'auth-resid'), Alias(MolScript.structureQuery.type.labelResidueId, 'label-resid'), Alias(MolScript.structureQuery.type.ringFingerprint, 'ringfp'), - Alias(MolScript.structureQuery.type.bondFlags, 'bond-flags'), + Alias(MolScript.structureQuery.type.linkFlags, 'bond-flags'), ], [ 'Slots', @@ -203,7 +203,7 @@ export const SymbolTable = [ Alias(MolScript.structureQuery.atomProperty.core.modelIndex, 'atom.model-index'), Alias(MolScript.structureQuery.atomProperty.core.modelLabel, 'atom.model-label'), Alias(MolScript.structureQuery.atomProperty.core.atomKey, 'atom.key'), - Alias(MolScript.structureQuery.atomProperty.core.bondCount, 'atom.bond-count'), + Alias(MolScript.structureQuery.atomProperty.core.linkCount, 'atom.link-count'), Alias(MolScript.structureQuery.atomProperty.topology.connectedComponentKey, 'atom.key.molecule'), @@ -242,11 +242,11 @@ export const SymbolTable = [ // args => B.core.flags.hasAny([B.struct.atomProperty.macromolecular.secondaryStructureFlags(), B.struct.type.secondaryStructureFlags(args)])), ], [ - 'Bond Properties', - Alias(MolScript.structureQuery.bondProperty.order, 'bond.order'), - // Macro(MSymbol('bond.is', Arguments.List(Struct.Types.BondFlag), Type.Bool, - // `Test if the current bond has at least one (or all if partial = false) of the specified flags: ${Type.oneOfValues(Struct.Types.BondFlag).join(', ')}`), - // args => B.core.flags.hasAny([B.struct.bondProperty.flags(), B.struct.type.bondFlags(M.getPositionalArgs(args))])), + 'Link Properties', + Alias(MolScript.structureQuery.linkProperty.order, 'link.order'), + // Macro(MSymbol('bond.is', Arguments.List(Struct.Types.LinkFlag), Type.Bool, + // `Test if the current bond has at least one (or all if partial = false) of the specified flags: ${Type.oneOfValues(Struct.Types.LinkFlag).join(', ')}`), + // args => B.core.flags.hasAny([B.struct.bondProperty.flags(), B.struct.type.linkFlags(M.getPositionalArgs(args))])), ] ] ];