Skip to content
Snippets Groups Projects
Commit cc462a27 authored by David Sehnal's avatar David Sehnal
Browse files

mol-state: wip, automatic default params

parent 384f589c
Branches
Tags
No related merge requests found
......@@ -25,7 +25,7 @@ export const PDBeStructureQualityReport = PluginBehavior.create<{ autoAttach: bo
private provider: CustomPropertyRegistry.Provider = {
option: [StructureQualityReport.Descriptor.name, 'PDBe Structure Quality Report'],
descriptor: StructureQualityReport.Descriptor,
defaultSelected: false,
defaultSelected: this.params.autoAttach,
attachableTo: () => true,
attach: this.attach
}
......
......@@ -36,7 +36,7 @@ const DefaultSpec: PluginSpec = {
PluginSpec.Behavior(PluginBehaviors.Representation.SelectLoci),
PluginSpec.Behavior(PluginBehaviors.Representation.DefaultLociLabelProvider),
PluginSpec.Behavior(PluginBehaviors.Camera.FocusLociOnSelect, { minRadius: 20, extraRadius: 4 }),
PluginSpec.Behavior(PluginBehaviors.CustomProps.PDBeStructureQualityReport, { autoAttach: false })
PluginSpec.Behavior(PluginBehaviors.CustomProps.PDBeStructureQualityReport, { autoAttach: true })
]
}
......
......@@ -4,25 +4,20 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { PluginContext } from 'mol-plugin/context';
import { StateTree, Transformer } from 'mol-state';
import { StateAction } from 'mol-state/action';
import { StateSelection } from 'mol-state/state/selection';
import { StateTreeBuilder } from 'mol-state/tree/builder';
import { ParamDefinition as PD } from 'mol-util/param-definition';
import { PluginStateObject } from '../objects';
import { StateTransforms } from '../transforms';
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';
import { StateTree, Transformer } from 'mol-state';
import { StateTreeBuilder } from 'mol-state/tree/builder';
import { PolymerIdColorThemeParams } from 'mol-theme/color/polymer-id';
import { UniformSizeThemeParams } from 'mol-theme/size/uniform';
import { ElementSymbolColorThemeParams } from 'mol-theme/color/element-symbol';
import { PhysicalSizeThemeParams } from 'mol-theme/size/physical';
import { SpacefillParams } from 'mol-repr/structure/representation/spacefill';
import { StructureRepresentation3DHelpers } from '../transforms/representation';
// TODO: "structure parser provider"
export { DownloadStructure }
export { DownloadStructure };
type DownloadStructure = typeof DownloadStructure
const DownloadStructure = StateAction.build({
from: PluginStateObject.Root,
......@@ -55,7 +50,7 @@ const DownloadStructure = StateAction.build({
]
})
}
})(({ params, state }) => {
})(({ params, state }, ctx: PluginContext) => {
const b = state.build();
const src = params.source;
let url: Transformer.Params<Download>;
......@@ -77,69 +72,55 @@ const DownloadStructure = StateAction.build({
}
const data = b.toRoot().apply(StateTransforms.Data.Download, url);
return state.update(createStructureTree(data, params.source.params.supportProps));
return state.update(createStructureTree(ctx, data, params.source.params.supportProps));
});
export const OpenStructure = StateAction.build({
display: { name: 'Open Structure', description: 'Load a structure from file and create its default Assembly and visual' },
from: PluginStateObject.Root,
params: { file: PD.File({ accept: '.cif,.bcif' }) }
})(({ params, state }) => {
})(({ params, state }, ctx: PluginContext) => {
const b = state.build();
const data = b.toRoot().apply(StateTransforms.Data.ReadFile, { file: params.file, isBinary: /\.bcif$/i.test(params.file.name) });
return state.update(createStructureTree(data, false));
return state.update(createStructureTree(ctx, data, false));
});
function createStructureTree(b: StateTreeBuilder.To<PluginStateObject.Data.Binary | PluginStateObject.Data.String>, supportProps: boolean): StateTree {
function createStructureTree(ctx: PluginContext, b: StateTreeBuilder.To<PluginStateObject.Data.Binary | PluginStateObject.Data.String>, supportProps: boolean): StateTree {
let root = b
.apply(StateTransforms.Data.ParseCif)
.apply(StateTransforms.Model.TrajectoryFromMmCif, {})
.apply(StateTransforms.Model.TrajectoryFromMmCif)
.apply(StateTransforms.Model.ModelFromTrajectory, { modelIndex: 0 });
if (supportProps) {
// TODO: implement automatic default property assigment in State.update
root = root.apply(StateTransforms.Model.CustomModelProperties, { properties: [] });
root = root.apply(StateTransforms.Model.CustomModelProperties);
}
root = root.apply(StateTransforms.Model.StructureAssemblyFromModel);
complexRepresentation(root);
const structure = root.apply(StateTransforms.Model.StructureAssemblyFromModel);
complexRepresentation(ctx, structure);
return root.getTree();
}
function complexRepresentation(root: StateTreeBuilder.To<PluginStateObject.Molecule.Structure>) {
function complexRepresentation(ctx: PluginContext, root: StateTreeBuilder.To<PluginStateObject.Molecule.Structure>) {
root.apply(StateTransforms.Model.StructureComplexElement, { type: 'atomic-sequence' })
.apply(StateTransforms.Representation.StructureRepresentation3D, {
type: { name: 'cartoon', params: PD.getDefaultValues(CartoonParams) },
colorTheme: { name: 'polymer-id', params: PD.getDefaultValues(PolymerIdColorThemeParams) },
sizeTheme: { name: 'uniform', params: PD.getDefaultValues(UniformSizeThemeParams) },
});
.apply(StateTransforms.Representation.StructureRepresentation3D,
StructureRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'cartoon'));
root.apply(StateTransforms.Model.StructureComplexElement, { type: 'atomic-het' })
.apply(StateTransforms.Representation.StructureRepresentation3D, {
type: { name: 'ball-and-stick', params: PD.getDefaultValues(BallAndStickParams) },
colorTheme: { name: 'element-symbol', params: PD.getDefaultValues(ElementSymbolColorThemeParams) },
sizeTheme: { name: 'uniform', params: PD.getDefaultValues(UniformSizeThemeParams) },
});
.apply(StateTransforms.Representation.StructureRepresentation3D,
StructureRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'ball-and-stick'));
root.apply(StateTransforms.Model.StructureComplexElement, { type: 'water' })
.apply(StateTransforms.Representation.StructureRepresentation3D, {
type: { name: 'ball-and-stick', params: { ...PD.getDefaultValues(BallAndStickParams), alpha: 0.51 } },
colorTheme: { name: 'element-symbol', params: PD.getDefaultValues(ElementSymbolColorThemeParams) },
sizeTheme: { name: 'uniform', params: PD.getDefaultValues(UniformSizeThemeParams) },
})
.apply(StateTransforms.Representation.StructureRepresentation3D,
StructureRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'ball-and-stick', { alpha: 0.51 }));
root.apply(StateTransforms.Model.StructureComplexElement, { type: 'spheres' })
.apply(StateTransforms.Representation.StructureRepresentation3D, {
type: { name: 'spacefill', params: { ...PD.getDefaultValues(SpacefillParams) } },
colorTheme: { name: 'polymer-id', params: PD.getDefaultValues(PolymerIdColorThemeParams) },
sizeTheme: { name: 'physical', params: PD.getDefaultValues(PhysicalSizeThemeParams) },
})
.apply(StateTransforms.Representation.StructureRepresentation3D,
StructureRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'spacefill'));
}
export const CreateComplexRepresentation = StateAction.build({
display: { name: 'Create Complex', description: 'Split the structure into Sequence/Water/Ligands/... ' },
from: PluginStateObject.Molecule.Structure
})(({ ref, state }) => {
})(({ ref, state }, ctx: PluginContext) => {
const root = state.build().to(ref);
complexRepresentation(root);
complexRepresentation(ctx, root);
return state.update(root.getTree());
});
......
......@@ -14,16 +14,31 @@ import { ParamDefinition as PD } from 'mol-util/param-definition';
import { createTheme } from 'mol-theme/theme';
import { BuiltInStructureRepresentationsName } from 'mol-repr/structure/registry';
import { Structure } from 'mol-model/structure';
import { UnitsMeshParams } from 'mol-repr/structure/units-visual';
export namespace StructureRepresentation3DHelpers {
export function getDefaultParams(ctx: PluginContext, name: BuiltInStructureRepresentationsName, structure: Structure): Transformer.Params<StructureRepresentation3D> {
export function getDefaultParams(ctx: PluginContext, name: BuiltInStructureRepresentationsName, structure: Structure, meshParams?: Partial<PD.Values<UnitsMeshParams>>): Transformer.Params<StructureRepresentation3D> {
const type = ctx.structureRepresentation.registry.get(name);
const themeDataCtx = { structure };
const colorParams = ctx.structureRepresentation.themeCtx.colorThemeRegistry.get(type.defaultColorTheme).getParams(themeDataCtx);
const sizeParams = ctx.structureRepresentation.themeCtx.sizeThemeRegistry.get(type.defaultSizeTheme).getParams(themeDataCtx)
return ({
type: { name, params: type.defaultValues },
type: { name, params: meshParams ? { ...type.defaultValues, ...meshParams } : type.defaultValues },
colorTheme: { name: type.defaultColorTheme, params: PD.getDefaultValues(colorParams) },
sizeTheme: { name: type.defaultSizeTheme, params: PD.getDefaultValues(sizeParams) }
})
}
export function getDefaultParamsStatic(ctx: PluginContext, name: BuiltInStructureRepresentationsName, meshParams?: Partial<PD.Values<UnitsMeshParams>>): Transformer.Params<StructureRepresentation3D> {
const type = ctx.structureRepresentation.registry.get(name);
// TODO: there should be "static default properties" for the themes.
const themeDataCtx = { };
const colorParams = ctx.structureRepresentation.themeCtx.colorThemeRegistry.get(type.defaultColorTheme).getParams(themeDataCtx);
const sizeParams = ctx.structureRepresentation.themeCtx.sizeThemeRegistry.get(type.defaultSizeTheme).getParams(themeDataCtx)
return ({
type: { name, params: meshParams ? { ...type.defaultValues, ...meshParams } : type.defaultValues },
colorTheme: { name: type.defaultColorTheme, params: PD.getDefaultValues(colorParams) },
sizeTheme: { name: type.defaultSizeTheme, params: PD.getDefaultValues(sizeParams) }
})
......
......@@ -18,6 +18,7 @@ import { StateActionManager } from './action/manager';
import { TransientTree } from './tree/transient';
import { LogEntry } from 'mol-util/log-entry';
import { now, formatTimespan } from 'mol-util/now';
import { ParamDefinition } from 'mol-util/param-definition';
export { State }
......@@ -498,6 +499,16 @@ async function updateSubtree(ctx: UpdateContext, root: Ref) {
}
}
function resolveDefaultParams(ctx: UpdateContext, transform: Transform, src: StateObject) {
const prms = transform.transformer.definition.params;
const defaults = prms
? ParamDefinition.getDefaultValues(prms(src, ctx.parent.globalContext))
: { };
// TODO: this should probably be resolved each time separately the transform is applied.
// the params should be cached in the cell?
(transform.params as any) = defaults;
}
async function updateNode(ctx: UpdateContext, currentRef: Ref): Promise<UpdateNodeResult> {
const { oldTree, tree } = ctx;
const current = ctx.cells.get(currentRef)!;
......@@ -514,6 +525,10 @@ async function updateNode(ctx: UpdateContext, currentRef: Ref): Promise<UpdateNo
const parent = parentCell.obj!;
current.sourceRef = parentCell.transform.ref;
if (!transform.params) {
resolveDefaultParams(ctx, transform, parent);
}
if (!oldTree.transforms.has(currentRef)) {
const obj = await createObject(ctx, currentRef, transform.transformer, parent, transform.params);
current.obj = obj;
......
......@@ -40,7 +40,7 @@ export namespace Transform {
transformer,
props: (options && options.props) || { },
ref,
params: params || {} as any,
params: params as any,
version: UUID.create22()
}
}
......
......@@ -51,6 +51,12 @@ namespace StateTreeBuilder {
export class To<A extends StateObject> implements StateTreeBuilder {
get editInfo() { return this.state.editInfo; }
readonly ref: Transform.Ref;
/**
* Apply the transformed to the parent node
* If no params are specified (params <- undefined), default params are lazily resolved.
*/
apply<T extends Transformer<A, any, any>>(tr: T, params?: Transformer.Params<T>, options?: Partial<Transform.Options>, initialCellState?: Partial<StateObjectCell.State>): To<Transformer.To<T>> {
const t = tr.apply(this.ref, params, options);
this.state.tree.add(t, initialCellState);
......@@ -84,7 +90,8 @@ namespace StateTreeBuilder {
getTree(): StateTree { return this.state.tree.asImmutable(); }
constructor(private state: State, private ref: Transform.Ref, private root: Root) {
constructor(private state: State, ref: Transform.Ref, private root: Root) {
this.ref = ref;
if (!this.state.tree.transforms.has(ref)) {
throw new Error(`Could not find node '${ref}'.`);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment