molstar
Version:
A comprehensive macromolecular library.
133 lines (132 loc) • 7.31 kB
JavaScript
/**
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { __assign } from "tslib";
import { ParamDefinition as PD } from '../../../mol-util/param-definition';
import { StructureElement, StructureProperties } from '../../../mol-model/structure';
import { TextBuilder } from '../../../mol-geo/geometry/text/text-builder';
import { ComplexTextVisual, ComplexTextParams } from '../complex-visual';
import { ElementIterator, getSerialElementLoci, eachSerialElement } from './util/element';
import { ColorNames } from '../../../mol-util/color/names';
import { Vec3 } from '../../../mol-math/linear-algebra';
import { BoundaryHelper } from '../../../mol-math/geometry/boundary-helper';
export var LabelTextParams = __assign(__assign({}, ComplexTextParams), { background: PD.Boolean(false), backgroundMargin: PD.Numeric(0, { min: 0, max: 1, step: 0.01 }), backgroundColor: PD.Color(ColorNames.black), backgroundOpacity: PD.Numeric(0.5, { min: 0, max: 1, step: 0.01 }), borderWidth: PD.Numeric(0.25, { min: 0, max: 0.5, step: 0.01 }), level: PD.Select('residue', [['chain', 'Chain'], ['residue', 'Residue'], ['element', 'Element']], { isEssential: true }), chainScale: PD.Numeric(10, { min: 0, max: 20, step: 0.1 }), residueScale: PD.Numeric(1, { min: 0, max: 20, step: 0.1 }), elementScale: PD.Numeric(0.5, { min: 0, max: 20, step: 0.1 }) });
export function LabelTextVisual(materialId) {
return ComplexTextVisual({
defaultProps: PD.getDefaultValues(LabelTextParams),
createGeometry: createLabelText,
createLocationIterator: ElementIterator.fromStructure,
getLoci: getSerialElementLoci,
eachLocation: eachSerialElement,
setUpdateState: function (state, newProps, currentProps) {
state.createGeometry = (newProps.level !== currentProps.level ||
(newProps.level === 'chain' && newProps.chainScale !== currentProps.chainScale) ||
(newProps.level === 'residue' && newProps.residueScale !== currentProps.residueScale) ||
(newProps.level === 'element' && newProps.elementScale !== currentProps.elementScale));
}
}, materialId);
}
function createLabelText(ctx, structure, theme, props, text) {
switch (props.level) {
case 'chain': return createChainText(ctx, structure, theme, props, text);
case 'residue': return createResidueText(ctx, structure, theme, props, text);
case 'element': return createElementText(ctx, structure, theme, props, text);
}
}
//
var tmpVec = Vec3();
var boundaryHelper = new BoundaryHelper('98');
function createChainText(ctx, structure, theme, props, text) {
var l = StructureElement.Location.create(structure);
var units = structure.units, serialMapping = structure.serialMapping;
var _a = StructureProperties.chain, auth_asym_id = _a.auth_asym_id, label_asym_id = _a.label_asym_id;
var cumulativeUnitElementCount = serialMapping.cumulativeUnitElementCount;
var count = units.length;
var chainScale = props.chainScale;
var builder = TextBuilder.create(props, count, count / 2, text);
for (var i = 0, il = units.length; i < il; ++i) {
var unit = units[i];
l.unit = unit;
l.element = unit.elements[0];
var _b = unit.lookup3d.boundary.sphere, center = _b.center, radius = _b.radius;
Vec3.transformMat4(tmpVec, center, unit.conformation.operator.matrix);
var authId = auth_asym_id(l);
var labelId = label_asym_id(l);
var text_1 = authId === labelId ? labelId : "".concat(labelId, " [").concat(authId, "]");
builder.add(text_1, tmpVec[0], tmpVec[1], tmpVec[2], radius, chainScale, cumulativeUnitElementCount[i]);
}
return builder.getText();
}
function createResidueText(ctx, structure, theme, props, text) {
var l = StructureElement.Location.create(structure);
var units = structure.units, serialMapping = structure.serialMapping;
var label_comp_id = StructureProperties.atom.label_comp_id;
var auth_seq_id = StructureProperties.residue.auth_seq_id;
var cumulativeUnitElementCount = serialMapping.cumulativeUnitElementCount;
var count = structure.polymerResidueCount * 2;
var residueScale = props.residueScale;
var builder = TextBuilder.create(props, count, count / 2, text);
for (var i = 0, il = units.length; i < il; ++i) {
var unit = units[i];
var pos = unit.conformation.position;
var elements = unit.elements;
l.unit = unit;
l.element = unit.elements[0];
var residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index;
var groupOffset = cumulativeUnitElementCount[i];
var j = 0;
var jl = elements.length;
while (j < jl) {
var start = j, rI = residueIndex[elements[j]];
j++;
while (j < jl && residueIndex[elements[j]] === rI)
j++;
boundaryHelper.reset();
for (var eI = start; eI < j; eI++) {
pos(elements[eI], tmpVec);
boundaryHelper.includePosition(tmpVec);
}
boundaryHelper.finishedIncludeStep();
for (var eI = start; eI < j; eI++) {
pos(elements[eI], tmpVec);
boundaryHelper.radiusPosition(tmpVec);
}
l.element = elements[start];
var _a = boundaryHelper.getSphere(), center = _a.center, radius = _a.radius;
var authSeqId = auth_seq_id(l);
var compId = label_comp_id(l);
var text_2 = "".concat(compId, " ").concat(authSeqId);
builder.add(text_2, center[0], center[1], center[2], radius, residueScale, groupOffset + start);
}
}
return builder.getText();
}
function createElementText(ctx, structure, theme, props, text) {
var l = StructureElement.Location.create(structure);
var units = structure.units, serialMapping = structure.serialMapping;
var _a = StructureProperties.atom, label_atom_id = _a.label_atom_id, label_alt_id = _a.label_alt_id;
var cumulativeUnitElementCount = serialMapping.cumulativeUnitElementCount;
var sizeTheme = theme.size;
var count = structure.elementCount;
var elementScale = props.elementScale;
var builder = TextBuilder.create(props, count, count / 2, text);
for (var i = 0, il = units.length; i < il; ++i) {
var unit = units[i];
var pos = unit.conformation.position;
var elements = unit.elements;
l.unit = unit;
var groupOffset = cumulativeUnitElementCount[i];
for (var j = 0, _j = elements.length; j < _j; j++) {
l.element = elements[j];
pos(l.element, tmpVec);
var atomId = label_atom_id(l);
var altId = label_alt_id(l);
var text_3 = altId ? "".concat(atomId, "%").concat(altId) : atomId;
builder.add(text_3, tmpVec[0], tmpVec[1], tmpVec[2], sizeTheme.size(l), elementScale, groupOffset + j);
}
}
return builder.getText();
}