Compare commits

...
Author SHA1 Message Date
ohif-bot a7b5f1847a chore(release): publish [skip ci]
- @ohif/extension-debugging@0.1.4
 - @ohif/extension-dicom-rt@0.4.4
 - @ohif/extension-dicom-segmentation@0.4.4
 - @ohif/viewer@4.5.8
2020-09-10 09:14:18 +00:00
James Petts 5cb6e63b88 [IDC-1672] Highlight SEG segment/ RT structure when click to jump. (#2034)
* Highlight for RTSTRUCT.

* SEG temp crosshairs.

* Disable RT highlighting for now.

* Remove TODO
2020-09-10 11:11:59 +02:00
ohif-bot 48eb4a9ec3 chore(release): publish [skip ci]
- @ohif/viewer@4.5.7
2020-09-09 13:00:24 +00:00
James Petts d9231fd431 Split query parameter calls. (#2035) 2020-09-09 14:59:07 +02:00
20 changed files with 373 additions and 28 deletions

No files matched your search

+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.1.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.1.3...@ohif/extension-debugging@0.1.4) (2020-09-10)
**Note:** Version bump only for package @ohif/extension-debugging
## 0.1.3 (2020-09-03)
**Note:** Version bump only for package @ohif/extension-debugging
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-debugging",
"version": "0.1.3",
"version": "0.1.4",
"description": "OHIF extension for debugging.",
"author": "OHIF",
"license": "MIT",
@@ -131,8 +131,6 @@ const getBrowserInfo = () => {
const getSeriesInstanceUIDsPerRow = viewports => {
const { viewportSpecificData, numColumns } = viewports;
debugger;
// NOTE viewportSpecificData is actually an object with numerical keys.
return Object.keys(viewportSpecificData).map(viewportIndex => {
const vsd = viewportSpecificData[viewportIndex];
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.4.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.4.3...@ohif/extension-dicom-rt@0.4.4) (2020-09-10)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.4.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.4.2...@ohif/extension-dicom-rt@0.4.3) (2020-09-03)
**Note:** Version bump only for package @ohif/extension-dicom-rt
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-rt",
"version": "0.4.3",
"version": "0.4.4",
"description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.",
"author": "OHIF",
"license": "MIT",
@@ -12,6 +12,9 @@ import StructureSetItem from '../StructureSetItem/StructureSetItem';
import RTPanelSettings from '../RTSettings/RTSettings';
import PanelSection from '../PanelSection/PanelSection';
import LoadingIndicator from '../LoadingIndicator/LoadingIndicator';
import TOOL_NAMES from '../../utils/toolNames';
const { RTSTRUCT_DISPLAY_TOOL } = TOOL_NAMES;
const { studyMetadataManager } = utils;
@@ -144,13 +147,16 @@ const RTPanel = ({
if (isCornerstone()) {
const enabledElements = cornerstone.getEnabledElements();
const element = enabledElements[activeIndex].element;
const toolState = cornerstoneTools.getToolState(element, 'stack');
const stackToolState = cornerstoneTools.getToolState(
element,
'stack'
);
if (!toolState) {
if (!stackToolState) {
return;
}
const imageIds = toolState.data[0].imageIds;
const imageIds = stackToolState.data[0].imageIds;
const module = cornerstoneTools.getModule('rtstruct');
const imageId = module.getters.imageIdOfCenterFrameOfROIContour(
@@ -159,6 +165,18 @@ const RTPanel = ({
imageIds
);
const toolState = cornerstoneTools.globalImageIdSpecificToolStateManager.saveToolState();
const imageIdSpecificToolState = toolState[imageId];
const rtstructData =
imageIdSpecificToolState[RTSTRUCT_DISPLAY_TOOL];
const specificData = rtstructData.data.find(
rtData => rtData.ROINumber === ROINumber
);
specificData.highlight = true;
const frameIndex = imageIds.indexOf(imageId);
const SOPInstanceUID = cornerstone.metaData.get(
'SOPInstanceUID',
@@ -1,6 +1,6 @@
import { importInternal, getToolState, toolColors } from 'cornerstone-tools';
import TOOL_NAMES from '../utils/toolNames';
import drawCanvasCrosshairs from '../utils/drawCanvasCrosshairs';
// Cornerstone 3rd party dev kit imports
const draw = importInternal('drawing/draw');
@@ -37,11 +37,17 @@ export default class RTStructDisplayTool extends BaseTool {
return;
}
const { lineWidth, opacity } = rtstructModule.configuration;
const {
lineWidth,
opacity,
highlightOpacity,
} = rtstructModule.configuration;
// We have tool data for this element - iterate over each one and draw it
const context = getNewContext(eventData.canvasContext.canvas);
let crossHairCenter;
for (let i = 0; i < toolState.data.length; i++) {
const data = toolState.data[i];
@@ -75,27 +81,51 @@ export default class RTStructDisplayTool extends BaseTool {
colorArray[2]
},${opacity})`;
let highlight = data.highlight;
const options = { color, lineWidth };
if (highlight) {
crossHairCenter = { x: 0, y: 0 };
points.forEach(point => {
crossHairCenter.x += point.x;
crossHairCenter.y += point.y;
});
crossHairCenter.x /= points.length;
crossHairCenter.y /= points.length;
// TODO: Disabling hightlight for now, it'd be good to bring it back
// when we have a good way of doing this for SEG.
// options.fillStyle = color = `rgba(${colorArray[0]},${colorArray[1]},${
// colorArray[2]
// },${highlightOpacity})`;
// Draw highlight lines.
delete data.highlight; // Don't highlight on next render.
}
switch (data.type) {
case 'CLOSED_PLANAR':
this._renderClosedPlanar(context, eventData.element, points, {
color,
lineWidth,
});
this._renderClosedPlanar(context, eventData.element, points, options);
break;
case 'POINT':
this._renderPoint(context, eventData.element, points, {
color,
lineWidth,
});
this._renderPoint(context, eventData.element, points, options);
break;
case 'OPEN_PLANAR':
this._renderOpenPlanar(context, eventData.element, points, {
color,
lineWidth,
});
this._renderOpenPlanar(context, eventData.element, points, options);
break;
}
}
if (crossHairCenter) {
drawCanvasCrosshairs(eventData, crossHairCenter, {
color: toolColors.getActiveColor(),
lineWidth: 1,
});
}
}
_renderClosedPlanar(context, element, points, options) {
@@ -13,7 +13,8 @@ function refreshViewport() {
const configuration = {
lineWidth: 3,
opacity: 1.0,
opacity: 0.75,
highlightOpacity: 0.5,
};
const state = {
@@ -0,0 +1,56 @@
import cornerstone from 'cornerstone-core';
import cornerstoneTools from 'cornerstone-tools';
const { importInternal } = cornerstoneTools;
const draw = importInternal('drawing/draw');
const drawLine = importInternal('drawing/drawLine');
const getNewContext = importInternal('drawing/getNewContext');
export default function _drawCanvasCrosshairs(eventData, center, options) {
const context = getNewContext(eventData.canvasContext.canvas);
const { element } = eventData;
const centerCanvas = cornerstone.pixelToCanvas(element, center);
const { clientWidth: width, clientHeight: height } = element;
const offset = 10;
draw(context, context => {
drawLine(
context,
element,
{ x: centerCanvas.x + offset, y: centerCanvas.y },
{ x: width, y: centerCanvas.y },
options,
'canvas'
);
drawLine(
context,
element,
{ x: centerCanvas.x - offset, y: centerCanvas.y },
{ x: 0, y: centerCanvas.y },
options,
'canvas'
);
drawLine(
context,
element,
{ x: centerCanvas.x, y: centerCanvas.y + offset },
{ x: centerCanvas.x, y: height },
options,
'canvas'
);
drawLine(
context,
element,
{ x: centerCanvas.x, y: centerCanvas.y - offset },
{ x: centerCanvas.x, y: 0 },
options,
'canvas'
);
});
}
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.4.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.4.3...@ohif/extension-dicom-segmentation@0.4.4) (2020-09-10)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.4.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.4.2...@ohif/extension-dicom-segmentation@0.4.3) (2020-09-03)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-segmentation",
"version": "0.4.3",
"version": "0.4.4",
"description": "OHIF extension for viewing segmentations in the 2D MPR view",
"author": "OHIF",
"license": "MIT",
@@ -5,6 +5,7 @@ import cornerstone from 'cornerstone-core';
import moment from 'moment';
import { utils, log } from '@ohif/core';
import { ScrollableArea, TableList, Icon } from '@ohif/ui';
import DICOMSegTempCrosshairsTool from '../../tools/DICOMSegTempCrosshairsTool';
import setActiveLabelmap from '../../utils/setActiveLabelMap';
import refreshViewports from '../../utils/refreshViewports';
@@ -334,6 +335,12 @@ const SegmentationPanel = ({
imageId
);
DICOMSegTempCrosshairsTool.addCrosshair(
element,
imageId,
segmentNumber
);
onSegmentItemClick({
StudyInstanceUID,
SOPInstanceUID,
@@ -1,4 +1,5 @@
import csTools from 'cornerstone-tools';
import DICOMSegTempCrosshairsTool from './tools/DICOMSegTempCrosshairsTool';
/**
*
@@ -17,4 +18,6 @@ export default function init({ servicesManager, configuration = {} }) {
alwaysEraseOnClick: true,
},
});
csTools.addTool(DICOMSegTempCrosshairsTool);
}
@@ -0,0 +1,127 @@
import cornerstoneTools, {
importInternal,
getToolState,
toolColors,
getModule,
globalImageIdSpecificToolStateManager,
} from 'cornerstone-tools';
import cornerstone from 'cornerstone-core';
import drawCanvasCrosshairs from '../utils/drawCanvasCrosshairs';
import TOOL_NAMES from './TOOL_NAMES';
const { DICOM_SEG_TEMP_CROSSHAIRS_TOOL } = TOOL_NAMES;
const { getters } = getModule('segmentation');
// Cornerstone 3rd party dev kit imports
const BaseTool = importInternal('base/BaseTool');
/**
* @class RTStructDisplayTool - Renders RTSTRUCT data in a read only manner (i.e. as an overlay).
* @extends cornerstoneTools.BaseTool
*/
export default class DICOMSegTempCrosshairsTool extends BaseTool {
constructor(props = {}) {
const defaultProps = {
mixins: ['enabledOrDisabledBinaryTool'],
name: DICOM_SEG_TEMP_CROSSHAIRS_TOOL,
};
const initialProps = Object.assign(defaultProps, props);
super(initialProps);
this._rtStructModule = cornerstoneTools.getModule('rtstruct');
}
renderToolData(evt) {
const eventData = evt.detail;
const { element } = eventData;
const toolState = getToolState(evt.currentTarget, this.name);
if (!toolState) {
return;
}
// We have tool data for this element - iterate over each one and draw it
for (let i = 0; i < toolState.data.length; i++) {
const data = toolState.data[i];
const crossHairCenter = data.center;
drawCanvasCrosshairs(eventData, crossHairCenter, {
color: toolColors.getActiveColor(),
lineWidth: 1,
});
// Remove the crosshairs, we only render them for one redraw.
toolState.data.pop();
}
}
}
DICOMSegTempCrosshairsTool.addCrosshair = (element, imageId, segmentNumber) => {
const labelmap3D = getters.labelmap3D(element);
const stackToolState = cornerstoneTools.getToolState(element, 'stack');
const enabledElement = cornerstone.getEnabledElement(element);
const { rows, columns } = enabledElement.image;
if (!stackToolState) {
return;
}
const imageIds = stackToolState.data[0].imageIds;
const imageIdIndex = imageIds.findIndex(imgId => imgId === imageId);
const labelmap2D = labelmap3D.labelmaps2D[imageIdIndex];
const { pixelData } = labelmap2D;
let xCenter = 0;
let yCenter = 0;
let count = 0;
for (let y = 0; y < rows; y++) {
for (let x = 0; x < columns; x++) {
if (pixelData[y * columns + x] === segmentNumber) {
count++;
xCenter += x + 0.5;
yCenter += y + 0.5;
}
}
}
xCenter /= count;
yCenter /= count;
const globalToolState = globalImageIdSpecificToolStateManager.saveToolState();
if (!globalToolState[imageId]) {
globalToolState[imageId] = {};
}
const imageIdSpecificToolState = globalToolState[imageId];
if (!imageIdSpecificToolState[DICOM_SEG_TEMP_CROSSHAIRS_TOOL]) {
imageIdSpecificToolState[DICOM_SEG_TEMP_CROSSHAIRS_TOOL] = { data: [] };
} else if (!imageIdSpecificToolState[DICOM_SEG_TEMP_CROSSHAIRS_TOOL].data) {
imageIdSpecificToolState[DICOM_SEG_TEMP_CROSSHAIRS_TOOL].data = [];
}
const toolSpecificData =
imageIdSpecificToolState[DICOM_SEG_TEMP_CROSSHAIRS_TOOL].data;
toolSpecificData.push({ center: { x: xCenter, y: yCenter }, segmentNumber });
// Enable the tool if not enabled for the element.
const tool = cornerstoneTools.getToolForElement(
element,
DICOM_SEG_TEMP_CROSSHAIRS_TOOL
);
if (tool.mode !== 'enabled') {
// If not already active or passive, set passive so contours render.
cornerstoneTools.setToolEnabled(DICOM_SEG_TEMP_CROSSHAIRS_TOOL);
}
};
@@ -0,0 +1,5 @@
const TOOL_NAMES = {
DICOM_SEG_TEMP_CROSSHAIRS_TOOL: 'DICOMSegTempCrosshairsTool',
};
export default TOOL_NAMES;
@@ -0,0 +1,56 @@
import cornerstone from 'cornerstone-core';
import cornerstoneTools from 'cornerstone-tools';
const { importInternal } = cornerstoneTools;
const draw = importInternal('drawing/draw');
const drawLine = importInternal('drawing/drawLine');
const getNewContext = importInternal('drawing/getNewContext');
export default function _drawCanvasCrosshairs(eventData, center, options) {
const context = getNewContext(eventData.canvasContext.canvas);
const { element } = eventData;
const centerCanvas = cornerstone.pixelToCanvas(element, center);
const { clientWidth: width, clientHeight: height } = element;
const offset = 10;
draw(context, context => {
drawLine(
context,
element,
{ x: centerCanvas.x + offset, y: centerCanvas.y },
{ x: width, y: centerCanvas.y },
options,
'canvas'
);
drawLine(
context,
element,
{ x: centerCanvas.x - offset, y: centerCanvas.y },
{ x: 0, y: centerCanvas.y },
options,
'canvas'
);
drawLine(
context,
element,
{ x: centerCanvas.x, y: centerCanvas.y + offset },
{ x: centerCanvas.x, y: height },
options,
'canvas'
);
drawLine(
context,
element,
{ x: centerCanvas.x, y: centerCanvas.y - offset },
{ x: centerCanvas.x, y: 0 },
options,
'canvas'
);
});
}
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [4.5.8](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.5.7...@ohif/viewer@4.5.8) (2020-09-10)
**Note:** Version bump only for package @ohif/viewer
## [4.5.7](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.5.6...@ohif/viewer@4.5.7) (2020-09-09)
**Note:** Version bump only for package @ohif/viewer
## [4.5.6](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.5.5...@ohif/viewer@4.5.6) (2020-09-03)
**Note:** Version bump only for package @ohif/viewer
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/viewer",
"version": "4.5.6",
"version": "4.5.8",
"description": "OHIF Viewer",
"author": "OHIF Contributors",
"license": "MIT",
@@ -50,12 +50,12 @@
"@babel/runtime": "^7.5.5",
"@ohif/core": "^2.10.4",
"@ohif/extension-cornerstone": "^2.9.4",
"@ohif/extension-debugging": "^0.1.3",
"@ohif/extension-debugging": "^0.1.4",
"@ohif/extension-dicom-html": "^1.2.7",
"@ohif/extension-dicom-microscopy": "^0.51.2",
"@ohif/extension-dicom-pdf": "^1.0.5",
"@ohif/extension-dicom-rt": "^0.4.3",
"@ohif/extension-dicom-segmentation": "^0.4.3",
"@ohif/extension-dicom-rt": "^0.4.4",
"@ohif/extension-dicom-segmentation": "^0.4.4",
"@ohif/extension-lesion-tracker": "^0.2.1",
"@ohif/extension-vtk": "^1.7.5",
"@ohif/i18n": "^0.52.8",
+1
View File
@@ -5,6 +5,7 @@ window.config = function(props) {
disableMeasurementPanel: true,
routerBasename: '/',
enableGoogleCloudAdapter: true,
splitQueryParameterCalls: true, // Allows the user to split QIDO SeriesInstanceUID filters into multiple calls, if the server does not support multi-valued query parameters.
enableGoogleCloudAdapterUI: false,
showStudyList: true,
filterQueryParam: true,
@@ -341,7 +341,10 @@ function ViewerRetrieveStudyData({
}
}
if (appConfig.enableGoogleCloudAdapter) {
if (
appConfig.splitQueryParameterCalls ||
appConfig.enableGoogleCloudAdapter
) {
retrieveParams.push(true); // Seperate SeriesInstanceUID filter calls.
}