NGL@1.0.0-beta.7 Home Manual Reference Source Gallery

src/parser/gro-parser.js

/**
 * @file Gro Parser
 * @author Alexander Rose <alexander.rose@weirdbyte.de>
 * @private
 */

import { Debug, Log, ParserRegistry } from '../globals.js'
import StructureParser from './structure-parser.js'
import {
    calculateBonds, calculateChainnames, calculateSecondaryStructure
} from '../structure/structure-utils.js'

class GroParser extends StructureParser {
  get type () { return 'gro' }

  _parse () {
        // http://manual.gromacs.org/current/online/gro.html

    if (Debug) Log.time('GroParser._parse ' + this.name)

    var s = this.structure
    var sb = this.structureBuilder

    var firstModelOnly = this.firstModelOnly
    var asTrajectory = this.asTrajectory
    var cAlphaOnly = this.cAlphaOnly

    var frames = s.frames
    var boxes = s.boxes
    var currentFrame, currentCoord

    var firstLines = this.streamer.peekLines(3)

    s.title = firstLines[ 0 ].trim()

        // determine number of decimal places
    var ndec = firstLines[ 2 ].length - firstLines[ 2 ].lastIndexOf('.') - 1
    var lpos = 5 + ndec
    var xpos = 20
    var ypos = 20 + lpos
    var zpos = 20 + 2 * lpos

        //

    var atomname, resname, resno, serial

    var atomCount = parseInt(firstLines[ 1 ])
    var modelLineCount = atomCount + 3

    var atomMap = s.atomMap
    var atomStore = s.atomStore
    atomStore.resize(atomCount)

    var idx = 0
    var modelIdx = 0
    var lineNo = 0

    function _parseChunkOfLines (_i, _n, lines) {
      for (var i = _i; i < _n; ++i) {
        ++lineNo
        var l = lineNo - 1

        var line = lines[ i ]

        if (!line) continue

        if (l % modelLineCount === 0) {
                    // Log.log( "title", line )

          if (asTrajectory) {
            currentFrame = new Float32Array(atomCount * 3)
            frames.push(currentFrame)
            currentCoord = 0
          }
        } else if (l % modelLineCount === 1) {

                    // Log.log( "atomCount", line )

        } else if (l % modelLineCount === modelLineCount - 1) {
          var str = line.trim().split(/\s+/)
          var box = new Float32Array(9)
          box[ 0 ] = parseFloat(str[ 0 ]) * 10
          box[ 4 ] = parseFloat(str[ 1 ]) * 10
          box[ 8 ] = parseFloat(str[ 2 ]) * 10
          boxes.push(box)

          if (firstModelOnly) {
            return true
          }

          modelIdx += 1
        } else {
          atomname = line.substr(10, 5).trim()
          if (cAlphaOnly && atomname !== 'CA') continue

          var x = parseFloat(line.substr(xpos, lpos)) * 10
          var y = parseFloat(line.substr(ypos, lpos)) * 10
          var z = parseFloat(line.substr(zpos, lpos)) * 10

          if (asTrajectory) {
            var j = currentCoord * 3

            currentFrame[ j + 0 ] = x
            currentFrame[ j + 1 ] = y
            currentFrame[ j + 2 ] = z

            currentCoord += 1

            if (l > modelLineCount) continue
          }

          resname = line.substr(5, 5).trim()
          resno = parseInt(line.substr(0, 5))
          serial = parseInt(line.substr(15, 5))

          atomStore.growIfFull()
          atomStore.atomTypeId[ idx ] = atomMap.add(atomname)

          atomStore.x[ idx ] = x
          atomStore.y[ idx ] = y
          atomStore.z[ idx ] = z
          atomStore.serial[ idx ] = serial

          sb.addAtom(modelIdx, '', '', resname, resno, 0, 'l')

          idx += 1
        }
      }
    }

    this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {
      _parseChunkOfLines(0, lines.length, lines)
    })

    sb.finalize()
    s.finalizeAtoms()
    calculateChainnames(s)
    calculateBonds(s)
    s.finalizeBonds()

    calculateSecondaryStructure(s)

    if (Debug) Log.timeEnd('GroParser._parse ' + this.name)
  }
}

ParserRegistry.add('gro', GroParser)

export default GroParser