Skip to main content

Overlays and thresholds

An overlay is any volume after the first. A common case is a statistical map drawn over an anatomical template, showing only the voxels that pass a threshold.

The demo loads an SPM motor-task map over the MNI152 template. Positive values use redyell and negative values use winter, each with its own threshold:

import NiiVue, { SHOW_RENDER } from '@niivue/niivue'

const demo = async (canvas, { ui, asset }) => {
const nv = new NiiVue({
isColorbarVisible: true,
showRender: SHOW_RENDER.ALWAYS,
backgroundColor: [0.1, 0.1, 0.1, 1],
})
await nv.attachToCanvas(canvas)
await nv.loadVolumes([
{
url: asset('volumes/mni152.nii.gz'),
calMin: 30,
calMax: 80,
isColorbarVisible: false,
},
{
url: asset('volumes/spmMotor.nii.gz'),
colormap: 'redyell',
colormapNegative: 'winter',
},
])

let pos = 3
let neg = 3
let colormapType = 0
const update = async () => {
await nv.setVolume(1, {
calMin: pos,
calMax: pos + 3,
calMinNeg: -neg,
calMaxNeg: -neg - 3,
colormapType,
})
}
await update()

ui.slider(
'+Thresh',
1,
6,
pos,
async (v) => {
pos = v
await update()
},
0.1,
)
ui.slider(
'-Thresh',
1,
6,
neg,
async (v) => {
neg = v
await update()
},
0.1,
)
// 0: min to max, 1: zero to max (transparent below), 2: zero to max (translucent below)
ui.select(
'Mode',
[
['min to max', '0'],
['zero to max, transparent', '1'],
['zero to max, translucent', '2'],
],
'0',
async (v) => {
colormapType = Number(v)
await update()
},
)
ui.slider(
'Outline',
0,
1,
0,
(v) => {
nv.volumeOutlineWidth = v
},
0.25,
)
return nv
}

export default demo

Positive and negative thresholds​

For an overlay, calMin is the threshold: voxels below it are transparent. calMax is where the colormap saturates. A signed map adds a second colormap and window for the negative side:

await nv.loadVolumes([
{ url: '/volumes/mni152.nii.gz', calMin: 30, calMax: 80, isColorbarVisible: false },
{ url: '/volumes/spmMotor.nii.gz', colormap: 'redyell', colormapNegative: 'winter' },
])
await nv.setVolume(1, { calMin: 3, calMax: 6, calMinNeg: -3, calMaxNeg: -6 })

The two sides do not have to match. calMinNeg and calMaxNeg default to NaN, which mirrors the positive window.

Colormap type​

colormapType decides how the colorbar relates to the threshold:

COLORMAP_TYPEColors spanBelow calMin
MIN_TO_MAX (0, default)calMin to calMaxtransparent
ZERO_TO_MAX_TRANSPARENT_BELOW_MIN (1)0 to calMaxtransparent
ZERO_TO_MAX_TRANSLUCENT_BELOW_MIN (2)0 to calMaxfades in (translucent)

Types 1 and 2 keep the color of a value the same as you move the threshold, which makes maps thresholded at different levels easier to compare:

import { COLORMAP_TYPE } from '@niivue/niivue'

await nv.setVolume(1, {
colormapType: COLORMAP_TYPE.ZERO_TO_MAX_TRANSLUCENT_BELOW_MIN,
})

Opacity and outlines​

opacity fades an overlay (0 to 1), and visible: false hides it while keeping its opacity:

await nv.setVolume(1, { opacity: 0.6 })

nv.volumeOutlineWidth outlines the suprathreshold clusters on 2D slices. The value is the outline width in overlay voxels; it applies to the whole viewer, and 0 (the default) turns it off.

Several overlays​

With two or more overlays, two viewer settings decide how overlapping voxels combine. volumeOverlayAlphaBlend combines their opacities and volumeOverlayColorBlend combines their colors:

import { OVERLAY_ALPHA_BLEND, OVERLAY_COLOR_BLEND } from '@niivue/niivue'

nv.volumeOverlayAlphaBlend = OVERLAY_ALPHA_BLEND.UNION
nv.volumeOverlayColorBlend = OVERLAY_COLOR_BLEND.OVER
Setting0 (default)12
volumeOverlayAlphaBlendMAX: the most opaque winsADDITIVE: opacities add, capped at 1UNION: 1 - prod(1 - a)
volumeOverlayColorBlendADDITIVE: opacity-weighted sumMEAN: opacity-weighted averageOVER: later overlays on top

Alpha UNION with colour OVER gives ordinary layered compositing, in volume order. Colour OVER with another alpha mode changes only the opacity. UNION was named OVER before 1.0. ADDITIVE alpha suits fractions that sum to 1, such as tissue probability maps. NiiVue 0.x had only the MAX and ADDITIVE defaults.

Label volumes, where each value names a region, work differently; see Atlases and labels.