diff --git a/src/mol-plugin/index.ts b/src/mol-plugin/index.ts index d746789f47017bf8c49d336bfb8b51dc960e0115..eefc0064172ec38a4f5543f43d55c65cdeec891a 100644 --- a/src/mol-plugin/index.ts +++ b/src/mol-plugin/index.ts @@ -10,7 +10,7 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { PluginCommands } from './command'; import { PluginSpec } from './spec'; -import { ObtainAtomicStructure } from './state/actions/basic'; +import { DownloadAtomicStructure, CreateComplexRepresentation } from './state/actions/basic'; import { StateTransforms } from './state/transforms'; import { PluginBehaviors } from './behavior'; import { LogEntry } from 'mol-util/log-entry'; @@ -22,7 +22,8 @@ function getParam(name: string, regex: string): string { const DefaultSpec: PluginSpec = { actions: [ - PluginSpec.Action(ObtainAtomicStructure), + PluginSpec.Action(DownloadAtomicStructure), + PluginSpec.Action(CreateComplexRepresentation), PluginSpec.Action(StateTransforms.Data.Download), PluginSpec.Action(StateTransforms.Data.ParseCif), PluginSpec.Action(StateTransforms.Model.StructureAssemblyFromModel), diff --git a/src/mol-plugin/state/actions/basic.ts b/src/mol-plugin/state/actions/basic.ts index 0d49c8d145196a87c06ec3a7f7e5f89ff8fbac25..9fd7a10df2ba4d41cc933089d04cdfd418ba1734 100644 --- a/src/mol-plugin/state/actions/basic.ts +++ b/src/mol-plugin/state/actions/basic.ts @@ -13,8 +13,8 @@ import { CartoonParams } from 'mol-repr/structure/representation/cartoon'; import { BallAndStickParams } from 'mol-repr/structure/representation/ball-and-stick'; import { Download } from '../transforms/data'; -export { ObtainAtomicStructure } -namespace ObtainAtomicStructure { +export { DownloadAtomicStructure } +namespace DownloadAtomicStructure { export type Sources = 'pdbe-updated' | 'rcsb' | 'bcif-static' | 'url' | 'file' export type Source = ObtainStructureHelpers.MapParams<Sources, typeof ObtainStructureHelpers.ControlMap> export interface Params { @@ -22,25 +22,26 @@ namespace ObtainAtomicStructure { } } namespace ObtainStructureHelpers { - export const SourceOptions: [ObtainAtomicStructure.Sources, string][] = [ + export const SourceOptions: [DownloadAtomicStructure.Sources, string][] = [ ['pdbe-updated', 'PDBe Updated'], ['rcsb', 'RCSB'], ['bcif-static', 'BinaryCIF (static PDBe Updated)'], ['url', 'URL'], + // TODO // ['file', 'File'] ]; export const ControlMap = { 'pdbe-updated': PD.Text('1cbs', { label: 'Id' }), 'rcsb': PD.Text('1tqn', { label: 'Id' }), 'bcif-static': PD.Text('1tqn', { label: 'Id' }), - 'url': PD.Group({ url: PD.Text(''), isBinary: PD.Boolean(false) }), + 'url': PD.Group({ url: PD.Text(''), isBinary: PD.Boolean(false) }, { isExpanded: true }), 'file': PD.Group({ }) } export function getControls(key: string) { return (ControlMap as any)[key]; } - export type MapParams<P extends ObtainAtomicStructure.Sources, Map extends { [K in P]: PD.Any }> = P extends ObtainAtomicStructure.Sources ? PD.NamedParams<Map[P]['defaultValue'], P> : never + export type MapParams<P extends DownloadAtomicStructure.Sources, Map extends { [K in P]: PD.Any }> = P extends DownloadAtomicStructure.Sources ? PD.NamedParams<Map[P]['defaultValue'], P> : never - export function getUrl(src: ObtainAtomicStructure.Source): Download.Params { + export function getUrl(src: DownloadAtomicStructure.Source): Download.Params { switch (src.name) { case 'url': return src.params; case 'pdbe-updated': return { url: `https://www.ebi.ac.uk/pdbe/static/entry/${src.params.toLowerCase()}_updated.cif`, isBinary: false, label: `PDBe: ${src.params}` }; @@ -50,10 +51,10 @@ namespace ObtainStructureHelpers { } } } -const ObtainAtomicStructure = StateAction.create<PluginStateObject.Root, void, ObtainAtomicStructure.Params>({ +const DownloadAtomicStructure = StateAction.create<PluginStateObject.Root, void, DownloadAtomicStructure.Params>({ from: [PluginStateObject.Root], display: { - name: 'Obtain Structure', + name: 'Download Structure', description: 'Load a structure from PDBe and create its default Assembly and visual' }, params: () => ({ source: PD.Mapped('bcif-static', ObtainStructureHelpers.SourceOptions, ObtainStructureHelpers.getControls) }), @@ -91,6 +92,25 @@ const ObtainAtomicStructure = StateAction.create<PluginStateObject.Root, void, O } }); +export const CreateComplexRepresentation = StateAction.create<PluginStateObject.Molecule.Structure, void, {}>({ + from: [PluginStateObject.Molecule.Structure], + display: { + name: 'Create Complex', + description: 'Split the structure into Sequence/Water/Ligands/... ' + }, + apply({ ref, state }) { + const root = state.build().to(ref); + root.apply(StateTransforms.Model.StructureComplexElement, { type: 'sequence' }) + .apply(StateTransforms.Representation.StructureRepresentation3D, { type: { name: 'cartoon', params: PD.getDefaultValues(CartoonParams) } }); + root.apply(StateTransforms.Model.StructureComplexElement, { type: 'ligands' }) + .apply(StateTransforms.Representation.StructureRepresentation3D, { type: { name: 'ball-and-stick', params: PD.getDefaultValues(BallAndStickParams) } }); + root.apply(StateTransforms.Model.StructureComplexElement, { type: 'water' }) + .apply(StateTransforms.Representation.StructureRepresentation3D, { type: { name: 'ball-and-stick', params: { ...PD.getDefaultValues(BallAndStickParams), alpha: 0.51 } } }); + + return state.update(root.getTree()); + } +}); + export const UpdateTrajectory = StateAction.create<PluginStateObject.Root, void, { action: 'advance' | 'reset', by?: number }>({ from: [], display: { diff --git a/src/mol-plugin/ui/controls/parameters.tsx b/src/mol-plugin/ui/controls/parameters.tsx index e3e79de81cdcce1cb2a511a8c2c22c111fd0778b..98bbfa53f5212ae0e126d1e444ddbec81accf1ed 100644 --- a/src/mol-plugin/ui/controls/parameters.tsx +++ b/src/mol-plugin/ui/controls/parameters.tsx @@ -224,7 +224,7 @@ export class MultiSelectControl extends React.PureComponent<ParamProps<PD.MultiS } export class GroupControl extends React.PureComponent<ParamProps<PD.Group<any>>, { isExpanded: boolean }> { - state = { isExpanded: false } + state = { isExpanded: !!this.props.param.isExpanded } change(value: any ) { this.props.onChange({ name: this.props.name, param: this.props.param, value }); diff --git a/src/mol-plugin/ui/plugin.tsx b/src/mol-plugin/ui/plugin.tsx index 3d91ea82467227d25b02e7eb5cc93d079e0a7e50..f29ed9fb5eb5d3d431318af510bb3e805bc554d3 100644 --- a/src/mol-plugin/ui/plugin.tsx +++ b/src/mol-plugin/ui/plugin.tsx @@ -19,6 +19,7 @@ import { BackgroundTaskProgress } from './task'; import { ApplyActionContol } from './state/apply-action'; import { PluginState } from 'mol-plugin/state'; import { UpdateTransformContol } from './state/update-transform'; +import { StateObjectCell } from 'mol-state'; export class Plugin extends React.Component<{ plugin: PluginContext }, {}> { @@ -141,22 +142,20 @@ export class CurrentObject extends PluginComponent { const current = this.current; const ref = current.ref; - // const n = this.props.plugin.state.data.tree.nodes.get(ref)!; - const obj = current.state.cells.get(ref)!; + const cell = current.state.cells.get(ref)!; + const parent: StateObjectCell | undefined = (cell.sourceRef && current.state.cells.get(cell.sourceRef)!) || void 0; - const type = obj && obj.obj ? obj.obj.type : void 0; + const type = cell && cell.obj ? cell.obj.type : void 0; + const transform = cell.transform; + const def = transform.transformer.definition; - const transform = current.state.transforms.get(ref); - - const actions = type - ? current.state.actions.fromType(type) - : [] + const actions = type ? current.state.actions.fromType(type) : []; return <> <div className='msp-section-header'> - {obj.obj ? obj.obj.label : ref} + {cell.obj ? cell.obj.label : (def.display && def.display.name) || def.name} </div> - <UpdateTransformContol state={current.state} transform={transform} /> - { + { (parent && parent.status === 'ok') && <UpdateTransformContol state={current.state} transform={transform} /> } + {cell.status === 'ok' && actions.map((act, i) => <ApplyActionContol plugin={this.plugin} key={`${act.id}`} state={current.state} action={act} nodeRef={ref} />) } </>; diff --git a/src/mol-state/action.ts b/src/mol-state/action.ts index 64826d3b64472b546082a6c8ea9e12fdff842d0a..b1e2ee0e0fd565fecd874e3676762928b78d47a4 100644 --- a/src/mol-state/action.ts +++ b/src/mol-state/action.ts @@ -31,6 +31,7 @@ namespace StateAction { } export interface ApplyParams<A extends StateObject = StateObject, P extends {} = {}> { + ref: string, cell: StateObjectCell, a: A, state: State, diff --git a/src/mol-state/state.ts b/src/mol-state/state.ts index d73d707efaf5280f3f4c0e385b745b8ade465f5e..53a758b1c12aeb086f5ba5eae66d8305386dd8a9 100644 --- a/src/mol-state/state.ts +++ b/src/mol-state/state.ts @@ -104,7 +104,7 @@ class State { if (!cell) throw new Error(`'${ref}' does not exist.`); if (cell.status !== 'ok') throw new Error(`Action cannot be applied to a cell with status '${cell.status}'`); - return runTask(action.definition.apply({ cell, a: cell.obj!, params, state: this }, this.globalContext), ctx); + return runTask(action.definition.apply({ ref, cell, a: cell.obj!, params, state: this }, this.globalContext), ctx); }); } diff --git a/src/mol-util/param-definition.ts b/src/mol-util/param-definition.ts index cd05fcd0ff37f6bbc866b9f9b9a7d08b51f44c34..08db5aee7cbd5d453064872d5cf8779479a56fe4 100644 --- a/src/mol-util/param-definition.ts +++ b/src/mol-util/param-definition.ts @@ -126,10 +126,13 @@ export namespace ParamDefinition { export interface Group<T> extends Base<T> { type: 'group', - params: Params + params: Params, + isExpanded?: boolean } - export function Group<P extends Params>(params: P, info?: Info): Group<Values<P>> { - return setInfo<Group<Values<P>>>({ type: 'group', defaultValue: getDefaultValues(params) as any, params }, info); + export function Group<P extends Params>(params: P, info?: Info & { isExpanded?: boolean }): Group<Values<P>> { + const ret = setInfo<Group<Values<P>>>({ type: 'group', defaultValue: getDefaultValues(params) as any, params }, info); + if (info && info.isExpanded) ret.isExpanded = info.isExpanded; + return ret; } export interface NamedParams<T = any, K = string> { name: K, params: T }