Forráskód Böngészése

controls for validation report

Sebastian Bittrich 3 éve
szülő
commit
ebf5a07385
4 módosított fájl, 102 hozzáadás és 1 törlés
  1. 4 1
      src/viewer/index.ts
  2. 3 0
      src/viewer/types.ts
  3. 2 0
      src/viewer/ui/controls.tsx
  4. 93 0
      src/viewer/ui/validation.tsx

+ 4 - 1
src/viewer/index.ts

@@ -64,6 +64,7 @@ const DefaultViewerProps = {
     showStructureSourceControls: true,
     showSuperpositionControls: true,
     showMembraneOrientationPreset: false,
+    showValidationReportControls: true,
     /**
      * Needed when running outside of sierra. If set to true, the strucmotif UI will use an absolute URL to sierra-prod.
      * Otherwise, the link will be relative on the current host.
@@ -159,6 +160,7 @@ export class Viewer {
             showSessionControls: o.showSessionControls,
             showStructureSourceControls: o.showStructureSourceControls,
             showSuperpositionControls: o.showSuperpositionControls,
+            showValidationReportControls: o.showValidationReportControls,
             modelLoader: new ModelLoader(this.plugin),
             collapsed: new BehaviorSubject<CollapsedState>({
                 selection: true,
@@ -169,7 +171,8 @@ export class Viewer {
                 volume: true,
                 custom: true,
                 // this must be set to true as the Mp4Controls depends on the canvas which will be undefined at init() time
-                mp4export: true
+                mp4export: true,
+                validationReport: true
             }),
             detachedFromSierra: o.detachedFromSierra
         };

+ 3 - 0
src/viewer/types.ts

@@ -41,6 +41,7 @@ export type CollapsedState = {
     volume: boolean
     custom: boolean
     mp4export: boolean
+    validationReport: boolean
 }
 
 export interface ViewerState {
@@ -49,10 +50,12 @@ export interface ViewerState {
     showSessionControls: boolean
     showStructureSourceControls: boolean
     showSuperpositionControls: boolean
+    showValidationReportControls: boolean
     modelLoader: ModelLoader
     collapsed: BehaviorSubject<CollapsedState>
     detachedFromSierra: boolean
 }
+
 export function ViewerState(plugin: PluginContext) {
     return plugin.customState as ViewerState;
 }

+ 2 - 0
src/viewer/ui/controls.tsx

@@ -17,6 +17,7 @@ import { VolumeStreamingControls } from 'molstar/lib/mol-plugin-ui/structure/vol
 import { SessionControls } from './session';
 import { StrucmotifSubmitControls } from './strucmotif';
 import { Mp4EncoderUI } from 'molstar/lib/extensions/mp4-export/ui';
+import { ValidationReportControls } from './validation';
 
 export class StructureTools extends PluginUIComponent {
     get customState() {
@@ -36,6 +37,7 @@ export class StructureTools extends PluginUIComponent {
             {this.customState.showSuperpositionControls && <StructureSuperpositionControls initiallyCollapsed={collapsed.superposition} />}
             <StructureComponentControls initiallyCollapsed={collapsed.component} />
             <VolumeStreamingControls header='Density' initiallyCollapsed={collapsed.volume} />
+            {this.customState.showValidationReportControls && <ValidationReportControls initiallyCollapsed={collapsed.validationReport} />}
             <CustomStructureControls initiallyCollapsed={collapsed.custom} />
             <Mp4EncoderUI initiallyCollapsed={collapsed.mp4export}/>
         </>;

+ 93 - 0
src/viewer/ui/validation.tsx

@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Sebastian Bittrich <sebastian.bittrich@rcsb.org>
+ */
+
+import { CollapsableControls, CollapsableState } from 'molstar/lib/mol-plugin-ui/base';
+import { TuneSvg } from 'molstar/lib/mol-plugin-ui/controls/icons';
+import { StructureHierarchyManager } from 'molstar/lib/mol-plugin-state/manager/structure/hierarchy';
+import { ValidationReport } from 'molstar/lib/extensions/rcsb/validation-report/prop';
+import { ValidationReportGeometryQualityPreset } from 'molstar/lib/extensions/rcsb/validation-report/behavior';
+import { ActionMenu } from 'molstar/lib/mol-plugin-ui/controls/action-menu';
+import { Model } from 'molstar/lib/mol-model/structure/model';
+import { MmcifFormat } from 'molstar/lib/mol-model-formats/structure/mmcif';
+
+interface ValidationReportState extends CollapsableState {
+    isInitialized: boolean
+}
+
+/**
+ * A high-level component that gives access to the validation report preset.
+ */
+export class ValidationReportControls extends CollapsableControls<{}, ValidationReportState> {
+    protected defaultState() {
+        return {
+            header: 'Validation Report',
+            isCollapsed: false,
+            isHidden: true,
+            isInitialized: false,
+            brand: { accent: 'gray' as const, svg: TuneSvg } // TODO better logo
+        };
+    }
+
+    componentDidMount() {
+        this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, () => {
+            this.setState({
+                isHidden: !this.canEnable(),
+                description: StructureHierarchyManager.getSelectedStructuresDescription(this.plugin)
+            });
+        });
+    }
+
+    get pivot() {
+        return this.plugin.managers.structure.hierarchy.selection.structures[0];
+    }
+
+    canEnable() {
+        const { selection } = this.plugin.managers.structure.hierarchy;
+        if (selection.structures.length !== 1) return false;
+        const pivot = this.pivot.cell;
+        if (!pivot.obj) return false;
+        return pivot.obj.data.models.length === 1 && ValidationReport.isApplicable(pivot.obj.data.models[0]);
+    }
+
+    get noReport() {
+        const structure = this.pivot.cell.obj?.data;
+        if (!structure || structure.models.length !== 1) return true;
+        const model = structure.models[0];
+        return !model || !this.isFromPdbArchive(model);
+    }
+
+    isFromPdbArchive(model: Model) {
+        if (!MmcifFormat.is(model.sourceData)) return false;
+        return model.entryId.match(/^[1-9][a-z0-9]{3}$/i) !== null ||
+            model.entryId.match(/^pdb_[0-9]{4}[1-9][a-z0-9]{3}$/i) !== null;
+    }
+
+    requestPreset = () => {
+        ValidationReportGeometryQualityPreset.apply(this.pivot.cell, Object.create(null), this.plugin);
+    }
+
+    get actions(): ActionMenu.Items {
+        const noReport = this.noReport;
+        // TODO this could support other kinds of reports/validation like the AlphaFold confidence scores
+        return [
+            {
+                kind: 'item',
+                label: noReport ? 'No Report Available' : 'Visualize RCSB PDB Validation Report',
+                value: this.requestPreset,
+                disabled: noReport
+            },
+        ];
+    }
+
+    selectAction: ActionMenu.OnSelect = item => {
+        if (!item) return;
+        (item?.value as any)();
+    }
+
+    renderControls() {
+        return <ActionMenu items={this.actions} onSelect={this.selectAction} />;
+    }
+}