Skip to content

Commit

Permalink
feat(pstate): Generate TS bindings for apply-presentation-state-to-im…
Browse files Browse the repository at this point in the history
…age operation

Update bindgen script to add the following import statement at the
beginning of Result type declaration files:
```
import { ... } from 'itk-wasm'
```
This is required for the output types that are defined in itk-wasm.

After the above modification, generate bindings for the
apply-presentation-state-to-image operation.
  • Loading branch information
jadh4v committed Oct 27, 2022
1 parent fa1bdca commit 5211a78
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 0 deletions.
12 changes: 12 additions & 0 deletions dist/dicom/src/ApplyPresentationStateToImageNodeResult.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Image } from 'itk-wasm'

interface ApplyPresentationStateToImageNodeResult {
/** Output overlay information */
presentationStateOutStream: string

/** Output image */
outputImage: Image

}

export default ApplyPresentationStateToImageNodeResult
25 changes: 25 additions & 0 deletions dist/dicom/src/ApplyPresentationStateToImageOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
interface ApplyPresentationStateToImageOptions {
/** filename: string. Process using presentation state file */
presentationStateFile?: Uint8Array

/** filename: string. Process using settings from configuration file */
configFile?: string

/** frame: integer. Process using image frame f (default: 1) */
frame?: number

/** get presentation state information in text stream (default: ON). */
presentationStateOutput?: boolean

/** get resulting image as bitmap output stream (default: ON). */
bitmapOutput?: boolean

/** save image as PGM (default) */
pgm?: boolean

/** save image as DICOM secondary capture */
dicom?: boolean

}

export default ApplyPresentationStateToImageOptions
15 changes: 15 additions & 0 deletions dist/dicom/src/ApplyPresentationStateToImageResult.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Image } from 'itk-wasm'

interface ApplyPresentationStateToImageResult {
/** WebWorker used for computation */
webWorker: Worker | null

/** Output overlay information */
presentationStateOutStream: string

/** Output image */
outputImage: Image

}

export default ApplyPresentationStateToImageResult
85 changes: 85 additions & 0 deletions dist/dicom/src/applyPresentationStateToImage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import {
TextStream,
Image,
InterfaceTypes,
PipelineInput,
runPipeline
} from 'itk-wasm'

import ApplyPresentationStateToImageOptions from './ApplyPresentationStateToImageOptions.js'
import ApplyPresentationStateToImageResult from './ApplyPresentationStateToImageResult.js'

/**
* Apply a presentation state to a given DICOM image and render output as pgm bitmap or dicom file.
*
* @param {Uint8Array} imageIn - Input DICOM file
*
* @returns {Promise<ApplyPresentationStateToImageResult>} - result object
*/
async function applyPresentationStateToImage(
webWorker: null | Worker,
imageIn: Uint8Array,
options: ApplyPresentationStateToImageOptions = {})
: Promise<ApplyPresentationStateToImageResult> {

const desiredOutputs = [
{ type: InterfaceTypes.TextStream },
{ type: InterfaceTypes.Image },
]
const inputs: [ PipelineInput ] = [
{ type: InterfaceTypes.BinaryFile, data: { data: imageIn, path: "file0" } },
]

const args = []
// Inputs
args.push('file0')
// Outputs
args.push('0')
args.push('1')
// Options
args.push('--memory-io')
if (options.presentationStateFile) {
const inputFile = 'file' + inputs.length.toString()
inputs.push({ type: InterfaceTypes.BinaryFile, data: { data: options.presentationStateFile, path: inputFile } })
args.push('--presentation-state-file', inputFile)
}
if (options.configFile) {
args.push('--config-file', options.configFile.toString())
}
if (options.frame) {
args.push('--frame', options.frame.toString())
}
if (options.presentationStateOutput) {
args.push('--presentation-state-output')
}
if (options.bitmapOutput) {
args.push('--bitmap-output')
}
if (options.pgm) {
args.push('--pgm')
}
if (options.dicom) {
args.push('--dicom')
}

const pipelinePath = 'apply-presentation-state-to-image'

const {
webWorker: usedWebWorker,
returnValue,
stderr,
outputs
} = await runPipeline(webWorker, pipelinePath, args, desiredOutputs, inputs)
if (returnValue !== 0) {
throw new Error(stderr)
}

const result = {
webWorker: usedWebWorker as Worker,
presentationStateOutStream: (outputs[0].data as TextStream).data,
outputImage: outputs[1].data as Image,
}
return result
}

export default applyPresentationStateToImage
84 changes: 84 additions & 0 deletions dist/dicom/src/applyPresentationStateToImageNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import {
TextStream,
Image,
InterfaceTypes,
PipelineInput,
runPipelineNode
} from 'itk-wasm'

import ApplyPresentationStateToImageOptions from './ApplyPresentationStateToImageOptions.js'
import ApplyPresentationStateToImageNodeResult from './ApplyPresentationStateToImageNodeResult.js'


import path from 'path'

