Browse Source

remove custom model export

Sebastian Bittrich 3 years ago
parent
commit
9238f085b9
6 changed files with 13 additions and 155 deletions
  1. 8 0
      CHANGELOG.md
  2. 0 97
      src/viewer/helpers/export.ts
  3. 5 8
      src/viewer/index.ts
  4. 0 1
      src/viewer/types.ts
  5. 0 2
      src/viewer/ui/controls.tsx
  6. 0 47
      src/viewer/ui/export.tsx

+ 8 - 0
CHANGELOG.md

@@ -2,6 +2,14 @@
 
 [Semantic Versioning](https://semver.org/)
 
+## [2.0.10] - 2022-02-03
+### General
+- Mol* 3.0.2
+
+### Breaking Internal Change
+- Remove `ExportControls` et al. in favor of impl from parent project
+- `viewer#exportLoadedStructures` now returns single structures directly (rather than as a ZIP file)
+
 ## [2.0.9] - 2022-01-24
 ### General
 - Update to Mol* 3.0.0 

+ 0 - 97
src/viewer/helpers/export.ts

@@ -1,97 +0,0 @@
-import { PluginContext } from 'molstar/lib/mol-plugin/context';
-import { StateObjectRef, StateSelection } from 'molstar/lib/mol-state';
-import { PluginStateObject } from 'molstar/lib/mol-plugin-state/objects';
-import { StructureSelection, Structure } from 'molstar/lib/mol-model/structure';
-import { CifExportContext, encode_mmCIF_categories } from 'molstar/lib/mol-model/structure/export/mmcif';
-import { utf8ByteCount, utf8Write } from 'molstar/lib/mol-io/common/utf8';
-import { Zip } from 'molstar/lib/mol-util/zip/zip';
-import { getFormattedTime } from 'molstar/lib/mol-util/date';
-import { download } from 'molstar/lib/mol-util/download';
-import { CustomPropertyDescriptor } from 'molstar/lib/mol-model/custom-property';
-import { CifWriter } from 'molstar/lib/mol-io/writer/cif';
-
-type encode_mmCIF_categories_Params = {
-    skipCategoryNames?: Set<string>,
-    exportCtx?: CifExportContext,
-    copyAllCategories?: boolean,
-    customProperties?: CustomPropertyDescriptor[]
-}
-
-function exportParams(): encode_mmCIF_categories_Params {
-    const skipCategories: Set<string> = new Set();
-    skipCategories
-        // Basics
-        .add('entry')
-        // Symmetry
-        .add('cell')
-        .add('symmetry')
-        // Secondary structure
-        .add('struct_conf')
-        .add('struct_sheet_range')
-        // Assemblies
-        .add('pdbx_struct_assembly')
-        .add('pdbx_struct_assembly_gen')
-        .add('pdbx_struct_oper_list');
-    return {
-        skipCategoryNames: skipCategories
-    };
-}
-
-function to_mmCIF(name: string, structure: Structure, asBinary = false) {
-    const enc = CifWriter.createEncoder({ binary: asBinary });
-    enc.startDataBlock(name);
-    encode_mmCIF_categories(enc, structure, exportParams());
-    return enc.getData();
-}
-
-function getDecorator(plugin: PluginContext, root: string): string {
-    const tree = plugin.state.data.tree;
-    const children = tree.children.get(root);
-    if (children.size !== 1) return root;
-    const child = children.first();
-    if (tree.transforms.get(child).transformer.definition.isDecorator) {
-        return getDecorator(plugin, child);
-    }
-    return root;
-}
-
-function extractStructureDataFromState(plugin: PluginContext): { [k: string]: Structure } {
-    const content: { [k: string]: Structure } = Object.create(null);
-    const cells = plugin.state.data.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Structure));
-    for (let i = 0; i < cells.length; i++) {
-        const c = cells[i];
-        // get decorated root structure
-        const rootRef = getDecorator(plugin, c.transform.ref);
-        const rootCell = StateObjectRef.resolveAndCheck(plugin.state.data, rootRef);
-        // get all leaf children of root
-        const children = plugin.state.data.tree.children.get(rootRef).toArray()
-            .map(x => plugin.state.data.select(StateSelection.Generators.byRef(x!))[0])
-            .filter(c => c.obj?.type === PluginStateObject.Molecule.Structure.type)
-            .map(x => x.obj!.data as Structure);
-        // merge children
-        const sele = StructureSelection.Sequence(rootCell!.obj!.data, children);
-        const structure = StructureSelection.unionStructure(sele);
-        const name = `${i + 1}-${structure.model.entryId}`;
-        content[name] = structure;
-    }
-    return content;
-}
-
-export function encodeStructureData(plugin: PluginContext): { [k: string]: Uint8Array } {
-    const content: { [k: string]: Uint8Array } = Object.create(null);
-    const structures = extractStructureDataFromState(plugin);
-    for (const [key, structure] of Object.entries(structures)) {
-        const filename = `${key}.cif`;
-        const str = to_mmCIF(filename, structure, false) as string;
-        const data = new Uint8Array(utf8ByteCount(str));
-        utf8Write(data, 0, str);
-        content[filename] = data;
-    }
-    return content;
-}
-
-export async function downloadAsZipFile(plugin: PluginContext, content: { [k: string]: Uint8Array }) {
-    const filename = `mol-star_download_${getFormattedTime()}.zip`;
-    const buf = await plugin.runTask(Zip(content));
-    download(new Blob([buf], { type: 'application/zip' }), filename);
-}

