diff --git a/src/extensions/membrane-orientation/behavior.ts b/src/extensions/membrane-orientation/behavior.ts
index ea097071964839ba4777248bff2ec894acbe3220..90c1dae568e8e6e51c49a514d2e297611c1ee46c 100644
--- a/src/extensions/membrane-orientation/behavior.ts
+++ b/src/extensions/membrane-orientation/behavior.ts
@@ -8,11 +8,13 @@
import { ParamDefinition as PD } from '../../mol-util/param-definition';
import { StructureRepresentationPresetProvider, PresetStructureRepresentations } from '../../mol-plugin-state/builder/structure/representation-preset';
import { MembraneOrientationProvider, MembraneOrientation } from './membrane-orientation';
-import { StateObjectRef } from '../../mol-state';
+import { StateObjectRef, StateAction, StateTransformer, StateTransform } from '../../mol-state';
import { Task } from '../../mol-task';
import { PluginBehavior } from '../../mol-plugin/behavior';
-import { MembraneOrientationRepresentationProvider } from './representation';
+import { MembraneOrientationRepresentationProvider, MembraneOrientationParams, MembraneOrientationRepresentation } from './representation';
import { HydrophobicityColorThemeProvider } from '../../mol-theme/color/hydrophobicity';
+import { PluginStateObject, PluginStateTransform } from '../../mol-plugin-state/objects';
+import { PluginContext } from '../../mol-plugin/context';
export const MembraneOrientationData = PluginBehavior.create<{ autoAttach: boolean }>({
name: 'membrane-orientation-prop',
@@ -25,10 +27,10 @@ export const MembraneOrientationData = PluginBehavior.create<{ autoAttach: boole
private provider = MembraneOrientationProvider
register(): void {
+ console.log('beh @ register');
+ this.ctx.state.data.actions.add(InitMembraneOrientation3D);
this.ctx.customStructureProperties.register(this.provider, this.params.autoAttach);
- this.ctx.representation.structure.themes.colorThemeRegistry.add(HydrophobicityColorThemeProvider);
-
this.ctx.representation.structure.registry.add(MembraneOrientationRepresentationProvider);
this.ctx.query.structure.registry.add(MembraneOrientation.isTransmembrane);
@@ -43,10 +45,9 @@ export const MembraneOrientationData = PluginBehavior.create<{ autoAttach: boole
}
unregister() {
+ this.ctx.state.data.actions.remove(InitMembraneOrientation3D);
this.ctx.customStructureProperties.unregister(this.provider.descriptor.name);
- this.ctx.representation.structure.themes.colorThemeRegistry.remove(HydrophobicityColorThemeProvider);
-
this.ctx.representation.structure.registry.remove(MembraneOrientationRepresentationProvider);
this.ctx.query.structure.registry.remove(MembraneOrientation.isTransmembrane);
@@ -58,13 +59,75 @@ export const MembraneOrientationData = PluginBehavior.create<{ autoAttach: boole
})
});
+export const InitMembraneOrientation3D = StateAction.build({
+ display: {
+ name: 'Membrane Orientation',
+ description: 'Initialize Membrane Orientation planes and rims. Data calculated with ANVIL algorithm.'
+ },
+ from: PluginStateObject.Molecule.Structure,
+ isApplicable: (a) => MembraneOrientationProvider.isApplicable(a.data)
+})(({ a, ref, state }, plugin: PluginContext) => Task.create('Init Membrane Orientation', async ctx => {
+ try {
+ const propCtx = { runtime: ctx, assetManager: plugin.managers.asset };
+ await MembraneOrientationProvider.attach(propCtx, a.data);
+ } catch(e) {
+ plugin.log.error(`Membrane Orientation: ${e}`);
+ return;
+ }
+ const tree = state.build().to(ref)
+ .applyOrUpdateTagged('membrane-orientation-3d', MembraneOrientation3D);
+ await state.updateTree(tree).runInContext(ctx);
+}));
+
+export { MembraneOrientation3D };
+
+type MembraneOrientation3D = typeof MembraneOrientation3D
+const MembraneOrientation3D = PluginStateTransform.BuiltIn({
+ name: 'membrane-orientation-3d',
+ display: {
+ name: 'Membrane Orientation',
+ description: 'Membrane Orientation planes and rims. Data calculated with ANVIL algorithm.'
+ },
+ from: PluginStateObject.Molecule.Structure,
+ to: PluginStateObject.Shape.Representation3D,
+ params: (a) => {
+ return {
+ ...MembraneOrientationParams,
+ };
+ }
+})({
+ canAutoUpdate({ oldParams, newParams }) {
+ return true;
+ },
+ apply({ a, params }, plugin: PluginContext) {
+ return Task.create('Membrane Orientation', async ctx => {
+ await MembraneOrientationProvider.attach({ runtime: ctx, assetManager: plugin.managers.asset }, a.data);
+ const repr = MembraneOrientationRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => MembraneOrientationParams);
+ await repr.createOrUpdate(params, a.data).runInContext(ctx);
+ return new PluginStateObject.Shape.Representation3D({ repr, source: a });
+ });
+ },
+ update({ a, b, newParams }, plugin: PluginContext) {
+ return Task.create('Membrane Orientation', async ctx => {
+ await MembraneOrientationProvider.attach({ runtime: ctx, assetManager: plugin.managers.asset }, a.data);
+ const props = { ...b.data.repr.props, ...newParams };
+ await b.data.repr.createOrUpdate(props, a.data).runInContext(ctx);
+ return StateTransformer.UpdateResult.Updated;
+ });
+ },
+ isApplicable(a) {
+ return MembraneOrientationProvider.isApplicable(a.data);
+ }
+});
+
export const MembraneOrientationPreset = StructureRepresentationPresetProvider({
id: 'preset-membrane-orientation',
display: {
name: 'Membrane Orientation', group: 'Annotation',
- description: 'Initialize orientation of membrane layers. Data calculated with ANVIL algorithm.' // TODO add ' or obtained via RCSB PDB'
+ description: 'Shows orientation of membrane layers. Data calculated with ANVIL algorithm.' // TODO add ' or obtained via RCSB PDB'
},
isApplicable(a) {
+ console.log(`present applicable: ${MembraneOrientationProvider.isApplicable(a.data)}`);
return MembraneOrientationProvider.isApplicable(a.data);
},
params: () => StructureRepresentationPresetProvider.CommonParams,
@@ -73,11 +136,24 @@ export const MembraneOrientationPreset = StructureRepresentationPresetProvider({
const structure = structureCell?.obj?.data;
if (!structureCell || !structure) return {};
- await plugin.runTask(Task.create('Membrane Orientation', async runtime => {
- await MembraneOrientationProvider.attach({ runtime, assetManager: plugin.managers.asset }, structure);
- }));
+ if (!MembraneOrientationProvider.get(structure).value) {
+ await plugin.runTask(Task.create('Membrane Orientation', async runtime => {
+ console.log('present: attaching');
+ await MembraneOrientationProvider.attach({ runtime, assetManager: plugin.managers.asset }, structure);
+ }));
+ }
+ const membraneOrientation = await tryCreateMembraneOrientation(plugin, structureCell);
const colorTheme = HydrophobicityColorThemeProvider.name as any;
- return await PresetStructureRepresentations.auto.apply(ref, { ...params, theme: { globalName: colorTheme, focus: { name: colorTheme } } }, plugin);
+ const preset = await PresetStructureRepresentations.auto.apply(ref, { ...params, theme: { globalName: colorTheme, focus: { name: colorTheme } } }, plugin);
+
+ return { components: preset.components, representations: { ...preset.representations, membraneOrientation } };
}
});
+
+export function tryCreateMembraneOrientation(plugin: PluginContext, structure: StateObjectRef<PluginStateObject.Molecule.Structure>, params?: StateTransformer.Params<MembraneOrientation3D>, initialState?: Partial<StateTransform.State>) {
+ const state = plugin.state.data;
+ const membraneOrientation = state.build().to(structure)
+ .applyOrUpdateTagged('membrane-orientation-3d', MembraneOrientation3D, params, { state: initialState });
+ return membraneOrientation.commit({ revertOnError: true });
+}
diff --git a/src/extensions/membrane-orientation/representation.ts b/src/extensions/membrane-orientation/representation.ts
index 76b4cba0cf56ec0546ed92a1d25727f2651a753b..b8d4e1922332f0c1d8e18a608eec2fd79d25bec8 100644
--- a/src/extensions/membrane-orientation/representation.ts
+++ b/src/extensions/membrane-orientation/representation.ts
@@ -74,11 +74,13 @@ export type MembraneOrientationParams = typeof MembraneOrientationParams
export type MembraneOrientationProps = PD.Values<MembraneOrientationParams>
export function getMembraneOrientationParams(ctx: ThemeRegistryContext, structure: Structure) {
+ console.log('rep @ getParams');
return PD.clone(MembraneOrientationParams);
}
export type MembraneOrientationRepresentation = StructureRepresentation<MembraneOrientationParams>
export function MembraneOrientationRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, MembraneOrientationParams>): MembraneOrientationRepresentation {
+ console.log('rep @ create');
return Representation.createMulti('Membrane Orientation', ctx, getParams, StructureRepresentationStateBuilder, MembraneOrientationVisuals as unknown as Representation.Def<Structure, MembraneOrientationParams>);
}
@@ -95,6 +97,7 @@ export const MembraneOrientationRepresentationProvider = StructureRepresentation
});
function getBilayerRims(ctx: RuntimeContext, data: Structure, props: BilayerRimsProps): Shape<Lines> {
+ console.log('rims');
const { p1, p2, centroid, normal, radius } = MembraneOrientationProvider.get(data).value!;
const scaledRadius = props.radiusFactor * radius;
const builder = LinesBuilder.create(128, 64);
@@ -131,6 +134,7 @@ function getCircle(p: Vec3, centroid: Vec3, normal: Vec3, radius: number) {
}
function getBilayerPlanes(ctx: RuntimeContext, data: Structure, props: BilayerPlanesProps, shape?: Shape<Mesh>): Shape<Mesh> {
+ console.log('planes');
const { p1, p2, centroid, normal, radius } = MembraneOrientationProvider.get(data).value!;
const state = MeshBuilder.createState(128, 64, shape && shape.geometry);
const scaledRadius = props.radiusFactor * radius;