/**
* Apply a presentation state to a given DICOM image and render output as pgm bitmap or dicom file.
*
* @param {Uint8Array} imageIn - Input DICOM file
*
* @returns {Promise<ApplyPresentationStateToImageNodeResult>} - result object
*/
async function applyPresentationStateToImageNode( imageIn: Uint8Array,
options: ApplyPresentationStateToImageOptions = {})
: Promise<ApplyPresentationStateToImageNodeResult> {

const desiredOutputs = [
{ type: InterfaceTypes.TextStream },
{ type: InterfaceTypes.Image },
]
const inputs: [ PipelineInput ] = [
{ type: InterfaceTypes.BinaryFile, data: { data: imageIn, path: "file0" } },
]

const args = []
// Inputs
args.push('file0')
// Outputs
args.push('0')
args.push('1')
// Options
args.push('--memory-io')
if (options.presentationStateFile) {
const inputFile = 'file' + inputs.length.toString()
inputs.push({ type: InterfaceTypes.BinaryFile, data: { data: options.presentationStateFile, path: inputFile } })
args.push('--presentation-state-file', inputFile)
}
if (options.configFile) {
args.push('--config-file', options.configFile.toString())
}
if (options.frame) {
args.push('--frame', options.frame.toString())
}
if (options.presentationStateOutput) {
args.push('--presentation-state-output')
}
if (options.bitmapOutput) {
args.push('--bitmap-output')
}
if (options.pgm) {
args.push('--pgm')
}
if (options.dicom) {
args.push('--dicom')
}

const pipelinePath = path.join(path.dirname(import.meta.url.substring(7)), 'pipelines', 'apply-presentation-state-to-image')

const {
returnValue,
stderr,
outputs
} = await runPipelineNode(pipelinePath, args, desiredOutputs, inputs)
if (returnValue !== 0) {
throw new Error(stderr)
}

const result = {
presentationStateOutStream: (outputs[0].data as TextStream).data,
outputImage: outputs[1].data as Image,
}
return result
}

export default applyPresentationStateToImageNode
10 changes: 10 additions & 0 deletions dist/dicom/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@


import ApplyPresentationStateToImageResult from './ApplyPresentationStateToImageResult.js'
export type { ApplyPresentationStateToImageResult }

import ApplyPresentationStateToImageOptions from './ApplyPresentationStateToImageOptions.js'
export type { ApplyPresentationStateToImageOptions }

import applyPresentationStateToImage from './applyPresentationStateToImage.js'
export { applyPresentationStateToImage }


import ReadDicomEncapsulatedPdfResult from './ReadDicomEncapsulatedPdfResult.js'
export type { ReadDicomEncapsulatedPdfResult }

Expand Down
10 changes: 10 additions & 0 deletions dist/dicom/src/indexNode.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@


import ApplyPresentationStateToImageNodeResult from './ApplyPresentationStateToImageNodeResult.js'
export type { ApplyPresentationStateToImageNodeResult }

import ApplyPresentationStateToImageOptions from './ApplyPresentationStateToImageOptions.js'
export type { ApplyPresentationStateToImageOptions }

import applyPresentationStateToImageNode from './applyPresentationStateToImageNode.js'
export { applyPresentationStateToImageNode }


import ReadDicomEncapsulatedPdfNodeResult from './ReadDicomEncapsulatedPdfNodeResult.js'
export type { ReadDicomEncapsulatedPdfNodeResult }

Expand Down
15 changes: 15 additions & 0 deletions src/itk-wasm-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const program = new Command()

const defaultImageTag = '20220906-f5d801e2'

// Array of types that will require an import from itk-wasm
const typesRequireImport = ['Image']

function processCommonOptions() {
const options = program.opts()

Expand Down Expand Up @@ -294,6 +297,10 @@ function typescriptBindings(srcOutputDir, buildDir, wasmBinaries, forNode=false)
if (!forNode) {
resultContent += ` /** WebWorker used for computation */\n webWorker: Worker | null\n\n`
}

// track unique output types in this set
const importTypes = new Set()

interfaceJson.outputs.forEach((output) => {
if (!interfaceJsonTypeToTypeScriptType.has(output.type)) {

Expand All @@ -302,8 +309,16 @@ function typescriptBindings(srcOutputDir, buildDir, wasmBinaries, forNode=false)
}
resultContent += ` /** ${output.description} */\n`
const outputType = interfaceJsonTypeToTypeScriptType.get(output.type)
if(typesRequireImport.includes(outputType)) {
importTypes.add(outputType)
}
resultContent += ` ${camelCase(output.name)}: ${outputType}\n\n`
})

// Insert the import statement in the beginning for the file.
if(importTypes.size !== 0)
resultContent = `import { ${Array.from(importTypes).join(',')} } from 'itk-wasm'\n\n` + resultContent;

resultContent += `}\n\nexport default ${modulePascalCase}${nodeText}Result\n`
fs.writeFileSync(path.join(srcOutputDir, `${modulePascalCase}${nodeText}Result.ts`), resultContent)
indexContent += `\n\nimport ${modulePascalCase}${nodeText}Result from './${modulePascalCase}${nodeText}Result.js'\n`
Expand Down

0 comments on commit 5211a78

Please sign in to comment.