diff --git a/src/mol-model-props/common/custom-element-property.ts b/src/mol-model-props/common/custom-element-property.ts new file mode 100644 index 0000000000000000000000000000000000000000..3b84056bd06ae87e9d11be11c390d263d4011a48 --- /dev/null +++ b/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) + }; + } +} \ No newline at end of file diff --git a/src/mol-plugin/util/custom-prop-registry.ts b/src/mol-model-props/common/custom-property-registry.ts similarity index 100% rename from src/mol-plugin/util/custom-prop-registry.ts rename to src/mol-model-props/common/custom-property-registry.ts diff --git a/src/mol-plugin/behavior/dynamic/custom-props/pdbe/structure-quality-report.ts b/src/mol-plugin/behavior/dynamic/custom-props/pdbe/structure-quality-report.ts index dc882b0efb0991435ff6f0ff618ecdbdf17ca957..110ec57b823b70cada7d330ce14a68677cc18cf3 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/pdbe/structure-quality-report.ts +++ b/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', diff --git a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts index fc131da26a344fac0b72dc545072c2b8263f50f1..e156dd20d54e7f3b8af6dda004005ba23920e398 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts +++ b/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', diff --git a/src/mol-plugin/context.ts b/src/mol-plugin/context.ts index 25bd3648cfee27be1f62c3cf5753f41f3c761411..0a3904c8f29753a9e5cd940569fa9ced98a8f7e1 100644 --- a/src/mol-plugin/context.ts +++ b/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; diff --git a/src/servers/volume/server/local-api.ts b/src/servers/volume/server/local-api.ts index 387d72a3139394630d09d3288a062509f3b9b7f9..de87df318ec3e7cf457a92aa932598e2bd7b666b 100644 --- a/src/servers/volume/server/local-api.ts +++ b/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