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

plugin/state: helpers & fixes

parent ae484443
Branches
No related tags found
No related merge requests found
...@@ -227,24 +227,28 @@ const DownloadStructure = StateAction.build({ ...@@ -227,24 +227,28 @@ const DownloadStructure = StateAction.build({
await state.transaction(async () => { await state.transaction(async () => {
if (downloadParams.length > 0 && asTrajectory) { if (downloadParams.length > 0 && asTrajectory) {
const data = await plugin.builders.data.downloadBlob({ const blob = await plugin.builders.data.downloadBlob({
sources: downloadParams.map((src, i) => ({ id: '' + i, url: src.url, isBinary: src.isBinary })), sources: downloadParams.map((src, i) => ({ id: '' + i, url: src.url, isBinary: src.isBinary })),
maxConcurrency: 6 maxConcurrency: 6
}, { state: { isGhost: true } }); }, { state: { isGhost: true } });
const traj = await plugin.builders.structure.parseTrajectory(data, { const { structure } = await plugin.builders.structure.parseStructure({
formats: downloadParams.map((_, i) => ({ id: '' + i, format: 'cif' as 'cif' })) blob,
blobParams: { formats: downloadParams.map((_, i) => ({ id: '' + i, format: 'cif' as 'cif' })) },
modelProperties: supportProps,
structureProperties: supportProps
}); });
const { model } = await plugin.builders.structure.createModel(traj, { properties: supportProps });
const { structure } = await plugin.builders.structure.createStructure(model, { structure: src.params.structure.type, properties: supportProps });
if (createRepr) { if (createRepr) {
await plugin.builders.representation.structurePreset(structure, 'auto'); await plugin.builders.representation.structurePreset(structure, 'auto');
} }
} else { } else {
for (const download of downloadParams) { for (const download of downloadParams) {
const data = await plugin.builders.data.download(download, { state: { isGhost: true } }); const data = await plugin.builders.data.download(download, { state: { isGhost: true } });
const traj = await plugin.builders.structure.parseTrajectory(data, format); const { structure } = await plugin.builders.structure.parseStructure({
const { model } = await plugin.builders.structure.createModel(traj, { properties: supportProps }); data,
const { structure } = await plugin.builders.structure.createStructure(model, { structure: src.params.structure.type, properties: supportProps }); dataFormat: format,
modelProperties: supportProps,
structureProperties: supportProps
});
if (createRepr) { if (createRepr) {
await plugin.builders.representation.structurePreset(structure, 'auto'); await plugin.builders.representation.structurePreset(structure, 'auto');
} }
...@@ -366,10 +370,7 @@ export const EnableModelCustomProps = StateAction.build({ ...@@ -366,10 +370,7 @@ export const EnableModelCustomProps = StateAction.build({
isApplicable(a, t, ctx: PluginContext) { isApplicable(a, t, ctx: PluginContext) {
return t.transformer !== CustomModelProperties; return t.transformer !== CustomModelProperties;
} }
})(({ ref, params, state }, ctx: PluginContext) => { })(({ ref, params }, ctx: PluginContext) => ctx.builders.structure.insertModelProperties(ref, params));
const root = state.build().to(ref).insert(CustomModelProperties, params);
return state.updateTree(root);
});
export const EnableStructureCustomProps = StateAction.build({ export const EnableStructureCustomProps = StateAction.build({
display: { name: 'Custom Structure Properties', description: 'Enable parameters for custom properties of the structure.' }, display: { name: 'Custom Structure Properties', description: 'Enable parameters for custom properties of the structure.' },
...@@ -380,10 +381,7 @@ export const EnableStructureCustomProps = StateAction.build({ ...@@ -380,10 +381,7 @@ export const EnableStructureCustomProps = StateAction.build({
isApplicable(a, t, ctx: PluginContext) { isApplicable(a, t, ctx: PluginContext) {
return t.transformer !== CustomStructureProperties; return t.transformer !== CustomStructureProperties;
} }
})(({ ref, params, state }, ctx: PluginContext) => { })(({ ref, params }, ctx: PluginContext) => ctx.builders.structure.insertStructureProperties(ref, params));
const root = state.build().to(ref).insert(CustomStructureProperties, params);
return state.updateTree(root);
});
export const TransformStructureConformation = StateAction.build({ export const TransformStructureConformation = StateAction.build({
display: { name: 'Transform Conformation' }, display: { name: 'Transform Conformation' },
......
...@@ -64,6 +64,39 @@ export class StructureBuilder { ...@@ -64,6 +64,39 @@ export class StructureBuilder {
return trajectory.selector; return trajectory.selector;
} }
async parseStructure(params: {
data?: StateObjectRef<SO.Data.Binary | SO.Data.String>,
dataFormat?: TrajectoryFormat,
blob?: StateObjectRef<SO.Data.Blob>
blobParams?: StateTransformer.Params<StateTransforms['Data']['ParseBlob']>,
model?: StateTransformer.Params<StateTransforms['Model']['ModelFromTrajectory']>,
modelProperties?: boolean | StateTransformer.Params<StateTransforms['Model']['CustomModelProperties']>,
structure?: RootStructureDefinition.Params,
structureProperties?: boolean | StateTransformer.Params<StateTransforms['Model']['CustomStructureProperties']>
}) {
const trajectory = params.data
? await this.parseTrajectory(params.data, params.dataFormat! || 'cif')
: await this.parseTrajectoryBlob(params.blob!, params.blobParams!);
const model = await this.createModel(trajectory, params.model);
const modelProperties = !!params.modelProperties
? await this.insertModelProperties(model, typeof params?.modelProperties !== 'boolean' ? params?.modelProperties : void 0) : void 0;
const structure = await this.createStructure(modelProperties || model, params.structure);
const structureProperties = !!params.structureProperties
? await this.insertStructureProperties(structure, typeof params?.structureProperties !== 'boolean' ? params?.structureProperties : void 0) : void 0;
return {
trajectory,
model: modelProperties || model,
modelBase: model,
modelProperties,
structure: structureProperties || structure,
structureBase: structure,
structureProperties
};
}
async parseTrajectory(data: StateObjectRef<SO.Data.Binary | SO.Data.String>, format: TrajectoryFormat): Promise<StateObjectSelector<SO.Molecule.Trajectory>> async parseTrajectory(data: StateObjectRef<SO.Data.Binary | SO.Data.String>, format: TrajectoryFormat): Promise<StateObjectSelector<SO.Molecule.Trajectory>>
async parseTrajectory(blob: StateObjectRef<SO.Data.Blob>, params: StateTransformer.Params<StateTransforms['Data']['ParseBlob']>): Promise<StateObjectSelector<SO.Molecule.Trajectory>> async parseTrajectory(blob: StateObjectRef<SO.Data.Blob>, params: StateTransformer.Params<StateTransforms['Data']['ParseBlob']>): Promise<StateObjectSelector<SO.Molecule.Trajectory>>
async parseTrajectory(data: StateObjectRef, params: any) { async parseTrajectory(data: StateObjectRef, params: any) {
...@@ -79,43 +112,57 @@ export class StructureBuilder { ...@@ -79,43 +112,57 @@ export class StructureBuilder {
} }
} }
async createModel(trajectory: StateObjectRef<SO.Molecule.Trajectory>, params?: { async createModel(trajectory: StateObjectRef<SO.Molecule.Trajectory>, params?: StateTransformer.Params<StateTransforms['Model']['ModelFromTrajectory']>) {
model?: StateTransformer.Params<StateTransforms['Model']['ModelFromTrajectory']>,
properties?: boolean | StateTransformer.Params<StateTransforms['Model']['CustomModelProperties']>
}) {
const state = this.dataState; const state = this.dataState;
const model = state.build().to(trajectory) const model = state.build().to(trajectory)
.apply(StateTransforms.Model.ModelFromTrajectory, params?.model || void 0, { tags: StructureBuilderTags.Model }); .apply(StateTransforms.Model.ModelFromTrajectory, params || { modelIndex: 0 }, { tags: StructureBuilderTags.Model });
const props = !!params?.properties // const props = !!params?.properties
? model.apply(StateTransforms.Model.CustomModelProperties, typeof params?.properties !== 'boolean' ? params?.properties : void 0, { tags: StructureBuilderTags.ModelProperties, isDecorator: true }) // ? model.apply(StateTransforms.Model.CustomModelProperties, typeof params?.properties !== 'boolean' ? params?.properties : void 0, { tags: StructureBuilderTags.ModelProperties, isDecorator: true })
: void 0; // : void 0;
await this.plugin.runTask(this.dataState.updateTree(model, { revertOnError: true })); await this.plugin.runTask(this.dataState.updateTree(model, { revertOnError: true }));
const modelSelector = model.selector, propertiesSelector = props?.selector; return model.selector;
return { model: propertiesSelector || modelSelector, index: modelSelector, properties: propertiesSelector }; // const modelSelector = model.selector, propertiesSelector = props?.selector;
// return { model: propertiesSelector || modelSelector, index: modelSelector, properties: propertiesSelector };
} }
async createStructure(model: StateObjectRef<SO.Molecule.Model>, params?: { async insertModelProperties(model: StateObjectRef<SO.Molecule.Model>, params?: StateTransformer.Params<StateTransforms['Model']['CustomModelProperties']>) {
structure?: RootStructureDefinition.Params, const state = this.dataState;
properties?: boolean | StateTransformer.Params<StateTransforms['Model']['CustomStructureProperties']> const props = state.build().to(model)
}) { .apply(StateTransforms.Model.CustomModelProperties, params, { tags: StructureBuilderTags.ModelProperties, isDecorator: true });
await this.plugin.runTask(this.dataState.updateTree(props, { revertOnError: true }));
return props.selector;
}
async createStructure(model: StateObjectRef<SO.Molecule.Model>, params?: RootStructureDefinition.Params) {
const state = this.dataState; const state = this.dataState;
const structure = state.build().to(model) const structure = state.build().to(model)
.apply(StateTransforms.Model.StructureFromModel, { type: params?.structure || { name: 'assembly', params: { } } }, { tags: StructureBuilderTags.Structure }); .apply(StateTransforms.Model.StructureFromModel, { type: params || { name: 'assembly', params: { } } }, { tags: StructureBuilderTags.Structure });
const props = !!params?.properties // const props = !!params?.properties
? structure.apply(StateTransforms.Model.CustomStructureProperties, typeof params?.properties !== 'boolean' ? params?.properties : void 0, { tags: StructureBuilderTags.StructureProperties, isDecorator: true }) // ? structure.apply(StateTransforms.Model.CustomStructureProperties, typeof params?.properties !== 'boolean' ? params?.properties : void 0, { tags: StructureBuilderTags.StructureProperties, isDecorator: true })
: void 0; // : void 0;
await this.plugin.runTask(this.dataState.updateTree(structure, { revertOnError: true })); await this.plugin.runTask(this.dataState.updateTree(structure, { revertOnError: true }));
const structureSelector = structure.selector, propertiesSelector = props?.selector; return structure.selector;
return { structure: propertiesSelector || structureSelector, definition: structureSelector, properties: propertiesSelector }; // const structureSelector = structure.selector, propertiesSelector = props?.selector;
// return { structure: propertiesSelector || structureSelector, definition: structureSelector, properties: propertiesSelector };
}
async insertStructureProperties(structure: StateObjectRef<SO.Molecule.Structure>, params?: StateTransformer.Params<StateTransforms['Model']['CustomStructureProperties']>) {
const state = this.dataState;
const props = state.build().to(structure)
.apply(StateTransforms.Model.CustomStructureProperties, params, { tags: StructureBuilderTags.StructureProperties, isDecorator: true });
await this.plugin.runTask(this.dataState.updateTree(props, { revertOnError: true }));
return props.selector;
} }
/** returns undefined if the component is empty/null */ /** returns undefined if the component is empty/null */
......
...@@ -247,7 +247,7 @@ export class CurrentObject extends PluginUIComponent { ...@@ -247,7 +247,7 @@ export class CurrentObject extends PluginUIComponent {
let decorators: JSX.Element[] | undefined = decoratorChain.length > 1 ? [] : void 0; let decorators: JSX.Element[] | undefined = decoratorChain.length > 1 ? [] : void 0;
for (let i = decoratorChain.length - 2; i >= 0; i--) { for (let i = decoratorChain.length - 2; i >= 0; i--) {
const d = decoratorChain[i]; const d = decoratorChain[i];
decorators!.push(<ExpandGroup header={d.transform.transformer.definition.display.name}> decorators!.push(<ExpandGroup key={`${d.transform.transformer.id}-${i}`} header={d.transform.transformer.definition.display.name}>
<UpdateTransformControl state={current.state} transform={d.transform} customHeader='none' /> <UpdateTransformControl state={current.state} transform={d.transform} customHeader='none' />
</ExpandGroup>); </ExpandGroup>);
} }
......
...@@ -146,8 +146,8 @@ export class StateObjectSelector<S extends StateObject = StateObject, T extends ...@@ -146,8 +146,8 @@ export class StateObjectSelector<S extends StateObject = StateObject, T extends
/** Create a new build and apply update or use the provided one. */ /** Create a new build and apply update or use the provided one. */
update(params: StateTransformer.Params<T>, builder?: StateBuilder.Root | StateBuilder.To<any>): StateBuilder update(params: StateTransformer.Params<T>, builder?: StateBuilder.Root | StateBuilder.To<any>): StateBuilder
update(params: (old: StateTransformer.Params<T>) => StateTransformer.Params<T>, builder?: StateBuilder.Root | StateBuilder.To<any>): StateBuilder update(params: (old: StateTransformer.Params<T>) => StateTransformer.Params<T> | void, builder?: StateBuilder.Root | StateBuilder.To<any>): StateBuilder
update(params: ((old: StateTransformer.Params<T>) => StateTransformer.Params<T>) | StateTransformer.Params<T>, builder?: StateBuilder.Root | StateBuilder.To<any>): StateBuilder { update(params: ((old: StateTransformer.Params<T>) => StateTransformer.Params<T> | void) | StateTransformer.Params<T>, builder?: StateBuilder.Root | StateBuilder.To<any>): StateBuilder {
if (!this.state) throw new Error(`To use update() from StateObjectSelector, 'state' must be defined.`); if (!this.state) throw new Error(`To use update() from StateObjectSelector, 'state' must be defined.`);
if (!builder) builder = this.state.build(); if (!builder) builder = this.state.build();
(builder || this.state.build()).to(this).update(params); (builder || this.state.build()).to(this).update(params);
......
...@@ -114,13 +114,7 @@ namespace StateBuilder { ...@@ -114,13 +114,7 @@ namespace StateBuilder {
* Apply the transformed to the parent node * Apply the transformed to the parent node
* If no params are specified (params <- undefined), default params are lazily resolved. * If no params are specified (params <- undefined), default params are lazily resolved.
*/ */
apply<T extends StateTransformer<A, any, any>>(tr: T, params?: StateTransformer.Params<T>, options?: Partial<StateTransform.Options>): To<StateTransformer.To<T>, T> { apply<T extends StateTransformer<A, any, any>>(tr: T, params?: StateTransformer.Params<T>, options?: Partial<StateTransform.Options>): To<StateTransformer.To<T>, T> {const t = tr.apply(this.ref, params, options);
if (options?.isDecorator) {
const children = this.state.tree.children.get(this.ref);
if (children.size > 0) throw new Error('Decorators can only be applied to childless nodes.');
}
const t = tr.apply(this.ref, params, options);
this.state.tree.add(t); this.state.tree.add(t);
this.editInfo.count++; this.editInfo.count++;
this.editInfo.lastUpdate = t.ref; this.editInfo.lastUpdate = t.ref;
...@@ -231,8 +225,8 @@ namespace StateBuilder { ...@@ -231,8 +225,8 @@ namespace StateBuilder {
} }
} }
update<T extends StateTransformer<any, A, any>>(transformer: T, params: (old: StateTransformer.Params<T>) => StateTransformer.Params<T>): Root update<T extends StateTransformer<any, A, any>>(transformer: T, params: (old: StateTransformer.Params<T>) => StateTransformer.Params<T> | void): Root
update(params: StateTransformer.Params<T> | ((old: StateTransformer.Params<T>) => StateTransformer.Params<T>)): Root update(params: StateTransformer.Params<T> | ((old: StateTransformer.Params<T>) => StateTransformer.Params<T> | void)): Root
update<T extends StateTransformer<any, A, any>>(paramsOrTransformer: T | any, provider?: (old: StateTransformer.Params<T>) => StateTransformer.Params<T>) { update<T extends StateTransformer<any, A, any>>(paramsOrTransformer: T | any, provider?: (old: StateTransformer.Params<T>) => StateTransformer.Params<T>) {
let params: any; let params: any;
if (provider) { if (provider) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment