Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe9551b9b1 | ||
|
|
ef60156a47 | ||
|
|
850de2903a | ||
|
|
f26ed5539b | ||
|
|
21aeaa63c7 | ||
|
|
2ac0d3f017 | ||
|
|
efdbe8e7b4 | ||
|
|
67b70eaa98 | ||
|
|
5150ed9427 | ||
|
|
1bcb0acf9f | ||
|
|
5d6cf2a609 | ||
|
|
9f813e0ea0 | ||
|
|
49de44ba34 | ||
|
|
b04e186274 | ||
|
|
c59d66412f | ||
|
|
f8b4ccbb59 | ||
|
|
5426773ffc | ||
|
|
a507a00f59 | ||
|
|
cedeb756c0 | ||
|
|
64385485b6 | ||
|
|
32828d9a6e | ||
|
|
b94d4782d1 | ||
|
|
36b47ce3a3 | ||
|
|
fe57c00577 | ||
|
|
21a3bc2ded | ||
|
|
b6b09f22fc |
No files matched your search
@@ -3,6 +3,54 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.12.13](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.12...@ohif/extension-cornerstone@2.12.13) (2022-06-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.12.12](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.11...@ohif/extension-cornerstone@2.12.12) (2022-06-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.12.11](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.10...@ohif/extension-cornerstone@2.12.11) (2022-06-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.12.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.9...@ohif/extension-cornerstone@2.12.10) (2022-04-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.12.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.8...@ohif/extension-cornerstone@2.12.9) (2022-03-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.12.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.7...@ohif/extension-cornerstone@2.12.8) (2022-03-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.12.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.6...@ohif/extension-cornerstone@2.12.7) (2022-02-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "2.12.7",
|
||||
"version": "2.12.13",
|
||||
"description": "OHIF extension for Cornerstone",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -36,7 +36,7 @@
|
||||
"cornerstone-math": "^0.1.9",
|
||||
"cornerstone-tools": "^6.0.6",
|
||||
"cornerstone-wado-image-loader": "^4.1.0",
|
||||
"dcmjs": "0.19.4",
|
||||
"dcmjs": "0.19.9",
|
||||
"dicom-parser": "^1.8.11",
|
||||
"hammerjs": "^2.0.8",
|
||||
"prop-types": "^15.6.2",
|
||||
@@ -44,7 +44,8 @@
|
||||
"react-dom": "^16.8.6",
|
||||
"react-redux": "^6.0.0",
|
||||
"react-resize-detector": "^3.4.0",
|
||||
"redux": "^4.0.1"
|
||||
"redux": "^4.0.1",
|
||||
"styled-components": "^5.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
|
||||
@@ -237,11 +237,21 @@ 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) {
|
||||
filteredSRLabels = displaySet.SRLabels.filter(
|
||||
SRLabel =>
|
||||
SRLabel.ReferencedSOPInstanceUID === displaySet.SOPInstanceUID
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<OHIFCornerstoneViewportOverlay
|
||||
{...props}
|
||||
inconsistencyWarnings={inconsistencyWarnings}
|
||||
SRLabels={filteredSRLabels}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -254,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)
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
bottom: 140px;
|
||||
left: 20px;
|
||||
}
|
||||
.OHIFCornerstoneViewportOverlay .bottom-left3 {
|
||||
bottom: 110px;
|
||||
left: -20px;
|
||||
}
|
||||
.OHIFCornerstoneViewportOverlay .bottom-right {
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { PureComponent } from 'react';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import PropTypes from 'prop-types';
|
||||
import cornerstone from 'cornerstone-core';
|
||||
import './OHIFCornerstoneViewportOverlay.css';
|
||||
@@ -9,13 +10,27 @@ import {
|
||||
formatDICOMDate,
|
||||
formatDICOMTime,
|
||||
formatPN,
|
||||
getCompression
|
||||
getCompression,
|
||||
} from '../utils/formatStudy';
|
||||
import classNames from 'classnames';
|
||||
import { Icon } from '@ohif/ui/src/elements/Icon';
|
||||
import { Tooltip } from '@ohif/ui/src/components/tooltip';
|
||||
import { OverlayTrigger } from '@ohif/ui/src/components/overlayTrigger';
|
||||
|
||||
const Button = styled.button`
|
||||
color: white;
|
||||
padding: 2px 7px;
|
||||
border-radius: 10px;
|
||||
outline: 0;
|
||||
text-transform: none;
|
||||
margin: 2px 2px;
|
||||
cursor: pointer;
|
||||
&:disabled {
|
||||
cursor: default;
|
||||
opacity: 0.9;
|
||||
}
|
||||
`;
|
||||
|
||||
class OHIFCornerstoneViewportOverlay extends PureComponent {
|
||||
static propTypes = {
|
||||
scale: PropTypes.number.isRequired,
|
||||
@@ -30,11 +45,19 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
|
||||
imageId: PropTypes.string.isRequired,
|
||||
imageIndex: PropTypes.number.isRequired,
|
||||
stackSize: PropTypes.number.isRequired,
|
||||
inconsistencyWarnings: PropTypes.array.isRequired
|
||||
inconsistencyWarnings: PropTypes.array,
|
||||
SRLabels: PropTypes.array,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { imageId, scale, windowWidth, windowCenter, inconsistencyWarnings } = this.props;
|
||||
const {
|
||||
imageId,
|
||||
scale,
|
||||
windowWidth,
|
||||
windowCenter,
|
||||
inconsistencyWarnings,
|
||||
SRLabels,
|
||||
} = this.props;
|
||||
|
||||
if (!imageId) {
|
||||
return null;
|
||||
@@ -72,8 +95,11 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
|
||||
|
||||
const { imageIndex, stackSize } = this.props;
|
||||
|
||||
const inconsistencyWarningsOn = inconsistencyWarnings && inconsistencyWarnings.length !== 0 ? true : false;
|
||||
const getWarningContent = (warningList) => {
|
||||
const inconsistencyWarningsOn =
|
||||
inconsistencyWarnings && inconsistencyWarnings.length !== 0
|
||||
? true
|
||||
: false;
|
||||
const getWarningContent = warningList => {
|
||||
if (Array.isArray(warningList)) {
|
||||
const listedWarnings = warningList.map((warn, index) => {
|
||||
return <li key={index}>{warn}</li>;
|
||||
@@ -86,33 +112,100 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
|
||||
};
|
||||
|
||||
const getWarningInfo = (seriesNumber, inconsistencyWarnings) => {
|
||||
return(
|
||||
return (
|
||||
<React.Fragment>
|
||||
{inconsistencyWarnings.length != 0 ? (
|
||||
<OverlayTrigger
|
||||
key={seriesNumber}
|
||||
placement="left"
|
||||
overlay={
|
||||
<Tooltip
|
||||
placement="left"
|
||||
className="in tooltip-warning"
|
||||
id="tooltip-left"
|
||||
>
|
||||
<div className="warningTitle">Series Inconsistencies</div>
|
||||
<div className="warningContent">{getWarningContent(inconsistencyWarnings)}</div>
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
<div className={classNames('warning')}>
|
||||
<span className="warning-icon">
|
||||
<Icon name="exclamation-triangle" />
|
||||
</span>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
) : (
|
||||
<React.Fragment></React.Fragment>
|
||||
{inconsistencyWarnings.length != 0 ? (
|
||||
<OverlayTrigger
|
||||
key={seriesNumber}
|
||||
placement="left"
|
||||
overlay={
|
||||
<Tooltip
|
||||
placement="left"
|
||||
className="in tooltip-warning"
|
||||
id="tooltip-left"
|
||||
>
|
||||
<div className="warningTitle">Series Inconsistencies</div>
|
||||
<div className="warningContent">
|
||||
{getWarningContent(inconsistencyWarnings)}
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
<div className={classNames('warning')}>
|
||||
<span className="warning-icon">
|
||||
<Icon name="exclamation-triangle" />
|
||||
</span>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
) : (
|
||||
<React.Fragment></React.Fragment>
|
||||
)}
|
||||
</React.Fragment>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
SRLabel.labels.visible && (
|
||||
<OverlayTrigger
|
||||
key={index}
|
||||
placement="top"
|
||||
overlay={
|
||||
<Tooltip
|
||||
placement="top"
|
||||
className="in tooltip-warning"
|
||||
id="tooltip-top"
|
||||
>
|
||||
<div className="warningTitle">
|
||||
{' '}
|
||||
Coding scheme designators{' '}
|
||||
</div>
|
||||
<div className="warningContent">
|
||||
{SRLabel.labels.labelCodingSchemeDesignator +
|
||||
' : ' +
|
||||
SRLabel.labels.valueCodingSchemeDesignator}
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
<div style={{ display: 'inline-block' }}>
|
||||
<Button
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
}}
|
||||
disabled={true}
|
||||
key={index}
|
||||
>
|
||||
{SRLabel.labels.label + ' : ' + SRLabel.labels.value}
|
||||
</Button>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return <ol>{listedSRLabels}</ol>;
|
||||
} else {
|
||||
return <React.Fragment></React.Fragment>;
|
||||
}
|
||||
};
|
||||
|
||||
const getSRLabelsInfo = SRLabels => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{SRLabels.length != 0 ? (
|
||||
getSRLabelsContent(SRLabels)
|
||||
) : (
|
||||
<React.Fragment></React.Fragment>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -134,7 +227,14 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
|
||||
<div className="compressionIndicator">{compression}</div>
|
||||
</div>
|
||||
<div className="bottom-left2 warning">
|
||||
<div>{inconsistencyWarningsOn ? getWarningInfo(seriesNumber, inconsistencyWarnings) : ''}</div>
|
||||
<div>
|
||||
{inconsistencyWarningsOn
|
||||
? getWarningInfo(seriesNumber, inconsistencyWarnings)
|
||||
: ''}
|
||||
</div>
|
||||
</div>
|
||||
<div className="bottom-left3 warning">
|
||||
<div>{SRLabelsOn ? getSRLabelsInfo(SRLabels) : ''}</div>
|
||||
</div>
|
||||
<div className="bottom-left overlay-element">
|
||||
<div>{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}</div>
|
||||
|
||||
@@ -97,6 +97,8 @@ export default class DICOMSRDisplayTool extends BaseTool {
|
||||
const renderableDataForGraphicType = renderableData[GraphicType];
|
||||
|
||||
switch (GraphicType) {
|
||||
case SCOORD_TYPES.TEXT:
|
||||
break;
|
||||
case SCOORD_TYPES.POINT:
|
||||
this.renderPoint(renderableDataForGraphicType, eventData, options);
|
||||
break;
|
||||
@@ -167,20 +169,22 @@ export default class DICOMSRDisplayTool extends BaseTool {
|
||||
return data.handles.textBox.anchorPoints;
|
||||
}
|
||||
|
||||
draw(context, context => {
|
||||
drawLinkedTextBox(
|
||||
context,
|
||||
element,
|
||||
data.handles.textBox,
|
||||
text,
|
||||
data.handles,
|
||||
textBoxAnchorPoints,
|
||||
color,
|
||||
lineWidth,
|
||||
0,
|
||||
true
|
||||
);
|
||||
});
|
||||
if (data.handles.textBox.anchorPoints.length !== 0) {
|
||||
draw(context, context => {
|
||||
drawLinkedTextBox(
|
||||
context,
|
||||
element,
|
||||
data.handles.textBox,
|
||||
text,
|
||||
data.handles,
|
||||
textBoxAnchorPoints,
|
||||
color,
|
||||
lineWidth,
|
||||
0,
|
||||
true
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TOOD -> text boxes may overlap with other annotations at the moment.
|
||||
@@ -230,7 +234,6 @@ export default class DICOMSRDisplayTool extends BaseTool {
|
||||
const { element, image } = eventData;
|
||||
const { rows, columns } = image;
|
||||
const context = getNewContext(eventData.canvasContext.canvas);
|
||||
|
||||
const { color, lineWidth } = options;
|
||||
|
||||
// Find a suitable length for the image size.
|
||||
@@ -332,6 +335,8 @@ function _getTextBoxAnchorPointsForRenderableData(renderableData, eventData) {
|
||||
const renderableDataForGraphicType = renderableData[GraphicType];
|
||||
|
||||
switch (GraphicType) {
|
||||
case SCOORD_TYPES.TEXT:
|
||||
break;
|
||||
case SCOORD_TYPES.POINT:
|
||||
renderableDataForGraphicType.forEach(points => {
|
||||
anchorPoints = [...anchorPoints, ...points];
|
||||
@@ -405,7 +410,7 @@ function _getBoundingBoxFromAnchorPoints(anchorPoints) {
|
||||
minX = x;
|
||||
}
|
||||
|
||||
if (y > maxX) {
|
||||
if (y > maxY) {
|
||||
maxY = y;
|
||||
} else if (y < minY) {
|
||||
minY = y;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export default {
|
||||
TEXT: 'TEXT',
|
||||
POINT: 'POINT',
|
||||
MULTIPOINT: 'MULTIPOINT',
|
||||
POLYLINE: 'POLYLINE',
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.3.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.3.2...@ohif/extension-debugging@0.3.3) (2022-06-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-debugging
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.3.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.3.1...@ohif/extension-debugging@0.3.2) (2022-03-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-debugging
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-debugging",
|
||||
"version": "0.3.2",
|
||||
"version": "0.3.3",
|
||||
"description": "OHIF extension for debugging.",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -89,10 +89,10 @@ const DubugReportModal = ({
|
||||
|
||||
Object.keys(viewportSpecificData).forEach(viewportIndex => {
|
||||
const displaySet = viewportSpecificData[viewportIndex];
|
||||
const [
|
||||
referencedDisplaySetsRef,
|
||||
referencedDisplaySetsCount,
|
||||
] = _getReferencedSeriesInstanceUIDsString(displaySet, 'SEG');
|
||||
const [referencedDisplaySetsRef] = _getReferencedSeriesInstanceUIDsString(
|
||||
displaySet,
|
||||
'SEG'
|
||||
);
|
||||
|
||||
const [row, column] = _viewportIndexToViewportPosition(
|
||||
viewportIndex,
|
||||
@@ -106,10 +106,27 @@ const DubugReportModal = ({
|
||||
|
||||
Object.keys(viewportSpecificData).forEach(viewportIndex => {
|
||||
const displaySet = viewportSpecificData[viewportIndex];
|
||||
const [
|
||||
referencedDisplaySetsRef,
|
||||
referencedDisplaySetsCount,
|
||||
] = _getReferencedSeriesInstanceUIDsString(displaySet, 'RTSTRUCT');
|
||||
const [referencedDisplaySetsRef] = _getReferencedSeriesInstanceUIDsString(
|
||||
displaySet,
|
||||
'RTSTRUCT'
|
||||
);
|
||||
|
||||
const [row, column] = _viewportIndexToViewportPosition(
|
||||
viewportIndex,
|
||||
numColumns
|
||||
);
|
||||
|
||||
body += `[${row},${column}]\t${referencedDisplaySetsRef}\n`;
|
||||
});
|
||||
|
||||
body += '== ReferencedSRSeriesInstanceUIDs ==\n';
|
||||
|
||||
Object.keys(viewportSpecificData).forEach(viewportIndex => {
|
||||
const displaySet = viewportSpecificData[viewportIndex];
|
||||
const [referencedDisplaySetsRef] = _getReferencedSeriesInstanceUIDsString(
|
||||
displaySet,
|
||||
'SR'
|
||||
);
|
||||
|
||||
const [row, column] = _viewportIndexToViewportPosition(
|
||||
viewportIndex,
|
||||
@@ -261,11 +278,15 @@ const getLayout = viewports => {
|
||||
<tr>
|
||||
<th>ReferencedSEGSeriesInstanceUIDs</th>
|
||||
</tr>
|
||||
{getReferencedSEGSeriesInstanceUIDsPerRow(viewports)}
|
||||
{getReferencedSeriesInstanceUIDsPerRow(viewports, 'SEG')}
|
||||
<tr>
|
||||
<th>ReferencedRTSTRUCTSeriesInstanceUIDs</th>
|
||||
</tr>
|
||||
{getReferencedRTSTRUCTSeriesInstanceUIDsPerRow(viewports)}
|
||||
{getReferencedSeriesInstanceUIDsPerRow(viewports, 'RTSTRUCT')}
|
||||
<tr>
|
||||
<th>ReferencedSRSeriesInstanceUIDs</th>
|
||||
</tr>
|
||||
{getReferencedSeriesInstanceUIDsPerRow(viewports, 'SR')}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
@@ -351,7 +372,7 @@ const _getReferencedSeriesInstanceUIDsString = (displaySet, Modality) => {
|
||||
return [referencedDisplaySetsRef, referencedDisplaySetsCount];
|
||||
};
|
||||
|
||||
const getReferencedSEGSeriesInstanceUIDsPerRow = viewports => {
|
||||
const getReferencedSeriesInstanceUIDsPerRow = (viewports, Modality) => {
|
||||
const { viewportSpecificData, numColumns } = viewports;
|
||||
|
||||
// NOTE viewportSpecificData is actually an object with numerical keys.
|
||||
@@ -360,43 +381,7 @@ const getReferencedSEGSeriesInstanceUIDsPerRow = viewports => {
|
||||
const [
|
||||
referencedDisplaySetsRef,
|
||||
referencedDisplaySetsCount,
|
||||
] = _getReferencedSeriesInstanceUIDsString(displaySet, 'SEG');
|
||||
|
||||
const [row, column] = _viewportIndexToViewportPosition(
|
||||
viewportIndex,
|
||||
numColumns
|
||||
);
|
||||
|
||||
if (referencedDisplaySetsCount > 1) {
|
||||
return (
|
||||
<tr>
|
||||
<td>{`[${row},${column}]`}</td>
|
||||
<td className="debug-overflowText-border">
|
||||
{referencedDisplaySetsRef}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<tr>
|
||||
<td>{`[${row},${column}]`}</td>
|
||||
<td className="debug-overflowText">{referencedDisplaySetsRef}</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const getReferencedRTSTRUCTSeriesInstanceUIDsPerRow = viewports => {
|
||||
const { viewportSpecificData, numColumns } = viewports;
|
||||
|
||||
// NOTE viewportSpecificData is actually an object with numerical keys.
|
||||
return Object.keys(viewportSpecificData).map(viewportIndex => {
|
||||
const displaySet = viewportSpecificData[viewportIndex];
|
||||
const [
|
||||
referencedDisplaySetsRef,
|
||||
referencedDisplaySetsCount,
|
||||
] = _getReferencedSeriesInstanceUIDsString(displaySet, 'RTSTRUCT');
|
||||
] = _getReferencedSeriesInstanceUIDsString(displaySet, Modality);
|
||||
|
||||
const [row, column] = _viewportIndexToViewportPosition(
|
||||
viewportIndex,
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.3.22](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.21...@ohif/extension-dicom-html@1.3.22) (2022-06-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.3.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.20...@ohif/extension-dicom-html@1.3.21) (2022-04-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.3.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.19...@ohif/extension-dicom-html@1.3.20) (2022-03-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.3.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.18...@ohif/extension-dicom-html@1.3.19) (2022-03-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.3.18](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.17...@ohif/extension-dicom-html@1.3.18) (2022-02-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-html",
|
||||
"version": "1.3.18",
|
||||
"version": "1.3.22",
|
||||
"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.19.4",
|
||||
"dcmjs": "0.19.9",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MODULE_TYPES, utils } from '@ohif/core';
|
||||
import { MODULE_TYPES, utils, metadata } from '@ohif/core';
|
||||
|
||||
// TODO: Should probably use dcmjs for this
|
||||
const SOP_CLASS_UIDS = {
|
||||
@@ -10,7 +10,7 @@ const SOP_CLASS_UIDS = {
|
||||
MAMMOGRAPHY_CAD_SR: '1.2.840.10008.5.1.4.1.1.88.50',
|
||||
CHEST_CAD_SR: '1.2.840.10008.5.1.4.1.1.88.65',
|
||||
X_RAY_RADIATION_DOSE_SR: '1.2.840.10008.5.1.4.1.1.88.67',
|
||||
ACQUISITION_CONTEXT_SR_STORAGE: '1.2.840.10008.5.1.4.1.1.88.71'
|
||||
ACQUISITION_CONTEXT_SR_STORAGE: '1.2.840.10008.5.1.4.1.1.88.71',
|
||||
};
|
||||
|
||||
const sopClassUIDs = Object.values(SOP_CLASS_UIDS);
|
||||
@@ -32,7 +32,7 @@ const OHIFDicomHtmlSopClassHandler = {
|
||||
SeriesTime,
|
||||
} = metadata;
|
||||
|
||||
return {
|
||||
const srDisplaySet = {
|
||||
plugin: 'html',
|
||||
Modality: 'SR',
|
||||
displaySetInstanceUID: utils.guid(),
|
||||
@@ -49,7 +49,15 @@ const OHIFDicomHtmlSopClassHandler = {
|
||||
authorizationHeaders,
|
||||
sopClassUids: sopClassUIDs,
|
||||
images: series._instances,
|
||||
isDerived: true,
|
||||
referencedDisplaySets: [],
|
||||
};
|
||||
|
||||
srDisplaySet.getSourceDisplaySet = function() {
|
||||
return srDisplaySet.referencedDisplaySets;
|
||||
};
|
||||
|
||||
return srDisplaySet;
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.7.12](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.11...@ohif/extension-dicom-rt@0.7.12) (2022-08-31)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.7.11](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.10...@ohif/extension-dicom-rt@0.7.11) (2022-04-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.7.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.9...@ohif/extension-dicom-rt@0.7.10) (2022-03-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.7.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.8...@ohif/extension-dicom-rt@0.7.9) (2022-03-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.7.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.7...@ohif/extension-dicom-rt@0.7.8) (2022-02-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-rt",
|
||||
"version": "0.7.8",
|
||||
"version": "0.7.12",
|
||||
"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.6.1",
|
||||
"cornerstone-tools": "^6.0.6",
|
||||
"dcmjs": "0.19.4",
|
||||
"dcmjs": "0.19.9",
|
||||
"gl-matrix": "^3.3.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.8.6",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cornerstoneTools from 'cornerstone-tools';
|
||||
import cornerstone from 'cornerstone-core';
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.7.12](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.11...@ohif/extension-dicom-segmentation@0.7.12) (2022-08-31)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.7.11](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.10...@ohif/extension-dicom-segmentation@0.7.11) (2022-04-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.7.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.9...@ohif/extension-dicom-segmentation@0.7.10) (2022-03-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.7.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.8...@ohif/extension-dicom-segmentation@0.7.9) (2022-03-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.7.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.7...@ohif/extension-dicom-segmentation@0.7.8) (2022-02-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-segmentation",
|
||||
"version": "0.7.8",
|
||||
"version": "0.7.12",
|
||||
"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.6.1",
|
||||
"cornerstone-tools": "^6.0.6",
|
||||
"dcmjs": "0.19.4",
|
||||
"dcmjs": "0.19.9",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
|
||||
+3
-21
@@ -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';
|
||||
@@ -224,33 +224,15 @@ const SegmentationPanel = ({
|
||||
)
|
||||
);
|
||||
};
|
||||
}, [
|
||||
activeIndex,
|
||||
updateSegmentationComboBox,
|
||||
viewports,
|
||||
]);
|
||||
}, [activeIndex, viewports]);
|
||||
|
||||
const updateSegmentationComboBox = e => {
|
||||
const index = e.detail.activatedLabelmapIndex;
|
||||
if (index !== -1) {
|
||||
setState(state => ({ ...state, selectedSegmentation: index }));
|
||||
} else {
|
||||
cleanSegmentationComboBox();
|
||||
}
|
||||
};
|
||||
|
||||
const cleanSegmentationComboBox = () => {
|
||||
setState(state => ({
|
||||
...state,
|
||||
segmentsHidden: [],
|
||||
segmentNumbers: [],
|
||||
labelMapList: [],
|
||||
segmentList: [],
|
||||
isDisabled: true,
|
||||
selectedSegmentation: -1,
|
||||
}));
|
||||
};
|
||||
|
||||
const refreshSegmentations = () => {
|
||||
const activeViewport = getActiveViewport();
|
||||
const isDisabled = !activeViewport || !activeViewport.StudyInstanceUID;
|
||||
@@ -709,7 +691,7 @@ const SegmentationPanel = ({
|
||||
count={state.segmentList.length}
|
||||
isVisible={
|
||||
state.segmentsHidden.filter(isHidden => isHidden === true).length <
|
||||
state.segmentNumbers.length
|
||||
state.segmentNumbers.length && state.segmentNumbers.length > 0
|
||||
}
|
||||
onVisibilityChange={onVisibilityChangeHandler}
|
||||
>
|
||||
|
||||
@@ -47,14 +47,23 @@ export default async function setActiveLabelmap(
|
||||
return labelmapIndex;
|
||||
}
|
||||
|
||||
if (!displaySet.isLoaded) {
|
||||
if (!displaySet.isLoaded && !displaySet.loadError) {
|
||||
try {
|
||||
await displaySet.load(referencedDisplaySet, studies);
|
||||
} catch (error) {
|
||||
displaySet.isLoaded = false;
|
||||
displaySet.loadError = true;
|
||||
displaySet.segLoadErrorMessagge = error.message;
|
||||
onDisplaySetLoadFailure(error);
|
||||
|
||||
/*
|
||||
* TODO: Improve the way we notify parts of the app
|
||||
* that depends on derived display sets to be loaded.
|
||||
* (Implement pubsub for better tracking of derived display sets)
|
||||
*/
|
||||
const event = new CustomEvent('segmentationLoadingError');
|
||||
document.dispatchEvent(event);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.2.23](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.22...@ohif/extension-dicom-tag-browser@0.2.23) (2022-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.2.22](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.21...@ohif/extension-dicom-tag-browser@0.2.22) (2022-04-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.2.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.20...@ohif/extension-dicom-tag-browser@0.2.21) (2022-03-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.2.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.19...@ohif/extension-dicom-tag-browser@0.2.20) (2022-03-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.2.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.18...@ohif/extension-dicom-tag-browser@0.2.19) (2022-02-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-tag-browser",
|
||||
"version": "0.2.19",
|
||||
"version": "0.2.23",
|
||||
"description": "OHIF extension for checking DICOM headers.",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -28,7 +28,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "^2.6.0",
|
||||
"dcmjs": "0.19.4",
|
||||
"dcmjs": "0.19.9",
|
||||
"react": "^16.8.6"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -59,7 +59,7 @@ const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
|
||||
let metadata;
|
||||
const isImageStack =
|
||||
activeDisplaySet instanceof ImageSet &&
|
||||
activeDisplaySet.isModalitySupported === true;
|
||||
activeDisplaySet.isSOPClassUIDSupported === true;
|
||||
|
||||
let instanceList;
|
||||
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.2.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-lesion-tracker@0.2.1...@ohif/extension-lesion-tracker@0.2.2) (2022-06-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-lesion-tracker
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.2.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-lesion-tracker@0.2.0...@ohif/extension-lesion-tracker@0.2.1) (2020-09-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-lesion-tracker
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-lesion-tracker",
|
||||
"version": "0.2.1",
|
||||
"version": "0.2.2",
|
||||
"description": "OHIF extension for Lesion Tracker",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -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={() => {}}
|
||||
/>
|
||||
<div className="generate-report">
|
||||
<button className="btn btn-primary">Generate Report</button>
|
||||
|
||||
@@ -3,6 +3,94 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.12.29](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.28...@ohif/extension-vtk@1.12.29) (2022-08-31)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.12.28](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.27...@ohif/extension-vtk@1.12.28) (2022-08-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.12.27](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.26...@ohif/extension-vtk@1.12.27) (2022-06-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.12.26](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.25...@ohif/extension-vtk@1.12.26) (2022-06-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.12.25](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.24...@ohif/extension-vtk@1.12.25) (2022-06-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.12.24](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.23...@ohif/extension-vtk@1.12.24) (2022-06-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.12.23](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.22...@ohif/extension-vtk@1.12.23) (2022-04-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.12.22](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.21...@ohif/extension-vtk@1.12.22) (2022-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.12.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.20...@ohif/extension-vtk@1.12.21) (2022-04-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.12.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.19...@ohif/extension-vtk@1.12.20) (2022-03-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.12.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.18...@ohif/extension-vtk@1.12.19) (2022-03-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.12.18](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.17...@ohif/extension-vtk@1.12.18) (2022-03-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-vtk",
|
||||
"version": "1.12.18",
|
||||
"version": "1.12.29",
|
||||
"description": "OHIF extension for VTK.js",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -35,7 +35,7 @@
|
||||
"cornerstone-core": "^2.6.1",
|
||||
"cornerstone-tools": "^6.0.6",
|
||||
"cornerstone-wado-image-loader": "^4.1.0",
|
||||
"dcmjs": "0.19.4",
|
||||
"dcmjs": "0.19.9",
|
||||
"dicom-parser": "^1.8.11",
|
||||
"i18next": "^17.0.3",
|
||||
"i18next-browser-languagedetector": "^3.0.1",
|
||||
@@ -53,8 +53,8 @@
|
||||
"react-vtkjs-viewport": "^0.14.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ohif/core": "^2.16.13",
|
||||
"@ohif/ui": "^1.10.7",
|
||||
"@ohif/core": "^2.16.24",
|
||||
"@ohif/ui": "^1.10.10",
|
||||
"cornerstone-tools": "^6.0.6",
|
||||
"cornerstone-wado-image-loader": "^4.1.0",
|
||||
"dicom-parser": "^1.8.11",
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
"shader-loader": "^1.3.1",
|
||||
"start-server-and-test": "^1.10.0",
|
||||
"style-loader": "^1.0.0",
|
||||
"styled-components": "^5.3.5",
|
||||
"stylelint": "^10.1.0",
|
||||
"stylelint-config-recommended": "^2.2.0",
|
||||
"stylus": "^0.54.5",
|
||||
|
||||
@@ -3,6 +3,97 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.16.24](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.23...@ohif/core@2.16.24) (2022-08-31)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.16.23](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.22...@ohif/core@2.16.23) (2022-08-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.16.22](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.21...@ohif/core@2.16.22) (2022-06-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.16.21](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.20...@ohif/core@2.16.21) (2022-06-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.16.20](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.19...@ohif/core@2.16.20) (2022-06-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Re IDC2797, fix double parsing of SR qualitative annotations ([#2830](https://github.com/OHIF/Viewers/issues/2830)) ([9f813e0](https://github.com/OHIF/Viewers/commit/9f813e0ea08f0aada8efab9ef6228ad90dd1758d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.16.19](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.18...@ohif/core@2.16.19) (2022-06-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.16.18](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.17...@ohif/core@2.16.18) (2022-04-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.16.17](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.16...@ohif/core@2.16.17) (2022-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.16.16](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.15...@ohif/core@2.16.16) (2022-04-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.16.15](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.14...@ohif/core@2.16.15) (2022-03-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.16.14](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.13...@ohif/core@2.16.14) (2022-03-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.16.13](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.12...@ohif/core@2.16.13) (2022-03-14)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/core",
|
||||
"version": "2.16.13",
|
||||
"version": "2.16.24",
|
||||
"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.19.4",
|
||||
"dcmjs": "0.19.9",
|
||||
"dicomweb-client": "^0.8.3",
|
||||
"immer": "9.0.12",
|
||||
"isomorphic-base64": "^1.0.2",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export default {
|
||||
TEXT: 'TEXT',
|
||||
POINT: 'POINT',
|
||||
MULTIPOINT: 'MULTIPOINT',
|
||||
POLYLINE: 'POLYLINE',
|
||||
|
||||
@@ -8,6 +8,17 @@ const parseSCOORD3D = ({ servicesManager, displaySets }) => {
|
||||
const { MeasurementService } = servicesManager.services;
|
||||
|
||||
const srDisplaySets = displaySets.filter(ds => ds.Modality === 'SR');
|
||||
const imageDisplaySets = displaySets.filter(
|
||||
ds =>
|
||||
ds.Modality !== 'SR' &&
|
||||
ds.Modality !== 'SEG' &&
|
||||
ds.Modality !== 'RTSTRUCT' &&
|
||||
ds.Modality !== 'RTDOSE'
|
||||
);
|
||||
|
||||
imageDisplaySets.forEach(imageDisplaySet => {
|
||||
imageDisplaySet.SRLabels = [];
|
||||
});
|
||||
|
||||
srDisplaySets.forEach(srDisplaySet => {
|
||||
const firstInstance = srDisplaySet.metadata;
|
||||
@@ -18,7 +29,7 @@ const parseSCOORD3D = ({ servicesManager, displaySets }) => {
|
||||
const { ContentSequence } = firstInstance;
|
||||
|
||||
srDisplaySet.referencedImages = getReferencedImagesList(ContentSequence);
|
||||
srDisplaySet.measurements = getMeasurements(ContentSequence, srDisplaySet);
|
||||
srDisplaySet.measurements = getMeasurements(ContentSequence);
|
||||
const mappings = MeasurementService.getSourceMappings(
|
||||
'CornerstoneTools',
|
||||
'4'
|
||||
@@ -28,13 +39,6 @@ const parseSCOORD3D = ({ servicesManager, displaySets }) => {
|
||||
srDisplaySet.isRehydratable = isRehydratable(srDisplaySet, mappings);
|
||||
srDisplaySet.isLoaded = true;
|
||||
|
||||
const imageDisplaySets = displaySets.filter(
|
||||
ds =>
|
||||
ds.Modality !== 'SR' &&
|
||||
ds.Modality !== 'SEG' &&
|
||||
ds.Modality !== 'RTSTRUCT' &&
|
||||
ds.Modality !== 'RTDOSE'
|
||||
);
|
||||
imageDisplaySets.forEach(imageDisplaySet => {
|
||||
// Check currently added displaySets and add measurements if the sources exist.
|
||||
checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, imageDisplaySet);
|
||||
@@ -127,10 +131,10 @@ const checkIfCanAddMeasurementsToDisplaySet = (
|
||||
|
||||
const imageIds = images.map(i => i.getImageId());
|
||||
const SOPInstanceUIDs = images.map(i => i.SOPInstanceUID);
|
||||
const colors = new Map();
|
||||
measurements.forEach(measurement => {
|
||||
const { coords } = measurement;
|
||||
|
||||
coords.forEach(coord => {
|
||||
coords.forEach((coord, index) => {
|
||||
if (coord.ReferencedSOPSequence !== undefined) {
|
||||
const imageIndex = SOPInstanceUIDs.findIndex(
|
||||
SOPInstanceUID =>
|
||||
@@ -138,14 +142,50 @@ const checkIfCanAddMeasurementsToDisplaySet = (
|
||||
coord.ReferencedSOPSequence.ReferencedSOPInstanceUID
|
||||
);
|
||||
if (imageIndex > -1) {
|
||||
if (!srDisplaySet.referencedDisplaySets.includes(imageDisplaySet)) {
|
||||
srDisplaySet.referencedDisplaySets.push(imageDisplaySet);
|
||||
}
|
||||
|
||||
const imageId = imageIds[imageIndex];
|
||||
const imageMetadata = images[imageIndex].getData().metadata;
|
||||
addMeasurement(
|
||||
measurement,
|
||||
imageId,
|
||||
imageMetadata,
|
||||
imageDisplaySet.displaySetInstanceUID
|
||||
);
|
||||
|
||||
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],
|
||||
});
|
||||
|
||||
if (index === 0) {
|
||||
addMeasurement(
|
||||
measurement,
|
||||
imageId,
|
||||
imageMetadata,
|
||||
imageDisplaySet.displaySetInstanceUID
|
||||
);
|
||||
}
|
||||
} else {
|
||||
addMeasurement(
|
||||
measurement,
|
||||
imageId,
|
||||
imageMetadata,
|
||||
imageDisplaySet.displaySetInstanceUID
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
const getCoordsFromSCOORDOrSCOORD3D = (graphicItem, displaySet) => {
|
||||
const { ValueType, RelationshipType, GraphicType, GraphicData } = graphicItem;
|
||||
|
||||
// if (RelationshipType !== RELATIONSHIP_TYPE.INFERRED_FROM) {
|
||||
// console.warn(
|
||||
// `Relationshiptype === ${RelationshipType}. Cannot deal with NON TID-1400 SCOORD group with RelationshipType !== "INFERRED FROM."`
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
|
||||
const getCoordsFromSCOORDOrSCOORD3D = graphicItem => {
|
||||
const { ValueType, GraphicType, GraphicData } = graphicItem;
|
||||
const coords = { ValueType, GraphicType, GraphicData };
|
||||
|
||||
// ContentSequence has length of 1 as RelationshipType === 'INFERRED FROM'
|
||||
if (ValueType === 'SCOORD') {
|
||||
const { ReferencedSOPSequence } = graphicItem.ContentSequence;
|
||||
coords.ReferencedSOPSequence = ReferencedSOPSequence;
|
||||
} else if (ValueType === 'SCOORD3D') {
|
||||
if (graphicItem.ReferencedFrameOfReferenceUID) {
|
||||
coords.ReferencedFrameOfReferenceSequence = graphicItem.ReferencedFrameOfReferenceUID;
|
||||
coords.ReferencedFrameOfReferenceSequence =
|
||||
graphicItem.ReferencedFrameOfReferenceUID;
|
||||
} else if (graphicItem.ContentSequence) {
|
||||
const {
|
||||
ReferencedFrameOfReferenceSequence,
|
||||
|
||||
@@ -3,10 +3,7 @@ import getSequenceAsArray from './getSequenceAsArray';
|
||||
import getMergedContentSequencesByTrackingUniqueIdentifiers from './getMergedContentSequencesByTrackingUniqueIdentifiers';
|
||||
import processMeasurement from './processMeasurement';
|
||||
|
||||
const getMeasurements = (
|
||||
ImagingMeasurementReportContentSequence,
|
||||
displaySet
|
||||
) => {
|
||||
const getMeasurements = ImagingMeasurementReportContentSequence => {
|
||||
const ImagingMeasurements = ImagingMeasurementReportContentSequence.find(
|
||||
item =>
|
||||
item.ConceptNameCodeSequence.CodeValue ===
|
||||
@@ -21,25 +18,19 @@ const getMeasurements = (
|
||||
CodeNameCodeSequenceValues.MeasurementGroup
|
||||
);
|
||||
|
||||
const mergedContentSequencesByTrackingUniqueIdentifiers = getMergedContentSequencesByTrackingUniqueIdentifiers(
|
||||
/* const mergedContentSequencesByTrackingUniqueIdentifiers = getMergedContentSequencesByTrackingUniqueIdentifiers(
|
||||
MeasurementGroups
|
||||
);
|
||||
);*/
|
||||
|
||||
let measurements = [];
|
||||
|
||||
Object.keys(mergedContentSequencesByTrackingUniqueIdentifiers).forEach(
|
||||
trackingUniqueIdentifier => {
|
||||
const mergedContentSequence =
|
||||
mergedContentSequencesByTrackingUniqueIdentifiers[
|
||||
trackingUniqueIdentifier
|
||||
];
|
||||
|
||||
const measurement = processMeasurement(mergedContentSequence, displaySet);
|
||||
if (measurement) {
|
||||
measurements.push(measurement);
|
||||
}
|
||||
MeasurementGroups.forEach(MeasurementGroup => {
|
||||
const contentSequence = MeasurementGroup.ContentSequence;
|
||||
const measurement = processMeasurement(contentSequence);
|
||||
if (measurement) {
|
||||
measurements.push(measurement);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
return measurements;
|
||||
};
|
||||
|
||||
@@ -57,6 +57,10 @@ const getRenderableData = (
|
||||
|
||||
// https://dicom.innolitics.com/ciods/procedure-log/sr-document-content/00700023
|
||||
switch (GraphicType) {
|
||||
case SCOORD_TYPES.TEXT:
|
||||
renderableData = [{ x: GraphicData[0], y: GraphicData[1] }];
|
||||
|
||||
break;
|
||||
case SCOORD_TYPES.POINT:
|
||||
renderableData = [];
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import processTID1410Measurement from './processTID1410Measurement';
|
||||
import processNonGeometricallyDefinedMeasurement from './processNonGeometricallyDefinedMeasurement';
|
||||
|
||||
const processMeasurement = (mergedContentSequence, displaySet) => {
|
||||
const processMeasurement = contentSequence => {
|
||||
if (
|
||||
mergedContentSequence.some(
|
||||
contentSequence.some(
|
||||
group => group.ValueType === 'SCOORD' || group.ValueType === 'SCOORD3D'
|
||||
)
|
||||
) {
|
||||
return processTID1410Measurement(mergedContentSequence, displaySet);
|
||||
return processTID1410Measurement(contentSequence);
|
||||
}
|
||||
|
||||
return processNonGeometricallyDefinedMeasurement(mergedContentSequence);
|
||||
return processNonGeometricallyDefinedMeasurement(contentSequence);
|
||||
};
|
||||
|
||||
export default processMeasurement;
|
||||
+46
-6
@@ -1,31 +1,40 @@
|
||||
import getLabelFromMeasuredValueSequence from './getLabelFromMeasuredValueSequence';
|
||||
import getCoordsFromSCOORDOrSCOORD3D from './getCoordsFromSCOORDOrSCOORD3D';
|
||||
import { CodeNameCodeSequenceValues, CodingSchemeDesignators } from '../enums';
|
||||
import SCOORD_TYPES from '../constants/scoordTypes';
|
||||
|
||||
const CORNERSTONE_FREETEXT_CODE_VALUE = 'CORNERSTONEFREETEXT';
|
||||
|
||||
const processNonGeometricallyDefinedMeasurement = mergedContentSequence => {
|
||||
const NUMContentItems = mergedContentSequence.filter(
|
||||
const processNonGeometricallyDefinedMeasurement = contentSequence => {
|
||||
const NUMContentItems = contentSequence.filter(
|
||||
group => group.ValueType === 'NUM'
|
||||
);
|
||||
|
||||
const UIDREFContentItem = mergedContentSequence.find(
|
||||
const CODEContentItems = contentSequence.filter(
|
||||
group => group.ValueType === 'CODE'
|
||||
);
|
||||
|
||||
const UIDREFContentItem = contentSequence.find(
|
||||
group => group.ValueType === 'UIDREF'
|
||||
);
|
||||
|
||||
const TrackingIdentifierContentItem = mergedContentSequence.find(
|
||||
const IMAGEContentItem = contentSequence.find(
|
||||
group => group.ValueType === 'IMAGE'
|
||||
);
|
||||
|
||||
const TrackingIdentifierContentItem = contentSequence.find(
|
||||
item =>
|
||||
item.ConceptNameCodeSequence.CodeValue ===
|
||||
CodeNameCodeSequenceValues.TrackingIdentifier
|
||||
);
|
||||
|
||||
const Finding = mergedContentSequence.find(
|
||||
const Finding = contentSequence.find(
|
||||
item =>
|
||||
item.ConceptNameCodeSequence.CodeValue ===
|
||||
CodeNameCodeSequenceValues.Finding
|
||||
);
|
||||
|
||||
const FindingSites = mergedContentSequence.filter(
|
||||
const FindingSites = contentSequence.filter(
|
||||
item =>
|
||||
item.ConceptNameCodeSequence.CodingSchemeDesignator ===
|
||||
CodingSchemeDesignators.SRT &&
|
||||
@@ -111,6 +120,37 @@ const processNonGeometricallyDefinedMeasurement = mergedContentSequence => {
|
||||
}
|
||||
});
|
||||
|
||||
if (NUMContentItems.length === 0 && IMAGEContentItem) {
|
||||
CODEContentItems.forEach(item => {
|
||||
const { ConceptCodeSequence, ConceptNameCodeSequence } = item;
|
||||
|
||||
if (!ConceptCodeSequence || !ConceptNameCodeSequence) {
|
||||
console.warn(`Graphic missing, skipping annotation.`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const GraphicData = [0, 0];
|
||||
const GraphicType = SCOORD_TYPES.TEXT;
|
||||
const { ValueType } = item;
|
||||
const ReferencedSOPSequence = IMAGEContentItem.ReferencedSOPSequence;
|
||||
const coord = {
|
||||
ValueType,
|
||||
GraphicType,
|
||||
GraphicData,
|
||||
ReferencedSOPSequence,
|
||||
};
|
||||
measurement.coords.push(coord);
|
||||
measurement.labels.push({
|
||||
label: ConceptNameCodeSequence.CodeMeaning,
|
||||
labelCodingSchemeDesignator:
|
||||
ConceptNameCodeSequence.CodingSchemeDesignator,
|
||||
value: ConceptCodeSequence.CodeMeaning,
|
||||
valueCodingSchemeDesignator: ConceptCodeSequence.CodingSchemeDesignator,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return measurement;
|
||||
};
|
||||
|
||||
|
||||
@@ -5,14 +5,14 @@ import { RELATIONSHIP_TYPE, CodeNameCodeSequenceValues } from '../enums';
|
||||
/**
|
||||
* TID 1410 Planar ROI Measurements and Qualitative Evaluations.
|
||||
*
|
||||
* @param {*} mergedContentSequence
|
||||
* @param {*} contentSequence
|
||||
* @returns
|
||||
*/
|
||||
const processTID1410Measurement = (mergedContentSequence, displaySet) => {
|
||||
const processTID1410Measurement = contentSequence => {
|
||||
// Need to deal with TID 1410 style measurements, which will have a SCOORD or SCOORD3D at the top level,
|
||||
// And non-geometric representations where each NUM has "INFERRED FROM" SCOORD/SCOORD3D
|
||||
|
||||
const graphicItem = mergedContentSequence.find(
|
||||
const graphicItem = contentSequence.find(
|
||||
group => group.ValueType === 'SCOORD' || group.ValueType === 'SCOORD3D'
|
||||
);
|
||||
|
||||
@@ -23,24 +23,24 @@ const processTID1410Measurement = (mergedContentSequence, displaySet) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const UIDREFContentItem = mergedContentSequence.find(
|
||||
const UIDREFContentItem = contentSequence.find(
|
||||
group => group.ValueType === 'UIDREF'
|
||||
);
|
||||
|
||||
const TrackingIdentifierContentItem = mergedContentSequence.find(
|
||||
const TrackingIdentifierContentItem = contentSequence.find(
|
||||
item =>
|
||||
item.ConceptNameCodeSequence.CodeValue ===
|
||||
CodeNameCodeSequenceValues.TrackingIdentifier
|
||||
);
|
||||
|
||||
const NUMContentItems = mergedContentSequence.filter(
|
||||
const NUMContentItems = contentSequence.filter(
|
||||
group => group.ValueType === 'NUM'
|
||||
);
|
||||
|
||||
const measurement = {
|
||||
loaded: false,
|
||||
labels: [],
|
||||
coords: [getCoordsFromSCOORDOrSCOORD3D(graphicItem, displaySet)],
|
||||
coords: [getCoordsFromSCOORDOrSCOORD3D(graphicItem)],
|
||||
TrackingUniqueIdentifier: UIDREFContentItem.UID,
|
||||
TrackingIdentifier: TrackingIdentifierContentItem.TextValue,
|
||||
};
|
||||
|
||||
@@ -401,7 +401,7 @@ class StackLoadingListener extends BaseLoadingListener {
|
||||
const totalFramesCount = this.stack.imageIds.length;
|
||||
const loadedFramesCount = this.loadedCount;
|
||||
const loadingFramesCount = totalFramesCount - loadedFramesCount;
|
||||
const percentComplete = Math.round(
|
||||
const percentComplete = Math.ceil(
|
||||
(loadedFramesCount / totalFramesCount) * 100
|
||||
);
|
||||
const progressId = this._getProgressId();
|
||||
@@ -469,8 +469,8 @@ class StudyLoadingListener {
|
||||
|
||||
// TODO: Make this work for plugins
|
||||
if (!stack) {
|
||||
console.warn('Skipping adding displaySet to StudyLoadingListener');
|
||||
console.warn(displaySet);
|
||||
//console.warn('Skipping adding displaySet to StudyLoadingListener');
|
||||
//console.warn(displaySet);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ import DICOMWeb from './../../DICOMWeb';
|
||||
import ImageSet from './../ImageSet';
|
||||
import { InstanceMetadata } from './InstanceMetadata';
|
||||
import { Metadata } from './Metadata';
|
||||
import OHIFError from '../OHIFError';
|
||||
import { SeriesMetadata } from './SeriesMetadata';
|
||||
// - createStacks
|
||||
import { api } from 'dicomweb-client';
|
||||
// - createStacks
|
||||
import { isImage } from '../../utils/isImage';
|
||||
import { naturalizeSOPClassUID } from '../../utils/naturalizeSOPClassUID';
|
||||
import {
|
||||
isDisplaySetReconstructable,
|
||||
isSpacingUniform,
|
||||
@@ -169,8 +169,12 @@ class StudyMetadata extends Metadata {
|
||||
!isImage(instance.getTagValue('SOPClassUID')) &&
|
||||
!instance.getTagValue('Rows')
|
||||
) {
|
||||
// we set an empty display and we add a isModalitySupported variable to
|
||||
// print a warning that the modality is not supported in the thumbnail.
|
||||
// we set an empty display and we add a isSOPClassUIDSupported variable to
|
||||
// print a warning that the series is not supported in the thumbnail.
|
||||
// SOPClassUIDNaturalized is human readable name, since for non image series,
|
||||
// we could have a mismatch between the SOPClassUID and the Modality.
|
||||
// For example, in the Parametric map IOD Modality is expected to match
|
||||
// the value for the series used to generate Parametric map, and there is no "PM" modality.
|
||||
const displaySet = new ImageSet([]);
|
||||
const seriesData = series.getData();
|
||||
displaySet.setAttributes({
|
||||
@@ -188,7 +192,10 @@ class StudyMetadata extends Metadata {
|
||||
InstanceNumber: instance.getTagValue('InstanceNumber'), // Include the instance number
|
||||
AcquisitionDatetime: instance.getTagValue('AcquisitionDateTime'), // Include the acquisition datetime
|
||||
isReconstructable: false,
|
||||
isModalitySupported: false,
|
||||
isSOPClassUIDSupported: false,
|
||||
SOPClassUIDNaturalized: naturalizeSOPClassUID(
|
||||
instance.getTagValue('SOPClassUID')
|
||||
),
|
||||
metadata: instance.getData().metadata,
|
||||
});
|
||||
|
||||
@@ -333,10 +340,38 @@ class StudyMetadata extends Metadata {
|
||||
if (referencedSeriesInstanceUID) {
|
||||
filteredDerivedDisplaySets = filteredDerivedDisplaySets.filter(
|
||||
displaySet => {
|
||||
return (
|
||||
StudyMetadata.getReferencedDisplaySet(displaySet, [this])
|
||||
.SeriesInstanceUID === referencedSeriesInstanceUID
|
||||
const referencedDisplaySet = StudyMetadata.getReferencedDisplaySet(
|
||||
displaySet,
|
||||
[this]
|
||||
);
|
||||
if (referencedDisplaySet) {
|
||||
return (
|
||||
referencedDisplaySet.SeriesInstanceUID ===
|
||||
referencedSeriesInstanceUID
|
||||
);
|
||||
} else {
|
||||
if (
|
||||
!displaySet.referencedDisplaySets ||
|
||||
displaySet.referencedDisplaySets.length === 0
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const filteredReferencedDisplaySets = displaySet.referencedDisplaySets.filter(
|
||||
referencedDisplaySet =>
|
||||
referencedDisplaySet.SeriesInstanceUID ===
|
||||
referencedSeriesInstanceUID
|
||||
);
|
||||
|
||||
if (
|
||||
filteredReferencedDisplaySets &&
|
||||
filteredReferencedDisplaySets.length !== 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -923,7 +958,7 @@ const makeDisplaySet = (series, instances) => {
|
||||
: displayReconstructableInfo.reconstructionIssues;
|
||||
}
|
||||
|
||||
imageSet.isModalitySupported = true;
|
||||
imageSet.isSOPClassUIDSupported = true;
|
||||
|
||||
return imageSet;
|
||||
};
|
||||
|
||||
@@ -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 ||
|
||||
''}`;
|
||||
|
||||
@@ -420,6 +420,10 @@ class MeasurementService {
|
||||
throw new Error('No source definition provided.');
|
||||
}
|
||||
|
||||
if (definition == 'stack' || definition == 'stackPrefetch') {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceInfo = this._getSourceInfo(source);
|
||||
|
||||
if (!this._sourceHasMappings(source)) {
|
||||
|
||||
@@ -25,7 +25,7 @@ function createAndAddStack(stackMap, study, displaySet, stackUpdatedCallbacks) {
|
||||
const imageIds = [];
|
||||
let imageId;
|
||||
|
||||
displaySet.images.forEach((instance, imageIndex) => {
|
||||
images.forEach((instance, imageIndex) => {
|
||||
const image = instance.getData();
|
||||
const metaData = {
|
||||
instance: image, // in this context, instance will be the data of the InstanceMetadata object...
|
||||
@@ -35,7 +35,7 @@ function createAndAddStack(stackMap, study, displaySet, stackUpdatedCallbacks) {
|
||||
imageIndex: imageIndex + 1,
|
||||
};
|
||||
|
||||
const naturalizedInstance = instance.getData().metadata;
|
||||
const naturalizedInstance = image.metadata;
|
||||
const NumberOfFrames = naturalizedInstance.NumberOfFrames;
|
||||
|
||||
if (NumberOfFrames > 1) {
|
||||
|
||||
@@ -49,7 +49,12 @@ import studyMetadataManager from './studyMetadataManager';
|
||||
* @param {object} snackbar
|
||||
* @returns void
|
||||
*/
|
||||
async function loadAndCacheDerivedDisplaySets(referencedDisplaySet, studies, logger, snackbar) {
|
||||
async function loadAndCacheDerivedDisplaySets(
|
||||
referencedDisplaySet,
|
||||
studies,
|
||||
logger,
|
||||
snackbar
|
||||
) {
|
||||
const { StudyInstanceUID, SeriesInstanceUID } = referencedDisplaySet;
|
||||
const promises = [];
|
||||
const studyMetadata = studyMetadataManager.get(StudyInstanceUID);
|
||||
@@ -80,60 +85,111 @@ async function loadAndCacheDerivedDisplaySets(referencedDisplaySet, studies, log
|
||||
});
|
||||
|
||||
// For each type, see if any are loaded, if not load the most recent.
|
||||
await Promise.all(Object.keys(displaySetsPerModality).map(async (key) => {
|
||||
const displaySets = displaySetsPerModality[key];
|
||||
await Promise.all(
|
||||
Object.keys(displaySetsPerModality).map(async key => {
|
||||
const displaySets = displaySetsPerModality[key];
|
||||
|
||||
const isLoaded = displaySets.some(displaySet => displaySet.isLoaded);
|
||||
if (isLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (displaySets.some(displaySet => displaySet.loadError)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// find most recent and load it.
|
||||
let recentDateTime = 0;
|
||||
let recentDisplaySet = displaySets[0];
|
||||
|
||||
displaySets.forEach(displaySet => {
|
||||
const dateTime = Number(
|
||||
`${displaySet.SeriesDate}${displaySet.SeriesTime}`
|
||||
);
|
||||
if (dateTime > recentDateTime) {
|
||||
recentDateTime = dateTime;
|
||||
recentDisplaySet = displaySet;
|
||||
const isLoaded = displaySets.some(displaySet => displaySet.isLoaded);
|
||||
if (isLoaded) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
if (recentDisplaySet.hasOwnProperty('getSourceDisplaySet') &&
|
||||
typeof recentDisplaySet.getSourceDisplaySet === 'function') {
|
||||
await recentDisplaySet.getSourceDisplaySet(studies);
|
||||
} else {
|
||||
await recentDisplaySet.load(referencedDisplaySet, studies);
|
||||
if (displaySets.some(displaySet => displaySet.loadError)) {
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
recentDisplaySet.isLoaded = false;
|
||||
recentDisplaySet.loadError = true;
|
||||
logger.error({ error, message: error.message });
|
||||
snackbar.show({
|
||||
title: 'Error loading derived display set:',
|
||||
message: error.message,
|
||||
type: 'error',
|
||||
error,
|
||||
autoClose: false,
|
||||
|
||||
// find most recent and load it.
|
||||
let recentDateTime = 0;
|
||||
let recentDisplaySet = displaySets[0];
|
||||
|
||||
displaySets.forEach(displaySet => {
|
||||
const dateTime = Number(
|
||||
`${displaySet.SeriesDate}${displaySet.SeriesTime}`
|
||||
);
|
||||
if (dateTime > recentDateTime) {
|
||||
recentDateTime = dateTime;
|
||||
recentDisplaySet = displaySet;
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
try {
|
||||
if (
|
||||
recentDisplaySet.hasOwnProperty('getSourceDisplaySet') &&
|
||||
typeof recentDisplaySet.getSourceDisplaySet === 'function'
|
||||
) {
|
||||
if (recentDisplaySet.Modality === 'SEG' && logger) {
|
||||
const onDisplaySetLoadFailureHandler = error => {
|
||||
logger.error({ error, message: error.message });
|
||||
snackbar.show({
|
||||
title: 'DICOM Segmentation Loader',
|
||||
message: error.message,
|
||||
type: 'error',
|
||||
autoClose: true,
|
||||
});
|
||||
};
|
||||
|
||||
let activatedLabelmapIndex = -1;
|
||||
while (activatedLabelmapIndex == -1) {
|
||||
const {
|
||||
referencedDisplaySet,
|
||||
activatedLabelmapPromise,
|
||||
} = await recentDisplaySet.getSourceDisplaySet(
|
||||
studies,
|
||||
true,
|
||||
onDisplaySetLoadFailureHandler
|
||||
);
|
||||
|
||||
activatedLabelmapIndex = await activatedLabelmapPromise;
|
||||
const selectionFired = new CustomEvent(
|
||||
'extensiondicomsegmentationsegselected',
|
||||
{
|
||||
detail: { activatedLabelmapIndex: activatedLabelmapIndex },
|
||||
}
|
||||
);
|
||||
document.dispatchEvent(selectionFired);
|
||||
|
||||
const lastDateTime = Number(
|
||||
`${recentDisplaySet.SeriesDate}${recentDisplaySet.SeriesTime}`
|
||||
);
|
||||
recentDateTime = 0;
|
||||
displaySets.forEach(displaySet => {
|
||||
const dateTime = Number(
|
||||
`${displaySet.SeriesDate}${displaySet.SeriesTime}`
|
||||
);
|
||||
if (dateTime > recentDateTime && dateTime < lastDateTime) {
|
||||
recentDateTime = dateTime;
|
||||
recentDisplaySet = displaySet;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
await recentDisplaySet.getSourceDisplaySet(studies);
|
||||
}
|
||||
} else {
|
||||
await recentDisplaySet.load(referencedDisplaySet, studies);
|
||||
}
|
||||
} catch (error) {
|
||||
recentDisplaySet.isLoaded = false;
|
||||
recentDisplaySet.loadError = true;
|
||||
logger.error({ error, message: error.message });
|
||||
snackbar.show({
|
||||
title: 'Error loading derived display set:',
|
||||
message: error.message,
|
||||
type: 'error',
|
||||
error,
|
||||
autoClose: false,
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
/*
|
||||
* TODO: Improve the way we notify parts of the app
|
||||
* that depends on derived display sets to be loaded.
|
||||
* (Implement pubsub for better tracking of derived display sets)
|
||||
*/
|
||||
* TODO: Improve the way we notify parts of the app
|
||||
* that depends on derived display sets to be loaded.
|
||||
* (Implement pubsub for better tracking of derived display sets)
|
||||
*/
|
||||
const event = new CustomEvent('deriveddisplaysetsloadedandcached');
|
||||
document.dispatchEvent(event);
|
||||
};
|
||||
}
|
||||
|
||||
export default loadAndCacheDerivedDisplaySets;
|
||||
@@ -0,0 +1,200 @@
|
||||
import { sopClassDictionary } from './sopClassDictionary';
|
||||
import { isImage } from './isImage';
|
||||
|
||||
/**
|
||||
* Naturalize SOP Class UID which do not have image data
|
||||
* @param {string} SOPClassUID - SOP Class UID to be converted
|
||||
* @returns {string} - human readable name
|
||||
*/
|
||||
export const naturalizeSOPClassUID = SOPClassUID => {
|
||||
let naturalizedName = '';
|
||||
if (!SOPClassUID) return naturalizedName;
|
||||
if (!isImage) return naturalizedName;
|
||||
|
||||
if (sopClassDictionary.MRSpectroscopyStorage === SOPClassUID) {
|
||||
naturalizedName = 'MRSpectroscopy';
|
||||
} else if (sopClassDictionary.EnhancedUSVolumeStorage === SOPClassUID) {
|
||||
naturalizedName = 'EnhancedUSVolume';
|
||||
} else if (sopClassDictionary.Sop12LeadECGWaveformStorage === SOPClassUID) {
|
||||
naturalizedName = 'Sop12LeadECGWaveform';
|
||||
} else if (sopClassDictionary.GeneralECGWaveformStorage === SOPClassUID) {
|
||||
naturalizedName = 'GeneralECGWaveform';
|
||||
} else if (sopClassDictionary.AmbulatoryECGWaveformStorage === SOPClassUID) {
|
||||
naturalizedName = 'AECAmbulatoryECGWaveformGW';
|
||||
} else if (sopClassDictionary.HemodynamicWaveformStorage === SOPClassUID) {
|
||||
naturalizedName = 'HemodynamicWaveform';
|
||||
} else if (
|
||||
sopClassDictionary.CardiacElectrophysiologyWaveformStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'CardiacElectrophysiologyWaveform';
|
||||
} else if (
|
||||
sopClassDictionary.BasicVoiceAudioWaveformStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'BasicVoiceAudioWaveform';
|
||||
} else if (sopClassDictionary.GeneralAudioWaveformStorage === SOPClassUID) {
|
||||
naturalizedName = 'GGeneralAudioWaveformAW';
|
||||
} else if (sopClassDictionary.ArterialPulseWaveformStorage === SOPClassUID) {
|
||||
naturalizedName = 'APArterialPulseWaveformW';
|
||||
} else if (sopClassDictionary.RespiratoryWaveformStorage === SOPClassUID) {
|
||||
naturalizedName = 'RespiratoryWaveform';
|
||||
} else if (
|
||||
sopClassDictionary.GrayscaleSoftcopyPresentationStateStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'GrayscaleSoftcopyPresentationState';
|
||||
} else if (
|
||||
sopClassDictionary.ColorSoftcopyPresentationStateStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'ColorSoftcopyPresentationState';
|
||||
} else if (
|
||||
sopClassDictionary.PseudoColorSoftcopyPresentationStateStorage ===
|
||||
SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'PseudoColorSoftcopyPresentationState';
|
||||
} else if (
|
||||
sopClassDictionary.BlendingSoftcopyPresentationStateStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'BlendingSoftcopyPresentationState';
|
||||
} else if (
|
||||
sopClassDictionary.XAXRFGrayscaleSoftcopyPresentationStateStorage ===
|
||||
SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'XAXRFGrayscaleSoftcopyPresentationState';
|
||||
} else if (sopClassDictionary.RawDataStorage === SOPClassUID) {
|
||||
naturalizedName = 'RawData';
|
||||
} else if (sopClassDictionary.SpatialRegistrationStorage === SOPClassUID) {
|
||||
naturalizedName = 'SpatialRegistration';
|
||||
} else if (sopClassDictionary.SpatialFiducialsStorage === SOPClassUID) {
|
||||
naturalizedName = 'SpatialFiducials';
|
||||
} else if (
|
||||
sopClassDictionary.DeformableSpatialRegistrationStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'DeformableSpatialRegistration';
|
||||
} else if (sopClassDictionary.SegmentationStorage === SOPClassUID) {
|
||||
naturalizedName = 'SEG';
|
||||
} else if (sopClassDictionary.SurfaceSegmentationStorage === SOPClassUID) {
|
||||
naturalizedName = 'SurfaceSEG';
|
||||
} else if (sopClassDictionary.RealWorldValueMappingStorage === SOPClassUID) {
|
||||
naturalizedName = 'RealWorldValueMapping';
|
||||
} else if (sopClassDictionary.SurfaceScanMeshStorage === SOPClassUID) {
|
||||
naturalizedName = 'SurfaceScanMesh';
|
||||
} else if (sopClassDictionary.SurfaceScanPointCloudStorage === SOPClassUID) {
|
||||
naturalizedName = 'SurfaceScanPointCloud';
|
||||
} else if (
|
||||
sopClassDictionary.StereometricRelationshipStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'StereometricRelationship';
|
||||
} else if (sopClassDictionary.LensometryMeasurementsStorage === SOPClassUID) {
|
||||
naturalizedName = 'LensometryMeasurements';
|
||||
} else if (
|
||||
sopClassDictionary.AutorefractionMeasurementsStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'AutorefractionMeasurements';
|
||||
} else if (
|
||||
sopClassDictionary.KeratometryMeasurementsStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'KeratometryMeasurements';
|
||||
} else if (
|
||||
sopClassDictionary.SubjectiveRefractionMeasurementsStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'SubjectiveRefractionMeasurements';
|
||||
} else if (
|
||||
sopClassDictionary.VisualAcuityMeasurementsStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'VisualAcuityMeasurements';
|
||||
} else if (
|
||||
sopClassDictionary.SpectaclePrescriptionReportStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'SpectaclePrescriptionReport';
|
||||
} else if (
|
||||
sopClassDictionary.OphthalmicAxialMeasurementsStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'OphthalmicAxialMeasurements';
|
||||
} else if (
|
||||
sopClassDictionary.IntraocularLensCalculationsStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'IntraocularLensCalculations';
|
||||
} else if (
|
||||
sopClassDictionary.MacularGridThicknessandVolumeReport === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'MacularGridThicknessandVolume';
|
||||
} else if (
|
||||
sopClassDictionary.OphthalmicVisualFieldStaticPerimetryMeasurementsStorage ===
|
||||
SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'OphthalmicVisualFieldStaticPerimetryMeasurements';
|
||||
} else if (sopClassDictionary.OphthalmicThicknessMapStorage === SOPClassUID) {
|
||||
naturalizedName = 'OphthalmicThicknessMap';
|
||||
} else if (sopClassDictionary.CornealTopographyMapStorage === SOPClassUID) {
|
||||
naturalizedName = 'CornealTopographyMap';
|
||||
} else if (sopClassDictionary.BasicTextSR === SOPClassUID) {
|
||||
naturalizedName = 'BasicTextSR';
|
||||
} else if (sopClassDictionary.EnhancedSR === SOPClassUID) {
|
||||
naturalizedName = 'EnhancedSR';
|
||||
} else if (sopClassDictionary.ComprehensiveSR === SOPClassUID) {
|
||||
naturalizedName = 'ComprehensiveSR';
|
||||
} else if (sopClassDictionary.Comprehensive3DSR === SOPClassUID) {
|
||||
naturalizedName = 'Comprehensive3DSR';
|
||||
} else if (sopClassDictionary.ProcedureLog === SOPClassUID) {
|
||||
naturalizedName = 'ProcedureLog';
|
||||
} else if (sopClassDictionary.MammographyCADSR === SOPClassUID) {
|
||||
naturalizedName = 'MammographyCADSR';
|
||||
} else if (sopClassDictionary.KeyObjectSelection === SOPClassUID) {
|
||||
naturalizedName = 'KeyObject';
|
||||
} else if (sopClassDictionary.ChestCADSR === SOPClassUID) {
|
||||
naturalizedName = 'ChestCADSR';
|
||||
} else if (sopClassDictionary.XRayRadiationDoseSR === SOPClassUID) {
|
||||
naturalizedName = 'XRayRadiationDoseSR';
|
||||
} else if (
|
||||
sopClassDictionary.RadiopharmaceuticalRadiationDoseSR === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'RadiopharmaceuticalRadiationDoseSR';
|
||||
} else if (sopClassDictionary.ColonCADSR === SOPClassUID) {
|
||||
naturalizedName = 'ColonCADSR';
|
||||
} else if (
|
||||
sopClassDictionary.ImplantationPlanSRDocumentStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'ImplantationPlanSRDocument';
|
||||
} else if (sopClassDictionary.EncapsulatedPDFStorage === SOPClassUID) {
|
||||
naturalizedName = 'EncapsulatedPDF';
|
||||
} else if (sopClassDictionary.EncapsulatedCDAStorage === SOPClassUID) {
|
||||
naturalizedName = 'EncapsulatedCDA';
|
||||
} else if (sopClassDictionary.BasicStructuredDisplayStorage === SOPClassUID) {
|
||||
naturalizedName = 'BasicStructuredDisplay';
|
||||
} else if (sopClassDictionary.RTDoseStorage === SOPClassUID) {
|
||||
naturalizedName = 'RTDose';
|
||||
} else if (sopClassDictionary.RTStructureSetStorage === SOPClassUID) {
|
||||
naturalizedName = 'RTStructureSet';
|
||||
} else if (sopClassDictionary.RTBeamsTreatmentRecordStorage === SOPClassUID) {
|
||||
naturalizedName = 'RTBeamsTreatmentRecord';
|
||||
} else if (sopClassDictionary.RTPlanStorage === SOPClassUID) {
|
||||
naturalizedName = 'RTPlan';
|
||||
} else if (
|
||||
sopClassDictionary.RTBrachyTreatmentRecordStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'RTBrachyTreatmentRecord';
|
||||
} else if (
|
||||
sopClassDictionary.RTTreatmentSummaryRecordStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'RTTreatmentSummaryRecord';
|
||||
} else if (sopClassDictionary.RTIonPlanStorage === SOPClassUID) {
|
||||
naturalizedName = 'RTIonPlan';
|
||||
} else if (
|
||||
sopClassDictionary.RTIonBeamsTreatmentRecordStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'RTIonBeamsTreatmentRecord';
|
||||
} else if (
|
||||
sopClassDictionary.RTBeamsDeliveryInstructionStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'RTBeamsDeliveryInstruction';
|
||||
} else if (sopClassDictionary.GenericImplantTemplateStorage === SOPClassUID) {
|
||||
naturalizedName = 'GenericImplantTemplate';
|
||||
} else if (
|
||||
sopClassDictionary.ImplantAssemblyTemplateStorage === SOPClassUID
|
||||
) {
|
||||
naturalizedName = 'ImplantAssemblyTemplate';
|
||||
} else if (sopClassDictionary.ImplantTemplateGroupStorage === SOPClassUID) {
|
||||
naturalizedName = 'ImplantTemplateGroup';
|
||||
}
|
||||
|
||||
return naturalizedName;
|
||||
};
|
||||
@@ -3,6 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.10.10](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.9...@ohif/ui@1.10.10) (2022-08-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/ui
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.10.9](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.8...@ohif/ui@1.10.9) (2022-06-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/ui
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.10.8](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.7...@ohif/ui@1.10.8) (2022-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/ui
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.10.7](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.6...@ohif/ui@1.10.7) (2022-03-14)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/ui",
|
||||
"version": "1.10.7",
|
||||
"version": "1.10.10",
|
||||
"description": "A set of React components for Medical Imaging Viewers",
|
||||
"author": "OHIF Contributors",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -9,6 +9,14 @@ import { TableListItem } from './../tableList/TableListItem.js';
|
||||
|
||||
import './MeasurementTableItem.styl';
|
||||
|
||||
const ColoredCircle = ({ color }) => {
|
||||
return <div className="item-color" style={{ backgroundColor: color }}></div>;
|
||||
};
|
||||
|
||||
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,115 @@ class MeasurementTableItem extends Component {
|
||||
actionButtons.push(deleteButton);
|
||||
}
|
||||
|
||||
return (
|
||||
<TableListItem
|
||||
itemKey={this.props.measurementData.measurementNumber}
|
||||
itemClass={`measurementItem ${this.props.itemClass} ${hasWarningClass}`}
|
||||
itemIndex={this.props.itemIndex}
|
||||
onItemClick={this.onItemClick}
|
||||
>
|
||||
<div>
|
||||
<div className="measurementLocation">
|
||||
{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 (
|
||||
<React.Fragment>
|
||||
<TableListItem
|
||||
key={this.props.measurementData.measurementNumber}
|
||||
itemKey={this.props.measurementData.measurementNumber}
|
||||
itemClass={`measurementItem ${this.props.itemClass} ${hasWarningClass}`}
|
||||
itemIndex={this.props.itemIndex}
|
||||
onItemClick={this.onItemClick}
|
||||
>
|
||||
<div>
|
||||
<div className="measurementLocation">
|
||||
{this.props.t(this.props.measurementData.label, {
|
||||
keySeparator: '>',
|
||||
nsSeparator: '|',
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className="icons">
|
||||
<div className="displayTexts">{this.getDataDisplayText()}</div>
|
||||
<Icon
|
||||
className={`eye-icon`}
|
||||
name={this.state.visible ? 'eye' : 'eye-closed'}
|
||||
width="20px"
|
||||
height="20px"
|
||||
onClick={() => {
|
||||
this.props.measurementData.labels.forEach(label => {
|
||||
label.visible = !this.state.visible;
|
||||
});
|
||||
|
||||
this.setState({
|
||||
visible: !this.state.visible,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Icon
|
||||
className={`angle-double-${
|
||||
this.state.collapsed ? 'down' : 'up'
|
||||
}`}
|
||||
name={`angle-double-${this.state.collapsed ? 'down' : 'up'}`}
|
||||
width="20px"
|
||||
height="20px"
|
||||
onClick={() => {
|
||||
this.setState({
|
||||
collapsed: !this.state.collapsed,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</TableListItem>
|
||||
{this.state.collapsed &&
|
||||
this.props.measurementData.labels.map((SRLabel, index) => {
|
||||
return (
|
||||
<TableListItem
|
||||
key={index}
|
||||
itemKey={index}
|
||||
itemMeta={<ColoredCircle color={SRLabel.color} />}
|
||||
itemMetaClass="item-color-section"
|
||||
onItemClick={this.onItemClick}
|
||||
>
|
||||
<div>
|
||||
<div className="icons">
|
||||
<span style={{ width: '90px' }}>
|
||||
{SRLabel.label + ' : ' + SRLabel.value}
|
||||
</span>
|
||||
<Icon
|
||||
className={`eye-icon`}
|
||||
name={SRLabel.visible ? 'eye' : 'eye-closed'}
|
||||
width="20px"
|
||||
height="20px"
|
||||
onClick={() => {
|
||||
SRLabel.visible = !SRLabel.visible;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TableListItem>
|
||||
);
|
||||
})}
|
||||
</React.Fragment>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<TableListItem
|
||||
key={this.props.measurementData.measurementNumber}
|
||||
itemKey={this.props.measurementData.measurementNumber}
|
||||
itemClass={`measurementItem ${this.props.itemClass} ${hasWarningClass}`}
|
||||
itemIndex={this.props.itemIndex}
|
||||
onItemClick={this.onItemClick}
|
||||
>
|
||||
<div>
|
||||
<div className="measurementLocation">
|
||||
{this.props.t(this.props.measurementData.label, {
|
||||
keySeparator: '>',
|
||||
nsSeparator: '|',
|
||||
})}
|
||||
</div>
|
||||
<div className="displayTexts">{this.getDataDisplayText()}</div>
|
||||
{!this.props.measurementData.isReadOnly && (
|
||||
<div className="rowActions">{actionButtons}</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="displayTexts">{this.getDataDisplayText()}</div>
|
||||
{!this.props.measurementData.isReadOnly && (
|
||||
<div className="rowActions">{actionButtons}</div>
|
||||
)}
|
||||
</div>
|
||||
</TableListItem>
|
||||
);
|
||||
</TableListItem>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
onItemClick = event => {
|
||||
|
||||
@@ -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;
|
||||
@@ -177,7 +177,9 @@ function Thumbnail(props) {
|
||||
const { progressId, progressData } = detail;
|
||||
if (`StackProgress:${displaySetInstanceUID}` === progressId) {
|
||||
const percent = progressData ? progressData.percentComplete : 0;
|
||||
setStackPercentComplete(percent);
|
||||
if (percent > stackPercentComplete) {
|
||||
setStackPercentComplete(percent);
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
box-shadow: inset 0 0 0 1px var(--ui-border-color-dark);
|
||||
border: 2px solid transparent;
|
||||
border-radius: 12px;
|
||||
height: 135px;
|
||||
min-height: 135px;
|
||||
max-height: 250px;
|
||||
margin: 0 auto;
|
||||
padding: 5px;
|
||||
position: relative;
|
||||
@@ -36,6 +37,11 @@
|
||||
h1
|
||||
text-align: center
|
||||
color: var(--text-primary-color);
|
||||
max-width: 200px;
|
||||
max-height: 250px;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
hyphens: auto;
|
||||
|
||||
.series-details
|
||||
display: flex;
|
||||
|
||||
@@ -18,6 +18,7 @@ $headerRowHeight = 63px
|
||||
|
||||
.tableListHeaderTitle
|
||||
color: var(--text-secondary-color)
|
||||
max-width: 230px
|
||||
font-size: 22px
|
||||
font-weight: 300
|
||||
line-height: $headerRowHeight
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -3,6 +3,102 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [4.12.33](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.32...@ohif/viewer@4.12.33) (2022-08-31)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.12.32](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.31...@ohif/viewer@4.12.32) (2022-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.12.31](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.30...@ohif/viewer@4.12.31) (2022-08-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.12.30](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.29...@ohif/viewer@4.12.30) (2022-06-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.12.29](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.28...@ohif/viewer@4.12.29) (2022-06-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.12.28](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.27...@ohif/viewer@4.12.28) (2022-06-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.12.27](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.26...@ohif/viewer@4.12.27) (2022-06-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.12.26](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.25...@ohif/viewer@4.12.26) (2022-04-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.12.25](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.24...@ohif/viewer@4.12.25) (2022-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.12.24](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.23...@ohif/viewer@4.12.24) (2022-04-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.12.23](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.22...@ohif/viewer@4.12.23) (2022-03-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.12.22](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.21...@ohif/viewer@4.12.22) (2022-03-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.12.21](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.20...@ohif/viewer@4.12.21) (2022-03-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/viewer",
|
||||
"version": "4.12.21",
|
||||
"version": "4.12.33",
|
||||
"description": "OHIF Viewer",
|
||||
"author": "OHIF Contributors",
|
||||
"license": "MIT",
|
||||
@@ -47,18 +47,18 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@ohif/core": "^2.16.13",
|
||||
"@ohif/extension-cornerstone": "^2.12.7",
|
||||
"@ohif/extension-debugging": "^0.3.2",
|
||||
"@ohif/extension-dicom-html": "^1.3.18",
|
||||
"@ohif/core": "^2.16.24",
|
||||
"@ohif/extension-cornerstone": "^2.12.13",
|
||||
"@ohif/extension-debugging": "^0.3.3",
|
||||
"@ohif/extension-dicom-html": "^1.3.22",
|
||||
"@ohif/extension-dicom-microscopy": "^0.52.0",
|
||||
"@ohif/extension-dicom-pdf": "^1.1.2",
|
||||
"@ohif/extension-dicom-rt": "^0.7.8",
|
||||
"@ohif/extension-dicom-segmentation": "^0.7.8",
|
||||
"@ohif/extension-lesion-tracker": "^0.2.1",
|
||||
"@ohif/extension-vtk": "^1.12.18",
|
||||
"@ohif/extension-dicom-rt": "^0.7.12",
|
||||
"@ohif/extension-dicom-segmentation": "^0.7.12",
|
||||
"@ohif/extension-lesion-tracker": "^0.2.2",
|
||||
"@ohif/extension-vtk": "^1.12.29",
|
||||
"@ohif/i18n": "^0.53.0",
|
||||
"@ohif/ui": "^1.10.7",
|
||||
"@ohif/ui": "^1.10.10",
|
||||
"@tanem/react-nprogress": "^1.1.25",
|
||||
"classnames": "^2.2.6",
|
||||
"core-js": "^3.2.1",
|
||||
@@ -66,7 +66,7 @@
|
||||
"cornerstone-math": "^0.1.9",
|
||||
"cornerstone-tools": "^6.0.6",
|
||||
"cornerstone-wado-image-loader": "^4.1.0",
|
||||
"dcmjs": "0.19.4",
|
||||
"dcmjs": "0.19.9",
|
||||
"dicom-parser": "^1.8.11",
|
||||
"dicomweb-client": "^0.8.3",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -30,6 +30,7 @@ window.config = {
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Extensions should be able to suggest default values for these?
|
||||
// Or we can require that these be explicitly set
|
||||
hotkeys: [
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { measurements, utils } from '@ohif/core';
|
||||
|
||||
import { servicesManager } from './../../App.js';
|
||||
const { MeasurementApi } = measurements;
|
||||
const { studyMetadataManager } = utils;
|
||||
|
||||
@@ -19,6 +19,25 @@ export default function jumpToRowItem(
|
||||
timepointManagerState,
|
||||
options = { invertViewportTimepointsOrder: false, childToolKey: null }
|
||||
) {
|
||||
const viewports = viewportsState.layout.viewports;
|
||||
const activeViewportIndex = viewportsState.activeViewportIndex;
|
||||
const activeViewport = viewports[activeViewportIndex];
|
||||
if (activeViewport.vtk) {
|
||||
const error = new Error('Measurements are not supported by the MPR mode.');
|
||||
const { UINotificationService, LoggerService } = servicesManager.services;
|
||||
LoggerService.error({ error, message: error.message });
|
||||
UINotificationService.show({
|
||||
title: 'Measurements panel',
|
||||
message: error.message,
|
||||
type: 'warning',
|
||||
autoClose: true,
|
||||
});
|
||||
return {
|
||||
viewportSpecificData: [],
|
||||
layout: [], // TODO: if we need to change layout, we should return this here
|
||||
};
|
||||
}
|
||||
|
||||
const numViewports = viewportsState.layout.viewports.length;
|
||||
const numTimepoints = timepointManagerState.timepoints.length;
|
||||
const { measurements, timepoints } = timepointManagerState;
|
||||
|
||||
@@ -48,7 +48,7 @@ const mapDispatchToProps = (dispatch, ownProps) => {
|
||||
);
|
||||
document.dispatchEvent(selectionFired);
|
||||
});
|
||||
} else {
|
||||
} else if (Modality !== 'SR') {
|
||||
displaySet = displaySet.getSourceDisplaySet(ownProps.studyMetadata);
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ const mapDispatchToProps = (dispatch, ownProps) => {
|
||||
});
|
||||
}
|
||||
|
||||
if (displaySet.isModalitySupported === false) {
|
||||
if (displaySet.isSOPClassUIDSupported === false) {
|
||||
const error = new Error('Modality not supported');
|
||||
const message = 'Modality not supported';
|
||||
LoggerService.error({ error, message });
|
||||
|
||||
@@ -105,6 +105,11 @@ class Viewer extends Component {
|
||||
if (this.props.dialog) {
|
||||
this.props.dialog.dismissAll();
|
||||
}
|
||||
|
||||
document.removeEventListener(
|
||||
'segmentationLoadingError',
|
||||
this._updateThumbnails
|
||||
);
|
||||
}
|
||||
|
||||
retrieveTimepoints = filter => {
|
||||
@@ -212,6 +217,12 @@ class Viewer extends Component {
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener(
|
||||
'segmentationLoadingError',
|
||||
this._updateThumbnails.bind(this),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
@@ -251,10 +262,28 @@ class Viewer extends Component {
|
||||
const { currentTimepointId } = this;
|
||||
|
||||
this.timepointApi.retrieveTimepoints({ PatientID });
|
||||
this.measurementApi.retrieveMeasurements(PatientID, [currentTimepointId]);
|
||||
this.measurementApi
|
||||
.retrieveMeasurements(PatientID, [currentTimepointId])
|
||||
.then(() => {
|
||||
this._updateThumbnails();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_updateThumbnails() {
|
||||
const { studies, activeViewportIndex, viewports } = this.props;
|
||||
|
||||
const activeViewport = viewports[activeViewportIndex];
|
||||
const activeDisplaySetInstanceUID = activeViewport
|
||||
? activeViewport.displaySetInstanceUID
|
||||
: undefined;
|
||||
|
||||
this.setState({
|
||||
thumbnails: _mapStudiesToThumbnails(studies, activeDisplaySetInstanceUID),
|
||||
activeDisplaySetInstanceUID,
|
||||
});
|
||||
}
|
||||
|
||||
_getActiveViewport() {
|
||||
return this.props.viewports[this.props.activeViewportIndex];
|
||||
}
|
||||
@@ -461,9 +490,7 @@ const _checkForDerivedDisplaySets = async function(displaySet, study) {
|
||||
/**
|
||||
* Async function to check if there are any inconsistences in the series.
|
||||
*
|
||||
* For segmentation checks that the geometry is consistent with the source images:
|
||||
* 1) no frames out of plane;
|
||||
* 2) have the same width and height.
|
||||
* For segmentation returns any error during loading.
|
||||
*
|
||||
* For reconstructable 3D volume:
|
||||
* 1) Is series multiframe?
|
||||
@@ -477,10 +504,7 @@ const _checkForDerivedDisplaySets = async function(displaySet, study) {
|
||||
* @param {*object} displaySet
|
||||
* @returns {[string]} an array of strings containing the warnings
|
||||
*/
|
||||
const _checkForSeriesInconsistencesWarnings = async function(
|
||||
displaySet,
|
||||
studies
|
||||
) {
|
||||
const _checkForSeriesInconsistencesWarnings = async function(displaySet) {
|
||||
if (displaySet.inconsistencyWarnings) {
|
||||
// warnings already checked and cached in displaySet
|
||||
return displaySet.inconsistencyWarnings;
|
||||
@@ -543,101 +567,17 @@ const _checkForSeriesInconsistencesWarnings = async function(
|
||||
);
|
||||
}
|
||||
|
||||
if (displaySet.isModalitySupported === false) {
|
||||
inconsistencyWarnings.push('The datasets modality is not supported.');
|
||||
if (displaySet.isSOPClassUIDSupported === false) {
|
||||
inconsistencyWarnings.push('The datasets is not supported.');
|
||||
}
|
||||
displaySet.inconsistencyWarnings = inconsistencyWarnings;
|
||||
} else {
|
||||
const segMetadata = displaySet.metadata;
|
||||
if (!segMetadata) {
|
||||
return inconsistencyWarnings;
|
||||
}
|
||||
|
||||
const { referencedDisplaySet } = displaySet.getSourceDisplaySet(
|
||||
studies,
|
||||
false
|
||||
);
|
||||
if (!referencedDisplaySet) {
|
||||
return inconsistencyWarnings;
|
||||
}
|
||||
|
||||
const imageIds = referencedDisplaySet.images.map(image =>
|
||||
image.getImageId()
|
||||
);
|
||||
if (!imageIds || imageIds.length === 0) {
|
||||
return inconsistencyWarnings;
|
||||
}
|
||||
|
||||
for (
|
||||
let i = 0,
|
||||
groupsLen = segMetadata.PerFrameFunctionalGroupsSequence.length;
|
||||
i < groupsLen;
|
||||
++i
|
||||
) {
|
||||
const PerFrameFunctionalGroups =
|
||||
segMetadata.PerFrameFunctionalGroupsSequence[i];
|
||||
if (!PerFrameFunctionalGroups) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let SourceImageSequence = undefined;
|
||||
if (segMetadata.SourceImageSequence) {
|
||||
SourceImageSequence = segMetadata.SourceImageSequence[i];
|
||||
} else if (PerFrameFunctionalGroups.DerivationImageSequence) {
|
||||
SourceImageSequence =
|
||||
PerFrameFunctionalGroups.DerivationImageSequence.SourceImageSequence;
|
||||
}
|
||||
if (!SourceImageSequence) {
|
||||
if (inconsistencyWarnings.length === 0) {
|
||||
const warningMessage =
|
||||
'The segmentation ' +
|
||||
'has frames out of plane respect to the source images.';
|
||||
inconsistencyWarnings.push(warningMessage);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const { ReferencedSOPInstanceUID } = SourceImageSequence;
|
||||
|
||||
const imageId = imageIds.find(imageId => {
|
||||
const sopCommonModule = cornerstone.metaData.get(
|
||||
'sopCommonModule',
|
||||
imageId
|
||||
);
|
||||
if (!sopCommonModule) {
|
||||
return;
|
||||
}
|
||||
|
||||
return sopCommonModule.sopInstanceUID === ReferencedSOPInstanceUID;
|
||||
});
|
||||
|
||||
if (!imageId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const sourceImageMetadata = cornerstone.metaData.get('instance', imageId);
|
||||
if (
|
||||
segMetadata.Rows !== sourceImageMetadata.Rows ||
|
||||
segMetadata.Columns !== sourceImageMetadata.Columns
|
||||
) {
|
||||
const warningMessage =
|
||||
'The segmentation ' +
|
||||
'has frames with different geometry ' +
|
||||
'dimensions (Rows and Columns) respect to the source images.';
|
||||
inconsistencyWarnings.push(warningMessage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inconsistencyWarnings.length !== 0) {
|
||||
const warningMessage =
|
||||
'The segmentation format is not supported yet. ' +
|
||||
'The segmentation data (segments) could not be loaded.';
|
||||
inconsistencyWarnings.push(warningMessage);
|
||||
if (displaySet.loadError) {
|
||||
inconsistencyWarnings.push(displaySet.segLoadErrorMessagge);
|
||||
displaySet.inconsistencyWarnings = inconsistencyWarnings;
|
||||
}
|
||||
}
|
||||
|
||||
// cache the warnings
|
||||
displaySet.inconsistencyWarnings = inconsistencyWarnings;
|
||||
return inconsistencyWarnings;
|
||||
};
|
||||
|
||||
@@ -672,9 +612,30 @@ const _isDisplaySetActive = function(
|
||||
if (
|
||||
displaySet.Modality !== 'SEG' &&
|
||||
displaySet.Modality !== 'RTSTRUCT' &&
|
||||
displaySet.Modality !== 'RTDOSE'
|
||||
displaySet.Modality !== 'RTDOSE' &&
|
||||
displaySet.Modality !== 'SR'
|
||||
) {
|
||||
active = activeDisplaySetInstanceUID === displaySetInstanceUID;
|
||||
} else if (displaySet.Modality === 'SR') {
|
||||
active = activeDisplaySetInstanceUID === displaySetInstanceUID;
|
||||
|
||||
if (!active && displaySet.getSourceDisplaySet) {
|
||||
const referencedDisplaySet = displaySet.getSourceDisplaySet(
|
||||
studies,
|
||||
false
|
||||
);
|
||||
if (referencedDisplaySet && referencedDisplaySet.length !== 0) {
|
||||
for (let i = 0; i < referencedDisplaySet.length; i++) {
|
||||
if (
|
||||
referencedDisplaySet[i].displaySetInstanceUID ===
|
||||
activeDisplaySetInstanceUID
|
||||
) {
|
||||
active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (displaySet.getSourceDisplaySet) {
|
||||
if (displaySet.Modality === 'SEG') {
|
||||
const { referencedDisplaySet } = displaySet.getSourceDisplaySet(
|
||||
@@ -725,21 +686,19 @@ 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();
|
||||
} else if (displaySet.isSOPClassUIDSupported === false) {
|
||||
altImageText = displaySet.SOPClassUIDNaturalized;
|
||||
} else {
|
||||
altImageText = displaySet.Modality ? displaySet.Modality : 'UN';
|
||||
}
|
||||
|
||||
const hasWarnings = _checkForSeriesInconsistencesWarnings(
|
||||
displaySet,
|
||||
studies
|
||||
);
|
||||
const hasWarnings = _checkForSeriesInconsistencesWarnings(displaySet);
|
||||
|
||||
const hasDerivedDisplaySets = _checkForDerivedDisplaySets(
|
||||
displaySet,
|
||||
|
||||
@@ -154,13 +154,26 @@ class ViewerMain extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
const { referencedDisplaySet } = displaySet.getSourceDisplaySet(
|
||||
const {
|
||||
referencedDisplaySet,
|
||||
activatedLabelmapPromise,
|
||||
} = displaySet.getSourceDisplaySet(
|
||||
this.props.studies,
|
||||
true,
|
||||
onDisplaySetLoadFailureHandler
|
||||
);
|
||||
displaySet = referencedDisplaySet;
|
||||
} else {
|
||||
|
||||
activatedLabelmapPromise.then(activatedLabelmapIndex => {
|
||||
const selectionFired = new CustomEvent(
|
||||
'extensiondicomsegmentationsegselected',
|
||||
{
|
||||
detail: { activatedLabelmapIndex: activatedLabelmapIndex },
|
||||
}
|
||||
);
|
||||
document.dispatchEvent(selectionFired);
|
||||
});
|
||||
} else if (Modality !== 'SR') {
|
||||
displaySet = displaySet.getSourceDisplaySet(this.props.studies);
|
||||
}
|
||||
|
||||
@@ -177,7 +190,7 @@ class ViewerMain extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
if (displaySet.isModalitySupported === false) {
|
||||
if (displaySet.isSOPClassUIDSupported === false) {
|
||||
const error = new Error('Modality not supported');
|
||||
const message = 'Modality not supported';
|
||||
LoggerService.error({ error, message });
|
||||
|
||||
@@ -36,7 +36,7 @@ function DicomStorePickerModal({
|
||||
user,
|
||||
url,
|
||||
},
|
||||
onClose
|
||||
onClose,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.0.0"
|
||||
|
||||
"@babel/code-frame@^7.16.7":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789"
|
||||
integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.16.7"
|
||||
|
||||
"@babel/core@>=7.2.2", "@babel/core@^7.1.0", "@babel/core@^7.5.0", "@babel/core@^7.5.5":
|
||||
version "7.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.4.tgz#6ebd9fe00925f6c3e177bb726a188b5f578088ff"
|
||||
@@ -29,6 +36,15 @@
|
||||
semver "^5.4.1"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@babel/generator@^7.18.2":
|
||||
version "7.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.2.tgz#33873d6f89b21efe2da63fe554460f3df1c5880d"
|
||||
integrity sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==
|
||||
dependencies:
|
||||
"@babel/types" "^7.18.2"
|
||||
"@jridgewell/gen-mapping" "^0.3.0"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/generator@^7.4.0":
|
||||
version "7.8.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.8.tgz#cdcd58caab730834cee9eeadb729e833b625da3e"
|
||||
@@ -56,6 +72,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.0.0"
|
||||
|
||||
"@babel/helper-annotate-as-pure@^7.16.0":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862"
|
||||
integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==
|
||||
dependencies:
|
||||
"@babel/types" "^7.16.7"
|
||||
|
||||
"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0":
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f"
|
||||
@@ -102,6 +125,11 @@
|
||||
"@babel/types" "^7.5.5"
|
||||
lodash "^4.17.13"
|
||||
|
||||
"@babel/helper-environment-visitor@^7.18.2":
|
||||
version "7.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz#8a6d2dedb53f6bf248e31b4baf38739ee4a637bd"
|
||||
integrity sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==
|
||||
|
||||
"@babel/helper-explode-assignable-expression@^7.1.0":
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6"
|
||||
@@ -119,6 +147,14 @@
|
||||
"@babel/template" "^7.1.0"
|
||||
"@babel/types" "^7.0.0"
|
||||
|
||||
"@babel/helper-function-name@^7.17.9":
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12"
|
||||
integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==
|
||||
dependencies:
|
||||
"@babel/template" "^7.16.7"
|
||||
"@babel/types" "^7.17.0"
|
||||
|
||||
"@babel/helper-get-function-arity@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3"
|
||||
@@ -126,6 +162,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.0.0"
|
||||
|
||||
"@babel/helper-hoist-variables@^7.16.7":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246"
|
||||
integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==
|
||||
dependencies:
|
||||
"@babel/types" "^7.16.7"
|
||||
|
||||
"@babel/helper-hoist-variables@^7.4.4":
|
||||
version "7.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a"
|
||||
@@ -147,6 +190,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.0.0"
|
||||
|
||||
"@babel/helper-module-imports@^7.16.0":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437"
|
||||
integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==
|
||||
dependencies:
|
||||
"@babel/types" "^7.16.7"
|
||||
|
||||
"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4":
|
||||
version "7.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a"
|
||||
@@ -207,6 +257,13 @@
|
||||
"@babel/template" "^7.1.0"
|
||||
"@babel/types" "^7.0.0"
|
||||
|
||||
"@babel/helper-split-export-declaration@^7.16.7":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b"
|
||||
integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==
|
||||
dependencies:
|
||||
"@babel/types" "^7.16.7"
|
||||
|
||||
"@babel/helper-split-export-declaration@^7.4.4":
|
||||
version "7.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677"
|
||||
@@ -214,6 +271,11 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.4.4"
|
||||
|
||||
"@babel/helper-validator-identifier@^7.16.7":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad"
|
||||
integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.9.5":
|
||||
version "7.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80"
|
||||
@@ -247,11 +309,25 @@
|
||||
esutils "^2.0.2"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/highlight@^7.16.7":
|
||||
version "7.17.12"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351"
|
||||
integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.16.7"
|
||||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3":
|
||||
version "7.8.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.8.tgz#4c3b7ce36db37e0629be1f0d50a571d2f86f6cd4"
|
||||
integrity sha512-mO5GWzBPsPf6865iIbzNE0AvkKF3NE+2S3eRUpE+FE07BOAkXh6G+GW/Pj01hhXjve1WScbaIO4UlY1JKeqCcA==
|
||||
|
||||
"@babel/parser@^7.16.7", "@babel/parser@^7.18.5":
|
||||
version "7.18.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.5.tgz#337062363436a893a2d22faa60be5bb37091c83c"
|
||||
integrity sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==
|
||||
|
||||
"@babel/parser@^7.6.0", "@babel/parser@^7.6.3", "@babel/parser@^7.6.4":
|
||||
version "7.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.4.tgz#cb9b36a7482110282d5cb6dd424ec9262b473d81"
|
||||
@@ -736,6 +812,15 @@
|
||||
"@babel/parser" "^7.6.0"
|
||||
"@babel/types" "^7.6.0"
|
||||
|
||||
"@babel/template@^7.16.7":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155"
|
||||
integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.16.7"
|
||||
"@babel/parser" "^7.16.7"
|
||||
"@babel/types" "^7.16.7"
|
||||
|
||||
"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.2", "@babel/traverse@^7.6.3":
|
||||
version "7.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.3.tgz#66d7dba146b086703c0fb10dd588b7364cec47f9"
|
||||
@@ -751,6 +836,22 @@
|
||||
globals "^11.1.0"
|
||||
lodash "^4.17.13"
|
||||
|
||||
"@babel/traverse@^7.4.5":
|
||||
version "7.18.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.5.tgz#94a8195ad9642801837988ab77f36e992d9a20cd"
|
||||
integrity sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.16.7"
|
||||
"@babel/generator" "^7.18.2"
|
||||
"@babel/helper-environment-visitor" "^7.18.2"
|
||||
"@babel/helper-function-name" "^7.17.9"
|
||||
"@babel/helper-hoist-variables" "^7.16.7"
|
||||
"@babel/helper-split-export-declaration" "^7.16.7"
|
||||
"@babel/parser" "^7.18.5"
|
||||
"@babel/types" "^7.18.4"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0", "@babel/types@^7.6.3":
|
||||
version "7.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.3.tgz#3f07d96f854f98e2fbd45c64b0cb942d11e8ba09"
|
||||
@@ -760,6 +861,14 @@
|
||||
lodash "^4.17.13"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.16.7", "@babel/types@^7.17.0", "@babel/types@^7.18.2", "@babel/types@^7.18.4":
|
||||
version "7.18.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.4.tgz#27eae9b9fd18e9dccc3f9d6ad051336f307be354"
|
||||
integrity sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.16.7"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.8.7":
|
||||
version "7.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444"
|
||||
@@ -882,11 +991,23 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413"
|
||||
integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==
|
||||
|
||||
"@emotion/is-prop-valid@^1.1.0":
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.1.3.tgz#f0907a416368cf8df9e410117068e20fe87c0a3a"
|
||||
integrity sha512-RFg04p6C+1uO19uG8N+vqanzKqiM9eeV1LDOG3bmkYmuOj7NbKNlFC/4EZq5gnwAIlcC/jOT24f8Td0iax2SXA==
|
||||
dependencies:
|
||||
"@emotion/memoize" "^0.7.4"
|
||||
|
||||
"@emotion/memoize@0.7.4":
|
||||
version "0.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
|
||||
integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
|
||||
|
||||
"@emotion/memoize@^0.7.4":
|
||||
version "0.7.5"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50"
|
||||
integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==
|
||||
|
||||
"@emotion/serialize@^0.11.15", "@emotion/serialize@^0.11.16":
|
||||
version "0.11.16"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.16.tgz#dee05f9e96ad2fb25a5206b6d759b2d1ed3379ad"
|
||||
@@ -903,12 +1024,12 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.4.tgz#894374bea39ec30f489bbfc3438192b9774d32e5"
|
||||
integrity sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==
|
||||
|
||||
"@emotion/stylis@0.8.5":
|
||||
"@emotion/stylis@0.8.5", "@emotion/stylis@^0.8.4":
|
||||
version "0.8.5"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04"
|
||||
integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==
|
||||
|
||||
"@emotion/unitless@0.7.5":
|
||||
"@emotion/unitless@0.7.5", "@emotion/unitless@^0.7.4":
|
||||
version "0.7.5"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
|
||||
integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
|
||||
@@ -1213,6 +1334,38 @@
|
||||
"@types/istanbul-reports" "^1.1.1"
|
||||
"@types/yargs" "^13.0.0"
|
||||
|
||||
"@jridgewell/gen-mapping@^0.3.0":
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9"
|
||||
integrity sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==
|
||||
dependencies:
|
||||
"@jridgewell/set-array" "^1.0.0"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
|
||||
"@jridgewell/resolve-uri@^3.0.3":
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe"
|
||||
integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==
|
||||
|
||||
"@jridgewell/set-array@^1.0.0":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea"
|
||||
integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==
|
||||
|
||||
"@jridgewell/sourcemap-codec@^1.4.10":
|
||||
version "1.4.13"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c"
|
||||
integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==
|
||||
|
||||
"@jridgewell/trace-mapping@^0.3.9":
|
||||
version "0.3.13"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea"
|
||||
integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==
|
||||
dependencies:
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@js.properties/properties@0.4.0":
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@js.properties/properties/-/properties-0.4.0.tgz#3f98b784ab6fe9b31fd3c1637fedbfa2ff320185"
|
||||
@@ -3454,6 +3607,17 @@ babel-plugin-module-resolver@^3.2.0:
|
||||
reselect "^3.0.1"
|
||||
resolve "^1.4.0"
|
||||
|
||||
"babel-plugin-styled-components@>= 1.12.0":
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz#c81ef34b713f9da2b7d3f5550df0d1e19e798086"
|
||||
integrity sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.16.0"
|
||||
"@babel/helper-module-imports" "^7.16.0"
|
||||
babel-plugin-syntax-jsx "^6.18.0"
|
||||
lodash "^4.17.11"
|
||||
picomatch "^2.3.0"
|
||||
|
||||
babel-plugin-syntax-jsx@^6.18.0:
|
||||
version "6.18.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
|
||||
@@ -4045,6 +4209,11 @@ camelcase@^5.0.0, camelcase@^5.3.1:
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||
|
||||
camelize@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b"
|
||||
integrity sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg==
|
||||
|
||||
caniuse-api@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
|
||||
@@ -5096,6 +5265,11 @@ css-blank-pseudo@^0.1.4:
|
||||
dependencies:
|
||||
postcss "^7.0.5"
|
||||
|
||||
css-color-keywords@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
|
||||
integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==
|
||||
|
||||
css-color-names@0.0.4, css-color-names@^0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
|
||||
@@ -5174,6 +5348,15 @@ css-select@^2.0.0:
|
||||
domutils "^1.7.0"
|
||||
nth-check "^1.0.2"
|
||||
|
||||
css-to-react-native@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.0.0.tgz#62dbe678072a824a689bcfee011fc96e02a7d756"
|
||||
integrity sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==
|
||||
dependencies:
|
||||
camelize "^1.0.0"
|
||||
css-color-keywords "^1.0.0"
|
||||
postcss-value-parser "^4.0.2"
|
||||
|
||||
css-tree@1.0.0-alpha.29:
|
||||
version "1.0.0-alpha.29"
|
||||
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39"
|
||||
@@ -5449,10 +5632,10 @@ dateformat@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
|
||||
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
|
||||
|
||||
dcmjs@0.19.4:
|
||||
version "0.19.4"
|
||||
resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.19.4.tgz#b2ce1cc1e672ead3fba12bafd2e8a655b398601a"
|
||||
integrity sha512-ZpOsuyBMcmDVPo0EtqztRGu1ARKMqIfbJGbtDxmBwxeE5SEHMQJvrZHhyLoxuS10R3w+jL2SJ0r7Dn9aSDZH1w==
|
||||
dcmjs@0.19.9:
|
||||
version "0.19.9"
|
||||
resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.19.9.tgz#be500101b1f75a28ea9eb7ef845a8ed197355e76"
|
||||
integrity sha512-V+0tND+SPX5e7WFeLzeoooaTsZbiKmEP2i3AyERsojaXXfaDV5E+pta5IqId4Ok1yfRT5qfTFwLGstGT6nLplA==
|
||||
dependencies:
|
||||
"@babel/polyfill" "^7.8.3"
|
||||
"@babel/runtime" "^7.8.4"
|
||||
@@ -7864,6 +8047,13 @@ hoist-non-react-statics@^2.3.1:
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
|
||||
integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==
|
||||
|
||||
hoist-non-react-statics@^3.0.0:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||
dependencies:
|
||||
react-is "^16.7.0"
|
||||
|
||||
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.2.1, hoist-non-react-statics@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b"
|
||||
@@ -11810,7 +12000,7 @@ picomatch@^2.0.4, picomatch@^2.0.5:
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6"
|
||||
integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==
|
||||
|
||||
picomatch@^2.2.1, picomatch@^2.2.3:
|
||||
picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
@@ -15204,6 +15394,22 @@ style-search@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902"
|
||||
integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=
|
||||
|
||||
styled-components@^5.3.5:
|
||||
version "5.3.5"
|
||||
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.5.tgz#a750a398d01f1ca73af16a241dec3da6deae5ec4"
|
||||
integrity sha512-ndETJ9RKaaL6q41B69WudeqLzOpY1A/ET/glXkNZ2T7dPjPqpPCXXQjDFYZWwNnE5co0wX+gTCqx9mfxTmSIPg==
|
||||
dependencies:
|
||||
"@babel/helper-module-imports" "^7.0.0"
|
||||
"@babel/traverse" "^7.4.5"
|
||||
"@emotion/is-prop-valid" "^1.1.0"
|
||||
"@emotion/stylis" "^0.8.4"
|
||||
"@emotion/unitless" "^0.7.4"
|
||||
babel-plugin-styled-components ">= 1.12.0"
|
||||
css-to-react-native "^3.0.0"
|
||||
hoist-non-react-statics "^3.0.0"
|
||||
shallowequal "^1.1.0"
|
||||
supports-color "^5.5.0"
|
||||
|
||||
stylehacks@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5"
|
||||
|
||||
Reference in new issue
Block a user