Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(nifti): Add nifti volume loader to cornerstone 3D repo #696

Merged
merged 15 commits into from
Sep 7, 2023
1 change: 1 addition & 0 deletions lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"packages/core",
"packages/tools",
"packages/streaming-image-volume-loader",
"packages/nifti-volume-loader",
"packages/dicomImageLoader"
],
"npmClient": "yarn",
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/loaders/volumeLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ let unknownVolumeLoader;
*/
function loadVolumeFromVolumeLoader(
volumeId: string,
options: VolumeLoaderOptions
options?: VolumeLoaderOptions
): Types.IVolumeLoadObject {
const colonIndex = volumeId.indexOf(':');
const scheme = volumeId.substring(0, colonIndex);
Expand Down Expand Up @@ -210,7 +210,7 @@ export function loadVolume(
*/
export async function createAndCacheVolume(
volumeId: string,
options: VolumeLoaderOptions
options?: VolumeLoaderOptions
): Promise<Record<string, any>> {
if (volumeId === undefined) {
throw new Error(
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/types/AffineMatrix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
type AffineMatrix = [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really need to define yet another matrix format? How about affineMatrix as a function producing a gl-matrix mat4 instance instead, taking four arrays like this as the arguments, and producing the standard mat4 representation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed in the meeting, I will do it later

[number, number, number, number],
[number, number, number, number],
[number, number, number, number],
[number, number, number, number]
];

export type { AffineMatrix };
14 changes: 3 additions & 11 deletions packages/core/src/types/Mat3.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
/**
* This represents a 3x3 matrix of numbers
*/
type Mat3 = [
number,
number,
number,
number,
number,
number,
number,
number,
number
];
type Mat3 =
| [number, number, number, number, number, number, number, number, number]
| Float32Array;

export default Mat3;
2 changes: 2 additions & 0 deletions packages/core/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import type { ViewportProperties } from './ViewportProperties';
import type { PixelDataTypedArray } from './PixelDataTypedArray';
import type { ImagePixelModule } from './ImagePixelModule';
import type { ImagePlaneModule } from './ImagePlaneModule';
import type { AffineMatrix } from './AffineMatrix';

export type {
// config
Expand Down Expand Up @@ -171,4 +172,5 @@ export type {
PixelDataTypedArray,
ImagePixelModule,
ImagePlaneModule,
AffineMatrix,
};
1 change: 1 addition & 0 deletions packages/nifti-volume-loader/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist/
8 changes: 8 additions & 0 deletions packages/nifti-volume-loader/.webpack/webpack.dev.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const path = require('path');
const webpackCommon = require('./../../../.webpack/webpack.common.js');
const SRC_DIR = path.join(__dirname, '../src');
const DIST_DIR = path.join(__dirname, '../dist');

module.exports = (env, argv) => {
return webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
};
45 changes: 45 additions & 0 deletions packages/nifti-volume-loader/.webpack/webpack.prod.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const { merge } = require('webpack-merge');
const path = require('path');
const webpackCommon = require('./../../../.webpack/webpack.common.js');
const pkg = require('./../package.json');

module.exports = (env, argv) => {
const commonConfig = webpackCommon(env, argv);

return merge(commonConfig, {
devtool: 'source-map',
entry: {
lib: path.join(__dirname, '../src/index.ts'),
},
output: {
path: path.join(__dirname, '../dist/umd'),
library: 'cornerstoneNiftiVolumeLoader',
libraryTarget: 'umd',
filename: 'index.js',
},
stats: {
colors: true,
hash: true,
timings: true,
assets: true,
chunks: false,
chunkModules: false,
modules: false,
children: false,
warnings: true,
},
optimization: {
minimize: true,
},
externals: [
{
'@cornerstonejs/core': {
root: 'cornerstone3D',
commonjs: '@cornerstonejs/core',
commonjs2: '@cornerstonejs/core',
amd: '@cornerstonejs/core',
},
},
],
});
};
Empty file.
3 changes: 3 additions & 0 deletions packages/nifti-volume-loader/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# @cornerstonejs/nifti-volume-loader

Nifti volume loader for the cornerstone3D framework.
9 changes: 9 additions & 0 deletions packages/nifti-volume-loader/api-extractor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "../../api-extractor.json",
"projectFolder": ".",
"mainEntryPointFilePath": "<projectFolder>/dist/cjs/index.d.ts",
"apiReport": {
"reportFileName": "<unscopedPackageName>.api.md",
"reportFolder": "../../common/reviews/api"
}
}
1 change: 1 addition & 0 deletions packages/nifti-volume-loader/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../../babel.config.js');
102 changes: 102 additions & 0 deletions packages/nifti-volume-loader/examples/niftiBasic/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import {
RenderingEngine,
Enums,
init as csInit,
Types,
volumeLoader,
setVolumesForViewports,
} from '@cornerstonejs/core';
import { init as csTools3dInit } from '@cornerstonejs/tools';
import { cornerstoneNiftiImageVolumeLoader } from '@cornerstonejs/nifti-volume-loader';

import { setCtTransferFunctionForVolumeActor } from '../../../../utils/demo/helpers';

// This is for debugging purposes
console.warn(
'Click on index.ts to open source code for this example --------->'
);

const size = '500px';

const content = document.getElementById('content');
const viewportGrid = document.createElement('div');
viewportGrid.style.display = 'flex';
viewportGrid.style.display = 'flex';
viewportGrid.style.flexDirection = 'row';

const element1 = document.createElement('div');
const element2 = document.createElement('div');
const element3 = document.createElement('div');
element1.style.width = size;
element1.style.height = size;
element2.style.width = size;
element2.style.height = size;
element3.style.width = size;
element3.style.height = size;

viewportGrid.appendChild(element1);
viewportGrid.appendChild(element2);
viewportGrid.appendChild(element3);

content.appendChild(viewportGrid);

const viewportId1 = 'CT_NIFTI_AXIAL';
const viewportId2 = 'CT_NIFTI_SAGITTAL';
const viewportId3 = 'CT_NIFTI_CORONAL';

async function setup() {
await csInit();
await csTools3dInit();

volumeLoader.registerVolumeLoader('nifti', cornerstoneNiftiImageVolumeLoader);

const niftiURL =
'https://ohif-assets.s3.us-east-2.amazonaws.com/nifti/MRHead.nii.gz';
const volumeId = 'nifti:' + niftiURL;

const volume = await volumeLoader.createAndCacheVolume(volumeId);

const renderingEngineId = 'myRenderingEngine';
const renderingEngine = new RenderingEngine(renderingEngineId);

const viewportInputArray = [
{
viewportId: viewportId1,
type: Enums.ViewportType.ORTHOGRAPHIC,
element: element1,
defaultOptions: {
orientation: Enums.OrientationAxis.AXIAL,
},
},
{
viewportId: viewportId2,
type: Enums.ViewportType.ORTHOGRAPHIC,
element: element2,
defaultOptions: {
orientation: Enums.OrientationAxis.SAGITTAL,
},
},
{
viewportId: viewportId3,
type: Enums.ViewportType.ORTHOGRAPHIC,
element: element3,
defaultOptions: {
orientation: Enums.OrientationAxis.CORONAL,
},
},
];

renderingEngine.setViewports(viewportInputArray);

volume.load();

setVolumesForViewports(
renderingEngine,
[{ volumeId, callback: setCtTransferFunctionForVolumeActor }],
viewportInputArray.map((v) => v.viewportId)
);

renderingEngine.render();
}

setup();
Loading