diff --git a/src/composables/untilLoaded.ts b/src/composables/untilLoaded.ts new file mode 100644 index 00000000..f5d169e2 --- /dev/null +++ b/src/composables/untilLoaded.ts @@ -0,0 +1,10 @@ +import { computed, unref } from 'vue'; +import { until } from '@vueuse/core'; +import useChunkStore from '../store/chunks'; + +export function untilLoaded(imageID: string) { + const doneLoading = computed( + () => !unref(useChunkStore().chunkImageById[imageID].isLoading) + ); + return until(doneLoading).toBe(true); +} diff --git a/src/store/datasets-layers.ts b/src/store/datasets-layers.ts index d4954637..8fb42c5d 100644 --- a/src/store/datasets-layers.ts +++ b/src/store/datasets-layers.ts @@ -1,5 +1,4 @@ -import { computed, ref, unref } from 'vue'; -import { until } from '@vueuse/core'; +import { ref } from 'vue'; import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData'; import vtkBoundingBox from '@kitware/vtk.js/Common/DataModel/BoundingBox'; import { defineStore } from 'pinia'; @@ -8,7 +7,7 @@ import { Maybe } from '@/src/types'; import { ensureSameSpace } from '@/src/io/resample/resample'; import { useErrorMessage } from '../composables/useErrorMessage'; import { Manifest, StateFile } from '../io/state-file/schema'; -import useChunkStore from './chunks'; +import { untilLoaded } from '../composables/untilLoaded'; // differ from Image/Volume IDs with a branded type export type LayerID = string & { __type: 'LayerID' }; @@ -39,6 +38,9 @@ export const useLayersStore = defineStore('layer', () => { { selection: source, id } as Layer, ]; + // ensureSameSpace need final image array to resample, so wait for all chunks + await untilLoaded(source); + const [parentImage, sourceImage] = await Promise.all( [parent, source].map(getImage) ); @@ -68,12 +70,6 @@ export const useLayersStore = defineStore('layer', () => { parent: DataSelection, source: DataSelection ) { - // ensureSameSpace need final image array to resample, so wait for all chunks - const doneLoading = computed( - () => !unref(useChunkStore().chunkImageById[source].isLoading) - ); - await until(doneLoading).toBe(true); - return useErrorMessage('Failed to build layer', async () => { try { await this._addLayer(parent, source); diff --git a/src/store/segmentGroups.ts b/src/store/segmentGroups.ts index 599cdea4..f09b3d2a 100644 --- a/src/store/segmentGroups.ts +++ b/src/store/segmentGroups.ts @@ -26,6 +26,7 @@ import { import { FileEntry } from '../io/types'; import { ensureSameSpace } from '../io/resample/resample'; import { useDICOMStore } from './datasets-dicom'; +import { untilLoaded } from '../composables/untilLoaded'; const LabelmapArrayType = Uint8Array; export type LabelmapArrayType = Uint8Array; @@ -248,7 +249,8 @@ export const useSegmentGroupStore = defineStore('segmentGroup', () => { if (imageID === parentID) throw new Error('Cannot convert an image to be a labelmap of itself'); - // Build vtkImageData for DICOMs + await untilLoaded(imageID); + const [childImage, parentImage] = await Promise.all( [imageID, parentID].map(getImage) ); diff --git a/src/utils/allocateImageFromChunks.ts b/src/utils/allocateImageFromChunks.ts index d1d16c88..c7e31cd0 100644 --- a/src/utils/allocateImageFromChunks.ts +++ b/src/utils/allocateImageFromChunks.ts @@ -117,15 +117,15 @@ export function allocateImageFromChunks(sortedChunks: Chunk[]) { image.setSpacing([1, 1, 1]); if (slices > 1 && imagePositionPatient && pixelSpacing) { - const secondMeta = new Map(sortedChunks[1].metadata); - const secondIPP = toVec(secondMeta.get(ImagePositionPatientTag)); - if (secondIPP) { - const spacing = [...pixelSpacing, 1]; + const lastMeta = new Map(sortedChunks[sortedChunks.length - 1].metadata); + const lastIPP = toVec(lastMeta.get(ImagePositionPatientTag)); + if (lastIPP) { // assumption: uniform Z spacing const zVec = vec3.create(); const firstIPP = imagePositionPatient; - vec3.sub(zVec, secondIPP as vec3, firstIPP as vec3); - spacing[2] = vec3.len(zVec) || 1; + vec3.sub(zVec, lastIPP as vec3, firstIPP as vec3); + const zSpacing = vec3.len(zVec) / (sortedChunks.length - 1) || 1; + const spacing = [...pixelSpacing, zSpacing]; image.setSpacing(spacing); } }