Browse Source

Merge branch 'master' of https://github.com/molstar/molstar

David Sehnal 5 years ago
parent
commit
69dedd8c22

+ 17 - 6
src/mol-geo/util/marching-cubes/algorithm.ts

@@ -196,11 +196,16 @@ class MarchingCubesState {
         const n1y = sfg(sf, hi, Math.max(0, hj - 1), hk) - sfg(sf, hi, Math.min(this.nY - 1, hj + 1), hk);
         const n1z = sfg(sf, hi, hj, Math.max(0, hk - 1)) - sfg(sf, hi, hj, Math.min(this.nZ - 1, hk + 1));
 
-        this.builder.addNormal(
-            n0x + t * (n0x - n1x),
-            n0y + t * (n0y - n1y),
-            n0z + t * (n0z - n1z)
-        );
+        const nx = n0x + t * (n0x - n1x);
+        const ny = n0y + t * (n0y - n1y);
+        const nz = n0z + t * (n0z - n1z);
+
+        // ensure normal-direction is the same for negative and positive iso-levels
+        if (this.isoLevel >= 0) {
+            this.builder.addNormal(nx, ny, nz);
+        } else {
+            this.builder.addNormal(-nx, -ny, -nz);
+        }
 
         return id;
     }
@@ -255,7 +260,13 @@ class MarchingCubesState {
 
         const triInfo = TriTable[tableIndex];
         for (let t = 0; t < triInfo.length; t += 3) {
-            this.builder.addTriangle(this.vertList, triInfo[t], triInfo[t + 1], triInfo[t + 2], edgeFilter);
+            const l = triInfo[t], m = triInfo[t + 1], n = triInfo[t + 2];
+            // ensure winding-order is the same for negative and positive iso-levels
+            if (this.isoLevel >= 0) {
+                this.builder.addTriangle(this.vertList, l, m, n, edgeFilter);
+            } else {
+                this.builder.addTriangle(this.vertList, n, m, l, edgeFilter);
+            }
         }
     }
 }

+ 19 - 2
src/mol-model-formats/structure/pdb/assembly.ts

@@ -59,13 +59,13 @@ export function parseRemark350(lines: Tokens, lineStart: number, lineEnd: number
     const assemblies: PdbAssembly[] = [];
 
     // Read the assemblies
-    let current: PdbAssembly, group: PdbAssembly['groups'][0], matrix: Mat4, operId = 1;
+    let current: PdbAssembly, group: PdbAssembly['groups'][0], matrix: Mat4, operId = 1, asmId = 1;
     const getLine = (n: number) => lines.data.substring(lines.indices[2 * n], lines.indices[2 * n + 1]);
     for (let i = lineStart; i < lineEnd; i++) {
         let line = getLine(i);
         if (line.substr(11, 12) === 'BIOMOLECULE:') {
             const id = line.substr(23).trim();
-            let details: string = `Biomolecule ` + id;
+            let details = `Biomolecule ${id}`;
             line = getLine(i + 1);
             if (line.substr(11, 30) !== 'APPLY THE FOLLOWING TO CHAINS:') {
                 i++;
@@ -100,6 +100,23 @@ export function parseRemark350(lines: Tokens, lineStart: number, lineEnd: number
                 const c = chainList[j].trim();
                 if (c) group!.chains.push(c);
             }
+        } else if (line.substr(11, 33) === 'APPLYING THE FOLLOWING TO CHAINS:') {
+            // variant in older PDB format version
+            current = PdbAssembly(`${asmId}`, `Biomolecule ${asmId}`);
+            assemblies.push(current);
+            asmId += 1;
+
+            group = { chains: [], operators: [] };
+            current!.groups.push(group);
+
+            i++;
+            line = getLine(i);
+
+            const chainList = line.substr(11, 69).split(',');
+            for (let j = 0, jl = chainList.length; j < jl; ++j) {
+                const c = chainList[j].trim();
+                if (c) group!.chains.push(c);
+            }
         }
     }
 

+ 17 - 10
src/mol-model/structure/model/model.ts

@@ -25,6 +25,7 @@ import { MmcifFormat } from '../../../mol-model-formats/structure/mmcif';
 import { ChainIndex } from './indexing';
 import { SymmetryOperator } from '../../../mol-math/geometry';
 import { ModelSymmetry } from '../../../mol-model-formats/structure/property/symmetry';
+import { Column } from '../../../mol-data/db';
 
 /**
  * Interface to the "source data" of the molecule.
@@ -233,18 +234,24 @@ export namespace Model {
     }
 
     export function hasDensityMap(model: Model): boolean {
+        if (!MmcifFormat.is(model.sourceData)) return false;
+        return hasXrayMap(model) || hasEmMap(model);
+    }
+
+    export function probablyHasDensityMap(model: Model): boolean {
         if (!MmcifFormat.is(model.sourceData)) return false;
         const { db } = model.sourceData.data;
-        return (
-            hasXrayMap(model) || hasEmMap(model) || (
-                // check if from pdb archive but missing relevant meta data
-                isFromPdbArchive(model) &&
-                !db.pdbx_database_related.db_name.isDefined &&
-                !db.pdbx_database_status.status_code_sf.isDefined && (
-                    !db.exptl.method.isDefined ||
-                    isFromXray(model) ||
-                    isFromEm(model)
-                )
+        return hasDensityMap(model) || (
+            // check if from pdb archive but missing relevant meta data
+            isFromPdbArchive(model) && (
+                !db.exptl.method.isDefined ||
+                (isFromXray(model) && (
+                    !db.pdbx_database_status.status_code_sf.isDefined ||
+                    db.pdbx_database_status.status_code_sf.valueKind(0) === Column.ValueKind.Unknown
+                )) ||
+                (isFromEm(model) && (
+                    !db.pdbx_database_related.db_name.isDefined
+                ))
             )
         );
     }

+ 1 - 1
src/mol-plugin-state/formats/volume.ts

@@ -181,7 +181,7 @@ export const DscifProvider = DataFormatProvider({
 
 export const BuiltInVolumeFormats = [
     ['ccp4', Ccp4Provider] as const,
-    ['dns6', Dsn6Provider] as const,
+    ['dsn6', Dsn6Provider] as const,
     ['cube', CubeProvider] as const,
     ['dx', DxProvider] as const,
     ['dscif', DscifProvider] as const,

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

@@ -54,7 +54,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 && Model.hasDensityMap(a.data.models[0]);
+        return a.data.models.length === 1 && Model.probablyHasDensityMap(a.data.models[0]);
     }
 })(({ ref, state, params }, plugin: PluginContext) => Task.create('Volume Streaming', async taskCtx => {
     const entries: InfoEntryProps[] = [];

+ 1 - 3
src/mol-plugin/config.ts

@@ -28,9 +28,7 @@ export const PluginConfig = {
     VolumeStreaming: {
         DefaultServer: item('volume-streaming.server', 'https://ds.litemol.org'),
         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));
+            return s.models.length === 1 && Model.probablyHasDensityMap(s.models[0]);
         }),
         EmdbHeaderServer: item('volume-streaming.emdb-header-server', 'https://ftp.wwpdb.org/pub/emdb/structures'),
     },