diff --git a/extensions/cornerstone/src/OHIFCornerstoneViewport.js b/extensions/cornerstone/src/OHIFCornerstoneViewport.js
index 92411423b..04b2565cc 100644
--- a/extensions/cornerstone/src/OHIFCornerstoneViewport.js
+++ b/extensions/cornerstone/src/OHIFCornerstoneViewport.js
@@ -237,7 +237,7 @@ class OHIFCornerstoneViewport extends Component {
}
};
- const warningsOverlay = props => {
+ const overlay = props => {
const displaySet = this.props.viewportData.displaySet;
let filteredSRLabels;
if (displaySet.SRLabels && displaySet.SRLabels.length !== 0) {
@@ -264,7 +264,7 @@ class OHIFCornerstoneViewport extends Component {
imageIdIndex={currentImageIdIndex}
onNewImageDebounced={newImageHandler}
onNewImageDebounceTime={300}
- viewportOverlayComponent={warningsOverlay}
+ viewportOverlayComponent={overlay}
stackPrefetch={this.props.stackPrefetch}
isStackPrefetchEnabled={this.props.isStackPrefetchEnabled}
// ~~ Connected (From REDUX)
diff --git a/extensions/cornerstone/src/components/OHIFCornerstoneViewportOverlay.css b/extensions/cornerstone/src/components/OHIFCornerstoneViewportOverlay.css
index 4ea733160..dca6f30d6 100644
--- a/extensions/cornerstone/src/components/OHIFCornerstoneViewportOverlay.css
+++ b/extensions/cornerstone/src/components/OHIFCornerstoneViewportOverlay.css
@@ -35,7 +35,7 @@
}
.OHIFCornerstoneViewportOverlay .bottom-left3 {
bottom: 110px;
- left: 100px;
+ left: -20px;
}
.OHIFCornerstoneViewportOverlay .bottom-right {
bottom: 20px;
diff --git a/extensions/cornerstone/src/components/OHIFCornerstoneViewportOverlay.js b/extensions/cornerstone/src/components/OHIFCornerstoneViewportOverlay.js
index 590040c5f..72a945625 100644
--- a/extensions/cornerstone/src/components/OHIFCornerstoneViewportOverlay.js
+++ b/extensions/cornerstone/src/components/OHIFCornerstoneViewportOverlay.js
@@ -18,19 +18,13 @@ import { Tooltip } from '@ohif/ui/src/components/tooltip';
import { OverlayTrigger } from '@ohif/ui/src/components/overlayTrigger';
const Button = styled.button`
- background-color: #3f51b5;
color: white;
- padding: 5px 15px;
+ padding: 2px 7px;
border-radius: 10px;
outline: 0;
- text-transform: lowercase;
- margin: 5px 5px;
+ text-transform: none;
+ margin: 2px 2px;
cursor: pointer;
- box-shadow: 0px 2px 2px lightgray;
- transition: ease background-color 250ms;
- &:hover {
- background-color: #283593;
- }
&:disabled {
cursor: default;
opacity: 0.9;
@@ -152,34 +146,48 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
const SRLabelsOn = SRLabels && SRLabels.length !== 0 ? true : false;
+ /**/
+
const getSRLabelsContent = SRLabels => {
if (Array.isArray(SRLabels)) {
const listedSRLabels = SRLabels.map((SRLabel, index) => {
+ const color = SRLabel.labels.color;
return (
-
- Designators
-
- {SRLabel.labels.labelCodingSchemeDesignator +
- ' : ' +
- SRLabel.labels.valueCodingSchemeDesignator}
-
-
- }
- >
-
-
-
-
+ SRLabel.labels.visible && (
+
+
+ {' '}
+ Coding scheme designators{' '}
+
+
+ {SRLabel.labels.labelCodingSchemeDesignator +
+ ' : ' +
+ SRLabel.labels.valueCodingSchemeDesignator}
+
+
+ }
+ >
+
+
+
+
+ )
);
});
diff --git a/extensions/lesion-tracker/src/components/MeasurementComparisonTable.js b/extensions/lesion-tracker/src/components/MeasurementComparisonTable.js
index 8218f2c55..2118895da 100644
--- a/extensions/lesion-tracker/src/components/MeasurementComparisonTable.js
+++ b/extensions/lesion-tracker/src/components/MeasurementComparisonTable.js
@@ -76,13 +76,13 @@ const additionalFindings = [
const currentCollections = [
{
- selectorAction: () => { },
+ selectorAction: () => {},
maxMeasurements: 3,
groupName: 'Measurements',
measurements: measurements,
},
{
- selectorAction: () => { },
+ selectorAction: () => {},
groupName: 'Additional Findings',
measurements: additionalFindings,
},
@@ -90,13 +90,13 @@ const currentCollections = [
const comparisonColletions = [
{
- selectorAction: () => { },
+ selectorAction: () => {},
maxMeasurements: 3,
groupName: 'Measurements',
measurements: measurements,
},
{
- selectorAction: () => { },
+ selectorAction: () => {},
groupName: 'Additional Findings',
measurements: additionalFindings,
},
@@ -128,7 +128,7 @@ const comparisonTimepoints = [
{
key: 'Comparison',
date: '15-Jun-18',
- }
+ },
];
const MeasurementComparisonTable = () => {
@@ -138,8 +138,8 @@ const MeasurementComparisonTable = () => {
timepoints={comparisonTimepoints}
overallWarnings={overallWarnings}
measurementCollection={comparisonCollections}
- onRelabelClick={() => { }}
- onEditDescriptionClick={() => { }}
+ onRelabelClick={() => {}}
+ onEditDescriptionClick={() => {}}
/>
diff --git a/platform/core/src/DICOMSR/SCOORD3D/parseSCOORD3D.js b/platform/core/src/DICOMSR/SCOORD3D/parseSCOORD3D.js
index 9d27a304e..ab5a44152 100644
--- a/platform/core/src/DICOMSR/SCOORD3D/parseSCOORD3D.js
+++ b/platform/core/src/DICOMSR/SCOORD3D/parseSCOORD3D.js
@@ -128,9 +128,9 @@ const checkIfCanAddMeasurementsToDisplaySet = (
const imageIds = images.map(i => i.getImageId());
const SOPInstanceUIDs = images.map(i => i.SOPInstanceUID);
imageDisplaySet.SRLabels = [];
+ const colors = new Map();
measurements.forEach(measurement => {
const { coords } = measurement;
-
coords.forEach((coord, index) => {
if (coord.ReferencedSOPSequence !== undefined) {
const imageIndex = SOPInstanceUIDs.findIndex(
@@ -143,19 +143,42 @@ const checkIfCanAddMeasurementsToDisplaySet = (
const imageMetadata = images[imageIndex].getData().metadata;
if (coord.GraphicType === 'TEXT') {
+ const key =
+ measurement.labels[index].label + measurement.labels[index].value;
+ let color = colors.get(key);
+ if (!color) {
+ // random dark color
+ color =
+ 'hsla(' + Math.floor(Math.random() * 360) + ', 70%, 30%, 1)';
+ colors.set(key, color);
+ }
+
+ measurement.labels[index].color = color;
+ measurement.isSRText = true;
+ measurement.labels[index].visible = true;
+
imageDisplaySet.SRLabels.push({
ReferencedSOPInstanceUID:
coord.ReferencedSOPSequence.ReferencedSOPInstanceUID,
labels: measurement.labels[index],
});
- }
- addMeasurement(
- measurement,
- imageId,
- imageMetadata,
- imageDisplaySet.displaySetInstanceUID
- );
+ if (index === 0) {
+ addMeasurement(
+ measurement,
+ imageId,
+ imageMetadata,
+ imageDisplaySet.displaySetInstanceUID
+ );
+ }
+ } else {
+ addMeasurement(
+ measurement,
+ imageId,
+ imageMetadata,
+ imageDisplaySet.displaySetInstanceUID
+ );
+ }
}
}
});
diff --git a/platform/core/src/DICOMSR/SCOORD3D/utils/addMeasurement.js b/platform/core/src/DICOMSR/SCOORD3D/utils/addMeasurement.js
index 42ad129f8..c8a69ff05 100644
--- a/platform/core/src/DICOMSR/SCOORD3D/utils/addMeasurement.js
+++ b/platform/core/src/DICOMSR/SCOORD3D/utils/addMeasurement.js
@@ -26,8 +26,10 @@ export default function addMeasurement(
const measurementData = {
TrackingUniqueIdentifier: measurement.TrackingUniqueIdentifier,
+ TrackingIdentifier: measurement.TrackingIdentifier,
renderableData: {},
labels: measurement.labels,
+ isSRText: measurement.isSRText,
};
measurement.coords.forEach(coord => {
diff --git a/platform/core/src/measurements/tools/dicomSRDisplayTool.js b/platform/core/src/measurements/tools/dicomSRDisplayTool.js
index ffed8efda..77da93a43 100644
--- a/platform/core/src/measurements/tools/dicomSRDisplayTool.js
+++ b/platform/core/src/measurements/tools/dicomSRDisplayTool.js
@@ -6,7 +6,8 @@ export const dicomSRDisplayTool = {
options: {
measurementTable: {
displayFunction: data => {
- return `(SR) ${data.lesionNamingNumber ||
+ return `(SR) ${data.TrackingIdentifier ||
+ data.lesionNamingNumber ||
data.measurementNumber ||
data.text ||
''}`;
diff --git a/platform/ui/src/components/measurementTable/MeasurementTableItem.js b/platform/ui/src/components/measurementTable/MeasurementTableItem.js
index 2e7038b17..33c7849c9 100644
--- a/platform/ui/src/components/measurementTable/MeasurementTableItem.js
+++ b/platform/ui/src/components/measurementTable/MeasurementTableItem.js
@@ -9,6 +9,14 @@ import { TableListItem } from './../tableList/TableListItem.js';
import './MeasurementTableItem.styl';
+const ColoredCircle = ({ color }) => {
+ return
;
+};
+
+ColoredCircle.propTypes = {
+ color: PropTypes.string.isRequired,
+};
+
class MeasurementTableItem extends Component {
static propTypes = {
measurementData: PropTypes.object.isRequired,
@@ -21,6 +29,14 @@ class MeasurementTableItem extends Component {
t: PropTypes.func,
};
+ constructor(props) {
+ super(props);
+ this.state = {
+ collapsed: true,
+ visible: true,
+ };
+ }
+
render() {
const {
warningTitle = '',
@@ -93,27 +109,113 @@ class MeasurementTableItem extends Component {
actionButtons.push(deleteButton);
}
- return (
-
-
-
- {this.props.t(this.props.measurementData.label, {
- keySeparator: '>',
- nsSeparator: '|',
+ if (
+ this.props.measurementData.isSRText === true &&
+ this.props.measurementData.labels &&
+ this.props.measurementData.labels.length > 0
+ ) {
+ return (
+
+
+
+
+ {this.props.t(this.props.measurementData.label, {
+ keySeparator: '>',
+ nsSeparator: '|',
+ })}
+
+
+
+
{this.getDataDisplayText()}
+
{
+ this.props.measurementData.labels.forEach(label => {
+ label.visible = !this.state.visible;
+ });
+
+ this.setState({
+ visible: !this.state.visible,
+ });
+ }}
+ />
+ {
+ this.setState({
+ collapsed: !this.state.collapsed,
+ });
+ }}
+ />
+
+
+ {this.state.collapsed &&
+ this.props.measurementData.labels.map((SRLabel, index) => {
+ return (
+ }
+ itemMetaClass="item-color-section"
+ onItemClick={this.onItemClick}
+ >
+
+
+ {SRLabel.label + ' : ' + SRLabel.value}
+ {
+ SRLabel.visible = !SRLabel.visible;
+ }}
+ />
+
+
+
+ );
})}
+
+ );
+ } else {
+ return (
+
+
+
+ {this.props.t(this.props.measurementData.label, {
+ keySeparator: '>',
+ nsSeparator: '|',
+ })}
+
+
{this.getDataDisplayText()}
+ {!this.props.measurementData.isReadOnly && (
+
{actionButtons}
+ )}
- {this.getDataDisplayText()}
- {!this.props.measurementData.isReadOnly && (
- {actionButtons}
- )}
-
-
- );
+
+ );
+ }
};
onItemClick = event => {
diff --git a/platform/ui/src/components/measurementTable/MeasurementTableItem.styl b/platform/ui/src/components/measurementTable/MeasurementTableItem.styl
index eb3ba7044..0293418b5 100644
--- a/platform/ui/src/components/measurementTable/MeasurementTableItem.styl
+++ b/platform/ui/src/components/measurementTable/MeasurementTableItem.styl
@@ -1,4 +1,16 @@
.measurementItem
+ .item-color-section
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+
+ .item-color
+ margin-top: 8px;
+ border-radius: 100%;
+ width: 20px;
+ height: 20px;
+
.rowActions
margin-left: -1px;
background-color: var(--ui-gray-darker)
@@ -63,3 +75,16 @@
width: 22px;
height: 20px;
pointer-events: inherit;
+
+.icons
+ display: flex;
+ align-items: center;
+ border-radius: 5px;
+
+.icons .eye-icon
+ margin-left: 100px;
+ margin-right: -5px;
+.icons .angle-double-down
+.icons .angle-double-up
+ margin-left: 15px;
+ margin-right: -5px;
diff --git a/platform/ui/src/components/tableList/TableListItem.js b/platform/ui/src/components/tableList/TableListItem.js
index b3b64d6a1..6ddc39516 100644
--- a/platform/ui/src/components/tableList/TableListItem.js
+++ b/platform/ui/src/components/tableList/TableListItem.js
@@ -12,16 +12,13 @@ export class TableListItem extends Component {
itemIndex: PropTypes.number,
itemMeta: PropTypes.node,
itemMetaClass: PropTypes.string,
- itemKey: PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.number,
- ]),
+ itemKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
onItemClick: PropTypes.func.isRequired,
};
static defaultProps = {
itemMeta: null,
- itemMetaClass: ''
+ itemMetaClass: '',
};
render() {
diff --git a/platform/viewer/src/appExtensions/MeasurementsPanel/ConnectedMeasurementTable.js b/platform/viewer/src/appExtensions/MeasurementsPanel/ConnectedMeasurementTable.js
index 13c0068a1..feae52669 100644
--- a/platform/viewer/src/appExtensions/MeasurementsPanel/ConnectedMeasurementTable.js
+++ b/platform/viewer/src/appExtensions/MeasurementsPanel/ConnectedMeasurementTable.js
@@ -122,6 +122,7 @@ function convertMeasurementsToTableData(toolCollections, timepoints) {
Object.keys(toolCollections).forEach(toolId => {
const toolMeasurements = toolCollections[toolId];
+
const tool = tools.find(tool => tool.id === toolId);
const { displayFunction } = tool.options.measurementTable;
@@ -131,12 +132,13 @@ function convertMeasurementsToTableData(toolCollections, timepoints) {
Object.keys(groupedMeasurements).forEach(groupedMeasurementsIndex => {
const measurementNumberList =
groupedMeasurements[groupedMeasurementsIndex];
+
const measurementData = measurementNumberList[0];
const {
measurementNumber,
lesionNamingNumber,
toolType,
- isReadOnly
+ isReadOnly,
} = measurementData;
const measurementId = measurementData._id;
@@ -150,6 +152,8 @@ function convertMeasurementsToTableData(toolCollections, timepoints) {
const tableMeasurement = {
itemNumber: lesionNamingNumber,
label: getMeasurementText(measurementData),
+ labels: measurementData.labels,
+ isSRText: measurementData.isSRText,
measurementId,
measurementNumber,
lesionNamingNumber,
diff --git a/platform/viewer/src/connectedComponents/Viewer.js b/platform/viewer/src/connectedComponents/Viewer.js
index bdd0e6238..41cfaf5e3 100644
--- a/platform/viewer/src/connectedComponents/Viewer.js
+++ b/platform/viewer/src/connectedComponents/Viewer.js
@@ -661,10 +661,9 @@ const _mapStudiesToThumbnails = function(studies, activeDisplaySetInstanceUID) {
let altImageText;
if (displaySet.Modality && displaySet.Modality === 'SEG') {
- // TODO: We want to replace this with a thumbnail showing
- // the segmentation map on the image, but this is easier
- // and better than what we have right now.
altImageText = 'SEG';
+ } else if (displaySet.Modality && displaySet.Modality === 'SR') {
+ altImageText = 'SR';
} else if (displaySet.images && displaySet.images.length) {
const imageIndex = Math.floor(displaySet.images.length / 2);
imageId = displaySet.images[imageIndex].getImageId();