Browse Source

for unknown carbs draw polygonal prisms

Alexander Rose 5 years ago
parent
commit
b38193aa19

+ 14 - 2
src/mol-geo/primitive/prism.ts

@@ -78,10 +78,22 @@ export function PentagonalPrism() {
 
 let hexagonalPrism: Primitive
 export function HexagonalPrism() {
-    if (!hexagonalPrism) hexagonalPrism = Prism(polygon(6, true))
+    if (!hexagonalPrism) hexagonalPrism = Prism(polygon(6, false))
     return hexagonalPrism
 }
 
+let shiftedHexagonalPrism: Primitive
+export function ShiftedHexagonalPrism() {
+    if (!shiftedHexagonalPrism) shiftedHexagonalPrism = Prism(polygon(6, true))
+    return shiftedHexagonalPrism
+}
+
+let heptagonalPrism: Primitive
+export function HeptagonalPrism() {
+    if (!heptagonalPrism) heptagonalPrism = Prism(polygon(7, false))
+    return heptagonalPrism
+}
+
 //
 
 /**
@@ -133,6 +145,6 @@ export function PentagonalPrismCage() {
 
 let hexagonalPrismCage: Cage
 export function HexagonalPrismCage() {
-    if (!hexagonalPrismCage) hexagonalPrismCage = PrismCage(polygon(6, true))
+    if (!hexagonalPrismCage) hexagonalPrismCage = PrismCage(polygon(6, false))
     return hexagonalPrismCage
 }

+ 3 - 2
src/mol-model/structure/structure/carbohydrates/compute.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  * @author David Sehnal <david.sehnal@gmail.com>
@@ -203,7 +203,8 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates {
                     elements.push({
                         geometry: { center, normal, direction },
                         component: saccharideComp,
-                        unit, residueIndex, anomericCarbon, ringAltId
+                        unit, residueIndex, anomericCarbon, ringAltId,
+                        ringMemberCount: ringAtoms.length
                     })
                 }
 

+ 31 - 43
src/mol-model/structure/structure/carbohydrates/constants.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  * @author David Sehnal <david.sehnal@gmail.com>
@@ -9,9 +9,13 @@ import { Color, ColorMap } from '../../../../mol-util/color';
 
 // follows community standard from https://www.ncbi.nlm.nih.gov/glycans/snfg.html
 
-export const enum SaccharideShapes {
+export const enum SaccharideShape {
+    // standard shapes
     FilledSphere, FilledCube, CrossedCube, DividedDiamond, FilledCone, DevidedCone,
-    FlatBox, FilledStar, FilledDiamond, FlatDiamond, FlatHexagon, Pentagon
+    FlatBox, FilledStar, FilledDiamond, FlatDiamond, FlatHexagon, Pentagon,
+
+    // generic shapes for rings with 4, 5, 6, or 7 members
+    DiamondPrism, PentagonalPrism, HexagonalPrism, HeptagonalPrism
 }
 
 export const SaccharideColors = ColorMap({
@@ -53,22 +57,30 @@ export function getSaccharideName(type: SaccharideType) {
 }
 
 const SaccharideTypeShapeMap = {
-    [SaccharideType.Hexose]: SaccharideShapes.FilledSphere,
-    [SaccharideType.HexNAc]: SaccharideShapes.FilledCube,
-    [SaccharideType.Hexosamine]: SaccharideShapes.CrossedCube,
-    [SaccharideType.Hexuronate]: SaccharideShapes.DividedDiamond,
-    [SaccharideType.Deoxyhexose]: SaccharideShapes.FilledCone,
-    [SaccharideType.DeoxyhexNAc]: SaccharideShapes.DevidedCone,
-    [SaccharideType.DiDeoxyhexose]: SaccharideShapes.FlatBox,
-    [SaccharideType.Pentose]: SaccharideShapes.FilledStar,
-    [SaccharideType.Deoxynonulosonate]: SaccharideShapes.FilledDiamond,
-    [SaccharideType.DiDeoxynonulosonate]: SaccharideShapes.FlatDiamond,
-    [SaccharideType.Unknown]: SaccharideShapes.FlatHexagon,
-    [SaccharideType.Assigned]: SaccharideShapes.Pentagon,
+    [SaccharideType.Hexose]: SaccharideShape.FilledSphere,
+    [SaccharideType.HexNAc]: SaccharideShape.FilledCube,
+    [SaccharideType.Hexosamine]: SaccharideShape.CrossedCube,
+    [SaccharideType.Hexuronate]: SaccharideShape.DividedDiamond,
+    [SaccharideType.Deoxyhexose]: SaccharideShape.FilledCone,
+    [SaccharideType.DeoxyhexNAc]: SaccharideShape.DevidedCone,
+    [SaccharideType.DiDeoxyhexose]: SaccharideShape.FlatBox,
+    [SaccharideType.Pentose]: SaccharideShape.FilledStar,
+    [SaccharideType.Deoxynonulosonate]: SaccharideShape.FilledDiamond,
+    [SaccharideType.DiDeoxynonulosonate]: SaccharideShape.FlatDiamond,
+    [SaccharideType.Unknown]: SaccharideShape.FlatHexagon,
+    [SaccharideType.Assigned]: SaccharideShape.Pentagon,
 }
 
-export function getSaccharideShape(type: SaccharideType) {
-    return SaccharideTypeShapeMap[type]
+export function getSaccharideShape(type: SaccharideType, ringMemberCount: number): SaccharideShape {
+    if (type === SaccharideType.Unknown) {
+        if (ringMemberCount === 4) return SaccharideShape.DiamondPrism
+        else if (ringMemberCount === 5) return SaccharideShape.PentagonalPrism
+        else if (ringMemberCount === 6) return SaccharideShape.HexagonalPrism
+        else if (ringMemberCount === 7) return SaccharideShape.HeptagonalPrism
+        else return SaccharideShape.FlatHexagon
+    } else {
+        return SaccharideTypeShapeMap[type]
+    }
 }
 
 export type SaccharideComponent = {
@@ -172,19 +184,6 @@ const Monosaccharides: SaccharideComponent[] = [
     { abbr: 'Tag', name: 'Tagatose', color: SaccharideColors.Yellow, type: SaccharideType.Assigned },
     { abbr: 'Sor', name: 'Sorbose', color: SaccharideColors.Orange, type: SaccharideType.Assigned },
     { abbr: 'Psi', name: 'Psicose', color: SaccharideColors.Pink, type: SaccharideType.Assigned },
-
-    { abbr: 'Hexose', name: 'Hexose', color: SaccharideColors.Secondary, type: SaccharideType.Hexose },
-    { abbr: 'HexNAc', name: 'HexNAc', color: SaccharideColors.Secondary, type: SaccharideType.HexNAc },
-    { abbr: 'Hexosamine', name: 'Hexosamine', color: SaccharideColors.Secondary, type: SaccharideType.Hexosamine },
-    { abbr: 'Hexuronate', name: 'Hexuronate', color: SaccharideColors.Secondary, type: SaccharideType.Hexuronate },
-    { abbr: 'Deoxyhexose', name: 'Deoxyhexose', color: SaccharideColors.Secondary, type: SaccharideType.Deoxyhexose },
-    { abbr: 'DeoxyhexNAc', name: 'DeoxyhexNAc', color: SaccharideColors.Secondary, type: SaccharideType.DeoxyhexNAc },
-    { abbr: 'Di-deoxyhexose', name: 'Di-deoxyhexose', color: SaccharideColors.Secondary, type: SaccharideType.DiDeoxyhexose },
-    { abbr: 'Pentose', name: 'Pentose', color: SaccharideColors.Secondary, type: SaccharideType.Pentose },
-    { abbr: 'Deoxynonulosonate', name: 'Deoxynonulosonate', color: SaccharideColors.Secondary, type: SaccharideType.Deoxynonulosonate },
-    { abbr: 'Di-deoxynonulosonate', name: 'Di-deoxynonulosonate', color: SaccharideColors.Secondary, type: SaccharideType.DiDeoxynonulosonate	 },
-    { abbr: 'Unknown', name: 'Unknown', color: SaccharideColors.Secondary, type: SaccharideType.Unknown },
-    { abbr: 'Assigned', name: 'Assigned', color: SaccharideColors.Secondary, type: SaccharideType.Assigned },
 ]
 
 export const SaccharidesSnfgMap = (function () {
@@ -301,24 +300,13 @@ const CommonSaccharideNames: { [k: string]: string[] } = {
     Tag: ['T6T'],
     Sor: ['SOE'],
     Psi: ['PSV'],
-    // Generic
-    Hexose: [],
-    HexNAc: [],
-    Hexosamine: [],
-    Hexuronate: [],
-    Deoxyhexose: [],
-    DeoxyhexNAc: [],
-    'Di-deoxyhexose': [],
-    Pentose: [],
-    Deoxynonulosonate: [],
-    'Di-deoxynonulosonate': [],
-    Unknown: [],
-    Assigned: ['PUF'],
 }
 
 const UnknownSaccharideNames = [
     'NGZ', // via CCD
     'LAT', // BETA-LACTOSE, Gal-Glc di-saccharide via GlyFinder
+
+    'PUF', 'GDA', '9WJ', // via updated CCD
 ]
 
 export const SaccharideCompIdMap = (function () {

+ 2 - 1
src/mol-model/structure/structure/carbohydrates/data.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -30,6 +30,7 @@ export interface CarbohydrateElement {
     readonly residueIndex: ResidueIndex,
     readonly component: SaccharideComponent,
     readonly ringAltId: string,
+    readonly ringMemberCount: number,
 }
 
 /** partial carbohydrate with no ring present */

+ 35 - 17
src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -9,11 +9,11 @@ import { Box, PerforatedBox } from '../../../mol-geo/primitive/box';
 import { OctagonalPyramid, PerforatedOctagonalPyramid } from '../../../mol-geo/primitive/pyramid';
 import { Star } from '../../../mol-geo/primitive/star';
 import { Octahedron, PerforatedOctahedron } from '../../../mol-geo/primitive/octahedron';
-import { DiamondPrism, PentagonalPrism, HexagonalPrism } from '../../../mol-geo/primitive/prism';
+import { DiamondPrism, PentagonalPrism, ShiftedHexagonalPrism, HexagonalPrism, HeptagonalPrism } from '../../../mol-geo/primitive/prism';
 import { Structure, StructureElement } from '../../../mol-model/structure';
 import { Mesh } from '../../../mol-geo/geometry/mesh/mesh';
 import { MeshBuilder } from '../../../mol-geo/geometry/mesh/mesh-builder';
-import { getSaccharideShape, SaccharideShapes } from '../../../mol-model/structure/structure/carbohydrates/constants';
+import { getSaccharideShape, SaccharideShape } from '../../../mol-model/structure/structure/carbohydrates/constants';
 import { addSphere } from '../../../mol-geo/geometry/mesh/builder/sphere';
 import { ComplexMeshParams, ComplexMeshVisual } from '../complex-visual';
 import { ParamDefinition as PD } from '../../../mol-util/param-definition';
@@ -43,6 +43,8 @@ const perforatedOctahedron = PerforatedOctahedron()
 const diamondPrism = DiamondPrism()
 const pentagonalPrism = PentagonalPrism()
 const hexagonalPrism = HexagonalPrism()
+const shiftedHexagonalPrism = ShiftedHexagonalPrism()
+const heptagonalPrism = HeptagonalPrism()
 
 function createCarbohydrateSymbolMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<CarbohydrateSymbolParams>, mesh?: Mesh) {
     const builderState = MeshBuilder.createState(256, 128, mesh)
@@ -55,7 +57,7 @@ function createCarbohydrateSymbolMesh(ctx: VisualContext, structure: Structure,
 
     for (let i = 0; i < n; ++i) {
         const c = carbohydrates.elements[i];
-        const shapeType = getSaccharideShape(c.component.type)
+        const shapeType = getSaccharideShape(c.component.type, c.ringMemberCount)
 
         l.unit = c.unit
         l.element = c.unit.elements[c.anomericCarbon]
@@ -71,47 +73,47 @@ function createCarbohydrateSymbolMesh(ctx: VisualContext, structure: Structure,
         builderState.currentGroup = i * 2
 
         switch (shapeType) {
-            case SaccharideShapes.FilledSphere:
+            case SaccharideShape.FilledSphere:
                 addSphere(builderState, center, radius, detail)
                 break;
-            case SaccharideShapes.FilledCube:
+            case SaccharideShape.FilledCube:
                 Mat4.scaleUniformly(t, t, side)
                 MeshBuilder.addPrimitive(builderState, t, box)
                 break;
-            case SaccharideShapes.CrossedCube:
+            case SaccharideShape.CrossedCube:
                 Mat4.scaleUniformly(t, t, side)
                 MeshBuilder.addPrimitive(builderState, t, perforatedBox)
                 Mat4.mul(t, t, Mat4.rotZ90X180)
                 builderState.currentGroup += 1
                 MeshBuilder.addPrimitive(builderState, t, perforatedBox)
                 break;
-            case SaccharideShapes.FilledCone:
+            case SaccharideShape.FilledCone:
                 Mat4.scaleUniformly(t, t, side * 1.2)
                 MeshBuilder.addPrimitive(builderState, t, octagonalPyramid)
                 break
-            case SaccharideShapes.DevidedCone:
+            case SaccharideShape.DevidedCone:
                 Mat4.scaleUniformly(t, t, side * 1.2)
                 MeshBuilder.addPrimitive(builderState, t, perforatedOctagonalPyramid)
                 Mat4.mul(t, t, Mat4.rotZ90)
                 builderState.currentGroup += 1
                 MeshBuilder.addPrimitive(builderState, t, perforatedOctagonalPyramid)
                 break
-            case SaccharideShapes.FlatBox:
+            case SaccharideShape.FlatBox:
                 Mat4.mul(t, t, Mat4.rotZY90)
                 Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2))
                 MeshBuilder.addPrimitive(builderState, t, box)
                 break
-            case SaccharideShapes.FilledStar:
+            case SaccharideShape.FilledStar:
                 Mat4.scaleUniformly(t, t, side)
                 Mat4.mul(t, t, Mat4.rotZY90)
                 MeshBuilder.addPrimitive(builderState, t, star)
                 break
-            case SaccharideShapes.FilledDiamond:
+            case SaccharideShape.FilledDiamond:
                 Mat4.mul(t, t, Mat4.rotZY90)
                 Mat4.scale(t, t, Vec3.set(sVec, side * 1.4, side * 1.4, side * 1.4))
                 MeshBuilder.addPrimitive(builderState, t, octahedron)
                 break
-            case SaccharideShapes.DividedDiamond:
+            case SaccharideShape.DividedDiamond:
                 Mat4.mul(t, t, Mat4.rotZY90)
                 Mat4.scale(t, t, Vec3.set(sVec, side * 1.4, side * 1.4, side * 1.4))
                 MeshBuilder.addPrimitive(builderState, t, perforatedOctahedron)
@@ -119,21 +121,37 @@ function createCarbohydrateSymbolMesh(ctx: VisualContext, structure: Structure,
                 builderState.currentGroup += 1
                 MeshBuilder.addPrimitive(builderState, t, perforatedOctahedron)
                 break
-            case SaccharideShapes.FlatDiamond:
+            case SaccharideShape.FlatDiamond:
                 Mat4.mul(t, t, Mat4.rotZY90)
                 Mat4.scale(t, t, Vec3.set(sVec, side, side / 2, side / 2))
                 MeshBuilder.addPrimitive(builderState, t, diamondPrism)
                 break
-            case SaccharideShapes.Pentagon:
+            case SaccharideShape.DiamondPrism:
+                Mat4.mul(t, t, Mat4.rotZY90)
+                Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2))
+                MeshBuilder.addPrimitive(builderState, t, diamondPrism)
+                break
+            case SaccharideShape.PentagonalPrism:
+            case SaccharideShape.Pentagon:
                 Mat4.mul(t, t, Mat4.rotZY90)
                 Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2))
                 MeshBuilder.addPrimitive(builderState, t, pentagonalPrism)
                 break
-            case SaccharideShapes.FlatHexagon:
+            case SaccharideShape.HexagonalPrism:
+                Mat4.mul(t, t, Mat4.rotZY90)
+                Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2))
+                MeshBuilder.addPrimitive(builderState, t, hexagonalPrism)
+                break
+            case SaccharideShape.HeptagonalPrism:
+                Mat4.mul(t, t, Mat4.rotZY90)
+                Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2))
+                MeshBuilder.addPrimitive(builderState, t, heptagonalPrism)
+                break
+            case SaccharideShape.FlatHexagon:
             default:
                 Mat4.mul(t, t, Mat4.rotZYZ90)
                 Mat4.scale(t, t, Vec3.set(sVec, side / 1.5, side , side / 2))
-                MeshBuilder.addPrimitive(builderState, t, hexagonalPrism)
+                MeshBuilder.addPrimitive(builderState, t, shiftedHexagonalPrism)
                 break
         }
     }