diff --git a/src/apps/canvas/index.ts b/src/apps/canvas/index.ts index c848f987e08498d97caee37b5c533be760e3c230..1124f99841ca574dc47f6d9ebdd659eb7f6ea09d 100644 --- a/src/apps/canvas/index.ts +++ b/src/apps/canvas/index.ts @@ -23,7 +23,11 @@ const assemblyId = urlQueryParameter('assembly') const pdbId = urlQueryParameter('pdb') if (pdbId) app.loadPdbIdOrMmcifUrl(pdbId, { assemblyId }) -// app.loadCcp4Url('http://localhost:8091/ngl/data/betaGal.mrc') +// app.loadPdbIdOrMmcifUrl('3pqr') +// app.loadCcp4Url('http://localhost:8091/ngl/data/3pqr-mode0.ccp4') + +app.loadPdbIdOrMmcifUrl('6DRV') +app.loadCcp4Url('http://localhost:8091/ngl/data/betaGal.mrc') // app.loadPdbIdOrMmcifUrl('3pqr') // app.loadVolCifUrl('https://webchem.ncbr.muni.cz/DensityServer/x-ray/3pqr/cell?space=fractional', true) @@ -32,4 +36,57 @@ if (pdbId) app.loadPdbIdOrMmcifUrl(pdbId, { assemblyId }) // app.loadVolcifUrl('https://webchem.ncbr.muni.cz/DensityServer/em/emd-8116/cell?space=cartesian&detail=6', true) // app.loadPdbIdOrMmcifUrl('5gag') -// app.loadVolcifUrl('https://webchem.ncbr.muni.cz/DensityServer/em/emd-8003/cell?detail=3', true) \ No newline at end of file +// app.loadVolcifUrl('https://webchem.ncbr.muni.cz/DensityServer/em/emd-8003/cell?detail=3', true) + +// app.loadPdbIdOrMmcifUrl('http://localhost:8091/test/pdb-dev/carb/1B5F-carb.cif') +// app.loadPdbIdOrMmcifUrl('http://localhost:8091/test/pdb-dev/carb/2HYV-carb.cif') +// app.loadPdbIdOrMmcifUrl('http://localhost:8091/test/pdb-dev/carb/2WMG-carb.cif') +// app.loadPdbIdOrMmcifUrl('http://localhost:8091/test/pdb-dev/carb/5KDS-carb.cif') + +const basisX = [ + h.xlen, + 0, + 0 + ] + + const basisY = [ + h.ylen * Math.cos(Math.PI / 180.0 * h.gamma), + h.ylen * Math.sin(Math.PI / 180.0 * h.gamma), + 0 + ] + + const basisZ = [ + h.zlen * Math.cos(Math.PI / 180.0 * h.beta), + h.zlen * ( + Math.cos(Math.PI / 180.0 * h.alpha) - + Math.cos(Math.PI / 180.0 * h.gamma) * + Math.cos(Math.PI / 180.0 * h.beta) + ) / Math.sin(Math.PI / 180.0 * h.gamma), + 0 + ] + basisZ[ 2 ] = Math.sqrt( + h.zlen * h.zlen * Math.sin(Math.PI / 180.0 * h.beta) * + Math.sin(Math.PI / 180.0 * h.beta) - basisZ[ 1 ] * basisZ[ 1 ] + ) + + const basis = [ 0, basisX, basisY, basisZ ] + const nxyz = [ 0, h.MX, h.MY, h.MZ ] + const mapcrs = [ 0, h.MAPC, h.MAPR, h.MAPS ] + + const matrix = new Matrix4() + + matrix.set( + basis[ mapcrs[1] ][0] / nxyz[ mapcrs[1] ], + basis[ mapcrs[2] ][0] / nxyz[ mapcrs[2] ], + basis[ mapcrs[3] ][0] / nxyz[ mapcrs[3] ], + 0, + basis[ mapcrs[1] ][1] / nxyz[ mapcrs[1] ], + basis[ mapcrs[2] ][1] / nxyz[ mapcrs[2] ], + basis[ mapcrs[3] ][1] / nxyz[ mapcrs[3] ], + 0, + basis[ mapcrs[1] ][2] / nxyz[ mapcrs[1] ], + basis[ mapcrs[2] ][2] / nxyz[ mapcrs[2] ], + basis[ mapcrs[3] ][2] / nxyz[ mapcrs[3] ], + 0, + 0, 0, 0, 1 + ) \ No newline at end of file diff --git a/src/apps/canvas/structure-view.ts b/src/apps/canvas/structure-view.ts index dce28b08646960608f900b5a4ec2ba84edef3886..bd35a273e5f6cd52f55fbb6a2c7af42ad78b1ab4 100644 --- a/src/apps/canvas/structure-view.ts +++ b/src/apps/canvas/structure-view.ts @@ -64,15 +64,13 @@ interface StructureViewProps { symmetryFeatureId?: number } - - export async function StructureView(app: App, viewer: Viewer, models: ReadonlyArray<Model>, props: StructureViewProps = {}): Promise<StructureView> { const active: { [k: string]: boolean } = { cartoon: true, point: false, surface: false, ballAndStick: false, - carbohydrate: false, + carbohydrate: true, spacefill: false, distanceRestraint: false, symmetryAxes: false, diff --git a/src/mol-geo/representation/volume/direct-volume.ts b/src/mol-geo/representation/volume/direct-volume.ts index 1dd1e9446bcad8bab3e1f2918d6fb1acd4917277..00c62032fce172f83b57ac4974b2ab1a69228804 100644 --- a/src/mol-geo/representation/volume/direct-volume.ts +++ b/src/mol-geo/representation/volume/direct-volume.ts @@ -112,10 +112,37 @@ function createVolumeTexture3d(volume: VolumeData) { const array = new Uint8Array(width * height * depth * 4) const textureVolume = { array, width, height, depth } + console.log('stats', stats) + + // let i = 0 + // for (let z = 0; z < depth; ++z) { + // for (let y = 0; y < height; ++y) { + // for (let x = 0; x < width; ++x) { + // array[i + 3] = ((get(data, x, y, z) - stats.min) / (stats.max - stats.min)) * 255 + // // array[i + 3] = ((get(data, x, z, y) - stats.min) / (stats.max - stats.min)) * 255 + // // array[i + 3] = ((get(data, y, x, z) - stats.min) / (stats.max - stats.min)) * 255 + // // array[i + 3] = ((get(data, y, z, x) - stats.min) / (stats.max - stats.min)) * 255 + // // array[i + 3] = ((get(data, z, y, x) - stats.min) / (stats.max - stats.min)) * 255 + // // array[i + 3] = ((get(data, z, x, y) - stats.min) / (stats.max - stats.min)) * 255 + // i += 4 + // } + // } + // } + + // let i = 0 + // for (let z = 0; z < depth; ++z) { + // for (let x = 0; x < width; ++x) { + // for (let y = 0; y < height; ++y) { + // array[i + 3] = ((get(data, x, y, z) - stats.min) / (stats.max - stats.min)) * 255 + // i += 4 + // } + // } + // } + let i = 0 - for (let z = 0; z < depth; ++z) { + for (let x = 0; x < width; ++x) { for (let y = 0; y < height; ++y) { - for (let x = 0; x < width; ++x) { + for (let z = 0; z < depth; ++z) { array[i + 3] = ((get(data, x, y, z) - stats.min) / (stats.max - stats.min)) * 255 i += 4 } @@ -129,6 +156,7 @@ export function createDirectVolume3d(ctx: RuntimeContext, webgl: Context, volume const gridDimension = volume.data.space.dimensions as Vec3 const textureVolume = createVolumeTexture3d(volume) const transform = VolumeData.getGridToCartesianTransform(volume) + // Mat4.invert(transform, transform) const bbox = getBoundingBox(gridDimension, transform) const texture = directVolume ? directVolume.gridTexture.ref.value : createTexture(webgl, 'volume-uint8', 'rgba', 'ubyte', 'linear') @@ -185,6 +213,8 @@ export function DirectVolumeVisual(): VolumeVisual<DirectVolumeProps> { // newProps.isoValueAbsolute = VolumeIsoValue.calcAbsolute(currentVolume.dataStats, props.isoValueRelative) } + console.log('newProps.isoValueAbsolute', newProps.isoValueAbsolute) + DirectVolume.updateValues(renderObject.values, newProps) updateRenderableState(renderObject.state, newProps) diff --git a/src/mol-gl/shader/direct-volume.vert b/src/mol-gl/shader/direct-volume.vert index 248ddcaebd330ef6df7264e57b211948962ff901..3e2e594ccf0647a8251d084f8b0c15288bdefe9a 100644 --- a/src/mol-gl/shader/direct-volume.vert +++ b/src/mol-gl/shader/direct-volume.vert @@ -18,13 +18,16 @@ varying float instance; uniform vec3 uBboxSize; uniform vec3 uBboxMin; uniform vec3 uBboxMax; +uniform vec3 uGridDim; +uniform mat4 uTransform; uniform mat4 uModelView; uniform mat4 uProjection; void main() { unitCoord = aPosition + vec3(0.5); - vec4 mvPosition = uModelView * vec4(unitCoord * uBboxSize + uBboxMin, 1.0); + vec4 mvPosition = uModelView * uTransform * vec4(unitCoord * uGridDim + uBboxMin, 1.0); + // vec4 mvPosition = uModelView * uTransform * vec4(unitCoord, 1.0); origPos = unitCoord * uBboxSize + uBboxMin; instance = aInstance; gl_Position = uProjection * mvPosition; diff --git a/src/mol-model/volume/data.ts b/src/mol-model/volume/data.ts index cda1035294766b00ea4edc8970c9bee925f1b95f..ee9fd299f3920e11e2cee42f4b192b0d70a135b4 100644 --- a/src/mol-model/volume/data.ts +++ b/src/mol-model/volume/data.ts @@ -25,7 +25,10 @@ namespace VolumeData { export function getGridToCartesianTransform(volume: VolumeData) { const { data: { space } } = volume; const scale = Mat4.fromScaling(_scale, Vec3.div(Vec3.zero(), Box3D.size(Vec3.zero(), volume.fractionalBox), Vec3.ofArray(space.dimensions))); + const scale1 = Mat4.getScaling(Vec3.zero(), scale) + console.log('scale1', scale1) const translate = Mat4.fromTranslation(_translate, volume.fractionalBox.min); + console.log('translate1', translate) return Mat4.mul3(Mat4.zero(), volume.cell.fromFractional, translate, scale); } } diff --git a/src/mol-model/volume/formats/ccp4.ts b/src/mol-model/volume/formats/ccp4.ts index eaa685c1eebd53312011f299bded0c7081b686a4..34af61067270113deebf14a8e78ba7582457ec37 100644 --- a/src/mol-model/volume/formats/ccp4.ts +++ b/src/mol-model/volume/formats/ccp4.ts @@ -7,7 +7,7 @@ import { VolumeData } from '../data' import { Task } from 'mol-task'; import { SpacegroupCell, Box3D } from 'mol-math/geometry'; -import { Tensor, Vec3 } from 'mol-math/linear-algebra'; +import { Tensor, Vec3, Mat4 } from 'mol-math/linear-algebra'; import { Ccp4File } from 'mol-io/reader/ccp4/schema'; import { degToRad } from 'mol-math/misc'; @@ -28,7 +28,7 @@ import { degToRad } from 'mol-math/misc'; function volumeFromCcp4(source: Ccp4File): Task<VolumeData> { return Task.create<VolumeData>('Parse Volume Data', async ctx => { const { header, values } = source; - + console.log('header', header) const cell = SpacegroupCell.create( header.ISPG, Vec3.create(header.xLength, header.yLength, header.zLength), @@ -41,9 +41,9 @@ function volumeFromCcp4(source: Ccp4File): Task<VolumeData> { const grid = [header.NX, header.NY, header.NZ]; const extent = normalizeOrder([header.NC, header.NR, header.NS]); - const gridOrigin: number[] = normalizeOrder([header.NCSTART, header.NRSTART, header.NSSTART]); + const gridOrigin = normalizeOrder([header.NCSTART, header.NRSTART, header.NSSTART]); - // TODO: this is code from LiteMol, but not sure about the part based on originXYZ. The + // TODO: this is code from LiteMol, but not sure about the part based on originXYZ. The // if (header.originX === 0.0 && header.originY === 0.0 && header.originZ === 0.0) { // gridOrigin = normalizeOrder([header.NCSTART, header.NRSTART, header.NSSTART]); // } else { @@ -58,6 +58,13 @@ function volumeFromCcp4(source: Ccp4File): Task<VolumeData> { const origin_frac = Vec3.create(gridOrigin[0] / grid[0], gridOrigin[1] / grid[1], gridOrigin[2] / grid[2]); const dimensions_frac = Vec3.create(extent[0] / grid[0], extent[1] / grid[1], extent[2] / grid[2]); + console.log('length', header.xLength, header.yLength, header.zLength) + console.log('grid', grid) + console.log('extent', extent) + console.log('gridOrigin', gridOrigin) + console.log('origin_frac', origin_frac) + console.log('dimensions_frac', dimensions_frac) + const space = Tensor.Space(extent, Tensor.invertAxisOrder(axis_order_fast_to_slow), header.MODE === 0 ? Int8Array : Float32Array); const data = Tensor.create(space, Tensor.Data1(values)); @@ -65,7 +72,7 @@ function volumeFromCcp4(source: Ccp4File): Task<VolumeData> { // Min/max/mean are reliable (based on LiteMol/DensityServer usage) // These, however, calculate sigma, so no data on that. - return { + const vd = { cell, fractionalBox: Box3D.create(origin_frac, Vec3.add(Vec3.zero(), origin_frac, dimensions_frac)), data, @@ -76,6 +83,12 @@ function volumeFromCcp4(source: Ccp4File): Task<VolumeData> { sigma: header.ARMS } }; + + const transform = VolumeData.getGridToCartesianTransform(vd); + const scale = Mat4.getScaling(Vec3.zero(), transform) + console.log('transform', transform) + console.log('scale', scale) + return vd }); }