Explorar el Código

improved bond handling

- filter (include/exclude) type in repr
- cleaned-up bond types and names
Alexander Rose hace 5 años
padre
commit
b77994d01f

+ 2 - 2
src/mol-model-formats/structure/mmcif/bonds/struct_conn.ts

@@ -235,9 +235,9 @@ export namespace StructConn {
                 case 'covale':
                     flags = BondType.Flag.Covalent;
                     break;
-                case 'disulf': flags = BondType.Flag.Covalent | BondType.Flag.Sulfide; break;
+                case 'disulf': flags = BondType.Flag.Covalent | BondType.Flag.Disulfide; break;
                 case 'hydrog':
-                    flags = BondType.Flag.Hydrogen;
+                    flags = BondType.Flag.HydrogenBond;
                     break;
                 case 'metalc': flags = BondType.Flag.MetallicCoordination; break;
             }

+ 37 - 5
src/mol-model/structure/model/types.ts

@@ -592,11 +592,10 @@ export namespace BondType {
         None                 = 0x0,
         Covalent             = 0x1,
         MetallicCoordination = 0x2,
-        Hydrogen             = 0x4,
-        Ionic                = 0x8,
-        Sulfide              = 0x10,
-        Aromatic             = 0x20,
-        Computed             = 0x40
+        HydrogenBond         = 0x4,
+        Disulfide            = 0x8,
+        Aromatic             = 0x10,
+        Computed             = 0x20
         // currently at most 16 flags are supported!!
     }
 
