UNPKG

molstar

Version:

A comprehensive macromolecular library.

198 lines (197 loc) 10.6 kB
/** * Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { Grid } from './grid'; import { OrderedSet } from '../../mol-data/int'; import { Sphere3D } from '../../mol-math/geometry'; import { Vec3, Mat4 } from '../../mol-math/linear-algebra'; import { BoundaryHelper } from '../../mol-math/geometry/boundary-helper'; import { CubeFormat } from '../../mol-model-formats/volume/cube'; import { equalEps } from '../../mol-math/linear-algebra/3d/common'; import { CustomProperties } from '../custom-property'; import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { toPrecision } from '../../mol-util/number'; import { DscifFormat } from '../../mol-model-formats/volume/density-server'; export var Volume; (function (Volume) { function is(x) { var _a, _b, _c, _d; // TODO: improve return (((_d = (_c = (_b = (_a = x === null || x === void 0 ? void 0 : x.grid) === null || _a === void 0 ? void 0 : _a.cells) === null || _b === void 0 ? void 0 : _b.space) === null || _c === void 0 ? void 0 : _c.dimensions) === null || _d === void 0 ? void 0 : _d.length) && (x === null || x === void 0 ? void 0 : x.sourceData) && (x === null || x === void 0 ? void 0 : x.customProperties) && (x === null || x === void 0 ? void 0 : x._propertyData)); } Volume.is = is; var IsoValue; (function (IsoValue) { function areSame(a, b, stats) { return equalEps(toAbsolute(a, stats).absoluteValue, toAbsolute(b, stats).absoluteValue, stats.sigma / 100); } IsoValue.areSame = areSame; function absolute(value) { return { kind: 'absolute', absoluteValue: value }; } IsoValue.absolute = absolute; function relative(value) { return { kind: 'relative', relativeValue: value }; } IsoValue.relative = relative; function calcAbsolute(stats, relativeValue) { return relativeValue * stats.sigma + stats.mean; } IsoValue.calcAbsolute = calcAbsolute; function calcRelative(stats, absoluteValue) { return stats.sigma === 0 ? 0 : ((absoluteValue - stats.mean) / stats.sigma); } IsoValue.calcRelative = calcRelative; function toAbsolute(value, stats) { return value.kind === 'absolute' ? value : { kind: 'absolute', absoluteValue: IsoValue.calcAbsolute(stats, value.relativeValue) }; } IsoValue.toAbsolute = toAbsolute; function toRelative(value, stats) { return value.kind === 'relative' ? value : { kind: 'relative', relativeValue: IsoValue.calcRelative(stats, value.absoluteValue) }; } IsoValue.toRelative = toRelative; function toString(value) { return value.kind === 'relative' ? "".concat(value.relativeValue.toFixed(2), " \u03C3") : "".concat(value.absoluteValue.toPrecision(4)); } IsoValue.toString = toString; })(IsoValue = Volume.IsoValue || (Volume.IsoValue = {})); // Converts iso value to relative if using downsample VolumeServer data function adjustedIsoValue(volume, value, kind) { if (kind === 'relative') return IsoValue.relative(value); var absolute = IsoValue.absolute(value); if (DscifFormat.is(volume.sourceData)) { var stats = { min: volume.sourceData.data.volume_data_3d_info.min_source.value(0), max: volume.sourceData.data.volume_data_3d_info.max_source.value(0), mean: volume.sourceData.data.volume_data_3d_info.mean_source.value(0), sigma: volume.sourceData.data.volume_data_3d_info.sigma_source.value(0), }; return Volume.IsoValue.toRelative(absolute, stats); } return absolute; } Volume.adjustedIsoValue = adjustedIsoValue; var defaultStats = { min: -1, max: 1, mean: 0, sigma: 0.1 }; function createIsoValueParam(defaultValue, stats) { var sts = stats || defaultStats; var min = sts.min, max = sts.max, mean = sts.mean, sigma = sts.sigma; // using ceil/floor could lead to "ouf of bounds" when converting var relMin = (min - mean) / sigma; var relMax = (max - mean) / sigma; var def = defaultValue; if (defaultValue.kind === 'absolute') { if (defaultValue.absoluteValue < min) def = Volume.IsoValue.absolute(min); else if (defaultValue.absoluteValue > max) def = Volume.IsoValue.absolute(max); } else { if (defaultValue.relativeValue < relMin) def = Volume.IsoValue.relative(relMin); else if (defaultValue.relativeValue > relMax) def = Volume.IsoValue.relative(relMax); } return PD.Conditioned(def, { 'absolute': PD.Converted(function (v) { return Volume.IsoValue.toAbsolute(v, Grid.One.stats).absoluteValue; }, function (v) { return Volume.IsoValue.absolute(v); }, PD.Numeric(mean, { min: min, max: max, step: toPrecision(sigma / 100, 2) }, { immediateUpdate: true })), 'relative': PD.Converted(function (v) { return Volume.IsoValue.toRelative(v, Grid.One.stats).relativeValue; }, function (v) { return Volume.IsoValue.relative(v); }, PD.Numeric(Math.min(1, relMax), { min: relMin, max: relMax, step: toPrecision(Math.round(((max - min) / sigma)) / 100, 2) }, { immediateUpdate: true })) }, function (v) { return v.kind === 'absolute' ? 'absolute' : 'relative'; }, function (v, c) { return c === 'absolute' ? Volume.IsoValue.toAbsolute(v, sts) : Volume.IsoValue.toRelative(v, sts); }, { isEssential: true }); } Volume.createIsoValueParam = createIsoValueParam; Volume.IsoValueParam = createIsoValueParam(Volume.IsoValue.relative(2)); Volume.One = { label: '', grid: Grid.One, sourceData: { kind: '', name: '', data: {} }, customProperties: new CustomProperties(), _propertyData: Object.create(null), }; function areEquivalent(volA, volB) { return Grid.areEquivalent(volA.grid, volB.grid); } Volume.areEquivalent = areEquivalent; function isEmpty(vol) { return Grid.isEmpty(vol.grid); } Volume.isEmpty = isEmpty; function isOrbitals(volume) { if (!CubeFormat.is(volume.sourceData)) return false; return volume.sourceData.data.header.orbitals; } Volume.isOrbitals = isOrbitals; function Loci(volume) { return { kind: 'volume-loci', volume: volume }; } Volume.Loci = Loci; function isLoci(x) { return !!x && x.kind === 'volume-loci'; } Volume.isLoci = isLoci; function areLociEqual(a, b) { return a.volume === b.volume; } Volume.areLociEqual = areLociEqual; function isLociEmpty(loci) { return Grid.isEmpty(loci.volume.grid); } Volume.isLociEmpty = isLociEmpty; function getBoundingSphere(volume, boundingSphere) { return Grid.getBoundingSphere(volume.grid, boundingSphere); } Volume.getBoundingSphere = getBoundingSphere; var Isosurface; (function (Isosurface) { function Loci(volume, isoValue) { return { kind: 'isosurface-loci', volume: volume, isoValue: isoValue }; } Isosurface.Loci = Loci; function isLoci(x) { return !!x && x.kind === 'isosurface-loci'; } Isosurface.isLoci = isLoci; function areLociEqual(a, b) { return a.volume === b.volume && Volume.IsoValue.areSame(a.isoValue, b.isoValue, a.volume.grid.stats); } Isosurface.areLociEqual = areLociEqual; function isLociEmpty(loci) { return loci.volume.grid.cells.data.length === 0; } Isosurface.isLociEmpty = isLociEmpty; function getBoundingSphere(volume, isoValue, boundingSphere) { // TODO get bounding sphere for subgrid with values >= isoValue return Volume.getBoundingSphere(volume, boundingSphere); } Isosurface.getBoundingSphere = getBoundingSphere; })(Isosurface = Volume.Isosurface || (Volume.Isosurface = {})); var Cell; (function (Cell) { function Loci(volume, indices) { return { kind: 'cell-loci', volume: volume, indices: indices }; } Cell.Loci = Loci; function isLoci(x) { return !!x && x.kind === 'cell-loci'; } Cell.isLoci = isLoci; function areLociEqual(a, b) { return a.volume === b.volume && OrderedSet.areEqual(a.indices, b.indices); } Cell.areLociEqual = areLociEqual; function isLociEmpty(loci) { return OrderedSet.size(loci.indices) === 0; } Cell.isLociEmpty = isLociEmpty; var boundaryHelper = new BoundaryHelper('98'); var tmpBoundaryPos = Vec3(); function getBoundingSphere(volume, indices, boundingSphere) { boundaryHelper.reset(); var transform = Grid.getGridToCartesianTransform(volume.grid); var getCoords = volume.grid.cells.space.getCoords; for (var i = 0, _i = OrderedSet.size(indices); i < _i; i++) { var o = OrderedSet.getAt(indices, i); getCoords(o, tmpBoundaryPos); Vec3.transformMat4(tmpBoundaryPos, tmpBoundaryPos, transform); boundaryHelper.includePosition(tmpBoundaryPos); } boundaryHelper.finishedIncludeStep(); for (var i = 0, _i = OrderedSet.size(indices); i < _i; i++) { var o = OrderedSet.getAt(indices, i); getCoords(o, tmpBoundaryPos); Vec3.transformMat4(tmpBoundaryPos, tmpBoundaryPos, transform); boundaryHelper.radiusPosition(tmpBoundaryPos); } var bs = boundaryHelper.getSphere(boundingSphere); return Sphere3D.expand(bs, bs, Mat4.getMaxScaleOnAxis(transform) * 10); } Cell.getBoundingSphere = getBoundingSphere; })(Cell = Volume.Cell || (Volume.Cell = {})); Volume.PickingGranularity = { set: function (volume, granularity) { volume._propertyData['__picking_granularity__'] = granularity; }, get: function (volume) { var _a; return (_a = volume._propertyData['__picking_granularity__']) !== null && _a !== void 0 ? _a : 'voxel'; } }; })(Volume || (Volume = {}));