UNPKG

@cornerstonejs/core

Version:
54 lines (53 loc) 2.09 kB
import VOILUTFunctionType from '../enums/VOILUTFunctionType.js'; import { logit } from './logit.js'; import * as windowLevelUtil from './windowLevel.js'; const Y_EPS = 1e-6; export function mapScalarToViewportVoiIntensity(value, props) { const { lower, upper } = props.voiRange; const span = upper - lower; const fn = props.VOILUTFunction; const applyInvert = (y) => (props.invert === true ? 1 - y : y); if (fn === VOILUTFunctionType.SAMPLED_SIGMOID || fn === 'SIGMOID') { const { windowCenter, windowWidth } = windowLevelUtil.toWindowLevel(lower, upper); const w = Math.max(Math.abs(windowWidth), 1e-12); return applyInvert(1 / (1 + Math.exp((-4 * (value - windowCenter)) / w))); } if (span === 0 || !Number.isFinite(span)) { return applyInvert(0); } return applyInvert(clamp01((value - lower) / span)); } export function mapViewportVoiIntensityToScalar(mapped01, props) { const { lower, upper } = props.voiRange; const fn = props.VOILUTFunction; const y = props.invert === true ? clamp01(1 - clamp01(mapped01)) : clamp01(mapped01); if (fn === VOILUTFunctionType.SAMPLED_SIGMOID || fn === 'SIGMOID') { const { windowCenter, windowWidth } = windowLevelUtil.toWindowLevel(lower, upper); const yy = clamp(y, Y_EPS, 1 - Y_EPS); return logit(yy, windowCenter, windowWidth); } const span = upper - lower; if (span === 0 || !Number.isFinite(span)) { return lower; } return lower + y * span; } export function mapMappedBandToRawRange(mappedMin, mappedMax, props) { const a = Math.min(mappedMin, mappedMax); const b = Math.max(mappedMin, mappedMax); const rawAtA = mapViewportVoiIntensityToScalar(a, props); const rawAtB = mapViewportVoiIntensityToScalar(b, props); return { rawMin: Math.min(rawAtA, rawAtB), rawMax: Math.max(rawAtA, rawAtB), }; } function clamp01(x) { if (!Number.isFinite(x)) { return 0; } return clamp(x, 0, 1); } function clamp(x, lo, hi) { return Math.min(hi, Math.max(lo, x)); }