|
@@ -14,6 +14,13 @@ import { RootStructureDefinition } from 'molstar/lib/mol-plugin-state/helpers/ro
|
|
|
import { StructureRepresentationPresetProvider } from 'molstar/lib/mol-plugin-state/builder/structure/representation-preset';
|
|
|
import { StructureElement } from 'molstar/lib/mol-model/structure';
|
|
|
import { InitVolumeStreaming } from 'molstar/lib/mol-plugin/behavior/dynamic/volume-streaming/transformers';
|
|
|
+import {
|
|
|
+ Structure,
|
|
|
+ StructureSelection,
|
|
|
+ QueryContext,
|
|
|
+ StructureElement
|
|
|
+} from 'molstar/lib/mol-model/structure';
|
|
|
+import { compile } from 'molstar/lib/mol-script/runtime/query/compiler';
|
|
|
import { ViewerState } from '../types';
|
|
|
import {
|
|
|
StateSelection,
|
|
@@ -21,13 +28,68 @@ import {
|
|
|
StateObject,
|
|
|
StateTransformer
|
|
|
} from 'molstar/lib/mol-state';
|
|
|
-import { VolumeStreaming } from 'molstar/lib/mol-plugin/behavior/dynamic/volume-streaming/behavior';
|
|
|
import { Mat4 } from 'molstar/lib/mol-math/linear-algebra';
|
|
|
import { CustomStructureProperties } from 'molstar/lib/mol-plugin-state/transforms/model';
|
|
|
import { FlexibleStructureFromModel } from './superpose/flexible-structure';
|
|
|
import { PluginCommands } from 'molstar/lib/mol-plugin/commands';
|
|
|
import { InteractivityManager } from 'molstar/lib/mol-plugin-state/manager/interactivity';
|
|
|
import { MembraneOrientationPreset } from 'molstar/lib/extensions/anvil/behavior';
|
|
|
+import { setSubtreeVisibility } from 'molstar/lib/mol-plugin/behavior/static/state';
|
|
|
+import { VolumeStreaming } from 'molstar/lib/mol-plugin/behavior/dynamic/volume-streaming/behavior';
|
|
|
+import {
|
|
|
+ InitVolumeStreaming,
|
|
|
+ VolumeStreamingVisual
|
|
|
+} from 'molstar/lib/mol-plugin/behavior/dynamic/volume-streaming/transformers';
|
|
|
+
|
|
|
+type Target = {
|
|
|
+ readonly auth_seq_id?: number
|
|
|
+ readonly label_seq_id?: number
|
|
|
+ readonly label_comp_id?: string
|
|
|
+ readonly label_asym_id?: string
|
|
|
+}
|
|
|
+
|
|
|
+function targetToExpression(target: Target): Expression {
|
|
|
+ const residueTests: Expression[] = [];
|
|
|
+ const tests = Object.create(null);
|
|
|
+
|
|
|
+ if (target.auth_seq_id) {
|
|
|
+ residueTests.push(MS.core.rel.eq([target.auth_seq_id, MS.ammp('auth_seq_id')]));
|
|
|
+ } else if (target.label_seq_id) {
|
|
|
+ residueTests.push(MS.core.rel.eq([target.label_seq_id, MS.ammp('label_seq_id')]));
|
|
|
+ }
|
|
|
+ if (target.label_comp_id) {
|
|
|
+ residueTests.push(MS.core.rel.eq([target.label_comp_id, MS.ammp('label_comp_id')]));
|
|
|
+ }
|
|
|
+ if (residueTests.length === 1) {
|
|
|
+ tests['residue-test'] = residueTests[0];
|
|
|
+ } else if (residueTests.length > 1) {
|
|
|
+ tests['residue-test'] = MS.core.logic.and(residueTests);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (target.label_asym_id) {
|
|
|
+ tests['chain-test'] = MS.core.rel.eq([target.label_asym_id, MS.ammp('label_asym_id')]);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Object.keys(tests).length > 0) {
|
|
|
+ return MS.struct.modifier.union([
|
|
|
+ MS.struct.generator.atomGroups(tests)
|
|
|
+ ]);
|
|
|
+ } else {
|
|
|
+ return MS.struct.generator.empty;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function targetToLoci(target: Target, structure: Structure): StructureElement.Loci {
|
|
|
+ const expression = targetToExpression(target);
|
|
|
+ const query = compile<StructureSelection>(expression);
|
|
|
+ const selection = query(new QueryContext(structure));
|
|
|
+ return StructureSelection.toLociWithSourceUnits(selection);
|
|
|
+}
|
|
|
+
|
|
|
+type Range = {
|
|
|
+ label_asym_id: string
|
|
|
+ label_seq_id?: { beg: number, end?: number }
|
|
|
+}
|
|
|
import {
|
|
|
normalizeTargets,
|
|
|
createSelectionExpressions,
|
|
@@ -92,7 +154,9 @@ type MembraneProps = {
|
|
|
|
|
|
type FeatureDensityProps = {
|
|
|
kind: 'feature-density',
|
|
|
- target: Target
|
|
|
+ target: Target,
|
|
|
+ radius?: number,
|
|
|
+ hiddenChannels?: string[]
|
|
|
} & BaseProps
|
|
|
|
|
|
export type MotifProps = {
|
|
@@ -251,7 +315,7 @@ export const RcsbPreset = TrajectoryHierarchyPresetProvider({
|
|
|
const target = chainMode ? loci : StructureElement.Loci.firstResidue(loci);
|
|
|
|
|
|
if (p.kind === 'feature-density') {
|
|
|
- await initVolumeStreaming(plugin, structure);
|
|
|
+ await initVolumeStreaming(plugin, structure, { overrideRadius: p.radius || 0, hiddenChannels: p.hiddenChannels || ['fo-fc(+ve)', 'fo-fc(-ve)'] });
|
|
|
}
|
|
|
|
|
|
plugin.managers.structure.focus.setFromLoci(target);
|
|
@@ -286,13 +350,33 @@ export const RcsbPreset = TrajectoryHierarchyPresetProvider({
|
|
|
}
|
|
|
});
|
|
|
|
|
|
-async function initVolumeStreaming(plugin: PluginContext, structure: StructureObject) {
|
|
|
+async function initVolumeStreaming(plugin: PluginContext, structure: StructureObject, props?: { overrideRadius?: number, hiddenChannels: string[] }) {
|
|
|
if (!structure?.cell?.parent) return;
|
|
|
|
|
|
const volumeRoot = StateSelection.findTagInSubtree(structure.cell.parent.tree, structure.cell.transform.ref, VolumeStreaming.RootTag);
|
|
|
if (!volumeRoot) {
|
|
|
+ const state = plugin.state.data;
|
|
|
const params = PD.getDefaultValues(InitVolumeStreaming.definition.params!(structure.obj!, plugin));
|
|
|
- await plugin.runTask(plugin.state.data.applyAction(InitVolumeStreaming, params, structure.ref));
|
|
|
+ await plugin.runTask(state.applyAction(InitVolumeStreaming, params, structure.ref));
|
|
|
+
|
|
|
+ // RO-2751: allow to specify radius of shown density
|
|
|
+ if (props?.overrideRadius !== void 0) {
|
|
|
+ const { params, transform } = state.select(StateSelection.Generators.ofType(VolumeStreaming))[0];
|
|
|
+
|
|
|
+ const p = params?.values;
|
|
|
+ (p.entry.params.view.params as any).radius = props.overrideRadius;
|
|
|
+
|
|
|
+ await state.build().to(transform.ref).update(p).commit();
|
|
|
+ }
|
|
|
+ // RO-2751: hide all but 2Fo-Fc map
|
|
|
+ if (props?.hiddenChannels?.length) {
|
|
|
+ const cells = state.select(StateSelection.Generators.ofTransformer(VolumeStreamingVisual));
|
|
|
+ for (const cell of cells) {
|
|
|
+ if (props.hiddenChannels.indexOf(cell.obj!.tags![0]) !== -1) {
|
|
|
+ setSubtreeVisibility(state, cell.transform.ref, true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
ViewerState(plugin).collapsed.next({
|