|
@@ -20,9 +20,12 @@ import { Run } from 'mol-task'
|
|
|
import { Symmetry, Structure, Model } from 'mol-model/structure'
|
|
|
|
|
|
// import mcubes from './utils/mcubes'
|
|
|
-import { getModelFromPdbId, getModelFromFile, log } from './utils'
|
|
|
+import { getModelFromPdbId, getModelFromFile, log, Volume, getVolumeFromEmdId } from './utils'
|
|
|
import { StructureRepresentation } from 'mol-geo/representation/structure';
|
|
|
import { Color } from 'mol-util/color';
|
|
|
+import Surface, { SurfaceProps } from 'mol-geo/representation/volume/surface';
|
|
|
+import { VolumeIsoValue } from 'mol-model/volume';
|
|
|
+import { VolumeRepresentation } from 'mol-geo/representation/volume';
|
|
|
// import Cylinder from 'mol-geo/primitive/cylinder';
|
|
|
|
|
|
|
|
@@ -37,14 +40,16 @@ export type ColorTheme = keyof typeof ColorTheme
|
|
|
|
|
|
export default class State {
|
|
|
viewer: Viewer
|
|
|
- pdbId = '4cup'
|
|
|
+ pdbId = ''
|
|
|
+ emdId = '8689'
|
|
|
model = new BehaviorSubject<Model | undefined>(undefined)
|
|
|
+ volume = new BehaviorSubject<Volume | undefined>(undefined)
|
|
|
initialized = new BehaviorSubject<boolean>(false)
|
|
|
loading = new BehaviorSubject<boolean>(false)
|
|
|
|
|
|
colorTheme = new BehaviorSubject<ColorTheme>('element-symbol')
|
|
|
colorValue = new BehaviorSubject<Color>(0xFF4411)
|
|
|
- detail = new BehaviorSubject<number>(0)
|
|
|
+ sphereDetail = new BehaviorSubject<number>(0)
|
|
|
assembly = new BehaviorSubject<string>('')
|
|
|
|
|
|
pointVisibility = new BehaviorSubject<boolean>(true)
|
|
@@ -52,11 +57,12 @@ export default class State {
|
|
|
|
|
|
pointRepr: StructureRepresentation<PointProps>
|
|
|
spacefillRepr: StructureRepresentation<SpacefillProps>
|
|
|
+ surfaceRepr: VolumeRepresentation<SurfaceProps>
|
|
|
|
|
|
constructor() {
|
|
|
this.colorTheme.subscribe(() => this.update())
|
|
|
this.colorValue.subscribe(() => this.update())
|
|
|
- this.detail.subscribe(() => this.update())
|
|
|
+ this.sphereDetail.subscribe(() => this.update())
|
|
|
this.assembly.subscribe(() => this.initStructure())
|
|
|
|
|
|
this.pointVisibility.subscribe(() => this.updateVisibility())
|
|
@@ -66,7 +72,7 @@ export default class State {
|
|
|
getSpacefillProps (): SpacefillProps {
|
|
|
const colorThemeName = this.colorTheme.getValue()
|
|
|
return {
|
|
|
- detail: this.detail.getValue(),
|
|
|
+ detail: this.sphereDetail.getValue(),
|
|
|
colorTheme: colorThemeName === 'uniform' ?
|
|
|
{ name: colorThemeName, value: this.colorValue.getValue() } :
|
|
|
{ name: colorThemeName }
|
|
@@ -87,6 +93,7 @@ export default class State {
|
|
|
this.viewer = Viewer.create(canvas, container)
|
|
|
this.initialized.next(true)
|
|
|
this.loadPdbId()
|
|
|
+ this.loadEmdId()
|
|
|
this.viewer.animate()
|
|
|
}
|
|
|
|
|
@@ -97,7 +104,7 @@ export default class State {
|
|
|
let structure: Structure
|
|
|
const assemblies = model.symmetry.assemblies
|
|
|
if (assemblies.length) {
|
|
|
- structure = await Run(Symmetry.buildAssembly(Structure.ofModel(model), assembly || '1'), log, 100)
|
|
|
+ structure = await Run(Symmetry.buildAssembly(Structure.ofModel(model), assembly || '1'), log, 500)
|
|
|
} else {
|
|
|
structure = Structure.ofModel(model)
|
|
|
}
|
|
@@ -105,8 +112,8 @@ export default class State {
|
|
|
}
|
|
|
|
|
|
async initStructure () {
|
|
|
- const { viewer, model } = this
|
|
|
- if (!viewer || !model) return
|
|
|
+ const { viewer } = this
|
|
|
+ if (!viewer || !this.model.getValue()) return
|
|
|
|
|
|
viewer.clear()
|
|
|
|
|
@@ -114,11 +121,11 @@ export default class State {
|
|
|
if (!structure) return
|
|
|
|
|
|
this.pointRepr = StructureRepresentation(Point)
|
|
|
- await Run(this.pointRepr.create(structure, this.getPointProps()), log, 100)
|
|
|
+ await Run(this.pointRepr.create(structure, this.getPointProps()), log, 500)
|
|
|
viewer.add(this.pointRepr)
|
|
|
|
|
|
this.spacefillRepr = StructureRepresentation(Spacefill)
|
|
|
- await Run(this.spacefillRepr.create(structure, this.getSpacefillProps()), log, 100)
|
|
|
+ await Run(this.spacefillRepr.create(structure, this.getSpacefillProps()), log, 500)
|
|
|
viewer.add(this.spacefillRepr)
|
|
|
|
|
|
this.updateVisibility()
|
|
@@ -138,6 +145,21 @@ export default class State {
|
|
|
this.setModel((await getModelFromFile(file))[0])
|
|
|
}
|
|
|
|
|
|
+ async initVolume () {
|
|
|
+ const { viewer } = this
|
|
|
+ const v = this.volume.getValue()
|
|
|
+ if (!viewer || !v) return
|
|
|
+
|
|
|
+ viewer.clear()
|
|
|
+
|
|
|
+ this.surfaceRepr = VolumeRepresentation(Surface)
|
|
|
+ await Run(this.surfaceRepr.create(v.volume, { isoValue: VolumeIsoValue.relative(v.volume.dataStats, 1.5) }), log, 500)
|
|
|
+ viewer.add(this.surfaceRepr)
|
|
|
+
|
|
|
+ viewer.requestDraw()
|
|
|
+ console.log(viewer.stats)
|
|
|
+ }
|
|
|
+
|
|
|
async loadPdbId () {
|
|
|
this.viewer.clear()
|
|
|
if (this.pdbId.length !== 4) return
|
|
@@ -145,10 +167,23 @@ export default class State {
|
|
|
this.setModel((await getModelFromPdbId(this.pdbId))[0])
|
|
|
}
|
|
|
|
|
|
+ setVolume(volume: Volume) {
|
|
|
+ this.volume.next(volume)
|
|
|
+ this.initVolume()
|
|
|
+ this.loading.next(false)
|
|
|
+ }
|
|
|
+
|
|
|
+ async loadEmdId () {
|
|
|
+ this.viewer.clear()
|
|
|
+ if (this.emdId.length !== 4) return
|
|
|
+ this.loading.next(true)
|
|
|
+ this.setVolume(await getVolumeFromEmdId(this.emdId))
|
|
|
+ }
|
|
|
+
|
|
|
async update () {
|
|
|
if (!this.spacefillRepr) return
|
|
|
- await Run(this.spacefillRepr.update(this.getSpacefillProps()), log, 100)
|
|
|
- await Run(this.pointRepr.update(this.getPointProps()), log, 100)
|
|
|
+ await Run(this.spacefillRepr.update(this.getSpacefillProps()), log, 500)
|
|
|
+ await Run(this.pointRepr.update(this.getPointProps()), log, 500)
|
|
|
this.viewer.add(this.spacefillRepr)
|
|
|
this.viewer.add(this.pointRepr)
|
|
|
this.viewer.update()
|