UNPKG

molstar

Version:

A comprehensive macromolecular library.

324 lines (323 loc) 13.2 kB
/** * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { StructureElement } from './structure'; import { Bond } from './structure/structure/unit/bonds'; import { Shape, ShapeGroup } from './shape'; import { Sphere3D } from '../mol-math/geometry'; import { Vec3 } from '../mol-math/linear-algebra'; import { Structure } from './structure/structure'; import { ParamDefinition } from '../mol-util/param-definition'; import { shallowEqual } from '../mol-util'; import { BoundaryHelper } from '../mol-math/geometry/boundary-helper'; import { stringToWords } from '../mol-util/string'; import { Volume } from './volume/volume'; /** A Loci that includes every loci */ export var EveryLoci = { kind: 'every-loci' }; export function isEveryLoci(x) { return !!x && x.kind === 'every-loci'; } /** A Loci that is empty */ export var EmptyLoci = { kind: 'empty-loci' }; export function isEmptyLoci(x) { return !!x && x.kind === 'empty-loci'; } export function isDataLoci(x) { return !!x && x.kind === 'data-loci'; } export function areDataLociEqual(a, b) { // use shallowEqual to allow simple data objects that are contructed on-the-fly if (!shallowEqual(a.data, b.data) || a.tag !== b.tag) return false; if (a.elements.length !== b.elements.length) return false; for (var i = 0, il = a.elements.length; i < il; ++i) { if (!shallowEqual(a.elements[i], b.elements[i])) return false; } return true; } export function isDataLociEmpty(loci) { return loci.elements.length === 0 ? true : false; } export function DataLoci(tag, data, elements, getBoundingSphere, getLabel) { return { kind: 'data-loci', tag: tag, data: data, elements: elements, getBoundingSphere: getBoundingSphere, getLabel: getLabel }; } export { Loci }; var Loci; (function (Loci) { var boundaryHelper = new BoundaryHelper('98'); function getBundleBoundingSphere(bundle) { var spheres = bundle.loci.map(function (l) { return getBoundingSphere(l); }).filter(function (s) { return !!s; }); boundaryHelper.reset(); for (var _i = 0, spheres_1 = spheres; _i < spheres_1.length; _i++) { var s = spheres_1[_i]; boundaryHelper.includePositionRadius(s.center, s.radius); } boundaryHelper.finishedIncludeStep(); for (var _a = 0, spheres_2 = spheres; _a < spheres_2.length; _a++) { var s = spheres_2[_a]; boundaryHelper.radiusPositionRadius(s.center, s.radius); } return boundaryHelper.getSphere(); } Loci.getBundleBoundingSphere = getBundleBoundingSphere; function areEqual(lociA, lociB) { if (isEveryLoci(lociA) && isEveryLoci(lociB)) return true; if (isEmptyLoci(lociA) && isEmptyLoci(lociB)) return true; if (isDataLoci(lociA) && isDataLoci(lociB)) { return areDataLociEqual(lociA, lociB); } if (Structure.isLoci(lociA) && Structure.isLoci(lociB)) { return Structure.areLociEqual(lociA, lociB); } if (StructureElement.Loci.is(lociA) && StructureElement.Loci.is(lociB)) { return StructureElement.Loci.areEqual(lociA, lociB); } if (Bond.isLoci(lociA) && Bond.isLoci(lociB)) { return Bond.areLociEqual(lociA, lociB); } if (Shape.isLoci(lociA) && Shape.isLoci(lociB)) { return Shape.areLociEqual(lociA, lociB); } if (ShapeGroup.isLoci(lociA) && ShapeGroup.isLoci(lociB)) { return ShapeGroup.areLociEqual(lociA, lociB); } if (Volume.isLoci(lociA) && Volume.isLoci(lociB)) { return Volume.areLociEqual(lociA, lociB); } if (Volume.Isosurface.isLoci(lociA) && Volume.Isosurface.isLoci(lociB)) { return Volume.Isosurface.areLociEqual(lociA, lociB); } if (Volume.Cell.isLoci(lociA) && Volume.Cell.isLoci(lociB)) { return Volume.Cell.areLociEqual(lociA, lociB); } return false; } Loci.areEqual = areEqual; function isEvery(loci) { return !!loci && loci.kind === 'every-loci'; } Loci.isEvery = isEvery; function isEmpty(loci) { if (isEveryLoci(loci)) return false; if (isEmptyLoci(loci)) return true; if (isDataLoci(loci)) return isDataLociEmpty(loci); if (Structure.isLoci(loci)) return Structure.isLociEmpty(loci); if (StructureElement.Loci.is(loci)) return StructureElement.Loci.isEmpty(loci); if (Bond.isLoci(loci)) return Bond.isLociEmpty(loci); if (Shape.isLoci(loci)) return Shape.isLociEmpty(loci); if (ShapeGroup.isLoci(loci)) return ShapeGroup.isLociEmpty(loci); if (Volume.isLoci(loci)) return Volume.isLociEmpty(loci); if (Volume.Isosurface.isLoci(loci)) return Volume.Isosurface.isLociEmpty(loci); if (Volume.Cell.isLoci(loci)) return Volume.Cell.isLociEmpty(loci); return false; } Loci.isEmpty = isEmpty; function remap(loci, data) { if (data instanceof Structure) { if (StructureElement.Loci.is(loci)) { loci = StructureElement.Loci.remap(loci, data); } else if (Structure.isLoci(loci)) { loci = Structure.remapLoci(loci, data); } else if (Bond.isLoci(loci)) { loci = Bond.remapLoci(loci, data); } } return loci; } Loci.remap = remap; function getBoundingSphere(loci, boundingSphere) { var _a; if (loci.kind === 'every-loci' || loci.kind === 'empty-loci') return void 0; if (!boundingSphere) boundingSphere = Sphere3D(); if (loci.kind === 'structure-loci') { return Sphere3D.copy(boundingSphere, loci.structure.boundary.sphere); } else if (loci.kind === 'element-loci') { return Sphere3D.copy(boundingSphere, StructureElement.Loci.getBoundary(loci).sphere); } else if (loci.kind === 'bond-loci') { return Bond.getBoundingSphere(loci, boundingSphere); } else if (loci.kind === 'shape-loci') { return Sphere3D.copy(boundingSphere, loci.shape.geometry.boundingSphere); } else if (loci.kind === 'group-loci') { return ShapeGroup.getBoundingSphere(loci, boundingSphere); } else if (loci.kind === 'data-loci') { return (_a = loci.getBoundingSphere) === null || _a === void 0 ? void 0 : _a.call(loci, boundingSphere); } else if (loci.kind === 'volume-loci') { return Volume.getBoundingSphere(loci.volume, boundingSphere); } else if (loci.kind === 'isosurface-loci') { return Volume.Isosurface.getBoundingSphere(loci.volume, loci.isoValue, boundingSphere); } else if (loci.kind === 'cell-loci') { return Volume.Cell.getBoundingSphere(loci.volume, loci.indices, boundingSphere); } } Loci.getBoundingSphere = getBoundingSphere; var tmpSphere3D = Sphere3D.zero(); function getCenter(loci, center) { var boundingSphere = getBoundingSphere(loci, tmpSphere3D); return boundingSphere ? Vec3.copy(center || Vec3(), boundingSphere.center) : undefined; } Loci.getCenter = getCenter; function getPrincipalAxes(loci) { if (loci.kind === 'every-loci' || loci.kind === 'empty-loci') return void 0; if (loci.kind === 'structure-loci') { return StructureElement.Loci.getPrincipalAxes(Structure.toStructureElementLoci(loci.structure)); } else if (loci.kind === 'element-loci') { return StructureElement.Loci.getPrincipalAxes(loci); } else if (loci.kind === 'bond-loci') { // TODO return void 0; } else if (loci.kind === 'shape-loci') { // TODO return void 0; } else if (loci.kind === 'group-loci') { // TODO return void 0; } else if (loci.kind === 'data-loci') { // TODO maybe add loci.getPrincipalAxes()??? return void 0; } else if (loci.kind === 'volume-loci') { // TODO return void 0; } else if (loci.kind === 'isosurface-loci') { // TODO return void 0; } else if (loci.kind === 'cell-loci') { // TODO return void 0; } } Loci.getPrincipalAxes = getPrincipalAxes; // var Granularity = { 'element': function (loci) { return loci; }, 'residue': function (loci) { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToWholeResidues(loci, true) : loci; }, 'chain': function (loci) { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToWholeChains(loci) : loci; }, 'entity': function (loci) { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToWholeEntities(loci) : loci; }, 'model': function (loci) { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToWholeModels(loci) : loci; }, 'operator': function (loci) { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToWholeOperators(loci) : loci; }, 'structure': function (loci) { return StructureElement.Loci.is(loci) ? Structure.toStructureElementLoci(loci.structure) : ShapeGroup.isLoci(loci) ? Shape.Loci(loci.shape) : Volume.Cell.isLoci(loci) ? Volume.Loci(loci.volume) : loci; }, 'elementInstances': function (loci) { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToAllInstances(loci) : loci; }, 'residueInstances': function (loci) { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToAllInstances(StructureElement.Loci.extendToWholeResidues(loci, true)) : loci; }, 'chainInstances': function (loci) { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToAllInstances(StructureElement.Loci.extendToWholeChains(loci)) : loci; }, }; Loci.GranularityOptions = ParamDefinition.objectToOptions(Granularity, function (k) { switch (k) { case 'element': return 'Atom/Coarse Element'; case 'elementInstances': return ['Atom/Coarse Element Instances', 'With Symmetry']; case 'structure': return 'Structure/Shape'; default: return k.indexOf('Instances') ? [stringToWords(k), 'With Symmetry'] : stringToWords(k); } }); /** Exclude `Instances` granularity kinds */ function simpleGranularity(granularity) { return granularity.replace('Instances', ''); } Loci.simpleGranularity = simpleGranularity; function applyGranularity(loci, granularity) { return Granularity[granularity](loci); } Loci.applyGranularity = applyGranularity; /** * Converts structure related loci to StructureElement.Loci and applies * granularity if given */ function normalize(loci, granularity, alwaysConvertBonds) { if (alwaysConvertBonds === void 0) { alwaysConvertBonds = false; } if ((granularity !== 'element' || alwaysConvertBonds) && Bond.isLoci(loci)) { // convert Bond.Loci to a StructureElement.Loci so granularity can be applied loci = Bond.toStructureElementLoci(loci); } if (Structure.isLoci(loci)) { // convert to StructureElement.Loci loci = Structure.toStructureElementLoci(loci.structure); } if (StructureElement.Loci.is(loci)) { // ensure the root structure is used loci = StructureElement.Loci.remap(loci, loci.structure.root); } if (granularity) { // needs to be applied AFTER remapping to root loci = applyGranularity(loci, granularity); } return loci; } Loci.normalize = normalize; })(Loci || (Loci = {}));