diff --git a/src/mol-plugin/index.ts b/src/mol-plugin/index.ts index 20e7fa253a5b760265f57161dad7ef5c5240bcdf..209daad2cf8211815ed338108973b88dfb217af1 100644 --- a/src/mol-plugin/index.ts +++ b/src/mol-plugin/index.ts @@ -52,7 +52,7 @@ export const DefaultPluginSpec: PluginSpec = { PluginSpec.Action(StateTransforms.Representation.ExplodeStructureRepresentation3D), PluginSpec.Action(StateTransforms.Representation.UnwindStructureAssemblyRepresentation3D), PluginSpec.Action(StateTransforms.Representation.OverpaintStructureRepresentation3DFromScript), - PluginSpec.Action(StateTransforms.Representation.TransparencyStructureRepresentation3D), + PluginSpec.Action(StateTransforms.Representation.TransparencyStructureRepresentation3DFromScript), PluginSpec.Action(StateTransforms.Volume.VolumeFromCcp4), PluginSpec.Action(StateTransforms.Representation.VolumeRepresentation3D), diff --git a/src/mol-plugin/state/transforms/helpers.ts b/src/mol-plugin/state/transforms/helpers.ts index c777529b70e17883f545566d6142167b8e9d85ad..6d2bbf3cec44b65e5adbf61f5ee883ab8298d215 100644 --- a/src/mol-plugin/state/transforms/helpers.ts +++ b/src/mol-plugin/state/transforms/helpers.ts @@ -4,50 +4,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Structure, StructureSelection, QueryContext, StructureElement } from '../../../mol-model/structure'; -import { Color } from '../../../mol-util/color'; -import { Overpaint } from '../../../mol-theme/overpaint'; -import { parseMolScript } from '../../../mol-script/language/parser'; -import { transpileMolScript } from '../../../mol-script/script/mol-script/symbols'; -import { compile } from '../../../mol-script/runtime/query/compiler'; -import { Transparency } from '../../../mol-theme/transparency'; +import { Structure } from '../../../mol-model/structure'; import { ComputedSecondaryStructure } from '../../../mol-model-props/computed/secondary-structure'; -type Script = { language: string, expression: string } - -function scriptToLoci(structure: Structure, script: Script) { - const parsed = parseMolScript(script.expression) - if (parsed.length === 0) throw new Error('No query') - const query = transpileMolScript(parsed[0]) - - const compiled = compile<StructureSelection>(query) - const result = compiled(new QueryContext(structure)) - return StructureSelection.toLoci2(result) -} - -export function getStructureOverpaintFromScript(structure: Structure, scriptLayers: { script: Script, color: Color, clear: boolean }[], alpha: number): Overpaint { - const layers: Overpaint.Layer[] = [] - for (let i = 0, il = scriptLayers.length; i < il; ++i) { - const { script, color, clear } = scriptLayers[i] - layers.push({ loci: scriptToLoci(structure, script), color, clear }) - } - return { layers, alpha } -} - -export function getStructureOverpaintFromBundle(structure: Structure, bundleLayers: { bundle: StructureElement.Bundle, color: Color, clear: boolean }[], alpha: number): Overpaint { - const layers: Overpaint.Layer[] = [] - for (let i = 0, il = bundleLayers.length; i < il; ++i) { - const { bundle, color, clear } = bundleLayers[i] - const loci = StructureElement.Bundle.toLoci(bundle, structure.root) - layers.push({ loci, color, clear }) - } - return { layers, alpha } -} - -export function getStructureTransparency(structure: Structure, script: Script, value: number, variant: Transparency.Variant): Transparency { - return { loci: scriptToLoci(structure, script), value, variant } -} - /** * Attaches ComputedSecondaryStructure property when unavailable in sourceData */ diff --git a/src/mol-plugin/state/transforms/representation.ts b/src/mol-plugin/state/transforms/representation.ts index cdc5e19320cf10585a244b03d56cb3fd5f8d1be8..84be0e176ab66d8d095cb1ea2977d91832bf2918 100644 --- a/src/mol-plugin/state/transforms/representation.ts +++ b/src/mol-plugin/state/transforms/representation.ts @@ -29,8 +29,8 @@ import { unwindStructureAssembly, explodeStructure } from '../animation/helpers' import { Color } from '../../../mol-util/color'; import { Overpaint } from '../../../mol-theme/overpaint'; import { Transparency } from '../../../mol-theme/transparency'; -import { getStructureOverpaintFromScript, getStructureOverpaintFromBundle, getStructureTransparency } from './helpers'; import { BaseGeometry } from '../../../mol-geo/geometry/base'; +import { Script } from '../../../mol-script/script'; export { StructureRepresentation3D } export { StructureRepresentation3DHelpers } @@ -39,7 +39,8 @@ export { ExplodeStructureRepresentation3D } export { UnwindStructureAssemblyRepresentation3D } export { OverpaintStructureRepresentation3DFromScript } export { OverpaintStructureRepresentation3DFromBundle } -export { TransparencyStructureRepresentation3D } +export { TransparencyStructureRepresentation3DFromScript } +export { TransparencyStructureRepresentation3DFromBundle } export { VolumeRepresentation3D } namespace StructureRepresentation3DHelpers { @@ -334,12 +335,12 @@ const OverpaintStructureRepresentation3DFromScript = PluginStateTransform.BuiltI to: SO.Molecule.Structure.Representation3DState, params: { layers: PD.ObjectList({ - script: PD.ScriptExpression({ language: 'mol-script', expression: '(sel.atom.all)' }), + script: PD.Script(Script('(sel.atom.all)', 'mol-script')), color: PD.Color(ColorNames.blueviolet), clear: PD.Boolean(false) }, e => `${e.clear ? 'Clear' : Color.toRgbString(e.color)}`, { defaultValue: [{ - script: { language: 'mol-script', expression: '(sel.atom.all)' }, + script: Script('(sel.atom.all)', 'mol-script'), color: ColorNames.blueviolet, clear: false }] @@ -352,7 +353,7 @@ const OverpaintStructureRepresentation3DFromScript = PluginStateTransform.BuiltI }, apply({ a, params }) { const structure = a.data.source.data - const overpaint = getStructureOverpaintFromScript(structure, params.layers, params.alpha) + const overpaint = Overpaint.ofScript(params.layers, params.alpha, structure) return new SO.Molecule.Structure.Representation3DState({ state: { overpaint }, @@ -366,7 +367,7 @@ const OverpaintStructureRepresentation3DFromScript = PluginStateTransform.BuiltI const newStructure = a.data.source.data if (newStructure !== oldStructure) return StateTransformer.UpdateResult.Recreate const oldOverpaint = b.data.state.overpaint! - const newOverpaint = getStructureOverpaintFromScript(newStructure, newParams.layers, newParams.alpha) + const newOverpaint = Overpaint.ofScript(newParams.layers, newParams.alpha, newStructure) if (oldParams.alpha === newParams.alpha && Overpaint.areEqual(oldOverpaint, newOverpaint)) return StateTransformer.UpdateResult.Unchanged b.data.state.overpaint = newOverpaint @@ -403,7 +404,7 @@ const OverpaintStructureRepresentation3DFromBundle = PluginStateTransform.BuiltI }, apply({ a, params }) { const structure = a.data.source.data - const overpaint = getStructureOverpaintFromBundle(structure, params.layers, params.alpha) + const overpaint = Overpaint.ofBundle(params.layers, params.alpha, structure) return new SO.Molecule.Structure.Representation3DState({ state: { overpaint }, @@ -417,7 +418,7 @@ const OverpaintStructureRepresentation3DFromBundle = PluginStateTransform.BuiltI const newStructure = a.data.source.data if (newStructure !== oldStructure) return StateTransformer.UpdateResult.Recreate const oldOverpaint = b.data.state.overpaint! - const newOverpaint = getStructureOverpaintFromBundle(newStructure, newParams.layers, newParams.alpha) + const newOverpaint = Overpaint.ofBundle(newParams.layers, newParams.alpha, newStructure) if (oldParams.alpha === newParams.alpha && Overpaint.areEqual(oldOverpaint, newOverpaint)) return StateTransformer.UpdateResult.Unchanged b.data.state.overpaint = newOverpaint @@ -427,14 +428,14 @@ const OverpaintStructureRepresentation3DFromBundle = PluginStateTransform.BuiltI } }); -type TransparencyStructureRepresentation3D = typeof TransparencyStructureRepresentation3D -const TransparencyStructureRepresentation3D = PluginStateTransform.BuiltIn({ - name: 'transparency-structure-representation-3d', +type TransparencyStructureRepresentation3DFromScript = typeof TransparencyStructureRepresentation3DFromScript +const TransparencyStructureRepresentation3DFromScript = PluginStateTransform.BuiltIn({ + name: 'transparency-structure-representation-3d-from-script', display: 'Transparency 3D Representation', from: SO.Molecule.Structure.Representation3D, to: SO.Molecule.Structure.Representation3DState, params: { - script: PD.ScriptExpression({ language: 'mol-script', expression: '(sel.atom.all)' }), + script: PD.Script(Script('(sel.atom.all)', 'mol-script')), value: PD.Numeric(0.75, { min: 0, max: 1, step: 0.01 }, { label: 'Transparency' }), variant: PD.Select('single', [['single', 'Single-layer'], ['multi', 'Multi-layer']]) } @@ -444,7 +445,7 @@ const TransparencyStructureRepresentation3D = PluginStateTransform.BuiltIn({ }, apply({ a, params }) { const structure = a.data.source.data - const transparency = getStructureTransparency(structure, params.script, params.value, params.variant) + const transparency = Transparency.ofScript(params.script, params.value, params.variant, structure) return new SO.Molecule.Structure.Representation3DState({ state: { transparency }, @@ -457,7 +458,47 @@ const TransparencyStructureRepresentation3D = PluginStateTransform.BuiltIn({ const structure = b.data.info as Structure if (a.data.source.data !== structure) return StateTransformer.UpdateResult.Recreate const oldTransparency = b.data.state.transparency! - const newTransparency = getStructureTransparency(structure, newParams.script, newParams.value, newParams.variant) + const newTransparency = Transparency.ofScript(newParams.script, newParams.value, newParams.variant, structure) + if (Transparency.areEqual(oldTransparency, newTransparency)) return StateTransformer.UpdateResult.Unchanged + + b.data.state.transparency = newTransparency + b.data.source = a + b.label = `Transparency (${newTransparency.value})` + return StateTransformer.UpdateResult.Updated + } +}); + +type TransparencyStructureRepresentation3DFromBundle = typeof TransparencyStructureRepresentation3DFromBundle +const TransparencyStructureRepresentation3DFromBundle = PluginStateTransform.BuiltIn({ + name: 'transparency-structure-representation-3d-from-bundle', + display: 'Transparency 3D Representation', + from: SO.Molecule.Structure.Representation3D, + to: SO.Molecule.Structure.Representation3DState, + params: { + bundle: PD.Value<StructureElement.Bundle>(StructureElement.Bundle.Empty), + value: PD.Numeric(0.75, { min: 0, max: 1, step: 0.01 }, { label: 'Transparency' }), + variant: PD.Select('single', [['single', 'Single-layer'], ['multi', 'Multi-layer']]) + } +})({ + canAutoUpdate() { + return true; + }, + apply({ a, params }) { + const structure = a.data.source.data + const transparency = Transparency.ofBundle(params.bundle, params.value, params.variant, structure) + + return new SO.Molecule.Structure.Representation3DState({ + state: { transparency }, + initialState: { transparency: Transparency.Empty }, + info: structure, + source: a + }, { label: `Transparency (${transparency.value})` }) + }, + update({ a, b, newParams, oldParams }) { + const structure = b.data.info as Structure + if (a.data.source.data !== structure) return StateTransformer.UpdateResult.Recreate + const oldTransparency = b.data.state.transparency! + const newTransparency = Transparency.ofBundle(newParams.bundle, newParams.value, newParams.variant, structure) if (Transparency.areEqual(oldTransparency, newTransparency)) return StateTransformer.UpdateResult.Unchanged b.data.state.transparency = newTransparency diff --git a/src/mol-theme/overpaint.ts b/src/mol-theme/overpaint.ts index 2d80d6154f99cea09537034782e0c1130a8bafb5..b7de9494417c0c5c7044a681a846331f250b9683 100644 --- a/src/mol-theme/overpaint.ts +++ b/src/mol-theme/overpaint.ts @@ -6,7 +6,8 @@ import { Loci } from '../mol-model/loci'; import { Color } from '../mol-util/color'; -import { Structure } from '../mol-model/structure'; +import { Structure, StructureElement } from '../mol-model/structure'; +import { Script } from '../mol-script/script'; export { Overpaint } @@ -36,4 +37,23 @@ namespace Overpaint { } return { layers, alpha: overpaint.alpha } } + + export function ofScript(scriptLayers: { script: Script, color: Color, clear: boolean }[], alpha: number, structure: Structure): Overpaint { + const layers: Overpaint.Layer[] = [] + for (let i = 0, il = scriptLayers.length; i < il; ++i) { + const { script, color, clear } = scriptLayers[i] + layers.push({ loci: Script.toLoci(script, structure), color, clear }) + } + return { layers, alpha } + } + + export function ofBundle(bundleLayers: { bundle: StructureElement.Bundle, color: Color, clear: boolean }[], alpha: number, structure: Structure): Overpaint { + const layers: Overpaint.Layer[] = [] + for (let i = 0, il = bundleLayers.length; i < il; ++i) { + const { bundle, color, clear } = bundleLayers[i] + const loci = StructureElement.Bundle.toLoci(bundle, structure.root) + layers.push({ loci, color, clear }) + } + return { layers, alpha } + } } \ No newline at end of file diff --git a/src/mol-theme/transparency.ts b/src/mol-theme/transparency.ts index acb152aed3311a3c259076f569b4adf48e65625b..8bf1032ca3c6946db889b2fc406d7c0efb63941a 100644 --- a/src/mol-theme/transparency.ts +++ b/src/mol-theme/transparency.ts @@ -5,6 +5,8 @@ */ import { Loci, EmptyLoci } from '../mol-model/loci'; +import { StructureElement, Structure } from '../mol-model/structure'; +import { Script } from '../mol-script/script'; export { Transparency } @@ -24,4 +26,12 @@ namespace Transparency { if (!Loci.areEqual(tA.loci, tB.loci)) return false return true } + + export function ofScript(script: Script, value: number, variant: Transparency.Variant, structure: Structure): Transparency { + return { loci: Script.toLoci(script, structure), value, variant } + } + + export function ofBundle(bundle: StructureElement.Bundle, value: number, variant: Transparency.Variant, structure: Structure): Transparency { + return { loci: StructureElement.Bundle.toLoci(bundle, structure), value, variant } + } } \ No newline at end of file