From bd1b07ad8639fe7269956fb8e5627483a5ea333e Mon Sep 17 00:00:00 2001 From: Alexander Rose <alexander.rose@weirdbyte.de> Date: Sun, 24 Feb 2019 13:20:52 -0800 Subject: [PATCH] removed gaussian density calc from unit --- src/mol-model/structure/structure/unit.ts | 17 +-- .../structure/unit/gaussian-density.ts | 76 ----------- .../visual/gaussian-density-point.ts | 4 +- .../visual/gaussian-density-volume.ts | 57 +------- .../structure/visual/gaussian-surface-mesh.ts | 4 +- .../visual/gaussian-surface-wireframe.ts | 4 +- .../structure/visual/util/gaussian.ts | 124 ++++++++++++++++++ 7 files changed, 135 insertions(+), 151 deletions(-) delete mode 100644 src/mol-model/structure/structure/unit/gaussian-density.ts diff --git a/src/mol-model/structure/structure/unit.ts b/src/mol-model/structure/structure/unit.ts index cbdf58718..725862657 100644 --- a/src/mol-model/structure/structure/unit.ts +++ b/src/mol-model/structure/structure/unit.ts @@ -7,7 +7,7 @@ import { SymmetryOperator } from 'mol-math/geometry/symmetry-operator' import { Model } from '../model' -import { GridLookup3D, Lookup3D, DensityData } from 'mol-math/geometry' +import { GridLookup3D, Lookup3D } from 'mol-math/geometry' import { IntraUnitLinks, computeIntraUnitBonds } from './unit/links' import { CoarseElements, CoarseSphereConformation, CoarseGaussianConformation } from '../model/properties/coarse'; import { ValueRef } from 'mol-util'; @@ -18,9 +18,6 @@ import { IntMap, SortedArray } from 'mol-data/int'; import { hash2, hashFnv32a } from 'mol-data/util'; import { getAtomicPolymerElements, getCoarsePolymerElements, getAtomicGapElements, getCoarseGapElements } from './util/polymer'; import { getNucleotideElements } from './util/nucleotide'; -import { GaussianDensityProps, computeUnitGaussianDensityCached } from './unit/gaussian-density'; -import { RuntimeContext } from 'mol-task'; -import { WebGLContext } from 'mol-gl/webgl/context'; /** * A building block of a structure that corresponds to an atomic or @@ -191,10 +188,6 @@ namespace Unit { return this.model.atomicHierarchy.residueAtomSegments.index[this.elements[elementIndex]]; } - async computeGaussianDensity(props: GaussianDensityProps, ctx: RuntimeContext, webgl?: WebGLContext) { - return computeUnitGaussianDensityCached(this, props, this.props.gaussianDensities, ctx, webgl); - } - constructor(id: number, invariantId: number, model: Model, elements: StructureElement.Set, conformation: SymmetryOperator.ArrayMapping<ElementIndex>, props: AtomicProperties) { this.id = id; this.invariantId = invariantId; @@ -215,7 +208,6 @@ namespace Unit { polymerElements: ValueRef<SortedArray<ElementIndex> | undefined> gapElements: ValueRef<SortedArray<ElementIndex> | undefined> nucleotideElements: ValueRef<SortedArray<ElementIndex> | undefined> - gaussianDensities: Map<string, DensityData> } function AtomicProperties(): AtomicProperties { @@ -226,7 +218,6 @@ namespace Unit { polymerElements: ValueRef.create(void 0), gapElements: ValueRef.create(void 0), nucleotideElements: ValueRef.create(void 0), - gaussianDensities: new Map() }; } @@ -280,10 +271,6 @@ namespace Unit { return this.kind === Kind.Spheres ? this.model.coarseConformation.spheres : this.model.coarseConformation.gaussians; } - async computeGaussianDensity(props: GaussianDensityProps, ctx: RuntimeContext, webgl?: WebGLContext): Promise<DensityData> { - return computeUnitGaussianDensityCached(this as Unit.Spheres | Unit.Gaussians, props, this.props.gaussianDensities, ctx, webgl); // TODO get rid of casting - } - constructor(id: number, invariantId: number, model: Model, kind: K, elements: StructureElement.Set, conformation: SymmetryOperator.ArrayMapping<ElementIndex>, props: CoarseProperties) { this.kind = kind; this.id = id; @@ -299,7 +286,6 @@ namespace Unit { interface CoarseProperties { lookup3d: ValueRef<Lookup3D | undefined>, - gaussianDensities: Map<string, DensityData> polymerElements: ValueRef<SortedArray<ElementIndex> | undefined> gapElements: ValueRef<SortedArray<ElementIndex> | undefined> } @@ -307,7 +293,6 @@ namespace Unit { function CoarseProperties(): CoarseProperties { return { lookup3d: ValueRef.create(void 0), - gaussianDensities: new Map(), polymerElements: ValueRef.create(void 0), gapElements: ValueRef.create(void 0), }; diff --git a/src/mol-model/structure/structure/unit/gaussian-density.ts b/src/mol-model/structure/structure/unit/gaussian-density.ts deleted file mode 100644 index cefbfcd68..000000000 --- a/src/mol-model/structure/structure/unit/gaussian-density.ts +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import { Unit, StructureElement, ElementIndex } from 'mol-model/structure'; -import { GaussianDensity } from 'mol-math/geometry/gaussian-density'; -import { Task, RuntimeContext } from 'mol-task'; -import { DensityData } from 'mol-math/geometry'; -import { ParamDefinition as PD } from 'mol-util/param-definition'; -import { GaussianDensityTexture } from 'mol-math/geometry/gaussian-density/gpu'; -import { Texture } from 'mol-gl/webgl/texture'; -import { WebGLContext } from 'mol-gl/webgl/context'; -import { PhysicalSizeTheme } from 'mol-theme/size/physical'; - -export const GaussianDensityParams = { - resolution: PD.Numeric(1, { min: 0.1, max: 10, step: 0.1 }), - radiusOffset: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }), - smoothness: PD.Numeric(1.5, { min: 0.5, max: 2.5, step: 0.1 }), - useGpu: PD.Boolean(false), - ignoreCache: PD.Boolean(false), -} -export const DefaultGaussianDensityProps = PD.getDefaultValues(GaussianDensityParams) -export type GaussianDensityProps = typeof DefaultGaussianDensityProps - -function getConformation(unit: Unit) { - switch (unit.kind) { - case Unit.Kind.Atomic: return unit.model.atomicConformation - case Unit.Kind.Spheres: return unit.model.coarseConformation.spheres - case Unit.Kind.Gaussians: return unit.model.coarseConformation.gaussians - } -} - -function getConformationAndRadius(unit: Unit) { - const conformation = getConformation(unit) - const { elements } = unit - const position = { - indices: elements, - x: conformation.x, - y: conformation.y, - z: conformation.z - } - - const l = StructureElement.create(unit) - const sizeTheme = PhysicalSizeTheme({}, {}) - const radius = (index: number) => { - l.element = index as ElementIndex - return sizeTheme.size(l) - } - - return { position, radius } -} - -export function computeUnitGaussianDensity(unit: Unit, props: GaussianDensityProps, webgl?: WebGLContext) { - const { position, radius } = getConformationAndRadius(unit) - return Task.create('Gaussian Density', async ctx => { - return await GaussianDensity(ctx, position, unit.lookup3d.boundary.box, radius, props, webgl); - }); -} - -export function computeUnitGaussianDensityTexture(unit: Unit, props: GaussianDensityProps, webgl: WebGLContext, texture?: Texture) { - const { position, radius } = getConformationAndRadius(unit) - return Task.create('Gaussian Density', async ctx => { - return await GaussianDensityTexture(ctx, webgl, position, unit.lookup3d.boundary.box, radius, props, texture); - }); -} - -export async function computeUnitGaussianDensityCached(unit: Unit, props: GaussianDensityProps, cache: Map<string, DensityData>, ctx: RuntimeContext, webgl?: WebGLContext) { - const key = `${props.radiusOffset}|${props.resolution}|${props.smoothness}` - let density = cache.get(key) - if (density && !props.ignoreCache) return density - density = await computeUnitGaussianDensity(unit, props, webgl).runInContext(ctx) - if (!props.ignoreCache) cache.set(key, density) - return density -} \ No newline at end of file diff --git a/src/mol-repr/structure/visual/gaussian-density-point.ts b/src/mol-repr/structure/visual/gaussian-density-point.ts index 0be7361e8..c61ae5745 100644 --- a/src/mol-repr/structure/visual/gaussian-density-point.ts +++ b/src/mol-repr/structure/visual/gaussian-density-point.ts @@ -11,12 +11,12 @@ import { StructureElementIterator } from './util/element'; import { EmptyLoci } from 'mol-model/loci'; import { Vec3 } from 'mol-math/linear-algebra'; import { UnitsPointsVisual, UnitsPointsParams } from '../units-visual'; -import { GaussianDensityProps, GaussianDensityParams } from 'mol-model/structure/structure/unit/gaussian-density'; import { ParamDefinition as PD } from 'mol-util/param-definition'; import { Points } from 'mol-geo/geometry/points/points'; import { PointsBuilder } from 'mol-geo/geometry/points/points-builder'; import { VisualContext } from 'mol-repr/visual'; import { Theme } from 'mol-theme/theme'; +import { computeUnitGaussianDensity, GaussianDensityParams, GaussianDensityProps } from './util/gaussian'; export const GaussianDensityPointParams = { ...UnitsPointsParams, @@ -26,7 +26,7 @@ export const GaussianDensityPointParams = { export type GaussianDensityPointParams = typeof GaussianDensityPointParams export async function createGaussianDensityPoint(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityProps, points?: Points) { - const { transform, field: { space, data } } = await unit.computeGaussianDensity(props, ctx.runtime, ctx.webgl) + const { transform, field: { space, data } } = await computeUnitGaussianDensity(unit, props, ctx.webgl).runInContext(ctx.runtime) const { dimensions, get } = space const [ xn, yn, zn ] = dimensions diff --git a/src/mol-repr/structure/visual/gaussian-density-volume.ts b/src/mol-repr/structure/visual/gaussian-density-volume.ts index 3c928cdb6..51b8b809e 100644 --- a/src/mol-repr/structure/visual/gaussian-density-volume.ts +++ b/src/mol-repr/structure/visual/gaussian-density-volume.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Structure, StructureElement } from 'mol-model/structure'; +import { Structure } from 'mol-model/structure'; import { VisualUpdateState } from '../../util'; import { ParamDefinition as PD } from 'mol-util/param-definition'; import { DirectVolume } from 'mol-geo/geometry/direct-volume/direct-volume'; @@ -14,56 +14,9 @@ import { ComplexVisual, ComplexDirectVolumeVisual, ComplexDirectVolumeParams } f import { EmptyLoci } from 'mol-model/loci'; import { NullLocation } from 'mol-model/location'; import { LocationIterator } from 'mol-geo/util/location-iterator'; -import { WebGLContext } from 'mol-gl/webgl/context'; -import { Texture } from 'mol-gl/webgl/texture'; -import { GaussianDensityTexture } from 'mol-math/geometry/gaussian-density/gpu'; -import { Task } from 'mol-task'; -import { OrderedSet } from 'mol-data/int'; -import { PhysicalSizeTheme } from 'mol-theme/size/physical'; +import { computeStructureGaussianDensityTexture, GaussianDensityTextureProps, GaussianDensityTextureParams } from './util/gaussian'; -function getConformationAndRadius(structure: Structure) { - const n = structure.elementCount - - const xs = new Float32Array(n) - const ys = new Float32Array(n) - const zs = new Float32Array(n) - const rs = new Float32Array(n) - - const l = StructureElement.create() - const sizeTheme = PhysicalSizeTheme({}, {}) - - let m = 0 - for (let i = 0, il = structure.units.length; i < il; ++i) { - const unit = structure.units[i] - const { elements } = unit - const { x, y, z } = unit.conformation - l.unit = unit - for (let j = 0, jl = elements.length; j < jl; ++j) { - const eI = elements[j] - xs[m + j] = x(eI) - ys[m + j] = y(eI) - zs[m + j] = z(eI) - l.element = eI - rs[m + j] = sizeTheme.size(l) - } - m += elements.length - } - - const position = { indices: OrderedSet.ofRange(0, n), x: xs, y: ys, z: zs } - const radius = (index: number) => rs[index] - - return { position, radius } -} - -// TODO calculate by combining unit volumes -function computeStructureGaussianDensityTexture(structure: Structure, props: PD.Values<GaussianDensityVolumeParams>, webgl: WebGLContext, texture?: Texture) { - const { position, radius } = getConformationAndRadius(structure) - return Task.create('Gaussian Density', async ctx => { - return await GaussianDensityTexture(ctx, webgl, position, structure.lookup3d.boundary.box, radius, props, texture); - }); -} - -async function createGaussianDensityVolume(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<GaussianDensityVolumeParams>, directVolume?: DirectVolume): Promise<DirectVolume> { +async function createGaussianDensityVolume(ctx: VisualContext, structure: Structure, theme: Theme, props: GaussianDensityTextureProps, directVolume?: DirectVolume): Promise<DirectVolume> { const { runtime, webgl } = ctx if (webgl === undefined) throw new Error('createGaussianDensityVolume requires `webgl` object in VisualContext') @@ -77,9 +30,7 @@ async function createGaussianDensityVolume(ctx: VisualContext, structure: Struct export const GaussianDensityVolumeParams = { ...ComplexDirectVolumeParams, - resolution: PD.Numeric(1, { min: 0.1, max: 10, step: 0.1 }), - radiusOffset: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }), - smoothness: PD.Numeric(1.5, { min: 0.5, max: 2.5, step: 0.1 }), + ...GaussianDensityTextureParams } export type GaussianDensityVolumeParams = typeof GaussianDensityVolumeParams diff --git a/src/mol-repr/structure/visual/gaussian-surface-mesh.ts b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts index 0c01c3c0f..e39766fd4 100644 --- a/src/mol-repr/structure/visual/gaussian-surface-mesh.ts +++ b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts @@ -9,16 +9,16 @@ import { UnitsVisual } from '../representation'; import { VisualUpdateState } from '../../util'; import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; import { StructureElementIterator, getElementLoci, markElement } from './util/element'; -import { GaussianDensityProps, GaussianDensityParams } from 'mol-model/structure/structure/unit/gaussian-density'; import { ParamDefinition as PD } from 'mol-util/param-definition'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { computeMarchingCubesMesh } from 'mol-geo/util/marching-cubes/algorithm'; import { VisualContext } from 'mol-repr/visual'; import { Theme } from 'mol-theme/theme'; +import { GaussianDensityProps, computeUnitGaussianDensity, GaussianDensityParams } from './util/gaussian'; async function createGaussianSurfaceMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityProps, mesh?: Mesh): Promise<Mesh> { const { smoothness } = props - const { transform, field, idField } = await unit.computeGaussianDensity(props, ctx.runtime, ctx.webgl) + const { transform, field, idField } = await computeUnitGaussianDensity(unit, props, ctx.webgl).runInContext(ctx.runtime) const params = { isoLevel: Math.exp(-smoothness), diff --git a/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts b/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts index e17ebb6e2..68c31c56f 100644 --- a/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts +++ b/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts @@ -9,16 +9,16 @@ import { UnitsVisual } from '../representation'; import { VisualUpdateState } from '../../util'; import { UnitsLinesVisual, UnitsLinesParams } from '../units-visual'; import { StructureElementIterator, getElementLoci, markElement } from './util/element'; -import { GaussianDensityProps, GaussianDensityParams } from 'mol-model/structure/structure/unit/gaussian-density'; import { ParamDefinition as PD } from 'mol-util/param-definition'; import { Lines } from 'mol-geo/geometry/lines/lines'; import { computeMarchingCubesLines } from 'mol-geo/util/marching-cubes/algorithm'; import { VisualContext } from 'mol-repr/visual'; import { Theme } from 'mol-theme/theme'; +import { GaussianDensityProps, GaussianDensityParams, computeUnitGaussianDensity } from './util/gaussian'; async function createGaussianWireframe(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityProps, lines?: Lines): Promise<Lines> { const { smoothness } = props - const { transform, field, idField } = await unit.computeGaussianDensity(props, ctx.runtime) + const { transform, field, idField } = await computeUnitGaussianDensity(unit, props, ctx.webgl).runInContext(ctx.runtime) const params = { isoLevel: Math.exp(-smoothness), diff --git a/src/mol-repr/structure/visual/util/gaussian.ts b/src/mol-repr/structure/visual/util/gaussian.ts index 54cd72a4b..2f268c983 100644 --- a/src/mol-repr/structure/visual/util/gaussian.ts +++ b/src/mol-repr/structure/visual/util/gaussian.ts @@ -3,3 +3,127 @@ * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ + +import { Unit, StructureElement, ElementIndex, Structure } from 'mol-model/structure'; +import { GaussianDensity } from 'mol-math/geometry/gaussian-density'; +import { Task, RuntimeContext } from 'mol-task'; +import { DensityData } from 'mol-math/geometry'; +import { ParamDefinition as PD } from 'mol-util/param-definition'; +import { GaussianDensityTexture } from 'mol-math/geometry/gaussian-density/gpu'; +import { Texture } from 'mol-gl/webgl/texture'; +import { WebGLContext } from 'mol-gl/webgl/context'; +import { PhysicalSizeTheme } from 'mol-theme/size/physical'; +import { OrderedSet } from 'mol-data/int'; + +export const GaussianDensityParams = { + resolution: PD.Numeric(1, { min: 0.1, max: 10, step: 0.1 }), + radiusOffset: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }), + smoothness: PD.Numeric(1.5, { min: 0.5, max: 2.5, step: 0.1 }), + useGpu: PD.Boolean(false), + ignoreCache: PD.Boolean(false), +} +export const DefaultGaussianDensityProps = PD.getDefaultValues(GaussianDensityParams) +export type GaussianDensityProps = typeof DefaultGaussianDensityProps + +function getConformation(unit: Unit) { + switch (unit.kind) { + case Unit.Kind.Atomic: return unit.model.atomicConformation + case Unit.Kind.Spheres: return unit.model.coarseConformation.spheres + case Unit.Kind.Gaussians: return unit.model.coarseConformation.gaussians + } +} + +function getUnitConformationAndRadius(unit: Unit) { + const conformation = getConformation(unit) + const { elements } = unit + const position = { + indices: elements, + x: conformation.x, + y: conformation.y, + z: conformation.z + } + + const l = StructureElement.create(unit) + const sizeTheme = PhysicalSizeTheme({}, {}) + const radius = (index: number) => { + l.element = index as ElementIndex + return sizeTheme.size(l) + } + + return { position, radius } +} + +export function computeUnitGaussianDensity(unit: Unit, props: GaussianDensityProps, webgl?: WebGLContext) { + const { position, radius } = getUnitConformationAndRadius(unit) + return Task.create('Gaussian Density', async ctx => { + return await GaussianDensity(ctx, position, unit.lookup3d.boundary.box, radius, props, webgl); + }); +} + +export function computeUnitGaussianDensityTexture(unit: Unit, props: GaussianDensityProps, webgl: WebGLContext, texture?: Texture) { + const { position, radius } = getUnitConformationAndRadius(unit) + return Task.create('Gaussian Density', async ctx => { + return await GaussianDensityTexture(ctx, webgl, position, unit.lookup3d.boundary.box, radius, props, texture); + }); +} + +export async function computeUnitGaussianDensityCached(unit: Unit, props: GaussianDensityProps, cache: Map<string, DensityData>, ctx: RuntimeContext, webgl?: WebGLContext) { + const key = `${props.radiusOffset}|${props.resolution}|${props.smoothness}` + let density = cache.get(key) + if (density && !props.ignoreCache) return density + density = await computeUnitGaussianDensity(unit, props, webgl).runInContext(ctx) + if (!props.ignoreCache) cache.set(key, density) + return density +} + +// + +function getStructureConformationAndRadius(structure: Structure) { + const n = structure.elementCount + + const xs = new Float32Array(n) + const ys = new Float32Array(n) + const zs = new Float32Array(n) + const rs = new Float32Array(n) + + const l = StructureElement.create() + const sizeTheme = PhysicalSizeTheme({}, {}) + + let m = 0 + for (let i = 0, il = structure.units.length; i < il; ++i) { + const unit = structure.units[i] + const { elements } = unit + const { x, y, z } = unit.conformation + l.unit = unit + for (let j = 0, jl = elements.length; j < jl; ++j) { + const eI = elements[j] + xs[m + j] = x(eI) + ys[m + j] = y(eI) + zs[m + j] = z(eI) + l.element = eI + rs[m + j] = sizeTheme.size(l) + } + m += elements.length + } + + const position = { indices: OrderedSet.ofRange(0, n), x: xs, y: ys, z: zs } + const radius = (index: number) => rs[index] + + return { position, radius } +} + +export const GaussianDensityTextureParams = { + resolution: PD.Numeric(1, { min: 0.1, max: 10, step: 0.1 }), + radiusOffset: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }), + smoothness: PD.Numeric(1.5, { min: 0.5, max: 2.5, step: 0.1 }), +} +export const DefaultGaussianDensityTextureProps = PD.getDefaultValues(GaussianDensityTextureParams) +export type GaussianDensityTextureProps = typeof DefaultGaussianDensityTextureProps + +// TODO calculate by combining unit volumes +export function computeStructureGaussianDensityTexture(structure: Structure, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) { + const { position, radius } = getStructureConformationAndRadius(structure) + return Task.create('Gaussian Density', async ctx => { + return await GaussianDensityTexture(ctx, webgl, position, structure.lookup3d.boundary.box, radius, props, texture); + }); +} \ No newline at end of file -- GitLab