UNPKG

molstar

Version:

A comprehensive macromolecular library.

418 lines 23.6 kB
/** * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { __assign, __awaiter, __extends, __generator } from "tslib"; import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { PluginBehavior } from '../../../mol-plugin/behavior/behavior'; import { ValidationReport, ValidationReportProvider } from './prop'; import { RandomCoilIndexColorThemeProvider } from './color/random-coil-index'; import { GeometryQualityColorThemeProvider } from './color/geometry-quality'; import { OrderedSet } from '../../../mol-data/int'; import { ClashesRepresentationProvider } from './representation'; import { DensityFitColorThemeProvider } from './color/density-fit'; import { cantorPairing } from '../../../mol-data/util'; import { DefaultQueryRuntimeTable } from '../../../mol-script/runtime/query/compiler'; import { StructureSelectionQuery, StructureSelectionCategory } from '../../../mol-plugin-state/helpers/structure-selection-query'; import { MolScriptBuilder as MS } from '../../../mol-script/language/builder'; import { Task } from '../../../mol-task'; import { StructureRepresentationPresetProvider, PresetStructureRepresentations } from '../../../mol-plugin-state/builder/structure/representation-preset'; import { StateObjectRef } from '../../../mol-state'; import { Model } from '../../../mol-model/structure'; export var RCSBValidationReport = PluginBehavior.create({ name: 'rcsb-validation-report-prop', category: 'custom-props', display: { name: 'Validation Report', description: 'Data from wwPDB Validation Report, obtained via RCSB PDB.' }, ctor: /** @class */ (function (_super) { __extends(class_1, _super); function class_1() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.provider = ValidationReportProvider; _this.labelProvider = { label: function (loci) { if (!_this.params.showTooltip) return; return [ geometryQualityLabel(loci), densityFitLabel(loci), randomCoilIndexLabel(loci) ].filter(function (l) { return !!l; }).join('</br>'); } }; return _this; } class_1.prototype.register = function () { DefaultQueryRuntimeTable.addCustomProp(this.provider.descriptor); this.ctx.customModelProperties.register(this.provider, this.params.autoAttach); this.ctx.managers.lociLabels.addProvider(this.labelProvider); this.ctx.representation.structure.themes.colorThemeRegistry.add(DensityFitColorThemeProvider); this.ctx.representation.structure.themes.colorThemeRegistry.add(GeometryQualityColorThemeProvider); this.ctx.representation.structure.themes.colorThemeRegistry.add(RandomCoilIndexColorThemeProvider); this.ctx.representation.structure.registry.add(ClashesRepresentationProvider); this.ctx.query.structure.registry.add(hasClash); this.ctx.builders.structure.representation.registerPreset(ValidationReportGeometryQualityPreset); this.ctx.builders.structure.representation.registerPreset(ValidationReportDensityFitPreset); this.ctx.builders.structure.representation.registerPreset(ValidationReportRandomCoilIndexPreset); }; class_1.prototype.update = function (p) { var updated = this.params.autoAttach !== p.autoAttach; this.params.autoAttach = p.autoAttach; this.params.showTooltip = p.showTooltip; this.ctx.customStructureProperties.setDefaultAutoAttach(this.provider.descriptor.name, this.params.autoAttach); return updated; }; class_1.prototype.unregister = function () { DefaultQueryRuntimeTable.removeCustomProp(this.provider.descriptor); this.ctx.customStructureProperties.unregister(this.provider.descriptor.name); this.ctx.managers.lociLabels.removeProvider(this.labelProvider); this.ctx.representation.structure.themes.colorThemeRegistry.remove(DensityFitColorThemeProvider); this.ctx.representation.structure.themes.colorThemeRegistry.remove(GeometryQualityColorThemeProvider); this.ctx.representation.structure.themes.colorThemeRegistry.remove(RandomCoilIndexColorThemeProvider); this.ctx.representation.structure.registry.remove(ClashesRepresentationProvider); this.ctx.query.structure.registry.remove(hasClash); this.ctx.builders.structure.representation.unregisterPreset(ValidationReportGeometryQualityPreset); this.ctx.builders.structure.representation.unregisterPreset(ValidationReportDensityFitPreset); this.ctx.builders.structure.representation.unregisterPreset(ValidationReportRandomCoilIndexPreset); }; return class_1; }(PluginBehavior.Handler)), params: function () { return ({ autoAttach: PD.Boolean(false), showTooltip: PD.Boolean(true), baseUrl: PD.Text(ValidationReport.DefaultBaseUrl) }); } }); // function geometryQualityLabel(loci) { if (loci.kind === 'element-loci') { if (loci.elements.length === 0) return; if (loci.elements.length === 1 && OrderedSet.size(loci.elements[0].indices) === 1) { var _a = loci.elements[0], unit = _a.unit, indices = _a.indices; var validationReport = ValidationReportProvider.get(unit.model).value; if (!validationReport) return; if (!unit.model.customProperties.hasReference(ValidationReportProvider.descriptor)) return; var bondOutliers_1 = validationReport.bondOutliers, angleOutliers_1 = validationReport.angleOutliers; var eI = unit.elements[OrderedSet.start(indices)]; var issues_1 = new Set(); var bonds = bondOutliers_1.index.get(eI); if (bonds) bonds.forEach(function (b) { return issues_1.add(bondOutliers_1.data[b].tag); }); var angles = angleOutliers_1.index.get(eI); if (angles) angles.forEach(function (a) { return issues_1.add(angleOutliers_1.data[a].tag); }); if (issues_1.size === 0) { return "Geometry Quality <small>(1 Atom)</small>: no issues"; } var summary_1 = []; issues_1.forEach(function (name) { return summary_1.push(name); }); return "Geometry Quality <small>(1 Atom)</small>: " + summary_1.join(', '); } var hasValidationReport = false; var seen_1 = new Set(); var cummulativeIssues_1 = new Map(); var _loop_1 = function (indices, unit) { var validationReport = ValidationReportProvider.get(unit.model).value; if (!validationReport) return "continue"; if (!unit.model.customProperties.hasReference(ValidationReportProvider.descriptor)) return "continue"; hasValidationReport = true; var geometryIssues = validationReport.geometryIssues; var residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index; var elements = unit.elements; OrderedSet.forEach(indices, function (idx) { var eI = elements[idx]; var rI = residueIndex[eI]; var residueKey = cantorPairing(rI, unit.id); if (!seen_1.has(residueKey)) { var issues = geometryIssues.get(rI); if (issues) { issues.forEach(function (name) { var count = cummulativeIssues_1.get(name) || 0; cummulativeIssues_1.set(name, count + 1); }); } seen_1.add(residueKey); } }); }; for (var _i = 0, _b = loci.elements; _i < _b.length; _i++) { var _c = _b[_i], indices = _c.indices, unit = _c.unit; _loop_1(indices, unit); } if (!hasValidationReport) return; var residueCount = "<small>(" + seen_1.size + " " + (seen_1.size > 1 ? 'Residues' : 'Residue') + ")</small>"; if (cummulativeIssues_1.size === 0) { return "Geometry Quality " + residueCount + ": no issues"; } var summary_2 = []; cummulativeIssues_1.forEach(function (count, name) { summary_2.push("" + name + (count > 1 ? " \u00D7 " + count : '')); }); return "Geometry Quality " + residueCount + ": " + summary_2.join(', '); } } function densityFitLabel(loci) { if (loci.kind === 'element-loci') { if (loci.elements.length === 0) return; var seen_2 = new Set(); var rsrzSeen_1 = new Set(); var rsccSeen_1 = new Set(); var rsrzSum_1 = 0; var rsccSum_1 = 0; var _loop_2 = function (indices, unit) { var validationReport = ValidationReportProvider.get(unit.model).value; if (!validationReport) return "continue"; if (!unit.model.customProperties.hasReference(ValidationReportProvider.descriptor)) return "continue"; var rsrz = validationReport.rsrz, rscc = validationReport.rscc; var residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index; var elements = unit.elements; OrderedSet.forEach(indices, function (idx) { var eI = elements[idx]; var rI = residueIndex[eI]; var residueKey = cantorPairing(rI, unit.id); if (!seen_2.has(residueKey)) { var rsrzValue = rsrz.get(rI); var rsccValue = rscc.get(rI); if (rsrzValue !== undefined) { rsrzSum_1 += rsrzValue; rsrzSeen_1.add(residueKey); } else if (rsccValue !== undefined) { rsccSum_1 += rsccValue; rsccSeen_1.add(residueKey); } seen_2.add(residueKey); } }); }; for (var _i = 0, _a = loci.elements; _i < _a.length; _i++) { var _b = _a[_i], indices = _b.indices, unit = _b.unit; _loop_2(indices, unit); } if (seen_2.size === 0) return; var summary = []; if (rsrzSeen_1.size) { var rsrzCount = "<small>(" + rsrzSeen_1.size + " " + (rsrzSeen_1.size > 1 ? 'Residues avg.' : 'Residue') + ")</small>"; var rsrzAvg = rsrzSum_1 / rsrzSeen_1.size; summary.push("Real-Space R Z-score " + rsrzCount + ": " + rsrzAvg.toFixed(2)); } if (rsccSeen_1.size) { var rsccCount = "<small>(" + rsccSeen_1.size + " " + (rsccSeen_1.size > 1 ? 'Residues avg.' : 'Residue') + ")</small>"; var rsccAvg = rsccSum_1 / rsccSeen_1.size; summary.push("Real-Space Correlation Coefficient " + rsccCount + ": " + rsccAvg.toFixed(2)); } if (summary.length) { return summary.join('</br>'); } } } function randomCoilIndexLabel(loci) { if (loci.kind === 'element-loci') { if (loci.elements.length === 0) return; var seen_3 = new Set(); var sum_1 = 0; var _loop_3 = function (indices, unit) { var validationReport = ValidationReportProvider.get(unit.model).value; if (!validationReport) return "continue"; if (!unit.model.customProperties.hasReference(ValidationReportProvider.descriptor)) return "continue"; var rci = validationReport.rci; var residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index; var elements = unit.elements; OrderedSet.forEach(indices, function (idx) { var eI = elements[idx]; var rI = residueIndex[eI]; var residueKey = cantorPairing(rI, unit.id); if (!seen_3.has(residueKey)) { var rciValue = rci.get(rI); if (rciValue !== undefined) { sum_1 += rciValue; seen_3.add(residueKey); } } }); }; for (var _i = 0, _a = loci.elements; _i < _a.length; _i++) { var _b = _a[_i], indices = _b.indices, unit = _b.unit; _loop_3(indices, unit); } if (seen_3.size === 0) return; var residueCount = "<small>(" + seen_3.size + " " + (seen_3.size > 1 ? 'Residues avg.' : 'Residue') + ")</small>"; var rciAvg = sum_1 / seen_3.size; return "Random Coil Index " + residueCount + ": " + rciAvg.toFixed(2); } } // var hasClash = StructureSelectionQuery('Residues with Clashes', MS.struct.modifier.union([ MS.struct.modifier.wholeResidues([ MS.struct.modifier.union([ MS.struct.generator.atomGroups({ 'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']), 'atom-test': ValidationReport.symbols.hasClash.symbol(), }) ]) ]) ]), { description: 'Select residues with clashes in the wwPDB validation report.', category: StructureSelectionCategory.Residue, ensureCustomProperties: function (ctx, structure) { return ValidationReportProvider.attach(ctx, structure.models[0]); } }); // export var ValidationReportGeometryQualityPreset = StructureRepresentationPresetProvider({ id: 'preset-structure-representation-rcsb-validation-report-geometry-uality', display: { name: 'Validation Report (Geometry Quality)', group: 'Annotation', description: 'Color structure based on geometry quality; show geometry clashes. Data from wwPDB Validation Report, obtained via RCSB PDB.' }, isApplicable: function (a) { return a.data.models.length === 1 && ValidationReport.isApplicable(a.data.models[0]); }, params: function () { return StructureRepresentationPresetProvider.CommonParams; }, apply: function (ref, params, plugin) { var _a; return __awaiter(this, void 0, void 0, function () { var structureCell, structure, colorTheme, _b, components, representations, clashes, _c, update, builder, typeParams, color, clashesBallAndStick, clashesRepr; var _this = this; return __generator(this, function (_d) { switch (_d.label) { case 0: structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref); structure = (_a = structureCell === null || structureCell === void 0 ? void 0 : structureCell.obj) === null || _a === void 0 ? void 0 : _a.data; if (!structureCell || !structure) return [2 /*return*/, {}]; return [4 /*yield*/, plugin.runTask(Task.create('Validation Report', function (runtime) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, ValidationReportProvider.attach({ runtime: runtime, assetManager: plugin.managers.asset }, structure.models[0])]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }))]; case 1: _d.sent(); colorTheme = GeometryQualityColorThemeProvider.name; return [4 /*yield*/, PresetStructureRepresentations.auto.apply(ref, __assign(__assign({}, params), { theme: { globalName: colorTheme, focus: { name: colorTheme } } }), plugin)]; case 2: _b = _d.sent(), components = _b.components, representations = _b.representations; return [4 /*yield*/, plugin.builders.structure.tryCreateComponentFromExpression(structureCell, hasClash.expression, 'clashes', { label: 'Clashes' })]; case 3: clashes = _d.sent(); _c = StructureRepresentationPresetProvider.reprBuilder(plugin, params), update = _c.update, builder = _c.builder, typeParams = _c.typeParams, color = _c.color; if (representations) { clashesBallAndStick = builder.buildRepresentation(update, clashes, { type: 'ball-and-stick', typeParams: typeParams, color: colorTheme }, { tag: 'clashes-ball-and-stick' }); clashesRepr = builder.buildRepresentation(update, clashes, { type: ClashesRepresentationProvider.name, typeParams: typeParams, color: color }, { tag: 'clashes-repr' }); } return [4 /*yield*/, update.commit({ revertOnError: true })]; case 4: _d.sent(); return [2 /*return*/, { components: __assign(__assign({}, components), { clashes: clashes }), representations: __assign(__assign({}, representations), { clashesBallAndStick: clashesBallAndStick, clashesRepr: clashesRepr }) }]; } }); }); } }); export var ValidationReportDensityFitPreset = StructureRepresentationPresetProvider({ id: 'preset-structure-representation-rcsb-validation-report-density-fit', display: { name: 'Validation Report (Density Fit)', group: 'Annotation', description: 'Color structure based on density fit. Data from wwPDB Validation Report, obtained via RCSB PDB.' }, isApplicable: function (a) { return a.data.models.length === 1 && ValidationReport.isApplicable(a.data.models[0]) && Model.isFromXray(a.data.models[0]) && Model.probablyHasDensityMap(a.data.models[0]); }, params: function () { return StructureRepresentationPresetProvider.CommonParams; }, apply: function (ref, params, plugin) { var _a; return __awaiter(this, void 0, void 0, function () { var structureCell, structure, colorTheme; var _this = this; return __generator(this, function (_b) { switch (_b.label) { case 0: structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref); structure = (_a = structureCell === null || structureCell === void 0 ? void 0 : structureCell.obj) === null || _a === void 0 ? void 0 : _a.data; if (!structureCell || !structure) return [2 /*return*/, {}]; return [4 /*yield*/, plugin.runTask(Task.create('Validation Report', function (runtime) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, ValidationReportProvider.attach({ runtime: runtime, assetManager: plugin.managers.asset }, structure.models[0])]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }))]; case 1: _b.sent(); colorTheme = DensityFitColorThemeProvider.name; return [4 /*yield*/, PresetStructureRepresentations.auto.apply(ref, __assign(__assign({}, params), { theme: { globalName: colorTheme, focus: { name: colorTheme } } }), plugin)]; case 2: return [2 /*return*/, _b.sent()]; } }); }); } }); export var ValidationReportRandomCoilIndexPreset = StructureRepresentationPresetProvider({ id: 'preset-structure-representation-rcsb-validation-report-random-coil-index', display: { name: 'Validation Report (Random Coil Index)', group: 'Annotation', description: 'Color structure based on Random Coil Index. Data from wwPDB Validation Report, obtained via RCSB PDB.' }, isApplicable: function (a) { return a.data.models.length === 1 && ValidationReport.isApplicable(a.data.models[0]) && Model.isFromNmr(a.data.models[0]); }, params: function () { return StructureRepresentationPresetProvider.CommonParams; }, apply: function (ref, params, plugin) { var _a; return __awaiter(this, void 0, void 0, function () { var structureCell, structure, colorTheme; var _this = this; return __generator(this, function (_b) { switch (_b.label) { case 0: structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref); structure = (_a = structureCell === null || structureCell === void 0 ? void 0 : structureCell.obj) === null || _a === void 0 ? void 0 : _a.data; if (!structureCell || !structure) return [2 /*return*/, {}]; return [4 /*yield*/, plugin.runTask(Task.create('Validation Report', function (runtime) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, ValidationReportProvider.attach({ runtime: runtime, assetManager: plugin.managers.asset }, structure.models[0])]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }))]; case 1: _b.sent(); colorTheme = RandomCoilIndexColorThemeProvider.name; return [4 /*yield*/, PresetStructureRepresentations.auto.apply(ref, __assign(__assign({}, params), { theme: { globalName: colorTheme, focus: { name: colorTheme } } }), plugin)]; case 2: return [2 /*return*/, _b.sent()]; } }); }); } }); //# sourceMappingURL=behavior.js.map