Compare commits

..
Author SHA1 Message Date
ohif-bot 87d5c68e71 chore(release): publish [skip ci]
- @ohif/extension-dicom-rt@0.3.0
 - @ohif/viewer@4.3.1
2020-08-10 12:18:19 +00:00
James Petts 0e87ab37c2 feat: 🎸 Add support for POINT and OPEN_PLANAR for RT
* feat: 🎸 Add support for POINT and OPEN_PLANAR for RT
2020-08-10 14:16:19 +02:00
ohif-bot 756b005fe1 chore(release): publish [skip ci]
- @ohif/viewer@4.3.0
2020-08-10 09:42:47 +00:00
James Petts 3d86b5f876 feat: 🎸 Optional disable measurements panel in app config (#1912)
Can disable the measurements panel by adding disableMeasurementPanel:
true to the appConfig.

Closes: #1864
2020-08-10 11:40:11 +02:00
ohif-bot 2a647fd618 chore(release): publish [skip ci]
- @ohif/extension-dicom-rt@0.2.7
 - @ohif/extension-dicom-segmentation@0.3.4
 - @ohif/extension-vtk@1.6.10
 - @ohif/core@2.9.14
 - @ohif/viewer@4.2.16
2020-08-10 09:21:53 +00:00
James Petts f8fc31bcac [IDC-1670] Better display of derived datasets in side panel. (#1962)
* WIP

* WIP

* WIP

* WIP

* Working click on seg.

* Load SEG if not loaded and set active.

* RTSTRUCT

* feat: 🎸 Display SEG and RTSTRUCT in side panel

* Throw error if dataset not available.

* Add delay in microscopy viewer e2e test.

* Add delay in microscopy viewer e2e test.
2020-08-10 11:20:31 +02:00
27 changed files with 396 additions and 126 deletions

No files matched your search

+19
View File
@@ -3,6 +3,25 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [0.3.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.2.7...@ohif/extension-dicom-rt@0.3.0) (2020-08-10)
### Features
* 🎸 Add support for POINT and OPEN_PLANAR for RT ([0e87ab3](https://github.com/OHIF/Viewers/commit/0e87ab37c29fcf9af74bbcefca854c6e6b8707bc))
## [0.2.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.2.6...@ohif/extension-dicom-rt@0.2.7) (2020-08-10)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.2.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.2.5...@ohif/extension-dicom-rt@0.2.6) (2020-08-05) ## [0.2.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.2.5...@ohif/extension-dicom-rt@0.2.6) (2020-08-05)
**Note:** Version bump only for package @ohif/extension-dicom-rt **Note:** Version bump only for package @ohif/extension-dicom-rt
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/extension-dicom-rt", "name": "@ohif/extension-dicom-rt",
"version": "0.2.6", "version": "0.3.0",
"description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.", "description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
@@ -1,5 +1,6 @@
import { MODULE_TYPES, utils, DICOMWeb } from '@ohif/core'; import { MODULE_TYPES, utils, DICOMWeb } from '@ohif/core';
import loadRTStruct from './loadRTStruct'; import loadRTStruct from './loadRTStruct';
import getSourceDisplaySet from './getSourceDisplaySet';
import id from './id'; import id from './id';
@@ -67,6 +68,10 @@ const OHIFDicomRTStructSopClassHandler = {
} }
} }
rtStructDisplaySet.getSourceDisplaySet = function(studies) {
return getSourceDisplaySet(studies, rtStructDisplaySet);
};
rtStructDisplaySet.load = function(referencedDisplaySet, studies) { rtStructDisplaySet.load = function(referencedDisplaySet, studies) {
return loadRTStruct( return loadRTStruct(
rtStructDisplaySet, rtStructDisplaySet,
@@ -242,7 +242,7 @@ const RTPanel = ({
key={SeriesInstanceUID} key={SeriesInstanceUID}
title={metadata.StructureSetLabel} title={metadata.StructureSetLabel}
loading={!isLoaded || !loadedSet} loading={!isLoaded || !loadedSet}
visible={isLoaded && loadedSet.visible} visible={isLoaded && loadedSet && loadedSet.visible}
hideVisibleButton={!isLoaded} hideVisibleButton={!isLoaded}
expanded={ expanded={
isLoaded && isLoaded &&
@@ -0,0 +1,38 @@
export default function getSourceDisplaySet(studies, rtStructDisplaySet) {
const referencedDisplaySet = _getReferencedDisplaySet(
rtStructDisplaySet,
studies
);
rtStructDisplaySet.load(referencedDisplaySet, studies);
return referencedDisplaySet;
}
const _getReferencedDisplaySet = (rtStructDisplaySet, studies) => {
let allDisplaySets = [];
studies.forEach(study => {
allDisplaySets = allDisplaySets.concat(study.displaySets);
});
const otherDisplaySets = allDisplaySets.filter(
ds => ds.displaySetInstanceUID !== rtStructDisplaySet.displaySetInstanceUID
);
const ReferencedSeriesSequence = Array.isArray(
rtStructDisplaySet.metadata.ReferencedSeriesSequence
)
? rtStructDisplaySet.metadata.ReferencedSeriesSequence
: [rtStructDisplaySet.metadata.ReferencedSeriesSequence];
const referencedSeriesInstanceUIDs = ReferencedSeriesSequence.map(
ReferencedSeries => ReferencedSeries.SeriesInstanceUID
);
const referencedDisplaySet = otherDisplaySets.find(ds =>
referencedSeriesInstanceUIDs.includes(ds.SeriesInstanceUID)
);
return referencedDisplaySet;
};
+21 -11
View File
@@ -76,21 +76,15 @@ export default async function loadRTStruct(
const isSupported = false; const isSupported = false;
for (let c = 0; c < ContourSequence.length; c++) { const ContourSequenceArray = _toArray(ContourSequence);
for (let c = 0; c < ContourSequenceArray.length; c++) {
const { const {
ContourImageSequence, ContourImageSequence,
ContourData, ContourData,
NumberOfContourPoints, NumberOfContourPoints,
ContourGeometricType, ContourGeometricType,
} = ContourSequence[c]; } = ContourSequenceArray[c];
if (ContourGeometricType !== 'CLOSED_PLANAR') {
// TODO: Do we want to visualise types other than closed planar?
// We could easily do open planar and point.
continue;
}
isSupported = true;
const sopInstanceUID = ContourImageSequence.ReferencedSOPInstanceUID; const sopInstanceUID = ContourImageSequence.ReferencedSOPInstanceUID;
const imageId = _getImageId(imageIdSopInstanceUidPairs, sopInstanceUID); const imageId = _getImageId(imageIdSopInstanceUidPairs, sopInstanceUID);
@@ -102,6 +96,13 @@ export default async function loadRTStruct(
const imagePlane = cornerstone.metaData.get('imagePlaneModule', imageId); const imagePlane = cornerstone.metaData.get('imagePlaneModule', imageId);
const points = []; const points = [];
let measurementData;
switch (ContourGeometricType) {
case 'CLOSED_PLANAR':
case 'OPEN_PLANAR':
case 'POINT':
isSupported = true;
for (let p = 0; p < NumberOfContourPoints * 3; p += 3) { for (let p = 0; p < NumberOfContourPoints * 3; p += 3) {
points.push({ points.push({
@@ -113,15 +114,20 @@ export default async function loadRTStruct(
transformPointsToImagePlane(points, imagePlane); transformPointsToImagePlane(points, imagePlane);
const measurementData = { measurementData = {
handles: { handles: {
points, points,
}, },
type: ContourGeometricType,
structureSetSeriesInstanceUid: rtStructDataset.SeriesInstanceUID, structureSetSeriesInstanceUid: rtStructDataset.SeriesInstanceUID,
ROINumber: ReferencedROINumber, ROINumber: ReferencedROINumber,
}; };
imageIdSpecificToolData.push(measurementData); imageIdSpecificToolData.push(measurementData);
break;
default:
continue;
}
} }
_setROIContourMetadata( _setROIContourMetadata(
@@ -314,3 +320,7 @@ function _getImageIdSopInstanceUidPairsForDisplaySet(
}; };
}); });
} }
function _toArray(objOrArray) {
return Array.isArray(objOrArray) ? objOrArray : [objOrArray];
}
@@ -4,6 +4,7 @@ import TOOL_NAMES from '../utils/toolNames';
// Cornerstone 3rd party dev kit imports // Cornerstone 3rd party dev kit imports
const draw = importInternal('drawing/draw'); const draw = importInternal('drawing/draw');
const drawCircle = importInternal('drawing/drawCircle');
const drawJoinedLines = importInternal('drawing/drawJoinedLines'); const drawJoinedLines = importInternal('drawing/drawJoinedLines');
const getNewContext = importInternal('drawing/getNewContext'); const getNewContext = importInternal('drawing/getNewContext');
const BaseTool = importInternal('base/BaseTool'); const BaseTool = importInternal('base/BaseTool');
@@ -74,20 +75,50 @@ export default class RTStructDisplayTool extends BaseTool {
colorArray[2] colorArray[2]
},${opacity})`; },${opacity})`;
lineWidth; switch (data.type) {
case 'CLOSED_PLANAR':
this._renderClosedPlanar(context, eventData.element, points, {
color,
lineWidth,
});
break;
case 'POINT':
this._renderPoint(context, eventData.element, points, {
color,
lineWidth,
});
break;
case 'OPEN_PLANAR':
this._renderOpenPlanar(context, eventData.element, points, {
color,
lineWidth,
});
break;
}
}
}
_renderClosedPlanar(context, element, points, options) {
draw(context, context => { draw(context, context => {
drawJoinedLines( drawJoinedLines(
context, context,
eventData.element, element,
points[points.length - 1], points[points.length - 1],
points, points,
{ options
color,
lineWidth,
}
); );
}); });
} }
_renderPoint(context, element, points, options) {
draw(context, context => {
drawCircle(context, element, points[0], 3, options);
});
}
_renderOpenPlanar(context, element, points, options) {
draw(context, context => {
drawJoinedLines(context, element, points[0], points, options);
});
} }
} }
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.3.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.3.3...@ohif/extension-dicom-segmentation@0.3.4) (2020-08-10)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.3.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.3.2...@ohif/extension-dicom-segmentation@0.3.3) (2020-07-13) ## [0.3.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.3.2...@ohif/extension-dicom-segmentation@0.3.3) (2020-07-13)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation **Note:** Version bump only for package @ohif/extension-dicom-segmentation
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/extension-dicom-segmentation", "name": "@ohif/extension-dicom-segmentation",
"version": "0.3.3", "version": "0.3.4",
"description": "OHIF extension for viewing segmentations in the 2D MPR view", "description": "OHIF extension for viewing segmentations in the 2D MPR view",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
@@ -6,6 +6,9 @@ import moment from 'moment';
import { utils, log } from '@ohif/core'; import { utils, log } from '@ohif/core';
import { ScrollableArea, TableList, Icon } from '@ohif/ui'; import { ScrollableArea, TableList, Icon } from '@ohif/ui';
import setActiveLabelmap from '../../utils/setActiveLabelMap';
import refreshViewports from '../../utils/refreshViewports';
import { import {
BrushColorSelector, BrushColorSelector,
BrushRadius, BrushRadius,
@@ -19,12 +22,6 @@ import SegmentationSettings from '../SegmentationSettings/SegmentationSettings';
const { studyMetadataManager } = utils; const { studyMetadataManager } = utils;
const refreshViewport = () => {
cornerstone.getEnabledElements().forEach(enabledElement => {
cornerstone.updateImage(enabledElement.element);
});
};
/** /**
* SegmentationPanel component * SegmentationPanel component
* *
@@ -68,8 +65,7 @@ const SegmentationPanel = ({
*/ */
const [state, setState] = useState({ const [state, setState] = useState({
brushRadius: DEFAULT_BRUSH_RADIUS, brushRadius: DEFAULT_BRUSH_RADIUS,
brushColor: brushColor: 'rgba(221, 85, 85, 1)',
'rgba(221, 85, 85, 1)',
selectedSegment: null, selectedSegment: null,
selectedSegmentation: null, selectedSegmentation: null,
showSegmentationSettings: false, showSegmentationSettings: false,
@@ -78,7 +74,7 @@ const SegmentationPanel = ({
segmentList: [], segmentList: [],
cachedSegmentsProperties: [], cachedSegmentsProperties: [],
isLoading: false, isLoading: false,
isDisabled: true isDisabled: true,
}); });
useEffect(() => { useEffect(() => {
@@ -112,7 +108,10 @@ const SegmentationPanel = ({
* allows us to easily watch the module or the segmentations loading process in any other component * allows us to easily watch the module or the segmentations loading process in any other component
* without subscribing to external events. * without subscribing to external events.
*/ */
document.addEventListener('extensiondicomsegmentationsegloaded', refreshSegmentations); document.addEventListener(
'extensiondicomsegmentationsegloaded',
refreshSegmentations
);
/* /*
* These are specific to each element; * These are specific to each element;
@@ -127,7 +126,10 @@ const SegmentationPanel = ({
); );
return () => { return () => {
document.removeEventListener('extensiondicomsegmentationsegloaded', refreshSegmentations); document.removeEventListener(
'extensiondicomsegmentationsegloaded',
refreshSegmentations
);
cornerstoneTools.store.state.enabledElements.forEach(enabledElement => cornerstoneTools.store.state.enabledElements.forEach(enabledElement =>
enabledElement.removeEventListener( enabledElement.removeEventListener(
'cornerstonetoolslabelmapmodified', 'cornerstonetoolslabelmapmodified',
@@ -169,26 +171,29 @@ const SegmentationPanel = ({
selectedSegmentation: brushStackState.activeLabelmapIndex, selectedSegmentation: brushStackState.activeLabelmapIndex,
labelmapList, labelmapList,
segmentList, segmentList,
isDisabled isDisabled,
})); }));
} else { } else {
setState(state => ({ setState(state => ({
...state, ...state,
labelmapList: [], labelmapList: [],
segmentList: [], segmentList: [],
isDisabled isDisabled,
})); }));
} }
} }
}, [ }, [viewports, activeIndex, state.isLoading]);
viewports,
activeIndex,
state.isLoading
]);
useEffect(() => { useEffect(() => {
refreshSegmentations(); refreshSegmentations();
}, [viewports, activeIndex, isOpen, state.selectedSegmentation, activeContexts, state.isLoading]); }, [
viewports,
activeIndex,
isOpen,
state.selectedSegmentation,
activeContexts,
state.isLoading,
]);
/* Handle open/closed panel behaviour */ /* Handle open/closed panel behaviour */
useEffect(() => { useEffect(() => {
@@ -223,12 +228,10 @@ const SegmentationPanel = ({
title: displayDescription, title: displayDescription,
description: displayDate, description: displayDate,
onClick: async () => { onClick: async () => {
const activatedLabelmapIndex = await _setActiveLabelmap( const activatedLabelmapIndex = await setActiveLabelmap(
activeViewport, activeViewport,
studies, studies,
displaySet, displaySet,
firstImageId,
brushStackState.activeLabelmapIndex,
() => onSelectedSegmentationChange(), () => onSelectedSegmentationChange(),
onDisplaySetLoadFailure onDisplaySetLoadFailure
); );
@@ -376,9 +379,13 @@ const SegmentationPanel = ({
return !segmentsHidden[segmentIndex]; return !segmentsHidden[segmentIndex];
}; };
const cachedSegmentProperties = state.cachedSegmentsProperties[segmentNumber]; const cachedSegmentProperties =
state.cachedSegmentsProperties[segmentNumber];
let visible = isSegmentVisible(); let visible = isSegmentVisible();
if (cachedSegmentProperties && cachedSegmentProperties.visible !== visible) { if (
cachedSegmentProperties &&
cachedSegmentProperties.visible !== visible
) {
toggleSegmentVisibility(); toggleSegmentVisibility();
} }
@@ -406,8 +413,10 @@ const SegmentationPanel = ({
onSegmentVisibilityChange(segmentNumber, newVisibility); onSegmentVisibilityChange(segmentNumber, newVisibility);
} }
updateCachedSegmentsProperties(segmentNumber, { visible: newVisibility }); updateCachedSegmentsProperties(segmentNumber, {
refreshViewport(); visible: newVisibility,
});
refreshViewports();
}} }}
/> />
); );
@@ -429,10 +438,9 @@ const SegmentationPanel = ({
const segmentsProperties = state.cachedSegmentsProperties; const segmentsProperties = state.cachedSegmentsProperties;
const segmentProperties = state.cachedSegmentsProperties[segmentNumber]; const segmentProperties = state.cachedSegmentsProperties[segmentNumber];
segmentsProperties[segmentNumber] = segmentsProperties[segmentNumber] = segmentProperties
segmentProperties ? ? { ...segmentProperties, ...properties }
{ ...segmentProperties, ...properties } : : properties;
properties;
updateState('cachedSegmentsProperties', segmentsProperties); updateState('cachedSegmentsProperties', segmentsProperties);
}; };
@@ -499,10 +507,13 @@ const SegmentationPanel = ({
configuration.fillAlphaInactive = newConfiguration.fillAlphaInactive; configuration.fillAlphaInactive = newConfiguration.fillAlphaInactive;
configuration.outlineAlphaInactive = newConfiguration.outlineAlphaInactive; configuration.outlineAlphaInactive = newConfiguration.outlineAlphaInactive;
onConfigurationChange(newConfiguration); onConfigurationChange(newConfiguration);
refreshViewport(); refreshViewports();
}; };
const disabledConfigurationFields = ['outlineAlpha', 'shouldRenderInactiveLabelmaps']; const disabledConfigurationFields = [
'outlineAlpha',
'shouldRenderInactiveLabelmaps',
];
if (state.showSegmentationSettings) { if (state.showSegmentationSettings) {
return ( return (
<SegmentationSettings <SegmentationSettings
@@ -514,7 +525,10 @@ const SegmentationPanel = ({
); );
} else { } else {
return ( return (
<div className={`dcmseg-segmentation-panel ${state.isDisabled && 'disabled'}`}> <div
className={`dcmseg-segmentation-panel ${state.isDisabled &&
'disabled'}`}
>
<Icon <Icon
className="cog-icon" className="cog-icon"
name="cog" name="cog"
@@ -613,57 +627,6 @@ const _getReferencedSegDisplaysets = (StudyInstanceUID, SeriesInstanceUID) => {
return referencedDisplaysets; return referencedDisplaysets;
}; };
/**
*
*
* @param {*} viewportSpecificData
* @param {*} studies
* @param {*} displaySet
* @param {*} firstImageId
* @param {*} activeLabelmapIndex
* @returns
*/
const _setActiveLabelmap = async (
viewportSpecificData,
studies,
displaySet,
firstImageId,
activeLabelmapIndex,
callback = () => { },
onDisplaySetLoadFailure
) => {
if (displaySet.labelmapIndex === activeLabelmapIndex) {
log.warn(`${activeLabelmapIndex} is already the active labelmap`);
return displaySet.labelmapIndex;
}
if (!displaySet.isLoaded) {
// What props does this expect `viewportSpecificData` to have?
// TODO: Should this return the `labelmapIndex`?
const loadPromise = displaySet.load(viewportSpecificData, studies);
loadPromise.catch(error => {
onDisplaySetLoadFailure(error);
// Return old index.
return activeLabelmapIndex;
});
await loadPromise;
}
const { state } = cornerstoneTools.getModule('segmentation');
const brushStackState = state.series[firstImageId];
brushStackState.activeLabelmapIndex = displaySet.labelmapIndex;
refreshViewport();
callback();
return displaySet.labelmapIndex;
};
/** /**
* *
* @param {*} firstImageId * @param {*} firstImageId
@@ -683,7 +646,7 @@ const _setActiveSegment = (firstImageId, segmentIndex, activeSegmentIndex) => {
brushStackState.labelmaps3D[brushStackState.activeLabelmapIndex]; brushStackState.labelmaps3D[brushStackState.activeLabelmapIndex];
labelmap3D.activeSegmentIndex = segmentIndex; labelmap3D.activeSegmentIndex = segmentIndex;
refreshViewport(); refreshViewports();
return segmentIndex; return segmentIndex;
}; };
@@ -1,5 +1,6 @@
import { MODULE_TYPES, utils } from '@ohif/core'; import { MODULE_TYPES, utils } from '@ohif/core';
import loadSegmentation from './loadSegmentation'; import loadSegmentation from './loadSegmentation';
import getSourceDisplaySet from './getSourceDisplaySet';
// TODO: Should probably use dcmjs for this // TODO: Should probably use dcmjs for this
const SOP_CLASS_UIDS = { const SOP_CLASS_UIDS = {
@@ -54,6 +55,10 @@ export default function getSopClassHandlerModule({ servicesManager }) {
SeriesDescription, SeriesDescription,
}; };
segDisplaySet.getSourceDisplaySet = function(studies) {
return getSourceDisplaySet(studies, segDisplaySet);
};
segDisplaySet.load = function(referencedDisplaySet, studies) { segDisplaySet.load = function(referencedDisplaySet, studies) {
return loadSegmentation(segDisplaySet, referencedDisplaySet, studies); return loadSegmentation(segDisplaySet, referencedDisplaySet, studies);
}; };
@@ -0,0 +1,37 @@
import setActiveLabelmap from './utils/setActiveLabelMap';
export default function getSourceDisplaySet(studies, segDisplaySet) {
const referencedDisplaySet = _getReferencedDisplaySet(segDisplaySet, studies);
setActiveLabelmap(referencedDisplaySet, studies, segDisplaySet);
return referencedDisplaySet;
}
const _getReferencedDisplaySet = (segDisplaySet, studies) => {
let allDisplaySets = [];
studies.forEach(study => {
allDisplaySets = allDisplaySets.concat(study.displaySets);
});
const otherDisplaySets = allDisplaySets.filter(
ds => ds.displaySetInstanceUID !== segDisplaySet.displaySetInstanceUID
);
const ReferencedSeriesSequence = Array.isArray(
segDisplaySet.metadata.ReferencedSeriesSequence
)
? segDisplaySet.metadata.ReferencedSeriesSequence
: [segDisplaySet.metadata.ReferencedSeriesSequence];
const referencedSeriesInstanceUIDs = ReferencedSeriesSequence.map(
ReferencedSeries => ReferencedSeries.SeriesInstanceUID
);
const referencedDisplaySet = otherDisplaySets.find(ds =>
referencedSeriesInstanceUIDs.includes(ds.SeriesInstanceUID)
);
return referencedDisplaySet;
};
@@ -0,0 +1,5 @@
export default function refreshViewports() {
cornerstone.getEnabledElements().forEach(enabledElement => {
cornerstone.updateImage(enabledElement.element);
});
}
@@ -0,0 +1,67 @@
import { utils, log } from '@ohif/core';
import cornerstoneTools from 'cornerstone-tools';
import refreshViewports from './refreshViewports';
const { studyMetadataManager } = utils;
/**
*
*
* @param {*} viewportSpecificData
* @param {*} studies
* @param {*} displaySet
* @param {*} firstImageId
* @param {*} activeLabelmapIndex
* @returns
*/
export default async function setActiveLabelmap(
referencedDisplaySet,
studies,
displaySet,
callback = () => {},
onDisplaySetLoadFailure = err => {
throw new Error(err.message);
}
) {
const studyMetadata = studyMetadataManager.get(
referencedDisplaySet.StudyInstanceUID
);
const firstImageId = studyMetadata.getFirstImageId(
referencedDisplaySet.displaySetInstanceUID
);
let { state } = cornerstoneTools.getModule('segmentation');
let brushStackState = state.series[firstImageId];
const activeLabelmapIndex = brushStackState
? brushStackState.activeLabelmapIndex
: undefined;
if (displaySet.labelmapIndex === activeLabelmapIndex) {
log.warn(`${activeLabelmapIndex} is already the active labelmap`);
return displaySet.labelmapIndex;
}
if (!displaySet.isLoaded) {
const loadPromise = displaySet.load(referencedDisplaySet, studies);
loadPromise.catch(error => {
onDisplaySetLoadFailure(error);
// Return old index.
return activeLabelmapIndex;
});
await loadPromise;
}
// This might have just been created, so need to use the non-cached value.
state = cornerstoneTools.getModule('segmentation').state;
brushStackState = state.series[firstImageId];
brushStackState.activeLabelmapIndex = displaySet.labelmapIndex;
refreshViewports();
callback();
return displaySet.labelmapIndex;
}
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.6.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.6.9...@ohif/extension-vtk@1.6.10) (2020-08-10)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.6.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.6.8...@ohif/extension-vtk@1.6.9) (2020-07-23) ## [1.6.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.6.8...@ohif/extension-vtk@1.6.9) (2020-07-23)
**Note:** Version bump only for package @ohif/extension-vtk **Note:** Version bump only for package @ohif/extension-vtk
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/extension-vtk", "name": "@ohif/extension-vtk",
"version": "1.6.9", "version": "1.6.10",
"description": "OHIF extension for VTK.js", "description": "OHIF extension for VTK.js",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
@@ -53,7 +53,7 @@
"react-vtkjs-viewport": "^0.9.0" "react-vtkjs-viewport": "^0.9.0"
}, },
"devDependencies": { "devDependencies": {
"@ohif/core": "^2.9.13", "@ohif/core": "^2.9.14",
"@ohif/ui": "^1.5.3", "@ohif/ui": "^1.5.3",
"cornerstone-tools": "4.15.1", "cornerstone-tools": "4.15.1",
"cornerstone-wado-image-loader": "^3.1.0", "cornerstone-wado-image-loader": "^3.1.0",
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.9.14](https://github.com/OHIF/Viewers/compare/@ohif/core@2.9.13...@ohif/core@2.9.14) (2020-08-10)
**Note:** Version bump only for package @ohif/core
## [2.9.13](https://github.com/OHIF/Viewers/compare/@ohif/core@2.9.12...@ohif/core@2.9.13) (2020-07-22) ## [2.9.13](https://github.com/OHIF/Viewers/compare/@ohif/core@2.9.12...@ohif/core@2.9.13) (2020-07-22)
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/core", "name": "@ohif/core",
"version": "2.9.13", "version": "2.9.14",
"description": "Generic business logic for web-based medical imaging applications", "description": "Generic business logic for web-based medical imaging applications",
"author": "OHIF Core Team", "author": "OHIF Core Team",
"license": "MIT", "license": "MIT",
@@ -139,9 +139,11 @@ export class StudyMetadata extends Metadata {
if (displaySet) { if (displaySet) {
displaySet.sopClassModule = true; displaySet.sopClassModule = true;
displaySet.isDerived if (displaySet.isDerived) {
? this._addDerivedDisplaySet(displaySet) this._addDerivedDisplaySet(displaySet);
: displaySets.push(displaySet); }
displaySets.push(displaySet);
return displaySets; return displaySets;
} }
+27
View File
@@ -3,6 +3,33 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [4.3.1](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.3.0...@ohif/viewer@4.3.1) (2020-08-10)
**Note:** Version bump only for package @ohif/viewer
# [4.3.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.16...@ohif/viewer@4.3.0) (2020-08-10)
### Features
* 🎸 Optional disable measurements panel in app config ([#1912](https://github.com/OHIF/Viewers/issues/1912)) ([3d86b5f](https://github.com/OHIF/Viewers/commit/3d86b5f876d6481bcc57de88a0ba1f974f4ee263)), closes [#1864](https://github.com/OHIF/Viewers/issues/1864)
## [4.2.16](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.15...@ohif/viewer@4.2.16) (2020-08-10)
**Note:** Version bump only for package @ohif/viewer
## [4.2.15](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.14...@ohif/viewer@4.2.15) (2020-08-05) ## [4.2.15](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.14...@ohif/viewer@4.2.15) (2020-08-05)
**Note:** Version bump only for package @ohif/viewer **Note:** Version bump only for package @ohif/viewer
@@ -12,6 +12,8 @@ describe('OHIF Microscopy Extension', () => {
}); });
it('drags and drop a SM thumbnail into viewport', () => { it('drags and drop a SM thumbnail into viewport', () => {
// Waiting for series list to load all displaySets (lots of SRs, before defining which dom element to grab.)
cy.wait(3000);
cy.get('[data-cy="thumbnail-list"]') cy.get('[data-cy="thumbnail-list"]')
.contains('SM') .contains('SM')
.drag('.viewport-drop-target'); .drag('.viewport-drop-target');
+5 -5
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/viewer", "name": "@ohif/viewer",
"version": "4.2.15", "version": "4.3.1",
"description": "OHIF Viewer", "description": "OHIF Viewer",
"author": "OHIF Contributors", "author": "OHIF Contributors",
"license": "MIT", "license": "MIT",
@@ -48,16 +48,16 @@
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.5.5", "@babel/runtime": "^7.5.5",
"@ohif/core": "^2.9.13", "@ohif/core": "^2.9.14",
"@ohif/extension-cornerstone": "^2.8.5", "@ohif/extension-cornerstone": "^2.8.5",
"@ohif/extension-dicom-html": "^1.2.4", "@ohif/extension-dicom-html": "^1.2.4",
"@ohif/extension-dicom-microscopy": "^0.51.0", "@ohif/extension-dicom-microscopy": "^0.51.0",
"@ohif/extension-dicom-p10-downloader": "^0.1.2", "@ohif/extension-dicom-p10-downloader": "^0.1.2",
"@ohif/extension-dicom-pdf": "^1.0.3", "@ohif/extension-dicom-pdf": "^1.0.3",
"@ohif/extension-dicom-rt": "^0.2.6", "@ohif/extension-dicom-rt": "^0.3.0",
"@ohif/extension-dicom-segmentation": "^0.3.3", "@ohif/extension-dicom-segmentation": "^0.3.4",
"@ohif/extension-lesion-tracker": "^0.2.0", "@ohif/extension-lesion-tracker": "^0.2.0",
"@ohif/extension-vtk": "^1.6.9", "@ohif/extension-vtk": "^1.6.10",
"@ohif/i18n": "^0.52.8", "@ohif/i18n": "^0.52.8",
"@ohif/ui": "^1.5.3", "@ohif/ui": "^1.5.3",
"@tanem/react-nprogress": "^1.1.25", "@tanem/react-nprogress": "^1.1.25",
+1
View File
@@ -2,6 +2,7 @@ window.config = function(props) {
var servicesManager = props.servicesManager; var servicesManager = props.servicesManager;
return { return {
disableMeasurementPanel: true,
routerBasename: '/', routerBasename: '/',
enableGoogleCloudAdapter: true, enableGoogleCloudAdapter: true,
enableGoogleCloudAdapterUI: false, enableGoogleCloudAdapterUI: false,
+12 -8
View File
@@ -13,7 +13,7 @@ import {
ModalProvider, ModalProvider,
DialogProvider, DialogProvider,
OHIFModal, OHIFModal,
ErrorBoundary ErrorBoundary,
} from '@ohif/ui'; } from '@ohif/ui';
import { import {
@@ -168,7 +168,7 @@ class App extends Component {
if (this._userManager) { if (this._userManager) {
return ( return (
<ErrorBoundary context='App'> <ErrorBoundary context="App">
<Provider store={store}> <Provider store={store}>
<AppProvider config={this._appConfig}> <AppProvider config={this._appConfig}>
<I18nextProvider i18n={i18n}> <I18nextProvider i18n={i18n}>
@@ -200,7 +200,7 @@ class App extends Component {
} }
return ( return (
<ErrorBoundary context='App'> <ErrorBoundary context="App">
<Provider store={store}> <Provider store={store}>
<AppProvider config={this._appConfig}> <AppProvider config={this._appConfig}>
<I18nextProvider i18n={i18n}> <I18nextProvider i18n={i18n}>
@@ -271,17 +271,21 @@ function _initExtensions(extensions, cornerstoneExtensionConfig, appConfig) {
api: { api: {
contexts: CONTEXTS, contexts: CONTEXTS,
hooks: { hooks: {
useAppContext useAppContext,
} },
} },
}); });
const requiredExtensions = [ const requiredExtensions = [
GenericViewerCommands, GenericViewerCommands,
[OHIFCornerstoneExtension, cornerstoneExtensionConfig], [OHIFCornerstoneExtension, cornerstoneExtensionConfig],
/* WARNING: MUST BE REGISTERED _AFTER_ OHIFCornerstoneExtension */
MeasurementsPanel,
]; ];
if (appConfig.disableMeasurementPanel !== true) {
/* WARNING: MUST BE REGISTERED _AFTER_ OHIFCornerstoneExtension */
requiredExtensions.push(MeasurementsPanel);
}
const mergedExtensions = requiredExtensions.concat(extensions); const mergedExtensions = requiredExtensions.concat(extensions);
extensionManager.registerExtensions(mergedExtensions); extensionManager.registerExtensions(mergedExtensions);
} }
@@ -80,6 +80,7 @@ const ViewportGrid = function(props) {
// - When updating a panel, ensure that the currently enabled plugin // - When updating a panel, ensure that the currently enabled plugin
// in the viewport is capable of rendering this display set. If not // in the viewport is capable of rendering this display set. If not
// then use the most capable available plugin // then use the most capable available plugin
const pluginName = const pluginName =
!layout.plugin && displaySet && displaySet.plugin !layout.plugin && displaySet && displaySet.plugin
? displaySet.plugin ? displaySet.plugin
@@ -4,6 +4,8 @@ import { StudyBrowser } from '@ohif/ui';
import cloneDeep from 'lodash.clonedeep'; import cloneDeep from 'lodash.clonedeep';
import findDisplaySetByUID from './findDisplaySetByUID'; import findDisplaySetByUID from './findDisplaySetByUID';
const { studyMetadataManager } = OHIF.utils;
const { setActiveViewportSpecificData } = OHIF.redux.actions; const { setActiveViewportSpecificData } = OHIF.redux.actions;
// TODO // TODO
@@ -39,11 +41,27 @@ const mapStateToProps = (state, ownProps) => {
const mapDispatchToProps = (dispatch, ownProps) => { const mapDispatchToProps = (dispatch, ownProps) => {
return { return {
onThumbnailClick: displaySetInstanceUID => { onThumbnailClick: displaySetInstanceUID => {
const displaySet = findDisplaySetByUID( let displaySet = findDisplaySetByUID(
ownProps.studyMetadata, ownProps.studyMetadata,
displaySetInstanceUID displaySetInstanceUID
); );
if (displaySet.isDerived) {
const { Modality } = displaySet;
displaySet = displaySet.getSourceDisplaySet(ownProps.studyMetadata);
if (!displaySet) {
throw new Error(
`Referenced series for ${Modality} dataset not present.`
);
}
if (!displaySet) {
throw new Error('Source data not present');
}
}
dispatch(setActiveViewportSpecificData(displaySet)); dispatch(setActiveViewportSpecificData(displaySet));
}, },
}; };
@@ -133,12 +133,23 @@ class ViewerMain extends Component {
StudyInstanceUID, StudyInstanceUID,
displaySetInstanceUID, displaySetInstanceUID,
}) => { }) => {
const displaySet = this.findDisplaySet( let displaySet = this.findDisplaySet(
this.props.studies, this.props.studies,
StudyInstanceUID, StudyInstanceUID,
displaySetInstanceUID displaySetInstanceUID
); );
if (displaySet.isDerived) {
const { Modality } = displaySet;
displaySet = displaySet.getSourceDisplaySet(this.props.studies);
if (!displaySet) {
throw new Error(
`Referenced series for ${Modality} dataset not present.`
);
}
}
this.props.setViewportSpecificData(viewportIndex, displaySet); this.props.setViewportSpecificData(viewportIndex, displaySet);
}; };