src/parser/mol2-parser.js
- /**
- * @file Mol2 Parser
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- * @private
- */
-
- import { Debug, Log, ParserRegistry } from '../globals.js'
- import {
- assignResidueTypeBonds,
- calculateChainnames, calculateSecondaryStructure,
- calculateBondsBetween, calculateBondsWithin
- } from '../structure/structure-utils.js'
- import StructureParser from './structure-parser.js'
-
- const reWhitespace = /\s+/
- const bondTypes = {
- '1': 1,
- '2': 2,
- '3': 3,
- 'am': 1, // amide
- 'ar': 1, // aromatic
- 'du': 1, // dummy
- 'un': 1, // unknown
- 'nc': 0 // not connected
- }
-
- class Mol2Parser extends StructureParser {
- get type () { return 'mol2' }
-
- _parse () {
- // http://paulbourke.net/dataformats/mol2/
-
- if (Debug) Log.time('Mol2Parser._parse ' + this.name)
-
- const s = this.structure
- const sb = this.structureBuilder
-
- const firstModelOnly = this.firstModelOnly
- const asTrajectory = this.asTrajectory
-
- const frames = s.frames
- let doFrames = false
- let currentFrame, currentCoord
-
- const atomMap = s.atomMap
- const atomStore = s.atomStore
- atomStore.resize(Math.round(this.streamer.data.length / 60))
- atomStore.addField('partialCharge', 1, 'float32')
-
- let idx = 0
- let moleculeLineNo = 0
- let modelAtomIdxStart = 0
- let modelIdx = -1
- let numAtoms = 0
-
- let currentRecordType = 0
- let moleculeRecordType = 1
- let atomRecordType = 2
- let bondRecordType = 3
-
- const ap1 = s.getAtomProxy()
- const ap2 = s.getAtomProxy()
-
- function _parseChunkOfLines (_i, _n, lines) {
- for (let i = _i; i < _n; ++i) {
- const line = lines[ i ].trim()
-
- if (line === '' || line[ 0 ] === '#') continue
-
- if (line[ 0 ] === '@') {
- if (line === '@<TRIPOS>MOLECULE') {
- currentRecordType = moleculeRecordType
- moleculeLineNo = 0
-
- ++modelIdx
- } else if (line === '@<TRIPOS>ATOM') {
- currentRecordType = atomRecordType
- modelAtomIdxStart = atomStore.count
-
- if (asTrajectory) {
- currentCoord = 0
- currentFrame = new Float32Array(numAtoms * 3)
- frames.push(currentFrame)
-
- if (modelIdx > 0) doFrames = true
- }
- } else if (line === '@<TRIPOS>BOND') {
- currentRecordType = bondRecordType
- } else {
- currentRecordType = 0
- }
- } else if (currentRecordType === moleculeRecordType) {
- if (moleculeLineNo === 0) {
- s.title = line
- s.id = line
- } else if (moleculeLineNo === 1) {
- const ls = line.split(reWhitespace)
- numAtoms = parseInt(ls[ 0 ])
- // num_atoms [num_bonds [num_subst [num_feat [num_sets]]]]
- } else if (moleculeLineNo === 2) {
-
- // const molType = line;
- // SMALL, BIOPOLYMER, PROTEIN, NUCLEIC_ACID, SACCHARIDE
-
- } else if (moleculeLineNo === 3) {
-
- // const chargeType = line;
- // NO_CHARGES, DEL_RE, GASTEIGER, GAST_HUCK, HUCKEL,
- // PULLMAN, GAUSS80_CHARGES, AMPAC_CHARGES,
- // MULLIKEN_CHARGES, DICT_ CHARGES, MMFF94_CHARGES,
- // USER_CHARGES
-
- } else if (moleculeLineNo === 4) {
-
- // const statusBits = line;
-
- } else if (moleculeLineNo === 5) {
-
- // const molComment = line;
-
- }
-
- ++moleculeLineNo
- } else if (currentRecordType === atomRecordType) {
- const ls = line.split(reWhitespace)
-
- if (firstModelOnly && modelIdx > 0) continue
-
- const x = parseFloat(ls[ 2 ])
- const y = parseFloat(ls[ 3 ])
- const z = parseFloat(ls[ 4 ])
-
- if (asTrajectory) {
- const j = currentCoord * 3
-
- currentFrame[ j + 0 ] = x
- currentFrame[ j + 1 ] = y
- currentFrame[ j + 2 ] = z
-
- currentCoord += 1
-
- if (doFrames) continue
- }
-
- const serial = ls[ 0 ]
- const atomname = ls[ 1 ]
- const element = ls[ 5 ].split('.')[ 0 ]
- const resno = ls[ 6 ] ? parseInt(ls[ 6 ]) : 1
- const resname = ls[ 7 ] ? ls[ 7 ] : ''
- const partialCharge = ls[ 8 ] ? parseFloat(ls[ 8 ]) : 0.0
-
- atomStore.growIfFull()
- atomStore.atomTypeId[ idx ] = atomMap.add(atomname, element)
-
- atomStore.x[ idx ] = x
- atomStore.y[ idx ] = y
- atomStore.z[ idx ] = z
- atomStore.serial[ idx ] = serial
- atomStore.partialCharge[ idx ] = partialCharge
-
- sb.addAtom(modelIdx, '', '', resname, resno, 1)
-
- idx += 1
- } else if (currentRecordType === bondRecordType) {
- if (firstModelOnly && modelIdx > 0) continue
- if (asTrajectory && modelIdx > 0) continue
-
- const ls = line.split(reWhitespace)
-
- // ls[ 0 ] is bond id
- ap1.index = parseInt(ls[ 1 ]) - 1 + modelAtomIdxStart
- ap2.index = parseInt(ls[ 2 ]) - 1 + modelAtomIdxStart
- const order = bondTypes[ ls[ 3 ] ]
-
- s.bondStore.addBond(ap1, ap2, order)
- }
- }
- }
-
- this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {
- _parseChunkOfLines(0, lines.length, lines)
- })
-
- sb.finalize()
- s.finalizeAtoms()
- calculateChainnames(s)
- calculateBondsWithin(s, true)
- calculateBondsBetween(s, true)
- s.finalizeBonds()
- assignResidueTypeBonds(s)
- calculateSecondaryStructure(s)
-
- if (Debug) Log.timeEnd('Mol2Parser._parse ' + this.name)
- }
- }
-
- ParserRegistry.add('mol2', Mol2Parser)
-
- export default Mol2Parser