diff --git a/lib/getImageData.js b/lib/getImageData.js index 2bb1c2b..5a29191 100644 --- a/lib/getImageData.js +++ b/lib/getImageData.js @@ -13,7 +13,7 @@ export function getImageData(displaySet) { const { metaData0, metaDataMap, imageIds, imageMetaData0 } = buildMetadata(displaySet); const {rowCosines, columnCosines} = metaData0; - const crossProduct = columnCosines.crossVectors(columnCosines, rowCosines); + const crossProduct = columnCosines.crossVectors(rowCosines, columnCosines); const orientation = determineOrientation(crossProduct); const zAxis = computeZAxis(orientation, metaDataMap); const xSpacing = metaData0.columnPixelSpacing; diff --git a/lib/ohifInteractorStyleSlice.js b/lib/ohifInteractorStyleSlice.js index 69c08d1..909f600 100644 --- a/lib/ohifInteractorStyleSlice.js +++ b/lib/ohifInteractorStyleSlice.js @@ -288,8 +288,8 @@ function ohifInteractorStyleSlice(publicAPI, model) { }; /** - * windowLevel: used VTK's default 8 bit window level. - * TODO make similar to OHIF + * windowLevel: + * * @param renderer * @param position */ @@ -297,7 +297,6 @@ function ohifInteractorStyleSlice(publicAPI, model) { model.windowLevelCurrentPosition[0] = position.x; model.windowLevelCurrentPosition[1] = position.y; const rwi = model.interactor; - if (model.currentImageProperty) { const size = rwi.getView().getViewportSize(renderer); @@ -305,16 +304,8 @@ function ohifInteractorStyleSlice(publicAPI, model) { const level = model.windowLevelInitial[1]; // Compute normalized delta - let dx = - (model.windowLevelCurrentPosition[0] - - model.windowLevelStartPosition[0]) * - 4.0 / - size[0]; - let dy = - (model.windowLevelStartPosition[1] - - model.windowLevelCurrentPosition[1]) * - 4.0 / - size[1]; + let dx = (model.windowLevelCurrentPosition[0] - model.windowLevelStartPosition[0]) / size[0]; + let dy = (model.windowLevelStartPosition[1] - model.windowLevelCurrentPosition[1]) / size[1]; // Scale by current values if (Math.abs(mWindow) > 0.01) { @@ -338,12 +329,29 @@ function ohifInteractorStyleSlice(publicAPI, model) { // Compute new mWindow level let newWindow = dx + mWindow; - const newLevel = level - dy; + let newLevel = level - dy; + + + const slice = publicAPI.findSlice(); + const image = slice.getMapper().getInputData(); + + const range = image.getPointData().getScalars().getRange(); - if (newWindow < 0.01) { - newWindow = 0.01; + // we limit the window to the positive distance between low and high + const distance = Math.abs(range[1] - range[0]); + if (newWindow > distance){ + newWindow = distance; } + // we limit the level to within the window. + if (newLevel < 0) { + newLevel = 0; + } + else if (newLevel > distance) { + newLevel = distance; + } + + model.currentImageProperty.setColorWindow(newWindow); model.currentImageProperty.setColorLevel(newLevel); let viewDirection = publicAPI.getViewDirection(); diff --git a/multiplanarReformatting/main.js b/multiplanarReformatting/main.js index b5a9d61..4dce97b 100644 --- a/multiplanarReformatting/main.js +++ b/multiplanarReformatting/main.js @@ -304,6 +304,14 @@ var MultiplanarReformattingPlugin = class MultiplanarReformattingPlugin extends view: genericRenderWindow, func: function(v){ v.getRenderWindow().render(); + const range = imageData.getPointData().getScalars().getRange(); + console.log(range); + let props = interactorStyle.findSlice(); + + if (props){ + props.getProperty().setColorWindow(range[1] - range[0]); + props.getProperty().setColorLevel(range[0] + ((range[1] - range[0]) / 2)); + } } }); @@ -320,6 +328,8 @@ var MultiplanarReformattingPlugin = class MultiplanarReformattingPlugin extends const actorBounds = actor.getBounds(); const percentage = VTKUtils.computeZoomPercentage(imageData.getSpacing(),mode,renderer,actorBounds,imageData.getBounds()); this.updateZoomText(viewDirection,percentage); + + } /** diff --git a/volumeRendering/main.js b/volumeRendering/main.js index e83ac13..0ebc95d 100644 --- a/volumeRendering/main.js +++ b/volumeRendering/main.js @@ -23,6 +23,133 @@ var VolumeRenderingPlugin = class VolumeRenderingPlugin extends OHIF.plugins.Vie volumeController.render(); } + + /** + * Set up the divs to receive the dynamic text later on, i.e. patient name, etc. + * @param divParentElement + * @param viewDirection + * @param displaySet + */ + setupViewportText(divParentElement,viewDirection,displaySet){ + // TODO , load style sheets. + divParentElement.style.position = "relative"; + divParentElement.style.color = '#91b9cd'; + + ///////// TOP LEFT + // NO TOP LEFT because of Volume Widget. + + //////////// BOT LEFT + const botLeftParent = document.createElement('div'); + botLeftParent.style.position="absolute"; + botLeftParent.style.bottom="10px"; + botLeftParent.style.left="10px"; + botLeftParent.id = viewDirection + "BottomLeft"; + const SeriesNumber = document.createElement('div'); + SeriesNumber.id = 'SeriesNumber'; + botLeftParent.appendChild(SeriesNumber); + + const SeriesDescription = document.createElement('div'); + botLeftParent.appendChild(SeriesDescription); + SeriesDescription.id = 'SeriesDescription'; + + /////////// TOP RIGHT + divParentElement.appendChild(botLeftParent); + const topRightParent = document.createElement('div'); + topRightParent.style.position="absolute"; + topRightParent.style.top="10px"; + topRightParent.style.right="10px"; + topRightParent.id = viewDirection + "TopRight"; + const PatientName = document.createElement('div'); + PatientName.id = 'PatientName'; + topRightParent.appendChild(PatientName); + const PatientId = document.createElement('div'); + divParentElement.appendChild(topRightParent); + PatientId.id = 'PatientId'; + topRightParent.appendChild(PatientId); + + const StudyDescription = document.createElement('div'); + StudyDescription.id = 'StudyDescription'; + topRightParent.appendChild(StudyDescription); + const SeriesDate = document.createElement('div'); + topRightParent.appendChild(SeriesDate); + SeriesDate.id = 'SeriesDate'; + + divParentElement.appendChild(topRightParent); + /////////// BOT RIGHT + const botRightParent = document.createElement('div'); + botRightParent.style.position="absolute"; + botRightParent.style.bottom="10px"; + botRightParent.id = viewDirection + "BotRight"; + botRightParent.style.right="10px"; + } + + static setText(parent, textMap){ + for (let [key, value] of textMap) { + parent.querySelector(key).innerHTML = value; + } + } + + static setBottomLeftText(viewDirection, displaySet){ + let botLeftParent = document.querySelector('#'+viewDirection+"BottomLeft"); + + const bottomLeftMap = new Map(); + let seriesNum = displaySet.seriesNumber; + let seriesDescription = displaySet.images[0]._series.seriesDescription.replace(/\^/g, " "); + bottomLeftMap.set("#SeriesNumber","Ser:" + " " + seriesNum); + bottomLeftMap.set("#SeriesDescription",seriesDescription); + VolumeRenderingPlugin.setText(botLeftParent,bottomLeftMap); + } + + static setTopRightText(viewDirection, displaySet){ + let topRightParent = document.querySelector('#'+viewDirection+"TopRight"); + + const topRightMap = new Map(); + let patientName = displaySet.images[0]._study.patientName.replace(/\^/g, " "); + let patientId = displaySet.images[0]._study.patientId; + + + let studyDescription = displaySet.images[0]._study.studyDescription.replace(/\^/g, " "); + let studyDate = displaySet.images[0]._study.studyDate; + + let seriesYear = parseInt(studyDate.substr(0,4),10); + let seriesMonth = parseInt(studyDate.substr(4,2),10); + let seriesDay = parseInt(studyDate.substr(6,2),10); + let studyTime = displaySet.images[0]._study.studyTime; + let splitTime = studyTime.split("."); + let leftTime = splitTime[0]; + let seriesHour = parseInt(leftTime.substr(0,2),10); + let seriesMinute = parseInt(leftTime.substr(2,2),10); + let seriesSecond = parseInt(leftTime.substr(4,2),10); + let sd = new Date(seriesYear, seriesMonth-1, seriesDay,seriesHour,seriesMinute,seriesSecond); + const options = { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: "numeric", + minute: "numeric", + second: "numeric", + hour12: false, + }; + let seriesDateString = sd.toLocaleDateString("en-US",options); + topRightMap.set("#PatientName",patientName); + topRightMap.set("#PatientId",patientId); + topRightMap.set("#StudyDescription",studyDescription); + topRightMap.set("#SeriesDate",seriesDateString); + VolumeRenderingPlugin.setText(topRightParent,topRightMap); + } + + + /** + * Updates the text. The viewDirection helps us find the correct divs. + * @param viewDirection + * @param displaySet + */ + updateViewportText(viewDirection,displaySet){ + VolumeRenderingPlugin.setBottomLeftText(viewDirection,displaySet); + VolumeRenderingPlugin.setTopRightText(viewDirection,displaySet); + } + + /** * Overriden from base class. Sets up the viewport based on the viewportData and the displaySet. * @param div @@ -31,7 +158,8 @@ var VolumeRenderingPlugin = class VolumeRenderingPlugin extends OHIF.plugins.Vie */ setupViewport(div, viewportData, displaySet) { const viewportWrapper = div.parentElement; - + const self = this; + let { viewDirection } = viewportData.pluginData; // Seems like VolumeRendering in 4-up is not fast enough to use progressive // updating and have a nice user experience. Added loading spinner instead. div.innerHTML = `
@@ -96,6 +224,9 @@ var VolumeRenderingPlugin = class VolumeRenderingPlugin extends OHIF.plugins.Vie controllerWidget.setContainer(viewportWrapper); VolumeRenderingPlugin.installVTKVolumeController(controllerWidget, genericRenderWindow, actor, isDark); + + self.setupViewportText(viewportWrapper, viewDirection, displaySet); + self.updateViewportText(viewDirection, displaySet); } // Don't load data until the viewports etc are set up (above).