Skip to content
Snippets Groups Projects
Commit 261e9606 authored by Alexander Rose's avatar Alexander Rose
Browse files

Gro parser using computation

parent bb1d8f2f
No related branches found
No related tags found
No related merge requests found
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Alexander Rose <alexander.rose@weirdbyte.de>
*/ */
import Computation from '../../../utils/computation'
export interface Tokenizer { export interface Tokenizer {
data: string data: string
...@@ -15,6 +17,8 @@ export interface Tokenizer { ...@@ -15,6 +17,8 @@ export interface Tokenizer {
currentLineNumber: number currentLineNumber: number
currentTokenStart: number currentTokenStart: number
currentTokenEnd: number currentTokenEnd: number
computation: Computation.Chunked
} }
export interface Tokens { export interface Tokens {
...@@ -23,14 +27,15 @@ export interface Tokens { ...@@ -23,14 +27,15 @@ export interface Tokens {
indices: ArrayLike<number> indices: ArrayLike<number>
} }
export function Tokenizer(data: string): Tokenizer { export function Tokenizer(data: string, ctx: Computation.Context): Tokenizer {
return { return {
data, data,
position: 0, position: 0,
length: data.length, length: data.length,
currentLineNumber: 1, currentLineNumber: 1,
currentTokenStart: 0, currentTokenStart: 0,
currentTokenEnd: 0 currentTokenEnd: 0,
computation: new Computation.Chunked(ctx, 1000000)
}; };
} }
...@@ -86,12 +91,17 @@ export namespace Tokenizer { ...@@ -86,12 +91,17 @@ export namespace Tokenizer {
} }
/** Advance the state by the given number of lines and return line starts/ends as tokens. */ /** Advance the state by the given number of lines and return line starts/ends as tokens. */
export function readLines(state: Tokenizer, count: number): Tokens { export async function readLines(state: Tokenizer, count: number): Promise<Tokens> {
const { computation, position, length } = state
const lineTokens = TokenBuilder.create(state, count * 2); const lineTokens = TokenBuilder.create(state, count * 2);
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
markLine(state); markLine(state);
TokenBuilder.addUnchecked(lineTokens, state.currentTokenStart, state.currentTokenEnd); TokenBuilder.addUnchecked(lineTokens, state.currentTokenStart, state.currentTokenEnd);
if (computation.requiresUpdate) {
await computation.updateProgress('Parsing...', void 0, position, length);
}
} }
return { data: state.data, count, indices: lineTokens.indices }; return { data: state.data, count, indices: lineTokens.indices };
......
...@@ -10,6 +10,7 @@ import FixedColumn from '../common/text/column/fixed' ...@@ -10,6 +10,7 @@ import FixedColumn from '../common/text/column/fixed'
import { ColumnType, UndefinedColumn } from '../common/column' import { ColumnType, UndefinedColumn } from '../common/column'
import * as Schema from './schema' import * as Schema from './schema'
import Result from '../result' import Result from '../result'
import Computation from '../../utils/computation'
interface State { interface State {
tokenizer: Tokenizer, tokenizer: Tokenizer,
...@@ -85,9 +86,9 @@ function handleNumberOfAtoms(state: State) { ...@@ -85,9 +86,9 @@ function handleNumberOfAtoms(state: State) {
* position (in nm, x y z in 3 columns, each 8 positions with 3 decimal places) * position (in nm, x y z in 3 columns, each 8 positions with 3 decimal places)
* velocity (in nm/ps (or km/s), x y z in 3 columns, each 8 positions with 4 decimal places) * velocity (in nm/ps (or km/s), x y z in 3 columns, each 8 positions with 4 decimal places)
*/ */
function handleAtoms(state: State): Schema.Atoms { async function handleAtoms(state: State): Promise<Schema.Atoms> {
const { tokenizer, numberOfAtoms } = state; const { tokenizer, numberOfAtoms } = state;
const lines = Tokenizer.readLines(tokenizer, numberOfAtoms); const lines = await Tokenizer.readLines(tokenizer, numberOfAtoms);
const positionSample = tokenizer.data.substring(lines.indices[0], lines.indices[1]).substring(20); const positionSample = tokenizer.data.substring(lines.indices[0], lines.indices[1]).substring(20);
const precisions = positionSample.match(/\.\d+/g)!; const precisions = positionSample.match(/\.\d+/g)!;
...@@ -134,15 +135,15 @@ function handleBoxVectors(state: State) { ...@@ -134,15 +135,15 @@ function handleBoxVectors(state: State) {
state.header.box = [+values[0], +values[1], +values[2]]; state.header.box = [+values[0], +values[1], +values[2]];
} }
function parseInternal(data: string): Result<Schema.File> { async function parseInternal(data: string, ctx: Computation.Context): Promise<Result<Schema.File>> {
const tokenizer = Tokenizer(data); const tokenizer = Tokenizer(data, ctx);
const structures: Schema.Structure[] = []; const structures: Schema.Structure[] = [];
while (tokenizer.position < data.length) { while (tokenizer.position < data.length) {
const state = State(tokenizer); const state = State(tokenizer);
handleTitleString(state); handleTitleString(state);
handleNumberOfAtoms(state); handleNumberOfAtoms(state);
const atoms = handleAtoms(state); const atoms = await handleAtoms(state);
handleBoxVectors(state); handleBoxVectors(state);
structures.push({ header: state.header, atoms }); structures.push({ header: state.header, atoms });
} }
...@@ -152,7 +153,9 @@ function parseInternal(data: string): Result<Schema.File> { ...@@ -152,7 +153,9 @@ function parseInternal(data: string): Result<Schema.File> {
} }
export function parse(data: string) { export function parse(data: string) {
return parseInternal(data); return new Computation<Result<Schema.File>>(async ctx => {
return await parseInternal(data, ctx);
});
} }
export default parse; export default parse;
\ No newline at end of file
...@@ -25,8 +25,9 @@ const groStringHighPrecision = `Generated by trjconv : 2168 system t= 15.00000 ...@@ -25,8 +25,9 @@ const groStringHighPrecision = `Generated by trjconv : 2168 system t= 15.00000
1.82060 2.82060 3.82060` 1.82060 2.82060 3.82060`
describe('gro reader', () => { describe('gro reader', () => {
it('basic', () => { it('basic', async () => {
const parsed = Gro(groString) const comp = Gro(groString)
const parsed = await comp.run()
if (parsed.isError) { if (parsed.isError) {
console.log(parsed) console.log(parsed)
...@@ -57,8 +58,9 @@ describe('gro reader', () => { ...@@ -57,8 +58,9 @@ describe('gro reader', () => {
expect(atoms.vz.value(5)).toBeCloseTo(-0.0244, 0.0001); expect(atoms.vz.value(5)).toBeCloseTo(-0.0244, 0.0001);
}); });
it('high precision', () => { it('high precision', async () => {
const parsed = Gro(groStringHighPrecision); const comp = Gro(groStringHighPrecision)
const parsed = await comp.run()
if (parsed.isError) { if (parsed.isError) {
console.log(parsed) console.log(parsed)
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info.
* *
* @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author David Sehnal <david.sehnal@gmail.com>
*/ */
// import * as util from 'util' // import * as util from 'util'
...@@ -15,18 +16,16 @@ import CIF from './reader/cif/index' ...@@ -15,18 +16,16 @@ import CIF from './reader/cif/index'
// const file = 'test.gro' // const file = 'test.gro'
const file = 'md_1u19_trj.gro' const file = 'md_1u19_trj.gro'
export function _gro() { async function runGro(input: string) {
fs.readFile(`./examples/${file}`, 'utf8', function (err, input) { console.time('parseGro');
if (err) { const comp = Gro(input);
return console.log(err); const running = comp.runWithContext(new Computation.ObservableContext({ updateRateMs: 250 }));
} running.subscribe(p => console.log(`[Gro] ${(p.current / p.max * 100).toFixed(2)} (${p.elapsedMs | 0}ms)`));
// console.log(data); const parsed = await running.result;
console.timeEnd('parseGro');
console.time('parse')
const parsed = Gro(input)
console.timeEnd('parse')
if (parsed.isError) { if (parsed.isError) {
console.log(parsed) console.log(parsed);
return; return;
} }
...@@ -69,15 +68,25 @@ export function _gro() { ...@@ -69,15 +68,25 @@ export function _gro() {
const residueNumber = atoms.residueNumber.toArray({ array: Int32Array }) const residueNumber = atoms.residueNumber.toArray({ array: Int32Array })
console.timeEnd('getIntArray residueNumber') console.timeEnd('getIntArray residueNumber')
console.log(residueNumber.length, residueNumber[0], residueNumber[residueNumber.length - 1]) console.log(residueNumber.length, residueNumber[0], residueNumber[residueNumber.length - 1])
}
async function _gro() {
fs.readFile(`./examples/${file}`, 'utf8', function (err, input) {
if (err) {
return console.log(err);
}
runGro(input)
}); });
} }
_gro()
async function runCIF(input: string | Uint8Array) { async function runCIF(input: string | Uint8Array) {
console.time('parseCIF'); console.time('parseCIF');
const comp = typeof input === 'string' ? CIF.parseText(input) : CIF.parseBinary(input); const comp = typeof input === 'string' ? CIF.parseText(input) : CIF.parseBinary(input);
const running = comp.runWithContext(new Computation.ObservableContext({ updateRateMs: 250 })); const running = comp.runWithContext(new Computation.ObservableContext({ updateRateMs: 250 }));
running.subscribe(p => console.log(`${(p.current / p.max * 100).toFixed(2)} (${p.elapsedMs | 0}ms)`)); running.subscribe(p => console.log(`[CIF] ${(p.current / p.max * 100).toFixed(2)} (${p.elapsedMs | 0}ms)`));
const parsed = await running.result; const parsed = await running.result;
console.timeEnd('parseCIF'); console.timeEnd('parseCIF');
if (parsed.isError) { if (parsed.isError) {
...@@ -98,7 +107,7 @@ async function runCIF(input: string | Uint8Array) { ...@@ -98,7 +107,7 @@ async function runCIF(input: string | Uint8Array) {
export function _cif() { export function _cif() {
let path = `./examples/1cbs_updated.cif`; let path = `./examples/1cbs_updated.cif`;
path = 'c:/test/quick/3j3q.cif'; path = '../test/3j3q.cif';
fs.readFile(path, 'utf8', function (err, input) { fs.readFile(path, 'utf8', function (err, input) {
if (err) { if (err) {
return console.log(err); return console.log(err);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment