UNPKG

molstar

Version:

A comprehensive macromolecular library.

259 lines (258 loc) 11.6 kB
"use strict"; /** * Copyright (c) 2019-2024 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> * @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Yana Rose <yana.v.rose@gmail.com> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.pdbToMmCif = pdbToMmCif; const string_1 = require("../../../mol-util/string"); const cif_1 = require("../../../mol-io/reader/cif"); const tokenizer_1 = require("../../../mol-io/reader/common/text/tokenizer"); const assembly_1 = require("./assembly"); const secondary_structure_1 = require("./secondary-structure"); const entity_1 = require("./entity"); const component_1 = require("../common/component"); const entity_2 = require("../common/entity"); const db_1 = require("../../../mol-data/db"); const types_1 = require("../../../mol-model/structure/model/types"); const atom_site_1 = require("./atom-site"); const anisotropic_1 = require("./anisotropic"); const conect_1 = require("./conect"); const debug_1 = require("../../../mol-util/debug"); const header_1 = require("./header"); async function pdbToMmCif(pdb) { const { lines } = pdb; const { data, indices } = lines; const tokenizer = (0, tokenizer_1.Tokenizer)(data); const isPdbqt = !!pdb.isPdbqt; // Count the atoms let atomCount = 0; let anisotropicCount = 0; for (let i = 0, _i = lines.count; i < _i; i++) { const s = indices[2 * i], e = indices[2 * i + 1]; switch (data.charAt(s)) { case 'A': if ((0, string_1.substringStartsWith)(data, s, e, 'ATOM ')) atomCount++; else if ((0, string_1.substringStartsWith)(data, s, e, 'ANISOU')) anisotropicCount++; break; case 'H': if ((0, string_1.substringStartsWith)(data, s, e, 'HETATM')) atomCount++; break; } } const header = {}; const atomSite = (0, atom_site_1.getAtomSiteTemplate)(data, atomCount); const anisotropic = (0, anisotropic_1.getAnisotropicTemplate)(data, anisotropicCount); const entityBuilder = new entity_2.EntityBuilder(); const helperCategories = []; const heteroNames = []; let modelNum = 0, modelStr = ''; let conectRange = undefined; let hasAssemblies = false; const terIndices = new Set(); for (let i = 0, _i = lines.count; i < _i; i++) { let s = indices[2 * i], e = indices[2 * i + 1]; switch (data.charAt(s)) { case 'A': if ((0, string_1.substringStartsWith)(data, s, e, 'ATOM ')) { if (!modelNum) { modelNum++; modelStr = '' + modelNum; } (0, atom_site_1.addAtom)(atomSite, modelStr, tokenizer, s, e, isPdbqt); } else if ((0, string_1.substringStartsWith)(data, s, e, 'ANISOU')) { (0, anisotropic_1.addAnisotropic)(anisotropic, modelStr, tokenizer, s, e); } break; case 'C': if ((0, string_1.substringStartsWith)(data, s, e, 'CRYST1')) { helperCategories.push(...(0, assembly_1.parseCryst1)(pdb.id || '?', data.substring(s, e))); } else if ((0, string_1.substringStartsWith)(data, s, e, 'CONECT')) { let j = i + 1; while (true) { s = indices[2 * j]; e = indices[2 * j + 1]; if (!(0, string_1.substringStartsWith)(data, s, e, 'CONECT')) break; j++; } if (conectRange) { if (debug_1.isDebugMode) { console.log('only single CONECT block allowed, ignoring others'); } } else { conectRange = [i, j]; } i = j - 1; } else if ((0, string_1.substringStartsWith)(data, s, e, 'COMPND')) { let j = i + 1; while (true) { s = indices[2 * j]; e = indices[2 * j + 1]; if (!(0, string_1.substringStartsWith)(data, s, e, 'COMPND')) break; j++; } entityBuilder.setCompounds((0, entity_1.parseCmpnd)(lines, i, j)); i = j - 1; } break; case 'H': if ((0, string_1.substringStartsWith)(data, s, e, 'HEADER')) { (0, header_1.addHeader)(data, s, e, header); } else if ((0, string_1.substringStartsWith)(data, s, e, 'HETATM')) { if (!modelNum) { modelNum++; modelStr = '' + modelNum; } (0, atom_site_1.addAtom)(atomSite, modelStr, tokenizer, s, e, isPdbqt); } else if ((0, string_1.substringStartsWith)(data, s, e, 'HELIX')) { let j = i + 1; while (true) { s = indices[2 * j]; e = indices[2 * j + 1]; if (!(0, string_1.substringStartsWith)(data, s, e, 'HELIX')) break; j++; } helperCategories.push((0, secondary_structure_1.parseHelix)(lines, i, j)); i = j - 1; } else if ((0, string_1.substringStartsWith)(data, s, e, 'HETNAM')) { let j = i + 1; while (true) { s = indices[2 * j]; e = indices[2 * j + 1]; if (!(0, string_1.substringStartsWith)(data, s, e, 'HETNAM')) break; j++; } heteroNames.push(...Array.from((0, entity_1.parseHetnam)(lines, i, j).entries())); i = j - 1; } break; case 'M': if ((0, string_1.substringStartsWith)(data, s, e, 'MODEL ')) { modelNum++; modelStr = '' + modelNum; } if ((0, string_1.substringStartsWith)(data, s, e, 'MTRIX')) { let j = i + 1; while (true) { s = indices[2 * j]; e = indices[2 * j + 1]; if (!(0, string_1.substringStartsWith)(data, s, e, 'MTRIX')) break; j++; } helperCategories.push(...(0, assembly_1.parseMtrix)(lines, i, j)); i = j - 1; } // TODO: MODRES records => pdbx_struct_mod_residue break; case 'O': // TODO: ORIGX record => cif.database_PDB_matrix.origx, cif.database_PDB_matrix.origx_vector break; case 'R': if ((0, string_1.substringStartsWith)(data, s, e, 'REMARK 350')) { let j = i + 1; while (true) { s = indices[2 * j]; e = indices[2 * j + 1]; if (!(0, string_1.substringStartsWith)(data, s, e, 'REMARK 350')) break; j++; } helperCategories.push(...(0, assembly_1.parseRemark350)(lines, i, j)); i = j - 1; hasAssemblies = true; } break; case 'S': if ((0, string_1.substringStartsWith)(data, s, e, 'SHEET')) { let j = i + 1; while (true) { s = indices[2 * j]; e = indices[2 * j + 1]; if (!(0, string_1.substringStartsWith)(data, s, e, 'SHEET')) break; j++; } helperCategories.push((0, secondary_structure_1.parseSheet)(lines, i, j)); i = j - 1; } // TODO: SCALE record => cif.atom_sites.fract_transf_matrix, cif.atom_sites.fract_transf_vector break; case 'T': if ((0, string_1.substringStartsWith)(data, s, e, 'TER')) { terIndices.add(atomSite.index); } } } // build entry, struct_keywords and pdbx_database_status if (header.id_code) { const entry = { id: cif_1.CifField.ofString(header.id_code) }; helperCategories.push(cif_1.CifCategory.ofFields('entry', entry)); } if (header.classification) { const struct_keywords = { pdbx_keywords: cif_1.CifField.ofString(header.classification) }; helperCategories.push(cif_1.CifCategory.ofFields('struct_keywords', struct_keywords)); } if (header.dep_date) { const pdbx_database_status = { recvd_initial_deposition_date: cif_1.CifField.ofString(header.dep_date) }; helperCategories.push(cif_1.CifCategory.ofFields('pdbx_database_status', pdbx_database_status)); } // build entity and chem_comp categories const seqIds = db_1.Column.ofIntTokens(atomSite.auth_seq_id); const atomIds = db_1.Column.ofStringTokens(atomSite.auth_atom_id); const compIds = db_1.Column.ofStringTokens(atomSite.auth_comp_id); const asymIds = db_1.Column.ofStringTokens(atomSite.auth_asym_id); const labelAsymIdHelper = new atom_site_1.LabelAsymIdHelper(asymIds, atomSite.pdbx_PDB_model_num, terIndices, hasAssemblies); const componentBuilder = new component_1.ComponentBuilder(seqIds, atomIds); componentBuilder.setNames(heteroNames); entityBuilder.setNames(heteroNames); for (let i = 0, il = compIds.rowCount; i < il; ++i) { const compId = compIds.value(i); const moleculeType = (0, types_1.getMoleculeType)(componentBuilder.add(compId, i).type, compId); const asymId = labelAsymIdHelper.get(i); atomSite.label_entity_id[i] = entityBuilder.getEntityId(compId, moleculeType, asymId); } const atom_site = (0, atom_site_1.getAtomSite)(atomSite, labelAsymIdHelper, { hasAssemblies }); if (!isPdbqt) delete atom_site.partial_charge; if (conectRange) { helperCategories.push((0, conect_1.parseConect)(lines, conectRange[0], conectRange[1], atom_site)); } const categories = { entity: cif_1.CifCategory.ofTable('entity', entityBuilder.getEntityTable()), chem_comp: cif_1.CifCategory.ofTable('chem_comp', componentBuilder.getChemCompTable()), atom_site: cif_1.CifCategory.ofFields('atom_site', atom_site), atom_site_anisotrop: cif_1.CifCategory.ofFields('atom_site_anisotrop', (0, anisotropic_1.getAnisotropic)(anisotropic)) }; for (const c of helperCategories) { categories[c.name] = c; } return { header: pdb.id || 'PDB', categoryNames: Object.keys(categories), categories }; }