Browse Source

Mol2 parser now uses mol-task

David Sehnal 7 years ago
parent
commit
3ff823a63e

+ 3 - 2
src/mol-io/reader/_spec/gro.spec.ts

@@ -6,6 +6,7 @@
  */
 
 import Gro from '../gro/parser'
+import { Run } from 'mol-task';
 
 const groString = `MD of 2 waters, t= 4.2
     6
@@ -26,7 +27,7 @@ const groStringHighPrecision = `Generated by trjconv : 2168 system t=  15.00000
 
 describe('gro reader', () => {
     it('basic', async () => {
-        const parsed = await Gro(groString)();
+        const parsed = await Run(Gro(groString));
 
         if (parsed.isError) {
             console.log(parsed)
@@ -57,7 +58,7 @@ describe('gro reader', () => {
     });
 
     it('high precision', async () => {
-        const parsed = await Gro(groStringHighPrecision)()
+        const parsed = await Run(Gro(groStringHighPrecision));
 
         if (parsed.isError) {
             console.log(parsed)

+ 4 - 3
src/mol-io/reader/_spec/mol2.spec.ts

@@ -1,5 +1,6 @@
 
 import Mol2 from '../mol2/parser'
+import { Run } from 'mol-task';
 
 const Mol2String = `@<TRIPOS>MOLECULE
 5816
@@ -246,7 +247,7 @@ GASTEIGER
 
 describe('mol2 reader', () => {
     it('basic', async () => {
-        const parsed =  await Mol2(Mol2String)();
+        const parsed =  await Run(Mol2(Mol2String));
         if (parsed.isError) {
             throw new Error(parsed.message);
         }
@@ -297,7 +298,7 @@ describe('mol2 reader', () => {
     });
 
     it('multiblocks', async () => {
-        const parsed =  await Mol2(Mol2StringMultiBlocks)();
+        const parsed =  await Run(Mol2(Mol2StringMultiBlocks));
         if (parsed.isError) {
             throw new Error(parsed.message);
         }
@@ -348,7 +349,7 @@ describe('mol2 reader', () => {
     });
 
     it('minimal', async () => {
-        const parsed =  await Mol2(Mol2StringMinimal)();
+        const parsed =  await Run(Mol2(Mol2StringMinimal));
         if (parsed.isError) {
             throw new Error(parsed.message);
         }

+ 4 - 4
src/mol-io/reader/common/text/tokenizer.ts

@@ -6,7 +6,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import Computation from 'mol-util/computation'
+import { chunkedSubtask, RuntimeContext } from 'mol-task'
 
 export interface Tokenizer {
     data: string,
@@ -109,17 +109,17 @@ export namespace Tokenizer {
     }
 
     /** Advance the state by the given number of lines and return line starts/ends as tokens. */
-    export async function readLinesAsync(state: Tokenizer, count: number, chunker: Computation.Chunker): Promise<Tokens> {
+    export async function readLinesAsync(state: Tokenizer, count: number, ctx: RuntimeContext, initialLineCount = 100000): Promise<Tokens> {
         const { length } = state;
         const lineTokens = TokenBuilder.create(state, count * 2);
 
         let linesAlreadyRead = 0;
-        await chunker.process(chunkSize => {
+        await chunkedSubtask(ctx, initialLineCount, state, (chunkSize, state) => {
             const linesToRead = Math.min(count - linesAlreadyRead, chunkSize);
             readLinesChunk(state, linesToRead, lineTokens);
             linesAlreadyRead += linesToRead;
             return linesToRead;
-        }, update => update({ message: 'Parsing...', current: state.position, max: length }));
+        }, (ctx, state) => ctx.update({ message: 'Parsing...', current: state.position, max: length }));
 
         return lineTokens;
     }

+ 7 - 7
src/mol-io/reader/gro/parser.ts

@@ -10,13 +10,13 @@ import Tokenizer from '../common/text/tokenizer'
 import FixedColumn from '../common/text/column/fixed'
 import * as Schema from './schema'
 import Result from '../result'
-import Computation from 'mol-util/computation'
+import { Task, RuntimeContext } from 'mol-task'
 
 interface State {
     tokenizer: Tokenizer,
     header: Schema.Header,
     numberOfAtoms: number,
-    chunker: Computation.Chunker
+    runtimeCtx: RuntimeContext
 }
 
 function createEmptyHeader(): Schema.Header {
@@ -29,12 +29,12 @@ function createEmptyHeader(): Schema.Header {
     };
 }
 
-function State(tokenizer: Tokenizer, ctx: Computation.Context): State {
+function State(tokenizer: Tokenizer, runtimeCtx: RuntimeContext): State {
     return {
         tokenizer,
         header: createEmptyHeader(),
         numberOfAtoms: 0,
-        chunker: Computation.chunker(ctx, 100000) // 100000 lines is the default chunk size for this reader
+        runtimeCtx
     };
 }
 
@@ -90,7 +90,7 @@ function handleNumberOfAtoms(state: State) {
  */
 async function handleAtoms(state: State): Promise<Schema.Atoms> {
     const { tokenizer, numberOfAtoms } = state;
-    const lines = await Tokenizer.readLinesAsync(tokenizer, numberOfAtoms, state.chunker);
+    const lines = await Tokenizer.readLinesAsync(tokenizer, numberOfAtoms, state.runtimeCtx, 100000);
 
     const positionSample = tokenizer.data.substring(lines.indices[0], lines.indices[1]).substring(20);
     const precisions = positionSample.match(/\.\d+/g)!;
@@ -137,7 +137,7 @@ function handleBoxVectors(state: State) {
     state.header.box = [+values[0], +values[1], +values[2]];
 }
 
-async function parseInternal(data: string, ctx: Computation.Context): Promise<Result<Schema.File>> {
+async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<Schema.File>> {
     const tokenizer = Tokenizer(data);
 
     ctx.update({ message: 'Parsing...', current: 0, max: data.length });
@@ -156,7 +156,7 @@ async function parseInternal(data: string, ctx: Computation.Context): Promise<Re
 }
 
 export function parse(data: string) {
-    return Computation.create<Result<Schema.File>>(async ctx => {
+    return Task.create<Result<Schema.File>>('Parse GRO', async ctx => {
         return await parseInternal(data, ctx);
     });
 }

+ 43 - 43
src/mol-io/reader/mol2/parser.ts

@@ -6,7 +6,7 @@
  */
 
 //               NOTES
-//When want to created undefined string column, must use
+// When want to created undefined string column, must use
 // undefStr = UndefinedColumn(molecule.num_atoms, ColumnType.str)
 // but not
 // const undefPooledStr = UndefinedColumn(molecule.num_atoms, ColumnType.pooledStr);
@@ -16,14 +16,14 @@ import { TokenBuilder, Tokenizer } from '../common/text/tokenizer'
 import TokenColumn from '../common/text/column/token'
 import * as Schema from './schema'
 import Result from '../result'
-import Computation from 'mol-util/computation'
+import { Task, RuntimeContext, chunkedSubtask } from 'mol-task'
 
 const { skipWhitespace, eatValue, markLine, getTokenString, readLine } = Tokenizer;
 
 interface State {
     tokenizer: Tokenizer,
     molecule: Schema.Molecule,
-    chunker: Computation.Chunker
+    runtimeCtx: RuntimeContext
 }
 
 function createEmptyMolecule(): Schema.Molecule {
@@ -36,16 +36,16 @@ function createEmptyMolecule(): Schema.Molecule {
         num_sets: 0,
         mol_type: '',
         charge_type: '',
-        status_bits:'',
+        status_bits: '',
         mol_comment: ''
     };
 }
 
-function State(tokenizer: Tokenizer, ctx: Computation.Context): State {
+function State(tokenizer: Tokenizer, runtimeCtx: RuntimeContext): State {
     return {
         tokenizer,
         molecule: createEmptyMolecule(),
-        chunker: Computation.chunker(ctx, 100000)
+        runtimeCtx
     };
 }
 
@@ -54,7 +54,7 @@ const reWhitespace = /\s+/g;
 function handleMolecule(state: State) {
     const { tokenizer, molecule } = state;
 
-    while(getTokenString(tokenizer) !== '@<TRIPOS>MOLECULE'){
+    while (getTokenString(tokenizer) !== '@<TRIPOS>MOLECULE') {
         markLine(tokenizer);
     }
 
@@ -84,10 +84,10 @@ function handleMolecule(state: State) {
     molecule.mol_comment = getTokenString(tokenizer)
 }
 
-function isStatus_bit(aString: String): Boolean{
-    if(aString.includes('DSPMOD') || aString.includes('TYPECOL') || aString.includes('CAP')
-       || aString.includes('BACKBONE') || aString.includes('DICT') || aString.includes('ESSENTIAL')
-       || aString.includes('WATER') || aString.includes('DIRECT')){
+function isStatus_bit(aString: String): Boolean {
+    if (aString.includes('DSPMOD') || aString.includes('TYPECOL') || aString.includes('CAP')
+        || aString.includes('BACKBONE') || aString.includes('DICT') || aString.includes('ESSENTIAL')
+        || aString.includes('WATER') || aString.includes('DIRECT')) {
         return true;
     }
     return false;
@@ -101,7 +101,7 @@ async function handleAtoms(state: State): Promise<Schema.Atoms> {
     let hasStatus_bit = false;
 
     // skip empty lines and '@<TRIPOS>ATOM'
-    while(getTokenString(tokenizer) != '@<TRIPOS>ATOM'){
+    while (getTokenString(tokenizer) !== '@<TRIPOS>ATOM') {
         markLine(tokenizer);
     }
 
@@ -113,17 +113,17 @@ async function handleAtoms(state: State): Promise<Schema.Atoms> {
 
     // optional columns are in order "integer string float string".
     // Use this to find out which column is missing or empty
-    for(let i = 6; i < firstLineLength; i++){
-        if(!isNaN(Number(firstLineArray[i]))){
-            if(firstLineArray[i].indexOf('.') == -1){
+    for (let i = 6; i < firstLineLength; i++) {
+        if (!isNaN(Number(firstLineArray[i]))) {
+            if (firstLineArray[i].indexOf('.') === -1) {
                 hasSubst_id = true;
-            }else{
+            } else {
                 hasCharge = true;
             }
-        }else if(isNaN(Number(firstLineArray[i]))){
-            if(!isStatus_bit(firstLineArray[i])){
+        } else if (isNaN(Number(firstLineArray[i]))) {
+            if (!isStatus_bit(firstLineArray[i])) {
                 hasSubst_name = true;
-            }else{
+            } else {
                 hasStatus_bit = true;
             }
         }
@@ -131,7 +131,7 @@ async function handleAtoms(state: State): Promise<Schema.Atoms> {
 
     // required columns
     const atom_idTokens = TokenBuilder.create(tokenizer, molecule.num_atoms * 2);
-    const atom_nameTokens = TokenBuilder.create(tokenizer, molecule.num_atoms * 2);;
+    const atom_nameTokens = TokenBuilder.create(tokenizer, molecule.num_atoms * 2);
     const xTokens = TokenBuilder.create(tokenizer, molecule.num_atoms * 2);
     const yTokens = TokenBuilder.create(tokenizer, molecule.num_atoms * 2);
     const zTokens = TokenBuilder.create(tokenizer, molecule.num_atoms * 2);
@@ -160,28 +160,28 @@ async function handleAtoms(state: State): Promise<Schema.Atoms> {
     const undefStr = Column.Undefined(molecule.num_atoms, Column.Schema.str);
 
     let numOfColumn = 6;
-    if(hasSubst_id){numOfColumn++}
-    if(hasSubst_name){numOfColumn++}
-    if(hasCharge){numOfColumn++}
-    if(hasStatus_bit){numOfColumn++}
+    if (hasSubst_id) { numOfColumn++ }
+    if (hasSubst_name) { numOfColumn++ }
+    if (hasCharge) { numOfColumn++ }
+    if (hasStatus_bit) { numOfColumn++ }
 
     tokenizer.position = initialTokenizerPosition;
     tokenizer.lineNumber = initialTokenizerLineNumber;
 
     const { length } = tokenizer;
     let linesAlreadyRead = 0;
-    await state.chunker.process(chunkSize => {
+    await chunkedSubtask(state.runtimeCtx, 100000, void 0, chunkSize => {
         const linesToRead = Math.min(molecule.num_atoms - linesAlreadyRead, chunkSize);
-        for(let i = 0; i < linesToRead; i++){
+        for (let i = 0; i < linesToRead; i++) {
             let subst_idWritten = false;
             let subst_nameWritten = false;
             let chargeWritten = false;
             let status_bitWritten = false;
-            for(let j = 0; j < numOfColumn; j++){
+            for (let j = 0; j < numOfColumn; j++) {
                 skipWhitespace(tokenizer);
                 tokenizer.tokenStart = tokenizer.position;
                 eatValue(tokenizer);
-                switch(j){
+                switch (j) {
                     case 0:
                         TokenBuilder.addUnchecked(atom_idTokens, tokenizer.tokenStart, tokenizer.tokenEnd);
                         break;
@@ -201,16 +201,16 @@ async function handleAtoms(state: State): Promise<Schema.Atoms> {
                         TokenBuilder.addUnchecked(atom_typeTokens, tokenizer.tokenStart, tokenizer.tokenEnd);
                         break;
                     default:
-                        if(hasSubst_id === true && subst_idWritten === false){
+                        if (hasSubst_id === true && subst_idWritten === false) {
                             TokenBuilder.addUnchecked(subst_idTokens, tokenizer.tokenStart, tokenizer.tokenEnd);
                             subst_idWritten = true;
-                        }else if(hasSubst_name === true && subst_nameWritten === false){
+                        } else if (hasSubst_name === true && subst_nameWritten === false) {
                             TokenBuilder.addUnchecked(subst_nameTokens, tokenizer.tokenStart, tokenizer.tokenEnd);
                             subst_nameWritten = true;
-                        }else if(hasCharge === true && chargeWritten === false){
+                        } else if (hasCharge === true && chargeWritten === false) {
                             TokenBuilder.addUnchecked(chargeTokens, tokenizer.tokenStart, tokenizer.tokenEnd);
                             chargeWritten = true;
-                        }else if(hasStatus_bit === true && status_bitWritten === false){
+                        } else if (hasStatus_bit === true && status_bitWritten === false) {
                             TokenBuilder.addUnchecked(status_bitTokens, tokenizer.tokenStart, tokenizer.tokenEnd);
                             status_bitWritten = true;
                         }
@@ -219,7 +219,7 @@ async function handleAtoms(state: State): Promise<Schema.Atoms> {
         }
         linesAlreadyRead += linesToRead;
         return linesToRead;
-    }, update => update({ message: 'Parsing...', current: tokenizer.position, max: length }));
+    }, ctx => ctx.update({ message: 'Parsing...', current: tokenizer.position, max: length }));
 
     const ret = {
         count: molecule.num_atoms,
@@ -243,7 +243,7 @@ async function handleBonds(state: State): Promise<Schema.Bonds> {
     const { tokenizer, molecule } = state;
     let hasStatus_bit = false;
 
-    while(getTokenString(tokenizer) !== '@<TRIPOS>BOND'){
+    while (getTokenString(tokenizer) !== '@<TRIPOS>BOND') {
         markLine(tokenizer);
     }
 
@@ -252,7 +252,7 @@ async function handleBonds(state: State): Promise<Schema.Bonds> {
     const firstLine = readLine(tokenizer);
     const firstLineArray = firstLine.trim().split(/\s+/g)
     const firstLineLength = firstLineArray.length;
-    if(firstLineLength === 5){
+    if (firstLineLength === 5) {
         hasStatus_bit = true;
     }
 
@@ -273,21 +273,21 @@ async function handleBonds(state: State): Promise<Schema.Bonds> {
     const undefStr = Column.Undefined(molecule.num_bonds, Column.Schema.str);
 
     let numberOfColumn = 4;
-    if(hasStatus_bit){numberOfColumn++}
+    if (hasStatus_bit) { numberOfColumn++ }
 
     tokenizer.position = initialTokenizerPosition;
     tokenizer.lineNumber = initialTokenizerLineNumber;
 
     const { length } = tokenizer;
     let linesAlreadyRead = 0;
-    await state.chunker.process(chunkSize => {
+    await chunkedSubtask(state.runtimeCtx, 100000, void 0, chunkSize => {
         const linesToRead = Math.min(molecule.num_bonds - linesAlreadyRead, chunkSize);
-        for(let i = 0; i < linesToRead; i++){
-            for(let j = 0; j < numberOfColumn; j++){
+        for (let i = 0; i < linesToRead; i++) {
+            for (let j = 0; j < numberOfColumn; j++) {
                 skipWhitespace(tokenizer);
                 tokenizer.tokenStart = tokenizer.position;
                 eatValue(tokenizer);
-                switch(j){
+                switch (j) {
                     case 0:
                         TokenBuilder.addUnchecked(bond_idTokens, tokenizer.tokenStart, tokenizer.tokenEnd);
                         break;
@@ -308,7 +308,7 @@ async function handleBonds(state: State): Promise<Schema.Bonds> {
         }
         linesAlreadyRead += linesToRead;
         return linesToRead;
-    }, update => update({ message: 'Parsing...', current: tokenizer.position, max: length }));
+    }, ctx => ctx.update({ message: 'Parsing...', current: tokenizer.position, max: length }));
 
     const ret = {
         count: molecule.num_bonds,
@@ -324,7 +324,7 @@ async function handleBonds(state: State): Promise<Schema.Bonds> {
     return ret;
 }
 
-async function parseInternal(data: string, ctx: Computation.Context): Promise<Result<Schema.File>> {
+async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<Schema.File>> {
     const tokenizer = Tokenizer(data);
 
     ctx.update({ message: 'Parsing...', current: 0, max: data.length });
@@ -342,7 +342,7 @@ async function parseInternal(data: string, ctx: Computation.Context): Promise<Re
 }
 
 export function parse(data: string) {
-    return Computation.create<Result<Schema.File>>(async ctx => {
+    return Task.create<Result<Schema.File>>('Parse MOL2', async ctx => {
         return await parseInternal(data, ctx);
     });
 }