Browse Source

added helpers to Model, better InitVolumeStreaming.isApplicable check

Alexander Rose 5 years ago
parent
commit
3cd9042c72

+ 6 - 11
src/mol-model-props/computed/secondary-structure.ts

@@ -12,8 +12,8 @@ import { Unit } from '../../mol-model/structure/structure';
 import { CustomStructureProperty } from '../common/custom-structure-property';
 import { CustomProperty } from '../common/custom-property';
 import { ModelSecondaryStructure } from '../../mol-model-formats/structure/property/secondary-structure';
-import { MmcifFormat } from '../../mol-model-formats/structure/mmcif';
 import { CustomPropertyDescriptor } from '../../mol-model/structure/common/custom-property';
+import { Model } from '../../mol-model/structure/model';
 
 function getSecondaryStructureParams(data?: Structure) {
     let defaultType = 'model' as 'model' | 'dssp'
@@ -21,16 +21,11 @@ function getSecondaryStructureParams(data?: Structure) {
         defaultType = 'dssp'
         for (let i = 0, il = data.models.length; i < il; ++i) {
             const m = data.models[i]
-            if (MmcifFormat.is(m.sourceData)) {
-                if (m.sourceData.data.db.struct_conf.id.isDefined ||
-                    m.sourceData.data.db.struct_sheet_range.id.isDefined ||
-                    m.sourceData.data.db.database_2.database_id.isDefined
-                ) {
-                    // if there is any secondary structure definition given or if there is
-                    // an archival model, don't calculate dssp by default
-                    defaultType = 'model'
-                    break
-                }
+            if (Model.isFromPdbArchive(m) || Model.hasSecondaryStructure(m)) {
+                // if there is any secondary structure definition given or if there is
+                // an archival model, don't calculate dssp by default
+                defaultType = 'model'
+                break
             }
         }
     }

+ 79 - 0
src/mol-model/structure/model/model.ts

@@ -21,6 +21,7 @@ import { Topology } from '../topology';
 import { Task } from '../../../mol-task';
 import { IndexPairBonds } from '../../../mol-model-formats/structure/property/bonds/index-pair';
 import { createModels } from '../../../mol-model-formats/structure/basic/parser';
+import { MmcifFormat } from '../../../mol-model-formats/structure/mmcif';
 
 /**
  * Interface to the "source data" of the molecule.
@@ -135,4 +136,82 @@ export namespace Model {
         model._dynamicPropertyData[CenterProp] = center
         return center
     }
+
+    //
+
+    export function isFromPdbArchive(model: Model) {
+        if (!MmcifFormat.is(model.sourceData)) return false
+        const { db } = model.sourceData.data
+        return (
+            db.database_2.database_id.isDefined
+        )
+    }
+
+    export function hasSecondaryStructure(model: Model) {
+        if (!MmcifFormat.is(model.sourceData)) return false
+        const { db } = model.sourceData.data
+        return (
+            db.struct_conf.id.isDefined ||
+            db.struct_sheet_range.id.isDefined
+        )
+    }
+
+    export function hasCrystalSymmetry(model: Model) {
+        if (!MmcifFormat.is(model.sourceData)) return false
+        const { db } = model.sourceData.data
+        return (
+            db.symmetry._rowCount === 1 && db.cell._rowCount === 1 && !(
+                db.symmetry.Int_Tables_number.value(0) === 1 &&
+                db.cell.angle_alpha.value(0) === 90 &&
+                db.cell.angle_beta.value(0) === 90 &&
+                db.cell.angle_gamma.value(0) === 90 &&
+                db.cell.length_a.value(0) === 1 &&
+                db.cell.length_b.value(0) === 1 &&
+                db.cell.length_c.value(0) === 1
+            )
+        )
+    }
+
+    export function isFromXray(model: Model) {
+        if (!MmcifFormat.is(model.sourceData)) return false
+        const { db } = model.sourceData.data
+        for (let i = 0; i < db.exptl.method.rowCount; i++) {
+            const v = db.exptl.method.value(i).toUpperCase()
+            if (v.indexOf('DIFFRACTION') >= 0) return true
+        }
+        return false
+    }
+
+    export function isFromNmr(model: Model) {
+        if (!MmcifFormat.is(model.sourceData)) return false
+        const { db } = model.sourceData.data
+        for (let i = 0; i < db.exptl.method.rowCount; i++) {
+            const v = db.exptl.method.value(i).toUpperCase()
+            if (v.indexOf('NMR') >= 0) return true
+        }
+        return false
+    }
+
+    export function hasXrayMap(model: Model) {
+        if (!MmcifFormat.is(model.sourceData)) return false
+        const { db } = model.sourceData.data
+        return db.pdbx_database_status.status_code_sf.value(0) === 'REL'
+    }
+
+    export function hasEmMap(model: Model) {
+        if (!MmcifFormat.is(model.sourceData)) return false
+        const { db } = model.sourceData.data
+        let hasEmMap = false
+        for (let i = 0, il = db.pdbx_database_related._rowCount; i < il; ++i) {
+            if (db.pdbx_database_related.db_name.value(i).toUpperCase() === 'EMDB') {
+                hasEmMap = true
+                break
+            }
+        }
+        return hasEmMap
+    }
+
+    export function hasDensityMap(model: Model) {
+        return hasXrayMap(model) || hasEmMap(model)
+    }
 }

+ 2 - 1
src/mol-plugin/behavior/dynamic/volume-streaming/transformers.ts

@@ -22,6 +22,7 @@ import { Theme } from '../../../../mol-theme/theme';
 import { Box3D } from '../../../../mol-math/geometry';
 import { Vec3 } from '../../../../mol-math/linear-algebra';
 import { PluginConfig } from '../../../config';
+import { Model } from '../../../../mol-model/structure';
 
 function addEntry(entries: InfoEntryProps[], method: VolumeServerInfo.Kind, dataId: string, emDefaultContourLevel: number) {
     entries.push({
@@ -54,7 +55,7 @@ export const InitVolumeStreaming = StateAction.build({
     isApplicable: (a, _, plugin: PluginContext) => {
         const canStreamTest = plugin.config.get(PluginConfig.VolumeStreaming.CanStream);
         if (canStreamTest) return canStreamTest(a.data, plugin);
-        return a.data.models.length === 1;
+        return a.data.models.length === 1 && Model.hasDensityMap(a.data.models[0]);
     }
 })(({ ref, state, params }, plugin: PluginContext) => Task.create('Volume Streaming', async taskCtx => {
     const entries: InfoEntryProps[] = []

+ 7 - 2
src/mol-plugin/config.ts

@@ -2,9 +2,10 @@
  * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Structure } from '../mol-model/structure';
+import { Structure, Model } from '../mol-model/structure';
 import { PluginContext } from './context';
 
 export class PluginConfigItem<T = any> {
@@ -23,7 +24,11 @@ export const PluginConfig = {
     },
     VolumeStreaming: {
         DefaultServer: item('volume-streaming.server', 'https://ds.litemol.org'),
-        CanStream: item('volume-streaming.can-stream', (s: Structure, plugin: PluginContext) => s.models.length === 1)
+        CanStream: item('volume-streaming.can-stream', (s: Structure, plugin: PluginContext) => {
+            return s.models.length === 1 && (Model.hasDensityMap(s.models[0])
+                // the following test is to include e.g. 'updated' files from PDBe
+                || (!Model.isFromPdbArchive(s.models[0]) && s.models[0].entryId.length === 4))
+        })
     }
 }