Kaynağa Gözat

membrane orientation representation

JonStargaryen 4 yıl önce
ebeveyn
işleme
e82918db6a

+ 80 - 0
src/extensions/membrane-orientation/representation.ts

@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ * @author Sebastian Bittrich <sebastian.bittrich@rcsb.org>
+ */
+
+import { ParamDefinition as PD } from '../../mol-util/param-definition';
+import { Vec3 } from '../../mol-math/linear-algebra';
+import { Representation, RepresentationContext, RepresentationParamsGetter } from '../../mol-repr/representation';
+import { Structure } from '../../mol-model/structure';
+import { Spheres } from '../../mol-geo/geometry/spheres/spheres';
+import { SpheresBuilder } from '../../mol-geo/geometry/spheres/spheres-builder';
+import { MembraneOrientationProvider } from '../../mol-model-props/computed/membrane-orientation';
+import { StructureRepresentationProvider, StructureRepresentation, StructureRepresentationStateBuilder } from '../../mol-repr/structure/representation';
+import { MembraneOrientation } from '../../mol-model/structure/model/properties/membrane-orientation';
+import { ThemeRegistryContext } from '../../mol-theme/theme';
+import { ShapeRepresentation } from '../../mol-repr/shape/representation';
+import { Shape } from '../../mol-model/shape';
+import { ColorNames } from '../../mol-util/color/names';
+import { RuntimeContext } from '../../mol-task';
+
+const MembraneOrientationParams = {
+    ...Spheres.Params,
+    color: PD.Color(ColorNames.orange),
+    density: PD.Numeric(1, { min: 0.1, max: 10, step: 0.1 })
+};
+export type MembraneOrientationParams = typeof MembraneOrientationParams
+export type MembraneOrientationProps = PD.Values<MembraneOrientationParams>
+
+export function getMembraneOrientationParams(ctx: ThemeRegistryContext, structure: Structure) {
+    return PD.clone(MembraneOrientationParams);
+}
+
+export type MembraneOrientationRepresentation = StructureRepresentation<MembraneOrientationParams>
+export function MembraneOrientationRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, MembraneOrientationParams>): MembraneOrientationRepresentation {
+    return Representation.createMulti('Membrane Orientation', ctx, getParams, StructureRepresentationStateBuilder, MembraneOrientationVisuals as unknown as Representation.Def<Structure, MembraneOrientationParams>);
+}
+
+const MembraneOrientationVisuals = {
+    'membrane-orientation': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<MembraneOrientation, MembraneOrientationParams>) => ShapeRepresentation(getMembraneSpheres, Spheres.Utils),
+};
+
+
+export const MembraneOrientationRepresentationProvider = StructureRepresentationProvider({
+    name: 'membrane-orientation',
+    label: 'Membrane Orientation',
+    description: 'Displays a grid of points representing membrane layers.',
+    factory: MembraneOrientationRepresentation,
+    getParams: getMembraneOrientationParams,
+    defaultValues: PD.getDefaultValues(MembraneOrientationParams),
+    defaultColorTheme: { name: 'uniform' },
+    defaultSizeTheme: { name: 'uniform' },
+    isApplicable: (structure: Structure) => structure.elementCount > 0
+});
+
+function getMembraneSpheres(ctx: RuntimeContext, data: Structure, props: MembraneOrientationProps) {
+    const { density } = props;
+    const { radius, p1, p2, normal } = MembraneOrientationProvider.get(data).value!;;
+
+    const spheresBuilder = SpheresBuilder.create();
+    createMembraneLayer(spheresBuilder, p1, normal, density, radius);
+    createMembraneLayer(spheresBuilder, p2, normal, density, radius);
+    const getLabel = () => '?'; // TODO
+
+    return Shape.create(name, data, spheresBuilder.getSpheres(), () => props.color, () => 1, getLabel);
+}
+
+function createMembraneLayer(spheresBuilder: SpheresBuilder, point: Vec3, normalVector: Vec3, density: number, radius: number) {
+    const d = -Vec3.dot(normalVector, point);
+    const rep = Vec3();
+    for (let i = -1000, il = 1000; i < il; i += density) {
+        for (let j = -1000, jl = 1000; j < jl; j += density) {
+            Vec3.set(rep, i, j, -(d + i * normalVector[0] + j * normalVector[1]) / normalVector[2]);
+            if (Vec3.squaredDistance(rep, point) < radius) {
+                spheresBuilder.add(rep[0], rep[1], rep[2], 0);
+            }
+        }
+    }
+}

