|
@@ -17,12 +17,15 @@ import Spacefill, { SpacefillProps } from 'mol-geo/representation/structure/spac
|
|
|
import Point, { PointProps } from 'mol-geo/representation/structure/point'
|
|
|
|
|
|
import { Run } from 'mol-task'
|
|
|
-import { Symmetry, Structure } from 'mol-model/structure'
|
|
|
+import { Symmetry, Structure, Model } from 'mol-model/structure'
|
|
|
|
|
|
|
|
|
-import { getStructuresFromPdbId, getStructuresFromFile, 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';
|
|
|
|
|
|
|
|
|
|
|
@@ -37,24 +40,35 @@ export type ColorTheme = keyof typeof ColorTheme
|
|
|
|
|
|
export default class State {
|
|
|
viewer: Viewer
|
|
|
- pdbId = '4cup'
|
|
|
+ pdbId = '1crn'
|
|
|
+
|
|
|
+ emdId = '8116'
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ 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)
|
|
|
spacefillVisibility = new BehaviorSubject<boolean>(true)
|
|
|
|
|
|
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())
|
|
|
this.spacefillVisibility.subscribe(() => this.updateVisibility())
|
|
@@ -63,7 +77,8 @@ export default class State {
|
|
|
getSpacefillProps (): SpacefillProps {
|
|
|
const colorThemeName = this.colorTheme.getValue()
|
|
|
return {
|
|
|
- detail: this.detail.getValue(),
|
|
|
+ doubleSided: true,
|
|
|
+ detail: this.sphereDetail.getValue(),
|
|
|
colorTheme: colorThemeName === 'uniform' ?
|
|
|
{ name: colorThemeName, value: this.colorValue.getValue() } :
|
|
|
{ name: colorThemeName }
|
|
@@ -84,51 +99,105 @@ export default class State {
|
|
|
this.viewer = Viewer.create(canvas, container)
|
|
|
this.initialized.next(true)
|
|
|
this.loadPdbId()
|
|
|
+ this.loadEmdId()
|
|
|
this.viewer.animate()
|
|
|
}
|
|
|
|
|
|
- async initStructure (structure: Structure) {
|
|
|
- const { viewer, loading } = this
|
|
|
- viewer.clear()
|
|
|
+ async getStructure () {
|
|
|
+ const model = this.model.getValue()
|
|
|
+ if (!model) return
|
|
|
+ const assembly = this.assembly.getValue()
|
|
|
+ let structure: Structure
|
|
|
+ const assemblies = model.symmetry.assemblies
|
|
|
+ if (assemblies.length) {
|
|
|
+ structure = await Run(Symmetry.buildAssembly(Structure.ofModel(model), assembly || '1'), log, 500)
|
|
|
+ } else {
|
|
|
+ structure = Structure.ofModel(model)
|
|
|
+ }
|
|
|
+ return structure
|
|
|
+ }
|
|
|
+
|
|
|
+ async initStructure () {
|
|
|
+ const { viewer } = this
|
|
|
+ if (!viewer || !this.model.getValue()) return
|
|
|
|
|
|
- const struct = await Run(Symmetry.buildAssembly(structure, '1'), log, 100)
|
|
|
+ if (this.pointRepr) this.viewer.remove(this.pointRepr)
|
|
|
+ if (this.spacefillRepr) this.viewer.remove(this.spacefillRepr)
|
|
|
+
|
|
|
+ const structure = await this.getStructure()
|
|
|
+ if (!structure) return
|
|
|
|
|
|
this.pointRepr = StructureRepresentation(Point)
|
|
|
- await Run(this.pointRepr.create(struct, 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(struct, this.getSpacefillProps()), log, 100)
|
|
|
+ await Run(this.spacefillRepr.create(structure, this.getSpacefillProps()), log, 500)
|
|
|
viewer.add(this.spacefillRepr)
|
|
|
|
|
|
this.updateVisibility()
|
|
|
viewer.requestDraw()
|
|
|
console.log(viewer.stats)
|
|
|
+ }
|
|
|
|
|
|
- loading.next(false)
|
|
|
+ setModel(model: Model) {
|
|
|
+ this.model.next(model)
|
|
|
+ this.initStructure()
|
|
|
+ this.loading.next(false)
|
|
|
}
|
|
|
|
|
|
async loadFile (file: File) {
|
|
|
this.viewer.clear()
|
|
|
this.loading.next(true)
|
|
|
+ this.setModel((await getModelFromFile(file))[0])
|
|
|
+ }
|
|
|
+
|
|
|
+ async initVolume () {
|
|
|
+ const { viewer } = this
|
|
|
+ const v = this.volume.getValue()
|
|
|
+ if (!viewer || !v) return
|
|
|
+
|
|
|
+ if (this.surfaceRepr) this.viewer.remove(this.surfaceRepr)
|
|
|
|
|
|
- const structures = await getStructuresFromFile(file)
|
|
|
- this.initStructure(structures[0])
|
|
|
+ this.surfaceRepr = VolumeRepresentation(Surface)
|
|
|
+ await Run(this.surfaceRepr.create(v.volume, {
|
|
|
+ isoValue: VolumeIsoValue.relative(v.volume.dataStats, 3.0),
|
|
|
+ alpha: 0.5,
|
|
|
+ flatShaded: false,
|
|
|
+ flipSided: true,
|
|
|
+ doubleSided: true
|
|
|
+ }), log, 500)
|
|
|
+ viewer.add(this.surfaceRepr)
|
|
|
+
|
|
|
+ viewer.requestDraw()
|
|
|
+ console.log(viewer.stats)
|
|
|
}
|
|
|
|
|
|
async loadPdbId () {
|
|
|
- this.viewer.clear()
|
|
|
+ if (this.pointRepr) this.viewer.remove(this.pointRepr)
|
|
|
+ if (this.spacefillRepr) this.viewer.remove(this.spacefillRepr)
|
|
|
if (this.pdbId.length !== 4) return
|
|
|
this.loading.next(true)
|
|
|
+ this.setModel((await getModelFromPdbId(this.pdbId))[0])
|
|
|
+ }
|
|
|
+
|
|
|
+ setVolume(volume: Volume) {
|
|
|
+ this.volume.next(volume)
|
|
|
+ this.initVolume()
|
|
|
+ this.loading.next(false)
|
|
|
+ }
|
|
|
|
|
|
- const structures = await getStructuresFromPdbId(this.pdbId)
|
|
|
- this.initStructure(structures[0])
|
|
|
+ async loadEmdId () {
|
|
|
+ if (this.surfaceRepr) this.viewer.remove(this.surfaceRepr)
|
|
|
+ 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()
|
|
@@ -154,87 +223,4 @@ export default class State {
|
|
|
}
|
|
|
this.viewer.requestDraw()
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+}
|