|
@@ -0,0 +1,193 @@
|
|
|
+/**
|
|
|
+ * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
|
|
+ *
|
|
|
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
|
|
|
+ */
|
|
|
+
|
|
|
+import { ParamDefinition as PD } from 'molstar/lib/mol-util/param-definition';
|
|
|
+import { TrajectoryHierarchyPresetProvider } from 'molstar/lib/mol-plugin-state/builder/structure/hierarchy-preset';
|
|
|
+import { PluginStateObject } from 'molstar/lib/mol-plugin-state/objects';
|
|
|
+import { RootStructureDefinition } from 'molstar/lib/mol-plugin-state/helpers/root-structure';
|
|
|
+import { StructureRepresentationPresetProvider } from 'molstar/lib/mol-plugin-state/builder/structure/representation-preset';
|
|
|
+import {
|
|
|
+ StateObjectSelector,
|
|
|
+ StateObject,
|
|
|
+ StateTransformer
|
|
|
+} from 'molstar/lib/mol-state';
|
|
|
+import { Mat4 } from 'molstar/lib/mol-math/linear-algebra';
|
|
|
+import { MembraneOrientationPreset } from 'molstar/lib/extensions/anvil/behavior';
|
|
|
+import { Target } from '@rcsb/rcsb-molstar/build/src/viewer/helpers/selection';
|
|
|
+import { TMDET_STRUCTURE_PRESET_ID } from '@rcsb/rcsb-molstar/build/src/tmdet-extension/behavior';
|
|
|
+
|
|
|
+type BaseProps = {
|
|
|
+ assemblyId?: string
|
|
|
+ modelIndex?: number
|
|
|
+ plddt?: 'off' | 'single-chain' | 'on'
|
|
|
+}
|
|
|
+
|
|
|
+export { Mat4 } from 'molstar/lib/mol-math/linear-algebra';
|
|
|
+
|
|
|
+export type AlignmentProps = {
|
|
|
+ kind: 'alignment',
|
|
|
+ targets?: (Target & {
|
|
|
+ matrix?: Mat4
|
|
|
+ })[],
|
|
|
+ colors: {
|
|
|
+ value: number,
|
|
|
+ targets: Target[]
|
|
|
+ }[]
|
|
|
+} & BaseProps
|
|
|
+
|
|
|
+export type EmptyProps = {
|
|
|
+ kind: 'empty'
|
|
|
+} & BaseProps
|
|
|
+
|
|
|
+type ValidationProps = {
|
|
|
+ kind: 'validation'
|
|
|
+ colorTheme?: string
|
|
|
+ showClashes?: boolean
|
|
|
+} & BaseProps
|
|
|
+
|
|
|
+type StandardProps = {
|
|
|
+ kind: 'standard'
|
|
|
+} & BaseProps
|
|
|
+
|
|
|
+type SymmetryProps = {
|
|
|
+ kind: 'symmetry'
|
|
|
+ symmetryIndex?: number
|
|
|
+} & BaseProps
|
|
|
+
|
|
|
+type FeatureProps = {
|
|
|
+ kind: 'feature'
|
|
|
+ target: Target
|
|
|
+} & BaseProps
|
|
|
+
|
|
|
+type DensityProps = {
|
|
|
+ kind: 'density'
|
|
|
+} & BaseProps
|
|
|
+
|
|
|
+type MembraneProps = {
|
|
|
+ kind: 'membrane',
|
|
|
+} & BaseProps
|
|
|
+
|
|
|
+type FeatureDensityProps = {
|
|
|
+ kind: 'feature-density',
|
|
|
+ target: Target,
|
|
|
+ radius?: number,
|
|
|
+ hiddenChannels?: string[]
|
|
|
+} & BaseProps
|
|
|
+
|
|
|
+export type MotifProps = {
|
|
|
+ kind: 'motif',
|
|
|
+ label?: string,
|
|
|
+ targets: Target[],
|
|
|
+ color?: number
|
|
|
+} & BaseProps
|
|
|
+
|
|
|
+export type NakbProps = {
|
|
|
+ kind: 'nakb'
|
|
|
+} & BaseProps
|
|
|
+
|
|
|
+export type PresetProps = ValidationProps | StandardProps | SymmetryProps | FeatureProps | DensityProps | AlignmentProps |
|
|
|
+MembraneProps | FeatureDensityProps | MotifProps | NakbProps | EmptyProps;
|
|
|
+
|
|
|
+const RcsbParams = () => ({
|
|
|
+ preset: PD.Value<PresetProps>({ kind: 'standard', assemblyId: '' }, { isHidden: true })
|
|
|
+});
|
|
|
+
|
|
|
+type StructureObject = StateObjectSelector<PluginStateObject.Molecule.Structure, StateTransformer<StateObject<any, StateObject.Type<any>>, StateObject<any, StateObject.Type<any>>, any>>
|
|
|
+
|
|
|
+export const TmDetRcsbPreset = TrajectoryHierarchyPresetProvider({
|
|
|
+ id: 'tmdet-preset-trajectory-rcsb',
|
|
|
+ display: { name: 'TMDET RCSB Preset' },
|
|
|
+ isApplicable: () => true,
|
|
|
+ params: RcsbParams,
|
|
|
+ async apply(trajectory, params, plugin) {
|
|
|
+ console.log('TMDET RCSB PRESET: apply start');
|
|
|
+ const builder = plugin.builders.structure;
|
|
|
+ const p = params.preset;
|
|
|
+
|
|
|
+ const modelParams = { modelIndex: p.modelIndex || 0 };
|
|
|
+
|
|
|
+ const structureParams: RootStructureDefinition.Params = { name: 'model', params: {} };
|
|
|
+ if (p.assemblyId && p.assemblyId !== '' && p.assemblyId !== '0') {
|
|
|
+ Object.assign(structureParams, {
|
|
|
+ name: 'assembly',
|
|
|
+ params: { id: p.assemblyId }
|
|
|
+ } as RootStructureDefinition.Params);
|
|
|
+ }
|
|
|
+
|
|
|
+ const model = await builder.createModel(trajectory, modelParams);
|
|
|
+ const modelProperties = await builder.insertModelProperties(model);
|
|
|
+
|
|
|
+ let structure: StructureObject | undefined = undefined;
|
|
|
+ let structureProperties: StructureObject | undefined = undefined;
|
|
|
+ let unitcell: StateObjectSelector | undefined = undefined;
|
|
|
+ // If flexible transformation is allowed, we may need to create a single structure component
|
|
|
+ // from transformed substructures
|
|
|
+ structure = await builder.createStructure(modelProperties || model, structureParams);
|
|
|
+ structureProperties = await builder.insertStructureProperties(structure);
|
|
|
+
|
|
|
+ // default to pLDDT coloring when category present && single chain
|
|
|
+ const presetParams = Object.create(null);
|
|
|
+ let representation: StructureRepresentationPresetProvider.Result | undefined = undefined;
|
|
|
+ console.log('PRESET params:', params);
|
|
|
+ console.log('PRESET p:', p);
|
|
|
+
|
|
|
+ if (p.kind === 'alignment') {
|
|
|
+ console.warn('alignment case not implemented in TmDetRcsbPreset');
|
|
|
+ } else if (p.kind === 'motif' && structure?.obj) {
|
|
|
+ console.warn('motif case not implemented in TmDetRcsbPreset');
|
|
|
+ } else if (p.kind === 'validation') {
|
|
|
+ console.warn('validation case not implemented in TmDetRcsbPreset');
|
|
|
+ } else if (p.kind === 'symmetry' && structure?.obj) {
|
|
|
+ console.warn('symmetry case not implemented in TmDetRcsbPreset');
|
|
|
+ } else if (p.kind === 'empty') {
|
|
|
+ console.warn('Using empty representation in TmDetRcsbPreset');
|
|
|
+ } else if (p.kind === 'membrane') {
|
|
|
+ try {
|
|
|
+ representation = await plugin.builders.structure.representation.applyPreset<any>(structureProperties!, MembraneOrientationPreset, presetParams);
|
|
|
+
|
|
|
+ // reset the camera because the membranes render 1st and the structure might not be fully visible
|
|
|
+ requestAnimationFrame(() => plugin.canvas3d?.requestCameraReset());
|
|
|
+ } catch (error) {
|
|
|
+ const msg = 'Membrane calculation failed! - This can happen for tiny structures with only a dozen of residues.';
|
|
|
+ plugin.log.error(msg);
|
|
|
+ console.error(msg);
|
|
|
+ console.error(error);
|
|
|
+
|
|
|
+ // fall back to default representation to show something
|
|
|
+ representation = await plugin.builders.structure.representation.applyPreset(structureProperties!, 'auto', presetParams);
|
|
|
+ }
|
|
|
+ } else if (p.kind === 'nakb') {
|
|
|
+ console.warn('nakb case not implemented in TmDetRcsbPreset');
|
|
|
+ } else {
|
|
|
+ console.log('HERE WE GO:', { structure: structure, structureProps: structureProperties, presetParams: presetParams });
|
|
|
+ //representation = await plugin.builders.structure.representation.applyPreset(structureProperties!, 'auto', presetParams);
|
|
|
+ representation = await plugin.builders.structure.representation.applyPreset(
|
|
|
+ structureProperties!, 'auto', { theme: { globalName: 'tmdet-custom-color-theme' } });
|
|
|
+ await plugin.builders.structure.hierarchy.applyPreset(
|
|
|
+ trajectory, 'default', { representationPreset: TMDET_STRUCTURE_PRESET_ID as any });
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('STRUCTURE REPRESENTATION:', representation);
|
|
|
+
|
|
|
+ // TODO align with 'motif'?
|
|
|
+ if ((p.kind === 'feature' || p.kind === 'feature-density') && structure?.obj) {
|
|
|
+ console.warn('feature/feature-density case not implemented in TmDetRcsbPreset');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p.kind === 'density' && structure) {
|
|
|
+ console.warn('density case not implemented in TmDetRcsbPreset');
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ model,
|
|
|
+ modelProperties,
|
|
|
+ unitcell,
|
|
|
+ structure,
|
|
|
+ structureProperties,
|
|
|
+ representation
|
|
|
+ };
|
|
|
+ }
|
|
|
+});
|