Browse Source

mol-script: bond* => link*; make link tests "covalent" by default; wip link tests

David Sehnal 5 years ago
parent
commit
ea46b1c8c8

+ 18 - 5
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 }
+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 };
+    }
+}

+ 20 - 18
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()
         }
 

+ 6 - 0
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 => {

+ 23 - 20
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

+ 2 - 2
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;
 

+ 19 - 19
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
 }

+ 27 - 4
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);

+ 3 - 3
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)`
 // }, {

+ 7 - 7
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))])),
         ]
     ]
 ];