Compare commits

..
Author SHA1 Message Date
ohif-bot 08de987711 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.2.1
 - @ohif/viewer@3.11.1
2020-04-27 08:41:40 +00:00
Igor Octaviano 20e366ffbd fix: 🐛 Dropdown not updating when selecting segment (#1675)
Observe selectedSegmentation changes to refresh segment list

✅ Closes: #1669
2020-04-27 10:39:11 +02:00
ohif-bot 561911056a chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.7.0
 - @ohif/extension-dicom-html@1.2.0
 - @ohif/extension-dicom-rt@0.1.0
 - @ohif/extension-dicom-segmentation@0.2.0
 - @ohif/extension-vtk@1.5.0
 - @ohif/core@2.9.0
 - @ohif/viewer@3.11.0
2020-04-24 10:29:19 +00:00
Igor OctavianoandJames Petts 835f64d47a feat: 🎸 Seg jump to slice + show/hide
* Add segment part 2 (jump to frame and visibility toggle)

* Cr updates

* Filter displaysets with images

* feat: 🎸 Seg jump to slice + show/hide

Co-authored-by: James Petts <jamesapetts@gmail.com>
2020-04-24 12:25:05 +02:00
ohif-bot fc40d84092 chore(release): publish [skip ci]
- @ohif/viewer@3.10.2
2020-04-23 16:20:51 +00:00
Danny Brown 709f14708e fix: undefined errorHandler in cornerstoneWadoImageLoader configuration (#1664) 2020-04-23 12:17:49 -04:00
27 changed files with 497 additions and 246 deletions

No files matched your search

+11
View File
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.7.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.6.1...@ohif/extension-cornerstone@2.7.0) (2020-04-24)
### Features
* 🎸 Seg jump to slice + show/hide ([835f64d](https://github.com/OHIF/Viewers/commit/835f64d47a9994f6a25aaf3941a4974e215e7e7f))
## [2.6.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.6.0...@ohif/extension-cornerstone@2.6.1) (2020-04-23)
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone",
"version": "2.6.1",
"version": "2.7.0",
"description": "OHIF extension for Cornerstone",
"author": "OHIF",
"license": "MIT",
@@ -36,7 +36,7 @@
"cornerstone-math": "^0.1.8",
"cornerstone-tools": "4.12.5",
"cornerstone-wado-image-loader": "^3.1.0",
"dcmjs": "^0.10.1",
"dcmjs": "^0.12.2",
"dicom-parser": "^1.8.3",
"hammerjs": "^2.0.8",
"prop-types": "^15.6.2",
+1 -1
View File
@@ -267,7 +267,7 @@ const commandsModule = ({ servicesManager }) => {
const study = studyMetadataManager.get(StudyInstanceUID);
const displaySet = study.findDisplaySet(ds => {
return ds.images.find(i => i.getSOPInstanceUID() === SOPInstanceUID)
return ds.images && ds.images.find(i => i.getSOPInstanceUID() === SOPInstanceUID)
});
displaySet.SOPInstanceUID = SOPInstanceUID;
+11
View File
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.2.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.1.2...@ohif/extension-dicom-html@1.2.0) (2020-04-24)
### Features
* 🎸 Seg jump to slice + show/hide ([835f64d](https://github.com/OHIF/Viewers/commit/835f64d47a9994f6a25aaf3941a4974e215e7e7f))
## [1.1.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.1.1...@ohif/extension-dicom-html@1.1.2) (2020-04-02)
**Note:** Version bump only for package @ohif/extension-dicom-html
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-html",
"version": "1.1.2",
"version": "1.2.0",
"description": "OHIF extension for rendering structured reports to HTML",
"author": "OHIF",
"license": "MIT",
@@ -29,7 +29,7 @@
},
"peerDependencies": {
"@ohif/core": "^0.50.0",
"dcmjs": "^0.10.1",
"dcmjs": "^0.12.2",
"prop-types": "^15.6.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"
+11
View File
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [0.1.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.0.2...@ohif/extension-dicom-rt@0.1.0) (2020-04-24)
### Features
* 🎸 Seg jump to slice + show/hide ([835f64d](https://github.com/OHIF/Viewers/commit/835f64d47a9994f6a25aaf3941a4974e215e7e7f))
## 0.0.2 (2020-04-09)
**Note:** Version bump only for package @ohif/extension-dicom-rt
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-rt",
"version": "0.0.2",
"version": "0.1.0",
"description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.",
"author": "OHIF",
"license": "MIT",
@@ -31,7 +31,7 @@
"@ohif/core": "^0.50.0",
"cornerstone-core": "^2.2.8",
"cornerstone-tools": "^4.0.9",
"dcmjs": "^0.8.3",
"dcmjs": "^0.12.2",
"prop-types": "^15.6.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"
@@ -61,14 +61,17 @@
}
.dcmrt-structure-set-item .item-label {
overflow: hidden;
max-width: calc(100% - 15px); /* calc(100% - 50px); 20px = eye icon */
text-overflow: ellipsis;
overflow-wrap: normal;
white-space: nowrap;
display: flex;
justify-content: space-between;
padding-right: 10px;
}
.dcmrt-structure-set-item .item-label span {
overflow-wrap: normal;
white-space: nowrap;
overflow: hidden;
max-width: calc(100% - 40px); /* calc(100% - 50px); 20px = eye icon */
text-overflow: ellipsis;
}
.dcmrt-structure-set-item .item-label .eye-icon {
@@ -41,7 +41,7 @@ const StructureSetItem = ({
>
<div>
<div className="item-label" style={{ marginBottom: 4 }}>
{label}
<span>{label}</span>
<Icon
className={`eye-icon ${isVisible && '--visible'}`}
name={isVisible ? 'eye' : 'eye-closed'}
+5 -6
View File
@@ -27,10 +27,7 @@ export default {
};
return (
<RTPanel
{...props}
onContourItemClick={contourItemClickHandler}
/>
<RTPanel {...props} onContourItemClick={contourItemClickHandler} />
);
};
@@ -51,8 +48,10 @@ export default {
if (study && study.series) {
for (let j = 0; j < study.series.length; j++) {
const series = study.series[j];
console.log(studies);
if (['RTSTRUCT', 'RTPLAN', 'RTDOSE'].includes(series.Modality)) {
if (
/* Could be expanded to contain RTPLAN and RTDOSE information in the future */
['RTSTRUCT'].includes(series.Modality)
) {
return false;
}
}
@@ -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.
## [0.2.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.2.0...@ohif/extension-dicom-segmentation@0.2.1) (2020-04-27)
### Bug Fixes
* 🐛 Dropdown not updating when selecting segment ([#1675](https://github.com/OHIF/Viewers/issues/1675)) ([20e366f](https://github.com/OHIF/Viewers/commit/20e366ffbd76781f48dc99c9f59e24b255b5e5df)), closes [#1669](https://github.com/OHIF/Viewers/issues/1669)
# [0.2.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.1.2...@ohif/extension-dicom-segmentation@0.2.0) (2020-04-24)
### Features
* 🎸 Seg jump to slice + show/hide ([835f64d](https://github.com/OHIF/Viewers/commit/835f64d47a9994f6a25aaf3941a4974e215e7e7f))
## [0.1.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.1.1...@ohif/extension-dicom-segmentation@0.1.2) (2020-04-09)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-segmentation",
"version": "0.1.2",
"version": "0.2.1",
"description": "OHIF extension for viewing segmentations in the 2D MPR view",
"author": "OHIF",
"license": "MIT",
@@ -31,7 +31,7 @@
"@ohif/core": "^0.50.0",
"cornerstone-core": "^2.2.8",
"cornerstone-tools": "4.12.5",
"dcmjs": "^0.6.1",
"dcmjs": "^0.12.2",
"prop-types": "^15.6.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"
@@ -12,14 +12,6 @@
height: 20px;
}
.dcmseg-segment-item .segment-label {
overflow: hidden;
max-width: calc(100% - 50px);
text-overflow: ellipsis;
overflow-wrap: normal;
white-space: nowrap;
}
.dcmseg-segment-item .segment-info {
display: inline-block;
margin-top: 9px;
@@ -62,3 +54,30 @@
.dcmseg-segment-item .segment-actions .btnAction i {
margin-right: 4px;
}
.dcmseg-segment-item .segment-label {
display: flex;
justify-content: space-between;
padding-right: 20px;
}
.dcmseg-segment-item .segment-label span {
overflow-wrap: normal;
white-space: nowrap;
overflow: hidden;
max-width: calc(100% - 40px); /* calc(100% - 50px); 20px = eye icon */
text-overflow: ellipsis;
}
.dcmseg-segment-item .segment-label .eye-icon {
cursor: pointer;
color: var(--active-color);
}
.dcmseg-segment-item .segment-label .eye-icon:hover {
color: var(--hover-color);
}
.dcmseg-segment-item .segment-label .eye-icon.--visible {
color: var(--default-color);
}
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { TableListItem, Icon } from '@ohif/ui';
@@ -17,48 +17,63 @@ ColoredCircle.propTypes = {
color: PropTypes.array.isRequired,
};
const SegmentItem = ({ index, label, onClick, itemClass, color }) => (
<div className="dcmseg-segment-item">
<TableListItem
key={index}
itemKey={index}
itemIndex={index}
itemClass={itemClass}
itemMeta={<ColoredCircle color={color} />}
itemMetaClass="segment-color-section"
onItemClick={onClick}
>
<div>
<div className="segment-label" style={{ marginBottom: 4 }}>
{label}
</div>
{false && <div className="segment-info">{'...'}</div>}
{false && (
<div className="segment-actions">
<button
className="btnAction"
onClick={() => console.log('Relabelling...')}
>
<span style={{ marginRight: '4px' }}>
<Icon name="edit" width="14px" height="14px" />
</span>
const SegmentItem = ({ index, label, onClick, itemClass, color, visible = true, onVisibilityChange }) => {
const [isVisible, setIsVisible] = useState(visible);
return (
<div className="dcmseg-segment-item">
<TableListItem
key={index}
itemKey={index}
itemIndex={index}
itemClass={itemClass}
itemMeta={<ColoredCircle color={color} />}
itemMetaClass="segment-color-section"
onItemClick={onClick}
>
<div>
<div className="segment-label" style={{ marginBottom: 4 }}>
<span>{label}</span>
<Icon
className={`eye-icon ${isVisible && '--visible'}`}
name={isVisible ? 'eye' : 'eye-closed'}
width="20px"
height="20px"
onClick={event => {
event.stopPropagation();
const newVisibility = !isVisible;
setIsVisible(newVisibility);
onVisibilityChange(newVisibility);
}}
/>
</div>
{false && <div className="segment-info">{'...'}</div>}
{false && (
<div className="segment-actions">
<button
className="btnAction"
onClick={() => console.log('Relabelling...')}
>
<span style={{ marginRight: '4px' }}>
<Icon name="edit" width="14px" height="14px" />
</span>
Relabel
</button>
<button
className="btnAction"
onClick={() => console.log('Editing description...')}
>
<span style={{ marginRight: '4px' }}>
<Icon name="edit" width="14px" height="14px" />
</span>
<button
className="btnAction"
onClick={() => console.log('Editing description...')}
>
<span style={{ marginRight: '4px' }}>
<Icon name="edit" width="14px" height="14px" />
</span>
Description
</button>
</div>
)}
</div>
</TableListItem>
</div>
);
</div>
)}
</div>
</TableListItem>
</div>
);
};
SegmentItem.propTypes = {
index: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import cornerstoneTools from 'cornerstone-tools';
import cornerstone from 'cornerstone-core';
@@ -28,13 +28,20 @@ const refreshViewport = () => {
/**
* SegmentationPanel component
*
* @param {Object} props
* @param {Array} props.studies
* @param {Array} props.viewports - viewportSpecificData
* @param {number} props.activeIndex - activeViewportIndex
* @param {Array} props.studies - Studies data
* @param {Array} props.viewports - Viewports data (viewportSpecificData)
* @param {number} props.activeIndex - Active viewport index
* @param {boolean} props.isOpen - Boolean that indicates if the panel is expanded
* @param {Function} props.onSegItemClick - Segment click handler
* @returns component
*/
const SegmentationPanel = ({ studies, viewports, activeIndex, isOpen }) => {
const SegmentationPanel = ({
studies,
viewports,
activeIndex,
isOpen,
onSegItemClick,
}) => {
/*
* TODO: wrap get/set interactions with the cornerstoneTools
* store with context to make these kind of things less blurry.
@@ -43,13 +50,14 @@ const SegmentationPanel = ({ studies, viewports, activeIndex, isOpen }) => {
const DEFAULT_BRUSH_RADIUS = configuration.radius || 10;
const [state, setState] = useState({
brushRadius: DEFAULT_BRUSH_RADIUS,
brushColor: 'rgba(221, 85, 85, 1)', /* TODO: We shouldn't hardcode this color, in the future the SEG may set the colorLUT to whatever it wants. */
brushColor:
'rgba(221, 85, 85, 1)' /* TODO: We shouldn't hardcode this color, in the future the SEG may set the colorLUT to whatever it wants. */,
selectedSegment: null,
selectedSegmentation: null,
showSegSettings: false,
brushStackState: null,
labelmapList: [],
segmentList: []
segmentList: [],
});
useEffect(() => {
@@ -57,7 +65,12 @@ const SegmentationPanel = ({ studies, viewports, activeIndex, isOpen }) => {
log.warn('Segmentation Panel: labelmap modified', event);
const module = cornerstoneTools.getModule('segmentation');
const activeViewport = viewports[activeIndex];
const firstImageId = studyMetadata.getFirstImageId(activeViewport.displaySetInstanceUID);
const studyMetadata = studyMetadataManager.get(
activeViewport.StudyInstanceUID
);
const firstImageId = studyMetadata.getFirstImageId(
activeViewport.displaySetInstanceUID
);
updateState('brushStackState', module.state.series[firstImageId]);
};
@@ -86,20 +99,29 @@ const SegmentationPanel = ({ studies, viewports, activeIndex, isOpen }) => {
useEffect(() => {
const module = cornerstoneTools.getModule('segmentation');
const activeViewport = viewports[activeIndex];
const studyMetadata = studyMetadataManager.get(activeViewport.StudyInstanceUID);
const firstImageId = studyMetadata.getFirstImageId(activeViewport.displaySetInstanceUID);
const studyMetadata = studyMetadataManager.get(
activeViewport.StudyInstanceUID
);
const firstImageId = studyMetadata.getFirstImageId(
activeViewport.displaySetInstanceUID
);
const brushStackState = module.state.series[firstImageId];
if (brushStackState) {
const labelmap3D = brushStackState.labelmaps3D[brushStackState.activeLabelmapIndex];
const labelmapList = getLabelmapList(brushStackState, firstImageId, activeViewport);
const segmentList = getSegmentList(labelmap3D, firstImageId);
const labelmap3D =
brushStackState.labelmaps3D[brushStackState.activeLabelmapIndex];
const labelmapList = getLabelmapList(
brushStackState,
firstImageId,
activeViewport
);
const segmentList = getSegmentList(labelmap3D, firstImageId, brushStackState);
setState(state => ({
...state,
brushStackState,
selectedSegmentation: brushStackState.activeLabelmapIndex,
labelmapList,
segmentList
segmentList,
}));
} else {
setState(state => ({
@@ -108,126 +130,201 @@ const SegmentationPanel = ({ studies, viewports, activeIndex, isOpen }) => {
segmentList: [],
}));
}
}, [studies, viewports, activeIndex]);
}, [studies, viewports, activeIndex, getLabelmapList, getSegmentList, state.selectedSegmentation]);
/* Handle open/closed panel behaviour */
useEffect(() => {
updateState('showSegSettings', state.showSegSettings && !isOpen);
setState(state => ({
...state,
showSegSettings: state.showSegSettings && !isOpen,
}));
}, [isOpen]);
const getLabelmapList = (brushStackState, firstImageId, activeViewport) => {
/* Get list of SEG labelmaps specific to active viewport (reference series) */
const referencedSegDisplaysets = _getReferencedSegDisplaysets(
activeViewport.StudyInstanceUID,
activeViewport.SeriesInstanceUID
);
const getLabelmapList = useCallback(
(brushStackState, firstImageId, activeViewport) => {
/* Get list of SEG labelmaps specific to active viewport (reference series) */
const referencedSegDisplaysets = _getReferencedSegDisplaysets(
activeViewport.StudyInstanceUID,
activeViewport.SeriesInstanceUID
);
return referencedSegDisplaysets.map((displaySet, index) => {
const { labelmapIndex, SeriesDate, SeriesTime } = displaySet;
return referencedSegDisplaysets.map((displaySet, index) => {
const { labelmapIndex, SeriesDate, SeriesTime } = displaySet;
/* Map to display representation */
const dateStr = `${SeriesDate}:${SeriesTime}`.split('.')[0];
const date = moment(dateStr, 'YYYYMMDD:HHmmss');
const isActiveLabelmap =
labelmapIndex === brushStackState.activeLabelmapIndex;
const displayDate = date.format('ddd, MMM Do YYYY');
const displayTime = date.format('h:mm:ss a');
const displayDescription = displaySet.SeriesDescription;
/* Map to display representation */
const dateStr = `${SeriesDate}:${SeriesTime}`.split('.')[0];
const date = moment(dateStr, 'YYYYMMDD:HHmmss');
const isActiveLabelmap =
labelmapIndex === brushStackState.activeLabelmapIndex;
const displayDate = date.format('ddd, MMM Do YYYY');
const displayTime = date.format('h:mm:ss a');
const displayDescription = displaySet.SeriesDescription;
return {
value: labelmapIndex,
title: displayDescription,
description: displayDate,
onClick: async () => {
const activatedLabelmapIndex = await _setActiveLabelmap(
activeViewport,
studies,
displaySet,
firstImageId,
brushStackState.activeLabelmapIndex
);
updateState('selectedSegmentation', activatedLabelmapIndex);
},
};
});
};
return {
value: labelmapIndex,
title: displayDescription,
description: displayDate,
onClick: async () => {
const activatedLabelmapIndex = await _setActiveLabelmap(
activeViewport,
studies,
displaySet,
firstImageId,
brushStackState.activeLabelmapIndex
);
updateState('selectedSegmentation', activatedLabelmapIndex);
},
};
});
},
[studies]
);
const getSegmentList = (labelmap3D, firstImageId) => {
/*
* Newly created segments have no `meta`
* So we instead build a list of all segment indexes in use
* Then find any associated metadata
*/
const uniqueSegmentIndexes = labelmap3D.labelmaps2D
.reduce((acc, labelmap2D) => {
if (labelmap2D) {
const segmentIndexes = labelmap2D.segmentsOnLabelmap;
const getSegmentList = useCallback(
(labelmap3D, firstImageId, brushStackState) => {
/*
* Newly created segments have no `meta`
* So we instead build a list of all segment indexes in use
* Then find any associated metadata
*/
const uniqueSegmentIndexes = labelmap3D.labelmaps2D
.reduce((acc, labelmap2D) => {
if (labelmap2D) {
const segmentIndexes = labelmap2D.segmentsOnLabelmap;
for (let i = 0; i < segmentIndexes.length; i++) {
if (!acc.includes(segmentIndexes[i]) && segmentIndexes[i] !== 0) {
acc.push(segmentIndexes[i]);
for (let i = 0; i < segmentIndexes.length; i++) {
if (!acc.includes(segmentIndexes[i]) && segmentIndexes[i] !== 0) {
acc.push(segmentIndexes[i]);
}
}
}
return acc;
}, [])
.sort((a, b) => a - b);
const module = cornerstoneTools.getModule('segmentation');
const colorLutTable =
module.state.colorLutTables[labelmap3D.colorLUTIndex];
const hasLabelmapMeta = labelmap3D.metadata && labelmap3D.metadata.data;
const segmentList = [];
for (let i = 0; i < uniqueSegmentIndexes.length; i++) {
const segmentIndex = uniqueSegmentIndexes[i];
const color = colorLutTable[segmentIndex];
let segmentLabel = '(unlabeled)';
let segmentNumber = segmentIndex;
/* Meta */
if (hasLabelmapMeta) {
const segmentMeta = labelmap3D.metadata.data[segmentIndex];
if (segmentMeta) {
segmentNumber = segmentMeta.SegmentNumber;
segmentLabel = segmentMeta.SegmentLabel;
}
}
return acc;
}, [])
.sort((a, b) => a - b);
const sameSegment = state.selectedSegment === segmentNumber;
const setCurrentSelectedSegment = () => {
_setActiveSegment(
firstImageId,
segmentNumber,
labelmap3D.activeSegmentIndex
);
updateState('selectedSegment', sameSegment ? null : segmentNumber);
const module = cornerstoneTools.getModule('segmentation');
const colorLutTable =
module.state.colorLutTables[labelmap3D.colorLUTIndex];
const hasLabelmapMeta = labelmap3D.metadata && labelmap3D.metadata.data;
const validIndexList = [];
labelmap3D.labelmaps2D.forEach((labelMap2D, index) => {
if (labelMap2D.segmentsOnLabelmap.includes(segmentNumber)) {
validIndexList.push(index);
}
});
const avg = array => array.reduce((a, b) => a + b) / array.length;
const average = avg(validIndexList);
const closest = validIndexList.reduce((prev, curr) => {
return Math.abs(curr - average) < Math.abs(prev - average)
? curr
: prev;
});
const segmentList = [];
for (let i = 0; i < uniqueSegmentIndexes.length; i++) {
const segmentIndex = uniqueSegmentIndexes[i];
const enabledElements = cornerstone.getEnabledElements();
const element = enabledElements[activeIndex].element;
const toolState = cornerstoneTools.getToolState(element, 'stack');
const color = colorLutTable[segmentIndex];
let segmentLabel = '(unlabeled)';
let segmentNumber = segmentIndex;
if (!toolState) {
return;
}
/* Meta */
if (hasLabelmapMeta) {
const segmentMeta = labelmap3D.metadata.data[segmentIndex];
const imageIds = toolState.data[0].imageIds;
const imageId = imageIds[closest];
const frameIndex = imageIds.indexOf(imageId);
if (segmentMeta) {
segmentNumber = segmentMeta.SegmentNumber;
segmentLabel = segmentMeta.SegmentLabel;
const SOPInstanceUID = cornerstone.metaData.get(
'SOPInstanceUID',
imageId
);
const StudyInstanceUID = cornerstone.metaData.get(
'StudyInstanceUID',
imageId
);
onSegItemClick({
StudyInstanceUID,
SOPInstanceUID,
frameIndex,
activeViewportIndex: activeIndex,
});
};
const enabledElements = cornerstone.getEnabledElements();
const enabledElementViewport = enabledElements[activeIndex];
let isVisible = true;
if (enabledElementViewport) {
const element = enabledElementViewport.element;
const module = cornerstoneTools.getModule('segmentation');
isVisible = module.getters.isSegmentVisible(
element,
segmentNumber,
brushStackState.activeLabelmapIndex
);
}
segmentList.push(
<SegmentItem
key={segmentNumber}
itemClass={`segment-item ${sameSegment && 'selected'}`}
onClick={setCurrentSelectedSegment}
label={segmentLabel}
index={segmentNumber}
color={color}
visible={isVisible}
onVisibilityChange={() => {
const element = enabledElements[activeIndex].element;
module.setters.toggleSegmentVisibility(
element,
segmentNumber,
brushStackState.activeLabelmapIndex
);
refreshViewport();
}}
/>
);
}
const sameSegment = state.selectedSegment === segmentNumber;
const setCurrentSelectedSegment = () => {
_setActiveSegment(
firstImageId,
segmentNumber,
labelmap3D.activeSegmentIndex
);
updateState('selectedSegment', sameSegment ? null : segmentNumber);
};
return segmentList;
segmentList.push(
<SegmentItem
key={segmentNumber}
itemClass={`segment-item ${sameSegment && 'selected'}`}
onClick={setCurrentSelectedSegment}
label={segmentLabel}
index={segmentNumber}
color={color}
/>
);
}
return segmentList;
/*
* Let's iterate over segmentIndexes ^ above
* If meta has a match, use it to show info
* If now, add "no-meta" class
* Show default name
*/
};
/*
* Let's iterate over segmentIndexes ^ above
* If meta has a match, use it to show info
* If now, add "no-meta" class
* Show default name
*/
},
[activeIndex, onSegItemClick, state.selectedSegment]
);
const updateState = (field, value) => {
setState(state => ({ ...state, [field]: value }));
@@ -270,8 +367,7 @@ const SegmentationPanel = ({ studies, viewports, activeIndex, isOpen }) => {
}
const module = cornerstoneTools.getModule('segmentation');
const colorLutTable =
module.state.colorLutTables[labelmap3D.colorLUTIndex];
const colorLutTable = module.state.colorLutTables[labelmap3D.colorLUTIndex];
const color = colorLutTable[labelmap3D.activeSegmentIndex];
return `rgba(${color.join(',')})`;
@@ -328,9 +424,7 @@ const SegmentationPanel = ({ studies, viewports, activeIndex, isOpen }) => {
<h3>Segmentations</h3>
<div className="segmentations">
<SegmentationSelect
value={
state.labelmapList.find(i => i.value === state.selectedSegmentation) || null
}
value={state.labelmapList.find(i => i.value === state.selectedSegmentation)}
formatOptionLabel={SegmentationItem}
options={state.labelmapList}
/>
@@ -17,6 +17,10 @@ const defaultColor = computedstyle.getPropertyValue('--default-color');
const uiGrayDark = computedstyle.getPropertyValue('--ui-gray-dark');
const segmentationSelectStyles = {
singleValue: (base, state) => ({
...base,
width: '100%'
}),
control: (base, state) => ({
...base,
cursor: 'pointer',
+51 -3
View File
@@ -1,7 +1,9 @@
import React from 'react';
import init from './init.js';
import toolbarModule from './toolbarModule.js';
import panelModule from './panelModule.js';
import sopClassHandlerModule from './OHIFDicomSegSopClassHandler.js';
import SegmentationPanel from './components/SegmentationPanel/SegmentationPanel.js';
export default {
/**
@@ -21,8 +23,54 @@ export default {
getToolbarModule({ servicesManager }) {
return toolbarModule;
},
getPanelModule({ servicesManager }) {
return panelModule;
getPanelModule({ commandsManager }) {
const ExtendedSegmentationPanel = props => {
const segItemClickHandler = segData => {
commandsManager.runCommand('jumpToImage', segData);
};
return (
<SegmentationPanel {...props} onSegItemClick={segItemClickHandler} />
);
};
return {
menuOptions: [
{
icon: 'list',
label: 'Segmentations',
target: 'segmentation-panel',
isDisabled: studies => {
if (!studies) {
return true;
}
for (let i = 0; i < studies.length; i++) {
const study = studies[i];
if (study && study.series) {
for (let j = 0; j < study.series.length; j++) {
const series = study.series[j];
if (series.Modality === 'SEG') {
return false;
}
}
}
}
return true;
},
},
],
components: [
{
id: 'segmentation-panel',
component: ExtendedSegmentationPanel,
},
],
defaultContext: ['VIEWER'],
};
},
getSopClassHandlerModule({ servicesManager }) {
return sopClassHandlerModule;
@@ -1,39 +0,0 @@
import SegmentationPanel from './components/SegmentationPanel/SegmentationPanel.js';
export default {
menuOptions: [
{
icon: 'list',
label: 'Segmentations',
target: 'segmentation-panel',
isDisabled: studies => {
if (!studies) {
return true;
}
for (let i = 0; i < studies.length; i++) {
const study = studies[i];
if (study && study.series) {
for (let j = 0; j < study.series.length; j++) {
const series = study.series[j];
if (series.Modality === 'SEG') {
return false;
}
}
}
}
return true;
},
},
],
components: [
{
id: 'segmentation-panel',
component: SegmentationPanel,
},
],
defaultContext: ['VIEWER'],
};
+11
View File
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.5.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.4.1...@ohif/extension-vtk@1.5.0) (2020-04-24)
### Features
* 🎸 Seg jump to slice + show/hide ([835f64d](https://github.com/OHIF/Viewers/commit/835f64d47a9994f6a25aaf3941a4974e215e7e7f))
## [1.4.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.4.0...@ohif/extension-vtk@1.4.1) (2020-04-23)
**Note:** Version bump only for package @ohif/extension-vtk
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-vtk",
"version": "1.4.1",
"version": "1.5.0",
"description": "OHIF extension for VTK.js",
"author": "OHIF",
"license": "MIT",
@@ -35,7 +35,7 @@
"cornerstone-core": "^2.2.8",
"cornerstone-tools": "4.12.5",
"cornerstone-wado-image-loader": "^3.1.0",
"dcmjs": "^0.10.1",
"dcmjs": "^0.12.2",
"dicom-parser": "^1.8.3",
"i18next": "^17.0.3",
"i18next-browser-languagedetector": "^3.0.1",
@@ -53,7 +53,7 @@
"react-vtkjs-viewport": "^0.8.3"
},
"devDependencies": {
"@ohif/core": "^2.8.1",
"@ohif/core": "^2.9.0",
"@ohif/ui": "^1.4.3",
"cornerstone-tools": "4.12.5",
"cornerstone-wado-image-loader": "^3.1.0",
+11
View File
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.9.0](https://github.com/OHIF/Viewers/compare/@ohif/core@2.8.1...@ohif/core@2.9.0) (2020-04-24)
### Features
* 🎸 Seg jump to slice + show/hide ([835f64d](https://github.com/OHIF/Viewers/commit/835f64d47a9994f6a25aaf3941a4974e215e7e7f))
## [2.8.1](https://github.com/OHIF/Viewers/compare/@ohif/core@2.8.0...@ohif/core@2.8.1) (2020-04-23)
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/core",
"version": "2.8.1",
"version": "2.9.0",
"description": "Generic business logic for web-based medical imaging applications",
"author": "OHIF Core Team",
"license": "MIT",
@@ -39,7 +39,7 @@
"dependencies": {
"@babel/runtime": "^7.5.5",
"ajv": "^6.10.0",
"dcmjs": "^0.12.0",
"dcmjs": "^0.12.2",
"dicomweb-client": "^0.6.0",
"immer": "6.0.2",
"isomorphic-base64": "^1.0.2",
@@ -400,6 +400,7 @@ class MetadataProvider {
case WADO_IMAGE_LOADER_TAGS.GENERAL_IMAGE_MODULE:
metadata = {
sopInstanceUid: instance.SOPInstanceUID,
instanceNumber: instance.InstanceNumber,
lossyImageCompression: instance.LossyImageCompression,
lossyImageCompressionRatio: instance.LossyImageCompressionRatio,
+30
View File
@@ -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.
## [3.11.1](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.11.0...@ohif/viewer@3.11.1) (2020-04-27)
**Note:** Version bump only for package @ohif/viewer
# [3.11.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.10.2...@ohif/viewer@3.11.0) (2020-04-24)
### Features
* 🎸 Seg jump to slice + show/hide ([835f64d](https://github.com/OHIF/Viewers/commit/835f64d47a9994f6a25aaf3941a4974e215e7e7f))
## [3.10.2](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.10.1...@ohif/viewer@3.10.2) (2020-04-23)
### Bug Fixes
* undefined `errorHandler` in cornerstoneWadoImageLoader configuration ([#1664](https://github.com/OHIF/Viewers/issues/1664)) ([709f147](https://github.com/OHIF/Viewers/commit/709f14708e2b0f912b5ea509114acd87af3149cb))
## [3.10.1](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.10.0...@ohif/viewer@3.10.1) (2020-04-23)
**Note:** Version bump only for package @ohif/viewer
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/viewer",
"version": "3.10.1",
"version": "3.11.1",
"description": "OHIF Viewer",
"author": "OHIF Contributors",
"license": "MIT",
@@ -48,16 +48,16 @@
},
"dependencies": {
"@babel/runtime": "^7.5.5",
"@ohif/core": "^2.8.1",
"@ohif/extension-cornerstone": "^2.6.1",
"@ohif/extension-dicom-html": "^1.1.2",
"@ohif/core": "^2.9.0",
"@ohif/extension-cornerstone": "^2.7.0",
"@ohif/extension-dicom-html": "^1.2.0",
"@ohif/extension-dicom-microscopy": "^0.50.9",
"@ohif/extension-dicom-p10-downloader": "^0.1.0",
"@ohif/extension-dicom-pdf": "^1.0.3",
"@ohif/extension-dicom-rt": "^0.0.2",
"@ohif/extension-dicom-segmentation": "^0.1.2",
"@ohif/extension-dicom-rt": "^0.1.0",
"@ohif/extension-dicom-segmentation": "^0.2.1",
"@ohif/extension-lesion-tracker": "^0.2.0",
"@ohif/extension-vtk": "^1.4.1",
"@ohif/extension-vtk": "^1.5.0",
"@ohif/i18n": "^0.52.8",
"@ohif/ui": "^1.4.3",
"@tanem/react-nprogress": "^1.1.25",
@@ -67,7 +67,7 @@
"cornerstone-math": "^0.1.8",
"cornerstone-tools": "4.12.5",
"cornerstone-wado-image-loader": "^3.1.0",
"dcmjs": "^0.12.0",
"dcmjs": "^0.12.2",
"dicom-parser": "^1.8.3",
"dicomweb-client": "^0.4.4",
"hammerjs": "^2.0.8",
+1 -1
View File
@@ -54,7 +54,7 @@ export function setConfiguration(appConfig) {
// const { appConfig = {} } = AppContext;
if (typeof appConfig.httpErrorHandler === 'function') {
appConfig.httpErrorHandler(errorHandler);
appConfig.httpErrorHandler(error);
}
},
});
+4 -4
View File
@@ -6534,10 +6534,10 @@ dateformat@^3.0.0:
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
dcmjs@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.12.0.tgz#8b1634f9b66e452075295f5d1f2c5bf3dabdf03e"
integrity sha512-AZAnFMvzAxUv5+KWoZcxnTYflLKk0rNPeeFt2KrVAgaExFBFfDgJQh1lEgqdNlIP+XQDFrEEUmp726SQhgmVCg==
dcmjs@^0.12.2:
version "0.12.2"
resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.12.2.tgz#1c16e19c27ff43202abc7cd25c5ecd6d8bf7672e"
integrity sha512-B7cEVCfDi3mOLKoBYUMYy+6COjLZhtKaesNpq5XNA4IbEH4EJYVweJfiI9gsR5hypv9LAPg72xG/xrbqjy8TgQ==
dependencies:
"@babel/polyfill" "^7.8.3"
"@babel/runtime" "^7.8.4"