From 1b514a65977e268cdb1a9e233c43ad024a6df234 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Sun, 26 Nov 2023 15:51:46 -0500 Subject: [PATCH] feat(mesh-io): add read-mesh-node --- packages/mesh-io/CMakeLists.txt | 2 +- packages/mesh-io/typescript/package.json | 1 + packages/mesh-io/typescript/pnpm-lock.yaml | 7 ++ packages/mesh-io/typescript/src/index-node.ts | 31 ++++--- packages/mesh-io/typescript/src/index.ts | 20 +++++ .../typescript/src/mesh-io-index-node.ts | 35 ++++++++ .../mesh-io/typescript/src/read-mesh-node.ts | 72 +++++++++++++++ .../typescript/src/read-mesh-options.ts | 6 ++ .../src/wasm-zstd-read-mesh-node-result.ts | 14 +++ .../src/wasm-zstd-read-mesh-node.ts | 78 ++++++++++++++++ .../src/wasm-zstd-read-mesh-options.ts | 9 ++ .../src/wasm-zstd-read-mesh-result.ts | 17 ++++ .../typescript/src/wasm-zstd-read-mesh.ts | 85 ++++++++++++++++++ .../src/wasm-zstd-write-mesh-node-result.ts | 12 +++ .../src/wasm-zstd-write-mesh-node.ts | 84 ++++++++++++++++++ .../src/wasm-zstd-write-mesh-options.ts | 15 ++++ .../src/wasm-zstd-write-mesh-result.ts | 17 ++++ .../typescript/src/wasm-zstd-write-mesh.ts | 88 +++++++++++++++++++ .../test/browser/demo-app/index.html | 75 ++++++++++++++++ .../typescript/test/browser/demo-app/index.ts | 2 + .../test/node/read-mesh-node-test.js | 23 +++++ test/node/io/mesh/readMeshLocalFileTest.js | 18 ---- 22 files changed, 679 insertions(+), 32 deletions(-) create mode 100644 packages/mesh-io/typescript/src/mesh-io-index-node.ts create mode 100644 packages/mesh-io/typescript/src/read-mesh-node.ts create mode 100644 packages/mesh-io/typescript/src/read-mesh-options.ts create mode 100644 packages/mesh-io/typescript/src/wasm-zstd-read-mesh-node-result.ts create mode 100644 packages/mesh-io/typescript/src/wasm-zstd-read-mesh-node.ts create mode 100644 packages/mesh-io/typescript/src/wasm-zstd-read-mesh-options.ts create mode 100644 packages/mesh-io/typescript/src/wasm-zstd-read-mesh-result.ts create mode 100644 packages/mesh-io/typescript/src/wasm-zstd-read-mesh.ts create mode 100644 packages/mesh-io/typescript/src/wasm-zstd-write-mesh-node-result.ts create mode 100644 packages/mesh-io/typescript/src/wasm-zstd-write-mesh-node.ts create mode 100644 packages/mesh-io/typescript/src/wasm-zstd-write-mesh-options.ts create mode 100644 packages/mesh-io/typescript/src/wasm-zstd-write-mesh-result.ts create mode 100644 packages/mesh-io/typescript/src/wasm-zstd-write-mesh.ts create mode 100644 packages/mesh-io/typescript/test/node/read-mesh-node-test.js delete mode 100644 test/node/io/mesh/readMeshLocalFileTest.js diff --git a/packages/mesh-io/CMakeLists.txt b/packages/mesh-io/CMakeLists.txt index 1636f9dda..6465a325b 100644 --- a/packages/mesh-io/CMakeLists.txt +++ b/packages/mesh-io/CMakeLists.txt @@ -54,7 +54,7 @@ set(meshios_WebAssemblyInterface itkWasmMeshIO itkWasmZstdMeshIO) set(meshio_id_itkWasmMeshIO 8) set(meshio_kebab_itkWasmMeshIO "wasm") set(meshio_id_itkWasmZstdMeshIO 9) -set(meshio_kebab_itkWasmZstdMeshIO "wasm-ztd") +set(meshio_kebab_itkWasmZstdMeshIO "wasm-zstd") set(ITK_NO_MESHIO_FACTORY_REGISTER_MANAGER 1) set(MeshIOIndex_ARRAY "") diff --git a/packages/mesh-io/typescript/package.json b/packages/mesh-io/typescript/package.json index c01e18829..3e3b00a09 100644 --- a/packages/mesh-io/typescript/package.json +++ b/packages/mesh-io/typescript/package.json @@ -38,6 +38,7 @@ "devDependencies": { "@itk-wasm/image-io": "^0.2.0", "@shoelace-style/shoelace": "^2.5.2", + "@types/mime-types": "^2.1.4", "@types/node": "^20.2.5", "ava": "^5.3.1", "esbuild": "^0.19.5", diff --git a/packages/mesh-io/typescript/pnpm-lock.yaml b/packages/mesh-io/typescript/pnpm-lock.yaml index 76803c57f..fba6e393d 100644 --- a/packages/mesh-io/typescript/pnpm-lock.yaml +++ b/packages/mesh-io/typescript/pnpm-lock.yaml @@ -16,6 +16,9 @@ devDependencies: '@shoelace-style/shoelace': specifier: ^2.5.2 version: 2.12.0(@types/react@18.2.38) + '@types/mime-types': + specifier: ^2.1.4 + version: 2.1.4 '@types/node': specifier: ^20.2.5 version: 20.10.0 @@ -541,6 +544,10 @@ packages: /@types/emscripten@1.39.10: resolution: {integrity: sha512-TB/6hBkYQJxsZHSqyeuO1Jt0AB/bW6G7rHt9g7lML7SOF6lbgcHvw/Lr+69iqN0qxgXLhWKScAon73JNnptuDw==} + /@types/mime-types@2.1.4: + resolution: {integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==} + dev: true + /@types/node@20.10.0: resolution: {integrity: sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==} dependencies: diff --git a/packages/mesh-io/typescript/src/index-node.ts b/packages/mesh-io/typescript/src/index-node.ts index 402dcde96..c665b5f33 100644 --- a/packages/mesh-io/typescript/src/index-node.ts +++ b/packages/mesh-io/typescript/src/index-node.ts @@ -1,4 +1,9 @@ -// Generated file. To retain edits, remove this comment. + +import ReadMeshOptions from './read-mesh-options.js' +export type { ReadMeshOptions } + +import readMeshNode from './read-mesh-node.js' +export { readMeshNode } @@ -182,24 +187,24 @@ import wasmWriteMeshNode from './wasm-write-mesh-node.js' export { wasmWriteMeshNode } -import WasmZtdReadMeshNodeResult from './wasm-ztd-read-mesh-node-result.js' -export type { WasmZtdReadMeshNodeResult } +import WasmZstdReadMeshNodeResult from './wasm-zstd-read-mesh-node-result.js' +export type { WasmZstdReadMeshNodeResult } -import WasmZtdReadMeshOptions from './wasm-ztd-read-mesh-options.js' -export type { WasmZtdReadMeshOptions } +import WasmZstdReadMeshOptions from './wasm-zstd-read-mesh-options.js' +export type { WasmZstdReadMeshOptions } -import wasmZtdReadMeshNode from './wasm-ztd-read-mesh-node.js' -export { wasmZtdReadMeshNode } +import wasmZstdReadMeshNode from './wasm-zstd-read-mesh-node.js' +export { wasmZstdReadMeshNode } -import WasmZtdWriteMeshNodeResult from './wasm-ztd-write-mesh-node-result.js' -export type { WasmZtdWriteMeshNodeResult } +import WasmZstdWriteMeshNodeResult from './wasm-zstd-write-mesh-node-result.js' +export type { WasmZstdWriteMeshNodeResult } -import WasmZtdWriteMeshOptions from './wasm-ztd-write-mesh-options.js' -export type { WasmZtdWriteMeshOptions } +import WasmZstdWriteMeshOptions from './wasm-zstd-write-mesh-options.js' +export type { WasmZstdWriteMeshOptions } -import wasmZtdWriteMeshNode from './wasm-ztd-write-mesh-node.js' -export { wasmZtdWriteMeshNode } +import wasmZstdWriteMeshNode from './wasm-zstd-write-mesh-node.js' +export { wasmZstdWriteMeshNode } export type { JsonCompatible } from 'itk-wasm' export type { Mesh } from 'itk-wasm' diff --git a/packages/mesh-io/typescript/src/index.ts b/packages/mesh-io/typescript/src/index.ts index fce17dec9..93cf3b8b9 100644 --- a/packages/mesh-io/typescript/src/index.ts +++ b/packages/mesh-io/typescript/src/index.ts @@ -184,6 +184,26 @@ import wasmWriteMesh from './wasm-write-mesh.js' export { wasmWriteMesh } +import WasmZstdReadMeshResult from './wasm-zstd-read-mesh-result.js' +export type { WasmZstdReadMeshResult } + +import WasmZstdReadMeshOptions from './wasm-zstd-read-mesh-options.js' +export type { WasmZstdReadMeshOptions } + +import wasmZstdReadMesh from './wasm-zstd-read-mesh.js' +export { wasmZstdReadMesh } + + +import WasmZstdWriteMeshResult from './wasm-zstd-write-mesh-result.js' +export type { WasmZstdWriteMeshResult } + +import WasmZstdWriteMeshOptions from './wasm-zstd-write-mesh-options.js' +export type { WasmZstdWriteMeshOptions } + +import wasmZstdWriteMesh from './wasm-zstd-write-mesh.js' +export { wasmZstdWriteMesh } + + import WasmZtdReadMeshResult from './wasm-ztd-read-mesh-result.js' export type { WasmZtdReadMeshResult } diff --git a/packages/mesh-io/typescript/src/mesh-io-index-node.ts b/packages/mesh-io/typescript/src/mesh-io-index-node.ts new file mode 100644 index 000000000..33206c1f4 --- /dev/null +++ b/packages/mesh-io/typescript/src/mesh-io-index-node.ts @@ -0,0 +1,35 @@ +import vtkPolyDataReadMeshNode from './vtk-poly-data-read-mesh-node.js' +import vtkPolyDataWriteMeshNode from './vtk-poly-data-write-mesh-node.js' +import objReadMeshNode from './obj-read-mesh-node.js' +import objWriteMeshNode from './obj-write-mesh-node.js' +import stlReadMeshNode from './stl-read-mesh-node.js' +import stlWriteMeshNode from './stl-write-mesh-node.js' +import offReadMeshNode from './off-read-mesh-node.js' +import offWriteMeshNode from './off-write-mesh-node.js' +import wasmReadMeshNode from './wasm-read-mesh-node.js' +import wasmWriteMeshNode from './wasm-write-mesh-node.js' +import wasmZstdReadMeshNode from './wasm-zstd-read-mesh-node.js' +import wasmZstdWriteMeshNode from './wasm-zstd-write-mesh-node.js' +import swcReadMeshNode from './swc-read-mesh-node.js' +import swcWriteMeshNode from './swc-write-mesh-node.js' +import byuReadMeshNode from './byu-read-mesh-node.js' +import byuWriteMeshNode from './byu-write-mesh-node.js' +import freeSurferAsciiReadMeshNode from './free-surfer-ascii-read-mesh-node.js' +import freeSurferAsciiWriteMeshNode from './free-surfer-ascii-write-mesh-node.js' +import freeSurferBinaryReadMeshNode from './free-surfer-binary-read-mesh-node.js' +import freeSurferBinaryWriteMeshNode from './free-surfer-binary-write-mesh-node.js' + +const meshIoIndexNode = new Map([ + ['vtk', [vtkPolyDataReadMeshNode, vtkPolyDataWriteMeshNode]], + ['obj', [objReadMeshNode, objWriteMeshNode]], + ['stl', [stlReadMeshNode, stlWriteMeshNode]], + ['off', [offReadMeshNode, offWriteMeshNode]], + ['wasm', [wasmReadMeshNode, wasmWriteMeshNode]], + ['wasm-zst', [wasmZstdReadMeshNode, wasmZstdWriteMeshNode]], + ['swc', [swcReadMeshNode, swcWriteMeshNode]], + ['byu', [byuReadMeshNode, byuWriteMeshNode]], + ['free-surfer-ascii', [freeSurferAsciiReadMeshNode, freeSurferAsciiWriteMeshNode]], + ['free-surfer-binary', [freeSurferBinaryReadMeshNode, freeSurferBinaryWriteMeshNode]], +]) + +export default meshIoIndexNode diff --git a/packages/mesh-io/typescript/src/read-mesh-node.ts b/packages/mesh-io/typescript/src/read-mesh-node.ts new file mode 100644 index 000000000..bc6a18182 --- /dev/null +++ b/packages/mesh-io/typescript/src/read-mesh-node.ts @@ -0,0 +1,72 @@ +import path from 'path' +import mime from 'mime-types' + +import { + Mesh, + getFileExtension, +} from 'itk-wasm' + +import mimeToMeshIo from './mime-to-mesh-io.js' +import extensionToMeshIo from './extension-to-mesh-io.js' +import meshIoIndexNode from './mesh-io-index-node.js' + +import ReadMeshOptions from './read-mesh-options.js' + +interface ReaderResult { + couldRead: boolean, + mesh: Mesh +} +interface ReaderOptions { + /** Only read image metadata -- do not read pixel data. */ + informationOnly?: boolean +} +type Reader = (serializedMesh: string, options: ReaderOptions) => Promise + + +/** + * Read a mesh file format and convert it to the itk-wasm file format + * + * @param {string} serializedMesh - Path to input mesh serialized in the file format + * @param {ReadMeshOptions} options - options to cast resulting mesh type or to only read mesh metadata + * + * @returns {Promise} - Mesh result + */ +async function readMeshNode( + serializedMesh: string, + options: ReadMeshOptions = {} +) : Promise { + + const absoluteFilePath = path.resolve(serializedMesh) + const mimeType = mime.lookup(absoluteFilePath) + const extension = getFileExtension(absoluteFilePath) + + let io = null + if (mimeType && mimeToMeshIo.has(mimeType)) { + io = mimeToMeshIo.get(mimeType) + } else if (extensionToMeshIo.has(extension)) { + io = extensionToMeshIo.get(extension) + } else { + for (const readerWriter of meshIoIndexNode.values()) { + if (readerWriter[0] !== null) { + let { couldRead, mesh } = await (readerWriter[0] as Reader)(absoluteFilePath, { informationOnly: options.informationOnly }) + if (couldRead) { + return mesh + } + } + } + } + if (io === null ) { + throw Error('Could not find IO for: ' + absoluteFilePath) + } + const readerWriter = meshIoIndexNode.get(io as string) + + const reader = (readerWriter as Array)[0] + let { couldRead, mesh } = await reader(absoluteFilePath, { informationOnly: options.informationOnly }) + if (!couldRead) { + throw Error('Could not read: ' + absoluteFilePath) + } + + return mesh +} + +export default readMeshNode diff --git a/packages/mesh-io/typescript/src/read-mesh-options.ts b/packages/mesh-io/typescript/src/read-mesh-options.ts new file mode 100644 index 000000000..e3169fb1d --- /dev/null +++ b/packages/mesh-io/typescript/src/read-mesh-options.ts @@ -0,0 +1,6 @@ +interface ReadMeshOptions { + /** Only read mesh metadata -- do not read pixel data. */ + informationOnly?: boolean +} + +export default ReadMeshOptions diff --git a/packages/mesh-io/typescript/src/wasm-zstd-read-mesh-node-result.ts b/packages/mesh-io/typescript/src/wasm-zstd-read-mesh-node-result.ts new file mode 100644 index 000000000..e60945a91 --- /dev/null +++ b/packages/mesh-io/typescript/src/wasm-zstd-read-mesh-node-result.ts @@ -0,0 +1,14 @@ +// Generated file. To retain edits, remove this comment. + +import { JsonCompatible, Mesh } from 'itk-wasm' + +interface WasmZstdReadMeshNodeResult { + /** Whether the input could be read. If false, the output mesh is not valid. */ + couldRead: JsonCompatible + + /** Output mesh */ + mesh: Mesh + +} + +export default WasmZstdReadMeshNodeResult diff --git a/packages/mesh-io/typescript/src/wasm-zstd-read-mesh-node.ts b/packages/mesh-io/typescript/src/wasm-zstd-read-mesh-node.ts new file mode 100644 index 000000000..686bf0a90 --- /dev/null +++ b/packages/mesh-io/typescript/src/wasm-zstd-read-mesh-node.ts @@ -0,0 +1,78 @@ +// Generated file. To retain edits, remove this comment. + +import { + JsonCompatible, + Mesh, + InterfaceTypes, + PipelineOutput, + PipelineInput, + runPipelineNode +} from 'itk-wasm' + +import WasmZstdReadMeshOptions from './wasm-zstd-read-mesh-options.js' +import WasmZstdReadMeshNodeResult from './wasm-zstd-read-mesh-node-result.js' + +import path from 'path' + +/** + * Read a mesh file format and convert it to the itk-wasm file format + * + * @param {string} serializedMesh - Input mesh serialized in the file format + * @param {WasmZstdReadMeshOptions} options - options object + * + * @returns {Promise} - result object + */ +async function wasmZstdReadMeshNode( + serializedMesh: string, + options: WasmZstdReadMeshOptions = {} +) : Promise { + + const mountDirs: Set = new Set() + + const desiredOutputs: Array = [ + { type: InterfaceTypes.JsonCompatible }, + { type: InterfaceTypes.Mesh }, + ] + + mountDirs.add(path.dirname(serializedMesh as string)) + const inputs: Array = [ + ] + + const args = [] + // Inputs + const serializedMeshName = serializedMesh + args.push(serializedMeshName) + mountDirs.add(path.dirname(serializedMeshName)) + + // Outputs + const couldReadName = '0' + args.push(couldReadName) + + const meshName = '1' + args.push(meshName) + + // Options + args.push('--memory-io') + if (typeof options.informationOnly !== "undefined") { + options.informationOnly && args.push('--information-only') + } + + const pipelinePath = path.join(path.dirname(import.meta.url.substring(7)), 'pipelines', 'wasm-zstd-read-mesh') + + const { + returnValue, + stderr, + outputs + } = await runPipelineNode(pipelinePath, args, desiredOutputs, inputs, mountDirs) + if (returnValue !== 0 && stderr !== "") { + throw new Error(stderr) + } + + const result = { + couldRead: outputs[0]?.data as JsonCompatible, + mesh: outputs[1]?.data as Mesh, + } + return result +} + +export default wasmZstdReadMeshNode diff --git a/packages/mesh-io/typescript/src/wasm-zstd-read-mesh-options.ts b/packages/mesh-io/typescript/src/wasm-zstd-read-mesh-options.ts new file mode 100644 index 000000000..80f1be963 --- /dev/null +++ b/packages/mesh-io/typescript/src/wasm-zstd-read-mesh-options.ts @@ -0,0 +1,9 @@ +// Generated file. To retain edits, remove this comment. + +interface WasmZstdReadMeshOptions { + /** Only read image metadata -- do not read pixel data. */ + informationOnly?: boolean + +} + +export default WasmZstdReadMeshOptions diff --git a/packages/mesh-io/typescript/src/wasm-zstd-read-mesh-result.ts b/packages/mesh-io/typescript/src/wasm-zstd-read-mesh-result.ts new file mode 100644 index 000000000..82bcf5042 --- /dev/null +++ b/packages/mesh-io/typescript/src/wasm-zstd-read-mesh-result.ts @@ -0,0 +1,17 @@ +// Generated file. To retain edits, remove this comment. + +import { JsonCompatible, Mesh } from 'itk-wasm' + +interface WasmZstdReadMeshResult { + /** WebWorker used for computation */ + webWorker: Worker | null + + /** Whether the input could be read. If false, the output mesh is not valid. */ + couldRead: JsonCompatible + + /** Output mesh */ + mesh: Mesh + +} + +export default WasmZstdReadMeshResult diff --git a/packages/mesh-io/typescript/src/wasm-zstd-read-mesh.ts b/packages/mesh-io/typescript/src/wasm-zstd-read-mesh.ts new file mode 100644 index 000000000..8bf068851 --- /dev/null +++ b/packages/mesh-io/typescript/src/wasm-zstd-read-mesh.ts @@ -0,0 +1,85 @@ +// Generated file. To retain edits, remove this comment. + +import { + BinaryFile, + JsonCompatible, + Mesh, + InterfaceTypes, + PipelineOutput, + PipelineInput, + runPipeline +} from 'itk-wasm' + +import WasmZstdReadMeshOptions from './wasm-zstd-read-mesh-options.js' +import WasmZstdReadMeshResult from './wasm-zstd-read-mesh-result.js' + +import { getPipelinesBaseUrl } from './pipelines-base-url.js' +import { getPipelineWorkerUrl } from './pipeline-worker-url.js' + +/** + * Read a mesh file format and convert it to the itk-wasm file format + * + * @param {File | BinaryFile} serializedMesh - Input mesh serialized in the file format + * @param {WasmZstdReadMeshOptions} options - options object + * + * @returns {Promise} - result object + */ +async function wasmZstdReadMesh( + webWorker: null | Worker | boolean, + serializedMesh: File | BinaryFile, + options: WasmZstdReadMeshOptions = {} +) : Promise { + + const desiredOutputs: Array = [ + { type: InterfaceTypes.JsonCompatible }, + { type: InterfaceTypes.Mesh }, + ] + + let serializedMeshFile = serializedMesh + if (serializedMesh instanceof File) { + const serializedMeshBuffer = await serializedMesh.arrayBuffer() + serializedMeshFile = { path: serializedMesh.name, data: new Uint8Array(serializedMeshBuffer) } + } + const inputs: Array = [ + { type: InterfaceTypes.BinaryFile, data: serializedMeshFile as BinaryFile }, + ] + + const args = [] + // Inputs + const serializedMeshName = (serializedMeshFile as BinaryFile).path + args.push(serializedMeshName) + + // Outputs + const couldReadName = '0' + args.push(couldReadName) + + const meshName = '1' + args.push(meshName) + + // Options + args.push('--memory-io') + if (typeof options.informationOnly !== "undefined") { + options.informationOnly && args.push('--information-only') + } + + const pipelinePath = 'wasm-zstd-read-mesh' + + const { + webWorker: usedWebWorker, + returnValue, + stderr, + outputs + } = await runPipeline(webWorker, pipelinePath, args, desiredOutputs, inputs, { pipelineBaseUrl: getPipelinesBaseUrl(), pipelineWorkerUrl: getPipelineWorkerUrl() }) + if (returnValue !== 0 && stderr !== "") { + throw new Error(stderr) + } + + const result = { + webWorker: usedWebWorker as Worker, + couldRead: outputs[0]?.data as JsonCompatible, + mesh: outputs[1]?.data as Mesh, + } + return result +} + +export default wasmZstdReadMesh diff --git a/packages/mesh-io/typescript/src/wasm-zstd-write-mesh-node-result.ts b/packages/mesh-io/typescript/src/wasm-zstd-write-mesh-node-result.ts new file mode 100644 index 000000000..d717dfeb3 --- /dev/null +++ b/packages/mesh-io/typescript/src/wasm-zstd-write-mesh-node-result.ts @@ -0,0 +1,12 @@ +// Generated file. To retain edits, remove this comment. + +import { JsonCompatible } from 'itk-wasm' + +interface WasmZstdWriteMeshNodeResult { + /** Whether the input could be written. If false, the output mesh is not valid. */ + couldWrite: JsonCompatible + + /** Output mesh */ +} + +export default WasmZstdWriteMeshNodeResult diff --git a/packages/mesh-io/typescript/src/wasm-zstd-write-mesh-node.ts b/packages/mesh-io/typescript/src/wasm-zstd-write-mesh-node.ts new file mode 100644 index 000000000..70501d169 --- /dev/null +++ b/packages/mesh-io/typescript/src/wasm-zstd-write-mesh-node.ts @@ -0,0 +1,84 @@ +// Generated file. To retain edits, remove this comment. + +import { + Mesh, + JsonCompatible, + InterfaceTypes, + PipelineOutput, + PipelineInput, + runPipelineNode +} from 'itk-wasm' + +import WasmZstdWriteMeshOptions from './wasm-zstd-write-mesh-options.js' +import WasmZstdWriteMeshNodeResult from './wasm-zstd-write-mesh-node-result.js' + +import path from 'path' + +/** + * Write an itk-wasm file format converted to an mesh file format + * + * @param {Mesh} mesh - Input mesh + * @param {string} serializedMesh - Output mesh + * @param {WasmZstdWriteMeshOptions} options - options object + * + * @returns {Promise} - result object + */ +async function wasmZstdWriteMeshNode( + mesh: Mesh, + serializedMesh: string, + options: WasmZstdWriteMeshOptions = {} +) : Promise { + + const mountDirs: Set = new Set() + + const desiredOutputs: Array = [ + { type: InterfaceTypes.JsonCompatible }, + ] + + const inputs: Array = [ + { type: InterfaceTypes.Mesh, data: mesh }, + ] + + const args = [] + // Inputs + const meshName = '0' + args.push(meshName) + + // Outputs + const couldWriteName = '0' + args.push(couldWriteName) + + const serializedMeshName = serializedMesh + args.push(serializedMeshName) + mountDirs.add(path.dirname(serializedMeshName)) + + // Options + args.push('--memory-io') + if (typeof options.informationOnly !== "undefined") { + options.informationOnly && args.push('--information-only') + } + if (typeof options.useCompression !== "undefined") { + options.useCompression && args.push('--use-compression') + } + if (typeof options.binaryFileType !== "undefined") { + options.binaryFileType && args.push('--binary-file-type') + } + + const pipelinePath = path.join(path.dirname(import.meta.url.substring(7)), 'pipelines', 'wasm-zstd-write-mesh') + + const { + returnValue, + stderr, + outputs + } = await runPipelineNode(pipelinePath, args, desiredOutputs, inputs, mountDirs) + if (returnValue !== 0 && stderr !== "") { + throw new Error(stderr) + } + + const result = { + couldWrite: outputs[0]?.data as JsonCompatible, + } + return result +} + +export default wasmZstdWriteMeshNode diff --git a/packages/mesh-io/typescript/src/wasm-zstd-write-mesh-options.ts b/packages/mesh-io/typescript/src/wasm-zstd-write-mesh-options.ts new file mode 100644 index 000000000..183da813a --- /dev/null +++ b/packages/mesh-io/typescript/src/wasm-zstd-write-mesh-options.ts @@ -0,0 +1,15 @@ +// Generated file. To retain edits, remove this comment. + +interface WasmZstdWriteMeshOptions { + /** Only write image metadata -- do not write pixel data. */ + informationOnly?: boolean + + /** Use compression in the written file, if supported */ + useCompression?: boolean + + /** Use a binary file type in the written file, if supported */ + binaryFileType?: boolean + +} + +export default WasmZstdWriteMeshOptions diff --git a/packages/mesh-io/typescript/src/wasm-zstd-write-mesh-result.ts b/packages/mesh-io/typescript/src/wasm-zstd-write-mesh-result.ts new file mode 100644 index 000000000..b9fc544f1 --- /dev/null +++ b/packages/mesh-io/typescript/src/wasm-zstd-write-mesh-result.ts @@ -0,0 +1,17 @@ +// Generated file. To retain edits, remove this comment. + +import { JsonCompatible, BinaryFile } from 'itk-wasm' + +interface WasmZstdWriteMeshResult { + /** WebWorker used for computation */ + webWorker: Worker | null + + /** Whether the input could be written. If false, the output mesh is not valid. */ + couldWrite: JsonCompatible + + /** Output mesh */ + serializedMesh: BinaryFile + +} + +export default WasmZstdWriteMeshResult diff --git a/packages/mesh-io/typescript/src/wasm-zstd-write-mesh.ts b/packages/mesh-io/typescript/src/wasm-zstd-write-mesh.ts new file mode 100644 index 000000000..9880d846f --- /dev/null +++ b/packages/mesh-io/typescript/src/wasm-zstd-write-mesh.ts @@ -0,0 +1,88 @@ +// Generated file. To retain edits, remove this comment. + +import { + Mesh, + JsonCompatible, + BinaryFile, + InterfaceTypes, + PipelineOutput, + PipelineInput, + runPipeline +} from 'itk-wasm' + +import WasmZstdWriteMeshOptions from './wasm-zstd-write-mesh-options.js' +import WasmZstdWriteMeshResult from './wasm-zstd-write-mesh-result.js' + +import { getPipelinesBaseUrl } from './pipelines-base-url.js' +import { getPipelineWorkerUrl } from './pipeline-worker-url.js' + +/** + * Write an itk-wasm file format converted to an mesh file format + * + * @param {Mesh} mesh - Input mesh + * @param {string} serializedMesh - Output mesh + * @param {WasmZstdWriteMeshOptions} options - options object + * + * @returns {Promise} - result object + */ +async function wasmZstdWriteMesh( + webWorker: null | Worker | boolean, + mesh: Mesh, + serializedMesh: string, + options: WasmZstdWriteMeshOptions = {} +) : Promise { + + const desiredOutputs: Array = [ + { type: InterfaceTypes.JsonCompatible }, + { type: InterfaceTypes.BinaryFile, data: { path: serializedMesh, data: new Uint8Array() }}, + ] + + const inputs: Array = [ + { type: InterfaceTypes.Mesh, data: mesh }, + ] + + const args = [] + // Inputs + const meshName = '0' + args.push(meshName) + + // Outputs + const couldWriteName = '0' + args.push(couldWriteName) + + const serializedMeshName = serializedMesh + args.push(serializedMeshName) + + // Options + args.push('--memory-io') + if (typeof options.informationOnly !== "undefined") { + options.informationOnly && args.push('--information-only') + } + if (typeof options.useCompression !== "undefined") { + options.useCompression && args.push('--use-compression') + } + if (typeof options.binaryFileType !== "undefined") { + options.binaryFileType && args.push('--binary-file-type') + } + + const pipelinePath = 'wasm-zstd-write-mesh' + + const { + webWorker: usedWebWorker, + returnValue, + stderr, + outputs + } = await runPipeline(webWorker, pipelinePath, args, desiredOutputs, inputs, { pipelineBaseUrl: getPipelinesBaseUrl(), pipelineWorkerUrl: getPipelineWorkerUrl() }) + if (returnValue !== 0 && stderr !== "") { + throw new Error(stderr) + } + + const result = { + webWorker: usedWebWorker as Worker, + couldWrite: outputs[0]?.data as JsonCompatible, + serializedMesh: outputs[1]?.data as BinaryFile, + } + return result +} + +export default wasmZstdWriteMesh diff --git a/packages/mesh-io/typescript/test/browser/demo-app/index.html b/packages/mesh-io/typescript/test/browser/demo-app/index.html index f60fb4568..7d56a069f 100644 --- a/packages/mesh-io/typescript/test/browser/demo-app/index.html +++ b/packages/mesh-io/typescript/test/browser/demo-app/index.html @@ -76,6 +76,8 @@

👨‍💻 Live API Demo ✨

vtkPolyDataWriteMesh wasmReadMesh wasmWriteMesh + wasmZstdReadMesh + wasmZstdWriteMesh wasmZtdReadMesh wasmZtdWriteMesh @@ -737,6 +739,79 @@

👨‍💻 Live API Demo ✨

+ + + Read a mesh file format and convert it to the itk-wasm file format

+ +
+ + +

+ informationOnly - Only read image metadata -- do not read pixel data. +

+ +
Load sample inputs + Run

+ +
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+ + +

+ informationOnly - Only write image metadata -- do not write pixel data. +

+ useCompression - Use compression in the written file, if supported +

+ binaryFileType - Use a binary file type in the written file, if supported +

+ + +
Load sample inputs + Run

+ +
+ + +
+ + Download +

+ + Download +

+
+ +
+ + Read a mesh file format and convert it to the itk-wasm file format

diff --git a/packages/mesh-io/typescript/test/browser/demo-app/index.ts b/packages/mesh-io/typescript/test/browser/demo-app/index.ts index 903985193..6abad1602 100644 --- a/packages/mesh-io/typescript/test/browser/demo-app/index.ts +++ b/packages/mesh-io/typescript/test/browser/demo-app/index.ts @@ -32,6 +32,8 @@ import './vtk-poly-data-read-mesh-controller.js' import './vtk-poly-data-write-mesh-controller.js' import './wasm-read-mesh-controller.js' import './wasm-write-mesh-controller.js' +import './wasm-zstd-read-mesh-controller.js' +import './wasm-zstd-write-mesh-controller.js' import './wasm-ztd-read-mesh-controller.js' import './wasm-ztd-write-mesh-controller.js' diff --git a/packages/mesh-io/typescript/test/node/read-mesh-node-test.js b/packages/mesh-io/typescript/test/node/read-mesh-node-test.js new file mode 100644 index 000000000..d870e10fc --- /dev/null +++ b/packages/mesh-io/typescript/test/node/read-mesh-node-test.js @@ -0,0 +1,23 @@ +import test from 'ava' +import path from 'path' + +import { readMeshNode } from '../../dist/index-node.js' +import { IntTypes, FloatTypes, PixelTypes } from 'itk-wasm' + +import { testInputPath } from './common.js' + +const testFilePath = path.resolve(testInputPath, 'cow.vtk') + +const verifyMesh = (t, mesh) => { + t.is(mesh.meshType.dimension, 3) + t.is(mesh.meshType.pointComponentType, FloatTypes.Float32) + t.is(mesh.meshType.cellComponentType, IntTypes.UInt32) + t.is(mesh.meshType.pointPixelType, PixelTypes.Scalar) + t.is(mesh.meshType.cellPixelType, PixelTypes.Scalar) + t.is(mesh.numberOfPoints, 2903) + t.is(mesh.numberOfCells, 3263) +} +test('readMeshNode reads a file path given on the local filesystem', async t => { + const mesh = await readMeshNode(testFilePath) + verifyMesh(t, mesh) +}) diff --git a/test/node/io/mesh/readMeshLocalFileTest.js b/test/node/io/mesh/readMeshLocalFileTest.js deleted file mode 100644 index 2579311c7..000000000 --- a/test/node/io/mesh/readMeshLocalFileTest.js +++ /dev/null @@ -1,18 +0,0 @@ -import test from 'ava' -import path from 'path' - -import { IntTypes, FloatTypes, PixelTypes, readMeshLocalFile } from '../../../../dist/index.js' - -const testFilePath = path.resolve('build-emscripten', 'ExternalData', 'test', 'Input', 'cow.vtk') - -test('readMeshLocalFile reads a file path given on the local filesystem', t => { - return readMeshLocalFile(testFilePath).then(function (mesh) { - t.is(mesh.meshType.dimension, 3) - t.is(mesh.meshType.pointComponentType, FloatTypes.Float32) - t.is(mesh.meshType.cellComponentType, IntTypes.UInt32) - t.is(mesh.meshType.pointPixelType, PixelTypes.Scalar) - t.is(mesh.meshType.cellPixelType, PixelTypes.Scalar) - t.is(mesh.numberOfPoints, 2903) - t.is(mesh.numberOfCells, 3263) - }) -})