molstar
Version:
A comprehensive macromolecular library.
181 lines (180 loc) • 9.22 kB
JavaScript
"use strict";
/**
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Michal Malý <michal.maly@ibt.cas.cz>
* @author Jiří Černý <jiri.cerny@ibt.cas.cz>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfalPyramidsRepresentationProvider = exports.ConfalPyramidsParams = void 0;
exports.getConfalPyramidsParams = getConfalPyramidsParams;
exports.ConfalPyramidsRepresentation = ConfalPyramidsRepresentation;
const property_1 = require("./property");
const util_1 = require("./util");
const types_1 = require("./types");
const property_2 = require("../property");
const mesh_1 = require("../../../mol-geo/geometry/mesh/mesh");
const mesh_builder_1 = require("../../../mol-geo/geometry/mesh/mesh-builder");
const primitive_1 = require("../../../mol-geo/primitive/primitive");
const location_iterator_1 = require("../../../mol-geo/util/location-iterator");
const linear_algebra_1 = require("../../../mol-math/linear-algebra");
const loci_1 = require("../../../mol-model/loci");
const structure_1 = require("../../../mol-model/structure");
const representation_1 = require("../../../mol-repr/representation");
const representation_2 = require("../../../mol-repr/structure/representation");
const units_visual_1 = require("../../../mol-repr/structure/units-visual");
const param_definition_1 = require("../../../mol-util/param-definition");
const location_1 = require("../../../mol-model/location");
const t = linear_algebra_1.Mat4.identity();
const w = linear_algebra_1.Vec3.zero();
const mp = linear_algebra_1.Vec3.zero();
const posO3 = (0, linear_algebra_1.Vec3)();
const posP = (0, linear_algebra_1.Vec3)();
const posOP1 = (0, linear_algebra_1.Vec3)();
const posOP2 = (0, linear_algebra_1.Vec3)();
const posO5 = (0, linear_algebra_1.Vec3)();
function calcMidpoint(mp, v, w) {
linear_algebra_1.Vec3.sub(mp, v, w);
linear_algebra_1.Vec3.scale(mp, mp, 0.5);
linear_algebra_1.Vec3.add(mp, mp, w);
}
function shiftVertex(vec, ref, scale) {
linear_algebra_1.Vec3.sub(w, vec, ref);
linear_algebra_1.Vec3.scale(w, w, scale);
linear_algebra_1.Vec3.add(vec, vec, w);
}
const ConfalPyramidsMeshParams = {
...units_visual_1.UnitsMeshParams
};
function createConfalPyramidsIterator(structureGroup) {
var _a, _b;
const { structure, group } = structureGroup;
const instanceCount = group.units.length;
const data = (_b = (_a = property_1.ConfalPyramidsProvider.get(structure.model)) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.data;
if (!data)
return (0, location_iterator_1.LocationIterator)(0, 1, 1, () => location_1.NullLocation);
const halfPyramidsCount = data.steps.length * 2;
const getLocation = (groupIndex, instanceIndex) => {
if (halfPyramidsCount <= groupIndex)
return location_1.NullLocation;
const idx = Math.floor(groupIndex / 2); // Map groupIndex to a step, see createConfalPyramidsMesh() for full explanation
return types_1.ConfalPyramidsTypes.Location(data.steps[idx], groupIndex % 2 === 1);
};
return (0, location_iterator_1.LocationIterator)(halfPyramidsCount, instanceCount, 1, getLocation);
}
function createConfalPyramidsMesh(ctx, unit, structure, theme, props, mesh) {
var _a, _b;
if (!structure_1.Unit.isAtomic(unit))
return mesh_1.Mesh.createEmpty(mesh);
const data = (_b = (_a = property_1.ConfalPyramidsProvider.get(structure.model)) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.data;
if (!data)
return mesh_1.Mesh.createEmpty(mesh);
const { steps, mapping } = data;
if (steps.length === 0)
return mesh_1.Mesh.createEmpty(mesh);
const vertexCount = (6 * steps.length) / mapping.length;
const mb = mesh_builder_1.MeshBuilder.createState(vertexCount, vertexCount / 10, mesh);
const it = new util_1.ConfalPyramidsIterator(structure, unit);
while (it.hasNext) {
const allPoints = it.move();
if (!allPoints)
continue;
for (const points of allPoints) {
const { O3, P, OP1, OP2, O5, confalScore } = points;
const scale = (confalScore - 20.0) / 100.0;
// Steps can be drawn in a different order than they are stored.
// To make sure that we can get from the drawn pyramid back to the step in represents,
// we need to use an appropriate groupId. The stepIdx passed from the iterator
// is an index into the array of all steps in the structure.
// Since a step is drawn as two "half-pyramids" we need two ids to map to a single step.
// To do that, we just multiply the index by 2. idx*2 marks the "upper" half-pyramid,
// (idx*2)+1 the "lower" half-pyramid.
const groupIdx = points.stepIdx * 2;
unit.conformation.invariantPosition(O3, posO3);
unit.conformation.invariantPosition(P, posP);
unit.conformation.invariantPosition(OP1, posOP1);
unit.conformation.invariantPosition(OP2, posOP2);
unit.conformation.invariantPosition(O5, posO5);
shiftVertex(posO3, posP, scale);
shiftVertex(posOP1, posP, scale);
shiftVertex(posOP2, posP, scale);
shiftVertex(posO5, posP, scale);
calcMidpoint(mp, posO3, posO5);
mb.currentGroup = groupIdx;
let pb = (0, primitive_1.PrimitiveBuilder)(3);
/* Upper part (for first residue in step) */
pb.add(posO3, posOP1, posOP2);
pb.add(posO3, mp, posOP1);
pb.add(posO3, posOP2, mp);
mesh_builder_1.MeshBuilder.addPrimitive(mb, t, pb.getPrimitive());
/* Lower part (for second residue in step) */
mb.currentGroup = groupIdx + 1;
pb = (0, primitive_1.PrimitiveBuilder)(3);
pb.add(mp, posO5, posOP1);
pb.add(mp, posOP2, posO5);
pb.add(posO5, posOP2, posOP1);
mesh_builder_1.MeshBuilder.addPrimitive(mb, t, pb.getPrimitive());
}
}
return mesh_builder_1.MeshBuilder.getMesh(mb);
}
function getConfalPyramidLoci(pickingId, structureGroup, id) {
var _a, _b;
const { groupId, objectId, instanceId } = pickingId;
if (objectId !== id)
return loci_1.EmptyLoci;
const { structure } = structureGroup;
const unit = structureGroup.group.units[instanceId];
if (!structure_1.Unit.isAtomic(unit))
return loci_1.EmptyLoci;
const data = (_b = (_a = property_1.ConfalPyramidsProvider.get(structure.model)) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.data;
if (!data)
return loci_1.EmptyLoci;
const halfPyramidsCount = data.steps.length * 2;
if (halfPyramidsCount <= groupId)
return loci_1.EmptyLoci;
const idx = Math.floor(groupId / 2); // Map groupIndex to a step, see createConfalPyramidsMesh() for full explanation
return types_1.ConfalPyramidsTypes.Loci(data.steps, [idx]);
}
function eachConfalPyramid(loci, structureGroup, apply) {
return false; // TODO: Implement me
}
function ConfalPyramidsVisual(materialId) {
return (0, units_visual_1.UnitsMeshVisual)({
defaultProps: param_definition_1.ParamDefinition.getDefaultValues(ConfalPyramidsMeshParams),
createGeometry: createConfalPyramidsMesh,
createLocationIterator: createConfalPyramidsIterator,
getLoci: getConfalPyramidLoci,
eachLocation: eachConfalPyramid,
setUpdateState: (state, newProps, currentProps) => {
}
}, materialId);
}
const ConfalPyramidsVisuals = {
'confal-pyramids-symbol': (ctx, getParams) => (0, representation_2.UnitsRepresentation)('Confal Pyramids Symbol Mesh', ctx, getParams, ConfalPyramidsVisual),
};
exports.ConfalPyramidsParams = {
...units_visual_1.UnitsMeshParams
};
function getConfalPyramidsParams(ctx, structure) {
return param_definition_1.ParamDefinition.clone(exports.ConfalPyramidsParams);
}
function ConfalPyramidsRepresentation(ctx, getParams) {
const repr = representation_1.Representation.createMulti('Confal Pyramids', ctx, getParams, representation_2.StructureRepresentationStateBuilder, ConfalPyramidsVisuals);
return repr;
}
exports.ConfalPyramidsRepresentationProvider = (0, representation_2.StructureRepresentationProvider)({
name: 'confal-pyramids',
label: 'Confal Pyramids',
description: 'Displays schematic depiction of conformer classes and confal values',
factory: ConfalPyramidsRepresentation,
getParams: getConfalPyramidsParams,
defaultValues: param_definition_1.ParamDefinition.getDefaultValues(exports.ConfalPyramidsParams),
defaultColorTheme: { name: 'confal-pyramids' },
defaultSizeTheme: { name: 'uniform' },
isApplicable: (structure) => structure.models.some(m => property_2.Dnatco.isApplicable(m)),
ensureCustomProperties: {
attach: (ctx, structure) => property_1.ConfalPyramidsProvider.attach(ctx, structure.model, void 0, true),
detach: (data) => property_1.ConfalPyramidsProvider.ref(data.model, false),
}
});