UNPKG

cornerstone-tools-cacalc

Version:

Medical imaging tools for the Cornerstone library with added functionality for computing Agatston calcium scores

290 lines (225 loc) 8.24 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>regions/thresholding.js - Documentation</title> <script src="scripts/prettify/prettify.js"></script> <script src="scripts/prettify/lang-css.js"></script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc.css"> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav> <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#applyWWWCRegion">applyWWWCRegion</a></li><li><a href="global.html#calculateMinMaxMean">calculateMinMaxMean</a></li><li><a href="global.html#createMagnificationCanvas">createMagnificationCanvas</a></li><li><a href="global.html#dragCallback">dragCallback</a></li><li><a href="global.html#drawMagnificationTool">drawMagnificationTool</a></li><li><a href="global.html#getPlayClipTimeouts">getPlayClipTimeouts</a></li><li><a href="global.html#mouseDownCallback">mouseDownCallback</a></li><li><a href="global.html#mouseUpCallback">mouseUpCallback</a></li><li><a href="global.html#onImageRendered">onImageRendered</a></li><li><a href="global.html#performThresholding">performThresholding</a></li><li><a href="global.html#playClip">playClip</a></li><li><a href="global.html#recordStartPoint">recordStartPoint</a></li><li><a href="global.html#removeMagnificationCanvas">removeMagnificationCanvas</a></li><li><a href="global.html#stopClip">stopClip</a></li><li><a href="global.html#stopClipWithData">stopClipWithData</a></li><li><a href="global.html#triggerStopEvent">triggerStopEvent</a></li></ul> </nav> <div id="main"> <h1 class="page-title">regions/thresholding.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>import * as cornerstone from 'cornerstone-core'; import { addToolState, getToolState } from '../stateManagement/toolState'; // UNUSED const toolType = 'thresholding'; let LASTELEMENT = null; export function getLastElement () { return LASTELEMENT; } const LABEL_SIZE_BYTES = 1; let configuration = { historySize: 4, historyPosition: 0, toolRegionValue: 2, calciumThresholdHu: 130, layersAbove: 0, layersBelow: 0, drawAlpha: 1, regionColorsRGB: [ [255, 0, 255], [246, 193, 91], [237, 148, 69], [230, 103, 49], [184, 74, 41], [106, 58, 45] ], kvpToMultiplier: { 140: 1.04, 130: 1.02, 120: 1, 110: 0.98, 100: 0.96, 90: 0.93, 80: 0.89, // add dummy for 70 70: 0.86, }, growIterationsPerChunk: 2 }; /** * Perform the thresholding on a stack */ function performThresholding (stack, afterwards) { let width, height; const imageIds = stack.imageIds; const slices = imageIds.length; // Get slope and intercept return cornerstone.loadImage(imageIds[0]).then(function (image) { width = image.width; height = image.height; const length = width * height * slices * LABEL_SIZE_BYTES; const buffer = new ArrayBuffer(length); const view = new Uint8Array(buffer); // Thresholding promises const promises = imageIds.map(function (imageId, imageIdx) { return cornerstone.loadImage(imageId).then(function (image) { const slope = image.slope; const intercept = image.intercept; const pixelData = image.getPixelData(); const n = width * height; for (let i = 0; i &lt; n; i++) { const pixel = pixelData[i]; const hu = (pixel * slope) + intercept; const label = (hu >= configuration.calciumThresholdHu) ? 1 : 0; const viewIdx = (imageIdx) * n + i; view[viewIdx] = label; } }); }); // Callback with buffer return Promise.all(promises).then(function () { const result = { buffer, width, height }; if (afterwards) { afterwards(result); } return result; }); }); } let imgdata = null; /** * Draw regions on image */ function onImageRendered (e, eventData) { const element = eventData.element; const stackData = getToolState(element, 'stack'); const thresholdingData = getToolState(element, 'regions'); if (!thresholdingData || !thresholdingData.data || !thresholdingData.data.length) { return; } const slice = stackData.data[0].currentImageIdIndex; const buffer = thresholdingData.data[0].buffer; const context = eventData.canvasContext; const enabledElement = eventData.enabledElement; const image = eventData.image; const width = image.width; const height = image.height; const doubleBuffer = document.createElement('canvas'); const doubleBufferContext = doubleBuffer.getContext('2d'); doubleBuffer.width = width; doubleBuffer.height = height; imgdata = imgdata || doubleBufferContext.createImageData(width, height); const pixels = imgdata.data; const sliceSize = width * height; const sliceOffset = slice * sliceSize; const view = new Uint8Array(buffer, sliceOffset, sliceSize); for (let i = 0; i &lt; view.length; i += 1) { const label = view[i]; const pi = i * 4; if (label) { const color = configuration.regionColorsRGB[label - 1]; pixels[pi + 0] = color[0]; pixels[pi + 1] = color[1]; pixels[pi + 2] = color[2]; pixels[pi + 3] = configuration.drawAlpha * 255; } else { pixels[pi + 3] = 0; } } doubleBufferContext.putImageData(imgdata, 0, 0); cornerstone.setToPixelCoordinateSystem(enabledElement, context); context.drawImage(doubleBuffer, 0, 0); } function enable (element) { LASTELEMENT = element; // First check that there is stack data available const stackData = getToolState(element, 'stack'); if (!stackData || !stackData.data || !stackData.data.length) { return; } const initialThresholdingData = { enabled: 1, buffer: null, width: null, height: null, history: [] }; addToolState(element, 'regions', initialThresholdingData); const stack = stackData.data[0]; performThresholding(stack, function (regions) { // Add threshold data to tool state const thresholdingData = getToolState(element, 'regions'); thresholdingData.data[0].buffer = regions.buffer; thresholdingData.data[0].width = regions.width; thresholdingData.data[0].height = regions.height; // Draw regions on image $(element).on('CornerstoneImageRendered', onImageRendered); // Update the element to apply the viewport and tool changes cornerstone.updateImage(element); }); } function disable (element) { const thresholdingData = getToolState(element, 'regions'); // If there is actually something to disable, disable it if (thresholdingData &amp;&amp; thresholdingData.data.length) { thresholdingData.data[0].enabled = false; } } export function createUndoStep (element) { const thresholdingData = getToolState(element, 'regions'); const state = thresholdingData.data[0]; // Make a copy using .slice() const current = state.buffer.slice(); // Put at end of history state.history.push(current); // Remove oldest if too much history if (state.history.length > configuration.historySize) { state.history.shift(); } } export function getConfiguration () { return configuration; } export function setConfiguration (config) { configuration = config; } // Module/private exports export default { activate: enable, deactivate: disable, enable, disable, getConfiguration, setConfiguration }; </code></pre> </article> </section> </div> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.4</a> using the <a href="https://github.com/clenemt/docdash">docdash</a> theme. </footer> <script>prettyPrint();</script> <script src="scripts/linenumber.js"></script> </body> </html>