Skip to main content

4D Or Dynamic Volume

We think this is important enough to have a section for itself

imageIdsGroups is now imageIdGroups​

if you were using splitImageIdsBy4DTags to get the imageIdsGroups now you should expect the return object to have ImageIdGroups instead of ImageIdsGroups

migration

const { imageIdsGroups } = splitImageIdsBy4DTags(imageIds);

should be

const { imageIdGroups } = splitImageIdsBy4DTags(imageIds);

StreamingDynamicImageVolume​

Constructor Changes​

The constructor signature has been updated to include imageIdGroups instead of separate scalarData arrays.

constructor(
imageVolumeProperties: Types.ImageVolumeProps & { splittingTag: string },
streamingProperties: Types.IStreamingVolumeProperties
) {
// ...
}

Migration Steps:

  1. Update the constructor call to include imageIdGroups instead of scalarData.
  2. Remove any code that previously handled scalarData arrays.

New Methods for ImageId Management​

Version 2 introduces new methods for managing image IDs:

  • getCurrentTimePointImageIds()
  • flatImageIdIndexToTimePointIndex()
  • flatImageIdIndexToImageIdIndex()

Migration Steps:

  1. Use getCurrentTimePointImageIds() to get image IDs for the current time point.
  2. Utilize flatImageIdIndexToTimePointIndex() and flatImageIdIndexToImageIdIndex() for converting between flat indices and time point/image indices.

Removal of getScalarData Method and Using VoxelManager for Dynamic Image Volumes​

The getScalarData() method has been removed in version 2 in favor of the new voxel Manager

In version 2, the StreamingDynamicImageVolume class now uses a VoxelManager to handle time point data. This change provides more efficient memory management and easier access to voxel data across different time points. Here's how you can use the VoxelManager to access and manipulate data in your dynamic image volumes:

Accessing Voxel Data​

To access voxel data for the current time point:

const voxelValue = volume.voxelManager.get(index);

To access voxel data for a specific time point:

const voxelValue = volume.voxelManager.getAtIndexAndTimePoint(index, timePoint);

Getting Scalar Data​

To get the complete scalar data array for the current time point:

const scalarData = volume.voxelManager.getCurrentTimePointScalarData();

To get the scalar data for a specific time point:

const scalarData = volume.voxelManager.getTimePointScalarData(timePoint);

Getting Volume Information​

You can access various volume properties through the VoxelManager:

const scalarDataLength = volume.voxelManager.getScalarDataLength();
const dataType = volume.voxelManager.getConstructor();
const dataRange = volume.voxelManager.getRange();
const middleSliceData = volume.voxelManager.getMiddleSliceData();

Migration Steps:

  1. Replace direct access to scalarData arrays with calls to the appropriate VoxelManager methods.
  2. Update any code that manually managed time points to use the VoxelManager's time point-aware methods.
  3. Use getCurrentTimePointScalarData() or getTimePointScalarData(tp) instead of the removed getScalarData() method.
  4. If you need to perform operations across all time points, you can iterate through them using the numTimePoints property and the getTimePointScalarData(tp) method.

By leveraging the VoxelManager, you can efficiently work with dynamic image volumes without manually managing multiple scalar data arrays. This approach provides better performance and memory usage, especially for large datasets with many time points.

Exports Imports​

If you were previously using @cornerstonejs/streaming-image-volume-loader, you'll need to update your imports and potentially adjust your code to use the new integrated volume loading API in @cornerstonejs/core.

import {
cornerstoneStreamingDynamicImageVolumeLoader,
StreamingDynamicImageVolume,
helpers,
Enums,
} from '@cornerstonejs/streaming-image-volume-loader';

Enums.Events.DYNAMIC_VOLUME_TIME_POINT_INDEX_CHANGED;

getDataInTime​

The imageCoordinate option is now worldCoordinate, to better reflect that it's a world coordinate and not an image coordinate.

function getDataInTime(
dynamicVolume: Types.IDynamicImageVolume,
options: {
frameNumbers?;
maskVolumeId?;
imageCoordinate?;
}
): number[] | number[][];

Usage Example​

const result = getDataInTime(dynamicVolume, {
frameNumbers: [0, 1, 2],
imageCoordinate: [100, 100, 100],
});

generateImageFromTimeData​

function generateImageFromTimeData(
dynamicVolume: Types.IDynamicImageVolume,
operation: string,
frameNumbers?: number[]
);

Key Changes​

  1. operation now uses Enums.GenerateImageType enum.
  2. Frame numbers are passed in an options object.
  3. Function explicitly returns Float32Array.

Usage Example​

const result = generateImageFromTimeData(dynamicVolume, 'SUM', [0, 1, 2]);

Summary of Other Changes​

  • New updateVolumeFromTimeData function added for in-place volume updates.
  • Both functions now use voxelManager for improved performance.
  • Enhanced error handling and standardized error messages.
  • Operations now use Enums.GenerateImageType for better type safety.