Skip to content

Commit

Permalink
feat(SegmentGroup): convert a loaded image to labelmap/segmentGroup
Browse files Browse the repository at this point in the history
  • Loading branch information
jadh4v committed Dec 21, 2023
1 parent 80f534c commit 37e7622
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 3 deletions.
33 changes: 32 additions & 1 deletion src/components/ImageDataBrowser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ItemGroup from '@/src/components/ItemGroup.vue';
import GroupableItem from '@/src/components/GroupableItem.vue';
import ImageListCard from '@/src/components/ImageListCard.vue';
import { createVTKImageThumbnailer } from '@/src/core/thumbnailers/vtk-image';
import { useSegmentGroupStore } from '@/src/store/segmentGroups';
import { useImageStore } from '../store/datasets-images';
import { useDICOMStore } from '../store/datasets-dicom';
import {
Expand All @@ -30,6 +31,7 @@ export default defineComponent({
const dicomStore = useDICOMStore();
const dataStore = useDatasetStore();
const layersStore = useLayersStore();
const segmentGroupStore = useSegmentGroupStore();
const primarySelection = computed(() => dataStore.primarySelection);
Expand Down Expand Up @@ -62,7 +64,8 @@ export default defineComponent({
const isLayer = layerImageIDs.includes(id);
const layerLoaded = loadedLayerImageIDs.includes(id);
const layerLoading = isLayer && !layerLoaded;
const layerable = id !== selectedImageID && primarySelection.value;
const layerable =
id !== selectedImageID && primarySelection.value != null;
return {
id,
cacheKey: imageCacheKey(id),
Expand Down Expand Up @@ -132,6 +135,15 @@ export default defineComponent({
selected.value = [];
}
function convertToLabelMap(key: string) {
if (primarySelection.value) {
segmentGroupStore.convertImageToLabelmap(
{ type: 'image', dataID: key },
primarySelection.value
);
}
}
function removeData(id: string) {
imageStore.deleteData(id);
}
Expand All @@ -143,6 +155,7 @@ export default defineComponent({
toggleSelectAll,
removeSelection,
removeData,
convertToLabelMap,
images,
thumbnails,
primarySelection,
Expand Down Expand Up @@ -244,6 +257,24 @@ export default defineComponent({
<span v-else>Add as layer</span>
</template>
</v-list-item>
<v-list-item
@click="
image.layerable ? convertToLabelMap(image.id) : null
"
>
<v-icon v-if="!image.layerable" class="mr-1"
>mdi-alert</v-icon
>
Convert to Segment Group
<v-tooltip
activator="parent"
location="end"
max-width="200px"
:disabled="image.layerable"
>
Must load a background image before converting
</v-tooltip>
</v-list-item>
<v-list-item @click="removeData(image.id)">
Delete
</v-list-item>
Expand Down
63 changes: 61 additions & 2 deletions src/components/SegmentGroupControls.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<script setup lang="ts">
import SegmentList from '@/src/components/SegmentList.vue';
import { useCurrentImage } from '@/src/composables/useCurrentImage';
import { selectionEquals, useDatasetStore } from '@/src/store/datasets';
import { useDICOMStore } from '@/src/store/datasets-dicom';
import { useImageStore } from '@/src/store/datasets-images';
import { useSegmentGroupStore } from '@/src/store/segmentGroups';
import { usePaintToolStore } from '@/src/store/tools/paint';
import { Maybe } from '@/src/types';
Expand All @@ -10,6 +13,9 @@ const UNNAMED_GROUP_NAME = 'Unnamed Segment Group';
const segmentGroupStore = useSegmentGroupStore();
const { currentImageID } = useCurrentImage();
const imageStore = useImageStore();
const dicomStore = useDICOMStore();
const dataStore = useDatasetStore();
const currentSegmentGroups = computed(() => {
if (!currentImageID.value) return [];
Expand Down Expand Up @@ -110,14 +116,40 @@ function createSegmentGroup() {
startEditing(id);
}
// Filter and collect all acceptable images, excluding
// the current background image, that can be converted into
// a SegmentGroup (labelmap) for the current background image.
const nonDICOMImages = computed(() => {
const primarySelection = dataStore.primarySelection;
const ids = imageStore.idList.filter(
(id) =>
!(id in dicomStore.imageIDToVolumeKey) &&
primarySelection &&
!selectionEquals({ type: 'image', dataID: id }, primarySelection)
);
return ids.map((id) => ({ id, name: imageStore.metadata[id].name }));
});
function createSegmentGroupFromImage(selectedImageID: string) {
if (!selectedImageID) {
throw new Error('Cannot create a labelmap without a base image');
}
const primarySelection = dataStore.primarySelection;
if (primarySelection) {
segmentGroupStore.convertImageToLabelmap(
{ type: 'image', dataID: selectedImageID },
primarySelection
);
}
}
</script>

<template>
<div class="my-2" v-if="currentImageID">
<div
class="text-grey text-subtitle-2 d-flex flex-row align-center justify-space-between mb-2"
class="text-grey text-subtitle-2 d-flex align-center justify-space-evenly mb-2"
>
<div>Segment Groups</div>
<v-btn
variant="tonal"
color="secondary"
Expand All @@ -126,6 +158,33 @@ function createSegmentGroup() {
>
<v-icon class="mr-1">mdi-plus</v-icon> New Group
</v-btn>
<v-menu location="bottom">
<template v-slot:activator="{ props }">
<v-btn
variant="tonal"
color="secondary"
density="compact"
v-bind="props"
>
<v-icon class="mr-1">mdi-chevron-down</v-icon>From Image
</v-btn>
</template>
<v-list v-if="nonDICOMImages.length !== 0">
<v-list-item
v-for="(item, index) in nonDICOMImages"
:key="index"
@click="createSegmentGroupFromImage(item.id)"
>
{{ item.name }}
<v-tooltip activator="parent" location="end" max-width="200px">
Convert to segment group
</v-tooltip>
</v-list-item>
</v-list>
<v-list v-else>
<v-list-item class="font-italic" title="No eligible images found" />
</v-list>
</v-menu>
</div>
<v-divider />
<v-radio-group
Expand Down

0 comments on commit 37e7622

Please sign in to comment.