Kaynağa Gözat

wip generic atomic custom props

David Sehnal 6 yıl önce
ebeveyn
işleme
5e8ad4360f

+ 115 - 0
src/mol-model-props/common/custom-element-property.ts

@@ -0,0 +1,115 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+import { ElementIndex, Model, ModelPropertyDescriptor } from 'mol-model/structure';
+import { StructureElement } from 'mol-model/structure/structure';
+import { Location } from 'mol-model/location';
+import { CustomPropertyRegistry } from './custom-property-registry';
+import { Task } from 'mol-task';
+import { ThemeDataContext } from 'mol-theme/theme';
+import { ColorTheme, LocationColor } from 'mol-theme/color';
+import { Color } from 'mol-util/color';
+import { TableLegend } from 'mol-util/color/tables';
+import { Loci } from 'mol-model/loci';
+import { OrderedSet } from 'mol-data/int';
+
+export { CustomElementProperty };
+
+namespace CustomElementProperty {
+    export interface CreateParams<S, T> {
+        isStatic: boolean,
+        name: string,
+        autoAttach?: boolean,
+        display: string,
+        attachableTo: (model: Model) => boolean,
+        getData(model: Model): Map<ElementIndex, T> | Promise<Map<ElementIndex, T>>,
+        format?(e: T): string,
+        coloring?: {
+            getColor: (e: T) => Color,
+            defaultColor: Color
+        }
+    }
+
+    export function create<S, T>(params: CreateParams<S, T>) {
+        const name = params.name;
+
+        const Descriptor = ModelPropertyDescriptor({
+            isStatic: params.isStatic,
+            name: params.name,
+        });
+
+        function attach(model: Model) {
+            return Task.create(`Attach ${params.display}`, async () => {
+                const data = await params.getData(model);
+
+                if (params.isStatic) {
+                    model._staticPropertyData[name] = data;
+                } else {
+                    model._dynamicPropertyData[name] = data;
+                }
+
+                return true;
+            })
+        }
+
+        function getStatic(e: StructureElement) { return e.unit.model._staticPropertyData[name].get(e.element); }
+        function getDynamic(e: StructureElement) { return e.unit.model._staticPropertyData[name].get(e.element); }
+
+        const provider: CustomPropertyRegistry.Provider = {
+            option: [name, params.display],
+            descriptor: Descriptor,
+            defaultSelected: !!params.autoAttach,
+            attachableTo: params.attachableTo || (() => true),
+            attach
+        };
+
+        const get = params.isStatic ? getStatic : getDynamic;
+
+        function Coloring(ctx: ThemeDataContext, props: {}): ColorTheme<{}> {
+            let color: LocationColor;
+            const getColor = params.coloring!.getColor;
+            const defaultColor = params.coloring!.defaultColor;
+
+            if (ctx.structure && !ctx.structure.isEmpty && ctx.structure.models[0].customProperties.has(Descriptor)) {
+                color = (location: Location) => {
+                    if (StructureElement.isLocation(location)) {
+                        const e = get(location);
+                        if (typeof e !== 'undefined') return getColor(e);
+                    }
+                    return defaultColor;
+                }
+            } else {
+                color = () => defaultColor;
+            }
+
+            return {
+                factory: Coloring,
+                granularity: 'group',
+                color: color,
+                props: props,
+                description: 'Assign element colors based on the provided data.',
+                legend: TableLegend([])
+            };
+        }
+
+        function LabelProvider(loci: Loci): string | undefined {
+            if (loci.kind === 'element-loci') {
+                const e = loci.elements[0];
+                return params.format!(get(StructureElement.create(e.unit, e.unit.elements[OrderedSet.getAt(e.indices, 0)])));
+            }
+            return void 0;
+        }
+
+        return {
+            Descriptor,
+            attach,
+            get,
+            provider,
+            colorTheme: params.coloring ? Coloring : void 0,
+            labelProvider: params.format ? LabelProvider : ((loci: Loci) => void 0)
+        };
+    }
+}

+ 0 - 0
src/mol-plugin/util/custom-prop-registry.ts → src/mol-model-props/common/custom-property-registry.ts


+ 1 - 1
src/mol-plugin/behavior/dynamic/custom-props/pdbe/structure-quality-report.ts

@@ -9,10 +9,10 @@ import { StructureQualityReport } from 'mol-model-props/pdbe/structure-quality-r
 import { StructureQualityReportColorTheme } from 'mol-model-props/pdbe/themes/structure-quality-report';
 import { Loci } from 'mol-model/loci';
 import { StructureElement } from 'mol-model/structure';
-import { CustomPropertyRegistry } from 'mol-plugin/util/custom-prop-registry';
 import { ParamDefinition as PD } from 'mol-util/param-definition';
 import { PluginBehavior } from '../../../behavior';
 import { ThemeDataContext } from 'mol-theme/theme';
+import { CustomPropertyRegistry } from 'mol-model-props/common/custom-property-registry';
 
 export const PDBeStructureQualityReport = PluginBehavior.create<{ autoAttach: boolean }>({
     name: 'pdbe-structure-quality-report-prop',

+ 1 - 1
src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts

@@ -7,12 +7,12 @@
 import { PluginBehavior } from 'mol-plugin/behavior';
 import { ParamDefinition as PD } from 'mol-util/param-definition'
 import { AssemblySymmetry } from 'mol-model-props/rcsb/assembly-symmetry';
-import { CustomPropertyRegistry } from 'mol-plugin/util/custom-prop-registry';
 import { AssemblySymmetryClusterColorThemeProvider } from 'mol-model-props/rcsb/themes/assembly-symmetry-cluster';
 import { AssemblySymmetryAxesRepresentationProvider } from 'mol-model-props/rcsb/representations/assembly-symmetry-axes';
 import { Loci, isDataLoci } from 'mol-model/loci';
 import { OrderedSet } from 'mol-data/int';
 import { Table } from 'mol-data/db';
+import { CustomPropertyRegistry } from 'mol-model-props/common/custom-property-registry';
 
 export const RCSBAssemblySymmetry = PluginBehavior.create<{ autoAttach: boolean }>({
     name: 'rcsb-assembly-symmetry-prop',

+ 1 - 1
src/mol-plugin/context.ts

@@ -24,7 +24,6 @@ import { TaskManager } from './util/task-manager';
 import { Color } from 'mol-util/color';
 import { LociLabelEntry, LociLabelManager } from './util/loci-label-manager';
 import { ajaxGet } from 'mol-util/data-source';
-import { CustomPropertyRegistry } from './util/custom-prop-registry';
 import { VolumeRepresentationRegistry } from 'mol-repr/volume/registry';
 import { PLUGIN_VERSION, PLUGIN_VERSION_DATE } from './version';
 import { PluginLayout } from './layout';
@@ -32,6 +31,7 @@ import { List } from 'immutable';
 import { StateTransformParameters } from './ui/state/common';
 import { DataFormatRegistry } from './state/actions/volume';
 import { PluginBehavior } from './behavior/behavior';
+import { CustomPropertyRegistry } from 'mol-model-props/common/custom-property-registry';
 
 export class PluginContext {
     private disposed = false;

+ 1 - 1
src/servers/volume/server/local-api.ts

@@ -28,7 +28,7 @@ export interface JobEntry {
     params: {
         /** Determines the detail level as specified in server-config */
         detail?: number,
-        /** 
+        /**
          * Determines the sampling level:
          * 1: Original data
          * 2: Downsampled by factor 1/2