123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- import Tokenizer from '../common/text/tokenizer'
- import FixedColumn from '../common/text/column/fixed'
- import Column from '../../../mol-base/collections/column'
- import * as Schema from './schema'
- import Result from '../result'
- import Computation from '../../../mol-base/computation'
- interface State {
- tokenizer: Tokenizer,
- header: Schema.Header,
- numberOfAtoms: number,
- chunker: Computation.Chunker
- }
- function createEmptyHeader(): Schema.Header {
- return {
- title: '',
- timeInPs: 0,
- hasVelocities: false,
- precision: { position: 0, velocity: 0 },
- box: [0, 0, 0]
- };
- }
- function State(tokenizer: Tokenizer, ctx: Computation.Context): State {
- return {
- tokenizer,
- header: createEmptyHeader(),
- numberOfAtoms: 0,
- chunker: Computation.chunker(ctx, 100000)
- };
- }
- function handleTitleString(state: State) {
- const { tokenizer, header } = state;
- let line = Tokenizer.readLine(tokenizer);
-
- if (line.trim().length === 0) {
- line = Tokenizer.readLine(tokenizer);
- }
- const timeOffset = line.lastIndexOf('t=');
- if (timeOffset >= 0) {
- header.timeInPs = parseFloat(line.substring(timeOffset + 2));
- header.title = line.substring(0, timeOffset).trim();
- if (header.title && header.title[header.title.length - 1] === ',') {
- header.title = header.title.substring(0, header.title.length - 1);
- }
- } else {
- header.title = line;
- }
- }
- function handleNumberOfAtoms(state: State) {
- const { tokenizer } = state;
- Tokenizer.markLine(tokenizer);
- const line = Tokenizer.getTokenString(tokenizer);
- state.numberOfAtoms = parseInt(line);
- }
- async function handleAtoms(state: State): Promise<Schema.Atoms> {
- const { tokenizer, numberOfAtoms } = state;
- const lines = await Tokenizer.readLinesAsync(tokenizer, numberOfAtoms, state.chunker);
- const positionSample = tokenizer.data.substring(lines.indices[0], lines.indices[1]).substring(20);
- const precisions = positionSample.match(/\.\d+/g)!;
- const hasVelocities = precisions.length === 6;
- state.header.hasVelocities = hasVelocities;
- state.header.precision.position = precisions[0].length - 1;
- state.header.precision.velocity = hasVelocities ? precisions[3].length - 1 : 0;
- const pO = 20;
- const pW = state.header.precision.position + 5;
- const vO = pO + 3 * pW;
- const vW = state.header.precision.velocity + 4;
- const col = FixedColumn(lines);
- const undef = Column.Undefined(state.numberOfAtoms, Column.Type.float);
- const ret = {
- count: state.numberOfAtoms,
- residueNumber: col(0, 5, Column.Type.int),
- residueName: col(5, 5, Column.Type.str),
- atomName: col(10, 5, Column.Type.str),
- atomNumber: col(15, 5, Column.Type.int),
- x: col(pO, pW, Column.Type.float),
- y: col(pO + pW, pW, Column.Type.float),
- z: col(pO + 2 * pW, pW, Column.Type.float),
- vx: hasVelocities ? col(vO, vW, Column.Type.float) : undef,
- vy: hasVelocities ? col(vO + vW, vW, Column.Type.float) : undef,
- vz: hasVelocities ? col(vO + 2 * vW, vW, Column.Type.float) : undef,
- };
- return ret;
- }
- function handleBoxVectors(state: State) {
- const { tokenizer } = state;
- const values = Tokenizer.readLine(tokenizer).trim().split(/\s+/g);
- state.header.box = [+values[0], +values[1], +values[2]];
- }
- async function parseInternal(data: string, ctx: Computation.Context): Promise<Result<Schema.File>> {
- const tokenizer = Tokenizer(data);
- ctx.update({ message: 'Parsing...', current: 0, max: data.length });
- const structures: Schema.Structure[] = [];
- while (tokenizer.position < data.length) {
- const state = State(tokenizer, ctx);
- handleTitleString(state);
- handleNumberOfAtoms(state);
- const atoms = await handleAtoms(state);
- handleBoxVectors(state);
- structures.push({ header: state.header, atoms });
- }
- const result: Schema.File = { structures };
- return Result.success(result);
- }
- export function parse(data: string) {
- return Computation.create<Result<Schema.File>>(async ctx => {
- return await parseInternal(data, ctx);
- });
- }
- export default parse;
|