+ 5 - 8
src/viewer/index.ts

@@ -29,7 +29,6 @@ import { BuiltInTrajectoryFormat } from 'molstar/lib/mol-plugin-state/formats/tr
 import { ObjectKeys } from 'molstar/lib/mol-util/type-helpers';
 import { PluginLayoutControlsDisplay } from 'molstar/lib/mol-plugin/layout';
 import { SuperposeColorThemeProvider } from './helpers/superpose/color';
-import { encodeStructureData, downloadAsZipFile } from './helpers/export';
 import { setFocusFromRange, removeComponent, clearSelection, createComponent, select } from './helpers/viewer';
 import { SelectBase, SelectRange, SelectTarget, Target } from './helpers/selection';
 import { StructureRepresentationRegistry } from 'molstar/lib/mol-repr/structure/registry';
@@ -43,7 +42,8 @@ import { AnimateStateSnapshots } from 'molstar/lib/mol-plugin-state/animation/bu
 import { PluginFeatureDetection } from 'molstar/lib/mol-plugin/features';
 import { PresetStructureRepresentations } from 'molstar/lib/mol-plugin-state/builder/structure/representation-preset';
 import { MAQualityAssessment } from 'molstar/lib/extensions/model-archive/quality-assessment/behavior';
-// import { ModelExport } from 'molstar/lib/extensions/model-export';
+import { ModelExport } from 'molstar/lib/extensions/model-export';
+import { exportHierarchy } from 'molstar/lib/extensions/model-export/export';
 
 /** package version, filled in at bundle build time */
 declare const __RCSB_MOLSTAR_VERSION__: string;
