molstar
Version:
A comprehensive macromolecular library.
262 lines (261 loc) • 12.2 kB
JavaScript
/**
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { __assign } from "tslib";
import { BondType } from '../../../../mol-model/structure/model/types';
import { Unit, StructureElement, Structure, Bond } from '../../../../mol-model/structure';
import { ParamDefinition as PD } from '../../../../mol-util/param-definition';
import { LocationIterator } from '../../../../mol-geo/util/location-iterator';
import { LinkCylinderParams, LinkLineParams } from './link';
import { ObjectKeys } from '../../../../mol-util/type-helpers';
import { EmptyLoci } from '../../../../mol-model/loci';
import { Interval, OrderedSet, SortedArray } from '../../../../mol-data/int';
import { isH, isHydrogen } from './common';
export var BondParams = {
includeTypes: PD.MultiSelect(ObjectKeys(BondType.Names), PD.objectToOptions(BondType.Names)),
excludeTypes: PD.MultiSelect([], PD.objectToOptions(BondType.Names)),
ignoreHydrogens: PD.Boolean(false),
aromaticBonds: PD.Boolean(true, { description: 'Display aromatic bonds with dashes' }),
multipleBonds: PD.Select('symmetric', PD.arrayToOptions(['off', 'symmetric', 'offset'])),
};
export var DefaultBondProps = PD.getDefaultValues(BondParams);
export var BondCylinderParams = __assign(__assign(__assign({}, LinkCylinderParams), BondParams), { adjustCylinderLength: PD.Boolean(false, { description: 'Shorten cylinders to reduce overlap with spheres. Useful for for transparent bonds. Not working well with aromatic bonds.' }) });
export var DefaultBondCylinderProps = PD.getDefaultValues(BondCylinderParams);
export var BondLineParams = __assign(__assign({}, LinkLineParams), BondParams);
export var DefaultBondLineProps = PD.getDefaultValues(BondLineParams);
export function ignoreBondType(include, exclude, f) {
return !BondType.is(include, f) || BondType.is(exclude, f);
}
export function makeIntraBondIgnoreTest(structure, unit, props) {
var elements = unit.elements;
var atomicNumber = unit.model.atomicHierarchy.derived.atom.atomicNumber;
var bonds = unit.bonds;
var a = bonds.a, b = bonds.b, edgeProps = bonds.edgeProps;
var _flags = edgeProps.flags;
var ignoreHydrogens = props.ignoreHydrogens, includeTypes = props.includeTypes, excludeTypes = props.excludeTypes;
var include = BondType.fromNames(includeTypes);
var exclude = BondType.fromNames(excludeTypes);
var allBondTypes = BondType.isAll(include) && 0 /* BondType.Flag.None */ === exclude;
var child = structure.child;
var childUnit = child === null || child === void 0 ? void 0 : child.unitMap.get(unit.id);
if (child && !childUnit)
throw new Error('expected childUnit to exist if child exists');
if (allBondTypes && !ignoreHydrogens && !child)
return;
return function (edgeIndex) {
return ((!!childUnit && !SortedArray.has(childUnit.elements, elements[a[edgeIndex]])) ||
(ignoreHydrogens && (isH(atomicNumber, elements[a[edgeIndex]]) || isH(atomicNumber, elements[b[edgeIndex]]))) ||
(!allBondTypes && ignoreBondType(include, exclude, _flags[edgeIndex])));
};
}
export function makeInterBondIgnoreTest(structure, props) {
var bonds = structure.interUnitBonds;
var edges = bonds.edges;
var ignoreHydrogens = props.ignoreHydrogens, includeTypes = props.includeTypes, excludeTypes = props.excludeTypes;
var include = BondType.fromNames(includeTypes);
var exclude = BondType.fromNames(excludeTypes);
var allBondTypes = BondType.isAll(include) && 0 /* BondType.Flag.None */ === exclude;
var child = structure.child;
if (allBondTypes && !ignoreHydrogens && !child)
return;
return function (edgeIndex) {
if (child) {
var b = edges[edgeIndex];
var childUnitA = child.unitMap.get(b.unitA);
if (!childUnitA)
return true;
var unitA = structure.unitMap.get(b.unitA);
var eA = unitA.elements[b.indexA];
if (!SortedArray.has(childUnitA.elements, eA))
return true;
}
if (ignoreHydrogens) {
var b = edges[edgeIndex];
var uA = structure.unitMap.get(b.unitA);
var uB = structure.unitMap.get(b.unitB);
if (isHydrogen(uA, uA.elements[b.indexA]) || isHydrogen(uB, uB.elements[b.indexB]))
return true;
}
if (!allBondTypes) {
if (ignoreBondType(include, exclude, edges[edgeIndex].props.flag))
return true;
}
return false;
};
}
export var BondIterator;
(function (BondIterator) {
function fromGroup(structureGroup) {
var group = structureGroup.group, structure = structureGroup.structure;
var unit = group.units[0];
var groupCount = Unit.isAtomic(unit) ? unit.bonds.edgeCount * 2 : 0;
var instanceCount = group.units.length;
var location = Bond.Location(structure, undefined, undefined, structure, undefined, undefined);
var getLocation = function (groupIndex, instanceIndex) {
var unit = group.units[instanceIndex];
location.aUnit = unit;
location.bUnit = unit;
location.aIndex = unit.bonds.a[groupIndex];
location.bIndex = unit.bonds.b[groupIndex];
return location;
};
return LocationIterator(groupCount, instanceCount, 1, getLocation);
}
BondIterator.fromGroup = fromGroup;
function fromStructure(structure) {
var groupCount = structure.interUnitBonds.edgeCount;
var instanceCount = 1;
var location = Bond.Location(structure, undefined, undefined, structure, undefined, undefined);
var getLocation = function (groupIndex) {
var bond = structure.interUnitBonds.edges[groupIndex];
location.aUnit = structure.unitMap.get(bond.unitA);
location.aIndex = bond.indexA;
location.bUnit = structure.unitMap.get(bond.unitB);
location.bIndex = bond.indexB;
return location;
};
return LocationIterator(groupCount, instanceCount, 1, getLocation, true);
}
BondIterator.fromStructure = fromStructure;
})(BondIterator || (BondIterator = {}));
//
export function getIntraBondLoci(pickingId, structureGroup, id) {
var objectId = pickingId.objectId, instanceId = pickingId.instanceId, groupId = pickingId.groupId;
if (id === objectId) {
var structure = structureGroup.structure, group = structureGroup.group;
var unit = group.units[instanceId];
if (Unit.isAtomic(unit)) {
var target = structure.target;
var iA = unit.bonds.a[groupId];
var iB = unit.bonds.b[groupId];
return Bond.Loci(target, [
Bond.Location(target, unit, iA, target, unit, iB),
Bond.Location(target, unit, iB, target, unit, iA)
]);
}
}
return EmptyLoci;
}
export function eachIntraBond(loci, structureGroup, apply, isMarking) {
var changed = false;
if (Bond.isLoci(loci)) {
var structure = structureGroup.structure, group = structureGroup.group;
if (!Structure.areEquivalent(loci.structure, structure))
return false;
var unit = group.units[0];
if (!Unit.isAtomic(unit))
return false;
var groupCount = unit.bonds.edgeCount * 2;
for (var _i = 0, _a = loci.bonds; _i < _a.length; _i++) {
var b = _a[_i];
if (b.aUnit !== b.bUnit)
continue;
var unitIdx = group.unitIndexMap.get(b.aUnit.id);
if (unitIdx !== undefined) {
var idx = unit.bonds.getDirectedEdgeIndex(b.aIndex, b.bIndex);
if (idx !== -1) {
if (apply(Interval.ofSingleton(unitIdx * groupCount + idx)))
changed = true;
}
}
}
}
else if (StructureElement.Loci.is(loci)) {
var structure = structureGroup.structure, group = structureGroup.group;
if (!Structure.areEquivalent(loci.structure, structure))
return false;
var unit = group.units[0];
if (!Unit.isAtomic(unit))
return false;
var groupCount_1 = unit.bonds.edgeCount * 2;
var _loop_1 = function (e) {
var unitIdx = group.unitIndexMap.get(e.unit.id);
if (unitIdx !== undefined) {
var _d = unit.bonds, offset_1 = _d.offset, b_1 = _d.b;
OrderedSet.forEach(e.indices, function (v) {
for (var t = offset_1[v], _t = offset_1[v + 1]; t < _t; t++) {
if (!isMarking || OrderedSet.has(e.indices, b_1[t])) {
if (apply(Interval.ofSingleton(unitIdx * groupCount_1 + t)))
changed = true;
}
}
});
}
};
for (var _b = 0, _c = loci.elements; _b < _c.length; _b++) {
var e = _c[_b];
_loop_1(e);
}
}
return changed;
}
//
export function getInterBondLoci(pickingId, structure, id) {
var objectId = pickingId.objectId, groupId = pickingId.groupId;
if (id === objectId) {
var target = structure.target;
var b = structure.interUnitBonds.edges[groupId];
var uA = structure.unitMap.get(b.unitA);
var uB = structure.unitMap.get(b.unitB);
return Bond.Loci(target, [
Bond.Location(target, uA, b.indexA, target, uB, b.indexB),
Bond.Location(target, uB, b.indexB, target, uA, b.indexA)
]);
}
return EmptyLoci;
}
var __unitMap = new Map();
export function eachInterBond(loci, structure, apply, isMarking) {
var changed = false;
if (Bond.isLoci(loci)) {
if (!Structure.areEquivalent(loci.structure, structure))
return false;
for (var _i = 0, _a = loci.bonds; _i < _a.length; _i++) {
var b = _a[_i];
var idx = structure.interUnitBonds.getBondIndexFromLocation(b);
if (idx !== -1) {
if (apply(Interval.ofSingleton(idx)))
changed = true;
}
}
}
else if (StructureElement.Loci.is(loci)) {
if (!Structure.areEquivalent(loci.structure, structure))
return false;
if (isMarking && loci.elements.length === 1)
return false; // only a single unit
for (var _b = 0, _c = loci.elements; _b < _c.length; _b++) {
var e = _c[_b];
__unitMap.set(e.unit.id, e.indices);
}
var _loop_2 = function (e) {
var unit = e.unit;
if (!Unit.isAtomic(unit))
return "continue";
structure.interUnitBonds.getConnectedUnits(unit.id).forEach(function (b) {
var otherLociIndices = __unitMap.get(b.unitB);
if (!isMarking || otherLociIndices) {
OrderedSet.forEach(e.indices, function (v) {
if (!b.connectedIndices.includes(v))
return;
b.getEdges(v).forEach(function (bi) {
if (!isMarking || (otherLociIndices && OrderedSet.has(otherLociIndices, bi.indexB))) {
var idx = structure.interUnitBonds.getEdgeIndex(v, unit.id, bi.indexB, b.unitB);
if (apply(Interval.ofSingleton(idx)))
changed = true;
}
});
});
}
});
};
for (var _d = 0, _e = loci.elements; _d < _e.length; _d++) {
var e = _e[_d];
_loop_2(e);
}
__unitMap.clear();
}
return changed;
}