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

wip, gaussian surface

parent ec379968
Branches
Tags
No related merge requests found
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
......@@ -32,3 +32,11 @@ export type DensityTextureData = {
bbox: Box3D,
gridDimension: Vec3
}
export function fillGridDim(length: number, start: number, step: number) {
const a = new Float32Array(length)
for (let i = 0; i < a.length; i++) {
a[i] = start + (step * i)
}
return a
}
\ No newline at end of file
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Box3D } from '../../geometry';
import { Box3D, fillGridDim } from '../../geometry';
import { Vec3, Mat4, Tensor } from '../../linear-algebra';
import { RuntimeContext } from 'mol-task';
import { PositionData, DensityData } from '../common';
......@@ -13,6 +13,7 @@ import { GaussianDensityProps, getDelta } from '../gaussian-density';
export async function GaussianDensityCPU(ctx: RuntimeContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps): Promise<DensityData> {
const { resolution, radiusOffset, smoothness } = props
const scaleFactor = 1 / resolution
const { indices, x, y, z } = position
const n = OrderedSet.size(indices)
......@@ -31,11 +32,11 @@ export async function GaussianDensityCPU(ctx: RuntimeContext, position: Position
const pad = maxRadius * 2 + resolution
const expandedBox = Box3D.expand(Box3D.empty(), box, Vec3.create(pad, pad, pad))
const extent = Vec3.sub(Vec3.zero(), expandedBox.max, expandedBox.min)
const extent = Vec3.sub(Vec3(), expandedBox.max, expandedBox.min)
const min = expandedBox.min
const delta = getDelta(Box3D.expand(Box3D.empty(), box, Vec3.create(pad, pad, pad)), resolution)
const dim = Vec3.zero()
const dim = Vec3()
Vec3.ceil(dim, Vec3.mul(dim, extent, delta))
// console.log('grid dim cpu', dim)
......@@ -46,60 +47,59 @@ export async function GaussianDensityCPU(ctx: RuntimeContext, position: Position
const idData = space.create()
const idField = Tensor.create(space, idData)
const iu = dim[2], iv = dim[1], iuv = iu * iv
const [ dimX, dimY, dimZ ] = dim
const iu = dimZ, iv = dimY, iuv = iu * iv
const densData = space.create()
const gridx = fillGridDim(dim[0], min[0], resolution)
const gridy = fillGridDim(dim[1], min[1], resolution)
const gridz = fillGridDim(dim[2], min[2], resolution)
const v = Vec3()
const c = Vec3()
const densData = space.create()
const alpha = smoothness
const updateChunk = Math.ceil(1000000 / (Math.pow(maxRadius * 2, 3) * resolution))
const _r2 = maxRadius * 2
const _radius2 = Vec3.create(_r2, _r2, _r2)
Vec3.mul(_radius2, _radius2, delta)
const updateChunk = Math.ceil(1000000 / (_radius2[0] * _radius2[1] * _radius2[2]))
const beg = Vec3()
const end = Vec3()
const rad2 = Vec3()
const gridPad = 1 / Math.max(...delta)
const invDelta = Vec3.inverse(Vec3(), delta)
const [ invDeltaX, invDeltaY, invDeltaZ ] = invDelta
console.time('gaussian density cpu')
// console.time('gaussian density cpu')
for (let i = 0; i < n; ++i) {
const j = OrderedSet.getAt(indices, i)
Vec3.set(v, x[j], y[j], z[j])
Vec3.sub(v, v, min)
const [ vx, vy, vz ] = v
Vec3.mul(c, v, delta)
const vx = x[j], vy = y[j], vz = z[j]
const rad = radii[i]
const rSq = rad * rad
const rSqInv = 1 / rSq
const r2 = radiusOffset + rad * 2 + gridPad
const r2 = rad * 2
const r2sq = r2 * r2
Vec3.set(rad2, r2, r2, r2)
Vec3.mul(rad2, rad2, delta)
const [ begX, begY, begZ ] = Vec3.floor(beg, Vec3.sub(beg, c, rad2))
const [ endX, endY, endZ ] = Vec3.ceil(end, Vec3.add(end, c, rad2))
// Number of grid points, round this up...
const ng = Math.ceil(r2 * scaleFactor)
// Center of the atom, mapped to grid points (take floor)
const iax = Math.floor(scaleFactor * (vx - min[0]))
const iay = Math.floor(scaleFactor * (vy - min[1]))
const iaz = Math.floor(scaleFactor * (vz - min[2]))
// Extents of grid to consider for this atom
const begX = Math.max(0, iax - ng)
const begY = Math.max(0, iay - ng)
const begZ = Math.max(0, iaz - ng)
// Add two to these points:
// - iax are floor'd values so this ensures coverage
// - these are loop limits (exclusive)
const endX = Math.min(dimX, iax + ng + 2)
const endY = Math.min(dimY, iay + ng + 2)
const endZ = Math.min(dimZ, iaz + ng + 2)
for (let xi = begX; xi < endX; ++xi) {
const dx = xi * invDeltaX - vx
const dx = gridx[xi] - vx
const xIdx = xi * iuv
for (let yi = begY; yi < endY; ++yi) {
const dy = yi * invDeltaY - vy
const dy = gridy[yi] - vy
const dxySq = dx * dx + dy * dy
const xyIdx = yi * iu + xIdx
for (let zi = begZ; zi < endZ; ++zi) {
const dz = zi * invDeltaZ - vz
const dz = gridz[zi] - vz
const dSq = dxySq + dz * dz
if (dSq <= r2sq) {
const dens = Math.exp(-alpha * (dSq * rSqInv))
......@@ -118,7 +118,7 @@ export async function GaussianDensityCPU(ctx: RuntimeContext, position: Position
await ctx.update({ message: 'filling density grid', current: i, max: n })
}
}
console.timeEnd('gaussian density cpu')
// console.timeEnd('gaussian density cpu')
const transform = Mat4.identity()
Mat4.fromScaling(transform, Vec3.inverse(Vec3.zero(), delta))
......
......@@ -15,7 +15,7 @@ import { RuntimeContext } from 'mol-task';
import { OrderedSet } from 'mol-data/int';
import { PositionData } from './common';
import { Mat4 } from 'mol-math/linear-algebra/3d';
import { Box3D, GridLookup3D } from 'mol-math/geometry';
import { Box3D, GridLookup3D, fillGridDim } from 'mol-math/geometry';
import { getDelta } from './gaussian-density';
function normalToLine (out: Vec3, p: Vec3) {
......@@ -45,12 +45,6 @@ function getAngleTables (probePositions: number): AnglesTables {
return { cosTable, sinTable}
}
function fillGridDim(a: Float32Array, start: number, step: number) {
for (let i = 0; i < a.length; i++) {
a[i] = start + (step * i)
}
}
/**
* Is the point at x,y,z obscured by any of the atoms specifeid by indices in neighbours.
* Ignore indices a and b (these are the relevant atoms in projectPoints/Torii)
......@@ -371,13 +365,11 @@ async function createState(ctx: RuntimeContext, position: Required<PositionData>
fillUniform(data, -1001.0)
fillUniform(idData, -1)
const gridx = new Float32Array(dim[0])
const gridy = new Float32Array(dim[1])
const gridz = new Float32Array(dim[2])
const gridx = fillGridDim(dim[0], min[0], resolution)
const gridy = fillGridDim(dim[1], min[1], resolution)
const gridz = fillGridDim(dim[2], min[2], resolution)
fillGridDim(gridx, min[0], resolution)
fillGridDim(gridy, min[1], resolution)
fillGridDim(gridz, min[2], resolution)
const updateChunk = Math.ceil(1000000 / (Math.pow(maxRadius, 3) * resolution))
return {
lastClip: -1,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment