diff --git a/src/mol-io/reader/_spec/gro.spec.ts b/src/mol-io/reader/_spec/gro.spec.ts index 888f23c83369fa8fc27e4adec486aab86003e7ab..6254be8f9d45d287f643e2d50993e8b62eb11bbe 100644 --- a/src/mol-io/reader/_spec/gro.spec.ts +++ b/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) diff --git a/src/mol-io/reader/_spec/mol2.spec.ts b/src/mol-io/reader/_spec/mol2.spec.ts index c329f61a4e5c66a28588d8424eb4327dbafb25ff..43244780636af6fbcd75010522ba9405b75ca2ff 100644 --- a/src/mol-io/reader/_spec/mol2.spec.ts +++ b/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); } diff --git a/src/mol-io/reader/common/text/tokenizer.ts b/src/mol-io/reader/common/text/tokenizer.ts index 15a8492c74ffd939be708e62e4858a8129291106..60f14c1b135bfca7d215f3a3d8939997b4ec2ae5 100644 --- a/src/mol-io/reader/common/text/tokenizer.ts +++ b/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; } diff --git a/src/mol-io/reader/gro/parser.ts b/src/mol-io/reader/gro/parser.ts index d1c71ec315c3f98d47f45692838c9dfa462d4142..eee90135b4a588a565b25ee1f5354f150d987f3b 100644 --- a/src/mol-io/reader/gro/parser.ts +++ b/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); }); } diff --git a/src/mol-io/reader/mol2/parser.ts b/src/mol-io/reader/mol2/parser.ts index f807f4ff7b78d1c3f7a051fbba88a0a69c6216de..32126acb9050dbf33e490f2d9ffed2ca98a5f76c 100644 --- a/src/mol-io/reader/mol2/parser.ts +++ b/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); }); }