Alexander Rose 6 years ago
parent
commit
b21aff7a4a

+ 2 - 2
src/mol-app/ui/entity/tree.tsx

@@ -13,13 +13,13 @@ import { View } from '../view';
 import { EntityTreeController } from '../../controller/entity/tree';
 import { Controller } from '../../controller/controller';
 import { AnyEntity, RootEntity } from 'mol-view/state/entity';
-import { AnyTransform, SpacefillUpdate, UrlToData, DataToCif, FileToData, CifToMmcif, MmcifToModel, ModelToStructure, StructureToSpacefill, MmcifFileToSpacefill, StructureCenter, StructureToBallAndStick, DistanceRestraintUpdate, CartoonUpdate, BallAndStickUpdate, BackboneUpdate } from 'mol-view/state/transform';
+import { AnyTransform, SpacefillUpdate, UrlToData, DataToCif, FileToData, CifToMmcif, MmcifToModel, ModelToStructure, StructureToSpacefill, MmcifFileToSpacefill, StructureCenter, StructureToBallAndStick, DistanceRestraintUpdate, CartoonUpdate, BallAndStickUpdate, BackboneUpdate, MmcifUrlToSpacefill } from 'mol-view/state/transform';
 
 function getTransforms(entity: AnyEntity): AnyTransform[] {
     const transforms: AnyTransform[] = []
     switch (entity.kind) {
         case 'root':
-            transforms.push(MmcifFileToSpacefill)
+            transforms.push(MmcifFileToSpacefill, MmcifUrlToSpacefill)
             break;
         case 'url':
             transforms.push(UrlToData)

+ 3 - 0
src/mol-app/ui/transform/list.tsx

@@ -22,9 +22,12 @@ import { StructureCenter } from './structure';
 import { Cartoon } from './cartoon';
 import { DistanceRestraint } from './distance-restraint';
 import { Backbone } from './backbone';
+import { UrlLoader } from './url-loader';
 
 function getTransformComponent(controller: TransformListController, entity: AnyEntity, transform: AnyTransform) {
     switch (transform.kind) {
+        case 'url-to-spacefill':
+            return <UrlLoader controller={controller} ctx={controller.context.stage.ctx}></UrlLoader>
         case 'file-to-spacefill':
             return <FileLoader controller={controller} ctx={controller.context.stage.ctx}></FileLoader>
         case 'model-to-structure':

+ 124 - 0
src/mol-app/ui/transform/url-loader.tsx

@@ -0,0 +1,124 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import * as React from 'react'
+import { View } from '../view';
+import { TransformListController } from '../../controller/transform/list';
+import { UrlEntity } from 'mol-view/state/entity';
+import { ModelToStructure, StructureToBallAndStick, StructureToSpacefill, StructureToDistanceRestraint, StructureToBackbone, MmcifUrlToModel, StructureToCartoon } from 'mol-view/state/transform';
+import { StateContext } from 'mol-view/state/context';
+import { SpacefillProps } from 'mol-geo/representation/structure/spacefill';
+import { BallAndStickProps } from 'mol-geo/representation/structure/ball-and-stick';
+import { DistanceRestraintProps } from 'mol-geo/representation/structure/distance-restraint';
+import { BackboneProps } from 'mol-geo/representation/structure/backbone';
+import { CartoonProps } from 'mol-geo/representation/structure/cartoon';
+
+const spacefillProps: SpacefillProps = {
+    doubleSided: true,
+    colorTheme: { name: 'chain-id' },
+    quality: 'auto',
+    useFog: false
+}
+
+const ballAndStickProps: BallAndStickProps = {
+    doubleSided: true,
+    colorTheme: { name: 'chain-id' },
+    sizeTheme: { name: 'uniform', value: 0.05 },
+    linkRadius: 0.05,
+    quality: 'auto',
+    useFog: false
+}
+
+const distanceRestraintProps: DistanceRestraintProps = {
+    doubleSided: true,
+    colorTheme: { name: 'chain-id' },
+    linkRadius: 0.5,
+    quality: 'auto',
+    useFog: false
+}
+
+const backboneProps: BackboneProps = {
+    doubleSided: true,
+    colorTheme: { name: 'chain-id' },
+    quality: 'auto',
+    useFog: false
+}
+
+const cartoonProps: CartoonProps = {
+    doubleSided: true,
+    colorTheme: { name: 'chain-id' },
+    quality: 'auto',
+    useFog: false
+}
+
+function getPdbdevUrl(pdbdevId: string) {
+    return `https://pdb-dev.wwpdb.org/static/cif/${pdbdevId}.cif`
+}
+
+const exampleUrls = {
+    PDBDEV_00000001: getPdbdevUrl('PDBDEV_00000001'), // ok
+    PDBDEV_00000002: getPdbdevUrl('PDBDEV_00000002'), // ok
+    PDBDEV_00000003: getPdbdevUrl('PDBDEV_00000003'), // ok
+    PDBDEV_00000004: getPdbdevUrl('PDBDEV_00000004'), // TODO issue with cross-link extraction
+    PDBDEV_00000005: getPdbdevUrl('PDBDEV_00000005'), // ok
+    PDBDEV_00000006: getPdbdevUrl('PDBDEV_00000006'), // TODO only three spacefill atoms rendered
+    PDBDEV_00000007: getPdbdevUrl('PDBDEV_00000007'), // TODO only three spacefill atoms rendered
+    PDBDEV_00000008: getPdbdevUrl('PDBDEV_00000008'), // ok
+    PDBDEV_00000010: getPdbdevUrl('PDBDEV_00000010'), // ok
+    PDBDEV_00000011: getPdbdevUrl('PDBDEV_00000011'), // ok
+    PDBDEV_00000012: getPdbdevUrl('PDBDEV_00000012'), // ok
+    PDBDEV_00000014: getPdbdevUrl('PDBDEV_00000014'), // ok
+    PDBDEV_00000016: getPdbdevUrl('PDBDEV_00000016'),
+}
+
+export class UrlLoader extends View<TransformListController, { }, { ctx: StateContext }> {
+    async load(name: keyof typeof exampleUrls) {
+        console.log(exampleUrls[name])
+        const ctx = this.props.ctx
+        const urlEntity = UrlEntity.ofUrl(ctx, exampleUrls[name])
+        console.log(await urlEntity.value.getData())
+        const modelEntity = await MmcifUrlToModel.apply(ctx, urlEntity)
+        const structureEntity = await ModelToStructure.apply(ctx, modelEntity)
+
+        StructureToBallAndStick.apply(ctx, structureEntity, { ...ballAndStickProps, visible: true })
+        StructureToSpacefill.apply(ctx, structureEntity, { ...spacefillProps, visible: false })
+        StructureToDistanceRestraint.apply(ctx, structureEntity, { ...distanceRestraintProps, visible: false })
+        StructureToBackbone.apply(ctx, structureEntity, { ...backboneProps, visible: true })
+        StructureToCartoon.apply(ctx, structureEntity, { ...cartoonProps, visible: false })
+    }
+
+    render() {
+        const exampleOptions = Object.keys(exampleUrls).map(name => {
+            return <option key={name} value={name}>{name}</option>
+        })
+
+        return <div className='molstar-transformer-wrapper'>
+            <div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'>
+                <div className='molstar-panel-body'>
+                    <div>
+                        <div className='molstar-control-row molstar-options-group'>
+                            <span>Examples</span>
+                            <div>
+                                <select
+                                    className='molstar-form-control'
+                                    value=''
+                                    onChange={(e) => {
+                                        if (e.target.value) {
+                                            this.load(e.target.value as keyof typeof exampleUrls)}
+                                        }
+                                    }
+                                >
+                                    <option key='' value=''></option>
+                                    {exampleOptions}
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>;
+    }
+}

+ 1 - 0
src/mol-data/int/impl/segmentation.ts

@@ -41,6 +41,7 @@ export function ofOffsets(offsets: ArrayLike<number>, bounds: Interval): Segment
     return create(segments);
 }
 
+/** Get number of segments in a segmentation */
 export function count({ count }: Segmentation) { return count; }
 export function getSegment({ segmentMap }: Segmentation, value: number) { return segmentMap[value]; }
 

+ 3 - 3
src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts

@@ -33,9 +33,9 @@ async function createPolymerBackboneCylinderMesh(ctx: RuntimeContext, unit: Unit
     const builder = MeshBuilder.create(polymerElementCount * 30, polymerElementCount * 30 / 2, mesh)
 
     let i = 0
-    const polymerTraceIt = PolymerBackboneIterator(unit)
-    while (polymerTraceIt.hasNext) {
-        const { indexA, indexB, posA, posB } = polymerTraceIt.move()
+    const polymerBackboneIt = PolymerBackboneIterator(unit)
+    while (polymerBackboneIt.hasNext) {
+        const { indexA, indexB, posA, posB } = polymerBackboneIt.move()
         builder.setId(indexA)
         // TODO size theme
         builder.addCylinder(posA, posB, 0.5, { radiusTop: 0.2, radiusBottom: 0.2 })

+ 35 - 7
src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts

@@ -23,7 +23,20 @@ import { Loci, EmptyLoci } from 'mol-model/loci';
 import { SizeTheme } from '../../../theme';
 import { createMeshValues, updateMeshValues, updateRenderableState, createRenderableState, DefaultMeshProps } from '../../util';
 import { MeshBuilder } from '../../../shape/mesh-builder';
-import { getPolymerElementCount, PolymerBackboneIterator } from './util/polymer';
+import { getPolymerElementCount, PolymerTraceIterator } from './util/polymer';
+import { Vec3 } from 'mol-math/linear-algebra';
+
+// export function spline(target: THREE.Vector3, p1: THREE.Vector3, p2: THREE.Vector3, p3: THREE.Vector3, t: number) {
+//     let a = Math.pow(1 - t, 2) / 2;
+//     let c = Math.pow(t, 2) / 2;
+//     let b = 1 - a - c;
+
+//     let x = a * p1.x + b * p2.x + c * p3.x;
+//     let y = a * p1.y + b * p2.y + c * p3.y;
+//     let z = a * p1.z + b * p2.z + c * p3.z;
+
+//     target.set(x, y, z);
+// }
 
 async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Mesh) {
     const polymerElementCount = getPolymerElementCount(unit)
@@ -32,16 +45,31 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me
 
     // TODO better vertex count estimates
     const builder = MeshBuilder.create(polymerElementCount * 30, polymerElementCount * 30 / 2, mesh)
+    const linearSegmentCount = 10
+
+    const v0 = Vec3.zero()
+    const v1 = Vec3.zero()
 
     let i = 0
-    const polymerTraceIt = PolymerBackboneIterator(unit)
+    const polymerTraceIt = PolymerTraceIterator(unit)
     while (polymerTraceIt.hasNext) {
         const v = polymerTraceIt.move()
-        builder.setId(v.indexA)
-        // TODO size theme
-        builder.addCylinder(v.posA, v.posB, 0.5, { radiusTop: 0.2, radiusBottom: 0.2 })
-        builder.setId(v.indexB)
-        builder.addCylinder(v.posB, v.posA, 0.5, { radiusTop: 0.2, radiusBottom: 0.2 })
+
+        Vec3.spline(v1, v.c0, v.c1, v.c2, v.c3, 0.5, 0.5)
+
+        builder.setId(v.index)
+        for (let j = 1; j <= linearSegmentCount; ++j) {
+            let t = j * 1.0 / linearSegmentCount;
+            Vec3.copy(v0, v1)
+            // if ((v.last && t > 0.5) || (v.first && t < 0.5)) break
+            if (t < 0.5) {
+                Vec3.spline(v1, v.c0, v.c1, v.c2, v.c3, t + 0.5, 0.5)
+            } else {
+                Vec3.spline(v1, v.c1, v.c2, v.c3, v.c4, t - 0.5, 0.5)
+            }
+            // TODO size theme
+            builder.addCylinder(v0, v1, 1.0, { radiusTop: 0.1, radiusBottom: 0.1 })
+        }
 
         if (i % 10000 === 0 && ctx.shouldUpdate) {
             await ctx.update({ message: 'Backbone mesh', current: i, max: polymerElementCount });

+ 130 - 52
src/mol-geo/representation/structure/visual/util/polymer.ts

@@ -4,7 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Unit, Element, StructureProperties } from 'mol-model/structure';
+import { Unit, Element, StructureProperties, Model } from 'mol-model/structure';
 import { Segmentation } from 'mol-data/int';
 import { MoleculeType } from 'mol-model/structure/model/types';
 import Iterator from 'mol-data/iterator';
@@ -12,6 +12,18 @@ import { SegmentIterator } from 'mol-data/int/impl/segmentation';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { SymmetryOperator } from 'mol-math/geometry';
 
+// type TraceMap = Map<number, number>
+
+// interface TraceMaps {
+//     atomic: TraceMap
+//     spheres: TraceMap
+//     gaussians: TraceMap
+// }
+
+// function calculateTraceMaps (model: Model): TraceMaps {
+
+// }
+
 export function getPolymerElementCount(unit: Unit) {
     let count = 0
     const { elements } = unit
@@ -62,6 +74,33 @@ function setTraceElement(l: Element.Location, residueSegment: Segmentation.Segme
     return residueSegment.end - 1
 }
 
+
+function getTraceName2(model: Model, residueModelIndex: number) {
+    const compId = model.atomicHierarchy.residues.label_comp_id.value(residueModelIndex)
+    const chemCompMap = model.properties.chemicalComponentMap
+    const cc = chemCompMap.get(compId)
+    const moleculeType = cc ? cc.moleculeType : MoleculeType.unknown
+    let traceName = ''
+    if (moleculeType === MoleculeType.protein) {
+        traceName = 'CA'
+    } else if (moleculeType === MoleculeType.DNA || moleculeType === MoleculeType.RNA) {
+        traceName = 'P'
+    }
+    return traceName
+}
+
+function getTraceElement2(model: Model, residueModelSegment: Segmentation.Segment<Element>) {
+    const traceName = getTraceName2(model, residueModelSegment.index)
+
+    for (let j = residueModelSegment.start, _j = residueModelSegment.end; j < _j; j++) {
+        if (model.atomicHierarchy.atoms.label_atom_id.value(j) === traceName) return j
+    }
+    console.log('trace name element not found', { ...residueModelSegment })
+    return residueModelSegment.start
+}
+
+
+
 /** Iterates over consecutive pairs of residues/coarse elements in polymers */
 export function PolymerBackboneIterator(unit: Unit): Iterator<PolymerBackbonePair> {
     switch (unit.kind) {
@@ -125,7 +164,6 @@ export class AtomicPolymerBackboneIterator<T extends number = number> implements
             } else {
                 this.state = AtomicPolymerBackboneIteratorState.nextPolymer
             }
-
         }
 
         if (this.state === AtomicPolymerBackboneIteratorState.nextResidue) {
@@ -210,7 +248,6 @@ export class CoarsePolymerBackboneIterator<T extends number = number> implements
         }
 
         this.hasNext = this.elementIndex + 1 < this.polymerSegment.end || polymerIt.hasNext
-
         return this.value;
     }
 
@@ -246,73 +283,108 @@ export function PolymerTraceIterator(unit: Unit): Iterator<PolymerTraceElement>
 interface PolymerTraceElement {
     center: Element.Location
     index: number
-    pos: Vec3
-    posPrev: Vec3
-    posNext: Vec3
-    posNextNext: Vec3
+    first: boolean
+    last: boolean
+    c0: Vec3
+    c1: Vec3
+    c2: Vec3
+    c3: Vec3
+    c4: Vec3
 }
 
 function createPolymerTraceElement (unit: Unit) {
     return {
         center: Element.Location(unit),
         index: 0,
-        pos: Vec3.zero(),
-        posPrev: Vec3.zero(),
-        posNext: Vec3.zero(),
-        posNextNext: Vec3.zero()
+        first: false,
+        last: false,
+        c0: Vec3.zero(),
+        c1: Vec3.zero(),
+        c2: Vec3.zero(),
+        c3: Vec3.zero(),
+        c4: Vec3.zero()
     }
 }
 
-// const enum AtomicPolymerTraceIteratorState { nextPolymer, firstResidue, nextResidue }
+const enum AtomicPolymerTraceIteratorState { nextPolymer, nextResidue }
+
+function setSegment (outSegment: Segmentation.Segment<Element>, index: number, segments: Segmentation<Element>, boundingSegment: Segmentation.Segment<Element>): Segmentation.Segment<Element> {
+    index = Math.min(Math.max(0, index), segments.segments.length - 2)
+    outSegment.index = index
+    outSegment.start = segments.segments[index]
+    outSegment.end = segments.segments[index + 1]
+    return outSegment
+}
+
+// const p0 = Vec3.zero()
+// const p1 = Vec3.zero()
+// const p2 = Vec3.zero()
+// const p3 = Vec3.zero()
+// const p4 = Vec3.zero()
+// const p5 = Vec3.zero()
+// const p6 = Vec3.zero()
 
 export class AtomicPolymerTraceIterator<T extends number = number> implements Iterator<PolymerTraceElement> {
     private value: PolymerTraceElement
 
     private polymerIt: SegmentIterator<Element>
     private residueIt: SegmentIterator<Element>
-    // private polymerSegment: Segmentation.Segment<Element>
-    // private state: AtomicPolymerTraceIteratorState = AtomicPolymerTraceIteratorState.nextPolymer
-    // private pos: SymmetryOperator.CoordinateMapper
+    private polymerSegment: Segmentation.Segment<Element>
+    private state: AtomicPolymerTraceIteratorState = AtomicPolymerTraceIteratorState.nextPolymer
+    private residueSegments: Segmentation<Element>
+
+    private tmpSegment: Segmentation.Segment<Element>
+
+    private unit: Unit.Atomic
 
     hasNext: boolean = false;
 
+    private pos(target: Vec3, index: number) {
+        target[0] = this.unit.model.atomicConformation.x[index]
+        target[1] = this.unit.model.atomicConformation.y[index]
+        target[2] = this.unit.model.atomicConformation.z[index]
+    }
+
     move() {
-        // const { residueIt, polymerIt, value, pos } = this
-
-        // if (this.state === AtomicPolymerTraceIteratorState.nextPolymer) {
-        //     if (polymerIt.hasNext) {
-        //         this.polymerSegment = polymerIt.move();
-        //         residueIt.setSegment(this.polymerSegment);
-        //         this.state = AtomicPolymerTraceIteratorState.firstResidue
-        //     }
-        // }
-
-        // if (this.state === AtomicPolymerTraceIteratorState.firstResidue) {
-        //     const residueSegment = residueIt.move();
-        //     if (residueIt.hasNext) {
-        //         value.indexB = setTraceElement(value.centerB, residueSegment)
-        //         pos(value.centerB.element, value.posB)
-        //         this.state = AtomicPolymerTraceIteratorState.nextResidue
-        //     } else {
-        //         this.state = AtomicPolymerTraceIteratorState.nextPolymer
-        //     }
-
-        // }
-
-        // if (this.state === AtomicPolymerTraceIteratorState.nextResidue) {
-        //     const residueSegment = residueIt.move();
-        //     value.centerA.element = value.centerB.element
-        //     value.indexA = value.indexB
-        //     Vec3.copy(value.posA, value.posB)
-        //     value.indexB = setTraceElement(value.centerB, residueSegment)
-        //     pos(value.centerB.element, value.posB)
-
-        //     if (!residueIt.hasNext) {
-        //         this.state = AtomicPolymerTraceIteratorState.nextPolymer
-        //     }
-        // }
-
-        // this.hasNext = residueIt.hasNext || polymerIt.hasNext
+        const { residueIt, polymerIt, value } = this
+        value.first = false
+        value.last = false
+
+        if (this.state === AtomicPolymerTraceIteratorState.nextPolymer) {
+            if (polymerIt.hasNext) {
+                this.polymerSegment = polymerIt.move();
+                residueIt.setSegment(this.polymerSegment);
+                this.state = AtomicPolymerTraceIteratorState.nextResidue
+                value.first = true
+            }
+        }
+
+        if (this.state === AtomicPolymerTraceIteratorState.nextResidue) {
+            const residueSegment = residueIt.move();
+            value.index = setTraceElement(value.center, residueSegment)
+
+            setSegment(this.tmpSegment, residueSegment.index - 2, this.residueSegments, this.polymerSegment)
+            this.pos(value.c0, getTraceElement2(this.unit.model, this.tmpSegment))
+
+            setSegment(this.tmpSegment, residueSegment.index - 1, this.residueSegments, this.polymerSegment)
+            this.pos(value.c1, getTraceElement2(this.unit.model, this.tmpSegment))
+
+            setSegment(this.tmpSegment, residueSegment.index, this.residueSegments, this.polymerSegment)
+            this.pos(value.c2, getTraceElement2(this.unit.model, this.tmpSegment))
+
+            setSegment(this.tmpSegment, residueSegment.index + 1, this.residueSegments, this.polymerSegment)
+            this.pos(value.c3, getTraceElement2(this.unit.model, this.tmpSegment))
+
+            setSegment(this.tmpSegment, residueSegment.index + 2, this.residueSegments, this.polymerSegment)
+            this.pos(value.c4, getTraceElement2(this.unit.model, this.tmpSegment))
+
+            if (!residueIt.hasNext) {
+                this.state = AtomicPolymerTraceIteratorState.nextPolymer
+                value.last = true
+            }
+        }
+
+        this.hasNext = residueIt.hasNext || polymerIt.hasNext
 
         return this.value;
     }
@@ -321,9 +393,15 @@ export class AtomicPolymerTraceIterator<T extends number = number> implements It
         const { polymerSegments, residueSegments } = unit.model.atomicHierarchy
         this.polymerIt = Segmentation.transientSegments(polymerSegments, unit.elements);
         this.residueIt = Segmentation.transientSegments(residueSegments, unit.elements);
-        // this.pos = unit.conformation.invariantPosition
+        this.residueSegments = residueSegments
         this.value = createPolymerTraceElement(unit)
         this.hasNext = this.residueIt.hasNext || this.polymerIt.hasNext
+
+        this.tmpSegment = { index: 0, start: 0 as Element, end: 0 as Element }
+
+        this.unit = unit
+        console.log('model', unit.model)
+        console.log('unit', unit)
     }
 }
 

+ 12 - 0
src/mol-math/linear-algebra/3d/vec3.ts

@@ -19,6 +19,7 @@
 
 import Mat4 from './mat4';
 import { Quat, Mat3 } from '../3d';
+import { spline as _spline } from '../../interpolate'
 
 interface Vec3 extends Array<number> { [d: number]: number, '@type': 'vec3', length: 3 }
 
@@ -279,6 +280,17 @@ namespace Vec3 {
         return out;
     }
 
+    /**
+     * Performs a spline interpolation with two control points and a tension parameter
+     */
+    export function spline(out: Vec3, a: Vec3, b: Vec3, c: Vec3, d: Vec3, t: number, tension: number) {
+        out[0] = _spline(a[0], b[0], c[0], d[0], t, tension);
+        out[1] = _spline(a[1], b[1], c[1], d[1], t, tension);
+        out[2] = _spline(a[2], b[2], c[2], d[2], t, tension);
+
+        return out;
+    }
+
     /**
      * Generates a random vector with the given scale
      */

+ 0 - 1
src/mol-model/structure/model/formats/mmcif/atomic.ts

@@ -78,7 +78,6 @@ function isHierarchyDataEqual(a: AtomicData, b: AtomicData) {
         && Table.areEqual(a.atoms as Table<AtomsSchema>, b.atoms as Table<AtomsSchema>)
 }
 
-
 export function getAtomicHierarchyAndConformation(format: mmCIF_Format, atom_site: AtomSite, entities: Entities, previous?: Model) {
     const hierarchyOffsets = findHierarchyOffsets(atom_site);
     const hierarchyData = createHierarchyData(atom_site, hierarchyOffsets);

+ 0 - 2
src/mol-model/structure/model/properties/utils/coarse-keys.ts

@@ -82,8 +82,6 @@ export function getCoarseKeys(data: CoarseElementData, entities: Entities): Coar
         }
     }
 
-
-
     const { findChainKey, findSequenceKey } = createLookUp(entities, chainMaps, seqMaps);
 
     return { chainKey, entityKey, findSequenceKey, findChainKey };

+ 10 - 7
src/mol-view/stage.ts

@@ -44,13 +44,16 @@ const distanceRestraintProps: DistanceRestraintProps = {
 const backboneProps: BackboneProps = {
     doubleSided: true,
     colorTheme: { name: 'chain-id' },
+    // colorTheme: { name: 'uniform', value: 0xFF0000 },
     quality: 'auto',
-    useFog: false
+    useFog: false,
+    alpha: 0.5
 }
 
 const cartoonProps: CartoonProps = {
     doubleSided: true,
     colorTheme: { name: 'chain-id' },
+    // colorTheme: { name: 'uniform', value: 0x2200CC },
     quality: 'auto',
     useFog: false
 }
@@ -71,20 +74,20 @@ export class Stage {
         // this.loadPdbid('1jj2')
         // this.loadPdbid('4umt') // ligand has bond with order 3
         // this.loadPdbid('1crn') // small
-        this.loadPdbid('1hrv') // viral assembly
-        // this.loadPdbid('1rb8') // virus TODO funky inter unit bonds rendering
+        // this.loadPdbid('1hrv') // viral assembly
+        // this.loadPdbid('1rb8') // virus
         // this.loadPdbid('1blu') // metal coordination
         // this.loadPdbid('3pqr') // inter unit bonds
         // this.loadPdbid('4v5a') // ribosome
         // this.loadPdbid('3j3q') // ...
-        // this.loadPdbid('3sn6') // discontinuous chains
+        this.loadPdbid('3sn6') // discontinuous chains
         // this.loadMmcifUrl(`../../examples/1cbs_full.bcif`)
 
         // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000001.cif`) // ok
         // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000002.cif`) // ok
         // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000003.cif`) // ok
         // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000004.cif`) // TODO issue with cross-link extraction
-        // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000005.cif`) // TODO only three spacefill atoms rendered
+        // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000005.cif`) // ok
         // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000006.cif`) // TODO only three spacefill atoms rendered
         // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000007.cif`) // TODO only three spacefill atoms rendered
         // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000008.cif`) // ok
@@ -100,11 +103,11 @@ export class Stage {
         const modelEntity = await MmcifUrlToModel.apply(this.ctx, urlEntity)
         const structureEntity = await ModelToStructure.apply(this.ctx, modelEntity)
 
-        StructureToBallAndStick.apply(this.ctx, structureEntity, { ...ballAndStickProps, visible: true })
+        // StructureToBallAndStick.apply(this.ctx, structureEntity, { ...ballAndStickProps, visible: true })
         StructureToSpacefill.apply(this.ctx, structureEntity, { ...spacefillProps, visible: false })
         StructureToDistanceRestraint.apply(this.ctx, structureEntity, { ...distanceRestraintProps, visible: false })
         // StructureToBackbone.apply(this.ctx, structureEntity, { ...backboneProps, visible: true })
-        StructureToCartoon.apply(this.ctx, structureEntity, { ...cartoonProps, visible: false })
+        StructureToCartoon.apply(this.ctx, structureEntity, { ...cartoonProps, visible: true })
 
         this.globalContext.components.sequenceView.setState({ structure: structureEntity.value });
 

+ 6 - 5
src/mol-view/viewer.ts

@@ -100,7 +100,8 @@ namespace Viewer {
         const scene = Scene.create(ctx)
         // const controls = TrackballControls.create(input, scene, {})
         const controls = TrackballControls.create(input, camera, {})
-        const renderer = Renderer.create(ctx, camera)
+        // const renderer = Renderer.create(ctx, camera, { clearColor: 0xFFFFFF })
+        const renderer = Renderer.create(ctx, camera, { clearColor: 0x000000 })
 
         const pickScale = 1 / 4
         const pickWidth = Math.round(canvas.width * pickScale)
@@ -152,12 +153,12 @@ namespace Viewer {
             camera.near = Math.max(0.01, Math.min(near, targetDistance - 0.5))
 
             let fogNear = targetDistance - camera.near + 1 * focusRadius - nearPlaneDelta;
-            let fogFar = targetDistance - camera.near + 2 * focusRadius - nearPlaneDelta; 
-                                        
-            //console.log(fogNear, fogFar); 
+            let fogFar = targetDistance - camera.near + 2 * focusRadius - nearPlaneDelta;
+
+            //console.log(fogNear, fogFar);
             camera.fogNear = Math.max(fogNear, 0.1);
             camera.fogFar = Math.max(fogFar, 0.2);
-            
+
             // console.log(camera.fogNear, camera.fogFar, targetDistance)
 
             switch (variant) {