ソースを参照

factor out to extension

Sebastian Bittrich 1 年間 前
コミット
38c550b245

+ 2 - 0
src/apps/viewer/app.ts

@@ -50,6 +50,7 @@ import { SaccharideCompIdMapType } from '../../mol-model/structure/structure/car
 import { Backgrounds } from '../../extensions/backgrounds';
 import { SbNcbrPartialCharges, SbNcbrPartialChargesPreset, SbNcbrPartialChargesPropertyProvider } from '../../extensions/sb-ncbr';
 import { wwPDBStructConnExtensionFunctions } from '../../extensions/wwpdb/struct-conn';
+import { wwPDBChemicalComponentDictionary } from '../../extensions/wwpdb/ccd/behavior';
 
 export { PLUGIN_VERSION as version } from '../../mol-plugin/version';
 export { setDebugMode, setProductionMode, setTimingMode, consoleStats } from '../../mol-util/debug';
@@ -74,6 +75,7 @@ const Extensions = {
     'ma-quality-assessment': PluginSpec.Behavior(MAQualityAssessment),
     'zenodo-import': PluginSpec.Behavior(ZenodoImport),
     'sb-ncbr-partial-charges': PluginSpec.Behavior(SbNcbrPartialCharges),
+    'wwpdb-chemical-component-dictionary': PluginSpec.Behavior(wwPDBChemicalComponentDictionary),
 };
 
 const DefaultViewerOptions = {

+ 47 - 0
src/extensions/wwpdb/ccd/README.md

@@ -0,0 +1,47 @@
+# Chemical Component Dictionary Extension
+
+The [Chemical Component Dictionary (CCD)](https://www.wwpdb.org/data/ccd) describes all small molecules and monomers found in PDB entries. The dictionary provides a plethora of additional information not present in wwPDB archive structures such as chemical descriptors (SMILES & InChI) and stereochemical assignments, information on bond order and more. Most notably, the CCD provides 2 sets of coordinates:
+- `ideal`: idealized/minimized coordinates, obtained using Molecular Networks' Corina, and if there are issues, OpenEye's OMEGA
+- `model`: coordinates extracted from an archive structure
+
+## How to Load a Component from URL
+1. "Download Structure" -- switch "Source" to "URL"
+2. Enter URL of component, e.g. https://files.rcsb.org/ligands/view/HEM.cif, leave "Format" as is
+3. Click "Apply"
+
+This parses the corresponding component into 2 models (1st: `ideal` coordinates, 2nd: `model` coordinates) and applies the default representaiton to the 1st model. `model` coordinates are available as 2nd model. Click the canvas to re-focus if you don't see anything after switching models due to the coordinates being far away.
+
+## How to Visualize Components
+There's a dedicated representation preset that faciliates the comparison of `ideal` and `model` coordinates.
+
+1. Load a component as described above
+2. Switch structure preset to "Chemical Component" (button in the top-right, in the "Structure" panel)
+
+This creates a dedicated component for `ideal` as well as `model` coordinates and represents them as ball-and-stick. Initially, only `ideal` coordinates are shown. After toggling the visibility of `model` coordinates, they appear superimposed with the `ideal` coordinates. 
+
+## Examples & Test Cases
+Ligand | Description | Details
+-- | -- | --
+https://files.rcsb.org/ligands/view/HEM.cif | metal coordination |
+https://files.rcsb.org/ligands/view/FE.cif | +3 oxidation state |
+https://files.rcsb.org/ligands/view/FE2.cif | +2 oxidation state |
+https://files.rcsb.org/ligands/view/RUC.cif | transition metal | 
+https://files.rcsb.org/ligands/view/SF4.cif | Fe-S cluster | doesn't align nicely
+https://files.rcsb.org/ligands/view/TBR.cif | coords identical | 
+https://files.rcsb.org/ligands/view/OER.cif | coords identical | 
+https://files.rcsb.org/ligands/view/FEA.cif | charges |
+https://files.rcsb.org/ligands/view/PR2.cif | orientation differs | 
+https://files.rcsb.org/ligands/view/03R.cif | some atoms missing |
+https://files.rcsb.org/ligands/view/02U.cif | many atoms missing |
+https://files.rcsb.org/ligands/view/HC0.cif | no ideal coords | unrelated: O and H atoms clashing
+https://files.rcsb.org/ligands/view/Q6O.cif | no model coords |
+https://files.rcsb.org/ligands/view/H0C.cif | big ligand |
+https://files.rcsb.org/ligands/view/2NC.cif | dual representation as PRD and CC |
+https://files.rcsb.org/birds/view/PRDCC_000001.cif | PRDCC |
+https://raw.githubusercontent.com/wwPDB/extended-wwPDB-identifier-examples/main/CCD/BB87Q.cif | extended CCD identifier |
+https://raw.githubusercontent.com/wwPDB/extended-wwPDB-identifier-examples/main/CCD/7ZTVU.cif | extended CCD identifier |
+https://raw.githubusercontent.com/wwPDB/extended-wwPDB-identifier-examples/main/CCD/9QRZS.cif | extended CCD identifier |
+https://raw.githubusercontent.com/wwPDB/extended-wwPDB-identifier-examples/main/CCD/9ABCD.cif | extended CCD identifier |
+https://files.rcsb.org/ligands/view/UNK.cif | CCD special: unknown amino acid | unrelated: some model H are placed far away
+https://files.rcsb.org/ligands/view/UNX.cif | CCD special: unknown atom/ion | no ideal coordinates
+https://files.rcsb.org/ligands/view/UNL.cif | CCD special: unknown ligand | no coordinates whatsoever

+ 33 - 0
src/extensions/wwpdb/ccd/behavior.ts

@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Sebastian Bittrich <sebastian.bittrich@rcsb.org>
+ */
+
+import { PluginBehavior } from '../../../mol-plugin/behavior/behavior';
+import { ChemicalComponentPreset, ChemicalCompontentTrajectoryHierarchyPreset } from './representation';
+
+export const wwPDBChemicalComponentDictionary = PluginBehavior.create<{ }>({
+    name: 'wwpdb-chemical-component-dictionary',
+    category: 'representation',
+    display: {
+        name: 'wwPDB Chemical Compontent Dictionary',
+        description: 'Custom representation for data loaded from the CCD.'
+    },
+    ctor: class extends PluginBehavior.Handler<{ }> {
+        register(): void {
+            this.ctx.builders.structure.hierarchy.registerPreset(ChemicalCompontentTrajectoryHierarchyPreset);
+            this.ctx.builders.structure.representation.registerPreset(ChemicalComponentPreset);
+        }
+
+        update() {
+            return false;
+        }
+
+        unregister() {
+            this.ctx.builders.structure.hierarchy.unregisterPreset(ChemicalCompontentTrajectoryHierarchyPreset);
+            this.ctx.builders.structure.representation.unregisterPreset(ChemicalComponentPreset);
+        }
+    },
+    params: () => ({ })
+});

+ 166 - 0
src/extensions/wwpdb/ccd/representation.ts

@@ -0,0 +1,166 @@
+/**
+ * Copyright (c) 2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Sebastian Bittrich <sebastian.bittrich@rcsb.org>
+ */
+
+import { PluginStateObject } from '../../../mol-plugin-state/objects';
+import { ParamDefinition as PD } from '../../../mol-util/param-definition';
+import { StateObjectRef, StateTransform } from '../../../mol-state';
+import { StateTransforms } from '../../../mol-plugin-state/transforms';
+import { StructureRepresentationPresetProvider, presetStaticComponent } from '../../../mol-plugin-state/builder/structure/representation-preset';
+import { PluginContext } from '../../../mol-plugin/context';
+import { Mat4 } from '../../../mol-math/linear-algebra';
+import { Model, Structure } from '../../../mol-model/structure';
+import { CCDFormat } from '../../../mol-model-formats/structure/mmcif';
+import { MinimizeRmsd } from '../../../mol-math/linear-algebra/3d/minimize-rmsd';
+import { SetUtils } from '../../../mol-util/set';
+import { TrajectoryHierarchyPresetProvider } from '../../../mol-plugin-state/builder/structure/hierarchy-preset';
+import { capitalize } from '../../../mol-util/string';
+
+const CCDParams = (a: PluginStateObject.Molecule.Trajectory | undefined, plugin: PluginContext) => ({
+    representationPresetParams: PD.Optional(PD.Group(StructureRepresentationPresetProvider.CommonParams)),
+    showOriginalCoordinates: PD.Optional(PD.Boolean(true, { description: `Show original coordinates for 'model' and 'ideal' structure and do not align them.` })),
+    shownCoordinateType: PD.Select('ideal', PD.arrayToOptions(['ideal', 'model', 'both'] as const), { description: `What coordinate sets are visible.` }),
+    ...TrajectoryHierarchyPresetProvider.CommonParams(a, plugin)
+});
+
+export const ChemicalCompontentTrajectoryHierarchyPreset = TrajectoryHierarchyPresetProvider({
+    id: 'preset-trajectory-ccd',
+    display: {
+        name: 'Chemical Component', group: 'Preset',
+        description: 'Shows molecules from the Chemical Component Dictionary.'
+    },
+    isApplicable: o => {
+        return CCDFormat.is(o.data.representative.sourceData);
+    },
+    params: CCDParams,
+    async apply(trajectory, params, plugin) {
+        const tr = StateObjectRef.resolveAndCheck(plugin.state.data, trajectory)?.obj?.data;
+        if (!tr) return {};
+
+        const builder = plugin.builders.structure;
+
+        const idealModel = await builder.createModel(trajectory, { modelIndex: 0 });
+        const idealModelProperties = await builder.insertModelProperties(idealModel, params.modelProperties, { isCollapsed: true });
+
+        const idealStructure = await builder.createStructure(idealModelProperties || idealModel, { name: 'model', params: {} });
+        const idealStructureProperties = await builder.insertStructureProperties(idealStructure, params.structureProperties);
+
+        const representationPreset = params.representationPreset || ChemicalComponentPreset.id;
+        const representationPresetParams = params.representationPresetParams || {};
+        if (representationPresetParams.ignoreHydrogens === undefined) representationPresetParams.ignoreHydrogens = true;
+
+        // degenerate case where either model or ideal coordinates are missing
+        if (tr.frameCount !== 2) {
+            // variables are 1st model but not necessarily ideal coordinates -- consult trajectory index to distinguish ideal/model coordinates
+            const coordinateType = Model.TrajectoryInfo.get(idealModel.obj!.data).index === 0 ? CCDFormat.CoordinateType.Ideal : CCDFormat.CoordinateType.Model;
+            await builder.representation.applyPreset(idealStructureProperties, representationPreset, { ...representationPresetParams, coordinateType });
+
+            return { models: [idealModel], structures: [idealStructure] };
+        }
+
+        const modelModel = await builder.createModel(trajectory, { modelIndex: 1 });
+        const modelModelProperties = await builder.insertModelProperties(modelModel, params.modelProperties, { isCollapsed: true });
+
+        const modelStructure = await builder.createStructure(modelModelProperties || modelModel, { name: 'model', params: {} });
+        const modelStructureProperties = await builder.insertStructureProperties(modelStructure, params.structureProperties);
+
+        // align ideal and model coordinates
+        if (!params.showOriginalCoordinates) {
+            const [a, b] = getPositionTables(idealStructure.obj!.data, modelStructure.obj!.data);
+            if (!a) {
+                plugin.log.warn(`Cannot align ligands whose atom sets are disjoint.`);
+            } else {
+                const { bTransform, rmsd } = MinimizeRmsd.compute({ a, b });
+                await transform(plugin, modelStructure.cell!, bTransform);
+                plugin.log.info(`Superposed [model] and [ideal] with RMSD ${rmsd.toFixed(2)}.`);
+            }
+        }
+
+        await builder.representation.applyPreset(idealStructureProperties, representationPreset, { ...representationPresetParams, coordinateType: CCDFormat.CoordinateType.Ideal, isHidden: params.shownCoordinateType === 'model' });
+        await builder.representation.applyPreset(modelStructureProperties, representationPreset, { ...representationPresetParams, coordinateType: CCDFormat.CoordinateType.Model, isHidden: params.shownCoordinateType === 'ideal' });
+
+        return { models: [idealModel, modelModel], structures: [idealStructure, modelStructure] };
+    }
+});
+
+function getPositionTables(s1: Structure, s2: Structure) {
+    const m1 = getAtomIdSerialMap(s1);
+    const m2 = getAtomIdSerialMap(s2);
+    const intersecting = SetUtils.intersection(new Set(m1.keys()), new Set(m2.keys()));
+
+    const ret = [
+        MinimizeRmsd.Positions.empty(intersecting.size),
+        MinimizeRmsd.Positions.empty(intersecting.size)
+    ];
+    let o = 0;
+    intersecting.forEach(k => {
+        ret[0].x[o] = s1.model.atomicConformation.x[m1.get(k)!];
+        ret[0].y[o] = s1.model.atomicConformation.y[m1.get(k)!];
+        ret[0].z[o] = s1.model.atomicConformation.z[m1.get(k)!];
+        ret[1].x[o] = s2.model.atomicConformation.x[m2.get(k)!];
+        ret[1].y[o] = s2.model.atomicConformation.y[m2.get(k)!];
+        ret[1].z[o] = s2.model.atomicConformation.z[m2.get(k)!];
+        o++;
+    });
+
+    return ret;
+}
+
+function getAtomIdSerialMap(structure: Structure) {
+    const map = new Map<string, number>();
+    const { label_atom_id } = structure.model.atomicHierarchy.atoms;
+    for (let i = 0, il = label_atom_id.rowCount; i < il; ++i) {
+        const id = label_atom_id.value(i);
+        if (!map.has(id)) map.set(id, map.size);
+    }
+    return map;
+}
+
+function transform(plugin: PluginContext, s: StateObjectRef<PluginStateObject.Molecule.Structure>, matrix: Mat4) {
+    const b = plugin.state.data.build().to(s)
+        .insert(StateTransforms.Model.TransformStructureConformation, { transform: { name: 'matrix', params: { data: matrix, transpose: false } } });
+    return plugin.runTask(plugin.state.data.updateTree(b));
+}
+
+export const ChemicalComponentPreset = StructureRepresentationPresetProvider({
+    id: 'preset-structure-representation-chemical-component',
+    display: {
+        name: 'Chemical Component', group: 'Miscellaneous',
+        description: `Show 'Ideal' and 'Model' coordinates of chemical components.`
+    },
+    isApplicable: o => {
+        return CCDFormat.is(o.data.model.sourceData);
+    },
+    params: () => ({
+        ...StructureRepresentationPresetProvider.CommonParams,
+        coordinateType: PD.Select<CCDFormat.CoordinateType>(CCDFormat.CoordinateType.Ideal, PD.arrayToOptions(Object.keys(CCDFormat.CoordinateType) as CCDFormat.CoordinateType[])),
+        isHidden: PD.Boolean(false)
+    }),
+    async apply(ref, params, plugin) {
+        const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
+        if (!structureCell) return {};
+
+        const { coordinateType, isHidden } = params;
+        const components = {
+            [coordinateType]: await presetStaticComponent(plugin, structureCell, 'all', { label: capitalize(coordinateType), tags: [coordinateType] })
+        };
+
+        const structure = structureCell.obj!.data;
+        const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
+
+        const representations = {
+            [coordinateType]: builder.buildRepresentation(update, components[coordinateType], { type: 'ball-and-stick', typeParams }, { initialState: { isHidden } }),
+        };
+        // sync UI state
+        if (components[coordinateType]?.cell?.state && isHidden) {
+            StateTransform.assignState(components[coordinateType]!.cell!.state, { isHidden });
+        }
+
+        await update.commit({ revertOnError: true });
+        await StructureRepresentationPresetProvider.updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
+
+        return { components, representations };
+    }
+});

+ 2 - 114
src/mol-plugin-state/builder/structure/hierarchy-preset.ts

@@ -13,14 +13,11 @@ import { StateTransforms } from '../../transforms';
 import { RootStructureDefinition } from '../../helpers/root-structure';
 import { PresetStructureRepresentations, StructureRepresentationPresetProvider } from './representation-preset';
 import { PluginContext } from '../../../mol-plugin/context';
-import { Mat4, Vec3 } from '../../../mol-math/linear-algebra';
-import { Model, Structure } from '../../../mol-model/structure';
+import { Vec3 } from '../../../mol-math/linear-algebra';
+import { Model } from '../../../mol-model/structure';
 import { getStructureQuality } from '../../../mol-repr/util';
 import { OperatorNameColorThemeProvider } from '../../../mol-theme/color/operator-name';
 import { PluginConfig } from '../../../mol-plugin/config';
-import { CCDFormat } from '../../../mol-model-formats/structure/mmcif';
-import { MinimizeRmsd } from '../../../mol-math/linear-algebra/3d/minimize-rmsd';
-import { SetUtils } from '../../../mol-util/set';
 
 export interface TrajectoryHierarchyPresetProvider<P = any, S = {}> extends PresetProvider<PluginStateObject.Molecule.Trajectory, P, S> { }
 export function TrajectoryHierarchyPresetProvider<P, S>(preset: TrajectoryHierarchyPresetProvider<P, S>) { return preset; }
@@ -125,114 +122,6 @@ const allModels = TrajectoryHierarchyPresetProvider({
     }
 });
 
-const CCDParams = (a: PluginStateObject.Molecule.Trajectory | undefined, plugin: PluginContext) => ({
-    representationPresetParams: PD.Optional(PD.Group(StructureRepresentationPresetProvider.CommonParams)),
-    showOriginalCoordinates: PD.Optional(PD.Boolean(true, { description: `Show original coordinates for 'model' and 'ideal' structure and do not align them.` })),
-    shownCoordinateType: PD.Select('ideal', PD.arrayToOptions(['ideal', 'model', 'both'] as const), { description: `What coordinate sets are visible.` }),
-    ...CommonParams(a, plugin)
-});
-
-const ccd = TrajectoryHierarchyPresetProvider({
-    id: 'preset-trajectory-ccd',
-    display: {
-        name: 'Chemical Component', group: 'Preset',
-        description: 'Shows molecules from the Chemical Component Dictionary.'
-    },
-    isApplicable: o => {
-        return CCDFormat.is(o.data.representative.sourceData);
-    },
-    params: CCDParams,
-    async apply(trajectory, params, plugin) {
-        const tr = StateObjectRef.resolveAndCheck(plugin.state.data, trajectory)?.obj?.data;
-        if (!tr) return {};
-
-        const builder = plugin.builders.structure;
-
-        const idealModel = await builder.createModel(trajectory, { modelIndex: 0 });
-        const idealModelProperties = await builder.insertModelProperties(idealModel, params.modelProperties, { isCollapsed: true });
-
-        const idealStructure = await builder.createStructure(idealModelProperties || idealModel, { name: 'model', params: {} });
-        const idealStructureProperties = await builder.insertStructureProperties(idealStructure, params.structureProperties);
-
-        const representationPreset = params.representationPreset || PresetStructureRepresentations['chemical-component'].id;
-        const representationPresetParams = params.representationPresetParams || {};
-        if (representationPresetParams.ignoreHydrogens === undefined) representationPresetParams.ignoreHydrogens = true;
-
-        // degenerate case where either model or ideal coordinates are missing
-        if (tr.frameCount !== 2) {
-            // variables are 1st model but not necessarily ideal coordinates -- consult trajectory index to distinguish ideal/model coordinates
-            const coordinateType = Model.TrajectoryInfo.get(idealModel.obj!.data).index === 0 ? CCDFormat.CoordinateType.Ideal : CCDFormat.CoordinateType.Model;
-            await builder.representation.applyPreset(idealStructureProperties, representationPreset, { ...representationPresetParams, coordinateType });
-
-            return { models: [idealModel], structures: [idealStructure] };
-        }
-
-        const modelModel = await builder.createModel(trajectory, { modelIndex: 1 });
-        const modelModelProperties = await builder.insertModelProperties(modelModel, params.modelProperties, { isCollapsed: true });
-
-        const modelStructure = await builder.createStructure(modelModelProperties || modelModel, { name: 'model', params: {} });
-        const modelStructureProperties = await builder.insertStructureProperties(modelStructure, params.structureProperties);
-
-        // align ideal and model coordinates
-        if (!params.showOriginalCoordinates) {
-            const [a, b] = getPositionTables(idealStructure.obj!.data, modelStructure.obj!.data);
-            if (!a) {
-                plugin.log.warn(`Cannot align ligands whose atom sets are disjoint.`);
-            } else {
-                const { bTransform, rmsd } = MinimizeRmsd.compute({ a, b });
-                await transform(plugin, modelStructure.cell!, bTransform);
-                plugin.log.info(`Superposed [model] and [ideal] with RMSD ${rmsd.toFixed(2)}.`);
-            }
-        }
-
-        await builder.representation.applyPreset(idealStructureProperties, representationPreset, { ...representationPresetParams, coordinateType: CCDFormat.CoordinateType.Ideal, isHidden: params.shownCoordinateType === 'model' });
-        await builder.representation.applyPreset(modelStructureProperties, representationPreset, { ...representationPresetParams, coordinateType: CCDFormat.CoordinateType.Model, isHidden: params.shownCoordinateType === 'ideal' });
-
-        return { models: [idealModel, modelModel], structures: [idealStructure, modelStructure] };
-    }
-});
-
-/** tailored to CCD structures and not generally applicable */
-function getPositionTables(s1: Structure, s2: Structure) {
-    const m1 = getAtomIdSerialMap(s1);
-    const m2 = getAtomIdSerialMap(s2);
-    const intersecting = SetUtils.intersection(new Set(m1.keys()), new Set(m2.keys()));
-
-    const ret = [
-        MinimizeRmsd.Positions.empty(intersecting.size),
-        MinimizeRmsd.Positions.empty(intersecting.size)
-    ];
-    let o = 0;
-    intersecting.forEach(k => {
-        ret[0].x[o] = s1.model.atomicConformation.x[m1.get(k)!];
-        ret[0].y[o] = s1.model.atomicConformation.y[m1.get(k)!];
-        ret[0].z[o] = s1.model.atomicConformation.z[m1.get(k)!];
-        ret[1].x[o] = s2.model.atomicConformation.x[m2.get(k)!];
-        ret[1].y[o] = s2.model.atomicConformation.y[m2.get(k)!];
-        ret[1].z[o] = s2.model.atomicConformation.z[m2.get(k)!];
-        o++;
-    });
-
-    return ret;
-}
-
-/** tailored to CCD structures and not generally applicable */
-function getAtomIdSerialMap(structure: Structure) {
-    const map = new Map<string, number>();
-    const { label_atom_id } = structure.model.atomicHierarchy.atoms;
-    for (let i = 0, il = label_atom_id.rowCount; i < il; ++i) {
-        const id = label_atom_id.value(i);
-        if (!map.has(id)) map.set(id, map.size);
-    }
-    return map;
-}
-
-function transform(plugin: PluginContext, s: StateObjectRef<PluginStateObject.Molecule.Structure>, matrix: Mat4) {
-    const b = plugin.state.data.build().to(s)
-        .insert(StateTransforms.Model.TransformStructureConformation, { transform: { name: 'matrix', params: { data: matrix, transpose: false } } });
-    return plugin.runTask(plugin.state.data.updateTree(b));
-}
-
 const CrystalSymmetryParams = (a: PluginStateObject.Molecule.Trajectory | undefined, plugin: PluginContext) => ({
     model: PD.Optional(PD.Group(StateTransformer.getParamDefinition(StateTransforms.Model.ModelFromTrajectory, a, plugin))),
     ...CommonParams(a, plugin)
@@ -339,7 +228,6 @@ const crystalContacts = TrajectoryHierarchyPresetProvider({
 export const PresetTrajectoryHierarchy = {
     'default': defaultPreset,
     'all-models': allModels,
-    ccd,
     unitcell,
     supercell,
     crystalContacts,

+ 2 - 46
src/mol-plugin-state/builder/structure/representation-preset.ts

@@ -12,7 +12,7 @@ import { VisualQuality, VisualQualityOptions } from '../../../mol-geo/geometry/b
 import { ColorTheme } from '../../../mol-theme/color';
 import { Structure } from '../../../mol-model/structure';
 import { PluginContext } from '../../../mol-plugin/context';
-import { StateObjectRef, StateObjectSelector, StateTransform } from '../../../mol-state';
+import { StateObjectRef, StateObjectSelector } from '../../../mol-state';
 import { StaticStructureComponentType } from '../../helpers/structure-component';
 import { StructureSelectionQueries as Q } from '../../helpers/structure-selection-query';
 import { PluginConfig } from '../../../mol-plugin/config';
@@ -24,8 +24,6 @@ import { IndexPairBonds } from '../../../mol-model-formats/structure/property/bo
 import { StructConn } from '../../../mol-model-formats/structure/property/bonds/struct_conn';
 import { StructureRepresentationRegistry } from '../../../mol-repr/structure/registry';
 import { assertUnreachable } from '../../../mol-util/type-helpers';
-import { CCDFormat } from '../../../mol-model-formats/structure/mmcif';
-import { capitalize } from '../../../mol-util/string';
 
 export interface StructureRepresentationPresetProvider<P = any, S extends _Result = _Result> extends PresetProvider<PluginStateObject.Molecule.Structure, P, S> { }
 export function StructureRepresentationPresetProvider<P, S extends _Result>(repr: StructureRepresentationPresetProvider<P, S>) { return repr; }
@@ -431,47 +429,6 @@ const illustrative = StructureRepresentationPresetProvider({
     }
 });
 
-const chemicalComponent = StructureRepresentationPresetProvider({
-    id: 'preset-structure-representation-chemical-component',
-    display: {
-        name: 'Chemical Component', group: 'Miscellaneous',
-        description: `Show 'Ideal' and 'Model' coordinates of chemical components.`
-    },
-    isApplicable: o => {
-        return CCDFormat.is(o.data.model.sourceData);
-    },
-    params: () => ({
-        ...CommonParams,
-        coordinateType: PD.Select<CCDFormat.CoordinateType>(CCDFormat.CoordinateType.Ideal, PD.arrayToOptions(Object.keys(CCDFormat.CoordinateType) as CCDFormat.CoordinateType[])),
-        isHidden: PD.Boolean(false)
-    }),
-    async apply(ref, params, plugin) {
-        const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
-        if (!structureCell) return {};
-
-        const { coordinateType, isHidden } = params;
-        const components = {
-            [coordinateType]: await presetStaticComponent(plugin, structureCell, 'all', { label: capitalize(coordinateType), tags: [coordinateType] })
-        };
-
-        const structure = structureCell.obj!.data;
-        const { update, builder, typeParams } = reprBuilder(plugin, params);
-
-        const representations = {
-            [coordinateType]: builder.buildRepresentation(update, components[coordinateType], { type: 'ball-and-stick', typeParams }, { initialState: { isHidden } }),
-        };
-        // sync UI state
-        if (components[coordinateType]?.cell?.state && isHidden) {
-            StateTransform.assignState(components[coordinateType]!.cell!.state, { isHidden });
-        }
-
-        await update.commit({ revertOnError: true });
-        await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
-
-        return { components, representations };
-    }
-});
-
 export function presetStaticComponent(plugin: PluginContext, structure: StateObjectRef<PluginStateObject.Molecule.Structure>, type: StaticStructureComponentType, params?: { label?: string, tags?: string[] }) {
     return plugin.builders.structure.tryCreateComponentStatic(structure, type, params);
 }
@@ -488,7 +445,6 @@ export const PresetStructureRepresentations = {
     'polymer-and-ligand': polymerAndLigand,
     'protein-and-nucleic': proteinAndNucleic,
     'coarse-surface': coarseSurface,
-    illustrative,
-    'chemical-component': chemicalComponent
+    illustrative
 };
 export type PresetStructureRepresentations = typeof PresetStructureRepresentations;