Browse Source

tweak ignoreHydrogens non-polar handling (#669)

Alexander Rose 2 years ago
parent
commit
b772dea188

+ 1 - 0
CHANGELOG.md

@@ -8,6 +8,7 @@ Note that since we don't clearly distinguish between a public and private interf
 
 - Show histogram in direct volume control point settings
 - Add `solidInterior` parameter to sphere/cylinder impostors
+- [Breaking] Tweak `ignoreHydrogens` non-polar handling (introduced in 3.27.0)
 - Add `meshes` and `volumes-and-segmentations` extensions
 - Fix missing support for info in `ParamDefinition.Converted`
 - Add support for multi-visual volume representations

+ 5 - 4
src/mol-plugin-state/builder/structure/representation-preset.ts

@@ -37,7 +37,7 @@ export namespace StructureRepresentationPresetProvider {
 
     export const CommonParams = {
         ignoreHydrogens: PD.Optional(PD.Boolean(false)),
-        onlyPolarHydrogens: PD.Optional(PD.Boolean(false)),
+        ignoreHydrogensVariant: PD.Optional(PD.Select('all', PD.arrayToOptions(['all', 'non-polar'] as const))),
         ignoreLight: PD.Optional(PD.Boolean(false)),
         quality: PD.Optional(PD.Select<VisualQuality>('auto', VisualQualityOptions)),
         theme: PD.Optional(PD.Group({
@@ -69,15 +69,16 @@ export namespace StructureRepresentationPresetProvider {
     export function reprBuilder(plugin: PluginContext, params: CommonParams, structure?: Structure) {
         const update = plugin.state.data.build();
         const builder = plugin.builders.structure.representation;
+        const h = plugin.managers.structure.component.state.options.hydrogens;
         const typeParams = {
             quality: plugin.managers.structure.component.state.options.visualQuality,
-            ignoreHydrogens: plugin.managers.structure.component.state.options.hydrogens === 'hide-all',
-            onlyPolarHydrogens: plugin.managers.structure.component.state.options.hydrogens === 'only-polar',
+            ignoreHydrogens: h !== 'all',
+            ignoreHydrogensVariant: (h === 'only-polar' ? 'non-polar' : 'all') as 'all' | 'non-polar',
             ignoreLight: plugin.managers.structure.component.state.options.ignoreLight,
         };
         if (params.quality && params.quality !== 'auto') typeParams.quality = params.quality;
         if (params.ignoreHydrogens !== void 0) typeParams.ignoreHydrogens = !!params.ignoreHydrogens;
-        if (params.onlyPolarHydrogens !== void 0) typeParams.onlyPolarHydrogens = !!params.onlyPolarHydrogens;
+        if (params.ignoreHydrogensVariant !== void 0) typeParams.ignoreHydrogensVariant = params.ignoreHydrogensVariant;
         if (params.ignoreLight !== void 0) typeParams.ignoreLight = !!params.ignoreLight;
         const color: ColorTheme.BuiltIn | undefined = params.theme?.globalName ? params.theme?.globalName : void 0;
         const ballAndStickColor: ColorTheme.BuiltInParams<'element-symbol'> = params.theme?.carbonColor !== undefined

+ 12 - 12
src/mol-plugin-state/manager/structure/component.ts

@@ -70,8 +70,8 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
         return this.plugin.dataTransaction(async () => {
             await update.commit();
             await this.plugin.state.updateBehavior(StructureFocusRepresentation, p => {
-                p.ignoreHydrogens = options.hydrogens === 'hide-all';
-                p.onlyPolarHydrogens = options.hydrogens === 'only-polar';
+                p.ignoreHydrogens = options.hydrogens !== 'all';
+                p.ignoreHydrogensVariant = options.hydrogens === 'only-polar' ? 'non-polar' : 'all';
                 p.ignoreLight = options.ignoreLight;
                 p.material = options.materialStyle;
                 p.clip = options.clipObjects;
@@ -82,16 +82,16 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
 
     private updateReprParams(update: StateBuilder.Root, component: StructureComponentRef) {
         const { hydrogens, visualQuality: quality, ignoreLight, materialStyle: material, clipObjects: clip } = this.state.options;
-        const ignoreHydrogens = hydrogens === 'hide-all';
-        const onlyPolarHydrogens = hydrogens === 'only-polar';
+        const ignoreHydrogens = hydrogens !== 'all';
+        const ignoreHydrogensVariant = hydrogens === 'only-polar' ? 'non-polar' : 'all';
         for (const r of component.representations) {
             if (r.cell.transform.transformer !== StructureRepresentation3D) continue;
 
             const params = r.cell.transform.params as StateTransformer.Params<StructureRepresentation3D>;
-            if (!!params.type.params.ignoreHydrogens !== ignoreHydrogens || !!params.type.params.onlyPolarHydrogens !== onlyPolarHydrogens || params.type.params.quality !== quality || params.type.params.ignoreLight !== ignoreLight || !shallowEqual(params.type.params.material, material) || !PD.areEqual(Clip.Params, params.type.params.clip, clip)) {
+            if (!!params.type.params.ignoreHydrogens !== ignoreHydrogens || params.type.params.ignoreHydrogensVariant !== ignoreHydrogensVariant || params.type.params.quality !== quality || params.type.params.ignoreLight !== ignoreLight || !shallowEqual(params.type.params.material, material) || !PD.areEqual(Clip.Params, params.type.params.clip, clip)) {
                 update.to(r.cell).update(old => {
                     old.type.params.ignoreHydrogens = ignoreHydrogens;
-                    old.type.params.onlyPolarHydrogens = onlyPolarHydrogens;
+                    old.type.params.ignoreHydrogensVariant = ignoreHydrogensVariant;
                     old.type.params.quality = quality;
                     old.type.params.ignoreLight = ignoreLight;
                     old.type.params.material = material;
@@ -315,9 +315,9 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
         if (components.length === 0) return;
 
         const { hydrogens, visualQuality: quality, ignoreLight, materialStyle: material, clipObjects: clip } = this.state.options;
-        const ignoreHydrogens = hydrogens === 'hide-all';
-        const onlyPolarHydrogens = hydrogens === 'only-polar';
-        const typeParams = { ignoreHydrogens, onlyPolarHydrogens, quality, ignoreLight, material, clip };
+        const ignoreHydrogens = hydrogens !== 'all';
+        const ignoreHydrogensVariant = hydrogens === 'only-polar' ? 'non-polar' : 'all';
+        const typeParams = { ignoreHydrogens, ignoreHydrogensVariant, quality, ignoreLight, material, clip };
 
         return this.plugin.dataTransaction(async () => {
             for (const component of components) {
@@ -353,9 +353,9 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
             if (xs.length === 0) return;
 
             const { hydrogens, visualQuality: quality, ignoreLight, materialStyle: material, clipObjects: clip } = this.state.options;
-            const ignoreHydrogens = hydrogens === 'hide-all';
-            const onlyPolarHydrogens = hydrogens === 'only-polar';
-            const typeParams = { ignoreHydrogens, onlyPolarHydrogens, quality, ignoreLight, material, clip };
+            const ignoreHydrogens = hydrogens !== 'all';
+            const ignoreHydrogensVariant = hydrogens === 'only-polar' ? 'non-polar' : 'all';
+            const typeParams = { ignoreHydrogens, ignoreHydrogensVariant, quality, ignoreLight, material, clip };
 
             const componentKey = UUID.create22();
             for (const s of xs) {

+ 2 - 2
src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts

@@ -52,7 +52,7 @@ const StructureFocusRepresentationParams = (plugin: PluginContext) => {
         components: PD.MultiSelect(FocusComponents, PD.arrayToOptions(FocusComponents)),
         excludeTargetFromSurroundings: PD.Boolean(false, { label: 'Exclude Target', description: 'Exclude the focus "target" from the surroudings component.' }),
         ignoreHydrogens: PD.Boolean(false),
-        onlyPolarHydrogens: PD.Boolean(false),
+        ignoreHydrogensVariant: PD.Select('all', PD.arrayToOptions(['all', 'non-polar'] as const)),
         ignoreLight: PD.Boolean(false),
         material: Material.getParam(),
         clip: PD.Group(Clip.Params),
@@ -81,7 +81,7 @@ class StructureFocusRepresentationBehavior extends PluginBehavior.WithSubscriber
             ...reprParams,
             type: {
                 name: reprParams.type.name,
-                params: { ...reprParams.type.params, ignoreHydrogens: this.params.ignoreHydrogens, onlyPolarHydrogens: this.params.onlyPolarHydrogens, ignoreLight: this.params.ignoreLight, material: this.params.material, clip: this.params.clip }
+                params: { ...reprParams.type.params, ignoreHydrogens: this.params.ignoreHydrogens, ignoreHydrogensVariant: this.params.ignoreHydrogensVariant, ignoreLight: this.params.ignoreLight, material: this.params.material, clip: this.params.clip }
             }
         };
     }

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

@@ -222,7 +222,7 @@ export function InterUnitBondCylinderImpostorVisual(materialId: number): Complex
                 newProps.linkScale !== currentProps.linkScale ||
                 newProps.linkSpacing !== currentProps.linkSpacing ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
-                newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens ||
+                newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant ||
                 newProps.linkCap !== currentProps.linkCap ||
                 newProps.aromaticScale !== currentProps.aromaticScale ||
                 newProps.aromaticSpacing !== currentProps.aromaticSpacing ||
@@ -265,7 +265,7 @@ export function InterUnitBondCylinderMeshVisual(materialId: number): ComplexVisu
                 newProps.linkScale !== currentProps.linkScale ||
                 newProps.linkSpacing !== currentProps.linkSpacing ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
-                newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens ||
+                newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant ||
                 newProps.linkCap !== currentProps.linkCap ||
                 newProps.aromaticScale !== currentProps.aromaticScale ||
                 newProps.aromaticSpacing !== currentProps.aromaticSpacing ||

+ 1 - 1
src/mol-repr/structure/visual/bond-inter-unit-line.ts

@@ -138,7 +138,7 @@ export function InterUnitBondLineVisual(materialId: number): ComplexVisual<Inter
                 newProps.aromaticDashCount !== currentProps.aromaticDashCount ||
                 newProps.dashCount !== currentProps.dashCount ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
-                newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens ||
+                newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant ||
                 !arrayEqual(newProps.includeTypes, currentProps.includeTypes) ||
                 !arrayEqual(newProps.excludeTypes, currentProps.excludeTypes) ||
                 newProps.multipleBonds !== currentProps.multipleBonds

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

@@ -239,7 +239,7 @@ export function IntraUnitBondCylinderImpostorVisual(materialId: number): UnitsVi
                 newProps.linkScale !== currentProps.linkScale ||
                 newProps.linkSpacing !== currentProps.linkSpacing ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
-                newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens ||
+                newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant ||
                 newProps.linkCap !== currentProps.linkCap ||
                 newProps.aromaticScale !== currentProps.aromaticScale ||
                 newProps.aromaticSpacing !== currentProps.aromaticSpacing ||
@@ -287,7 +287,7 @@ export function IntraUnitBondCylinderMeshVisual(materialId: number): UnitsVisual
                 newProps.linkScale !== currentProps.linkScale ||
                 newProps.linkSpacing !== currentProps.linkSpacing ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
-                newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens ||
+                newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant ||
                 newProps.linkCap !== currentProps.linkCap ||
                 newProps.aromaticScale !== currentProps.aromaticScale ||
                 newProps.aromaticSpacing !== currentProps.aromaticSpacing ||

+ 1 - 1
src/mol-repr/structure/visual/bond-intra-unit-line.ts

@@ -164,7 +164,7 @@ export function IntraUnitBondLineVisual(materialId: number): UnitsVisual<IntraUn
                 newProps.aromaticDashCount !== currentProps.aromaticDashCount ||
                 newProps.dashCount !== currentProps.dashCount ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
-                newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens ||
+                newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant ||
                 !arrayEqual(newProps.includeTypes, currentProps.includeTypes) ||
                 !arrayEqual(newProps.excludeTypes, currentProps.excludeTypes) ||
                 newProps.aromaticBonds !== currentProps.aromaticBonds ||

+ 2 - 2
src/mol-repr/structure/visual/element-cross.ts

@@ -27,7 +27,7 @@ export const ElementCrossParams = {
     ...UnitsLinesParams,
     lineSizeAttenuation: PD.Boolean(false),
     ignoreHydrogens: PD.Boolean(false),
-    onlyPolarHydrogens: PD.Boolean(false),
+    ignoreHydrogensVariant: PD.Select('all', PD.arrayToOptions(['all', 'non-polar'] as const)),
     traceOnly: PD.Boolean(false),
     crosses: PD.Select('lone', PD.arrayToOptions(['lone', 'all'] as const)),
     crossSize: PD.Numeric(0.35, { min: 0, max: 2, step: 0.01 }),
@@ -86,7 +86,7 @@ export function ElementCrossVisual(materialId: number): UnitsVisual<ElementCross
         setUpdateState: (state: VisualUpdateState, newProps: PD.Values<ElementCrossParams>, currentProps: PD.Values<ElementCrossParams>) => {
             state.createGeometry = (
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
-                newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens ||
+                newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant ||
                 newProps.traceOnly !== currentProps.traceOnly ||
                 newProps.crosses !== currentProps.crosses ||
                 newProps.crossSize !== currentProps.crossSize

+ 2 - 2
src/mol-repr/structure/visual/element-point.ts

@@ -23,7 +23,7 @@ export const ElementPointParams = {
     ...UnitsPointsParams,
     pointSizeAttenuation: PD.Boolean(false),
     ignoreHydrogens: PD.Boolean(false),
-    onlyPolarHydrogens: PD.Boolean(false),
+    ignoreHydrogensVariant: PD.Select('all', PD.arrayToOptions(['all', 'non-polar'] as const)),
     traceOnly: PD.Boolean(false),
 };
 export type ElementPointParams = typeof ElementPointParams
@@ -90,7 +90,7 @@ export function ElementPointVisual(materialId: number): UnitsVisual<ElementPoint
         setUpdateState: (state: VisualUpdateState, newProps: PD.Values<ElementPointParams>, currentProps: PD.Values<ElementPointParams>) => {
             state.createGeometry = (
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
-                newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens ||
+                newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant ||
                 newProps.traceOnly !== currentProps.traceOnly
             );
         }

+ 3 - 3
src/mol-repr/structure/visual/element-sphere.ts

@@ -20,7 +20,7 @@ export const ElementSphereParams = {
     sizeFactor: PD.Numeric(1, { min: 0, max: 10, step: 0.1 }),
     detail: PD.Numeric(0, { min: 0, max: 3, step: 1 }, BaseGeometry.CustomQualityParamInfo),
     ignoreHydrogens: PD.Boolean(false),
-    onlyPolarHydrogens: PD.Boolean(false),
+    ignoreHydrogensVariant: PD.Select('all', PD.arrayToOptions(['all', 'non-polar'] as const)),
     traceOnly: PD.Boolean(false),
     tryUseImpostor: PD.Boolean(true),
 };
@@ -42,7 +42,7 @@ export function ElementSphereImpostorVisual(materialId: number): UnitsVisual<Ele
         setUpdateState: (state: VisualUpdateState, newProps: PD.Values<ElementSphereParams>, currentProps: PD.Values<ElementSphereParams>) => {
             state.createGeometry = (
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
-                newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens ||
+                newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant ||
                 newProps.traceOnly !== currentProps.traceOnly
             );
         },
@@ -64,7 +64,7 @@ export function ElementSphereMeshVisual(materialId: number): UnitsVisual<Element
                 newProps.sizeFactor !== currentProps.sizeFactor ||
                 newProps.detail !== currentProps.detail ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
-                newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens ||
+                newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant ||
                 newProps.traceOnly !== currentProps.traceOnly
             );
         },

+ 4 - 4
src/mol-repr/structure/visual/gaussian-density-volume.ts

@@ -43,7 +43,7 @@ export const GaussianDensityVolumeParams = {
     ...ComplexDirectVolumeParams,
     ...GaussianDensityParams,
     ignoreHydrogens: PD.Boolean(false),
-    onlyPolarHydrogens: PD.Boolean(false),
+    ignoreHydrogensVariant: PD.Select('all', PD.arrayToOptions(['all', 'non-polar'] as const)),
     includeParent: PD.Boolean(false, { isHidden: true }),
 };
 export type GaussianDensityVolumeParams = typeof GaussianDensityVolumeParams
@@ -60,7 +60,7 @@ export function GaussianDensityVolumeVisual(materialId: number): ComplexVisual<G
             if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true;
             if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true;
             if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true;
-            if (newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens) state.createGeometry = true;
+            if (newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant) state.createGeometry = true;
             if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true;
             if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true;
         },
@@ -101,7 +101,7 @@ export const UnitsGaussianDensityVolumeParams = {
     ...UnitsDirectVolumeParams,
     ...GaussianDensityParams,
     ignoreHydrogens: PD.Boolean(false),
-    onlyPolarHydrogens: PD.Boolean(false),
+    ignoreHydrogensVariant: PD.Select('all', PD.arrayToOptions(['all', 'non-polar'] as const)),
     includeParent: PD.Boolean(false, { isHidden: true }),
 };
 export type UnitsGaussianDensityVolumeParams = typeof UnitsGaussianDensityVolumeParams
@@ -118,7 +118,7 @@ export function UnitsGaussianDensityVolumeVisual(materialId: number): UnitsVisua
             if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true;
             if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true;
             if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true;
-            if (newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens) state.createGeometry = true;
+            if (newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant) state.createGeometry = true;
             if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true;
             if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true;
         },

+ 5 - 5
src/mol-repr/structure/visual/gaussian-surface-mesh.ts

@@ -34,7 +34,7 @@ const SharedParams = {
     ...GaussianDensityParams,
     ...ColorSmoothingParams,
     ignoreHydrogens: PD.Boolean(false),
-    onlyPolarHydrogens: PD.Boolean(false),
+    ignoreHydrogensVariant: PD.Select('all', PD.arrayToOptions(['all', 'non-polar'] as const)),
     tryUseGpu: PD.Boolean(true),
     includeParent: PD.Boolean(false, { isHidden: true }),
 };
@@ -128,7 +128,7 @@ export function GaussianSurfaceMeshVisual(materialId: number): UnitsVisual<Gauss
             if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true;
             if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true;
             if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true;
-            if (newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens) state.createGeometry = true;
+            if (newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant) state.createGeometry = true;
             if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true;
             if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true;
             if (newProps.smoothColors.name !== currentProps.smoothColors.name) {
@@ -195,7 +195,7 @@ export function StructureGaussianSurfaceMeshVisual(materialId: number): ComplexV
             if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true;
             if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true;
             if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true;
-            if (newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens) state.createGeometry = true;
+            if (newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant) state.createGeometry = true;
             if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true;
             if (newProps.smoothColors.name !== currentProps.smoothColors.name) {
                 state.updateColor = true;
@@ -267,7 +267,7 @@ export function GaussianSurfaceTextureMeshVisual(materialId: number): UnitsVisua
             if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true;
             if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true;
             if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true;
-            if (newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens) state.createGeometry = true;
+            if (newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant) state.createGeometry = true;
             if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true;
             if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true;
             if (newProps.smoothColors.name !== currentProps.smoothColors.name) {
@@ -343,7 +343,7 @@ export function StructureGaussianSurfaceTextureMeshVisual(materialId: number): C
             if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true;
             if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true;
             if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true;
-            if (newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens) state.createGeometry = true;
+            if (newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant) state.createGeometry = true;
             if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true;
             if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true;
             if (newProps.smoothColors.name !== currentProps.smoothColors.name) {

+ 2 - 2
src/mol-repr/structure/visual/gaussian-surface-wireframe.ts

@@ -41,7 +41,7 @@ export const GaussianWireframeParams = {
     sizeFactor: PD.Numeric(3, { min: 0, max: 10, step: 0.1 }),
     lineSizeAttenuation: PD.Boolean(false),
     ignoreHydrogens: PD.Boolean(false),
-    onlyPolarHydrogens: PD.Boolean(false),
+    ignoreHydrogensVariant: PD.Select('all', PD.arrayToOptions(['all', 'non-polar'] as const)),
     includeParent: PD.Boolean(false, { isHidden: true }),
 };
 export type GaussianWireframeParams = typeof GaussianWireframeParams
@@ -58,7 +58,7 @@ export function GaussianWireframeVisual(materialId: number): UnitsVisual<Gaussia
             if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true;
             if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true;
             if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true;
-            if (newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens) state.createGeometry = true;
+            if (newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant) state.createGeometry = true;
             if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true;
             if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true;
         }

+ 2 - 2
src/mol-repr/structure/visual/molecular-surface-mesh.ts

@@ -83,7 +83,7 @@ export function MolecularSurfaceMeshVisual(materialId: number): UnitsVisual<Mole
             if (newProps.probeRadius !== currentProps.probeRadius) state.createGeometry = true;
             if (newProps.probePositions !== currentProps.probePositions) state.createGeometry = true;
             if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true;
-            if (newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens) state.createGeometry = true;
+            if (newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant) state.createGeometry = true;
             if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true;
             if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true;
 
@@ -152,7 +152,7 @@ export function StructureMolecularSurfaceMeshVisual(materialId: number): Complex
             if (newProps.probeRadius !== currentProps.probeRadius) state.createGeometry = true;
             if (newProps.probePositions !== currentProps.probePositions) state.createGeometry = true;
             if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true;
-            if (newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens) state.createGeometry = true;
+            if (newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant) state.createGeometry = true;
             if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true;
             if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true;
 

+ 1 - 1
src/mol-repr/structure/visual/molecular-surface-wireframe.ts

@@ -57,7 +57,7 @@ export function MolecularSurfaceWireframeVisual(materialId: number): UnitsVisual
             if (newProps.probeRadius !== currentProps.probeRadius) state.createGeometry = true;
             if (newProps.probePositions !== currentProps.probePositions) state.createGeometry = true;
             if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true;
-            if (newProps.onlyPolarHydrogens !== currentProps.onlyPolarHydrogens) state.createGeometry = true;
+            if (newProps.ignoreHydrogensVariant !== currentProps.ignoreHydrogensVariant) state.createGeometry = true;
             if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true;
         }
     }, materialId);

+ 10 - 30
src/mol-repr/structure/visual/util/bond.ts

@@ -14,14 +14,13 @@ import { ObjectKeys } from '../../../../mol-util/type-helpers';
 import { PickingId } from '../../../../mol-geo/geometry/picking';
 import { EmptyLoci, Loci } from '../../../../mol-model/loci';
 import { Interval, OrderedSet, SortedArray } from '../../../../mol-data/int';
-import { isH, isHydrogen, StructureGroup } from './common';
-import { hasPolarNeighbour } from '../../../../mol-model-props/computed/chemistry/functional-group';
+import { isHydrogen, StructureGroup } from './common';
 
 export const BondParams = {
     includeTypes: PD.MultiSelect(ObjectKeys(BondType.Names), PD.objectToOptions(BondType.Names)),
     excludeTypes: PD.MultiSelect([] as BondType.Names[], PD.objectToOptions(BondType.Names)),
     ignoreHydrogens: PD.Boolean(false),
-    onlyPolarHydrogens: PD.Boolean(false),
+    ignoreHydrogensVariant: PD.Select('all', PD.arrayToOptions(['all', 'non-polar'] as const)),
     aromaticBonds: PD.Boolean(true, { description: 'Display aromatic bonds with dashes' }),
     multipleBonds: PD.Select('symmetric', PD.arrayToOptions(['off', 'symmetric', 'offset'] as const)),
 };
@@ -49,12 +48,11 @@ export function ignoreBondType(include: BondType.Flag, exclude: BondType.Flag, f
 
 export function makeIntraBondIgnoreTest(structure: Structure, unit: Unit.Atomic, props: BondProps): undefined | ((edgeIndex: number) => boolean) {
     const elements = unit.elements;
-    const { atomicNumber } = unit.model.atomicHierarchy.derived.atom;
     const bonds = unit.bonds;
     const { a, b, edgeProps } = bonds;
     const { flags: _flags } = edgeProps;
 
-    const { ignoreHydrogens, onlyPolarHydrogens, includeTypes, excludeTypes } = props;
+    const { ignoreHydrogens, ignoreHydrogensVariant, includeTypes, excludeTypes } = props;
 
     const include = BondType.fromNames(includeTypes);
     const exclude = BondType.fromNames(excludeTypes);
@@ -64,7 +62,7 @@ export function makeIntraBondIgnoreTest(structure: Structure, unit: Unit.Atomic,
     const childUnit = child?.unitMap.get(unit.id);
     if (child && !childUnit) throw new Error('expected childUnit to exist if child exists');
 
-    if (allBondTypes && !onlyPolarHydrogens && !ignoreHydrogens && !child) return;
+    if (allBondTypes && !ignoreHydrogens && !child) return;
 
     return (edgeIndex: number) => {
         const aI = a[edgeIndex];
@@ -78,15 +76,9 @@ export function makeIntraBondIgnoreTest(structure: Structure, unit: Unit.Atomic,
             return true;
         }
 
-        if (!ignoreHydrogens && !onlyPolarHydrogens) return false;
-        if (isH(atomicNumber, elements[aI])) {
-            if (ignoreHydrogens) return true;
-            if (onlyPolarHydrogens && !hasPolarNeighbour(structure, unit, aI)) return true;
-        }
-        if (isH(atomicNumber, elements[bI])) {
-            if (ignoreHydrogens) return true;
-            if (onlyPolarHydrogens && !hasPolarNeighbour(structure, unit, bI)) return true;
-        }
+        if (!ignoreHydrogens) return false;
+
+        if (isHydrogen(structure, unit, elements[aI], ignoreHydrogensVariant) || isHydrogen(structure, unit, elements[bI], ignoreHydrogensVariant)) return true;
 
         return false;
     };
@@ -96,7 +88,7 @@ export function makeInterBondIgnoreTest(structure: Structure, props: BondProps):
     const bonds = structure.interUnitBonds;
     const { edges } = bonds;
 
-    const { ignoreHydrogens, onlyPolarHydrogens, includeTypes, excludeTypes } = props;
+    const { ignoreHydrogens, ignoreHydrogensVariant, includeTypes, excludeTypes } = props;
 
     const include = BondType.fromNames(includeTypes);
     const exclude = BondType.fromNames(excludeTypes);
@@ -104,7 +96,7 @@ export function makeInterBondIgnoreTest(structure: Structure, props: BondProps):
 
     const { child } = structure;
 
-    if (allBondTypes && !onlyPolarHydrogens && !ignoreHydrogens && !child) return;
+    if (allBondTypes && !ignoreHydrogens && !child) return;
 
     return (edgeIndex: number) => {
         if (child) {
@@ -121,19 +113,7 @@ export function makeInterBondIgnoreTest(structure: Structure, props: BondProps):
             const b = edges[edgeIndex];
             const uA = structure.unitMap.get(b.unitA);
             const uB = structure.unitMap.get(b.unitB);
-            if (isHydrogen(uA, uA.elements[b.indexA]) || isHydrogen(uB, uB.elements[b.indexB])) return true;
-        }
-
-        if (onlyPolarHydrogens) {
-            const b = edges[edgeIndex];
-            const uA = structure.unitMap.get(b.unitA);
-            if (isHydrogen(uA, uA.elements[b.indexA]) && !hasPolarNeighbour(structure, uA as Unit.Atomic, b.indexA)) {
-                return true;
-            }
-            const uB = structure.unitMap.get(b.unitB);
-            if (isHydrogen(uB, uB.elements[b.indexB]) && !hasPolarNeighbour(structure, uB as Unit.Atomic, b.indexB)) {
-                return true;
-            }
+            if (isHydrogen(structure, uA, uA.elements[b.indexA], ignoreHydrogensVariant) || isHydrogen(structure, uB, uB.elements[b.indexB], ignoreHydrogensVariant)) return true;
         }
 
         if (!allBondTypes) {

+ 12 - 11
src/mol-repr/structure/visual/util/common.ts

@@ -141,7 +141,7 @@ export function getConformation(unit: Unit) {
 
 export const CommonSurfaceParams = {
     ignoreHydrogens: PD.Boolean(false, { description: 'Whether or not to include hydrogen atoms in the surface calculation.' }),
-    onlyPolarHydrogens: PD.Boolean(false, { description: 'Whether or not to include polar hydrogen atoms in the surface calculation.' }),
+    ignoreHydrogensVariant: PD.Select('all', PD.arrayToOptions(['all', 'non-polar'] as const)),
     traceOnly: PD.Boolean(false, { description: 'Whether or not to only use trace atoms in the surface calculation.' }),
     includeParent: PD.Boolean(false, { description: 'Include elements of the parent structure in surface calculation to get a surface patch of the current structure.' }),
 };
@@ -169,7 +169,7 @@ function filterUnitId(id: AssignableArrayLike<number>, elements: SortedArray, in
 }
 
 export function getUnitConformationAndRadius(structure: Structure, unit: Unit, sizeTheme: SizeTheme<any>, props: CommonSurfaceProps) {
-    const { ignoreHydrogens, onlyPolarHydrogens, traceOnly, includeParent } = props;
+    const { ignoreHydrogens, ignoreHydrogensVariant, traceOnly, includeParent } = props;
     const rootUnit = includeParent ? structure.root.unitMap.get(unit.id) : unit;
     const differentRoot = includeParent && rootUnit !== unit;
 
@@ -182,13 +182,12 @@ export function getUnitConformationAndRadius(structure: Structure, unit: Unit, s
     let indices: SortedArray<ElementIndex>;
     let id: AssignableArrayLike<number>;
 
-    if (ignoreHydrogens || onlyPolarHydrogens || traceOnly || differentRoot) {
+    if (ignoreHydrogens || traceOnly || differentRoot) {
         const _indices: number[] = [];
         const _id: number[] = [];
         for (let i = 0, il = elements.length; i < il; ++i) {
             const eI = elements[i];
-            if (ignoreHydrogens && isHydrogen(rootUnit, eI)) continue;
-            if (onlyPolarHydrogens && isHydrogen(rootUnit, eI) && Unit.isAtomic(rootUnit) && !hasPolarNeighbour(structure, rootUnit, SortedArray.indexOf(rootUnit.elements, eI) as StructureElement.UnitIndex)) continue;
+            if (ignoreHydrogens && isHydrogen(structure, rootUnit, eI, ignoreHydrogensVariant)) continue;
             if (traceOnly && !isTrace(rootUnit, eI)) continue;
             if (differentRoot && squaredDistance(x[eI], y[eI], z[eI], center) > radiusSq) continue;
 
@@ -219,7 +218,7 @@ export function getUnitConformationAndRadius(structure: Structure, unit: Unit, s
 }
 
 export function getStructureConformationAndRadius(structure: Structure, sizeTheme: SizeTheme<any>, props: CommonSurfaceProps) {
-    const { ignoreHydrogens, onlyPolarHydrogens, traceOnly, includeParent } = props;
+    const { ignoreHydrogens, ignoreHydrogensVariant, traceOnly, includeParent } = props;
     const differentRoot = includeParent && !!structure.parent;
     const l = StructureElement.Location.create(structure.root);
 
@@ -234,7 +233,7 @@ export function getStructureConformationAndRadius(structure: Structure, sizeThem
     let id: AssignableArrayLike<number>;
     let indices: OrderedSet<number>;
 
-    if (ignoreHydrogens || onlyPolarHydrogens || traceOnly || differentRoot) {
+    if (ignoreHydrogens || traceOnly || differentRoot) {
         const { getSerialIndex } = structure.serialMapping;
         const units = differentRoot ? structure.root.units : structure.units;
 
@@ -252,8 +251,7 @@ export function getStructureConformationAndRadius(structure: Structure, sizeThem
             l.unit = unit;
             for (let j = 0, jl = elements.length; j < jl; ++j) {
                 const eI = elements[j];
-                if (ignoreHydrogens && isHydrogen(unit, eI)) continue;
-                if (onlyPolarHydrogens && isHydrogen(unit, eI) && Unit.isAtomic(unit) && !hasPolarNeighbour(structure, unit, SortedArray.indexOf(unit.elements, eI) as StructureElement.UnitIndex)) continue;
+                if (ignoreHydrogens && isHydrogen(structure, unit, eI, ignoreHydrogensVariant)) continue;
                 if (traceOnly && !isTrace(unit, eI)) continue;
 
                 const _x = x(eI), _y = y(eI), _z = z(eI);
@@ -316,9 +314,12 @@ export function getStructureConformationAndRadius(structure: Structure, sizeThem
 }
 
 const _H = AtomicNumbers['H'];
-export function isHydrogen(unit: Unit, element: ElementIndex) {
+export function isHydrogen(structure: Structure, unit: Unit, element: ElementIndex, variant: 'all' | 'non-polar') {
     if (Unit.isCoarse(unit)) return false;
-    return unit.model.atomicHierarchy.derived.atom.atomicNumber[element] === _H;
+    return (
+        unit.model.atomicHierarchy.derived.atom.atomicNumber[element] === _H &&
+        (variant === 'all' || !hasPolarNeighbour(structure, unit, SortedArray.indexOf(unit.elements, element) as StructureElement.UnitIndex))
+    );
 }
 export function isH(atomicNumber: ArrayLike<number>, element: ElementIndex) {
     return atomicNumber[element] === _H;

+ 9 - 23
src/mol-repr/structure/visual/util/element.ts

@@ -19,16 +19,15 @@ import { VisualContext } from '../../../../mol-repr/visual';
 import { Theme } from '../../../../mol-theme/theme';
 import { Spheres } from '../../../../mol-geo/geometry/spheres/spheres';
 import { SpheresBuilder } from '../../../../mol-geo/geometry/spheres/spheres-builder';
-import { isTrace, isH, StructureGroup } from './common';
+import { isTrace, StructureGroup, isHydrogen } from './common';
 import { Sphere3D } from '../../../../mol-math/geometry';
-import { hasPolarNeighbour } from '../../../../mol-model-props/computed/chemistry/functional-group';
 
 // avoiding namespace lookup improved performance in Chrome (Aug 2020)
 const v3add = Vec3.add;
 
 type ElementProps = {
     ignoreHydrogens: boolean,
-    onlyPolarHydrogens: boolean,
+    ignoreHydrogensVariant: 'all' | 'non-polar',
     traceOnly: boolean,
 }
 
@@ -38,35 +37,22 @@ export type ElementSphereMeshProps = {
 } & ElementProps
 
 export function makeElementIgnoreTest(structure: Structure, unit: Unit, props: ElementProps): undefined | ((i: ElementIndex) => boolean) {
-    const { ignoreHydrogens, onlyPolarHydrogens, traceOnly } = props;
+    const { ignoreHydrogens, ignoreHydrogensVariant, traceOnly } = props;
 
-    const { atomicNumber } = unit.model.atomicHierarchy.derived.atom;
     const isCoarse = Unit.isCoarse(unit);
 
     const { child } = structure;
     const childUnit = child?.unitMap.get(unit.id);
     if (child && !childUnit) throw new Error('expected childUnit to exist if child exists');
 
-    if (!child && !ignoreHydrogens && !traceOnly && !onlyPolarHydrogens) return;
+    if (!child && !ignoreHydrogens && !traceOnly) return;
 
     return (element: ElementIndex) => {
-        if (!!childUnit && !SortedArray.has(childUnit.elements, element)) {
-            return true;
-        }
-
-        if (traceOnly && !isTrace(unit, element)) {
-            return true;
-        }
-
-        if (isCoarse) return false;
-
-        if (!isH(atomicNumber, element)) return false;
-        if (ignoreHydrogens) return true;
-        if (onlyPolarHydrogens) {
-            return !hasPolarNeighbour(structure, unit, SortedArray.indexOf(unit.elements, element) as StructureElement.UnitIndex);
-        }
-
-        return false;
+        return (
+            (!!childUnit && !SortedArray.has(childUnit.elements, element)) ||
+            (!isCoarse && ignoreHydrogens && isHydrogen(structure, unit, element, ignoreHydrogensVariant)) ||
+            (traceOnly && !isTrace(unit, element))
+        );
     };
 }