From fd0147b46437fe96977b57f8acaffc7e58be7bc3 Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Sun, 5 Nov 2023 14:20:13 -0500 Subject: [PATCH 1/2] feat(layers): use opacity transfer function except for PT Instead of a layer's opacity being uniform, despite voxel values, use the opacity points in the preset. Add a new preset, "2hot-opaque", with just one opacity point at 1 for use by PT/PET modality layers. --- src/components/VtkTwoView.vue | 24 +++++++++++++++++++- src/config.ts | 7 ++++++ src/store/view-configs/layers.ts | 27 ++++++++++++----------- src/store/view-configs/volume-coloring.ts | 3 +-- src/vtk/ColorMaps.ts | 8 ++++++- 5 files changed, 52 insertions(+), 17 deletions(-) diff --git a/src/components/VtkTwoView.vue b/src/components/VtkTwoView.vue index ff1e41bd5..542f9dc05 100644 --- a/src/components/VtkTwoView.vue +++ b/src/components/VtkTwoView.vue @@ -245,6 +245,7 @@ import { WL_HIST_BINS, } from '../constants'; import { useProxyManager } from '../composables/proxyManager'; +import { getShiftedOpacityFromPreset } from '../utils/vtk-helpers'; import { useLayersStore } from '../store/datasets-layers'; import { useViewCameraStore } from '../store/view-configs/camera'; import useLayerColoringStore from '../store/view-configs/layers'; @@ -815,7 +816,28 @@ export default defineComponent({ const pwf = proxyManager.getPiecewiseFunction(arrayName); pwf.setMode(vtkPiecewiseFunctionProxy.Mode.Points); pwf.setDataRange(...opFunc.mappingRange); - pwf.setPoints([[0, 1]]); // only slice mesh controls opacity + + switch (opFunc.mode) { + case vtkPiecewiseFunctionProxy.Mode.Gaussians: + pwf.setGaussians(opFunc.gaussians); + break; + case vtkPiecewiseFunctionProxy.Mode.Points: { + const opacityPoints = getShiftedOpacityFromPreset( + opFunc.preset, + opFunc.mappingRange, + opFunc.shift + ); + if (opacityPoints) { + pwf.setPoints(opacityPoints); + } + break; + } + case vtkPiecewiseFunctionProxy.Mode.Nodes: + pwf.setNodes(opFunc.nodes); + break; + default: + } + rep.setOpacity(blendConfig.opacity); // control color range manually diff --git a/src/config.ts b/src/config.ts index 2602fcbc9..eb8463441 100644 --- a/src/config.ts +++ b/src/config.ts @@ -255,6 +255,13 @@ export const DEFAULT_PRESET_BY_MODALITY: Record = { MR: 'CT-Coronary-Arteries-2', US: 'US-Fetal', }; +export const DEFAULT_PRESET = 'CT-AAA'; + +export const LAYER_PRESET_BY_MODALITY: Record = { + ...DEFAULT_PRESET_BY_MODALITY, + PT: '2hot-opaque', +}; +export const LAYER_PRESET_DEFAULT = 'Blue to Red Rainbow'; // Keyboard shortcuts/hotkeys. Can add modifiers: 'Shift+Ctrl+A' export const ACTION_TO_KEY = { diff --git a/src/store/view-configs/layers.ts b/src/store/view-configs/layers.ts index e7df49fa0..d24bc4817 100644 --- a/src/store/view-configs/layers.ts +++ b/src/store/view-configs/layers.ts @@ -14,29 +14,30 @@ import { } from '@/src/utils/doubleKeyRecord'; import { Maybe } from '@/src/types'; import { identity } from '@/src/utils'; +import { LAYER_PRESET_BY_MODALITY, LAYER_PRESET_DEFAULT } from '@/src/config'; import { createViewConfigSerializer } from './common'; -import { DEFAULT_PRESET } from '../../vtk/ColorMaps'; import { ViewConfig } from '../../io/state-file/schema'; import { LayersConfig } from './types'; import { LayerID, useLayersStore } from '../datasets-layers'; import { useDICOMStore } from '../datasets-dicom'; -export const MODALITY_TO_PRESET: Record = { - PT: '2hot', -}; - function getPreset(id: LayerID) { const layersStore = useLayersStore(); const layer = layersStore.getLayer(id); - if (layer) { - if (layer.selection.type === 'dicom') { - const dicomStore = useDICOMStore(); - const { Modality = undefined } = - dicomStore.volumeInfo[layer.selection.volumeKey]; - return (Modality && MODALITY_TO_PRESET[Modality]) || DEFAULT_PRESET; - } + if (!layer) { + throw new Error(`Layer ${id} not found`); + } + + if (layer.selection.type === 'dicom') { + const dicomStore = useDICOMStore(); + const { Modality = undefined } = + dicomStore.volumeInfo[layer.selection.volumeKey]; + return ( + (Modality && LAYER_PRESET_BY_MODALITY[Modality]) || LAYER_PRESET_DEFAULT + ); } - return DEFAULT_PRESET; + + return LAYER_PRESET_DEFAULT; } export const defaultLayersConfig = (): LayersConfig => ({ diff --git a/src/store/view-configs/volume-coloring.ts b/src/store/view-configs/volume-coloring.ts index 7ac4b2b07..21c06d78e 100644 --- a/src/store/view-configs/volume-coloring.ts +++ b/src/store/view-configs/volume-coloring.ts @@ -4,7 +4,7 @@ import { getColorFunctionRangeFromPreset, getOpacityFunctionFromPreset, } from '@/src/utils/vtk-helpers'; -import { DEFAULT_PRESET_BY_MODALITY } from '@/src/config'; +import { DEFAULT_PRESET_BY_MODALITY, DEFAULT_PRESET } from '@/src/config'; import { ColorTransferFunction } from '@/src/types/views'; import { defineStore } from 'pinia'; import { reactive } from 'vue'; @@ -17,7 +17,6 @@ import { import { DeepPartial, Maybe } from '@/src/types'; import { identity } from '@/src/utils'; import { createViewConfigSerializer } from './common'; -import { DEFAULT_PRESET } from '../../vtk/ColorMaps'; import { ViewConfig } from '../../io/state-file/schema'; import { VolumeColorConfig } from './types'; import { useDICOMStore } from '../datasets-dicom'; diff --git a/src/vtk/ColorMaps.ts b/src/vtk/ColorMaps.ts index 038bb6067..0a52d9995 100644 --- a/src/vtk/ColorMaps.ts +++ b/src/vtk/ColorMaps.ts @@ -9,6 +9,13 @@ function registerPresets(presets: typeof MedicalPresets) { registerPresets(MedicalPresets); +const twoHotOpaque = { + ...vtkColorMaps.getPresetByName('2hot'), + Name: '2hot-opaque', + OpacityPoints: [0, 1], +}; +vtkColorMaps.addPreset(twoHotOpaque); + /* prettier-ignore */ const GroupedPresets = [ { @@ -61,6 +68,5 @@ const GroupedPresets = [ }, ]; -export const DEFAULT_PRESET = 'CT-AAA'; export const PresetNameList = GroupedPresets.flatMap((group) => group.presets); export default GroupedPresets; From f9896c7e44b6a956375e8536968da0c69153b2c6 Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Mon, 6 Nov 2023 09:14:55 -0500 Subject: [PATCH 2/2] fix(MedicalColorPresets): add Blue to Red Rainbow preset Need to add here as vtk.js colormaps are excluded from built bundle. --- src/vtk/MedicalColorPresets.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vtk/MedicalColorPresets.json b/src/vtk/MedicalColorPresets.json index 69a6f74d1..db8dae432 100644 --- a/src/vtk/MedicalColorPresets.json +++ b/src/vtk/MedicalColorPresets.json @@ -1518,5 +1518,11 @@ 1, 1 ] + }, + { + "ColorSpace" : "HSV", + "Name" : "Blue to Red Rainbow", + "NanColor" : [ 0.498039215686, 0.498039215686, 0.498039215686 ], + "RGBPoints" : [ 0, 0, 0, 1, 1, 1, 0, 0 ] } ]