From f6462a3e7e8e2993d974f5b84dd7f48c7a21be13 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Wed, 29 May 2019 15:00:42 +0200 Subject: [PATCH] superposition examples --- src/apps/basic-wrapper/helpers.ts | 29 +++++++++- src/apps/basic-wrapper/index.html | 3 +- src/apps/basic-wrapper/index.ts | 9 ++- src/apps/basic-wrapper/superposition.ts | 55 ++++++++++++++++++- src/mol-math/linear-algebra/3d.ts | 3 +- .../linear-algebra/3d/minimize-rmsd.ts | 3 +- .../structure/structure/util/superposition.ts | 2 +- src/mol-state/state/selection.ts | 2 +- 8 files changed, 95 insertions(+), 11 deletions(-) diff --git a/src/apps/basic-wrapper/helpers.ts b/src/apps/basic-wrapper/helpers.ts index bbe9e92ab..342325ee8 100644 --- a/src/apps/basic-wrapper/helpers.ts +++ b/src/apps/basic-wrapper/helpers.ts @@ -11,6 +11,8 @@ import { StateTransforms } from 'mol-plugin/state/transforms'; import { StructureRepresentation3DHelpers } from 'mol-plugin/state/transforms/representation'; import { MolScriptBuilder as MS } from 'mol-script/language/builder'; import { StateBuilder } from 'mol-state'; +import Expression from 'mol-script/language/expression'; +import { BuiltInColorThemeName } from 'mol-theme/color'; type SupportedFormats = 'cif' | 'pdb' export namespace StateHelper { @@ -27,7 +29,7 @@ export namespace StateHelper { } export function structure(b: StateBuilder.To<PSO.Molecule.Model>) { - return b.apply(StateTransforms.Model.StructureFromModel, { tags: 'struct' }) + return b.apply(StateTransforms.Model.StructureFromModel, { tags: 'structure' }) }; export function selectChain(b: StateBuilder.To<PSO.Molecule.Structure>, auth_asym_id: string) { @@ -37,6 +39,23 @@ export namespace StateHelper { return b.apply(StateTransforms.Model.StructureSelection, { query, label: `Chain ${auth_asym_id}` }); } + export function select(b: StateBuilder.To<PSO.Molecule.Structure>, query: Expression) { + return b.apply(StateTransforms.Model.StructureSelection, { query }); + } + + export function selectSurroundingsOfFirstResidue(b: StateBuilder.To<PSO.Molecule.Structure>, comp_id: string, radius: number) { + const query = MS.struct.modifier.includeSurroundings({ + 0: MS.struct.filter.first([ + MS.struct.generator.atomGroups({ + 'residue-test': MS.core.rel.eq([MS.struct.atomProperty.macromolecular.label_comp_id(), comp_id]), + 'group-by': MS.struct.atomProperty.macromolecular.residueKey() + }) + ]), + radius + }) + return b.apply(StateTransforms.Model.StructureSelection, { query, label: `Surr. ${comp_id} (${radius} ang)` }); + } + export function identityTransform(b: StateBuilder.To<PSO.Molecule.Structure>, m: Mat4) { return b.apply(StateTransforms.Model.TransformStructureConformation, { axis: Vec3.create(1, 0, 0), angle: 0, translation: Vec3.zero() }, @@ -64,4 +83,12 @@ export namespace StateHelper { return visualRoot; } + export function ballsAndSticks(ctx: PluginContext, visualRoot: StateBuilder.To<PSO.Molecule.Structure>, query: Expression, coloring?: BuiltInColorThemeName) { + visualRoot + .apply(StateTransforms.Model.StructureSelection, { query }) + .apply(StateTransforms.Representation.StructureRepresentation3D, + StructureRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'ball-and-stick', void 0, coloring), { tags: 'het-visual' }); + return visualRoot; + } + } \ No newline at end of file diff --git a/src/apps/basic-wrapper/index.html b/src/apps/basic-wrapper/index.html index 1d68db266..6c9f2d9d5 100644 --- a/src/apps/basic-wrapper/index.html +++ b/src/apps/basic-wrapper/index.html @@ -107,7 +107,8 @@ addHeader('Tests'); - addControl('Static Super', () => BasicMolStarWrapper.tests.staticSuperposition()); + addControl('Static Superposition', () => BasicMolStarWrapper.tests.staticSuperposition()); + addControl('Dynamic Superposition', () => BasicMolStarWrapper.tests.dynamicSuperposition()); //////////////////////////////////////////////////////// diff --git a/src/apps/basic-wrapper/index.ts b/src/apps/basic-wrapper/index.ts index fb4392f3d..3520372ac 100644 --- a/src/apps/basic-wrapper/index.ts +++ b/src/apps/basic-wrapper/index.ts @@ -13,10 +13,10 @@ import { StructureRepresentation3DHelpers } from 'mol-plugin/state/transforms/re import { Color } from 'mol-util/color'; import { PluginStateObject as PSO } from 'mol-plugin/state/objects'; import { AnimateModelIndex } from 'mol-plugin/state/animation/built-in'; -import { StateBuilder } from 'mol-state'; +import { StateBuilder, StateTransform } from 'mol-state'; import { StripedResidues } from './coloring'; // import { BasicWrapperControls } from './controls'; -import { StaticSuperpositionTestData, buildStaticSuperposition } from './superposition'; +import { StaticSuperpositionTestData, buildStaticSuperposition, dynamicSuperpositionTest } from './superposition'; require('mol-plugin/skin/light.scss') type SupportedFormats = 'cif' | 'pdb' @@ -146,7 +146,12 @@ class BasicWrapper { staticSuperposition: async () => { const state = this.plugin.state.dataState; const tree = buildStaticSuperposition(this.plugin, StaticSuperpositionTestData); + await PluginCommands.State.RemoveObject.dispatch(this.plugin, { state, ref: StateTransform.RootRef }); await PluginCommands.State.Update.dispatch(this.plugin, { state, tree }); + }, + dynamicSuperposition: async () => { + await PluginCommands.State.RemoveObject.dispatch(this.plugin, { state: this.plugin.state.dataState, ref: StateTransform.RootRef }); + await dynamicSuperpositionTest(this.plugin, ['1tqn', '2hhb', '4hhb'], 'HEM'); } } } diff --git a/src/apps/basic-wrapper/superposition.ts b/src/apps/basic-wrapper/superposition.ts index 1961aab48..c2b190603 100644 --- a/src/apps/basic-wrapper/superposition.ts +++ b/src/apps/basic-wrapper/superposition.ts @@ -9,6 +9,14 @@ import { PluginContext } from 'mol-plugin/context'; import { Mat4 } from 'mol-math/linear-algebra'; import { StateHelper } from './helpers'; +import { PluginCommands } from 'mol-plugin/command'; +import { StateSelection, StateBuilder } from 'mol-state'; +import { PluginStateObject as PSO } from 'mol-plugin/state/objects'; +import { MolScriptBuilder as MS } from 'mol-script/language/builder'; +import { compile } from 'mol-script/runtime/query/compiler'; +import { StructureSelection, QueryContext } from 'mol-model/structure'; +import { superposeStructures } from 'mol-model/structure/structure/util/superposition'; +import Expression from 'mol-script/language/expression'; export type SuperpositionTestInput = { pdbId: string, @@ -52,4 +60,49 @@ export const StaticSuperpositionTestData: SuperpositionTestInput = [ [-0.312, 0.949, 0.057, -12.255], [-0.949, -0.307, -0.074, 53.562], [0, 0, 0, 1]] )} -]; \ No newline at end of file +]; + +export async function dynamicSuperpositionTest(ctx: PluginContext, src: string[], comp_id: string) { + const state = ctx.state.dataState; + + const structures = state.build().toRoot(); + for (const s of src) { + StateHelper.structure( + StateHelper.getModel(StateHelper.download(structures, `https://www.ebi.ac.uk/pdbe/static/entry/${s}_updated.cif`), 'cif')); + } + + await PluginCommands.State.Update.dispatch(ctx, { state, tree: structures }); + + const pivot = MS.struct.filter.first([ + MS.struct.generator.atomGroups({ + 'residue-test': MS.core.rel.eq([MS.struct.atomProperty.macromolecular.label_comp_id(), comp_id]), + 'group-by': MS.struct.atomProperty.macromolecular.residueKey() + }) + ]); + const rest = MS.struct.modifier.exceptBy({ + 0: MS.struct.generator.all(), + by: pivot + }); + + const query = compile<StructureSelection>(pivot); + const xs = state.select(StateSelection.Generators.rootsOfType(PSO.Molecule.Structure)); + const selections = xs.map(s => StructureSelection.toLoci(query(new QueryContext(s.obj!.data)))); + + const transforms = superposeStructures(selections); + const visuals = state.build(); + + siteVisual(ctx, StateHelper.selectSurroundingsOfFirstResidue(visuals.to(xs[0].transform.ref), 'HEM', 7), pivot, rest); + for (let i = 1; i < selections.length; i++) { + const root = visuals.to(xs[i].transform.ref); + siteVisual(ctx, + StateHelper.transform(StateHelper.selectSurroundingsOfFirstResidue(root, 'HEM', 7), transforms[i - 1].bTransform), + pivot, rest); + } + + await PluginCommands.State.Update.dispatch(ctx, { state, tree: visuals }); +} + +function siteVisual(ctx: PluginContext, b: StateBuilder.To<PSO.Molecule.Structure>, pivot: Expression, rest: Expression) { + StateHelper.ballsAndSticks(ctx, b, pivot, 'residue-name'); + StateHelper.ballsAndSticks(ctx, b, rest, 'uniform'); +} \ No newline at end of file diff --git a/src/mol-math/linear-algebra/3d.ts b/src/mol-math/linear-algebra/3d.ts index 88ba25f81..3a98d5ba7 100644 --- a/src/mol-math/linear-algebra/3d.ts +++ b/src/mol-math/linear-algebra/3d.ts @@ -23,7 +23,6 @@ import Vec2 from './3d/vec2' import Vec3 from './3d/vec3' import Vec4 from './3d/vec4' import Quat from './3d/quat' -import MinimizeRmsd from './3d/minimize-rmsd' import { EPSILON } from './3d/common' -export { Mat4, Mat3, Vec2, Vec3, Vec4, Quat, EPSILON, MinimizeRmsd } \ No newline at end of file +export { Mat4, Mat3, Vec2, Vec3, Vec4, Quat, EPSILON } \ No newline at end of file diff --git a/src/mol-math/linear-algebra/3d/minimize-rmsd.ts b/src/mol-math/linear-algebra/3d/minimize-rmsd.ts index 1296e10f3..b757b2e7a 100644 --- a/src/mol-math/linear-algebra/3d/minimize-rmsd.ts +++ b/src/mol-math/linear-algebra/3d/minimize-rmsd.ts @@ -10,8 +10,7 @@ import { EVD } from '../matrix/evd'; import { CentroidHelper } from 'mol-math/geometry/centroid-helper'; import Matrix from '../matrix/matrix'; -export default MinimizeRmsd; - +export { MinimizeRmsd }; namespace MinimizeRmsd { export interface Result { bTransform: Mat4, diff --git a/src/mol-model/structure/structure/util/superposition.ts b/src/mol-model/structure/structure/util/superposition.ts index 8c41ba996..bcd726258 100644 --- a/src/mol-model/structure/structure/util/superposition.ts +++ b/src/mol-model/structure/structure/util/superposition.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { MinimizeRmsd } from 'mol-math/linear-algebra'; +import { MinimizeRmsd } from 'mol-math/linear-algebra/3d/minimize-rmsd'; import StructureElement from '../element'; import { OrderedSet } from 'mol-data/int'; diff --git a/src/mol-state/state/selection.ts b/src/mol-state/state/selection.ts index 2a47745f5..097d73b70 100644 --- a/src/mol-state/state/selection.ts +++ b/src/mol-state/state/selection.ts @@ -49,7 +49,7 @@ namespace StateSelection { parent(): Builder<C>; first(): Builder<C>; filter(p: (n: C) => boolean): Builder<C>; - withTag(tag: string): Builder<C>; + withTag<D extends StateObjectCell = C>(tag: string): Builder<D>; withTransformer<T extends StateTransformer<any, StateObjectCell.Obj<C>, any>>(t: T): Builder<StateObjectCell<StateObjectCell.Obj<C>, StateTransform<T>>>; withStatus(s: StateObjectCell.Status): Builder<C>; subtree(): Builder; -- GitLab