@@ -59,12 +59,11 @@ const Extensions = {
     'rcsb-validation-report': PluginSpec.Behavior(RCSBValidationReport),
     'anvil-membrane-orientation': PluginSpec.Behavior(ANVILMembraneOrientation),
     'ma-quality-assessment': PluginSpec.Behavior(MAQualityAssessment),
-    // 'model-export': PluginSpec.Behavior(ModelExport), // TODO enable
+    'model-export': PluginSpec.Behavior(ModelExport),
 };
 
 const DefaultViewerProps = {
     showImportControls: false,
-    showExportControls: false,
     showSessionControls: false,
     showStructureSourceControls: true,
     showSuperpositionControls: true,
@@ -161,7 +160,6 @@ export class Viewer {
 
         (this._plugin.customState as ViewerState) = {
             showImportControls: o.showImportControls,
-            showExportControls: o.showExportControls,
             showSessionControls: o.showSessionControls,
             showStructureSourceControls: o.showStructureSourceControls,
             showSuperpositionControls: o.showSuperpositionControls,
@@ -280,9 +278,8 @@ export class Viewer {
         this._plugin.layout.events.updated.next(void 0);
     }
 
-    exportLoadedStructures() {
-        const content = encodeStructureData(this._plugin);
-        return downloadAsZipFile(this._plugin, content);
+    exportLoadedStructures(options?: { format?: 'cif' | 'bcif' }) {
+        return exportHierarchy(this.plugin, options);
     }
 
     setFocus(target: SelectRange) {

+ 0 - 1
src/viewer/types.ts

@@ -46,7 +46,6 @@ export type CollapsedState = {
 
 export interface ViewerState {
     showImportControls: boolean
-    showExportControls: boolean
     showSessionControls: boolean
     showStructureSourceControls: boolean
     showSuperpositionControls: boolean

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

@@ -8,7 +8,6 @@ import { PluginUIComponent } from 'molstar/lib/mol-plugin-ui/base';
 import { ViewerState } from '../types';
 import { CustomStructureControls } from 'molstar/lib/mol-plugin-ui/controls';
 import { ImportControls } from './import';
-import { ExportControls } from './export';
 import { StructureSourceControls } from 'molstar/lib/mol-plugin-ui/structure/source';
 import { StructureMeasurementsControls } from 'molstar/lib/mol-plugin-ui/structure/measurements';
 import { StructureSuperpositionControls } from 'molstar/lib/mol-plugin-ui/structure/superposition';
@@ -48,7 +47,6 @@ export class ControlsWrapper extends PluginUIComponent {
     render() {
         return <div className='msp-scrollable-container'>
             {ViewerState(this.plugin).showImportControls && <ImportControls />}
-            {ViewerState(this.plugin).showExportControls && <ExportControls />}
             {ViewerState(this.plugin).showSessionControls && <SessionControls />}
             <StructureTools />
         </div>;

+ 0 - 47
src/viewer/ui/export.tsx

@@ -1,47 +0,0 @@
-import { CollapsableControls, CollapsableState, PluginUIComponent } from 'molstar/lib/mol-plugin-ui/base';
-import { Button } from 'molstar/lib/mol-plugin-ui/controls/common';
-import { GetAppSvg } from 'molstar/lib/mol-plugin-ui/controls/icons';
-import { encodeStructureData, downloadAsZipFile } from '../helpers/export';
-
-export class ExportControls extends CollapsableControls {
-
-    protected defaultState(): CollapsableState {
-        return {
-            header: 'Export',
-            isCollapsed: true,
-            brand: { accent: 'gray' as const, svg: ExportOutlinedSvg }
-        };
-    }
-
-    componentDidMount() {
-        this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, sel => {
-            this.setState({ isHidden: sel.structures.length === 0 });
-        });
-    }
-
-    protected renderControls(): JSX.Element | null {
-        return <div className={'msp-control-offset'} style={{ paddingTop: '1px' }}>
-            <CoordinatesExportControls />
-        </div>;
-    }
-}
-
-class CoordinatesExportControls extends PluginUIComponent {
-    download = async () => {
-        const content = encodeStructureData(this.plugin);
-        await downloadAsZipFile(this.plugin, content);
-    };
-
-    render() {
-        return <>
-            <div className='msp-flex-row'>
-                <Button icon={GetAppSvg} onClick={this.download} title='Save structures as mmCIF files'>
-                    Structures
-                </Button>
-            </div>
-        </>;
-    }
-}
-
-function ExportOutlinedSvg() { return _ExportOutlined; }
-const _ExportOutlined = <svg width='24px' height='24px' viewBox='0 0 24 24' strokeWidth='0.1px'><path d="M19 12v7H5v-7H3v9h18v-9h-2zm-6 .67l2.59-2.58L17 11.5l-5 5-5-5 1.41-1.41L11 12.67V3h2v9.67z" /></svg>;