Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | import * as Types from '../types';
import cache, { ImageVolume } from '../cache';
import { ViewportType } from '../enums';
/**
* Converts a volume viewport to a stack viewport.
*
* @param params - The parameters for the conversion.
* @param params.viewport - The volume viewport to convert.
* @param params.options - The conversion options.
* @param [params.options.viewportId] - The new stackViewportId, If not provided, the volume viewport id will be used.
* @param [params.options.background] - The background color of the stack viewport.
* @param [params.options.decache] - Whether to decache the volume. Defaults to false.
*
* @returns The converted stack viewport.
*/
async function convertVolumeToStackViewport({
viewport,
options,
}: {
viewport: Types.IVolumeViewport;
options: {
viewportId?: string;
background?: Types.Point3;
};
}): Promise<Types.IStackViewport> {
const volumeViewport = viewport;
const { id, element } = volumeViewport;
const renderingEngine = viewport.getRenderingEngine();
const imageIdIndex = viewport.getCurrentImageIdIndex();
const { background } = options;
const viewportId = options.viewportId || id;
const actorEntry = volumeViewport.getDefaultActor();
const { uid: volumeId } = actorEntry;
const volume = cache.getVolume(volumeId) as Types.IImageVolume;
if (!(volume instanceof ImageVolume)) {
throw new Error(
'Currently, you cannot decache a volume that is not an ImageVolume. So, unfortunately, volumes such as nifti (which are basic Volume, without imageIds) cannot be decached.'
);
}
const viewportInput = {
viewportId,
type: ViewportType.STACK,
element,
defaultOptions: {
background,
},
};
renderingEngine.enableElement(viewportInput);
// Get the stack viewport that was created
const stackViewport = <Types.IStackViewport>(
renderingEngine.getViewport(viewportId)
);
// So here we have two scenarios that we need to handle:
// 1. the volume was derived from a stack and we need to decache it, this is easy
// since we just need purge the volume from the cache and those images will get
// their copy of the image back
// 2. It was actually a native volume and we need to decache it, this is a bit more
// complicated since then we need to decide on the imageIds for it to get
// decached to
const hasCachedImages = volume.imageCacheOffsetMap.size > 0;
// Initialize the variable to hold the final result
let isAllImagesCached = false;
if (hasCachedImages) {
// Check if every imageId in the volume is in the _imageCache
isAllImagesCached = volume.imageIds.every((imageId) =>
cache.getImage(imageId)
);
}
const volumeUsedInOtherViewports = renderingEngine
.getVolumeViewports()
.find((vp) => vp.hasVolumeId(volumeId));
volume.decache(!volumeUsedInOtherViewports && isAllImagesCached);
const stack = [...volume.imageIds].reverse();
let imageIdIndexToJump = Math.max(
volume.imageIds.length - imageIdIndex - 1,
0
);
// Check to see if the image is already cached or not. If it's not, we will use another
// nearby imageId for the first image to jump to. There seem to be a lot of side effects
// if we jump to an image that is not cached in stack viewport while we convert
// from a volume viewport. For example, if we switch back and forth between stack and volume,
// and then try to jump to an image that is not cached, the image will not render at
// all when the full volume is filled. I'm not sure why yet.
const imageToJump = cache.getImage(stack[imageIdIndexToJump]);
if (!imageToJump) {
let minDistance = Infinity;
let minDistanceIndex = null;
stack.forEach((imageId, index) => {
const image = cache.getImage(imageId);
if (image) {
const distance = Math.abs(imageIdIndexToJump - index);
if (distance < minDistance) {
minDistance = distance;
minDistanceIndex = index;
}
}
});
imageIdIndexToJump = minDistanceIndex;
}
await stackViewport.setStack(stack, imageIdIndexToJump ?? 0);
// Render the image
stackViewport.render();
return stackViewport;
}
export { convertVolumeToStackViewport };
|