-
Notifications
You must be signed in to change notification settings - Fork 228
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #856 from rordenlab/feature/add-wasm-npm-module
add wasm build for npm package
- Loading branch information
Showing
11 changed files
with
1,199 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,3 +13,8 @@ __pycache__/ | |
/MANIFEST* | ||
/*.egg*/ | ||
/dist/ | ||
|
||
dist | ||
node_modules | ||
dcm2niix.js | ||
dcm2niix.wasm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
# @niivue/dcm2niix | ||
|
||
`@niivue/dcm2niix` is a JavaScript + WASM library for converting DICOM files to nifti. This library is intended to be **used in the browser**, not in a Node.js environment. | ||
|
||
> All operations are performed using the WASM build of [dcm2niix](https://github.com/rordenlab/dcm2niix). The processing takes place in a separate worker thread, so it won't block the main thread in your application. | ||
## Usage | ||
|
||
The `@niivue/dcm2niix` JavaScript library offers an object oriented API for working with the `dcm2niix` CLI. Since `dcm2niix` is a CLI tool, the API implemented in `@niivue/dcm2niix` is just a wrapper around the CLI options and arguments. | ||
|
||
## Example | ||
|
||
```javascript | ||
// assuming you have an html input element to get directories. | ||
// <input type="file" id="fileInput" webkitdirectory multiple> | ||
import { Dcm2niix } from '@niivue/dcm2niix'; | ||
|
||
const dcm2niix = new Dcm2niix(); | ||
// call the init() method to load the wasm before processing any data | ||
await dcm2niix.init(); | ||
// fileInput is the id of the input element with options: webkitdirectory and multiple | ||
fileInput.addEventListener('change', async (event) => { | ||
inputFileList = event.target.files; | ||
}); | ||
// inputFileList is the value from the input element with options: webkitdirectory and multiple | ||
const resultFileList = await dcm2niix.input(inputFileList).run() | ||
console.log(resultFileList); | ||
// Do something with the resultFileList (normal browser File Objects) | ||
// perhaps view them with @niivue/niivue :) | ||
``` | ||
|
||
## Installation | ||
|
||
To install `@niivue/dcm2niix` in your project, run the following command: | ||
|
||
```bash | ||
npm install @niivue/dcm2niix | ||
``` | ||
|
||
### To install a local build of the library | ||
|
||
Fist, `cd` into the `js` directory of the `dcm2niix` repository. | ||
|
||
```bash | ||
# from dcm2niix root directory | ||
cd js | ||
``` | ||
|
||
To install a local build of the library, run the following command: | ||
|
||
```bash | ||
npm run build | ||
``` | ||
|
||
Then, install the library using the following command: | ||
|
||
```bash | ||
npm pack # will create a .tgz file in the root directory | ||
``` | ||
|
||
Then, install the `@niivue/dcm2niix` library in your application locally using the following command: | ||
|
||
```bash | ||
npm install /path/to/niivue-dcm2niix.tgz | ||
``` | ||
|
||
## Development | ||
|
||
First `cd` into the `js` directory of the `dcm2niix` repository. | ||
|
||
```bash | ||
# from dcm2niix root directory | ||
cd js | ||
``` | ||
|
||
To install the dependencies, run the following command: | ||
|
||
```bash | ||
npm install | ||
``` | ||
|
||
To build the library, run the following command | ||
|
||
```bash | ||
npm run build | ||
``` | ||
|
||
To run the tests, run the following command: | ||
|
||
```bash | ||
npm run test | ||
``` | ||
|
||
### Test using a simple demo | ||
|
||
To test that the `@niivue/dcm2niix` library is working correctly, you can run the following command: | ||
|
||
```bash | ||
npm run demo | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
const esbuild = require('esbuild'); | ||
const fs = require('fs'); | ||
|
||
esbuild.build({ | ||
entryPoints: ['./src/index.js'], | ||
outfile: './dist/index.js', | ||
bundle: true, | ||
format: 'esm', | ||
target: ['es2020'], | ||
minify: false, | ||
define: { | ||
'process.env.NODE_ENV': '"production"', | ||
}, | ||
}).then(() => { | ||
// copy worker.js, dcm2niix.wasm, dcm2niix.js to dist folder | ||
// (they do not require any processing by esbuild). | ||
// Technically, none of the files in the src folder require processing by esbuild, | ||
// but it does allow minification (optional), and ES version target specification if needed. | ||
// In the future, if we use Typescript, we can use esbuild to transpile the Typescript to JS. | ||
fs.copyFileSync('./src/worker.js', './dist/worker.js'); | ||
fs.copyFileSync('./src/dcm2niix.wasm', './dist/dcm2niix.wasm'); | ||
fs.copyFileSync('./src/dcm2niix.js', './dist/dcm2niix.js'); | ||
console.log('Build completed!'); | ||
}).catch(() => process.exit(1)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>dcm2niix WASM Demo</title> | ||
</head> | ||
|
||
<body> | ||
<h1>dcm2niix WASM Demo</h1> | ||
<input type="file" id="fileInput" webkitdirectory multiple> | ||
<button id="processButton">Process Image</button> | ||
<p id="status">Please select a dicom folder to process.</p> | ||
<a id="downloadLink" style="display: none;">Download Processed Image(s)</a> | ||
|
||
<script type="module"> | ||
import { Dcm2niix } from './dist/index.js'; | ||
const dcm2niix = new Dcm2niix(); | ||
const fileInput = document.getElementById('fileInput'); | ||
const processButton = document.getElementById('processButton'); | ||
const status = document.getElementById('status'); | ||
const downloadLink = document.getElementById('downloadLink'); | ||
|
||
let selectedFiles = null; | ||
|
||
fileInput.addEventListener('change', async (event) => { | ||
selectedFiles = event.target.files; | ||
console.log(selectedFiles); | ||
}); | ||
|
||
processButton.addEventListener('click', async () => { | ||
// if (!selectedFile) return; | ||
|
||
status.textContent = 'Processing...'; | ||
// processButton.disabled = true; | ||
|
||
try { | ||
console.log('Initializing dcm2niix wasm...'); | ||
await dcm2niix.init(); | ||
console.log('dcm2niix wasm initialized.'); | ||
|
||
const t0 = performance.now(); | ||
|
||
const inputFileList = selectedFiles | ||
const resultFileList = await dcm2niix.input(inputFileList).run() | ||
console.log(resultFileList); | ||
|
||
const t1 = performance.now(); | ||
console.log("dcm2niix wasm took " + (t1 - t0) + " milliseconds.") | ||
|
||
// Create a download link for each file in resultFileList | ||
resultFileList.forEach((resultFile, index) => { | ||
let url = URL.createObjectURL(resultFile); | ||
const downloadLink = document.createElement('a'); | ||
downloadLink.href = url; | ||
downloadLink.download = resultFile.name; | ||
downloadLink.textContent = `Download ${resultFile.name}`; | ||
downloadLink.style.display = 'block'; | ||
document.body.appendChild(downloadLink); | ||
}); | ||
|
||
|
||
status.textContent = 'Processing complete!'; | ||
} catch (error) { | ||
console.error('Processing failed:', error); | ||
status.textContent = 'Processing failed. Please check the console for details.'; | ||
} finally { | ||
processButton.disabled = false; | ||
} | ||
}); | ||
</script> | ||
</body> | ||
|
||
</html> |
Oops, something went wrong.