Skip to content

Commit

Permalink
Merge pull request #1271 from thewtex/transform-io-browser
Browse files Browse the repository at this point in the history
feat(transform-io): add readTransform, writeTransform
  • Loading branch information
thewtex authored Nov 13, 2024
2 parents 5b8eb2f + 9fa2924 commit 47404ea
Show file tree
Hide file tree
Showing 2,120 changed files with 36,290 additions and 139 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
strategy:
max-parallel: 3
matrix:
package: [compress-stringify, compare-images, dicom, mesh-io, image-io, downsample]
package: [compress-stringify, compare-images, dicom, mesh-io, image-io, transform-io, downsample]

steps:
- name: Checkout
Expand Down Expand Up @@ -138,6 +138,7 @@ jobs:
# Test deps
pnpm run --aggregate-output --filter "@itk-wasm/demo-app" build
pnpm run --aggregate-output --filter "@itk-wasm/mesh-io" build
pnpm run --aggregate-output --filter "@itk-wasm/transform-io" build
pnpm run --aggregate-output --filter "@itk-wasm/image-io" build
- name: Test itk-wasm with Chrome
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import snakeCase from "../snake-case.js"
import snakeCase from '../snake-case.js'

function inputParametersPython(functionName, indent, parameter, required) {
let initResult = ''
Expand Down Expand Up @@ -54,7 +54,9 @@ function inputParametersPython(functionName, indent, parameter, required) {
methodResult += `${indent} self.model.${modelProperty}['${parameterName}'] = int(self.${inputIdentifier}.value)\n\n`
break
default:
console.error(`Unexpected interface type: ${parameter.type}`)
console.error(
`inputParametersPython: Unexpected interface type: ${parameter.type}`
)
process.exit(1)
}
return { init: initResult, method: methodResult }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import snakeCase from "../snake-case.js"
import snakeCase from '../snake-case.js'

function outputPython(functionName, prefix, indent, parameter) {
const parameterName = snakeCase(parameter.name)
let initResult = ''
let methodResult = ''
let runResult = ''

switch(parameter.type) {
switch (parameter.type) {
// case 'OUTPUT_TEXT_FILE:FILE':
// case 'OUTPUT_TEXT_STREAM':
// result += `${indent}<sl-textarea disabled name="${parameter.name}" label="${snakeCase(parameter.name)}" help-text="${parameter.description}"></sl-textarea>\n`
// result += `${indent}<sl-button variant="neutral" name="${parameter.name}-download">${snakeCase(parameter.name)}</sl-button>\n`
// result += `<br /><br />\n`
// break
// result += `${indent}<sl-textarea disabled name="${parameter.name}" label="${snakeCase(parameter.name)}" help-text="${parameter.description}"></sl-textarea>\n`
// result += `${indent}<sl-button variant="neutral" name="${parameter.name}-download">${snakeCase(parameter.name)}</sl-button>\n`
// result += `<br /><br />\n`
// break
case 'OUTPUT_BINARY_FILE:FILE':
case 'OUTPUT_BINARY_STREAM':
initResult += `${indent} ${parameterName}_download_element = js.document.querySelector('#${functionName}-outputs sl-button[name=${parameter.name}-download]')\n`
Expand Down Expand Up @@ -53,7 +53,9 @@ function outputPython(functionName, prefix, indent, parameter) {
// result += `<br /><br />\n`
// break
default:
console.error(`Unexpected interface type: ${parameter.type}`)
console.error(
`outputPython: Unexpected interface type: ${parameter.type}`
)
process.exit(1)
}
return { init: initResult, method: methodResult, run: runResult }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const demoSupportedInputTypes = new Set([
'INPUT_JSON',
'INPUT_IMAGE',
'INPUT_MESH',
'INPUT_POINT_SET'
'INPUT_POINT_SET',
'INPUT_TRANSFORM'
])
const demoSupportedOutputTypes = new Set([
'OUTPUT_TEXT_FILE',
Expand All @@ -22,7 +23,8 @@ const demoSupportedOutputTypes = new Set([
'OUTPUT_JSON',
'OUTPUT_IMAGE',
'OUTPUT_MESH',
'OUTPUT_POINT_SET'
'OUTPUT_POINT_SET',
'OUTPUT_TRANSFORM'
])

function allDemoTypesSupported(interfaceJson) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ function inputParametersDemoHtml(
case 'INPUT_JSON':
case 'INPUT_MESH':
case 'INPUT_POINT_SET':
case 'INPUT_TRANSFORM':
result += `${prefix}${indent}<label for="${parameter.name}-file"><sl-button name="${parameter.name}-file-button" variant="primary" outline onclick="this.parentElement.nextElementSibling.click()">Upload</sp-button></label><input type="file" name="${parameter.name}-file" style="display: none"/>\n`
result += `${prefix}${indent}<sl-tooltip ${tooltipContent}><sl-details id="${functionName}-${parameter.name}-details" summary="${label}: ${description}" disabled></sl-details></sl-tooltip>\n`
result += '<br /><br />\n'
Expand All @@ -76,8 +77,11 @@ function inputParametersDemoHtml(
result += `${prefix}${indent}<sl-tooltip ${tooltipContent}><itk-image-details id="${functionName}-${parameter.name}-details" summary="${label}: ${description}" disabled></itk-image-details></sl-tooltip>\n`
result += '<br /><br />\n'
break
break
default:
console.error(`Unexpected interface type: ${parameterType}`)
console.error(
`inputParametersDemoHtml: Unexpected interface type: ${parameterType}`
)
process.exit(1)
}
return result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ function inputParametersDemoTypeScript(
case 'INPUT_IMAGE':
case 'INPUT_MESH':
case 'INPUT_POINT_SET':
case 'INPUT_TRANSFORM':
result += `${indent}const ${inputIdentifier} = document.querySelector('#${functionName}Inputs input[name=${parameter.name}-file]')\n`
result += `${indent}${inputIdentifier}.addEventListener('change', async (event) => {\n`
result += `${indent}${indent}const dataTransfer = event.dataTransfer\n`
Expand Down Expand Up @@ -172,12 +173,29 @@ function inputParametersDemoTypeScript(
result += `${indent}${indent}const details = document.getElementById("${functionName}-${parameter.name}-details")\n`
result += `${indent}${indent}details.innerHTML = \`<pre>$\{globalThis.escapeHtml(JSON.stringify(pointSet, globalThis.interfaceTypeJsonReplacer, 2))}</pre>\`\n`
}
} else if (parameterType === 'INPUT_TRANSFORM') {
if (parameter.itemsExpectedMax > 1) {
result += `${indent}${indent}const readTransform = await Promise.all(Array.from(files).map(async (file) => readTransform(file)))\n`
result += `${indent}${indent}readTransform.forEach(t => t.webWorker.terminate())\n`
result += `${indent}${indent}const inputTransform = readTransform.map(t => t.transform)\n`
result += `${indent}${indent}model.${modelProperty}.set("${parameterName}", inputTransform)\n`
result += `${indent}${indent}const details = document.getElementById("${functionName}-${parameter.name}-details")\n`
result += `${indent}${indent}details.innerHTML = \`<pre>$\{globalThis.escapeHtml(JSON.stringify(inputTransform, globalThis.interfaceTypeJsonReplacer, 2))}</pre>\`\n`
} else {
result += `${indent}${indent}const { transform, webWorker } = await readTransform(files[0])\n`
result += `${indent}${indent}webWorker.terminate()\n`
result += `${indent}${indent}model.${modelProperty}.set("${parameterName}", transform)\n`
result += `${indent}${indent}const details = document.getElementById("${functionName}-${parameter.name}-details")\n`
result += `${indent}${indent}details.innerHTML = \`<pre>$\{globalThis.escapeHtml(JSON.stringify(transform, globalThis.interfaceTypeJsonReplacer, 2))}</pre>\`\n`
}
}
result += `${indent}${indent}details.disabled = false\n`
result += `${indent}})\n\n`
break
default:
console.error(`Unexpected interface type: ${parameterType}`)
console.error(
`inputParametersDemoTypeScript: Unexpected interface type: ${parameterType}`
)
process.exit(1)
}
return result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ function interfaceFunctionsDemoTypeScript(
needReadImage,
needReadMesh,
needReadPointSet,
needReadTransform,
needWriteImage,
needWriteMesh,
needWritePointSet
needWritePointSet,
needWriteTransform
} = ioPackagesNeeded(interfaceJson)
if (needReadMesh) {
if (packageName === '@itk-wasm/mesh-io') {
Expand All @@ -49,6 +51,13 @@ function interfaceFunctionsDemoTypeScript(
result += `import { readImage } from '@itk-wasm/image-io'\n`
}
}
if (needReadTransform) {
if (packageName === '@itk-wasm/transform-io') {
result += `import { readTransform } from '../../../dist/index.js'\n`
} else {
result += `import { readTransform } from '@itk-wasm/transform-io'\n`
}
}
if (needWriteMesh) {
if (packageName === '@itk-wasm/mesh-io') {
result += `import { writeMesh } from '../../../dist/index.js'\n`
Expand All @@ -70,6 +79,13 @@ function interfaceFunctionsDemoTypeScript(
result += `import { writeImage } from '@itk-wasm/image-io'\n`
}
}
if (needWriteTransform) {
if (packageName === '@itk-wasm/transform-io') {
result += `import { writeTransform } from '../../../dist/index.js'\n`
} else {
result += `import { writeTransform } from '@itk-wasm/transform-io'\n`
}
}

result += `import * as ${camelCase(bundleName)} from '../../../dist/index.js'\n`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ function ioPackagesNeeded(interfaceJson) {
let needReadMesh = false
let needReadImage = false
let needReadPointSet = false
let needReadTransform = false
const pipelineComponents = ['inputs', 'parameters']
pipelineComponents.forEach((pipelineComponent) => {
needReadMesh =
Expand All @@ -22,6 +23,12 @@ function ioPackagesNeeded(interfaceJson) {
interfaceJson[pipelineComponent].filter(
(value) => interfaceJsonTypeToInterfaceType.get(value.type) === 'Image'
).length > 0
needReadTransform =
needReadTransform ||
interfaceJson[pipelineComponent].filter(
(value) =>
interfaceJsonTypeToInterfaceType.get(value.type) === 'TransformList'
).length > 0
})
const needWriteMesh =
interfaceJson.outputs.filter(
Expand All @@ -35,13 +42,20 @@ function ioPackagesNeeded(interfaceJson) {
interfaceJson.outputs.filter(
(value) => interfaceJsonTypeToInterfaceType.get(value.type) === 'Image'
).length > 0
const needWriteTransform =
interfaceJson.outputs.filter(
(value) =>
interfaceJsonTypeToInterfaceType.get(value.type) === 'TransformList'
).length > 0
return {
needReadImage,
needReadMesh,
needReadPointSet,
needReadTransform,
needWriteImage,
needWriteMesh,
needWritePointSet
needWritePointSet,
needWriteTransform
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,24 @@ function outputDemoHtml(functionName, prefix, indent, parameter) {
result += `<br /><br />\n`
}
break
case 'OUTPUT_TRANSFORM':
{
result += `${prefix}${indent}<sl-details disabled id="${functionName}-${parameter.name}-details" summary="${camelCase(parameter.name)}: ${description}"></sl-details>\n`

result += `${prefix}${indent}<sl-select id="${functionName}-${parameter.name}-output-format" placeholder="Format">\n`
const formats = ['h5', 'txt', 'mat', 'xfm']
formats.forEach((format) => {
result += `${prefix}${indent}${indent}<sl-option value="${format}">${format}</sl-option>\n`
})
result += `${prefix}${indent}</sl-select>\n`
result += `${prefix}${indent}<sl-button variant="neutral" outline name="${parameter.name}-download" disabled>Download</sl-button>\n`
result += `<br /><br />\n`
}
break
default:
console.error(`Unexpected interface type: ${parameterType}`)
console.error(
`outputDemoHtml: Unexpected interface type: ${parameterType}`
)
process.exit(1)
}
return result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ function outputDemoRunTypeScript(functionName, prefix, indent, parameter) {
case 'OUTPUT_IMAGE':
case 'OUTPUT_MESH':
case 'OUTPUT_POINT_SET':
case 'OUTPUT_TRANSFORM':
result += `${prefix}${indent}${parameterName}OutputDownload.variant = "success"\n`
result += `${prefix}${indent}${parameterName}OutputDownload.disabled = false\n`
result += `${indent}${indent}const ${parameterName}Details = document.getElementById("${functionName}-${parameter.name}-details")\n`
Expand All @@ -62,7 +63,9 @@ function outputDemoRunTypeScript(functionName, prefix, indent, parameter) {
}
break
default:
console.error(`Unexpected interface type: ${parameter.type}`)
console.error(
`outputDemoRunTypeScript: Unexpected interface type: ${parameter.type}`
)
process.exit(1)
}
return result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,25 @@ function outputDemoTypeScript(functionName, prefix, indent, parameter) {
result += `${prefix}${indent}${indent}}\n`
result += `${prefix}${indent}})\n`
break
case 'OUTPUT_TRANSFORM':
result += `${prefix}${indent}const ${parameterName}OutputDownload = document.querySelector('#${functionName}Outputs sl-button[name=${parameter.name}-download]')\n`
result += `${prefix}${indent}${parameterName}OutputDownload.addEventListener('click', async (event) => {\n`
result += `${prefix}${indent}${indent}event.preventDefault()\n`
result += `${prefix}${indent}${indent}event.stopPropagation()\n`
result += `${prefix}${indent}${indent}if (model.outputs.has("${parameterName}")) {\n`
result += `${prefix}${indent}${indent}${indent}const ${parameterName}DownloadFormat = document.getElementById('${functionName}-${parameter.name}-output-format')\n`
result += `${prefix}${indent}${indent}${indent}const downloadFormat = ${parameterName}DownloadFormat.value || 'h5'\n`
result += `${prefix}${indent}${indent}${indent}const fileName = \`${parameterName}.\${downloadFormat}\`\n`
result += `${prefix}${indent}${indent}${indent}const { webWorker, serializedTransform } = await writeTransform(model.outputs.get("${parameterName}"), fileName)\n\n`
result += `${prefix}${indent}${indent}${indent}webWorker.terminate()\n`
result += `${prefix}${indent}${indent}${indent}globalThis.downloadFile(serializedTransform.data, fileName)\n`
result += `${prefix}${indent}${indent}}\n`
result += `${prefix}${indent}})\n`
break
default:
console.error(`Unexpected interface type: ${parameter.type}`)
console.error(
`outputDemoTypeScript: Unexpected interface type: ${parameter.type}`
)
process.exit(1)
}
return result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@
},
"devDependencies": {
"@itk-wasm/demo-app": "^0.2.0",
"@itk-wasm/image-io": "^1.2.0",
"@itk-wasm/mesh-io": "^1.2.0",
"@itk-wasm/image-io": "^1.3.1",
"@itk-wasm/mesh-io": "^1.4.2",
"@itk-wasm/transform-io": "^0.1.1",
"@types/node": "^20.2.5",
"esbuild": "^0.19.8",
"shx": "^0.3.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,39 @@ export default defineConfig({
base,
build: {
outDir: '../../../demo-app',
emptyOutDir: true,
emptyOutDir: true
},
worker: {
format: 'es'
},
optimizeDeps: {
exclude: ['itk-wasm', '@itk-wasm/image-io', '@itk-wasm/mesh-io', '@thewtex/zstddec', '@itk-viewer/io']
exclude: [
'itk-wasm',
'@itk-wasm/image-io',
'@itk-wasm/mesh-io',
'@itk-wasm/transform-io',
'@thewtex/zstddec',
'@itk-viewer/io'
]
},
plugins: [
// put lazy loaded JavaScript and Wasm bundles in dist directory
viteStaticCopy({
targets: [
{ src: '../../../dist/pipelines/*', dest: 'pipelines' },
{ src: '../../../node_modules/@itk-wasm/image-io/dist/pipelines/*.{js,wasm,wasm.zst}', dest: 'pipelines' },
{ src: '../../../node_modules/@itk-wasm/mesh-io/dist/pipelines/*.{js,wasm,wasm.zst}', dest: 'pipelines' },
],
{
src: '../../../node_modules/@itk-wasm/image-io/dist/pipelines/*.{js,wasm,wasm.zst}',
dest: 'pipelines'
},
{
src: '../../../node_modules/@itk-wasm/mesh-io/dist/pipelines/*.{js,wasm,wasm.zst}',
dest: 'pipelines'
},
{
src: '../../../node_modules/@itk-wasm/transform-io/dist/pipelines/*.{js,wasm,wasm.zst}',
dest: 'pipelines'
}
]
})
],
]
})
Loading

0 comments on commit 47404ea

Please sign in to comment.