molstar
Version:
A comprehensive macromolecular library.
233 lines (232 loc) • 11.6 kB
JavaScript
/**
* Copyright (c) 2021 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 { DefaultQueryRuntimeTable } from '../../../mol-script/runtime/query/compiler';
import { PLDDTConfidenceColorThemeProvider } from './color/plddt';
import { QualityAssessment, QualityAssessmentProvider } from './prop';
import { StructureSelectionCategory, StructureSelectionQuery } from '../../../mol-plugin-state/helpers/structure-selection-query';
import { MolScriptBuilder as MS } from '../../../mol-script/language/builder';
import { OrderedSet } from '../../../mol-data/int';
import { cantorPairing } from '../../../mol-data/util';
import { QmeanScoreColorThemeProvider } from './color/qmean';
import { PresetStructureRepresentations, StructureRepresentationPresetProvider } from '../../../mol-plugin-state/builder/structure/representation-preset';
import { StateObjectRef } from '../../../mol-state';
export var MAQualityAssessment = PluginBehavior.create({
name: 'ma-quality-assessment-prop',
category: 'custom-props',
display: {
name: 'Quality Assessment',
description: 'Data included in Model Archive files.'
},
ctor: /** @class */ (function (_super) {
__extends(class_1, _super);
function class_1() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.provider = QualityAssessmentProvider;
_this.labelProvider = {
label: function (loci) {
if (!_this.params.showTooltip)
return;
return [
plddtLabel(loci),
qmeanLabel(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(PLDDTConfidenceColorThemeProvider);
this.ctx.representation.structure.themes.colorThemeRegistry.add(QmeanScoreColorThemeProvider);
this.ctx.query.structure.registry.add(confidentPLDDT);
this.ctx.builders.structure.representation.registerPreset(QualityAssessmentPLDDTPreset);
this.ctx.builders.structure.representation.registerPreset(QualityAssessmentQmeanPreset);
};
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(PLDDTConfidenceColorThemeProvider);
this.ctx.representation.structure.themes.colorThemeRegistry.remove(QmeanScoreColorThemeProvider);
this.ctx.query.structure.registry.remove(confidentPLDDT);
this.ctx.builders.structure.representation.unregisterPreset(QualityAssessmentPLDDTPreset);
this.ctx.builders.structure.representation.unregisterPreset(QualityAssessmentQmeanPreset);
};
return class_1;
}(PluginBehavior.Handler)),
params: function () { return ({
autoAttach: PD.Boolean(false),
showTooltip: PD.Boolean(true),
}); }
});
//
function plddtCategory(score) {
if (score > 50 && score <= 70)
return 'Low';
if (score > 70 && score <= 90)
return 'Confident';
if (score > 90)
return 'Very high';
return 'Very low';
}
function plddtLabel(loci) {
return metricLabel(loci, 'pLDDT', function (scoreAvg, countInfo) { return "pLDDT Score ".concat(countInfo, ": ").concat(scoreAvg.toFixed(2), " <small>(").concat(plddtCategory(scoreAvg), ")</small>"); });
}
function qmeanLabel(loci) {
return metricLabel(loci, 'qmean', function (scoreAvg, countInfo) { return "QMEAN Score ".concat(countInfo, ": ").concat(scoreAvg.toFixed(2)); });
}
function metricLabel(loci, name, label) {
var _a;
if (loci.kind === 'element-loci') {
if (loci.elements.length === 0)
return;
var seen_1 = new Set();
var scoreSeen_1 = new Set();
var scoreSum_1 = 0;
var _loop_1 = function (indices, unit) {
var metric = (_a = QualityAssessmentProvider.get(unit.model).value) === null || _a === void 0 ? void 0 : _a[name];
if (!metric)
return "continue";
var residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index;
var elements = unit.elements;
OrderedSet.forEach(indices, function (idx) {
var _a;
var eI = elements[idx];
var rI = residueIndex[eI];
var residueKey = cantorPairing(rI, unit.id);
if (!seen_1.has(residueKey)) {
var score = (_a = metric.get(residueIndex[eI])) !== null && _a !== void 0 ? _a : -1;
if (score !== -1) {
scoreSum_1 += score;
scoreSeen_1.add(residueKey);
}
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 (seen_1.size === 0)
return;
var summary = [];
if (scoreSeen_1.size) {
var countInfo = "<small>(".concat(scoreSeen_1.size, " ").concat(scoreSeen_1.size > 1 ? 'Residues avg.' : 'Residue', ")</small>");
var scoreAvg = scoreSum_1 / scoreSeen_1.size;
summary.push(label(scoreAvg, countInfo));
}
if (summary.length) {
return summary.join('</br>');
}
}
}
//
var confidentPLDDT = StructureSelectionQuery('Confident pLDDT (> 70)', 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']),
'residue-test': MS.core.rel.gr([QualityAssessment.symbols.pLDDT.symbol(), 70]),
})
])
])
]), {
description: 'Select residues with a pLDDT > 70 (confident).',
category: StructureSelectionCategory.Validation,
ensureCustomProperties: function (ctx, structure) { return __awaiter(void 0, void 0, void 0, function () {
var _i, _a, m;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_i = 0, _a = structure.models;
_b.label = 1;
case 1:
if (!(_i < _a.length)) return [3 /*break*/, 4];
m = _a[_i];
return [4 /*yield*/, QualityAssessmentProvider.attach(ctx, m, void 0, true)];
case 2:
_b.sent();
_b.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/];
}
});
}); }
});
//
export var QualityAssessmentPLDDTPreset = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-ma-quality-assessment-plddt',
display: {
name: 'Quality Assessment (pLDDT)', group: 'Annotation',
description: 'Color structure based on pLDDT Confidence.'
},
isApplicable: function (a) {
return !!a.data.models.some(function (m) { return QualityAssessment.isApplicable(m, 'pLDDT'); });
},
params: function () { return StructureRepresentationPresetProvider.CommonParams; },
apply: function (ref, params, plugin) {
var _a;
return __awaiter(this, void 0, void 0, function () {
var structureCell, structure, colorTheme;
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*/, {}];
colorTheme = PLDDTConfidenceColorThemeProvider.name;
return [4 /*yield*/, PresetStructureRepresentations.auto.apply(ref, __assign(__assign({}, params), { theme: { globalName: colorTheme, focus: { name: colorTheme } } }), plugin)];
case 1: return [2 /*return*/, _b.sent()];
}
});
});
}
});
export var QualityAssessmentQmeanPreset = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-ma-quality-assessment-qmean',
display: {
name: 'Quality Assessment (QMEAN)', group: 'Annotation',
description: 'Color structure based on QMEAN Score.'
},
isApplicable: function (a) {
return !!a.data.models.some(function (m) { return QualityAssessment.isApplicable(m, 'qmean'); });
},
params: function () { return StructureRepresentationPresetProvider.CommonParams; },
apply: function (ref, params, plugin) {
var _a;
return __awaiter(this, void 0, void 0, function () {
var structureCell, structure, colorTheme;
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*/, {}];
colorTheme = QmeanScoreColorThemeProvider.name;
return [4 /*yield*/, PresetStructureRepresentations.auto.apply(ref, __assign(__assign({}, params), { theme: { globalName: colorTheme, focus: { name: colorTheme } } }), plugin)];
case 1: return [2 /*return*/, _b.sent()];
}
});
});
}
});