cornerstone-nifti-image-loader
cornerstone-nifti-image-loader copied to clipboard
Compatibility with Cornerstone3D
I want to use this but I don't know how I am supposed to right now. Can you clarify if this is/isn't compatible with the new Cornerstone3D? package.json
doesn't list it as a dependency (peer or otherwise) so I'm not sure what version of Cornerstone I'm supposed to be using.
According to https://www.cornerstonejs.org/, Cornerstone3D, or @cornerstonejs/core
, is the new "beta" version of Cornerstone:
and according to https://github.com/cornerstonejs/cornerstone3D-beta/issues/118#issuecomment-1270731312, the legacy Cornerstone, cornerstone-core
, is no longer being maintained at all.
The two projects have separate versioning schemes. The legacy one is at 2.6.1, the beta is at 0.16.7. So they really are separate projects.
The reason I'm confused is:
-
this repo is installable as
@cornerstonejs/nifiti-image-loader
, in the same@cornerstonejs
group, as if it's a peer of@cornerstonejs/core
, and that copy has the most recent 1.0.7 release -
but it's also installable as the older name
cornerstone-nifiti-image-loader
, but that copy hasn't been updated since 1.0.0, so that copy is probably dead -
but the actual examples that show me how to use this in practice have vendored a copy of the legacy code, and haven't touched it in 5 years
https://github.com/cornerstonejs/cornerstone-nifti-image-loader/blob/b14ae74537d56ea17a282350490949c77512d71f/examples/cornerstone.js#L1
So, how do I use this? If I npm i @cornerstone/core
will this work correctly with it?
(I do plan to try to test and figure this out on my own. I'm posting this to ask for some guidance to be added to the docs to help others out during the transition)
I'm currently trying to make this project work with cornerstone3D but there are functions which changed with corenerstone3D (as loadAndCacheImage for example). I don't know if the both are compatible.
i load nifti files for Cornerstone3D, but it not works.
are you have some examples?
I'm currently trying to make this project work with cornerstone3D but there are functions which changed with corenerstone3D (as loadAndCacheImage for example). I don't know if the both are compatible.
Thank you for the clarification! That helps a lot. I'll build on cornerstone-core^2.6.1
+ cornerstore-nifti-image-loader
then. I feel pretty stupid for not being able to figure that out from the docs, but they are pretty sprawling and I found myself getting lost in them. Thank you for cutting through the noise for me @simonalo.
@acegank there's an example right in the repo.
But like I said, and like @simonalo confirmed, these NIfTI examples need to work against cornerstone-core
otherwise known as legacy cornerstone; @cornerstonejs/core
otherwise known as Cornerstone3D is not yet compatible with NIfTI files.
Hello, I managed to make Cornerstone3D
(@cornerstonejs/core
) and this project (cornerstone-nifti-image-loader
) work together, at least in Stack viewports. Now I'm trying to load a NIFTI as a volume in a Volume viewport, but that's another story...
I post the relevant portions of my code, if it can help somenone. It's not minimal, as I wanted to display 3 orientations (x,y,z) of the same image. And I had to tweak a few things (events, metadata), and I'm not quite sure if there are side effects...
package.json
{
"name": "cornerstone3d-tests",
"packageManager": "[email protected]",
"version": "0.0.0",
"description": "",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "webpack --watch",
"start": "webpack serve --open",
"build": "webpack"
},
"devDependencies": {
"css-loader": "^6.7.3",
"style-loader": "^3.3.1",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1"
},
"dependencies": {
"@cornerstonejs/core": "^0.25.1",
"@cornerstonejs/nifti-image-loader": "^1.0.9",
"@cornerstonejs/tools": "^0.35.0",
"@kitware/vtk.js": "^26.0.0",
"d3-array": "^3.2.1",
"d3-interpolate": "^3.0.1",
"gl-matrix": "^3.4.3"
}
}
index.js
:
import * as cornerstone from '@cornerstonejs/core';
import * as cornerstoneNIFTIImageLoader from '@cornerstonejs/nifti-image-loader';
const { ViewportType } = cornerstone.Enums;
function createElement( size = '400px') {
let element = document.createElement('div');
element.style.width = size;
element.style.height = size;
element.style.border = '1px solid red';
element.style.margin = '10px';
// Disable default context menu
element.oncontextmenu = (e) => e.preventDefault();
return element;
}
/**
* Hardcoded metadata provider for NIFTI images, as they don't exist in the old cornerstone module
* @param type The type of metadata to retrieve
* @param imageId The imageId of the image to retrieve metadata for. Must start with 'nifti:'
* @returns {Object} The metadata object
*/
function additionalMetaDataProvider(type, imageId) {
const colonIndex = imageId.indexOf(':');
const scheme = imageId.substring(0, colonIndex);
if (scheme !== 'nifti') return;
if (type === 'generalSeriesModule') {
return {
modality: 'Unknown',
};
}
}
/**
* Uses the NIFTI image loader to fetch metadata of a NIFTI, cache it in cornerstone,
* and return a list of imageIds for the frames.
*
* @returns {string[]} An array of imageIds for instances in the study.
*/
async function createImageIdsAndCacheMetaData(imageId) {
const colonIndex = imageId.indexOf(':');
const scheme = imageId.substring(0, colonIndex);
if (scheme !== 'nifti') {
console.warn('createImageIdsAndCacheMetaData: imageId must have scheme "nifti". imageId: ', imageId);
return;
}
// Load the image (it will be stored in the cache, and the metadata also)
const imageIdObject = cornerstoneNIFTIImageLoader.nifti.ImageId.fromURL(imageId);
const image = await cornerstone.imageLoader.loadAndCacheImage(imageIdObject.url);
// Get the number of frames from the metadata the image loader provides
const numberOfFrames = cornerstone.metaData.get('multiFrame', image.imageId).numberOfFrames;
const imageIds = Array.from(Array(numberOfFrames),
(_, i) => `nifti:${imageIdObject.filePath}#${imageIdObject.slice.dimension}-${i},t-0`)
console.log('imageIds', imageIds);
return imageIds;
}
async function run() {
// Create elements to render into
const content = document.getElementById('content');
content.style.display = 'flex';
content.style.flexDirection = 'row';
const element1 = createElement();
content.appendChild(element1);
const element2 = createElement();
content.appendChild(element2);
const element3 = createElement();
content.appendChild(element3);
// Initialize cornerstone and tools
await cornerstone.init();
// Create a rendering engine
const renderingEngineId = 'myRenderingEngine';
const renderingEngine = new cornerstone.RenderingEngine(renderingEngineId);
// Create the viewports (of type STACK)
const viewportInputArray = [
{
viewportId: 'X_VIEWPORT',
type: ViewportType.STACK,
element: element1,
},
{
viewportId: 'Y_VIEWPORT',
type: ViewportType.STACK,
element: element2,
},
{
viewportId: 'Z_VIEWPORT',
type: ViewportType.STACK,
element: element3,
}
];
renderingEngine.setViewports(viewportInputArray);
const viewportX = renderingEngine.getViewport('X_VIEWPORT');
const viewportY = renderingEngine.getViewport('Y_VIEWPORT');
const viewportZ = renderingEngine.getViewport('Z_VIEWPORT');
// Register the nifti image loader
cornerstoneNIFTIImageLoader.external.cornerstone = cornerstone;
// NOTE: This is a hack to get around the fact that the nifti image loader
// uses the old cornerstone module, and we need to provide it with the
// new cornerstone module (events = eventTarget).
cornerstoneNIFTIImageLoader.external.cornerstone.events = cornerstone.eventTarget;
// cornerstoneNIFTIImageLoader.nifti.streamingMode = true;
// Register an additional metadata provider for Nifti images (for the generalSeriesModule, not provided by the package)
cornerstone.metaData.addProvider(
(type, imageId) => additionalMetaDataProvider(type, imageId),
1000 // Priority of the NIFTI metadata provider is 10000, so this one is called after
);
// Example of a Nifti image, from the web.
// The number after # is the frame index
// const imageUrl = 'https://raw.githubusercontent.com/muschellij2/Neurohacking_data/master/BRAINIX/NIfTI/Output_3D_File.nii.gz#10'
// Will load a local image
const imageUrl = `data/mni152_2009_256.nii.gz`;
// Load the image and assign it to the viewport, for each orientation
const imageIdsZ = await createImageIdsAndCacheMetaData(`nifti:${imageUrl}#z`);
viewportZ.setStack(imageIdsZ, Math.floor(imageIdsZ.length / 2));
viewportZ.render();
const imageIdsY = await createImageIdsAndCacheMetaData(`nifti:${imageUrl}#y`);
viewportY.setStack(imageIdsY, Math.floor(imageIdsY.length / 2));
viewportY.render();
const imageIdsX = await createImageIdsAndCacheMetaData(`nifti:${imageUrl}#x`);
viewportX.setStack(imageIdsX, Math.floor(imageIdsX.length / 2));
viewportX.render();
}
run();
load a NIFTI as a volume
@scandel
Did you finish the job? I really don't understand the documentation, can I use imagevolume class to do this task directly?
Is this something planned to be tackled soon?
@scandel Thank you very much for your contribution and the explanations! Did you meanwhile found a way to load NIFTI into a volume?
Kind regards
Yes you can load NIFTI images in cornerstone3D in volume using @cornerstonejs/nifti-volume-loader. I am able to load in react typescript project with webpack