+ 5 - 4
src/mol-model-props/computed/membrane-orientation.ts

@@ -13,9 +13,10 @@ import { CustomPropertyDescriptor } from '../../mol-model/custom-property';
 import { ANVILParams, ANVILProps, computeANVIL } from './membrane-orientation/ANVIL';
 import { AccessibleSurfaceAreaProvider } from './accessible-surface-area';
 import { MembraneOrientation } from '../../mol-model/structure/model/properties/membrane-orientation';
+import { computeOPM } from './membrane-orientation/OPM';
 
 function getMembraneOrientationParams(data?: Structure) {
-    let defaultType = 'anvil' as 'anvil' | 'opm'; // TODO flip - OPM should be default if PDB identifier is known
+    let defaultType = 'anvil' as 'anvil' | 'opm'; // TODO flip - OPM (or some other db-source) should be default if PDB identifier is known
     return {
         type: PD.MappedStatic(defaultType, {
             'opm': PD.EmptyGroup({ label: 'OPM' }),
@@ -42,7 +43,7 @@ export const MembraneOrientationProvider: CustomStructureProperty.Provider<Membr
         const p = { ...PD.getDefaultValues(MembraneOrientationParams), ...props };
         switch (p.type.name) {
             case 'anvil': return { value: await computeAnvil(ctx, data, p.type.params) };
-            case 'opm': return { value: await computeOpm(data) };
+            case 'opm': return { value: await computeOpm(ctx, data) };
         }
     }
 });
@@ -53,6 +54,6 @@ async function computeAnvil(ctx: CustomProperty.Context, data: Structure, props:
     return await computeANVIL(data, p).runInContext(ctx.runtime);
 }
 
-async function computeOpm(structure: Structure): Promise<MembraneOrientation> {
-    throw Error('TODO impl');
+async function computeOpm(ctx: CustomProperty.Context, data: Structure): Promise<MembraneOrientation> {
+    return await computeOPM(data).runInContext(ctx.runtime);
 }

+ 18 - 0
src/mol-model-props/computed/membrane-orientation/OPM.ts

@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Sebastian Bittrich <sebastian.bittrich@rcsb.org>
+ */
+import { Structure } from '../../../mol-model/structure/structure';
+import { Task, RuntimeContext } from '../../../mol-task';
+import { MembraneOrientation } from '../../../mol-model/structure/model/properties/membrane-orientation';
+
+export function computeOPM(structure: Structure) {
+    return Task.create('Parse Membrane Topology', async runtime => {
+        return await calculate(runtime, structure);
+    });
+}
+
+export async function calculate(runtime: RuntimeContext, structure: Structure): Promise<MembraneOrientation> {
+    throw Error('impl me');
+}

+ 17 - 37
src/tests/browser/render-structure.ts

@@ -27,12 +27,7 @@ import { SecondaryStructureProvider } from '../../mol-model-props/computed/secon
 import { SyncRuntimeContext } from '../../mol-task/execution/synchronous';
 import { AssetManager } from '../../mol-util/assets';
 import { MembraneOrientationProvider } from '../../mol-model-props/computed/membrane-orientation';
-import { SpheresBuilder } from '../../mol-geo/geometry/spheres/spheres-builder';
-import { Spheres } from '../../mol-geo/geometry/spheres/spheres';
-import { Color } from '../../mol-util/color';
-import { createRenderObject } from '../../mol-gl/render-object';
-import { MembraneOrientation } from '../../mol-model/structure/model/properties/membrane-orientation';
-import { Vec3 } from '../../mol-math/linear-algebra';
+import { MembraneOrientationRepresentationProvider } from '../../extensions/membrane-orientation/representation';
 
 const parent = document.getElementById('app')!;
 parent.style.width = '100%';
@@ -123,33 +118,8 @@ function getGaussianSurfaceRepr() {
     return GaussianSurfaceRepresentationProvider.factory(reprCtx, GaussianSurfaceRepresentationProvider.getParams);
 }
 
-function getMembraneRepr(structure: Structure, membrane: MembraneOrientation) {
-    const density = 1;
-    const radius = membrane.radius;
-    const spheresBuilder = SpheresBuilder.create();
-    createMembraneLayer(spheresBuilder, membrane.p1, membrane.normal, density, radius);
-    createMembraneLayer(spheresBuilder, membrane.p2, membrane.normal, density, radius);
-    const spheres = spheresBuilder.getSpheres();
-
-    const values = Spheres.Utils.createValuesSimple(spheres, {}, Color(0xCCCCCC), 1);
-    const state = Spheres.Utils.createRenderableState({});
-    const renderObject = createRenderObject('spheres', values, state, -1);
-    console.log(renderObject);
-    const repr = Representation.fromRenderObject('spheres', renderObject);
-    return repr;
-}
-
-function createMembraneLayer(spheresBuilder: SpheresBuilder, point: Vec3, normalVector: Vec3, density: number, radius: number) {
-    const d = -Vec3.dot(normalVector, point);
-    const rep = Vec3();
-    for (let i = -1000, il = 1000; i < il; i += density) {
-        for (let j = -1000, jl = 1000; j < jl; j += density) {
-            Vec3.set(rep, i, j, -(d + i * normalVector[0] + j * normalVector[1]) / normalVector[2]);
-            if (Vec3.squaredDistance(rep, point) < radius) {
-                spheresBuilder.add(rep[0], rep[1], rep[2], 0);
-            }
-        }
-    }
+function getMembraneOrientationRepr() {
+    return MembraneOrientationRepresentationProvider.factory(reprCtx, MembraneOrientationRepresentationProvider.getParams);
 }
 
 async function init() {
@@ -163,9 +133,9 @@ async function init() {
     await SecondaryStructureProvider.attach(ctx, structure);
     console.timeEnd('compute SecondaryStructure');
 
-    console.time('compute Membrane');
+    console.time('compute Membrane Orientation');
     await MembraneOrientationProvider.attach(ctx, structure);
-    console.timeEnd('compute Membrane');
+    console.timeEnd('compute Membrane Orientation');
 
     console.time('compute Interactions');
     await InteractionsProvider.attach(ctx, structure);
@@ -186,7 +156,7 @@ async function init() {
     const ballAndStickRepr = getBallAndStickRepr();
     const molecularSurfaceRepr = getMolecularSurfaceRepr();
     const gaussianSurfaceRepr = getGaussianSurfaceRepr();
-    const membraneRepr = getMembraneRepr(structure, MembraneOrientationProvider.get(structure).value!);
+    const membraneOrientationRepr = getMembraneOrientationRepr();
 
     if (show.cartoon) {
         cartoonRepr.setTheme({
@@ -232,12 +202,22 @@ async function init() {
         console.timeEnd('gaussian surface');
     }
 
+    if (show.membrane) {
+        membraneOrientationRepr.setTheme({
+            color: reprCtx.colorThemeRegistry.create('uniform', { structure }),
+            size: reprCtx.sizeThemeRegistry.create('physical', { structure })
+        });
+        console.time('membrane orientation');
+        await membraneOrientationRepr.createOrUpdate({}, structure).run();
+        console.timeEnd('membrane orientation');
+    }
+
     if (show.cartoon) canvas3d.add(cartoonRepr);
     if (show.interaction) canvas3d.add(interactionRepr);
     if (show.ballAndStick) canvas3d.add(ballAndStickRepr);
     if (show.molecularSurface) canvas3d.add(molecularSurfaceRepr);
     if (show.gaussianSurface) canvas3d.add(gaussianSurfaceRepr);
-    if (show.membrane) canvas3d.add(membraneRepr);
+    if (show.membrane) canvas3d.add(membraneOrientationRepr);
     canvas3d.requestCameraReset();
     // canvas3d.setProps({ trackball: { ...canvas3d.props.trackball, spin: true } })
 }