molstar
Version:
A comprehensive macromolecular library.
194 lines (193 loc) • 6.4 kB
JavaScript
/**
* Copyright (c) 2018-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.DefaultQualityThresholds = exports.VisualUpdateState = void 0;
exports.getStructureQuality = getStructureQuality;
exports.getQualityProps = getQualityProps;
const mol_util_1 = require("../mol-util");
const structure_1 = require("../mol-model/structure");
const geometry_1 = require("../mol-math/geometry");
const symmetry_1 = require("../mol-model-formats/structure/property/symmetry");
const volume_1 = require("../mol-model/volume");
var VisualUpdateState;
(function (VisualUpdateState) {
function create() {
return {
updateTransform: false,
updateMatrix: false,
updateColor: false,
updateSize: false,
createGeometry: false,
createNew: false,
info: {}
};
}
VisualUpdateState.create = create;
function reset(state) {
state.updateTransform = false;
state.updateMatrix = false;
state.updateColor = false;
state.updateSize = false;
state.createGeometry = false;
state.createNew = false;
}
VisualUpdateState.reset = reset;
})(VisualUpdateState || (exports.VisualUpdateState = VisualUpdateState = {}));
exports.DefaultQualityThresholds = {
lowestElementCount: 1000000,
lowerElementCount: 500000,
lowElementCount: 100000,
mediumElementCount: 20000,
highElementCount: 2000,
coarseGrainedFactor: 10,
elementCountFactor: 1
};
function getStructureQuality(structure, tresholds = {}) {
const t = { ...exports.DefaultQualityThresholds, ...tresholds };
let score = structure.elementCount * t.elementCountFactor;
if (structure.isCoarseGrained || structure.isCoarse)
score *= t.coarseGrainedFactor;
if (score > t.lowestElementCount) {
return 'lowest';
}
else if (score > t.lowerElementCount) {
return 'lower';
}
else if (score > t.lowElementCount) {
return 'low';
}
else if (score > t.mediumElementCount) {
return 'medium';
}
else if (score > t.highElementCount) {
return 'high';
}
else {
return 'higher';
}
}
/**
* Uses cell volume to avoid costly boundary calculation if
* - single model
* - non-empty 'P 1' spacegroup
*/
function getRootVolume(structure) {
if (structure.root.models.length === 1) {
const sym = symmetry_1.ModelSymmetry.Provider.get(structure.root.model);
if (sym && sym.spacegroup.name === 'P 1' && !geometry_1.SpacegroupCell.isZero(sym.spacegroup.cell)) {
return sym.spacegroup.cell.volume;
}
}
return geometry_1.Box3D.volume(structure.root.boundary.box);
}
function getQualityProps(props, data) {
let quality = (0, mol_util_1.defaults)(props.quality, 'auto');
let detail = (0, mol_util_1.defaults)(props.detail, 1);
let radialSegments = (0, mol_util_1.defaults)(props.radialSegments, 12);
let linearSegments = (0, mol_util_1.defaults)(props.linearSegments, 8);
let resolution = (0, mol_util_1.defaults)(props.resolution, 2);
let imageResolution = (0, mol_util_1.defaults)(props.imageResolution, 1);
let probePositions = (0, mol_util_1.defaults)(props.probePositions, 12);
let doubleSided = (0, mol_util_1.defaults)(props.doubleSided, true);
let volume = 0;
if (quality === 'auto') {
if (data instanceof structure_1.Structure) {
quality = getStructureQuality(data.root);
volume = getRootVolume(data);
}
else if (volume_1.Volume.is(data)) {
const [x, y, z] = data.grid.cells.space.dimensions;
volume = x * y * z;
quality = volume < 10000000 ? 'medium' : 'low';
}
}
switch (quality) {
case 'highest':
detail = 3;
radialSegments = 36;
linearSegments = 18;
resolution = 0.1;
imageResolution = 0.01;
probePositions = 72;
doubleSided = true;
break;
case 'higher':
detail = 3;
radialSegments = 28;
linearSegments = 14;
resolution = 0.3;
imageResolution = 0.05;
probePositions = 48;
doubleSided = true;
break;
case 'high':
detail = 2;
radialSegments = 20;
linearSegments = 10;
resolution = 0.5;
imageResolution = 0.1;
probePositions = 36;
doubleSided = true;
break;
case 'medium':
detail = 1;
radialSegments = 12;
linearSegments = 8;
resolution = 0.8;
imageResolution = 0.2;
probePositions = 24;
doubleSided = true;
break;
case 'low':
detail = 0;
radialSegments = 8;
linearSegments = 3;
resolution = 1.3;
imageResolution = 0.4;
probePositions = 24;
doubleSided = false;
break;
case 'lower':
detail = 0;
radialSegments = 4;
linearSegments = 2;
resolution = 3;
imageResolution = 0.7;
probePositions = 12;
doubleSided = false;
break;
case 'lowest':
detail = 0;
radialSegments = 2;
linearSegments = 1;
resolution = 8;
imageResolution = 1;
probePositions = 12;
doubleSided = false;
break;
case 'custom':
// use defaults or given props as set above
break;
}
// max resolution based on volume (for 'auto' quality)
if (volume > 0) {
resolution = Math.max(resolution, volume / 300000000);
resolution = Math.min(resolution, 20);
}
if (props.transparentBackfaces === 'off' && ((props.alpha !== undefined && props.alpha < 1) || !!props.xrayShaded)) {
doubleSided = false;
}
return {
detail,
radialSegments,
linearSegments,
resolution,
imageResolution,
probePositions,
doubleSided
};
}
;