Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
248bc0a64a | ||
|
|
5fdace1432 | ||
|
|
71b6b454a3 | ||
|
|
3b02a06f5e | ||
|
|
ebdcde1c4d | ||
|
|
829ac2b410 | ||
|
|
09745a0349 | ||
|
|
cd73dd3027 | ||
|
|
ca511edeff | ||
|
|
bb5f30ce2a | ||
|
|
87d5c68e71 | ||
|
|
0e87ab37c2 | ||
|
|
756b005fe1 | ||
|
|
3d86b5f876 | ||
|
|
2a647fd618 | ||
|
|
f8fc31bcac |
No files matched your search
@@ -11,6 +11,7 @@ node -v
|
||||
|
||||
# Install build deps and all monorepo package dependencies. Yarn Workspaces
|
||||
# should also symlink all projects appropriately
|
||||
yarn run lerna:restore
|
||||
yarn install --no-ignore-optional --pure-lockfile
|
||||
|
||||
# Build && Move PWA Output
|
||||
|
||||
@@ -3,6 +3,28 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.9.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.9.0...@ohif/extension-cornerstone@2.9.1) (2020-08-20)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **stackPrefetch:** Added stackPrefetch config with 20 max concurrent requests ([#2000](https://github.com/OHIF/Viewers/issues/2000)) ([3b02a06](https://github.com/OHIF/Viewers/commit/3b02a06f5e250660edde4862ce44147db3dc3ab9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [2.9.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.8.5...@ohif/extension-cornerstone@2.9.0) (2020-08-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* 🎸 Update react-vtkjs-viewport usage to use requestPool ([#1984](https://github.com/OHIF/Viewers/issues/1984)) ([bb5f30c](https://github.com/OHIF/Viewers/commit/bb5f30ce2a0192d2e021beaaadfff22fd38e17b9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.8.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.8.4...@ohif/extension-cornerstone@2.8.5) (2020-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "2.8.5",
|
||||
"version": "2.9.1",
|
||||
"description": "OHIF extension for Cornerstone",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -34,7 +34,7 @@
|
||||
"@ohif/ui": "^0.50.0",
|
||||
"cornerstone-core": "^2.2.8",
|
||||
"cornerstone-math": "^0.1.8",
|
||||
"cornerstone-tools": "4.15.1",
|
||||
"cornerstone-tools": "^4.20.1",
|
||||
"cornerstone-wado-image-loader": "^3.1.0",
|
||||
"dcmjs": "0.16.0",
|
||||
"dicom-parser": "^1.8.3",
|
||||
|
||||
@@ -34,4 +34,11 @@ export default function(configuration = {}) {
|
||||
cornerstoneTools.toolColors.setActiveColor('rgb(0, 255, 0)');
|
||||
|
||||
cornerstoneTools.store.state.touchProximity = 40;
|
||||
|
||||
// Configure stack prefetch
|
||||
cornerstoneTools.stackPrefetch.setConfiguration({
|
||||
maxImagesToPrefetch: Infinity,
|
||||
preserveExistingPool: false,
|
||||
maxSimultaneousRequests: 20,
|
||||
});
|
||||
}
|
||||
@@ -3,6 +3,36 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [0.4.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.3.0...@ohif/extension-dicom-rt@0.4.0) (2020-08-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* 🎸 Update react-vtkjs-viewport usage to use requestPool ([#1984](https://github.com/OHIF/Viewers/issues/1984)) ([bb5f30c](https://github.com/OHIF/Viewers/commit/bb5f30ce2a0192d2e021beaaadfff22fd38e17b9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-rt",
|
||||
"version": "0.2.6",
|
||||
"version": "0.4.0",
|
||||
"description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -30,7 +30,7 @@
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "^0.50.0",
|
||||
"cornerstone-core": "^2.2.8",
|
||||
"cornerstone-tools": "4.15.1",
|
||||
"cornerstone-tools": "^4.20.1",
|
||||
"dcmjs": "0.16.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.8.6",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { MODULE_TYPES, utils, DICOMWeb } from '@ohif/core';
|
||||
import loadRTStruct from './loadRTStruct';
|
||||
import getSourceDisplaySet from './getSourceDisplaySet';
|
||||
|
||||
import id from './id';
|
||||
|
||||
@@ -67,6 +68,10 @@ const OHIFDicomRTStructSopClassHandler = {
|
||||
}
|
||||
}
|
||||
|
||||
rtStructDisplaySet.getSourceDisplaySet = function(studies) {
|
||||
return getSourceDisplaySet(studies, rtStructDisplaySet);
|
||||
};
|
||||
|
||||
rtStructDisplaySet.load = function(referencedDisplaySet, studies) {
|
||||
return loadRTStruct(
|
||||
rtStructDisplaySet,
|
||||
|
||||
@@ -242,7 +242,7 @@ const RTPanel = ({
|
||||
key={SeriesInstanceUID}
|
||||
title={metadata.StructureSetLabel}
|
||||
loading={!isLoaded || !loadedSet}
|
||||
visible={isLoaded && loadedSet.visible}
|
||||
visible={isLoaded && loadedSet && loadedSet.visible}
|
||||
hideVisibleButton={!isLoaded}
|
||||
expanded={
|
||||
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;
|
||||
};
|
||||
@@ -76,21 +76,15 @@ export default async function loadRTStruct(
|
||||
|
||||
const isSupported = false;
|
||||
|
||||
for (let c = 0; c < ContourSequence.length; c++) {
|
||||
const ContourSequenceArray = _toArray(ContourSequence);
|
||||
|
||||
for (let c = 0; c < ContourSequenceArray.length; c++) {
|
||||
const {
|
||||
ContourImageSequence,
|
||||
ContourData,
|
||||
NumberOfContourPoints,
|
||||
ContourGeometricType,
|
||||
} = ContourSequence[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;
|
||||
} = ContourSequenceArray[c];
|
||||
|
||||
const sopInstanceUID = ContourImageSequence.ReferencedSOPInstanceUID;
|
||||
const imageId = _getImageId(imageIdSopInstanceUidPairs, sopInstanceUID);
|
||||
@@ -102,26 +96,38 @@ export default async function loadRTStruct(
|
||||
|
||||
const imagePlane = cornerstone.metaData.get('imagePlaneModule', imageId);
|
||||
const points = [];
|
||||
let measurementData;
|
||||
|
||||
for (let p = 0; p < NumberOfContourPoints * 3; p += 3) {
|
||||
points.push({
|
||||
x: ContourData[p],
|
||||
y: ContourData[p + 1],
|
||||
z: ContourData[p + 2],
|
||||
});
|
||||
switch (ContourGeometricType) {
|
||||
case 'CLOSED_PLANAR':
|
||||
case 'OPEN_PLANAR':
|
||||
case 'POINT':
|
||||
isSupported = true;
|
||||
|
||||
for (let p = 0; p < NumberOfContourPoints * 3; p += 3) {
|
||||
points.push({
|
||||
x: ContourData[p],
|
||||
y: ContourData[p + 1],
|
||||
z: ContourData[p + 2],
|
||||
});
|
||||
}
|
||||
|
||||
transformPointsToImagePlane(points, imagePlane);
|
||||
|
||||
measurementData = {
|
||||
handles: {
|
||||
points,
|
||||
},
|
||||
type: ContourGeometricType,
|
||||
structureSetSeriesInstanceUid: rtStructDataset.SeriesInstanceUID,
|
||||
ROINumber: ReferencedROINumber,
|
||||
};
|
||||
|
||||
imageIdSpecificToolData.push(measurementData);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
transformPointsToImagePlane(points, imagePlane);
|
||||
|
||||
const measurementData = {
|
||||
handles: {
|
||||
points,
|
||||
},
|
||||
structureSetSeriesInstanceUid: rtStructDataset.SeriesInstanceUID,
|
||||
ROINumber: ReferencedROINumber,
|
||||
};
|
||||
|
||||
imageIdSpecificToolData.push(measurementData);
|
||||
}
|
||||
|
||||
_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
|
||||
const draw = importInternal('drawing/draw');
|
||||
const drawCircle = importInternal('drawing/drawCircle');
|
||||
const drawJoinedLines = importInternal('drawing/drawJoinedLines');
|
||||
const getNewContext = importInternal('drawing/getNewContext');
|
||||
const BaseTool = importInternal('base/BaseTool');
|
||||
@@ -72,22 +73,52 @@ export default class RTStructDisplayTool extends BaseTool {
|
||||
const colorArray = ROIContourData.colorArray;
|
||||
const color = `rgba(${colorArray[0]},${colorArray[1]},${
|
||||
colorArray[2]
|
||||
},${opacity})`;
|
||||
},${opacity})`;
|
||||
|
||||
lineWidth;
|
||||
|
||||
draw(context, context => {
|
||||
drawJoinedLines(
|
||||
context,
|
||||
eventData.element,
|
||||
points[points.length - 1],
|
||||
points,
|
||||
{
|
||||
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 => {
|
||||
drawJoinedLines(
|
||||
context,
|
||||
element,
|
||||
points[points.length - 1],
|
||||
points,
|
||||
options
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
_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,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [0.4.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.3.4...@ohif/extension-dicom-segmentation@0.4.0) (2020-08-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* 🎸 Update react-vtkjs-viewport usage to use requestPool ([#1984](https://github.com/OHIF/Viewers/issues/1984)) ([bb5f30c](https://github.com/OHIF/Viewers/commit/bb5f30ce2a0192d2e021beaaadfff22fd38e17b9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [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)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-segmentation",
|
||||
"version": "0.3.3",
|
||||
"version": "0.4.0",
|
||||
"description": "OHIF extension for viewing segmentations in the 2D MPR view",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -30,7 +30,7 @@
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "^0.50.0",
|
||||
"cornerstone-core": "^2.2.8",
|
||||
"cornerstone-tools": "4.15.1",
|
||||
"cornerstone-tools": "^4.20.1",
|
||||
"dcmjs": "0.16.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.8.6",
|
||||
|
||||
+48
-85
@@ -6,6 +6,9 @@ import moment from 'moment';
|
||||
import { utils, log } from '@ohif/core';
|
||||
import { ScrollableArea, TableList, Icon } from '@ohif/ui';
|
||||
|
||||
import setActiveLabelmap from '../../utils/setActiveLabelMap';
|
||||
import refreshViewports from '../../utils/refreshViewports';
|
||||
|
||||
import {
|
||||
BrushColorSelector,
|
||||
BrushRadius,
|
||||
@@ -19,12 +22,6 @@ import SegmentationSettings from '../SegmentationSettings/SegmentationSettings';
|
||||
|
||||
const { studyMetadataManager } = utils;
|
||||
|
||||
const refreshViewport = () => {
|
||||
cornerstone.getEnabledElements().forEach(enabledElement => {
|
||||
cornerstone.updateImage(enabledElement.element);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* SegmentationPanel component
|
||||
*
|
||||
@@ -68,8 +65,7 @@ const SegmentationPanel = ({
|
||||
*/
|
||||
const [state, setState] = useState({
|
||||
brushRadius: DEFAULT_BRUSH_RADIUS,
|
||||
brushColor:
|
||||
'rgba(221, 85, 85, 1)',
|
||||
brushColor: 'rgba(221, 85, 85, 1)',
|
||||
selectedSegment: null,
|
||||
selectedSegmentation: null,
|
||||
showSegmentationSettings: false,
|
||||
@@ -78,7 +74,7 @@ const SegmentationPanel = ({
|
||||
segmentList: [],
|
||||
cachedSegmentsProperties: [],
|
||||
isLoading: false,
|
||||
isDisabled: true
|
||||
isDisabled: true,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
@@ -112,7 +108,10 @@ const SegmentationPanel = ({
|
||||
* allows us to easily watch the module or the segmentations loading process in any other component
|
||||
* without subscribing to external events.
|
||||
*/
|
||||
document.addEventListener('extensiondicomsegmentationsegloaded', refreshSegmentations);
|
||||
document.addEventListener(
|
||||
'extensiondicomsegmentationsegloaded',
|
||||
refreshSegmentations
|
||||
);
|
||||
|
||||
/*
|
||||
* These are specific to each element;
|
||||
@@ -127,7 +126,10 @@ const SegmentationPanel = ({
|
||||
);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('extensiondicomsegmentationsegloaded', refreshSegmentations);
|
||||
document.removeEventListener(
|
||||
'extensiondicomsegmentationsegloaded',
|
||||
refreshSegmentations
|
||||
);
|
||||
cornerstoneTools.store.state.enabledElements.forEach(enabledElement =>
|
||||
enabledElement.removeEventListener(
|
||||
'cornerstonetoolslabelmapmodified',
|
||||
@@ -169,26 +171,29 @@ const SegmentationPanel = ({
|
||||
selectedSegmentation: brushStackState.activeLabelmapIndex,
|
||||
labelmapList,
|
||||
segmentList,
|
||||
isDisabled
|
||||
isDisabled,
|
||||
}));
|
||||
} else {
|
||||
setState(state => ({
|
||||
...state,
|
||||
labelmapList: [],
|
||||
segmentList: [],
|
||||
isDisabled
|
||||
isDisabled,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}, [
|
||||
viewports,
|
||||
activeIndex,
|
||||
state.isLoading
|
||||
]);
|
||||
}, [viewports, activeIndex, state.isLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
refreshSegmentations();
|
||||
}, [viewports, activeIndex, isOpen, state.selectedSegmentation, activeContexts, state.isLoading]);
|
||||
}, [
|
||||
viewports,
|
||||
activeIndex,
|
||||
isOpen,
|
||||
state.selectedSegmentation,
|
||||
activeContexts,
|
||||
state.isLoading,
|
||||
]);
|
||||
|
||||
/* Handle open/closed panel behaviour */
|
||||
useEffect(() => {
|
||||
@@ -223,12 +228,10 @@ const SegmentationPanel = ({
|
||||
title: displayDescription,
|
||||
description: displayDate,
|
||||
onClick: async () => {
|
||||
const activatedLabelmapIndex = await _setActiveLabelmap(
|
||||
const activatedLabelmapIndex = await setActiveLabelmap(
|
||||
activeViewport,
|
||||
studies,
|
||||
displaySet,
|
||||
firstImageId,
|
||||
brushStackState.activeLabelmapIndex,
|
||||
() => onSelectedSegmentationChange(),
|
||||
onDisplaySetLoadFailure
|
||||
);
|
||||
@@ -376,9 +379,13 @@ const SegmentationPanel = ({
|
||||
return !segmentsHidden[segmentIndex];
|
||||
};
|
||||
|
||||
const cachedSegmentProperties = state.cachedSegmentsProperties[segmentNumber];
|
||||
const cachedSegmentProperties =
|
||||
state.cachedSegmentsProperties[segmentNumber];
|
||||
let visible = isSegmentVisible();
|
||||
if (cachedSegmentProperties && cachedSegmentProperties.visible !== visible) {
|
||||
if (
|
||||
cachedSegmentProperties &&
|
||||
cachedSegmentProperties.visible !== visible
|
||||
) {
|
||||
toggleSegmentVisibility();
|
||||
}
|
||||
|
||||
@@ -406,8 +413,10 @@ const SegmentationPanel = ({
|
||||
onSegmentVisibilityChange(segmentNumber, newVisibility);
|
||||
}
|
||||
|
||||
updateCachedSegmentsProperties(segmentNumber, { visible: newVisibility });
|
||||
refreshViewport();
|
||||
updateCachedSegmentsProperties(segmentNumber, {
|
||||
visible: newVisibility,
|
||||
});
|
||||
refreshViewports();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -429,10 +438,9 @@ const SegmentationPanel = ({
|
||||
const segmentsProperties = state.cachedSegmentsProperties;
|
||||
const segmentProperties = state.cachedSegmentsProperties[segmentNumber];
|
||||
|
||||
segmentsProperties[segmentNumber] =
|
||||
segmentProperties ?
|
||||
{ ...segmentProperties, ...properties } :
|
||||
properties;
|
||||
segmentsProperties[segmentNumber] = segmentProperties
|
||||
? { ...segmentProperties, ...properties }
|
||||
: properties;
|
||||
|
||||
updateState('cachedSegmentsProperties', segmentsProperties);
|
||||
};
|
||||
@@ -499,10 +507,13 @@ const SegmentationPanel = ({
|
||||
configuration.fillAlphaInactive = newConfiguration.fillAlphaInactive;
|
||||
configuration.outlineAlphaInactive = newConfiguration.outlineAlphaInactive;
|
||||
onConfigurationChange(newConfiguration);
|
||||
refreshViewport();
|
||||
refreshViewports();
|
||||
};
|
||||
|
||||
const disabledConfigurationFields = ['outlineAlpha', 'shouldRenderInactiveLabelmaps'];
|
||||
const disabledConfigurationFields = [
|
||||
'outlineAlpha',
|
||||
'shouldRenderInactiveLabelmaps',
|
||||
];
|
||||
if (state.showSegmentationSettings) {
|
||||
return (
|
||||
<SegmentationSettings
|
||||
@@ -514,7 +525,10 @@ const SegmentationPanel = ({
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className={`dcmseg-segmentation-panel ${state.isDisabled && 'disabled'}`}>
|
||||
<div
|
||||
className={`dcmseg-segmentation-panel ${state.isDisabled &&
|
||||
'disabled'}`}
|
||||
>
|
||||
<Icon
|
||||
className="cog-icon"
|
||||
name="cog"
|
||||
@@ -613,57 +627,6 @@ const _getReferencedSegDisplaysets = (StudyInstanceUID, SeriesInstanceUID) => {
|
||||
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
|
||||
@@ -683,7 +646,7 @@ const _setActiveSegment = (firstImageId, segmentIndex, activeSegmentIndex) => {
|
||||
brushStackState.labelmaps3D[brushStackState.activeLabelmapIndex];
|
||||
labelmap3D.activeSegmentIndex = segmentIndex;
|
||||
|
||||
refreshViewport();
|
||||
refreshViewports();
|
||||
|
||||
return segmentIndex;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { MODULE_TYPES, utils } from '@ohif/core';
|
||||
import loadSegmentation from './loadSegmentation';
|
||||
import getSourceDisplaySet from './getSourceDisplaySet';
|
||||
|
||||
// TODO: Should probably use dcmjs for this
|
||||
const SOP_CLASS_UIDS = {
|
||||
@@ -54,6 +55,10 @@ export default function getSopClassHandlerModule({ servicesManager }) {
|
||||
SeriesDescription,
|
||||
};
|
||||
|
||||
segDisplaySet.getSourceDisplaySet = function(studies) {
|
||||
return getSourceDisplaySet(studies, segDisplaySet);
|
||||
};
|
||||
|
||||
segDisplaySet.load = function(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;
|
||||
}
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.7.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.6.10...@ohif/extension-vtk@1.7.0) (2020-08-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* 🎸 Update react-vtkjs-viewport usage to use requestPool ([#1984](https://github.com/OHIF/Viewers/issues/1984)) ([bb5f30c](https://github.com/OHIF/Viewers/commit/bb5f30ce2a0192d2e021beaaadfff22fd38e17b9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [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)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-vtk",
|
||||
"version": "1.6.9",
|
||||
"version": "1.7.0",
|
||||
"description": "OHIF extension for VTK.js",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -33,7 +33,7 @@
|
||||
"@ohif/i18n": "^0.50.0",
|
||||
"@ohif/ui": "^0.50.0",
|
||||
"cornerstone-core": "^2.2.8",
|
||||
"cornerstone-tools": "4.15.1",
|
||||
"cornerstone-tools": "^4.20.1",
|
||||
"cornerstone-wado-image-loader": "^3.1.0",
|
||||
"dcmjs": "0.16.0",
|
||||
"dicom-parser": "^1.8.3",
|
||||
@@ -50,12 +50,12 @@
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"react-vtkjs-viewport": "^0.9.0"
|
||||
"react-vtkjs-viewport": "^0.10.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ohif/core": "^2.9.13",
|
||||
"@ohif/core": "^2.10.0",
|
||||
"@ohif/ui": "^1.5.3",
|
||||
"cornerstone-tools": "4.15.1",
|
||||
"cornerstone-tools": "^4.20.1",
|
||||
"cornerstone-wado-image-loader": "^3.1.0",
|
||||
"dicom-parser": "^1.8.3",
|
||||
"gh-pages": "^2.0.1",
|
||||
|
||||
@@ -49,7 +49,7 @@ class OHIFVTKViewport extends Component {
|
||||
state = {
|
||||
volumes: null,
|
||||
paintFilterLabelMapImageData: null,
|
||||
paintFilterBackgroundImageData: null
|
||||
paintFilterBackgroundImageData: null,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
@@ -69,7 +69,7 @@ class OHIFVTKViewport extends Component {
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
onScroll: () => { },
|
||||
onScroll: () => {},
|
||||
};
|
||||
|
||||
static id = 'OHIFVTKViewport';
|
||||
@@ -156,9 +156,11 @@ class OHIFVTKViewport extends Component {
|
||||
const { activeLabelmapIndex } = brushStackState;
|
||||
const labelmap3D = brushStackState.labelmaps3D[activeLabelmapIndex];
|
||||
|
||||
this.segmentsDefaultProperties = labelmap3D.segmentsHidden.map(isHidden => {
|
||||
return { visible: !isHidden };
|
||||
});
|
||||
this.segmentsDefaultProperties = labelmap3D.segmentsHidden.map(
|
||||
isHidden => {
|
||||
return { visible: !isHidden };
|
||||
}
|
||||
);
|
||||
|
||||
const vtkLabelmapID = `${firstImageId}_${activeLabelmapIndex}`;
|
||||
|
||||
@@ -349,7 +351,7 @@ class OHIFVTKViewport extends Component {
|
||||
|
||||
if (
|
||||
displaySet.displaySetInstanceUID !==
|
||||
prevDisplaySet.displaySetInstanceUID ||
|
||||
prevDisplaySet.displaySetInstanceUID ||
|
||||
displaySet.SOPInstanceUID !== prevDisplaySet.SOPInstanceUID ||
|
||||
displaySet.frameIndex !== prevDisplaySet.frameIndex
|
||||
) {
|
||||
@@ -360,34 +362,35 @@ class OHIFVTKViewport extends Component {
|
||||
loadProgressively(imageDataObject) {
|
||||
loadImageData(imageDataObject);
|
||||
|
||||
const { isLoading, insertPixelDataPromises } = imageDataObject;
|
||||
|
||||
const NumberOfFrames = insertPixelDataPromises.length;
|
||||
const { isLoading, imageIds } = imageDataObject;
|
||||
|
||||
if (!isLoading) {
|
||||
this.setState({ isLoaded: true });
|
||||
return;
|
||||
}
|
||||
|
||||
insertPixelDataPromises.forEach(promise => {
|
||||
promise.then(numberProcessed => {
|
||||
const percentComplete = Math.floor(
|
||||
(numberProcessed * 100) / NumberOfFrames
|
||||
);
|
||||
const NumberOfFrames = imageIds.length;
|
||||
|
||||
if (percentComplete !== this.state.percentComplete) {
|
||||
this.setState({
|
||||
percentComplete,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
const onPixelDataInsertedCallback = numberProcessed => {
|
||||
const percentComplete = Math.floor(
|
||||
(numberProcessed * 100) / NumberOfFrames
|
||||
);
|
||||
|
||||
Promise.all(insertPixelDataPromises).then(() => {
|
||||
if (percentComplete !== this.state.percentComplete) {
|
||||
this.setState({
|
||||
percentComplete,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onAllPixelDataInsertedCallback = () => {
|
||||
this.setState({
|
||||
isLoaded: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
imageDataObject.onPixelDataInserted(onPixelDataInsertedCallback);
|
||||
imageDataObject.onAllPixelDataInserted(onAllPixelDataInsertedCallback);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -435,7 +438,7 @@ class OHIFVTKViewport extends Component {
|
||||
segmentsDefaultProperties: this.segmentsDefaultProperties,
|
||||
onNewSegmentationRequested: () => {
|
||||
this.setStateFromProps();
|
||||
}
|
||||
},
|
||||
}}
|
||||
onScroll={this.props.onScroll}
|
||||
/>
|
||||
|
||||
+2
-3
@@ -34,9 +34,8 @@
|
||||
"see-changed": "lerna changed",
|
||||
"docs:publish": "chmod +x ./build-and-publish-docs.sh && ./build-and-publish-docs.sh",
|
||||
"release": "yarn run lerna:version && yarn run lerna:publish",
|
||||
"lerna:cache": "[ $NETLIFY_RESTORE = 1 ] && ./netlify-lerna-cache.sh || :",
|
||||
"lerna:restore": "[ $NETLIFY_RESTORE = 1 ] && ./netlify-lerna-restore.sh || :",
|
||||
"preinstall": "yarn lerna:restore",
|
||||
"lerna:cache": "./netlify-lerna-cache.sh",
|
||||
"lerna:restore": "./netlify-lerna-restore.sh",
|
||||
"lerna:version": "npx lerna version prerelease --force-publish",
|
||||
"lerna:publish": "lerna publish from-package --canary --dist-tag canary",
|
||||
"link-list": "npm ls --depth=0 --link=true"
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [2.10.0](https://github.com/OHIF/Viewers/compare/@ohif/core@2.9.14...@ohif/core@2.10.0) (2020-08-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* 🎸 Update react-vtkjs-viewport usage to use requestPool ([#1984](https://github.com/OHIF/Viewers/issues/1984)) ([bb5f30c](https://github.com/OHIF/Viewers/commit/bb5f30ce2a0192d2e021beaaadfff22fd38e17b9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [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)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/core",
|
||||
"version": "2.9.13",
|
||||
"version": "2.10.0",
|
||||
"description": "Generic business logic for web-based medical imaging applications",
|
||||
"author": "OHIF Core Team",
|
||||
"license": "MIT",
|
||||
@@ -32,7 +32,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"cornerstone-core": "^2.2.8",
|
||||
"cornerstone-tools": "4.15.1",
|
||||
"cornerstone-tools": "^4.20.1",
|
||||
"cornerstone-wado-image-loader": "^3.1.0",
|
||||
"dicom-parser": "^1.8.3"
|
||||
},
|
||||
|
||||
@@ -139,9 +139,11 @@ export class StudyMetadata extends Metadata {
|
||||
if (displaySet) {
|
||||
displaySet.sopClassModule = true;
|
||||
|
||||
displaySet.isDerived
|
||||
? this._addDerivedDisplaySet(displaySet)
|
||||
: displaySets.push(displaySet);
|
||||
if (displaySet.isDerived) {
|
||||
this._addDerivedDisplaySet(displaySet);
|
||||
}
|
||||
|
||||
displaySets.push(displaySet);
|
||||
|
||||
return displaySets;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,66 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [4.5.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.4.1...@ohif/viewer@4.5.0) (2020-08-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* 🎸 Filter/promote multiple series instances ([#1533](https://github.com/OHIF/Viewers/issues/1533)) ([5fdace1](https://github.com/OHIF/Viewers/commit/5fdace1432b4b1bd31a60c5db6bd681610ec2b8e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.4.1](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.4.0...@ohif/viewer@4.4.1) (2020-08-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix incorrect command name in Percy test ([#1999](https://github.com/OHIF/Viewers/issues/1999)) ([ebdcde1](https://github.com/OHIF/Viewers/commit/ebdcde1c4d9c95393cf79cc9994f5d60f6d66fdd))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [4.4.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.3.1...@ohif/viewer@4.4.0) (2020-08-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* 🎸 Update react-vtkjs-viewport usage to use requestPool ([#1984](https://github.com/OHIF/Viewers/issues/1984)) ([bb5f30c](https://github.com/OHIF/Viewers/commit/bb5f30ce2a0192d2e021beaaadfff22fd38e17b9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [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)
|
||||
|
||||
**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', () => {
|
||||
// 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"]')
|
||||
.contains('SM')
|
||||
.drag('.viewport-drop-target');
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ describe('Visual Regression - OHIF VTK Extension', () => {
|
||||
cy.get('[data-cy="2d mpr"]').click();
|
||||
|
||||
//Wait waitVTKLoading Images
|
||||
cy.waitVTKwaitVTKLoading();
|
||||
cy.waitVTKLoading();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -114,7 +114,7 @@ Cypress.Commands.add('waitVTKLoading', () => {
|
||||
});
|
||||
|
||||
// Wait for finish loading
|
||||
cy.get('[data-cy="viewprt-grid"]', { timeout: 30000 }).should($grid => {
|
||||
cy.get('[data-cy="viewprt-grid"]', { timeout: 90000 }).should($grid => {
|
||||
expect($grid).not.to.contain.text('Loading');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/viewer",
|
||||
"version": "4.2.15",
|
||||
"version": "4.5.0",
|
||||
"description": "OHIF Viewer",
|
||||
"author": "OHIF Contributors",
|
||||
"license": "MIT",
|
||||
@@ -48,16 +48,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@ohif/core": "^2.9.13",
|
||||
"@ohif/extension-cornerstone": "^2.8.5",
|
||||
"@ohif/core": "^2.10.0",
|
||||
"@ohif/extension-cornerstone": "^2.9.1",
|
||||
"@ohif/extension-dicom-html": "^1.2.4",
|
||||
"@ohif/extension-dicom-microscopy": "^0.51.0",
|
||||
"@ohif/extension-dicom-p10-downloader": "^0.1.2",
|
||||
"@ohif/extension-dicom-pdf": "^1.0.3",
|
||||
"@ohif/extension-dicom-rt": "^0.2.6",
|
||||
"@ohif/extension-dicom-segmentation": "^0.3.3",
|
||||
"@ohif/extension-dicom-rt": "^0.4.0",
|
||||
"@ohif/extension-dicom-segmentation": "^0.4.0",
|
||||
"@ohif/extension-lesion-tracker": "^0.2.0",
|
||||
"@ohif/extension-vtk": "^1.6.9",
|
||||
"@ohif/extension-vtk": "^1.7.0",
|
||||
"@ohif/i18n": "^0.52.8",
|
||||
"@ohif/ui": "^1.5.3",
|
||||
"@tanem/react-nprogress": "^1.1.25",
|
||||
@@ -65,7 +65,7 @@
|
||||
"core-js": "^3.2.1",
|
||||
"cornerstone-core": "^2.2.8",
|
||||
"cornerstone-math": "^0.1.8",
|
||||
"cornerstone-tools": "4.15.1",
|
||||
"cornerstone-tools": "^4.20.1",
|
||||
"cornerstone-wado-image-loader": "^3.1.0",
|
||||
"dcmjs": "0.16.0",
|
||||
"dicom-parser": "^1.8.3",
|
||||
|
||||
@@ -2,6 +2,7 @@ window.config = function(props) {
|
||||
var servicesManager = props.servicesManager;
|
||||
|
||||
return {
|
||||
disableMeasurementPanel: true,
|
||||
routerBasename: '/',
|
||||
enableGoogleCloudAdapter: true,
|
||||
enableGoogleCloudAdapterUI: false,
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
ModalProvider,
|
||||
DialogProvider,
|
||||
OHIFModal,
|
||||
ErrorBoundary
|
||||
ErrorBoundary,
|
||||
} from '@ohif/ui';
|
||||
|
||||
import {
|
||||
@@ -168,7 +168,7 @@ class App extends Component {
|
||||
|
||||
if (this._userManager) {
|
||||
return (
|
||||
<ErrorBoundary context='App'>
|
||||
<ErrorBoundary context="App">
|
||||
<Provider store={store}>
|
||||
<AppProvider config={this._appConfig}>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
@@ -200,7 +200,7 @@ class App extends Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<ErrorBoundary context='App'>
|
||||
<ErrorBoundary context="App">
|
||||
<Provider store={store}>
|
||||
<AppProvider config={this._appConfig}>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
@@ -271,17 +271,21 @@ function _initExtensions(extensions, cornerstoneExtensionConfig, appConfig) {
|
||||
api: {
|
||||
contexts: CONTEXTS,
|
||||
hooks: {
|
||||
useAppContext
|
||||
}
|
||||
}
|
||||
useAppContext,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const requiredExtensions = [
|
||||
GenericViewerCommands,
|
||||
[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);
|
||||
extensionManager.registerExtensions(mergedExtensions);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ const ViewportGrid = function(props) {
|
||||
// - When updating a panel, ensure that the currently enabled plugin
|
||||
// in the viewport is capable of rendering this display set. If not
|
||||
// then use the most capable available plugin
|
||||
|
||||
const pluginName =
|
||||
!layout.plugin && displaySet && displaySet.plugin
|
||||
? displaySet.plugin
|
||||
|
||||
@@ -4,6 +4,8 @@ import { StudyBrowser } from '@ohif/ui';
|
||||
import cloneDeep from 'lodash.clonedeep';
|
||||
import findDisplaySetByUID from './findDisplaySetByUID';
|
||||
|
||||
const { studyMetadataManager } = OHIF.utils;
|
||||
|
||||
const { setActiveViewportSpecificData } = OHIF.redux.actions;
|
||||
|
||||
// TODO
|
||||
@@ -39,11 +41,27 @@ const mapStateToProps = (state, ownProps) => {
|
||||
const mapDispatchToProps = (dispatch, ownProps) => {
|
||||
return {
|
||||
onThumbnailClick: displaySetInstanceUID => {
|
||||
const displaySet = findDisplaySetByUID(
|
||||
let displaySet = findDisplaySetByUID(
|
||||
ownProps.studyMetadata,
|
||||
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));
|
||||
},
|
||||
};
|
||||
|
||||
@@ -133,12 +133,23 @@ class ViewerMain extends Component {
|
||||
StudyInstanceUID,
|
||||
displaySetInstanceUID,
|
||||
}) => {
|
||||
const displaySet = this.findDisplaySet(
|
||||
let displaySet = this.findDisplaySet(
|
||||
this.props.studies,
|
||||
StudyInstanceUID,
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,23 +14,25 @@ const { OHIFStudyMetadata, OHIFSeriesMetadata } = metadata;
|
||||
const { retrieveStudiesMetadata, deleteStudyMetadataPromise } = studies;
|
||||
const { studyMetadataManager, makeCancelable } = utils;
|
||||
|
||||
const _promoteToFront = (list, value, searchMethod) => {
|
||||
let response = [...list];
|
||||
let promoted = false;
|
||||
const index = response.findIndex(searchMethod.bind(undefined, value));
|
||||
const _promoteToFront = (list, values, searchMethod) => {
|
||||
let listCopy = [...list];
|
||||
let response = [];
|
||||
let promotedCount = 0;
|
||||
|
||||
if (index > 0) {
|
||||
const first = response.splice(index, 1);
|
||||
response = [...first, ...response];
|
||||
}
|
||||
const arrayValues = values.split(',');
|
||||
arrayValues.forEach(value => {
|
||||
const index = listCopy.findIndex(searchMethod.bind(undefined, value));
|
||||
|
||||
if (index >= 0) {
|
||||
promoted = true;
|
||||
}
|
||||
if (index >= 0) {
|
||||
const [itemToPromote] = listCopy.splice(index, 1);
|
||||
response[promotedCount] = itemToPromote;
|
||||
promotedCount++;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
promoted,
|
||||
data: response,
|
||||
promoted: promotedCount === arrayValues.length,
|
||||
data: [...response, ...listCopy],
|
||||
};
|
||||
};
|
||||
|
||||
@@ -90,12 +92,48 @@ const _isQueryParamApplied = (study, filters = {}, isFilterStrategy) => {
|
||||
if (!seriesInstanceUID) {
|
||||
return applied;
|
||||
}
|
||||
const seriesInstanceUIDs = seriesInstanceUID.split(',');
|
||||
|
||||
let validateFilterApplied = () => {
|
||||
const sameSize = arrayToInspect.length === seriesInstanceUIDs.length;
|
||||
if (!sameSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
return arrayToInspect.every(item =>
|
||||
seriesInstanceUIDs.some(
|
||||
seriesInstanceUIDStr => seriesInstanceUIDStr === item.SeriesInstanceUID
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
let validatePromoteApplied = () => {
|
||||
let isValid = true;
|
||||
for (let index = 0; index < seriesInstanceUIDs.length; index++) {
|
||||
const seriesInstanceUIDStr = seriesInstanceUIDs[index];
|
||||
const resultSeries = arrayToInspect[index];
|
||||
|
||||
if (
|
||||
!resultSeries ||
|
||||
resultSeries.SeriesInstanceUID !== seriesInstanceUIDStr
|
||||
) {
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isValid;
|
||||
};
|
||||
|
||||
const { series = [], displaySets = [] } = study;
|
||||
const firstSeries = isFilterStrategy ? series[0] : displaySets[0];
|
||||
const arrayToInspect = isFilterStrategy ? series : displaySets;
|
||||
const validateMethod = isFilterStrategy
|
||||
? validateFilterApplied
|
||||
: validatePromoteApplied;
|
||||
|
||||
if (!firstSeries || firstSeries.SeriesInstanceUID !== seriesInstanceUID) {
|
||||
if (!arrayToInspect) {
|
||||
applied = false;
|
||||
} else {
|
||||
applied = validateMethod();
|
||||
}
|
||||
|
||||
return applied;
|
||||
@@ -221,7 +259,7 @@ function ViewerRetrieveStudyData({
|
||||
// Show message in case not promoted neither filtered but should to
|
||||
_showUserMessage(
|
||||
isQueryParamApplied,
|
||||
'Query parameters were not applied. Using original series list for given study.',
|
||||
'Query parameters were not totally applied. It might be using original series list for given study.',
|
||||
snackbarContext
|
||||
);
|
||||
|
||||
@@ -233,7 +271,7 @@ function ViewerRetrieveStudyData({
|
||||
* Method to process studies. It will update displaySet, studyMetadata, load remaining series, ...
|
||||
* @param {Array} studiesData Array of studies retrieved from server
|
||||
* @param {Object} [filters] - Object containing filters to be applied
|
||||
* @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against
|
||||
* @param {string} [filters.seriesInstanceUID] - series instance uid to filter results against
|
||||
*/
|
||||
const processStudies = (studiesData, filters) => {
|
||||
if (Array.isArray(studiesData) && studiesData.length > 0) {
|
||||
@@ -299,7 +337,6 @@ function ViewerRetrieveStudyData({
|
||||
const filters = {};
|
||||
// Use the first, discard others
|
||||
const seriesInstanceUID = seriesInstanceUIDs && seriesInstanceUIDs[0];
|
||||
|
||||
const retrieveParams = [server, studyInstanceUIDs];
|
||||
|
||||
if (seriesInstanceUID) {
|
||||
|
||||
@@ -5950,10 +5950,10 @@ cornerstone-math@^0.1.8:
|
||||
resolved "https://registry.yarnpkg.com/cornerstone-math/-/cornerstone-math-0.1.8.tgz#68ab1f9e4fdcd7c5cb23a0d2eb4263f9f894f1c5"
|
||||
integrity sha512-x7NEQHBtVG7j1yeyj/aRoKTpXv1Vh2/H9zNLMyqYJDtJkNng8C4Q8M3CgZ1qer0Yr7eVq2x+Ynmj6kfOm5jXKw==
|
||||
|
||||
cornerstone-tools@4.15.1:
|
||||
version "4.15.1"
|
||||
resolved "https://registry.yarnpkg.com/cornerstone-tools/-/cornerstone-tools-4.15.1.tgz#f0b1026da9c7758defc088bb2f1e78426a23d91e"
|
||||
integrity sha512-fJuTUJW/NDSD520jPB++tX//Kq80jPDngChHZrhx2xjj/9dCnexD9kmTX30Z0WUq0a2JEHZ6FlcOX38kSmw1hQ==
|
||||
cornerstone-tools@^4.20.1:
|
||||
version "4.20.1"
|
||||
resolved "https://registry.yarnpkg.com/cornerstone-tools/-/cornerstone-tools-4.20.1.tgz#90f6c28356622eac037683b19f9175f85d33dff7"
|
||||
integrity sha512-SyQsrg3bnGHUvWGZpUq7ia7/gj12S9zQFK2VMhpyAYxK9pWz+PRv8HBi0eEe/fWGAo/Vc62IRkdP3uF9MJlqiQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.1.2"
|
||||
cornerstone-math "0.1.7"
|
||||
@@ -16047,10 +16047,10 @@ react-transition-group@^4.1.1:
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
react-vtkjs-viewport@^0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/react-vtkjs-viewport/-/react-vtkjs-viewport-0.9.0.tgz#5a7890643e511946f960db6b05142318be2dfe80"
|
||||
integrity sha512-kjpNr1n+eW0nU736HH07IsSYQXphxfn/RBvKtpBer9tNsl+FyLH8h+uY8KWdv8kVBHkEoaH6/srxB0JBa8l+jA==
|
||||
react-vtkjs-viewport@^0.10.3:
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/react-vtkjs-viewport/-/react-vtkjs-viewport-0.10.3.tgz#8eaa8bc558057215b648ad6ce17092d68cf5354b"
|
||||
integrity sha512-9aXuBrAlKa79Q1qPSWmPflSgpG2sm5jyKresdqUUvqYVJQJx83Xkkh4XfgOfLHY/nEwpTI8dr3FwtH2dzrBkoA==
|
||||
dependencies:
|
||||
date-fns "^2.2.1"
|
||||
gl-matrix "^3.1.0"
|
||||
|
||||
Reference in new issue
Block a user