Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/VTKViewport/View2D.js
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ export default class View2D extends Component {
istyle.setViewport(currentViewport);
}

istyle.getVolumeMapper();

if (istyle.getVolumeMapper() !== volumes[0]) {
if (slabThickness && istyle.setSlabThickness) {
istyle.setSlabThickness(slabThickness);
Expand Down
19 changes: 3 additions & 16 deletions src/VTKViewport/vtkInteractorStyleMPRSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,7 @@ function vtkInteractorStyleMPRSlice(publicAPI, model) {
const _viewUp = [...viewUp];

if (model.volumeMapper) {
let mapper = model.volumeMapper;
// get the mapper if the model is actually the actor, not the mapper
if (!model.volumeMapper.getInputData && model.volumeMapper.getMapper) {
mapper = model.volumeMapper.getMapper();
}
let volumeCoordinateSpace = vec9toMat3(
mapper.getInputData().getDirection()
);
let volumeCoordinateSpace = vec9toMat3([1, 0, 0, 0, 1, 0, 0, 0, 1]);
// Transpose the volume's coordinate space to create a transformation matrix
vtkMath.transpose3x3(volumeCoordinateSpace, volumeCoordinateSpace);

Expand All @@ -142,14 +135,8 @@ function vtkInteractorStyleMPRSlice(publicAPI, model) {

if (model.volumeMapper) {
vtkMath.normalize(_normal);
let mapper = model.volumeMapper;
// get the mapper if the model is actually the actor, not the mapper
if (!model.volumeMapper.getInputData && model.volumeMapper.getMapper) {
mapper = model.volumeMapper.getMapper();
}
let volumeCoordinateSpace = vec9toMat3(
mapper.getInputData().getDirection()
);

let volumeCoordinateSpace = vec9toMat3([1, 0, 0, 0, 1, 0, 0, 0, 1]);
// Transpose the volume's coordinate space to create a transformation matrix
vtkMath.transpose3x3(volumeCoordinateSpace, volumeCoordinateSpace);
// Convert the provided normal into the volume's space
Expand Down
161 changes: 1 addition & 160 deletions src/lib/data/insertSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
*
* @param {Object} imageData - The vtkImageData
* @param {*} sliceIndex - The index of the slice you are inserting.
* @param {*} acquistionDirection - The acquistion direction of the slice.
* @param {*} image The cornerstone image to pull pixel data data from.
* @param {*} modality The modality of the image.
* @param {*} modalitySpecificScalingParameters Specific scaling paramaters for this modality. E.g. Patient weight.
*/
export default function insertSlice(
imageData,
sliceIndex,
acquistionDirection,
image,
modality,
modalitySpecificScalingParameters
Expand All @@ -24,163 +22,6 @@ export default function insertSlice(
modalitySpecificScalingParameters
);

const vtkImageDimensions = imageData.getDimensions();

let minAndMax;

switch (acquistionDirection) {
case 'coronal':
minAndMax = insertCoronalSlice(
image,
sliceIndex,
vtkImageDimensions,
scalarData,
scalingFunction
);
break;
case 'sagittal':
minAndMax = insertSagittalSlice(
image,
sliceIndex,
vtkImageDimensions,
scalarData,
scalingFunction
);
break;
case 'axial':
minAndMax = insertAxialSlice(
image,
sliceIndex,
scalarData,
scalingFunction
);
break;
}

return minAndMax;
}

/**
*
* @param {object} image The cornerstone image to pull pixel data data from.
* @param {number} xIndex The x index of axially oriented vtk volume to put the sagital slice.
* @param {number[]} vtkImageDimensions The dimensions of the axially oriented vtk volume.
* @param {number[]} scalarData The data array for the axially oriented vtk volume.
* @param {function} scalingFunction The modality specific scaling function.
*
* @returns {object} The min and max pixel values in the inserted slice.
*/
function insertSagittalSlice(
image,
xIndex,
vtkImageDimensions,
scalarData,
scalingFunction
) {
const pixels = image.getPixelData();
const { rows, columns } = image;

let pixelIndex = 0;
let max = scalingFunction(pixels[pixelIndex]);
let min = max;

const vtkImageDimensionsX = vtkImageDimensions[0];
const vtkImageDimensionsY = vtkImageDimensions[1];
const vtkImageDimensionsZ = vtkImageDimensions[2];

const axialSliceLength = vtkImageDimensionsX * vtkImageDimensionsY;

for (let row = 0; row < rows; row++) {
for (let col = 0; col < columns; col++) {
const yPos = vtkImageDimensionsY - col;
const zPos = vtkImageDimensionsZ - row;

const destIdx =
zPos * axialSliceLength + yPos * vtkImageDimensionsX + xIndex;

const pixel = pixels[pixelIndex];
const pixelValue = scalingFunction(pixel);

if (pixelValue > max) {
max = pixelValue;
} else if (pixelValue < min) {
min = pixelValue;
}

scalarData[destIdx] = pixelValue;
pixelIndex++;
}
}

return { min, max };
}

/**
*
* @param {object} image The cornerstone image to pull pixel data data from.
* @param {number} yIndex The y index of axially oriented vtk volume to put the coronal slice.
* @param {number[]} vtkImageDimensions The dimensions of the axially oriented vtk volume.
* @param {number[]} scalarData The data array for the axially oriented vtk volume.
* @param {function} scalingFunction The modality specific scaling function.
*
* @returns {object} The min and max pixel values in the inserted slice.
*/
function insertCoronalSlice(
image,
yIndex,
vtkImageDimensions,
scalarData,
scalingFunction
) {
const pixels = image.getPixelData();
const { rows, columns } = image;

let pixelIndex = 0;
let max = scalingFunction(pixels[pixelIndex]);
let min = max;

const vtkImageDimensionsX = vtkImageDimensions[0];
const vtkImageDimensionsY = vtkImageDimensions[1];
const vtkImageDimensionsZ = vtkImageDimensions[2];

const axialSliceLength = vtkImageDimensionsX * vtkImageDimensionsY;

for (let row = 0; row < rows; row++) {
for (let col = 0; col < columns; col++) {
const xPos = col;
const yPos = yIndex;
const zPos = vtkImageDimensionsZ - row;

const destIdx =
zPos * axialSliceLength + yPos * vtkImageDimensionsX + xPos;

const pixel = pixels[pixelIndex];
const pixelValue = scalingFunction(pixel);

if (pixelValue > max) {
max = pixelValue;
} else if (pixelValue < min) {
min = pixelValue;
}

scalarData[destIdx] = pixelValue;
pixelIndex++;
}
}

return { min, max };
}

/**
*
* @param {object} image The cornerstone image to pull pixel data data from.
* @param {number} zIndex The z index of axially oriented vtk volume to put the axial slice.
* @param {number[]} scalarData The data array for the axially oriented vtk volume.
* @param {function} scalingFunction The modality specific scaling function.
*
* @returns {object} The min and max pixel values in the inserted slice.
*/
function insertAxialSlice(image, zIndex, scalarData, scalingFunction) {
const pixels = image.getPixelData();
const sliceLength = pixels.length;

Expand All @@ -189,7 +30,7 @@ function insertAxialSlice(image, zIndex, scalarData, scalingFunction) {
let min = max;

for (let pixelIndex = 0; pixelIndex < pixels.length; pixelIndex++) {
const destIdx = pixelIndex + zIndex * sliceLength;
const destIdx = pixelIndex + sliceIndex * sliceLength;
const pixel = pixels[pixelIndex];
const pixelValue = scalingFunction(pixel);

Expand Down
49 changes: 3 additions & 46 deletions src/lib/getImageData.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,27 +87,10 @@ export default function getImageData(imageIds, displaySetInstanceUid) {
scanAxisNormal.z,
];

const acquistionDirection = _getAcquisitionDirection(scanAxisNormal);
imageData.setDimensions(xVoxels, yVoxels, zVoxels);
imageData.setSpacing(xSpacing, ySpacing, zSpacing);

console.log(rowCosineVec);
console.log(colCosineVec);
console.log(scanAxisNormal);
console.log(acquistionDirection);

switch (acquistionDirection) {
case 'sagittal':
imageData.setDimensions(zVoxels, xVoxels, yVoxels);
imageData.setSpacing(zSpacing, xSpacing, ySpacing);
break;
case 'coronal':
imageData.setDimensions(xVoxels, zVoxels, yVoxels);
imageData.setSpacing(xSpacing, zSpacing, ySpacing);
break;
case 'axial':
imageData.setDimensions(xVoxels, yVoxels, zVoxels);
imageData.setSpacing(xSpacing, ySpacing, zSpacing);
break;
}
imageData.setDirection(direction);
Copy link
Member

Choose a reason for hiding this comment

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

Ahhh, sooo much nicer!


imageData.setOrigin(...origin);
imageData.getPointData().setScalars(scalarArray);
Expand All @@ -123,36 +106,10 @@ export default function getImageData(imageIds, displaySetInstanceUid) {
vtkImageData: imageData,
metaDataMap,
sortedDatasets,
acquistionDirection,
loaded: false,
};

imageDataCache.set(displaySetInstanceUid, imageDataObject);

return imageDataObject;
}

const sagittal = new Vector3(1, 0, 0);
const coronal = new Vector3(0, 1, 0);
const axial = new Vector3(0, 0, 1);

function _getAcquisitionDirection(zDirection) {
const zAbs = new Vector3(
Math.abs(zDirection.x),
Math.abs(zDirection.y),
Math.abs(zDirection.z)
);

// Get the direction of the acquisition.
const dotProducts = [
zAbs.dot(sagittal), // z . Sagittal
zAbs.dot(coronal), // z . Coronal
zAbs.dot(axial), // z . Axial
];

const directionIndex = dotProducts.indexOf(Math.max(...dotProducts));

const acquisitionDirections = ['sagittal', 'coronal', 'axial'];

return acquisitionDirections[directionIndex];
}
10 changes: 0 additions & 10 deletions src/lib/loadImageData.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export default function loadImageDataProgressively(imageDataObject) {
vtkImageData,
metaDataMap,
sortedDatasets,
acquistionDirection,
} = imageDataObject;
const loadImagePromises = imageIds.map(cornerstone.loadAndCacheImage);
const imageId0 = imageIds[0];
Expand Down Expand Up @@ -69,7 +68,6 @@ export default function loadImageDataProgressively(imageDataObject) {
const { max, min } = insertSlice(
vtkImageData,
sliceIndex,
acquistionDirection,
image,
modality,
modalitySpecificScalingParameters
Expand Down Expand Up @@ -114,12 +112,4 @@ export default function loadImageDataProgressively(imageDataObject) {
});

imageDataObject.insertPixelDataPromises = insertPixelDataPromises;

// TODO: Investigate progressive loading. Right now the UI gets super slow because
// we are rendering and decoding simultaneously. We might want to use fewer web workers
// for the decoding tasks.
//
// Update: Had some success with this locally. But it completely freezes up when stuck
// In an app like OHIF. There seems to be many small calls made to various vtk functions.
// Putting it aside for now, but a progressive loader still shows promise.
}