From 678f7887489cdc10cb44c1cf35ab1fb0ef9fe8f2 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Wed, 21 Nov 2018 10:40:27 +0100 Subject: [PATCH] mol-plugin: multi-source obtain structure, param definition tweaks --- src/mol-plugin/index.ts | 4 +- src/mol-plugin/state.ts | 1 - src/mol-plugin/state/actions/basic.ts | 51 ++++++++++++++++++++--- src/mol-plugin/ui/controls/parameters.tsx | 13 +++--- src/mol-util/param-definition.ts | 2 +- 5 files changed, 53 insertions(+), 18 deletions(-) diff --git a/src/mol-plugin/index.ts b/src/mol-plugin/index.ts index 7a87cb504..d746789f4 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 { CreateStructureFromPDBe } from './state/actions/basic'; +import { ObtainAtomicStructure } from './state/actions/basic'; import { StateTransforms } from './state/transforms'; import { PluginBehaviors } from './behavior'; import { LogEntry } from 'mol-util/log-entry'; @@ -22,7 +22,7 @@ function getParam(name: string, regex: string): string { const DefaultSpec: PluginSpec = { actions: [ - PluginSpec.Action(CreateStructureFromPDBe), + PluginSpec.Action(ObtainAtomicStructure), PluginSpec.Action(StateTransforms.Data.Download), PluginSpec.Action(StateTransforms.Data.ParseCif), PluginSpec.Action(StateTransforms.Model.StructureAssemblyFromModel), diff --git a/src/mol-plugin/state.ts b/src/mol-plugin/state.ts index db6cf78e9..e120f86bc 100644 --- a/src/mol-plugin/state.ts +++ b/src/mol-plugin/state.ts @@ -12,7 +12,6 @@ import { CameraSnapshotManager } from './state/camera'; import { PluginStateSnapshotManager } from './state/snapshots'; import { RxEventHelper } from 'mol-util/rx-event-helper'; import { Canvas3DParams } from 'mol-canvas3d/canvas3d'; -import { ParamDefinition } from 'mol-util/param-definition'; import { PluginCommands } from './command'; export { PluginState } diff --git a/src/mol-plugin/state/actions/basic.ts b/src/mol-plugin/state/actions/basic.ts index 002ca7f8a..0d49c8d14 100644 --- a/src/mol-plugin/state/actions/basic.ts +++ b/src/mol-plugin/state/actions/basic.ts @@ -11,16 +11,53 @@ import { ParamDefinition as PD } from 'mol-util/param-definition'; import { StateSelection } from 'mol-state/state/selection'; import { CartoonParams } from 'mol-repr/structure/representation/cartoon'; import { BallAndStickParams } from 'mol-repr/structure/representation/ball-and-stick'; +import { Download } from '../transforms/data'; -export const CreateStructureFromPDBe = StateAction.create<PluginStateObject.Root, void, { id: string }>({ +export { ObtainAtomicStructure } +namespace ObtainAtomicStructure { + export type Sources = 'pdbe-updated' | 'rcsb' | 'bcif-static' | 'url' | 'file' + export type Source = ObtainStructureHelpers.MapParams<Sources, typeof ObtainStructureHelpers.ControlMap> + export interface Params { + source: Source + } +} +namespace ObtainStructureHelpers { + export const SourceOptions: [ObtainAtomicStructure.Sources, string][] = [ + ['pdbe-updated', 'PDBe Updated'], + ['rcsb', 'RCSB'], + ['bcif-static', 'BinaryCIF (static PDBe Updated)'], + ['url', 'URL'], + // ['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) }), + '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 function getUrl(src: ObtainAtomicStructure.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}` }; + case 'rcsb': return { url: `https://files.rcsb.org/download/${src.params.toUpperCase()}.cif`, isBinary: false, label: `RCSB: ${src.params}` }; + case 'bcif-static': return { url: `https://webchem.ncbr.muni.cz/ModelServer/static/bcif/${src.params.toLowerCase()}`, isBinary: true, label: `BinaryCIF: ${src.params}` }; + default: throw new Error(`${src.name} not supported.`); + } + } +} +const ObtainAtomicStructure = StateAction.create<PluginStateObject.Root, void, ObtainAtomicStructure.Params>({ from: [PluginStateObject.Root], display: { - name: 'Entry from PDBe', - description: 'Download a structure from PDBe and create its default Assembly and visual' + name: 'Obtain Structure', + description: 'Load a structure from PDBe and create its default Assembly and visual' }, - params: () => ({ id: PD.Text('1grm', { label: 'PDB id' }) }), + params: () => ({ source: PD.Mapped('bcif-static', ObtainStructureHelpers.SourceOptions, ObtainStructureHelpers.getControls) }), apply({ params, state }) { - const url = `http://www.ebi.ac.uk/pdbe/static/entry/${params.id.toLowerCase()}_updated.cif`; const b = state.build(); // const query = MolScriptBuilder.struct.generator.atomGroups({ @@ -34,8 +71,10 @@ export const CreateStructureFromPDBe = StateAction.create<PluginStateObject.Root // ]) // }); + const url = ObtainStructureHelpers.getUrl(params.source); + const root = b.toRoot() - .apply(StateTransforms.Data.Download, { url }) + .apply(StateTransforms.Data.Download, url) .apply(StateTransforms.Data.ParseCif) .apply(StateTransforms.Model.TrajectoryFromMmCif, {}) .apply(StateTransforms.Model.ModelFromTrajectory, { modelIndex: 0 }) diff --git a/src/mol-plugin/ui/controls/parameters.tsx b/src/mol-plugin/ui/controls/parameters.tsx index de4a6afbb..e3e79de81 100644 --- a/src/mol-plugin/ui/controls/parameters.tsx +++ b/src/mol-plugin/ui/controls/parameters.tsx @@ -226,19 +226,17 @@ export class MultiSelectControl extends React.PureComponent<ParamProps<PD.MultiS export class GroupControl extends React.PureComponent<ParamProps<PD.Group<any>>, { isExpanded: boolean }> { state = { isExpanded: false } - change(value: PD.Mapped<any>['defaultValue'] ) { + change(value: any ) { this.props.onChange({ name: this.props.name, param: this.props.param, value }); } onChangeParam: ParamOnChange = e => { - const value: PD.Mapped<any>['defaultValue'] = this.props.value; - this.change({ ...value.params, [e.name]: e.value }); + this.change({ ...this.props.value, [e.name]: e.value }); } toggleExpanded = () => this.setState({ isExpanded: !this.state.isExpanded }); render() { - const value: PD.Mapped<any>['defaultValue'] = this.props.value; const params = this.props.param.params; const label = this.props.param.label || camelCaseToWords(this.props.name); @@ -250,7 +248,7 @@ export class GroupControl extends React.PureComponent<ParamProps<PD.Group<any>>, </button> </div> {this.state.isExpanded && <div className='msp-control-offset' style={{ display: this.state.isExpanded ? 'block' : 'none' }}> - <ParameterControls params={params} onChange={this.onChangeParam} values={value.params} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} /> + <ParameterControls params={params} onChange={this.onChangeParam} values={this.props.value} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} /> </div> } </div> @@ -268,8 +266,7 @@ export class MappedControl extends React.PureComponent<ParamProps<PD.Mapped<any> } onChangeParam: ParamOnChange = e => { - const value: PD.Mapped<any>['defaultValue'] = this.props.value; - this.change({ name: value.name, params: e.value }); + this.change({ name: this.props.value.name, params: e.value }); } render() { @@ -288,7 +285,7 @@ export class MappedControl extends React.PureComponent<ParamProps<PD.Mapped<any> return <div> {select} - <Mapped param={param} value={value} name={`${label} Properties`} onChange={this.onChangeParam} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} /> + <Mapped param={param} value={value.params} name={`${label} Properties`} onChange={this.onChangeParam} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} /> </div> } } diff --git a/src/mol-util/param-definition.ts b/src/mol-util/param-definition.ts index e508a72c7..cd05fcd0f 100644 --- a/src/mol-util/param-definition.ts +++ b/src/mol-util/param-definition.ts @@ -132,7 +132,7 @@ export namespace ParamDefinition { return setInfo<Group<Values<P>>>({ type: 'group', defaultValue: getDefaultValues(params) as any, params }, info); } - export interface NamedParams<T = any> { name: string, params: T } + export interface NamedParams<T = any, K = string> { name: K, params: T } export interface Mapped<T> extends Base<NamedParams<T>> { type: 'mapped', select: Select<string>, -- GitLab