Skip to content
Snippets Groups Projects
Commit 166edc61 authored by Alexander Rose's avatar Alexander Rose
Browse files

tweaks to represent ihm models

parent 8f1b3b7b
No related branches found
No related tags found
No related merge requests found
...@@ -17,10 +17,10 @@ import Spacefill, { SpacefillProps } from 'mol-geo/representation/structure/spac ...@@ -17,10 +17,10 @@ import Spacefill, { SpacefillProps } from 'mol-geo/representation/structure/spac
import Point, { PointProps } from 'mol-geo/representation/structure/point' import Point, { PointProps } from 'mol-geo/representation/structure/point'
import { Run } from 'mol-task' import { Run } from 'mol-task'
import { Symmetry, Structure } from 'mol-model/structure' import { Symmetry, Structure, Model } from 'mol-model/structure'
// import mcubes from './utils/mcubes' // import mcubes from './utils/mcubes'
import { getStructuresFromPdbId, getStructuresFromFile, log } from './utils' import { getModelFromPdbId, getModelFromFile, log } from './utils'
import { StructureRepresentation } from 'mol-geo/representation/structure'; import { StructureRepresentation } from 'mol-geo/representation/structure';
import { Color } from 'mol-util/color'; import { Color } from 'mol-util/color';
// import Cylinder from 'mol-geo/primitive/cylinder'; // import Cylinder from 'mol-geo/primitive/cylinder';
...@@ -87,18 +87,24 @@ export default class State { ...@@ -87,18 +87,24 @@ export default class State {
this.viewer.animate() this.viewer.animate()
} }
async initStructure (structure: Structure) { async initStructure (model: Model) {
const { viewer, loading } = this const { viewer, loading } = this
viewer.clear() viewer.clear()
const struct = await Run(Symmetry.buildAssembly(structure, '1'), log, 100) let structure: Structure
const assemblies = model.symmetry.assemblies
if (assemblies.length) {
structure = await Run(Symmetry.buildAssembly(Structure.ofModel(model), '1'), log, 100)
} else {
structure = Structure.ofModel(model)
}
this.pointRepr = StructureRepresentation(Point) this.pointRepr = StructureRepresentation(Point)
await Run(this.pointRepr.create(struct, this.getPointProps()), log, 100) await Run(this.pointRepr.create(structure, this.getPointProps()), log, 100)
viewer.add(this.pointRepr) viewer.add(this.pointRepr)
this.spacefillRepr = StructureRepresentation(Spacefill) this.spacefillRepr = StructureRepresentation(Spacefill)
await Run(this.spacefillRepr.create(struct, this.getSpacefillProps()), log, 100) await Run(this.spacefillRepr.create(structure, this.getSpacefillProps()), log, 100)
viewer.add(this.spacefillRepr) viewer.add(this.spacefillRepr)
this.updateVisibility() this.updateVisibility()
...@@ -112,7 +118,7 @@ export default class State { ...@@ -112,7 +118,7 @@ export default class State {
this.viewer.clear() this.viewer.clear()
this.loading.next(true) this.loading.next(true)
const structures = await getStructuresFromFile(file) const structures = await getModelFromFile(file)
this.initStructure(structures[0]) this.initStructure(structures[0])
} }
...@@ -121,7 +127,7 @@ export default class State { ...@@ -121,7 +127,7 @@ export default class State {
if (this.pdbId.length !== 4) return if (this.pdbId.length !== 4) return
this.loading.next(true) this.loading.next(true)
const structures = await getStructuresFromPdbId(this.pdbId) const structures = await getModelFromPdbId(this.pdbId)
this.initStructure(structures[0]) this.initStructure(structures[0])
} }
...@@ -155,86 +161,3 @@ export default class State { ...@@ -155,86 +161,3 @@ export default class State {
this.viewer.requestDraw() this.viewer.requestDraw()
} }
} }
\ No newline at end of file
// async foo () {
// const p1 = Vec3.create(0, 4, 0)
// const p2 = Vec3.create(-3, 0, 0)
// // const position = ValueCell.create(new Float32Array([0, -1, 0, -1, 0, 0, 1, 1, 0]))
// // const normal = ValueCell.create(new Float32Array([0, 0, 0, 0, 0, 0, 0, 0, 0]))
// const transformArray1 = ValueCell.create(new Float32Array(16))
// const transformArray2 = ValueCell.create(new Float32Array(16 * 3))
// const m4 = Mat4.identity()
// Mat4.toArray(m4, transformArray1.ref.value, 0)
// Mat4.toArray(m4, transformArray2.ref.value, 0)
// Mat4.setTranslation(m4, p1)
// Mat4.toArray(m4, transformArray2.ref.value, 16)
// Mat4.setTranslation(m4, p2)
// Mat4.toArray(m4, transformArray2.ref.value, 32)
// const color = ValueCell.create(createColorTexture(3))
// color.ref.value.set([
// 0, 0, 255,
// 0, 255, 0,
// 255, 0, 0
// ])
// // const points = createRenderObject('point', {
// // position,
// // transform: transformArray1
// // })
// // // renderer.add(points)
// // const mesh = createRenderObject('mesh', {
// // position,
// // normal,
// // color,
// // transform: transformArray2
// // })
// // renderer.add(mesh)
// // const cylinder = Cylinder({ height: 3, radiusBottom: 0.5, radiusTop: 0.5 })
// // console.log(cylinder)
// // const cylinderMesh = createRenderObject('mesh', {
// // position: ValueCell.create(cylinder.vertices),
// // normal: ValueCell.create(cylinder.normals),
// // color,
// // transform: transformArray2
// // }, cylinder.indices)
// // renderer.add(cylinderMesh)
// // const sphere = Icosahedron()
// // console.log(sphere)
// // const box = Box()
// // console.log(box)
// // const points2 = createRenderObject('point', {
// // position: ValueCell.create(new Float32Array(box.vertices)),
// // transform: transformArray1
// // })
// // renderer.add(points2)
// // let rr = 0.7;
// // function cubesF(x: number, y: number, z: number) {
// // return x * x + y * y + z * z - rr * rr;
// // }
// // let cubes = await mcubes(cubesF);
// // const makeCubesMesh = () => createRenderObject('mesh', {
// // position: cubes.surface.vertexBuffer,
// // normal: cubes.surface.normalBuffer,
// // color,
// // transform: transformArray2,
// // elements: cubes.surface.indexBuffer,
// // instanceCount: transformArray2.ref.value.length / 16,
// // elementCount: cubes.surface.triangleCount,
// // positionCount: cubes.surface.vertexCount
// // }, {});
// // const mesh2 = makeCubesMesh();
// // renderer.add(mesh2)
// }
\ No newline at end of file
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
import CIF from 'mol-io/reader/cif' import CIF from 'mol-io/reader/cif'
import { Run, Progress } from 'mol-task' import { Run, Progress } from 'mol-task'
import { Structure } from 'mol-model/structure' import { Model } from 'mol-model/structure'
export function log(progress: Progress) { export function log(progress: Progress) {
const p = progress.root.progress const p = progress.root.progress
...@@ -20,10 +20,10 @@ export async function parseCif(data: string|Uint8Array) { ...@@ -20,10 +20,10 @@ export async function parseCif(data: string|Uint8Array) {
return parsed return parsed
} }
export async function getStructuresFromPdbId(pdbid: string) { export async function getModelFromPdbId(pdbid: string) {
const data = await fetch(`https://files.rcsb.org/download/${pdbid}.cif`) const data = await fetch(`https://files.rcsb.org/download/${pdbid}.cif`)
const parsed = await parseCif(await data.text()) const parsed = await parseCif(await data.text())
return Structure.ofData({ kind: 'mmCIF', data: CIF.schema.mmCIF(parsed.result.blocks[0]) }) return Model.create({ kind: 'mmCIF', data: CIF.schema.mmCIF(parsed.result.blocks[0]) })
} }
const readFileAsText = (file: File) => { const readFileAsText = (file: File) => {
...@@ -38,7 +38,7 @@ const readFileAsText = (file: File) => { ...@@ -38,7 +38,7 @@ const readFileAsText = (file: File) => {
}) })
} }
export async function getStructuresFromFile(file: File) { export async function getModelFromFile(file: File) {
const parsed = await parseCif(await readFileAsText(file)) const parsed = await parseCif(await readFileAsText(file))
return Structure.ofData({ kind: 'mmCIF', data: CIF.schema.mmCIF(parsed.result.blocks[0]) }) return Model.create({ kind: 'mmCIF', data: CIF.schema.mmCIF(parsed.result.blocks[0]) })
} }
\ No newline at end of file
...@@ -18,6 +18,7 @@ import { VdwRadius } from 'mol-model/structure/model/properties/atomic'; ...@@ -18,6 +18,7 @@ import { VdwRadius } from 'mol-model/structure/model/properties/atomic';
import { createTransforms, createColors } from './utils'; import { createTransforms, createColors } from './utils';
import { ColorTheme } from '../../theme'; import { ColorTheme } from '../../theme';
import VertexMap from '../../shape/vertex-map'; import VertexMap from '../../shape/vertex-map';
import CoarseGrained from 'mol-model/structure/model/properties/coarse-grained';
export const DefaultSpacefillProps = { export const DefaultSpacefillProps = {
detail: 0, detail: 0,
...@@ -25,9 +26,9 @@ export const DefaultSpacefillProps = { ...@@ -25,9 +26,9 @@ export const DefaultSpacefillProps = {
} }
export type SpacefillProps = Partial<typeof DefaultSpacefillProps> export type SpacefillProps = Partial<typeof DefaultSpacefillProps>
function createSpacefillMesh(unit: Unit, elementGroup: ElementGroup, detail: number) { function buildAtomSpheres(meshBuilder: MeshBuilder, unit: Unit, elementGroup: ElementGroup, detail: number) {
return Task.create('Spacefill', async ctx => { return Task.create('Atom spheres', async ctx => {
const meshBuilder = MeshBuilder.create() if (!Unit.isAtomic(unit)) return
const v = Vec3.zero() const v = Vec3.zero()
const m = Mat4.identity() const m = Mat4.identity()
...@@ -43,14 +44,53 @@ function createSpacefillMesh(unit: Unit, elementGroup: ElementGroup, detail: num ...@@ -43,14 +44,53 @@ function createSpacefillMesh(unit: Unit, elementGroup: ElementGroup, detail: num
Mat4.setTranslation(m, v) Mat4.setTranslation(m, v)
meshBuilder.setId(i) meshBuilder.setId(i)
meshBuilder.addIcosahedron(m, { meshBuilder.addIcosahedron(m, { radius: VdwRadius(type_symbol.value(e)), detail })
radius: VdwRadius(type_symbol.value(e)),
detail if (i % 10000 === 0 && ctx.shouldUpdate) {
await ctx.update({ message: 'Atom spheres', current: i, max: elementCount });
}
}
}) })
}
function buildCoarseSpheres(meshBuilder: MeshBuilder, unit: Unit, elementGroup: ElementGroup, detail: number) {
return Task.create('Coarse spheres', async ctx => {
if (!Unit.isCoarse(unit) || unit.elementType !== CoarseGrained.ElementType.Sphere) return
const v = Vec3.zero()
const m = Mat4.identity()
const { x, y, z, radius } = unit.model.coarseGrained.spheres
const elementCount = OrderedSet.size(elementGroup.elements)
console.log('building coarse spheres', elementCount)
for (let i = 0; i < elementCount; i++) {
const e = OrderedSet.getAt(elementGroup.elements, i)
v[0] = x[e]
v[1] = y[e]
v[2] = z[e]
Mat4.setTranslation(m, v)
meshBuilder.setId(i)
meshBuilder.addIcosahedron(m, { radius: radius.value(e), detail })
if (i % 10000 === 0 && ctx.shouldUpdate) { if (i % 10000 === 0 && ctx.shouldUpdate) {
await ctx.update({ message: 'Spacefill', current: i, max: elementCount }); await ctx.update({ message: 'Coarse spheres', current: i, max: elementCount });
}
}
})
}
function createSpacefillMesh(unit: Unit, elementGroup: ElementGroup, detail: number) {
return Task.create('Spacefill', async ctx => {
const meshBuilder = MeshBuilder.create()
if (Unit.isAtomic(unit)) {
await ctx.runChild(buildAtomSpheres(meshBuilder, unit, elementGroup, detail))
} }
if (Unit.isCoarse(unit) && unit.elementType === CoarseGrained.ElementType.Sphere) {
console.log('building coarse spheres')
await ctx.runChild(buildCoarseSpheres(meshBuilder, unit, elementGroup, detail))
} }
return meshBuilder.getMesh() return meshBuilder.getMesh()
......
...@@ -12,7 +12,7 @@ import { createUniformSize } from '../../util/size-data'; ...@@ -12,7 +12,7 @@ import { createUniformSize } from '../../util/size-data';
import { vdwSizeData } from '../../theme/structure/size/vdw'; import { vdwSizeData } from '../../theme/structure/size/vdw';
import VertexMap from '../../shape/vertex-map'; import VertexMap from '../../shape/vertex-map';
import { ColorTheme, SizeTheme } from '../../theme'; import { ColorTheme, SizeTheme } from '../../theme';
import { atomIndexColorData, elementSymbolColorData, instanceIndexColorData, chainIdColorData } from '../../theme/structure/color'; import { elementIndexColorData, elementSymbolColorData, instanceIndexColorData, chainIdColorData } from '../../theme/structure/color';
export function createTransforms(units: ReadonlyArray<Unit>) { export function createTransforms(units: ReadonlyArray<Unit>) {
const unitCount = units.length const unitCount = units.length
...@@ -26,7 +26,7 @@ export function createTransforms(units: ReadonlyArray<Unit>) { ...@@ -26,7 +26,7 @@ export function createTransforms(units: ReadonlyArray<Unit>) {
export function createColors(units: ReadonlyArray<Unit>, elementGroup: ElementGroup, vertexMap: VertexMap, props: ColorTheme) { export function createColors(units: ReadonlyArray<Unit>, elementGroup: ElementGroup, vertexMap: VertexMap, props: ColorTheme) {
switch (props.name) { switch (props.name) {
case 'atom-index': case 'atom-index':
return atomIndexColorData({ units, elementGroup, vertexMap }) return elementIndexColorData({ units, elementGroup, vertexMap })
case 'chain-id': case 'chain-id':
return chainIdColorData({ units, elementGroup, vertexMap }) return chainIdColorData({ units, elementGroup, vertexMap })
case 'element-symbol': case 'element-symbol':
......
...@@ -4,21 +4,32 @@ ...@@ -4,21 +4,32 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Alexander Rose <alexander.rose@weirdbyte.de>
*/ */
import { ElementGroup, Model } from 'mol-model/structure'; import { ElementGroup, Unit, Queries, Element } from 'mol-model/structure';
import { StructureColorDataProps } from '.'; import { StructureColorDataProps } from '.';
import { createAttributeOrElementColor } from '../../../util/color-data'; import { createAttributeOrElementColor } from '../../../util/color-data';
import { ColorScale } from 'mol-util/color'; import { ColorScale } from 'mol-util/color';
import { Column } from 'mol-data/db';
function createChainIdMap(model: Model) { function createChainIdMap(unit: Unit) {
const { chains } = model.hierarchy
const { label_asym_id } = chains
const map = new Map<string, number>() const map = new Map<string, number>()
let index = 0 let index = 0
for (let i = 0, il = chains._rowCount; i < il; ++i) { let count: number
const chainId = label_asym_id.value(i) let asym_id: Column<string>
if (Unit.isAtomic(unit)) {
asym_id = unit.hierarchy.chains.label_asym_id
count = unit.hierarchy.chains._rowCount
} else if (Unit.isCoarse(unit)) {
asym_id = unit.siteBases.asym_id
count = unit.siteBases.count
} else {
console.warn('Unknown unit type')
return { map, count: index }
}
for (let i = 0; i < count; ++i) {
const chainId = asym_id.value(i)
if (map.get(chainId) === undefined) { if (map.get(chainId) === undefined) {
map.set(chainId, index) map.set(chainId, index)
index += 1 index += 1
...@@ -31,20 +42,25 @@ export function chainIdColorData(props: StructureColorDataProps) { ...@@ -31,20 +42,25 @@ export function chainIdColorData(props: StructureColorDataProps) {
const { units, elementGroup, vertexMap } = props const { units, elementGroup, vertexMap } = props
const unit = units[0] const unit = units[0]
const { chains, chainSegments } = unit.model.hierarchy const { map, count } = createChainIdMap(unit)
const { label_asym_id } = chains
const { map, count } = createChainIdMap(unit.model)
const domain = [ 0, count - 1 ] const domain = [ 0, count - 1 ]
const scale = ColorScale.create({ domain }) const scale = ColorScale.create({ domain })
let asym_id: Element.Property<string>
if (Unit.isAtomic(unit)) {
asym_id = Queries.props.chain.label_asym_id
} else if (Unit.isCoarse(unit)) {
asym_id = Queries.props.coarse_grained.asym_id
}
const l = Element.Location()
l.unit = unit
return createAttributeOrElementColor(vertexMap, { return createAttributeOrElementColor(vertexMap, {
colorFn: (elementIdx: number) => { colorFn: (elementIdx: number) => {
const aI = ElementGroup.getAt(elementGroup, elementIdx); l.element = ElementGroup.getAt(elementGroup, elementIdx)
const cI = chainSegments.segmentMap[aI] return scale.color(map.get(asym_id(l)) || 0)
const chainId = label_asym_id.value(cI)
return scale.color(map.get(chainId) || 0)
}, },
vertexMap vertexMap
}) })
......
...@@ -9,7 +9,7 @@ import { StructureColorDataProps } from '.'; ...@@ -9,7 +9,7 @@ import { StructureColorDataProps } from '.';
import { OrderedSet } from 'mol-data/int'; import { OrderedSet } from 'mol-data/int';
import { createElementInstanceColor } from '../../../util/color-data'; import { createElementInstanceColor } from '../../../util/color-data';
export function atomIndexColorData(props: StructureColorDataProps) { export function elementIndexColorData(props: StructureColorDataProps) {
const { units, elementGroup, vertexMap } = props const { units, elementGroup, vertexMap } = props
const instanceCount = units.length const instanceCount = units.length
const elementCount = OrderedSet.size(elementGroup.elements) const elementCount = OrderedSet.size(elementGroup.elements)
......
...@@ -13,7 +13,7 @@ export interface StructureColorDataProps { ...@@ -13,7 +13,7 @@ export interface StructureColorDataProps {
vertexMap: VertexMap vertexMap: VertexMap
} }
export { atomIndexColorData } from './atom-index' export { elementIndexColorData } from './element-index'
export { chainIdColorData } from './chain-id' export { chainIdColorData } from './chain-id'
export { elementSymbolColorData } from './element-symbol' export { elementSymbolColorData } from './element-symbol'
export { instanceIndexColorData } from './instance-index' export { instanceIndexColorData } from './instance-index'
\ No newline at end of file
...@@ -55,7 +55,7 @@ namespace Viewer { ...@@ -55,7 +55,7 @@ namespace Viewer {
input.resize.subscribe(handleResize) input.resize.subscribe(handleResize)
const camera = PerspectiveCamera.create({ const camera = PerspectiveCamera.create({
near: 0.01, near: 0.1,
far: 10000, far: 10000,
position: Vec3.create(0, 0, 50) position: Vec3.create(0, 0, 50)
}) })
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment