|
@@ -5,63 +5,36 @@
|
|
|
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
|
|
*/
|
|
|
|
|
|
-import { ANVILMembraneOrientation, MembraneOrientation3D, tryCreateMembraneOrientation } from '../../extensions/anvil/behavior';
|
|
|
-import { CellPack } from '../../extensions/cellpack';
|
|
|
-import { DnatcoConfalPyramids } from '../../extensions/dnatco';
|
|
|
-import { G3DFormat, G3dProvider } from '../../extensions/g3d/format';
|
|
|
-import { Mp4Export } from '../../extensions/mp4-export';
|
|
|
-import { GeometryExport } from '../../extensions/geo-export';
|
|
|
-import { PDBeStructureQualityReport } from '../../extensions/pdbe';
|
|
|
-import { RCSBAssemblySymmetry, RCSBValidationReport } from '../../extensions/rcsb';
|
|
|
-import { DownloadStructure, PdbDownloadProvider } from '../../mol-plugin-state/actions/structure';
|
|
|
-import { DownloadDensity } from '../../mol-plugin-state/actions/volume';
|
|
|
-import { StructureRepresentationPresetProvider } from '../../mol-plugin-state/builder/structure/representation-preset';
|
|
|
-import { DataFormatProvider } from '../../mol-plugin-state/formats/provider';
|
|
|
-import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory';
|
|
|
-import { BuildInVolumeFormat } from '../../mol-plugin-state/formats/volume';
|
|
|
-import { createVolumeRepresentationParams } from '../../mol-plugin-state/helpers/volume-representation-params';
|
|
|
-import { PluginStateObject } from '../../mol-plugin-state/objects';
|
|
|
+import { ANVILMembraneOrientation } from '../../extensions/anvil/behavior';
|
|
|
import { StateTransforms } from '../../mol-plugin-state/transforms';
|
|
|
import { createPlugin } from '../../mol-plugin-ui';
|
|
|
import { PluginUIContext } from '../../mol-plugin-ui/context';
|
|
|
import { PluginLayoutControlsDisplay } from '../../mol-plugin/layout';
|
|
|
import { DefaultPluginUISpec, PluginUISpec } from '../../mol-plugin-ui/spec';
|
|
|
-import { PluginCommands } from '../../mol-plugin/commands';
|
|
|
import { PluginConfig } from '../../mol-plugin/config';
|
|
|
import { PluginSpec } from '../../mol-plugin/spec';
|
|
|
-import { PluginState } from '../../mol-plugin/state';
|
|
|
-import { StateObjectRef, StateObjectSelector } from '../../mol-state';
|
|
|
-import { Asset } from '../../mol-util/assets';
|
|
|
+import { StateBuilder, StateObjectRef } from '../../mol-state';
|
|
|
import { Color } from '../../mol-util/color';
|
|
|
import '../../mol-util/polyfill';
|
|
|
import { ObjectKeys } from '../../mol-util/type-helpers';
|
|
|
import './embedded.html';
|
|
|
import './favicon.ico';
|
|
|
import './index.html';
|
|
|
+import { MolScriptBuilder as MS } from '../../mol-script/language/builder';
|
|
|
+import { createStructureRepresentationParams } from '../../mol-plugin-state/helpers/structure-representation-params';
|
|
|
+import { Expression } from '../../mol-script/language/expression';
|
|
|
+import { PluginStateObject } from '../../mol-plugin-state/objects';
|
|
|
|
|
|
require('mol-plugin-ui/skin/light.scss');
|
|
|
|
|
|
export { PLUGIN_VERSION as version } from '../../mol-plugin/version';
|
|
|
export { setDebugMode, setProductionMode } from '../../mol-util/debug';
|
|
|
|
|
|
-const CustomFormats = [
|
|
|
- ['g3d', G3dProvider] as const
|
|
|
-];
|
|
|
-
|
|
|
const Extensions = {
|
|
|
- 'cellpack': PluginSpec.Behavior(CellPack),
|
|
|
- 'dnatco-confal-pyramids': PluginSpec.Behavior(DnatcoConfalPyramids),
|
|
|
- 'pdbe-structure-quality-report': PluginSpec.Behavior(PDBeStructureQualityReport),
|
|
|
- 'rcsb-assembly-symmetry': PluginSpec.Behavior(RCSBAssemblySymmetry),
|
|
|
- 'rcsb-validation-report': PluginSpec.Behavior(RCSBValidationReport),
|
|
|
- 'anvil-membrane-orientation': PluginSpec.Behavior(ANVILMembraneOrientation),
|
|
|
- 'g3d': PluginSpec.Behavior(G3DFormat),
|
|
|
- 'mp4-export': PluginSpec.Behavior(Mp4Export),
|
|
|
- 'geo-export': PluginSpec.Behavior(GeometryExport)
|
|
|
+ 'anvil-membrane-orientation': PluginSpec.Behavior(ANVILMembraneOrientation)
|
|
|
};
|
|
|
|
|
|
const DefaultViewerOptions = {
|
|
|
- customFormats: CustomFormats as [string, DataFormatProvider][],
|
|
|
extensions: ObjectKeys(Extensions),
|
|
|
layoutIsExpanded: true,
|
|
|
layoutShowControls: true,
|
|
@@ -91,6 +64,85 @@ type ViewerOptions = typeof DefaultViewerOptions;
|
|
|
export class Viewer {
|
|
|
plugin: PluginUIContext
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ async loadWithUNITMPMembraneRepresentation(url: string, selectors: any[] = [], format: any = 'mmcif') {
|
|
|
+ const isBinary = false;
|
|
|
+
|
|
|
+
|
|
|
+ const data = await this.plugin.builders.data.download({ url, isBinary });
|
|
|
+ const trajectory = await this.plugin.builders.structure.parseTrajectory(data, format);
|
|
|
+ await this.plugin.builders.structure.hierarchy.applyPreset(
|
|
|
+ trajectory, 'default', { representationPreset: 'preset-membrane-orientation' as any });
|
|
|
+
|
|
|
+ const structure: StateObjectRef<PluginStateObject.Molecule.Structure> =
|
|
|
+ this.plugin.managers.structure.hierarchy.current.models[0].structures[0].cell;
|
|
|
+ const components = {
|
|
|
+ polymer: await this.plugin.builders.structure.tryCreateComponentStatic(structure, 'polymer'),
|
|
|
+ ligand: await this.plugin.builders.structure.tryCreateComponentStatic(structure, 'ligand'),
|
|
|
+ water: await this.plugin.builders.structure.tryCreateComponentStatic(structure, 'water'),
|
|
|
+ };
|
|
|
+
|
|
|
+ const builder = this.plugin.builders.structure.representation;
|
|
|
+ const update = this.plugin.build();
|
|
|
+ if (components.polymer) builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams: { alpha: 0.5 } }, { tag: 'polymer' });
|
|
|
+ if (components.ligand) builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick' }, { tag: 'ligand' });
|
|
|
+ if (components.water) builder.buildRepresentation(update, components.water, { type: 'ball-and-stick', typeParams: { alpha: 0.6 } }, { tag: 'water' });
|
|
|
+ await update.commit();
|
|
|
+
|
|
|
+ selectors.forEach(selector => {
|
|
|
+ const chain = selector;
|
|
|
+
|
|
|
+ for(let regionKey in chain.regions) {
|
|
|
+ const update = this.plugin.build();
|
|
|
+ const region = chain.regions[regionKey];
|
|
|
+ let color: Color = Color.fromArray(region.color, 0);
|
|
|
+ this.applyColor(chain.chain_id, region.auth_ids, update.to(structure), color);
|
|
|
+ update.commit();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ requestAnimationFrame(() => this.plugin.canvas3d?.requestCameraReset());
|
|
|
+ }
|
|
|
+
|
|
|
+ private applyColor(chain: string, auth_seq_ids: number[], update: StateBuilder.To<any, any>, color: Color) {
|
|
|
+ const label: string = `${chain}.${auth_seq_ids.length}`;
|
|
|
+ console.log(label);
|
|
|
+
|
|
|
+ const query: Expression = this.getQuery(chain, auth_seq_ids);
|
|
|
+
|
|
|
+
|
|
|
+ update
|
|
|
+ .apply(StateTransforms.Model.StructureSelectionFromExpression, { label: label, expression: query })
|
|
|
+ .apply(StateTransforms.Representation.StructureRepresentation3D, createStructureRepresentationParams(this.plugin, update.selector.data, {
|
|
|
+ color: 'uniform',
|
|
|
+ colorParams: { value: color }
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
+ private getQuery(chainId: string, auth_array: number[]): Expression {
|
|
|
+ const query: Expression =
|
|
|
+ MS.struct.generator.atomGroups({
|
|
|
+ 'residue-test': MS.core.set.has([MS.set( ...auth_array ), MS.ammp('auth_seq_id')]),
|
|
|
+ 'chain-test': MS.core.rel.eq([chainId, MS.ammp('label_asym_id')])
|
|
|
+ });
|
|
|
+ return query;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
constructor(elementOrId: string | HTMLElement, options: Partial<ViewerOptions> = {}) {
|
|
|
const o = { ...DefaultViewerOptions, ...options };
|
|
|
const defaultSpec = DefaultPluginUISpec();
|
|
@@ -103,7 +155,6 @@ export class Viewer {
|
|
|
],
|
|
|
animations: [...defaultSpec.animations || []],
|
|
|
customParamEditors: defaultSpec.customParamEditors,
|
|
|
- customFormats: o?.customFormats,
|
|
|
layout: {
|
|
|
initial: {
|
|
|
isExpanded: o.layoutIsExpanded,
|
|
@@ -152,215 +203,7 @@ export class Viewer {
|
|
|
this.plugin = createPlugin(element, spec);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- applyMembrane() {
|
|
|
- console.log("under investigation...");
|
|
|
- console.log(MembraneOrientation3D.id);
|
|
|
-
|
|
|
- const hier = this.plugin.managers.structure.hierarchy;
|
|
|
- const stateObj: StateObjectRef<PluginStateObject.Molecule.Structure> =
|
|
|
- hier.selection.structures[0].components[0].structure.cell;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- tryCreateMembraneOrientation(this.plugin, stateObj);
|
|
|
- }
|
|
|
-
|
|
|
- setRemoteSnapshot(id: string) {
|
|
|
- const url = `${this.plugin.config.get(PluginConfig.State.CurrentServer)}/get/${id}`;
|
|
|
- return PluginCommands.State.Snapshots.Fetch(this.plugin, { url });
|
|
|
- }
|
|
|
-
|
|
|
- loadSnapshotFromUrl(url: string, type: PluginState.SnapshotType) {
|
|
|
- return PluginCommands.State.Snapshots.OpenUrl(this.plugin, { url, type });
|
|
|
- }
|
|
|
-
|
|
|
- loadStructureFromUrl(url: string, format: BuiltInTrajectoryFormat = 'mmcif', isBinary = false, options?: LoadStructureOptions) {
|
|
|
- const params = DownloadStructure.createDefaultParams(this.plugin.state.data.root.obj!, this.plugin);
|
|
|
- return this.plugin.runTask(this.plugin.state.data.applyAction(DownloadStructure, {
|
|
|
- source: {
|
|
|
- name: 'url',
|
|
|
- params: {
|
|
|
- url: Asset.Url(url),
|
|
|
- format: format as any,
|
|
|
- isBinary,
|
|
|
- options: { ...params.source.params.options, representationParams: options?.representationParams as any },
|
|
|
- }
|
|
|
- }
|
|
|
- }));
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- async loadStructureWithMembraneRepresentation(url: string, format: BuiltInTrajectoryFormat, isBinary: boolean) {
|
|
|
- const data = await this.plugin.builders.data.download({ url, isBinary }, { state: { isGhost: true } });
|
|
|
- const trajectory = await this.plugin.builders.structure.parseTrajectory(data, format);
|
|
|
- await this.plugin.builders.structure.hierarchy.applyPreset(trajectory, 'default', { representationPreset: 'preset-membrane-orientation' as any });
|
|
|
-
|
|
|
-
|
|
|
- requestAnimationFrame(() => this.plugin.canvas3d?.requestCameraReset());
|
|
|
- }
|
|
|
-
|
|
|
- async loadAllModelsOrAssemblyFromUrl(url: string, format: BuiltInTrajectoryFormat = 'mmcif', isBinary = false, options?: LoadStructureOptions) {
|
|
|
- const plugin = this.plugin;
|
|
|
-
|
|
|
- const data = await plugin.builders.data.download({ url, isBinary }, { state: { isGhost: true } });
|
|
|
- const trajectory = await plugin.builders.structure.parseTrajectory(data, format);
|
|
|
-
|
|
|
- await this.plugin.builders.structure.hierarchy.applyPreset(trajectory, 'all-models', { useDefaultIfSingleModel: true, representationPresetParams: options?.representationParams });
|
|
|
- }
|
|
|
-
|
|
|
- async loadStructureFromData(data: string | number[], format: BuiltInTrajectoryFormat, options?: { dataLabel?: string }) {
|
|
|
- const _data = await this.plugin.builders.data.rawData({ data, label: options?.dataLabel });
|
|
|
- const trajectory = await this.plugin.builders.structure.parseTrajectory(_data, format);
|
|
|
- await this.plugin.builders.structure.hierarchy.applyPreset(trajectory, 'default');
|
|
|
- }
|
|
|
-
|
|
|
- loadPdb(pdb: string, options?: LoadStructureOptions) {
|
|
|
- const params = DownloadStructure.createDefaultParams(this.plugin.state.data.root.obj!, this.plugin);
|
|
|
- const provider = this.plugin.config.get(PluginConfig.Download.DefaultPdbProvider)!;
|
|
|
- return this.plugin.runTask(this.plugin.state.data.applyAction(DownloadStructure, {
|
|
|
- source: {
|
|
|
- name: 'pdb' as const,
|
|
|
- params: {
|
|
|
- provider: {
|
|
|
- id: pdb,
|
|
|
- server: {
|
|
|
- name: provider,
|
|
|
- params: PdbDownloadProvider[provider].defaultValue as any
|
|
|
- }
|
|
|
- },
|
|
|
- options: { ...params.source.params.options, representationParams: options?.representationParams as any },
|
|
|
- }
|
|
|
- }
|
|
|
- }));
|
|
|
- }
|
|
|
-
|
|
|
- loadPdbDev(pdbDev: string) {
|
|
|
- const params = DownloadStructure.createDefaultParams(this.plugin.state.data.root.obj!, this.plugin);
|
|
|
- return this.plugin.runTask(this.plugin.state.data.applyAction(DownloadStructure, {
|
|
|
- source: {
|
|
|
- name: 'pdb-dev' as const,
|
|
|
- params: {
|
|
|
- provider: {
|
|
|
- id: pdbDev,
|
|
|
- encoding: 'bcif',
|
|
|
- },
|
|
|
- options: params.source.params.options,
|
|
|
- }
|
|
|
- }
|
|
|
- }));
|
|
|
- }
|
|
|
-
|
|
|
- loadEmdb(emdb: string, options?: { detail?: number }) {
|
|
|
- const provider = this.plugin.config.get(PluginConfig.Download.DefaultEmdbProvider)!;
|
|
|
- return this.plugin.runTask(this.plugin.state.data.applyAction(DownloadDensity, {
|
|
|
- source: {
|
|
|
- name: 'pdb-emd-ds' as const,
|
|
|
- params: {
|
|
|
- provider: {
|
|
|
- id: emdb,
|
|
|
- server: provider,
|
|
|
- },
|
|
|
- detail: options?.detail ?? 3,
|
|
|
- }
|
|
|
- }
|
|
|
- }));
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * @example Load X-ray density from volume server
|
|
|
- viewer.loadVolumeFromUrl({
|
|
|
- url: 'https://www.ebi.ac.uk/pdbe/densities/x-ray/1tqn/cell?detail=3',
|
|
|
- format: 'dscif',
|
|
|
- isBinary: true
|
|
|
- }, [{
|
|
|
- type: 'relative',
|
|
|
- value: 1.5,
|
|
|
- color: 0x3362B2
|
|
|
- }, {
|
|
|
- type: 'relative',
|
|
|
- value: 3,
|
|
|
- color: 0x33BB33,
|
|
|
- volumeIndex: 1
|
|
|
- }, {
|
|
|
- type: 'relative',
|
|
|
- value: -3,
|
|
|
- color: 0xBB3333,
|
|
|
- volumeIndex: 1
|
|
|
- }], {
|
|
|
- entryId: ['2FO-FC', 'FO-FC'],
|
|
|
- isLazy: true
|
|
|
- });
|
|
|
- * *********************
|
|
|
- * @example Load EM density from volume server
|
|
|
- viewer.loadVolumeFromUrl({
|
|
|
- url: 'https://maps.rcsb.org/em/emd-30210/cell?detail=6',
|
|
|
- format: 'dscif',
|
|
|
- isBinary: true
|
|
|
- }, [{
|
|
|
- type: 'relative',
|
|
|
- value: 1,
|
|
|
- color: 0x3377aa
|
|
|
- }], {
|
|
|
- entryId: 'EMD-30210',
|
|
|
- isLazy: true
|
|
|
- });
|
|
|
- */
|
|
|
- async loadVolumeFromUrl({ url, format, isBinary }: { url: string, format: BuildInVolumeFormat, isBinary: boolean }, isovalues: VolumeIsovalueInfo[], options?: { entryId?: string | string[], isLazy?: boolean }) {
|
|
|
- const plugin = this.plugin;
|
|
|
-
|
|
|
- if (!plugin.dataFormats.get(format)) {
|
|
|
- throw new Error(`Unknown density format: ${format}`);
|
|
|
- }
|
|
|
-
|
|
|
- if (options?.isLazy) {
|
|
|
- const update = this.plugin.build();
|
|
|
- update.toRoot().apply(StateTransforms.Data.LazyVolume, {
|
|
|
- url,
|
|
|
- format,
|
|
|
- entryId: options?.entryId,
|
|
|
- isBinary,
|
|
|
- isovalues: isovalues.map(v => ({ alpha: 1, volumeIndex: 0, ...v }))
|
|
|
- });
|
|
|
- return update.commit();
|
|
|
- }
|
|
|
-
|
|
|
- return plugin.dataTransaction(async () => {
|
|
|
- const data = await plugin.builders.data.download({ url, isBinary }, { state: { isGhost: true } });
|
|
|
-
|
|
|
- const parsed = await plugin.dataFormats.get(format)!.parse(plugin, data, { entryId: options?.entryId });
|
|
|
- const firstVolume = (parsed.volume || parsed.volumes[0]) as StateObjectSelector<PluginStateObject.Volume.Data>;
|
|
|
- if (!firstVolume?.isOk) throw new Error('Failed to parse any volume.');
|
|
|
-
|
|
|
- const repr = plugin.build();
|
|
|
- for (const iso of isovalues) {
|
|
|
- repr
|
|
|
- .to(parsed.volumes?.[iso.volumeIndex ?? 0] ?? parsed.volume)
|
|
|
- .apply(StateTransforms.Representation.VolumeRepresentation3D, createVolumeRepresentationParams(this.plugin, firstVolume.data!, {
|
|
|
- type: 'isosurface',
|
|
|
- typeParams: { alpha: iso.alpha ?? 1, isoValue: iso.type === 'absolute' ? { kind: 'absolute', absoluteValue: iso.value } : { kind: 'relative', relativeValue: iso.value } },
|
|
|
- color: 'uniform',
|
|
|
- colorParams: { value: iso.color }
|
|
|
- }));
|
|
|
- }
|
|
|
-
|
|
|
- await repr.commit();
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
handleResize() {
|
|
|
this.plugin.layout.events.updated.next();
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-export interface LoadStructureOptions {
|
|
|
- representationParams?: StructureRepresentationPresetProvider.CommonParams
|
|
|
-}
|
|
|
-
|
|
|
-export interface VolumeIsovalueInfo {
|
|
|
- type: 'absolute' | 'relative',
|
|
|
- value: number,
|
|
|
- color: Color,
|
|
|
- alpha?: number,
|
|
|
- volumeIndex?: number
|
|
|
-}
|