diff --git a/src/apps/render-test/components/detail.tsx b/src/apps/render-test/components/detail.tsx index a53c64f826c6b77a33af5aeb258d90e00d53ab7c..9bbd84a6de3b6f208ece2c5d52f959f463a9b9d9 100644 --- a/src/apps/render-test/components/detail.tsx +++ b/src/apps/render-test/components/detail.tsx @@ -38,7 +38,7 @@ export default class Detail extends Observer<{ state: State } & WithStyles, Deta render() { const { classes } = this.props; - const items = [0, 1, 2].map((value, idx) => { + const items = [0, 1, 2, 3].map((value, idx) => { return <MenuItem key={idx} value={value}>{value.toString()}</MenuItem> }) diff --git a/src/mol-geo/primitive/icosahedron.ts b/src/mol-geo/primitive/icosahedron.ts index 7e73afb419daeef55278241fafe2cfef5f7dbeaf..07e544e07fcfdd7cddb36940173f2841c58da169 100644 --- a/src/mol-geo/primitive/icosahedron.ts +++ b/src/mol-geo/primitive/icosahedron.ts @@ -23,6 +23,10 @@ const indices = [ 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1 ]; +export function icosahedronVertexCount(detail: number) { + return 10 * Math.pow(Math.pow(2, detail), 2) + 2 +} + export const DefaultIcosahedronProps = { radius: 1, detail: 0 diff --git a/src/mol-geo/representation/structure/point.ts b/src/mol-geo/representation/structure/point.ts index b95347fb17e7035214d95963c38d896bf2002262..73884615d0dbaf21f78d746862c4d42b89cbc86e 100644 --- a/src/mol-geo/representation/structure/point.ts +++ b/src/mol-geo/representation/structure/point.ts @@ -7,7 +7,7 @@ import { ValueCell } from 'mol-util/value-cell' import { createPointRenderObject, RenderObject, PointRenderObject } from 'mol-gl/scene' import { OrderedSet } from 'mol-data/int' -import { Unit, ElementGroup } from 'mol-model/structure'; +import { Unit, ElementGroup, Element } from 'mol-model/structure'; import { Task } from 'mol-task' import { fillSerial } from 'mol-gl/renderable/util'; @@ -26,13 +26,17 @@ export type PointProps = Partial<typeof DefaultPointProps> export function createPointVertices(unit: Unit, elementGroup: ElementGroup) { const elementCount = OrderedSet.size(elementGroup.elements) const vertices = new Float32Array(elementCount * 3) - const { x, y, z } = unit.model.atomSiteConformation + + const { x, y, z } = unit + const l = Element.Location() + l.unit = unit + for (let i = 0; i < elementCount; i++) { - const e = OrderedSet.getAt(elementGroup.elements, i) + l.element = ElementGroup.getAt(elementGroup, i) const i3 = i * 3 - vertices[i3] = x[e] - vertices[i3 + 1] = y[e] - vertices[i3 + 2] = z[e] + vertices[i3] = x(l.element) + vertices[i3 + 1] = y(l.element) + vertices[i3 + 2] = z(l.element) } return vertices } diff --git a/src/mol-geo/representation/structure/spacefill.ts b/src/mol-geo/representation/structure/spacefill.ts index 4e2f9168361a547201b789eb28fdbddc9b66309b..47d238d2de34c249e29b7bdbe3f7afa217d2fc88 100644 --- a/src/mol-geo/representation/structure/spacefill.ts +++ b/src/mol-geo/representation/structure/spacefill.ts @@ -10,15 +10,15 @@ import { RenderObject, createMeshRenderObject, MeshRenderObject } from 'mol-gl/s // import { createColorTexture } from 'mol-gl/util'; import { Vec3, Mat4 } from 'mol-math/linear-algebra' import { OrderedSet } from 'mol-data/int' -import { Unit, ElementGroup } from 'mol-model/structure'; +import { Unit, ElementGroup, Element, Queries } from 'mol-model/structure'; import { RepresentationProps, UnitsRepresentation } from './index'; import { Task } from 'mol-task' import { MeshBuilder } from '../../shape/mesh-builder'; -import { VdwRadius } from 'mol-model/structure/model/properties/atomic'; import { createTransforms, createColors } from './utils'; import { ColorTheme } from '../../theme'; import VertexMap from '../../shape/vertex-map'; import CoarseGrained from 'mol-model/structure/model/properties/coarse-grained'; +import { icosahedronVertexCount } from '../../primitive/icosahedron'; export const DefaultSpacefillProps = { detail: 0, @@ -26,72 +26,43 @@ export const DefaultSpacefillProps = { } export type SpacefillProps = Partial<typeof DefaultSpacefillProps> -function buildAtomSpheres(meshBuilder: MeshBuilder, unit: Unit, elementGroup: ElementGroup, detail: number) { - return Task.create('Atom spheres', async ctx => { - if (!Unit.isAtomic(unit)) return - - const v = Vec3.zero() - const m = Mat4.identity() - - const { x, y, z } = unit.model.atomSiteConformation - const { type_symbol } = unit.model.hierarchy.atoms +function createSpacefillMesh(unit: Unit, elementGroup: ElementGroup, detail: number) { + return Task.create('Sphere mesh', async ctx => { const elementCount = OrderedSet.size(elementGroup.elements) - 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) + const vertexCount = elementCount * icosahedronVertexCount(detail) + const meshBuilder = MeshBuilder.create(vertexCount) - meshBuilder.setId(i) - meshBuilder.addIcosahedron(m, { radius: VdwRadius(type_symbol.value(e)), detail }) - - if (i % 10000 === 0 && ctx.shouldUpdate) { - await ctx.update({ message: 'Atom spheres', current: i, max: elementCount }); - } + let radius: Element.Property<number> + if (Unit.isAtomic(unit)) { + radius = Queries.props.atom.vdw_radius + } else if (Unit.isCoarse(unit) && unit.elementType === CoarseGrained.ElementType.Sphere) { + radius = Queries.props.coarse_grained.sphere_radius + } else { + console.warn('Unsupported unit type') + return meshBuilder.getMesh() } - }) -} - -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) + const { x, y, z } = unit + const l = Element.Location() + l.unit = unit + 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] + l.element = ElementGroup.getAt(elementGroup, i) + v[0] = x(l.element) + v[1] = y(l.element) + v[2] = z(l.element) Mat4.setTranslation(m, v) meshBuilder.setId(i) - meshBuilder.addIcosahedron(m, { radius: radius.value(e), detail }) + meshBuilder.addIcosahedron(m, { radius: radius(l), detail }) if (i % 10000 === 0 && ctx.shouldUpdate) { - await ctx.update({ message: 'Coarse spheres', current: i, max: elementCount }); + await ctx.update({ message: 'Sphere mesh', 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() }) diff --git a/src/mol-geo/representation/structure/utils.ts b/src/mol-geo/representation/structure/utils.ts index 65f7b35962d4b6eb769b8d34de2d4ff3ece77f59..fba67c536e46e9447fd19b170299d25771b19996 100644 --- a/src/mol-geo/representation/structure/utils.ts +++ b/src/mol-geo/representation/structure/utils.ts @@ -9,7 +9,7 @@ import { Mat4 } from 'mol-math/linear-algebra' import { createUniformColor } from '../../util/color-data'; import { createUniformSize } from '../../util/size-data'; -import { vdwSizeData } from '../../theme/structure/size/vdw'; +import { elementSizeData } from '../../theme/structure/size/element'; import VertexMap from '../../shape/vertex-map'; import { ColorTheme, SizeTheme } from '../../theme'; import { elementIndexColorData, elementSymbolColorData, instanceIndexColorData, chainIdColorData } from '../../theme/structure/color'; @@ -43,6 +43,6 @@ export function createSizes(units: ReadonlyArray<Unit>, elementGroup: ElementGro case 'uniform': return createUniformSize(props) case 'vdw': - return vdwSizeData({ units, elementGroup, vertexMap }) + return elementSizeData({ units, elementGroup, vertexMap }) } } \ No newline at end of file diff --git a/src/mol-geo/theme/structure/size/element.ts b/src/mol-geo/theme/structure/size/element.ts new file mode 100644 index 0000000000000000000000000000000000000000..699bc071a499ab303d3e40d48c3befb465248afe --- /dev/null +++ b/src/mol-geo/theme/structure/size/element.ts @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { ElementGroup, Element, Unit, Queries } from 'mol-model/structure'; +import CoarseGrained from 'mol-model/structure/model/properties/coarse-grained'; +import { StructureSizeDataProps } from '.'; +import { createAttributeSize } from '../../../util/size-data'; + +/** Create attribute data with the size of an element, i.e. vdw for atoms and radius for coarse spheres */ +export function elementSizeData(props: StructureSizeDataProps) { + const { units, elementGroup, vertexMap } = props + const unit = units[0] + let radius: Element.Property<number> + if (Unit.isAtomic(unit)) { + radius = Queries.props.atom.vdw_radius + } else if (Unit.isCoarse(unit) && unit.elementType === CoarseGrained.ElementType.Sphere) { + radius = Queries.props.coarse_grained.sphere_radius + } + const l = Element.Location() + l.unit = unit + return createAttributeSize({ + sizeFn: (elementIdx: number) => { + l.element = ElementGroup.getAt(elementGroup, elementIdx) + return radius(l) + }, + vertexMap + }) +} \ No newline at end of file diff --git a/src/mol-geo/theme/structure/size/index.ts b/src/mol-geo/theme/structure/size/index.ts index b178ad42b9f9877bf819b0f2da71aa95e661219c..22caed502febf7ab0dd05a25201fe1c960335f07 100644 --- a/src/mol-geo/theme/structure/size/index.ts +++ b/src/mol-geo/theme/structure/size/index.ts @@ -13,4 +13,4 @@ export interface StructureSizeDataProps { vertexMap: VertexMap } -export { vdwSizeData } from './vdw' \ No newline at end of file +export { elementSizeData } from './element' \ No newline at end of file diff --git a/src/mol-geo/theme/structure/size/vdw.ts b/src/mol-geo/theme/structure/size/vdw.ts deleted file mode 100644 index 3010380904ab0810d3d79ff5f0a5b0a0d1f7a921..0000000000000000000000000000000000000000 --- a/src/mol-geo/theme/structure/size/vdw.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import { OrderedSet } from 'mol-data/int'; -import { VdwRadius } from 'mol-model/structure/model/properties/atomic'; -import { StructureSizeDataProps } from '.'; -import { createAttributeSize } from '../../../util/size-data'; - - -export function vdwSizeData(props: StructureSizeDataProps) { - const { units, elementGroup, vertexMap } = props - const { type_symbol } = units[0].model.hierarchy.atoms - return createAttributeSize({ - sizeFn: (elementIdx: number) => { - const e = OrderedSet.getAt(elementGroup.elements, elementIdx) - return VdwRadius(type_symbol.value(e)) - }, - vertexMap - }) -} \ No newline at end of file diff --git a/src/mol-model/structure/query/properties.ts b/src/mol-model/structure/query/properties.ts index 8a766f9b5c6040a4fd7f7ebd8d23820f404bc7b7..98d22ce51ca05136bc70f0bf52c82399d8fbd400 100644 --- a/src/mol-model/structure/query/properties.ts +++ b/src/mol-model/structure/query/properties.ts @@ -1,11 +1,12 @@ /** - * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> */ import { Element, Unit } from '../structure' import CoarseGrained from '../model/properties/coarse-grained'; +import { VdwRadius } from '../model/properties/atomic'; const constant = { true: Element.property(l => true), @@ -38,7 +39,10 @@ const atom = { label_atom_id: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.hierarchy.atoms.label_atom_id.value(l.element)), auth_atom_id: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.hierarchy.atoms.auth_atom_id.value(l.element)), label_alt_id: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.hierarchy.atoms.label_alt_id.value(l.element)), - pdbx_formal_charge: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.hierarchy.atoms.pdbx_formal_charge.value(l.element)) + pdbx_formal_charge: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.hierarchy.atoms.pdbx_formal_charge.value(l.element)), + + // Derived + vdw_radius: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : VdwRadius(l.unit.hierarchy.atoms.type_symbol.value(l.element))), } const residue = {