Переглянути джерело

wip, structure tools refactoring

Alexander Rose 5 роки тому
батько
коміт
e2c9b601a6

+ 3 - 242
src/mol-plugin/ui/controls.tsx

@@ -13,21 +13,11 @@ import { LociLabelEntry } from '../../mol-plugin/util/loci-label-manager';
 import { IconButton, Icon } from './controls/common';
 import { PluginStateObject } from '../../mol-plugin/state/objects';
 import { StateTransforms } from '../../mol-plugin/state/transforms';
-import { StateTransformer, StateSelection, StateObjectCell, StateTransform, StateBuilder } from '../../mol-state';
+import { StateTransformer } from '../../mol-state';
 import { ModelFromTrajectory } from '../../mol-plugin/state/transforms/model';
 import { AnimationControls } from './state/animation';
-import { ParamDefinition as PD} from '../../mol-util/param-definition';
-import { ColorNames } from '../../mol-util/color/tables';
-import { ParameterControls } from './controls/parameters';
-import { formatMolScript } from '../../mol-script/language/expression-formatter';
-import { StructureElement, Structure, QueryContext, StructureSelection } from '../../mol-model/structure';
-import { isEmptyLoci, EmptyLoci } from '../../mol-model/loci';
-import { MolScriptBuilder } from '../../mol-script/language/builder';
-import { PluginContext } from '../context';
-import { StructureRepresentation3DHelpers } from '../state/transforms/representation';
-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 { OverpaintControls } from './structure/overpaint';
+import { RepresentationControls } from './structure/representation';
 
 export class TrajectoryViewportControls extends PluginUIComponent<{}, { show: boolean, label: string }> {
     state = { show: false, label: '' }
@@ -264,235 +254,6 @@ export class LociLabelControl extends PluginUIComponent<{}, { entries: ReadonlyA
     }
 }
 
-//
-
-function getExpression(loci: StructureElement.Loci | EmptyLoci) {
-    const scriptExpression = isEmptyLoci(loci)
-        ? MolScriptBuilder.struct.generator.empty()
-        : StructureElement.Loci.toScriptExpression(loci)
-    return formatMolScript(scriptExpression)
-}
-
-type OverpaintEachReprCallback = (update: StateBuilder.Root, repr: StateObjectCell<PluginStateObject.Molecule.Structure.Representation3D, StateTransform<typeof StateTransforms.Representation.StructureRepresentation3D>>, rootStructure: Structure, overpaint?: StateObjectCell<any, StateTransform<typeof StateTransforms.Representation.OverpaintStructureRepresentation3D>>) => void
-const OverpaintManagerTag = 'overpaint-controls'
-
-export class OverpaintControls extends PluginUIComponent<{}, { params: PD.Values<ReturnType<typeof OverpaintControls.getParams>> }> {
-    state = { params: PD.getDefaultValues(OverpaintControls.getParams(this.plugin)) }
-
-    static getParams = (plugin: PluginContext) => {
-        const { types } = plugin.structureRepresentation.registry
-        return {
-            color: PD.Color(ColorNames.cyan),
-            type: PD.MultiSelect(types.map(t => t[0]), types)
-        }
-    }
-
-    componentDidMount() {
-
-    }
-
-    private async eachRepr(callback: OverpaintEachReprCallback) {
-        const state = this.plugin.state.dataState;
-        const reprs = state.select(StateSelection.Generators.ofType(PluginStateObject.Molecule.Structure.Representation3D));
-
-        const update = state.build();
-        for (const r of reprs) {
-            const overpaint = state.select(StateSelection.Generators.ofTransformer(StateTransforms.Representation.OverpaintStructureRepresentation3D, r.transform.ref).withTag(OverpaintManagerTag));
-
-            const structure = r.obj!.data.source.data
-            const rootStructure = structure.parent || structure
-
-            callback(update, r, rootStructure, overpaint[0])
-        }
-
-        await this.plugin.runTask(state.updateTree(update, { doNotUpdateCurrent: true }));
-    }
-
-    set = async (clear: boolean) => {
-        await this.eachRepr((update, repr, rootStructure, overpaint) => {
-            if (!this.state.params.type.includes(repr.params!.values.type.name)) return
-
-            const loci = this.plugin.helpers.structureSelection.get(rootStructure)
-            if (isEmptyLoci(loci) || loci.elements.length === 0) return
-            const expression = getExpression(loci)
-
-            const layer = {
-                script: { language: 'mol-script', expression },
-                color: this.state.params.color,
-                clear
-            }
-
-            if (overpaint) {
-                update.to(overpaint).update({ layers: [ ...overpaint.params!.values.layers, layer ], alpha: 1 })
-            } else {
-                update.to(repr.transform.ref)
-                    .apply(StateTransforms.Representation.OverpaintStructureRepresentation3D, { layers: [ layer ], alpha: 1 }, { tags: OverpaintManagerTag });
-            }
-        })
-    }
-
-    add = async () => {
-        this.set(false)
-    }
-
-    clear = async () => {
-        this.set(true)
-    }
-
-    clearAll = async () => {
-        await this.eachRepr((update, repr, rootStructure, overpaint) => {
-            if (overpaint) update.delete(overpaint.transform.ref)
-        })
-    }
-
-    render() {
-        return <div className='msp-transform-wrapper'>
-            <div className='msp-transform-header'>
-                <button className='msp-btn msp-btn-block'>Current Selection Overpaint</button>
-            </div>
-            <div>
-                <ParameterControls params={OverpaintControls.getParams(this.plugin)} values={this.state.params} onChange={p => {
-                    const params = { ...this.state.params, [p.name]: p.value };
-                    this.setState({ params });
-                }}/>
-
-                <div className='msp-btn-row-group'>
-                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.add}>Add</button>
-                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.clear}>Clear</button>
-                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.clearAll}>Clear All</button>
-                </div>
-            </div>
-        </div>
-    }
-}
-
-type RepresentationEachStructureCallback = (update: StateBuilder.Root, structure: StateObjectCell<PluginStateObject.Molecule.Structure, StateTransform<StateTransformer<any, PluginStateObject.Molecule.Structure, any>>>) => void
-const RepresentationManagerTag = 'representation-controls'
-
-function getRepresentationManagerTag(type: string) {
-    return `${RepresentationManagerTag}-${type}`
-}
-
-function getCombinedLoci(mode: 'add' | 'remove' | 'only' | 'all', loci: StructureElement.Loci, currentLoci: StructureElement.Loci): StructureElement.Loci {
-    switch (mode) {
-        case 'add': return StructureElement.Loci.union(loci, currentLoci)
-        case 'remove': return StructureElement.Loci.subtract(currentLoci, loci)
-        case 'only': return loci
-        case 'all': return StructureElement.Loci.all(loci.structure)
-    }
-}
-
-export class RepresentationControls extends PluginUIComponent<{}, { params: PD.Values<ReturnType<typeof RepresentationControls.getParams>> }> {
-    state = { params: PD.getDefaultValues(RepresentationControls.getParams(this.plugin)) }
-
-    static getParams = (plugin: PluginContext) => {
-        const { types } = plugin.structureRepresentation.registry
-        return {
-            type: PD.Select(types[0][0], types)
-        }
-    }
-
-    componentDidMount() {
-
-    }
-
-    private async eachStructure(callback: RepresentationEachStructureCallback) {
-        const state = this.plugin.state.dataState;
-        const structures = state.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Structure));
-
-        const update = state.build();
-        for (const s of structures) {
-            callback(update, s)
-        }
-
-        await this.plugin.runTask(state.updateTree(update, { doNotUpdateCurrent: true }));
-    }
-
-    set = async (mode: 'add' | 'remove' | 'only' | 'all') => {
-        const state = this.plugin.state.dataState
-        const { type } = this.state.params
-
-        await this.eachStructure((update, structure) => {
-            const s = structure.obj!.data
-            const _loci = this.plugin.helpers.structureSelection.get(s)
-            const loci = isEmptyLoci(_loci) ? StructureElement.Loci(s, []) : _loci
-
-            const selections = state.select(StateSelection.Generators.ofType(PluginStateObject.Molecule.Structure, structure.transform.ref).withTag(getRepresentationManagerTag(type)));
-
-            if (selections.length > 0) {
-                const parsed = parseMolScript(selections[0].params!.values.query.expression)
-                if (parsed.length === 0) return
-
-                const query = transpileMolScript(parsed[0])
-                const compiled = compile(query)
-                const result = compiled(new QueryContext(structure.obj!.data))
-                const currentLoci = StructureSelection.toLoci2(result)
-
-                const combinedLoci = getCombinedLoci(mode, loci, currentLoci)
-
-                update.to(selections[0]).update({
-                    ...selections[0].params!.values,
-                    query: { language: 'mol-script', expression: getExpression(combinedLoci) }
-                })
-
-            } else {
-                const combinedLoci = getCombinedLoci(mode, loci, StructureElement.Loci(loci.structure, []))
-
-                update.to(structure.transform.ref)
-                    .apply(
-                        StateTransforms.Model.UserStructureSelection,
-                        {
-                            query: { language: 'mol-script', expression: getExpression(combinedLoci) },
-                            label: type
-                        },
-                        { tags: [ RepresentationManagerTag, getRepresentationManagerTag(type) ] }
-                    )
-                    .apply(
-                        StateTransforms.Representation.StructureRepresentation3D,
-                        StructureRepresentation3DHelpers.getDefaultParams(this.plugin, type as any, s)
-                    )
-            }
-        })
-    }
-
-    show = async () => { this.set('add') }
-    hide = async () => { this.set('remove') }
-    only = async () => { this.set('only') }
-    showAll = async () => { this.set('all') }
-
-    hideAll = async () => {
-        const { type } = this.state.params
-        const state = this.plugin.state.dataState;
-        const update = state.build();
-
-        state.select(StateSelection.Generators.ofType(PluginStateObject.Molecule.Structure).withTag(getRepresentationManagerTag(type))).forEach(structure => update.delete(structure.transform.ref));
-
-        await this.plugin.runTask(state.updateTree(update, { doNotUpdateCurrent: true }));
-    }
-
-    render() {
-        return <div className='msp-transform-wrapper'>
-            <div className='msp-transform-header'>
-                <button className='msp-btn msp-btn-block'>Current Selection Representation</button>
-            </div>
-            <div>
-                <ParameterControls params={RepresentationControls.getParams(this.plugin)} values={this.state.params} onChange={p => {
-                    const params = { ...this.state.params, [p.name]: p.value };
-                    this.setState({ params });
-                }}/>
-
-                <div className='msp-btn-row-group'>
-                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.show}>Show</button>
-                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.hide}>Hide</button>
-                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.only}>Only</button>
-                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.showAll}>Show All</button>
-                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.hideAll}>Hide All</button>
-                </div>
-            </div>
-        </div>
-    }
-}
-
 export class StructureToolsWrapper extends PluginUIComponent {
     render() {
         return <div>

+ 112 - 0
src/mol-plugin/ui/structure/overpaint.tsx

@@ -0,0 +1,112 @@
+/**
+ * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import * as React from 'react';
+import { PluginUIComponent } from '../base';
+import { PluginStateObject } from '../../../mol-plugin/state/objects';
+import { StateTransforms } from '../../../mol-plugin/state/transforms';
+import { StateSelection, StateObjectCell, StateTransform, StateBuilder } from '../../../mol-state';
+import { ParamDefinition as PD} from '../../../mol-util/param-definition';
+import { ColorNames } from '../../../mol-util/color/tables';
+import { ParameterControls } from '../controls/parameters';
+import { Structure } from '../../../mol-model/structure';
+import { isEmptyLoci } from '../../../mol-model/loci';
+import { PluginContext } from '../../context';
+import { getExpression } from './util';
+
+
+type OverpaintEachReprCallback = (update: StateBuilder.Root, repr: StateObjectCell<PluginStateObject.Molecule.Structure.Representation3D, StateTransform<typeof StateTransforms.Representation.StructureRepresentation3D>>, rootStructure: Structure, overpaint?: StateObjectCell<any, StateTransform<typeof StateTransforms.Representation.OverpaintStructureRepresentation3D>>) => void
+const OverpaintManagerTag = 'overpaint-controls'
+
+export class OverpaintControls extends PluginUIComponent<{}, { params: PD.Values<ReturnType<typeof OverpaintControls.getParams>> }> {
+    state = { params: PD.getDefaultValues(OverpaintControls.getParams(this.plugin)) }
+
+    static getParams = (plugin: PluginContext) => {
+        const { types } = plugin.structureRepresentation.registry
+        return {
+            color: PD.Color(ColorNames.cyan),
+            type: PD.MultiSelect(types.map(t => t[0]), types)
+        }
+    }
+
+    componentDidMount() {
+
+    }
+
+    private async eachRepr(callback: OverpaintEachReprCallback) {
+        const state = this.plugin.state.dataState;
+        const reprs = state.select(StateSelection.Generators.ofType(PluginStateObject.Molecule.Structure.Representation3D));
+
+        const update = state.build();
+        for (const r of reprs) {
+            const overpaint = state.select(StateSelection.Generators.ofTransformer(StateTransforms.Representation.OverpaintStructureRepresentation3D, r.transform.ref).withTag(OverpaintManagerTag));
+
+            const structure = r.obj!.data.source.data
+            const rootStructure = structure.parent || structure
+
+            callback(update, r, rootStructure, overpaint[0])
+        }
+
+        await this.plugin.runTask(state.updateTree(update, { doNotUpdateCurrent: true }));
+    }
+
+    set = async (clear: boolean) => {
+        await this.eachRepr((update, repr, rootStructure, overpaint) => {
+            if (!this.state.params.type.includes(repr.params!.values.type.name)) return
+
+            const loci = this.plugin.helpers.structureSelection.get(rootStructure)
+            if (isEmptyLoci(loci) || loci.elements.length === 0) return
+            const expression = getExpression(loci)
+
+            const layer = {
+                script: { language: 'mol-script', expression },
+                color: this.state.params.color,
+                clear
+            }
+
+            if (overpaint) {
+                update.to(overpaint).update({ layers: [ ...overpaint.params!.values.layers, layer ], alpha: 1 })
+            } else {
+                update.to(repr.transform.ref)
+                    .apply(StateTransforms.Representation.OverpaintStructureRepresentation3D, { layers: [ layer ], alpha: 1 }, { tags: OverpaintManagerTag });
+            }
+        })
+    }
+
+    add = async () => {
+        this.set(false)
+    }
+
+    clear = async () => {
+        this.set(true)
+    }
+
+    clearAll = async () => {
+        await this.eachRepr((update, repr, rootStructure, overpaint) => {
+            if (overpaint) update.delete(overpaint.transform.ref)
+        })
+    }
+
+    render() {
+        return <div className='msp-transform-wrapper'>
+            <div className='msp-transform-header'>
+                <button className='msp-btn msp-btn-block'>Current Selection Overpaint</button>
+            </div>
+            <div>
+                <ParameterControls params={OverpaintControls.getParams(this.plugin)} values={this.state.params} onChange={p => {
+                    const params = { ...this.state.params, [p.name]: p.value };
+                    this.setState({ params });
+                }}/>
+
+                <div className='msp-btn-row-group'>
+                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.add}>Add</button>
+                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.clear}>Clear</button>
+                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.clearAll}>Clear All</button>
+                </div>
+            </div>
+        </div>
+    }
+}

+ 147 - 0
src/mol-plugin/ui/structure/representation.tsx

@@ -0,0 +1,147 @@
+/**
+ * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import * as React from 'react';
+import { PluginUIComponent } from '../base';
+import { PluginStateObject } from '../../../mol-plugin/state/objects';
+import { StateTransforms } from '../../../mol-plugin/state/transforms';
+import { StateTransformer, StateSelection, StateObjectCell, StateTransform, StateBuilder } from '../../../mol-state';
+import { ParamDefinition as PD} from '../../../mol-util/param-definition';
+import { ParameterControls } from '../controls/parameters';
+import { StructureElement, QueryContext, StructureSelection } from '../../../mol-model/structure';
+import { isEmptyLoci } from '../../../mol-model/loci';
+import { PluginContext } from '../../context';
+import { getExpression } from './util';
+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 { StructureRepresentation3DHelpers } from '../../state/transforms/representation';
+
+type RepresentationEachStructureCallback = (update: StateBuilder.Root, structure: StateObjectCell<PluginStateObject.Molecule.Structure, StateTransform<StateTransformer<any, PluginStateObject.Molecule.Structure, any>>>) => void
+const RepresentationManagerTag = 'representation-controls'
+
+function getRepresentationManagerTag(type: string) {
+    return `${RepresentationManagerTag}-${type}`
+}
+
+function getCombinedLoci(mode: 'add' | 'remove' | 'only' | 'all', loci: StructureElement.Loci, currentLoci: StructureElement.Loci): StructureElement.Loci {
+    switch (mode) {
+        case 'add': return StructureElement.Loci.union(loci, currentLoci)
+        case 'remove': return StructureElement.Loci.subtract(currentLoci, loci)
+        case 'only': return loci
+        case 'all': return StructureElement.Loci.all(loci.structure)
+    }
+}
+
+export class RepresentationControls extends PluginUIComponent<{}, { params: PD.Values<ReturnType<typeof RepresentationControls.getParams>> }> {
+    state = { params: PD.getDefaultValues(RepresentationControls.getParams(this.plugin)) }
+
+    static getParams = (plugin: PluginContext) => {
+        const { types } = plugin.structureRepresentation.registry
+        return {
+            type: PD.Select(types[0][0], types)
+        }
+    }
+
+    componentDidMount() {
+
+    }
+
+    private async eachStructure(callback: RepresentationEachStructureCallback) {
+        const state = this.plugin.state.dataState;
+        const structures = state.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Structure));
+
+        const update = state.build();
+        for (const s of structures) {
+            callback(update, s)
+        }
+
+        await this.plugin.runTask(state.updateTree(update, { doNotUpdateCurrent: true }));
+    }
+
+    set = async (mode: 'add' | 'remove' | 'only' | 'all') => {
+        const state = this.plugin.state.dataState
+        const { type } = this.state.params
+
+        await this.eachStructure((update, structure) => {
+            const s = structure.obj!.data
+            const _loci = this.plugin.helpers.structureSelection.get(s)
+            const loci = isEmptyLoci(_loci) ? StructureElement.Loci(s, []) : _loci
+
+            const selections = state.select(StateSelection.Generators.ofType(PluginStateObject.Molecule.Structure, structure.transform.ref).withTag(getRepresentationManagerTag(type)));
+
+            if (selections.length > 0) {
+                const parsed = parseMolScript(selections[0].params!.values.query.expression)
+                if (parsed.length === 0) return
+
+                const query = transpileMolScript(parsed[0])
+                const compiled = compile(query)
+                const result = compiled(new QueryContext(structure.obj!.data))
+                const currentLoci = StructureSelection.toLoci2(result)
+
+                const combinedLoci = getCombinedLoci(mode, loci, currentLoci)
+
+                update.to(selections[0]).update({
+                    ...selections[0].params!.values,
+                    query: { language: 'mol-script', expression: getExpression(combinedLoci) }
+                })
+            } else {
+                const combinedLoci = getCombinedLoci(mode, loci, StructureElement.Loci(loci.structure, []))
+
+                update.to(structure.transform.ref)
+                    .apply(
+                        StateTransforms.Model.UserStructureSelection,
+                        {
+                            query: { language: 'mol-script', expression: getExpression(combinedLoci) },
+                            label: type
+                        },
+                        { tags: [ RepresentationManagerTag, getRepresentationManagerTag(type) ] }
+                    )
+                    .apply(
+                        StateTransforms.Representation.StructureRepresentation3D,
+                        StructureRepresentation3DHelpers.getDefaultParams(this.plugin, type as any, s)
+                    )
+            }
+        })
+    }
+
+    show = async () => { this.set('add') }
+    hide = async () => { this.set('remove') }
+    only = async () => { this.set('only') }
+    showAll = async () => { this.set('all') }
+
+    hideAll = async () => {
+        const { type } = this.state.params
+        const state = this.plugin.state.dataState;
+        const update = state.build();
+
+        state.select(StateSelection.Generators.ofType(PluginStateObject.Molecule.Structure).withTag(getRepresentationManagerTag(type))).forEach(structure => update.delete(structure.transform.ref));
+
+        await this.plugin.runTask(state.updateTree(update, { doNotUpdateCurrent: true }));
+    }
+
+    render() {
+        return <div className='msp-transform-wrapper'>
+            <div className='msp-transform-header'>
+                <button className='msp-btn msp-btn-block'>Current Selection Representation</button>
+            </div>
+            <div>
+                <ParameterControls params={RepresentationControls.getParams(this.plugin)} values={this.state.params} onChange={p => {
+                    const params = { ...this.state.params, [p.name]: p.value };
+                    this.setState({ params });
+                }}/>
+
+                <div className='msp-btn-row-group'>
+                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.show}>Show</button>
+                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.hide}>Hide</button>
+                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.only}>Only</button>
+                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.showAll}>Show All</button>
+                    <button className='msp-btn msp-btn-block msp-form-control' onClick={this.hideAll}>Hide All</button>
+                </div>
+            </div>
+        </div>
+    }
+}

+ 17 - 0
src/mol-plugin/ui/structure/util.ts

@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { StructureElement } from '../../../mol-model/structure';
+import { EmptyLoci, isEmptyLoci } from '../../../mol-model/loci';
+import { MolScriptBuilder } from '../../../mol-script/language/builder';
+import { formatMolScript } from '../../../mol-script/language/expression-formatter';
+
+export function getExpression(loci: StructureElement.Loci | EmptyLoci) {
+    const scriptExpression = isEmptyLoci(loci)
+        ? MolScriptBuilder.struct.generator.empty()
+        : StructureElement.Loci.toScriptExpression(loci)
+    return formatMolScript(scriptExpression)
+}