@@ -607,6 +606,39 @@ export namespace BondType {
     export function isCovalent(flags: BondType.Flag) {
         return (flags & BondType.Flag.Covalent) !== 0;
     }
+
+    export const Names = {
+        'covalent': Flag.Covalent,
+        'metal-coordination': Flag.MetallicCoordination,
+        'hydrogen-bond': Flag.HydrogenBond,
+        'disulfide': Flag.HydrogenBond,
+        'aromatic': Flag.HydrogenBond,
+        'computed': Flag.HydrogenBond,
+    }
+    export type Names = keyof typeof Names
+
+    export function isName(name: string): name is Names {
+        return name in Names
+    }
+
+    export function fromName(name: Names): Flag {
+        switch (name) {
+            case 'covalent': return Flag.Covalent;
+            case 'metal-coordination': return Flag.MetallicCoordination;
+            case 'hydrogen-bond': return Flag.HydrogenBond;
+            case 'disulfide': return Flag.Disulfide;
+            case 'aromatic': return Flag.Aromatic;
+            case 'computed': return Flag.Computed;
+        }
+    }
+
+    export function fromNames(names: Names[]): Flag {
+        let f = Flag.None
+        for (let i = 0, il = names.length; i < il; ++i) {
+            f |= fromName(names[i])
+        }
+        return f
+    }
 }
 
 /**

+ 1 - 1
src/mol-plugin/util/structure-selection-helper.ts

@@ -264,7 +264,7 @@ const disulfideBridges = StructureSelectionQuery('Disulfide Bridges', MS.struct.
             MS.struct.generator.bondedAtomicPairs({
                 0: MS.core.flags.hasAny([
                     MS.struct.bondProperty.flags(),
-                    MS.core.type.bitflags([BondType.Flag.Sulfide])
+                    MS.core.type.bitflags([BondType.Flag.Disulfide])
                 ])
             })
         ])

+ 17 - 9
src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts

@@ -10,14 +10,15 @@ import { Structure, StructureElement, Bond, Unit } from '../../../mol-model/stru
 import { Theme } from '../../../mol-theme/theme';
 import { Mesh } from '../../../mol-geo/geometry/mesh/mesh';
 import { Vec3 } from '../../../mol-math/linear-algebra';
-import { BitFlags } from '../../../mol-util';
-import { createBondCylinderMesh, BondCylinderParams, BondIterator } from './util/bond';
+import { BitFlags, arrayEqual } from '../../../mol-util';
+import { createBondCylinderMesh, BondCylinderParams, BondIterator, ignoreBondType } from './util/bond';
 import { ComplexMeshParams, ComplexVisual, ComplexMeshVisual } from '../complex-visual';
 import { VisualUpdateState } from '../../util';
 import { PickingId } from '../../../mol-geo/geometry/picking';
 import { EmptyLoci, Loci } from '../../../mol-model/loci';
 import { Interval, OrderedSet } from '../../../mol-data/int';
 import { isHydrogen } from './util/common';
+import { BondType } from '../../../mol-model/structure/model/types';
 
 const tmpRefPosBondIt = new Bond.ElementBondIterator()
 function setRefPosition(pos: Vec3, structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) {
@@ -36,7 +37,16 @@ const tmpLoc = StructureElement.Location.create()
 function createInterUnitBondCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<InterUnitBondParams>, mesh?: Mesh) {
     const bonds = structure.interUnitBonds
     const { edgeCount, edges } = bonds
-    const { sizeFactor, sizeAspectRatio, ignoreHydrogens } = props
+    const { sizeFactor, sizeAspectRatio, ignoreHydrogens, includeTypes, excludeTypes } = props
+
+    const include = BondType.fromNames(includeTypes)
+    const exclude = BondType.fromNames(excludeTypes)
+
+    const ignoreHydrogen = ignoreHydrogens ? (edgeIndex: number) => {
+        const b = edges[edgeIndex]
+        const uA = b.unitA, uB = b.unitB
+        return isHydrogen(uA, uA.elements[b.indexA]) || isHydrogen(uB, uB.elements[b.indexB])
+    } : () => false
 
     if (!edgeCount) return Mesh.createEmpty(mesh)
 
@@ -75,11 +85,7 @@ function createInterUnitBondCylinderMesh(ctx: VisualContext, structure: Structur
             const sizeB = theme.size.size(tmpLoc)
             return Math.min(sizeA, sizeB) * sizeFactor * sizeAspectRatio
         },
-        ignore: ignoreHydrogens ? (edgeIndex: number) => {
-            const b = edges[edgeIndex]
-            const uA = b.unitA, uB = b.unitB
-            return isHydrogen(uA, uA.elements[b.indexA]) || isHydrogen(uB, uB.elements[b.indexB])
-        } : () => false
+        ignore: (edgeIndex: number) => ignoreHydrogen(edgeIndex) || ignoreBondType(include, exclude, edges[edgeIndex].props.flag)
     }
 
     return createBondCylinderMesh(ctx, builderProps, props, mesh)
@@ -109,7 +115,9 @@ export function InterUnitBondVisual(materialId: number): ComplexVisual<InterUnit
                 newProps.bondScale !== currentProps.bondScale ||
                 newProps.bondSpacing !== currentProps.bondSpacing ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
-                newProps.bondCap !== currentProps.bondCap
+                newProps.bondCap !== currentProps.bondCap ||
+                !arrayEqual(newProps.includeTypes, currentProps.includeTypes) ||
+                !arrayEqual(newProps.excludeTypes, currentProps.excludeTypes)
             )
         }
     }, materialId)

+ 16 - 8
src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  * @author David Sehnal <david.sehnal@gmail.com>
@@ -11,14 +11,15 @@ import { Unit, Structure, StructureElement, Bond } from '../../../mol-model/stru
 import { Theme } from '../../../mol-theme/theme';
 import { Mesh } from '../../../mol-geo/geometry/mesh/mesh';
 import { Vec3 } from '../../../mol-math/linear-algebra';
-import { BitFlags } from '../../../mol-util';
-import { createBondCylinderMesh, BondCylinderParams, BondIterator } from './util/bond';
+import { BitFlags, arrayEqual } from '../../../mol-util';
+import { createBondCylinderMesh, BondCylinderParams, BondIterator, ignoreBondType } from './util/bond';
 import { UnitsMeshParams, UnitsVisual, UnitsMeshVisual, StructureGroup } from '../units-visual';
 import { VisualUpdateState } from '../../util';
 import { PickingId } from '../../../mol-geo/geometry/picking';
 import { EmptyLoci, Loci } from '../../../mol-model/loci';
 import { Interval, OrderedSet } from '../../../mol-data/int';
 import { isHydrogen } from './util/common';
+import { BondType } from '../../../mol-model/structure/model/types';
 
 function createIntraUnitBondCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<IntraUnitBondParams>, mesh?: Mesh) {
     if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh)
@@ -29,7 +30,14 @@ function createIntraUnitBondCylinderMesh(ctx: VisualContext, unit: Unit, structu
     const bonds = unit.bonds
     const { edgeCount, a, b, edgeProps, offset } = bonds
     const { order: _order, flags: _flags } = edgeProps
-    const { sizeFactor, sizeAspectRatio, ignoreHydrogens } = props
+    const { sizeFactor, sizeAspectRatio, ignoreHydrogens, includeTypes, excludeTypes } = props
+
+    const include = BondType.fromNames(includeTypes)
+    const exclude = BondType.fromNames(excludeTypes)
+
+    const ignoreHydrogen = ignoreHydrogens ? (edgeIndex: number) => {
+        return isHydrogen(unit, elements[a[edgeIndex]]) || isHydrogen(unit, elements[b[edgeIndex]])
+    } : () => false
 
     if (!edgeCount) return Mesh.createEmpty(mesh)
 
@@ -68,9 +76,7 @@ function createIntraUnitBondCylinderMesh(ctx: VisualContext, unit: Unit, structu
             const sizeB = theme.size.size(location)
             return Math.min(sizeA, sizeB) * sizeFactor * sizeAspectRatio
         },
-        ignore: ignoreHydrogens ? (edgeIndex: number) => {
-            return isHydrogen(unit, elements[a[edgeIndex]]) || isHydrogen(unit, elements[b[edgeIndex]])
-        } : () => false
+        ignore: (edgeIndex: number) => ignoreHydrogen(edgeIndex) || ignoreBondType(include, exclude, _flags[edgeIndex])
     }
 
     return createBondCylinderMesh(ctx, builderProps, props, mesh)
@@ -100,7 +106,9 @@ export function IntraUnitBondVisual(materialId: number): UnitsVisual<IntraUnitBo
                 newProps.bondScale !== currentProps.bondScale ||
                 newProps.bondSpacing !== currentProps.bondSpacing ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
-                newProps.bondCap !== currentProps.bondCap
+                newProps.bondCap !== currentProps.bondCap ||
+                !arrayEqual(newProps.includeTypes, currentProps.includeTypes) ||
+                !arrayEqual(newProps.excludeTypes, currentProps.excludeTypes)
             )
         }
     }, materialId)

+ 8 - 2
src/mol-repr/structure/visual/util/bond.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -21,10 +21,16 @@ export const BondCylinderParams = {
     bondSpacing: PD.Numeric(1, { min: 0, max: 2, step: 0.01 }),
     bondCap: PD.Boolean(false),
     radialSegments: PD.Numeric(16, { min: 2, max: 56, step: 2 }),
+    includeTypes: PD.MultiSelect(Object.keys(BondType.Names) as BondType.Names[], PD.objectToOptions(BondType.Names)),
+    excludeTypes: PD.MultiSelect([] as BondType.Names[], PD.objectToOptions(BondType.Names)),
 }
 export const DefaultBondCylinderProps = PD.getDefaultValues(BondCylinderParams)
 export type BondCylinderProps = typeof DefaultBondCylinderProps
 
+export function ignoreBondType(include: BondType.Flag, exclude: BondType.Flag, f: BondType.Flag) {
+    return !BondType.is(include, f) || BondType.is(exclude, f)
+}
+
 const tmpShiftV12 = Vec3.zero()
 const tmpShiftV13 = Vec3.zero()
 
@@ -99,7 +105,7 @@ export function createBondCylinderMesh(ctx: VisualContext, bondBuilder: BondCyli
         const f = flags(edgeIndex)
         builderState.currentGroup = edgeIndex
 
-        if (BondType.is(f, BondType.Flag.MetallicCoordination) || BondType.is(f, BondType.Flag.Hydrogen)) {
+        if (BondType.is(f, BondType.Flag.MetallicCoordination) || BondType.is(f, BondType.Flag.HydrogenBond)) {
             // show metall coordinations and hydrogen bonds with dashed cylinders
             cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius / 3
             cylinderProps.topCap = cylinderProps.bottomCap = true

+ 1 - 10
src/mol-script/runtime/query/table.ts

@@ -353,16 +353,7 @@ function atomProp(p: (e: StructureElement.Location) => any): (ctx: QueryContext,
 }
 
 function bondFlag(current: BondType, f: string): BondType {
-    switch (f.toLowerCase()) {
-        case 'covalent': return current | BondType.Flag.Covalent;
-        case 'metallic': return current | BondType.Flag.MetallicCoordination;
-        case 'ionic': return current | BondType.Flag.Ionic;
-        case 'hydrogen': return current | BondType.Flag.Hydrogen;
-        case 'sulfide': return current | BondType.Flag.Sulfide;
-        case 'aromatic': return current | BondType.Flag.Aromatic;
-        case 'computed': return current | BondType.Flag.Computed;
-        default: return current;
-    }
+    return current | (BondType.isName(f) ? BondType.fromName(f) : BondType.Flag.None)
 }
 
 function secondaryStructureFlag(current: SecondaryStructureType, f: string): SecondaryStructureType {