diff --git a/src/mol-model-formats/structure/mmcif/bonds/struct_conn.ts b/src/mol-model-formats/structure/mmcif/bonds/struct_conn.ts index 9850bc6a63c838fdaca3c6860cc5be1180445895..b29c31dcee71bd7d5d0c0bc2d40896a0929fed7e 100644 --- a/src/mol-model-formats/structure/mmcif/bonds/struct_conn.ts +++ b/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; } diff --git a/src/mol-model/structure/model/types.ts b/src/mol-model/structure/model/types.ts index 88f5513e7e7c3419b796a28152cd70325d0f68bb..d591872740d6488e32cec8555d4be01390b25a69 100644 --- a/src/mol-model/structure/model/types.ts +++ b/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 + } } /** diff --git a/src/mol-plugin/util/structure-selection-helper.ts b/src/mol-plugin/util/structure-selection-helper.ts index 64929a2e2e06b67f10de3cf53313de00b88c137d..a24f0339999e1410898ae9297a4d3b2fffb100fd 100644 --- a/src/mol-plugin/util/structure-selection-helper.ts +++ b/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]) ]) }) ]) diff --git a/src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts b/src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts index 013ff64aaec7a5bc8a54c2d8559609875f65f57b..e2813e6d596b36c4240194d6890e9c21e6047bf3 100644 --- a/src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts +++ b/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) diff --git a/src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts b/src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts index a07c04b85e5e74b0b950ff8ec654072666783549..d3844f4b9c382258b60c7959e3fa638985f9eac3 100644 --- a/src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts +++ b/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) diff --git a/src/mol-repr/structure/visual/util/bond.ts b/src/mol-repr/structure/visual/util/bond.ts index 5088ba9704cbc3cec992cecc82ba65fa91ee1f51..fdc46e8c8421fc0b554c06b1ce489272cf59d0aa 100644 --- a/src/mol-repr/structure/visual/util/bond.ts +++ b/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 diff --git a/src/mol-script/runtime/query/table.ts b/src/mol-script/runtime/query/table.ts index afa124280517a5a2b16b65ea81e7520011430ae0..4eaa59ebc581db64515bc73737c5a6d93b5f9111 100644 --- a/src/mol-script/runtime/query/table.ts +++ b/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 {