pdbe-molstar
Version:
Molstar implementation for PDBe
631 lines (630 loc) • 38.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SuperpositionColorPalette = void 0;
exports.getNextColor = getNextColor;
exports.initSuperposition = initSuperposition;
exports.loadAfStructure = loadAfStructure;
exports.superposeAf = superposeAf;
exports.renderSuperposition = renderSuperposition;
exports.transform = transform;
const tslib_1 = require("tslib");
const linear_algebra_1 = require("molstar/lib/mol-math/linear-algebra");
const structure_1 = require("molstar/lib/mol-model/structure");
const transforms_1 = require("molstar/lib/mol-plugin-state/transforms");
const builder_1 = require("molstar/lib/mol-script/language/builder");
const script_1 = require("molstar/lib/mol-script/script");
const mol_state_1 = require("molstar/lib/mol-state");
const assets_1 = require("molstar/lib/mol-util/assets");
const color_1 = require("molstar/lib/mol-util/color/color");
const lists_1 = require("molstar/lib/mol-util/color/lists");
const alphafold_transparency_1 = require("./alphafold-transparency");
const helpers_1 = require("./helpers");
const plugin_custom_state_1 = require("./plugin-custom-state");
const superposition_sifts_mapping_1 = require("./superposition-sifts-mapping");
function combinedColorPalette(palettes) {
return palettes.flatMap(paletteName => lists_1.ColorLists[paletteName].list);
}
exports.SuperpositionColorPalette = combinedColorPalette(['dark-2', 'red-yellow-green', 'paired', 'set-1', 'accent', 'set-2', 'rainbow']);
const DefaultLigandColor = color_1.Color.fromRgb(253, 3, 253);
function getNextColor(plugin, segmentIndex) {
const spState = (0, plugin_custom_state_1.PluginCustomState)(plugin).superpositionState;
if (!spState)
throw new Error('customState.superpositionState has not been initialized');
const nextColor = exports.SuperpositionColorPalette[spState.colorCounters[segmentIndex]];
spState.colorCounters[segmentIndex] = (spState.colorCounters[segmentIndex] + 1) % exports.SuperpositionColorPalette.length;
return nextColor;
}
function initSuperposition(plugin, completeSubject) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a;
let success = false;
try {
yield plugin.clear();
const customState = (0, plugin_custom_state_1.PluginCustomState)(plugin);
customState.superpositionState = {
models: {},
entries: {},
refMaps: {},
segmentData: undefined,
matrixData: {},
activeSegment: 0,
loadedStructs: [],
visibleRefs: [],
invalidStruct: [],
noMatrixStruct: [],
hets: {},
colorCounters: [],
alphafold: {
apiData: {
bcif: '',
cif: '',
pae: '',
length: 0,
},
length: 0,
ref: '',
traceOnly: true,
visibility: [],
transforms: [],
rmsds: [],
coordinateSystems: [],
},
};
// Get segment and cluster information for the given uniprot accession
yield getSegmentData(plugin);
const segmentData = customState.superpositionState.segmentData;
if (!segmentData)
return;
// Load Matrix Data
yield getMatrixData(plugin);
if (!customState.superpositionState.segmentData)
return;
if (!customState.initParams.moleculeId)
throw new Error('initParams.moleculeId is not defined');
const afApiData = yield getAfUrls(plugin, customState.initParams.moleculeId);
if (afApiData)
customState.superpositionState.alphafold.apiData = afApiData;
segmentData.forEach(() => {
customState.superpositionState.loadedStructs.push([]);
customState.superpositionState.visibleRefs.push([]);
customState.superpositionState.colorCounters.push(0);
});
// Set segment and cluster details from superPositionParams
const superpositionParams = customState.initParams.superpositionParams;
const segmentIndex = (superpositionParams === null || superpositionParams === void 0 ? void 0 : superpositionParams.segment) ? superpositionParams.segment - 1 : 0;
customState.superpositionState.activeSegment = segmentIndex + 1;
const clusterIndexs = (superpositionParams === null || superpositionParams === void 0 ? void 0 : superpositionParams.cluster) ? superpositionParams.cluster : undefined;
// Emit segment API data load event
(_a = customState.events) === null || _a === void 0 ? void 0 : _a.superpositionInit.next(true);
// Get entry list to load matrix data
const entryList = [];
const clusters = segmentData[segmentIndex].clusters;
clusters.forEach((cluster, clusterIndex) => {
// Validate for cluster index if provided in superPositionParams
if (clusterIndexs && clusterIndexs.indexOf(clusterIndex) === -1)
return;
// Add respresentative structure to the list
if (superpositionParams === null || superpositionParams === void 0 ? void 0 : superpositionParams.superposeAll) {
entryList.push(...cluster);
}
else {
entryList.push(cluster[0]);
}
});
yield renderSuperposition(plugin, segmentIndex, entryList);
success = true;
}
finally {
completeSubject === null || completeSubject === void 0 ? void 0 : completeSubject.next(success);
}
});
}
function createCarbVisLabel(carbLigNamesAndCount) {
const compList = [];
for (const carbCompId in carbLigNamesAndCount) {
compList.push(`${carbCompId} (${carbLigNamesAndCount[carbCompId]})`);
}
return compList.join(', ');
}
function getAfUrls(plugin, accession) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const url = `https://alphafold.ebi.ac.uk/api/prediction/${accession}`;
try {
const apiResponse = yield plugin.runTask(plugin.fetch({ url, type: 'json' }));
if (apiResponse === null || apiResponse === void 0 ? void 0 : apiResponse[0].bcifUrl) {
return {
bcif: apiResponse[0].bcifUrl,
cif: apiResponse[0].cifUrl,
pae: apiResponse[0].paeImageUrl,
length: apiResponse[0].uniprotEnd,
};
}
}
catch (_a) {
// ignore, will return undefined
}
console.warn(`Failed to get AFDB URLs for ${accession}: ${url}`);
return undefined;
});
}
function loadAfStructure(plugin) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a, _b;
const customState = (0, plugin_custom_state_1.PluginCustomState)(plugin);
if (!customState.superpositionState)
throw new Error('customState.superpositionState has not been initialized');
const isBinary = ((_a = customState.initParams) === null || _a === void 0 ? void 0 : _a.encoding) === 'bcif';
const url = isBinary ? customState.superpositionState.alphafold.apiData.bcif : customState.superpositionState.alphafold.apiData.cif;
const { structure } = yield loadStructure(plugin, url, 'mmcif', isBinary);
const strInstance = structure;
if (!strInstance)
return false;
// Store Refs in state
const spState = customState.superpositionState;
spState.alphafold.ref = strInstance === null || strInstance === void 0 ? void 0 : strInstance.ref;
if (!((_b = customState.initParams) === null || _b === void 0 ? void 0 : _b.moleculeId))
throw new Error('initParams.moleculeId is not defined');
spState.models[`AF-${customState.initParams.moleculeId}`] = strInstance === null || strInstance === void 0 ? void 0 : strInstance.ref;
const chainSel = yield plugin.builders.structure.tryCreateComponentStatic(strInstance, 'polymer', { label: `AlphaFold Structure`, tags: [`alphafold-chain`, `superposition-sel`] });
if (chainSel) {
yield plugin.builders.structure.representation.addRepresentation(chainSel, { type: 'putty', color: 'plddt-confidence', size: 'uniform', sizeParams: { value: 1.5 } }, { tag: `af-superposition-visual` });
return strInstance === null || strInstance === void 0 ? void 0 : strInstance.ref;
}
return false;
});
}
function superposeAf(plugin, traceOnly, segmentIndex) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const customState = (0, plugin_custom_state_1.PluginCustomState)(plugin);
const spState = customState.superpositionState;
if (!(spState === null || spState === void 0 ? void 0 : spState.segmentData))
return;
// Load AF structure
const afStrRef = spState.alphafold.ref || (yield loadAfStructure(plugin));
if (!afStrRef)
return;
const afStr = plugin.managers.structure.hierarchy.current.refs.get(afStrRef);
const segmentNum = segmentIndex ? segmentIndex : spState.activeSegment - 1;
if (!spState.alphafold.transforms[segmentNum]) {
// Create representative list
const mappingResult = [];
const coordinateSystems = [];
const failedPairsResult = [];
const zeroOverlapPairsResult = [];
let minRmsd = 0;
let minIndex = 0;
const rmsdList = [];
const segmentClusters = spState.segmentData[segmentNum].clusters;
segmentClusters.forEach((cluster) => {
var _a, _b, _c;
const modelRef = spState.models[`${cluster[0].pdb_id}_${cluster[0].struct_asym_id}`];
if (modelRef) {
const structHierarchy = plugin.managers.structure.hierarchy.current.refs.get(modelRef);
if (structHierarchy) {
const input = [structHierarchy.components[0], afStr];
const structures = input.map(s => { var _a; return (_a = s.cell.obj) === null || _a === void 0 ? void 0 : _a.data; });
let { entries, failedPairs, zeroOverlapPairs } = (0, superposition_sifts_mapping_1.alignAndSuperposeWithSIFTSMapping)(structures, {
traceOnly,
includeResidueTest: loc => structure_1.StructureProperties.atom.B_iso_or_equiv(loc) > 70,
applyTestIndex: [1],
});
if (entries.length === 0 || (entries && entries[0] && entries[0].transform.rmsd.toFixed(1) === '0.0')) {
const alignWithoutPlddt = (0, superposition_sifts_mapping_1.alignAndSuperposeWithSIFTSMapping)(structures, { traceOnly });
entries = alignWithoutPlddt.entries;
}
if (entries && entries[0]) {
mappingResult.push(entries[0]);
coordinateSystems.push((_c = (_b = (_a = input[0]) === null || _a === void 0 ? void 0 : _a.transform) === null || _b === void 0 ? void 0 : _b.cell.obj) === null || _c === void 0 ? void 0 : _c.data.coordinateSystem);
const totalMappings = mappingResult.length;
if (totalMappings === 1 || entries[0].transform.rmsd < minRmsd) {
minRmsd = entries[0].transform.rmsd;
minIndex = totalMappings === 1 ? 0 : mappingResult.length - 1;
}
rmsdList.push(`${cluster[0].pdb_id} chain ${cluster[0].struct_asym_id}:${entries[0].transform.rmsd.toFixed(2)}`);
}
else {
if (failedPairs.length > 0)
failedPairsResult.push(failedPairs);
if (zeroOverlapPairs.length > 0)
zeroOverlapPairsResult.push(zeroOverlapPairs);
// rmsdList.push(`${cluster[0].pdb_id} ${cluster[0].struct_asym_id}:-`)
}
}
}
});
// console.log(failedPairsResult);
// console.log(zeroOverlapPairsResult);
if (mappingResult.length > 0) {
spState.alphafold.visibility[segmentNum] = true;
spState.alphafold.transforms[segmentNum] = mappingResult[minIndex].transform.bTransform;
spState.alphafold.coordinateSystems[segmentNum] = coordinateSystems[minIndex];
spState.alphafold.rmsds[segmentNum] = rmsdList.sort((a, b) => parseFloat(a.split(':')[1]) - parseFloat(b.split(':')[1]));
}
}
yield afTransform(plugin, afStr.cell, spState.alphafold.transforms[segmentNum], spState.alphafold.coordinateSystems[segmentNum]);
(0, alphafold_transparency_1.applyAFTransparency)(plugin, afStr, 0.8, 70);
return true;
});
}
function renderSuperposition(plugin, segmentIndex, entryList) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a;
const customState = (0, plugin_custom_state_1.PluginCustomState)(plugin);
const superpositionParams = customState.initParams.superpositionParams;
let busyFlagOn = false;
if (entryList.length > 1) {
busyFlagOn = true;
(_a = customState.events) === null || _a === void 0 ? void 0 : _a.isBusy.next(true);
}
// Load Coordinates and render respresentations
return plugin.dataTransaction(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a, e_1, _b, _c;
var _d;
if (!customState.initParams)
throw new Error('customState.initParams has not been initialized');
if (!customState.superpositionState)
throw new Error('customState.superpositionState has not been initialized');
const spState = customState.superpositionState;
for (const s of entryList) {
// validate matrix availability
if (!spState.matrixData[`${s.pdb_id}_${s.auth_asym_id}`]) {
spState.noMatrixStruct.push(`${s.pdb_id}_${s.struct_asym_id}`);
spState.invalidStruct.push(`${s.pdb_id}_${s.struct_asym_id}`);
continue;
}
spState.loadedStructs[segmentIndex].push(`${s.pdb_id}_${s.struct_asym_id}`);
// Set Coordinate server url
const request = (superpositionParams && superpositionParams.ligandView) ?
{ pdbId: s.pdb_id, queryType: 'full' }
: { pdbId: s.pdb_id, queryType: 'atoms', queryParams: { auth_asym_id: s.auth_asym_id } };
const strUrl = (0, helpers_1.getStructureUrl)(customState.initParams, request);
// Load Data
let strInstance;
let modelRef;
let clearOnFail = true;
if (superpositionParams && superpositionParams.ligandView && spState.entries[s.pdb_id]) {
const polymerInstance = plugin.state.data.select(spState.entries[s.pdb_id])[0];
modelRef = polymerInstance.transform.parent;
const modelInstance = plugin.state.data.select(modelRef)[0];
strInstance = yield plugin.builders.structure.createStructure(modelInstance, { name: 'model', params: {} });
clearOnFail = false;
}
else {
const isBinary = customState.initParams.encoding === 'bcif' ? true : false;
const { model, structure } = yield loadStructure(plugin, strUrl, 'mmcif', isBinary);
strInstance = structure;
modelRef = model.ref;
}
if (!strInstance)
continue;
// Store Refs in state
if (!spState.models[`${s.pdb_id}_${s.struct_asym_id}`])
spState.models[`${s.pdb_id}_${s.struct_asym_id}`] = strInstance === null || strInstance === void 0 ? void 0 : strInstance.ref;
if (superpositionParams && superpositionParams.ligandView && !spState.entries[s.pdb_id])
spState.entries[s.pdb_id] = strInstance === null || strInstance === void 0 ? void 0 : strInstance.ref;
// Apply tranform matrix
const matrix = linear_algebra_1.Mat4.ofRows(customState.superpositionState.matrixData[`${s.pdb_id}_${s.auth_asym_id}`].matrix);
yield transform(plugin, strInstance, matrix);
// Create representations
let chainSel;
if ((superpositionParams && superpositionParams.ligandView) && s.is_representative) {
const uniformColor1 = getNextColor(plugin, segmentIndex); // random color
chainSel = yield plugin.builders.structure.tryCreateComponentFromExpression(strInstance, chainSelection(s.struct_asym_id), `Chain-${segmentIndex}`, { label: `Chain`, tags: [`superposition-sel`] });
if (chainSel) {
yield plugin.builders.structure.representation.addRepresentation(chainSel, { type: 'putty', color: 'uniform', colorParams: { value: uniformColor1 }, size: 'uniform' }, { tag: `superposition-visual` });
spState.refMaps[chainSel.ref] = `${s.pdb_id}_${s.struct_asym_id}`;
}
}
else if ((superpositionParams && superpositionParams.ligandView) && !s.is_representative) {
// Do nothing
}
else {
const uniformColor2 = getNextColor(plugin, segmentIndex); // random color
chainSel = yield plugin.builders.structure.tryCreateComponentStatic(strInstance, 'polymer', { label: `Chain`, tags: [`Chain-${segmentIndex}`, `superposition-sel`] });
if (chainSel) {
yield plugin.builders.structure.representation.addRepresentation(chainSel, { type: 'putty', color: 'uniform', colorParams: { value: uniformColor2 }, size: 'uniform' }, { tag: `superposition-visual` });
spState.refMaps[chainSel.ref] = `${s.pdb_id}_${s.struct_asym_id}`;
}
// // const addTooltipUpdate = plugin.state.behaviors.build().to(BestDatabaseSequenceMapping.id).update(BestDatabaseSequenceMapping, (old: any) => { old.showTooltip = true; });
// // await plugin.runTask(plugin.state.behaviors.updateTree(addTooltipUpdate));
// BestDatabaseSequenceMapping
// console.log(plugin.state.data.select(modelRef)[0])
}
let invalidStruct = chainSel ? false : true;
if (superpositionParams && superpositionParams.ligandView) {
const state = plugin.state.data;
const hetInfo = yield getLigandNamesFromModelData(plugin, state, modelRef);
const hets = hetInfo ? hetInfo.hetNames : [];
// const interactingHets = [];
if (hets && hets.length > 0) {
try {
for (var _e = true, hets_1 = (e_1 = void 0, tslib_1.__asyncValues(hets)), hets_1_1; hets_1_1 = yield hets_1.next(), _a = hets_1_1.done, !_a; _e = true) {
_c = hets_1_1.value;
_e = false;
const het = _c;
const ligand = builder_1.MolScriptBuilder.struct.generator.atomGroups({
'chain-test': builder_1.MolScriptBuilder.core.rel.eq([builder_1.MolScriptBuilder.struct.atomProperty.macromolecular.auth_asym_id(), s.auth_asym_id]),
'residue-test': builder_1.MolScriptBuilder.core.rel.eq([builder_1.MolScriptBuilder.struct.atomProperty.macromolecular.label_comp_id(), het]),
'group-by': builder_1.MolScriptBuilder.core.str.concat([builder_1.MolScriptBuilder.struct.atomProperty.core.operatorName(), builder_1.MolScriptBuilder.struct.atomProperty.macromolecular.residueKey()]),
});
const labelTagParams = { label: `${het}`, tags: [`superposition-ligand-sel`] };
const hetColor = (0, helpers_1.normalizeColor)(superpositionParams.ligandColor, DefaultLigandColor);
const ligandExp = yield plugin.builders.structure.tryCreateComponentFromExpression(strInstance, ligand, `${het}-${segmentIndex}`, labelTagParams);
if (ligandExp) {
yield plugin.builders.structure.representation.addRepresentation(ligandExp, { type: 'ball-and-stick', color: 'uniform', colorParams: { value: hetColor } }, { tag: `superposition-ligand-visual` });
spState.refMaps[ligandExp.ref] = `${s.pdb_id}_${s.struct_asym_id}`;
invalidStruct = false;
// interactingHets.push(het);
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (!_e && !_a && (_b = hets_1.return)) yield _b.call(hets_1);
}
finally { if (e_1) throw e_1.error; }
}
}
const carbEntityCount = hetInfo ? hetInfo.carbEntityCount : 0;
if (carbEntityCount > 0) {
// Get Carbohydrate Polymers details from PDBe API
const allCarbPolymers = yield getCarbPolymerDetailsFromApi(plugin, s.pdb_id);
// Polymer chain + surroundings query
const polymerChainWithSurroundings = builder_1.MolScriptBuilder.struct.modifier.includeSurroundings({
0: builder_1.MolScriptBuilder.struct.generator.atomGroups({
'entity-test': builder_1.MolScriptBuilder.core.rel.eq([builder_1.MolScriptBuilder.ammp('entityType'), 'polymer']),
'chain-test': builder_1.MolScriptBuilder.core.rel.eq([builder_1.MolScriptBuilder.struct.atomProperty.macromolecular.auth_asym_id(), s.auth_asym_id]),
'group-by': builder_1.MolScriptBuilder.core.str.concat([builder_1.MolScriptBuilder.struct.atomProperty.core.operatorName(), builder_1.MolScriptBuilder.struct.atomProperty.macromolecular.residueKey()]),
}),
radius: 5,
'as-whole-residues': true,
});
let i = 0;
for (const carbEntityChainId of allCarbPolymers.branchedChains) {
const carbEntityChain = builder_1.MolScriptBuilder.struct.generator.atomGroups({
'entity-test': builder_1.MolScriptBuilder.core.rel.eq([builder_1.MolScriptBuilder.ammp('entityType'), 'branched']),
'chain-test': builder_1.MolScriptBuilder.core.rel.eq([builder_1.MolScriptBuilder.struct.atomProperty.macromolecular.auth_asym_id(), carbEntityChainId]),
'group-by': builder_1.MolScriptBuilder.core.str.concat([builder_1.MolScriptBuilder.struct.atomProperty.core.operatorName(), builder_1.MolScriptBuilder.struct.atomProperty.macromolecular.residueKey()]),
});
const carbEntityChainInVicinity = builder_1.MolScriptBuilder.struct.filter.intersectedBy({
0: polymerChainWithSurroundings,
by: carbEntityChain,
});
const data = (plugin.state.data.select(strInstance.ref)[0].obj).data;
const carbChainSel = script_1.Script.getStructureSelection(carbEntityChainInVicinity, data);
if (carbChainSel && carbChainSel.kind === 'sequence') {
// console.log(carbEntityChainId + ' chain present in 5 A radius');
const carbLigands = [];
const carbLigNamesAndCount = {};
const carbLigList = [];
for (const carbLigs of allCarbPolymers.branchedLigands[i]) {
const ligResDetails = carbLigs.split('-');
carbLigands.push(builder_1.MolScriptBuilder.core.rel.eq([builder_1.MolScriptBuilder.struct.atomProperty.macromolecular.auth_seq_id(), +ligResDetails[1]]));
if (carbLigNamesAndCount[ligResDetails[0]]) {
carbLigNamesAndCount[ligResDetails[0]]++;
}
else {
carbLigNamesAndCount[ligResDetails[0]] = 1;
}
carbLigList.push(ligResDetails[0]);
}
const carbVisLabel = createCarbVisLabel(carbLigNamesAndCount);
const branchedEntity = builder_1.MolScriptBuilder.struct.generator.atomGroups({
'entity-test': builder_1.MolScriptBuilder.core.rel.eq([builder_1.MolScriptBuilder.ammp('entityType'), 'branched']),
'group-by': builder_1.MolScriptBuilder.core.str.concat([builder_1.MolScriptBuilder.struct.atomProperty.core.operatorName(), builder_1.MolScriptBuilder.struct.atomProperty.macromolecular.residueKey()]),
'chain-test': builder_1.MolScriptBuilder.core.rel.eq([builder_1.MolScriptBuilder.struct.atomProperty.macromolecular.auth_asym_id(), carbEntityChainId]),
'residue-test': builder_1.MolScriptBuilder.core.logic.or(carbLigands),
});
const labelTagParams = { label: `${carbVisLabel}`, tags: [`superposition-carb-sel`] };
const ligandExp = yield plugin.builders.structure.tryCreateComponentFromExpression(strInstance, branchedEntity, `${carbLigList.join('-')}-${segmentIndex}`, labelTagParams);
if (ligandExp) {
yield plugin.builders.structure.representation.addRepresentation(ligandExp, { type: 'carbohydrate' }, { tag: `superposition-carb-visual` });
spState.refMaps[ligandExp.ref] = `${s.pdb_id}_${s.struct_asym_id}`;
invalidStruct = false;
}
}
i++;
}
}
if (invalidStruct) {
spState.invalidStruct.push(`${s.pdb_id}_${s.struct_asym_id}`);
const loadedStructIndex = spState.loadedStructs[segmentIndex].indexOf(`${s.pdb_id}_${s.struct_asym_id}`);
if (loadedStructIndex > -1)
spState.loadedStructs[segmentIndex].splice(loadedStructIndex, 1);
// remove downloaded data
if (clearOnFail) {
// const m = plugin.state.data.select(modelRef)[0];
// const t = plugin.state.data.select(m.transform.parent)[0];
// const d = plugin.state.data.select(t.transform.parent)[0];
// PluginCommands.State.RemoveObject(plugin, { state: d.parent!, ref: d.transform.parent, removeParentGhosts: true });
}
}
else {
// if(interactingHets.length > 0) spState.hets[`${s.pdb_id}_${s.struct_asym_id}`] = interactingHets;
}
}
}
if (busyFlagOn) {
busyFlagOn = false;
(_d = customState.events) === null || _d === void 0 ? void 0 : _d.isBusy.next(false);
}
}));
});
}
function getLigandNamesFromModelData(plugin, state, modelRef) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a;
const cell = state.select(modelRef)[0];
if (!cell || !cell.obj)
return undefined;
const model = cell.obj.data;
if (!model)
return;
const structures = [];
for (const s of plugin.managers.structure.hierarchy.selection.structures) {
const structure = (_a = s.cell.obj) === null || _a === void 0 ? void 0 : _a.data;
if (structure)
structures.push(structure);
}
const info = yield helpers_1.ModelInfo.get(model, structures);
return info;
});
}
function loadStructure(plugin, url, format, isBinary) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
try {
const data = yield plugin.builders.data.download({ url: assets_1.Asset.Url(url), isBinary: isBinary });
const trajectory = yield plugin.builders.structure.parseTrajectory(data, format);
const model = yield plugin.builders.structure.createModel(trajectory);
const modelProperties = yield plugin.builders.structure.insertModelProperties(model);
const structure = yield plugin.builders.structure.createStructure(modelProperties || model, { name: 'model', params: {} });
yield plugin.builders.structure.insertStructureProperties(structure);
return { data, trajectory, model, structure };
}
catch (e) {
return { structure: undefined };
}
});
}
function chainSelection(struct_asym_id) {
return builder_1.MolScriptBuilder.struct.generator.atomGroups({
'chain-test': builder_1.MolScriptBuilder.core.rel.eq([builder_1.MolScriptBuilder.struct.atomProperty.macromolecular.label_asym_id(), struct_asym_id]),
});
}
/** Apply tranformation to a structure. Only use once per structure, combining multiple transformations is not implemented. */
function transform(plugin, s, matrix) {
const b = plugin.state.data.build().to(s)
.insert(transforms_1.StateTransforms.Model.TransformStructureConformation, { transform: { name: 'matrix', params: { data: matrix, transpose: false } } });
return plugin.runTask(plugin.state.data.updateTree(b));
}
function afTransform(plugin, s, matrix, coordinateSystem) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const r = mol_state_1.StateObjectRef.resolveAndCheck(plugin.state.data, s);
if (!r)
return;
const o = plugin.state.data.selectQ(q => q.byRef(r.transform.ref).subtree().withTransformer(transforms_1.StateTransforms.Model.TransformStructureConformation))[0];
const transform = coordinateSystem && !linear_algebra_1.Mat4.isIdentity(coordinateSystem.matrix)
? linear_algebra_1.Mat4.mul((0, linear_algebra_1.Mat4)(), coordinateSystem.matrix, matrix)
: matrix;
const params = {
transform: {
name: 'matrix',
params: { data: transform, transpose: false },
},
};
const b = o
? plugin.state.data.build().to(o).update(params)
: plugin.state.data.build().to(s)
.insert(transforms_1.StateTransforms.Model.TransformStructureConformation, params, { tags: 'SuperpositionTransform' });
yield plugin.runTask(plugin.state.data.updateTree(b));
});
}
function getMatrixData(plugin) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a, _b, _c;
const customState = (0, plugin_custom_state_1.PluginCustomState)(plugin);
if (!customState.initParams)
throw new Error('customState.initParams has not been initialized');
if (!customState.superpositionState)
throw new Error('customState.superpositionState has not been initialized');
const matrixAccession = (_b = (_a = customState.initParams.superpositionParams) === null || _a === void 0 ? void 0 : _a.matrixAccession) !== null && _b !== void 0 ? _b : customState.initParams.moleculeId;
const clusterRecUrlStr = `${customState.initParams.pdbeUrl}static/superpose/matrices/${matrixAccession}`;
const assetManager = plugin.managers.asset;
const clusterRecUrl = assets_1.Asset.getUrlAsset(assetManager, clusterRecUrlStr);
try {
const clusterRecData = yield plugin.runTask(assetManager.resolve(clusterRecUrl, 'json', false));
if (clusterRecData && clusterRecData.data) {
customState.superpositionState.matrixData = clusterRecData.data;
}
}
catch (e) {
customState.superpositionError = `Matrix data not available for ${matrixAccession}`;
(_c = customState.events) === null || _c === void 0 ? void 0 : _c.superpositionInit.next(true); // Emit segment API data load event
}
});
}
/** Download data about segment clustering and save in plugin custom state */
function getSegmentData(plugin) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a;
const customState = (0, plugin_custom_state_1.PluginCustomState)(plugin);
if (!customState.initParams)
throw new Error('customState.initParams has not been initialized');
if (!customState.superpositionState)
throw new Error('customState.superpositionState has not been initialized');
// Get Data
const segmentsUrl = `${customState.initParams.pdbeUrl}graph-api/uniprot/superposition/${customState.initParams.moleculeId}`;
const assetManager = plugin.managers.asset;
const url = assets_1.Asset.getUrlAsset(assetManager, segmentsUrl);
try {
const result = yield plugin.runTask(assetManager.resolve(url, 'json', false));
if (result === null || result === void 0 ? void 0 : result.data) {
customState.superpositionState.segmentData = result.data[customState.initParams.moleculeId];
}
}
catch (e) {
customState.superpositionError = `Superposition data not available for ${customState.initParams.moleculeId}`;
(_a = customState.events) === null || _a === void 0 ? void 0 : _a.superpositionInit.next(true); // Emit segment API data load event
}
});
}
function getChainLigands(carbEntity) {
const ligandChain = [];
const ligandLabels = [];
const ligands = [];
const labelValueArr = [];
let ligNameStr = '';
for (const chemComp of carbEntity.chem_comp_list) {
labelValueArr.push(`${chemComp.chem_comp_id} (${chemComp.count})`);
}
ligNameStr = labelValueArr.join(', ');
for (const chain of carbEntity.chains) {
ligandChain.push(chain.chain_id);
ligandLabels.push(ligNameStr);
const chainLigands = [];
for (const residue of chain.residues) {
chainLigands.push(residue.chem_comp_id + '-' + residue.residue_number);
}
ligands.push(chainLigands);
}
return {
ligands,
ligandChain,
ligandLabels,
};
}
function getCarbPolymerDetailsFromApi(plugin, pdb_id) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const customState = (0, plugin_custom_state_1.PluginCustomState)(plugin);
if (!customState.initParams)
throw new Error('customState.initParams has not been initialized');
// Get Data
const apiUrl = `${customState.initParams.pdbeUrl}api/pdb/entry/carbohydrate_polymer/${pdb_id}`;
const assetManager = plugin.managers.asset;
const url = assets_1.Asset.getUrlAsset(assetManager, apiUrl);
let branchedLigands = [];
let branchedChains = [];
let branchedlabels = [];
try {
const result = yield plugin.runTask(assetManager.resolve(url, 'json', false));
if (result && result.data) {
const carbEntities = result.data[pdb_id];
for (const carbEntity of carbEntities) {
const carbLigData = getChainLigands(carbEntity);
branchedLigands = branchedLigands.concat(carbLigData.ligands);
branchedChains = branchedChains.concat(carbLigData.ligandChain);
branchedlabels = branchedlabels.concat(carbLigData.ligandLabels);
}
}
}
catch (e) {
// ignore
}
return {
branchedChains,
branchedLigands,
branchedlabels,
};
});
}