Compare commits

..
578 changed files with 10729 additions and 3279 deletions

No files matched your search

+1 -2
View File
@@ -1,6 +1,5 @@
server {
listen ${PORT} default_server;
listen [::]:${PORT} default_server;
listen ${PORT};
location / {
root /usr/share/nginx/html;
index index.html index.htm;
@@ -1,22 +0,0 @@
server {
listen ${SSL_PORT} ssl http2 default_server;
listen [::]:${SSL_PORT} ssl http2 default_server;
ssl_certificate /etc/ssl/certs/ssl-certificate.crt;
ssl_certificate_key /etc/ssl/private/ssl-private-key.key;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
add_header Cross-Origin-Opener-Policy same-origin;
add_header Cross-Origin-Embedder-Policy require-corp;
add_header Cross-Origin-Resource-Policy same-origin;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
+1 -11
View File
@@ -1,16 +1,6 @@
#!/bin/sh
if [ -n "$SSL_PORT" ]
then
envsubst '${SSL_PORT}:${PORT}' < /usr/src/default.ssl.conf.template > /etc/nginx/conf.d/default.conf
else
envsubst '${PORT}' < /usr/src/default.conf.template > /etc/nginx/conf.d/default.conf
fi
if [ -n "$APP_CONFIG" ]
then
echo "$APP_CONFIG" > /usr/share/nginx/html/app-config.js
fi
envsubst '${PORT}' < /usr/src/default.conf.template > /etc/nginx/conf.d/default.conf
if [ -n "$CLIENT_ID" ] || [ -n "$HEALTHCARE_API_ENDPOINT" ]
then
+9
View File
@@ -73,6 +73,15 @@ module.exports = (env, argv, { SRC_DIR, ENTRY }) => {
children: false,
warnings: true,
},
devServer: {
open: true,
port: 3000,
historyApiFallback: true,
headers: {
'Cross-Origin-Embedder-Policy': 'require-corp',
'Cross-Origin-Opener-Policy': 'same-origin',
},
},
cache: {
type: 'filesystem',
},
+1 -6
View File
@@ -61,7 +61,7 @@ RUN yarn run build
# Stage 3: Bundle the built application into a Docker container
# which runs Nginx using Alpine Linux
FROM nginxinc/nginx-unprivileged:1.25-alpine as final
FROM nginxinc/nginx-unprivileged:1.23.1-alpine as final
#RUN apk add --no-cache bash
ENV PORT=80
RUN rm /etc/nginx/conf.d/default.conf
@@ -69,10 +69,5 @@ USER nginx
COPY --chown=nginx:nginx .docker/Viewer-v3.x /usr/src
RUN chmod 777 /usr/src/entrypoint.sh
COPY --from=builder /usr/src/app/platform/app/dist /usr/share/nginx/html
# In entrypoint.sh, app-config.js might be overwritten, so chmod it to be writeable.
# The nginx user cannot chmod it, so change to root.
USER root
RUN chmod 666 /usr/share/nginx/html/app-config.js
USER nginx
ENTRYPOINT ["/usr/src/entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]
+22 -12
View File
@@ -17,6 +17,10 @@ provided by the <a href="https://ohif.org/">Open Health Imaging Foundation (OHIF
<div align="center">
📰 <a href="https://ohif.org/news/"><strong>Join OHIF Newsletter</strong></a> 📰
</div>
<div align="center">
📰 <a href="https://ohif.org/news/"><strong>Join OHIF Newsletter</strong></a> 📰
</div>
<hr />
@@ -34,16 +38,7 @@ provided by the <a href="https://ohif.org/">Open Health Imaging Foundation (OHIF
<!-- [![All Contributors](https://img.shields.io/badge/all_contributors-10-orange.svg?style=flat-square)](#contributors) -->
<!-- prettier-ignore-end -->
| | | |
| :-: | :--- | :--- |
| <img src="platform/docs/docs/assets/img/demo-measurements.jpg" alt="Measurement tracking" width="350"/> | Measurement Tracking | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5) |
| <img src="platform/docs/docs/assets/img/demo-segmentation.png" alt="Segmentations" width="350"/> | Labelmap Segmentations | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046) |
| <img src="platform/docs/docs/assets/img/demo-ptct.png" alt="Hanging Protocols" width="350"/> | Fusion and Custom Hanging protocols | [Demo](https://viewer.ohif.org/tmtv?StudyInstanceUIDs=1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463) |
| <img src="platform/docs/docs/assets/img/demo-microscopy.png" alt="Microscopy" width="350"/> | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.275741864483510678566144889372061815320) |
| <img src="platform/docs/docs/assets/img/demo-volumeRendering.png" alt="Volume Rendering" width="350"/> | Volume Rendering | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingprotocolId=mprAnd3DVolumeViewport) |
![Alt text](platform/docs/docs/assets/img/OHIF-Viewer.jpg)
## About
@@ -90,14 +85,17 @@ forking).
### Support
We offer support through
[GitHub Issues](https://github.com/OHIF/Viewers/issues/new/choose). You can:
- [Report a Bug 🐛](https://github.com/OHIF/Viewers/issues/new?assignees=&labels=Community%3A+Report+%3Abug%3A%2CAwaiting+Reproduction&projects=&template=bug-report.yml&title=%5BBug%5D+)
- [Request a Feature 🚀](https://github.com/OHIF/Viewers/issues/new?assignees=&labels=Community%3A+Request+%3Ahand%3A&projects=&template=feature-request.yml&title=%5BFeature+Request%5D+)
- [Ask a Question 🤗](community.ohif.org)
- [Slack Channel](https://join.slack.com/t/cornerstonejs/shared_invite/zt-1r8xb2zau-dOxlD6jit3TN0Uwf928w9Q)
For commercial support, academic collaborations, and answers to common
questions; please use [Get Support](https://ohif.org/get-support/) to contact
us.
questions; please read our
[documented FAQ](https://docs.ohif.org/faq/index.html#does-ohif-offer-commercial-support).
## Developing
@@ -130,6 +128,9 @@ Here is a schematic representation of our development workflow:
### Requirements
- [Yarn 1.17.3+](https://yarnpkg.com/en/docs/install)
@@ -221,6 +222,15 @@ you'll see the following:
└── README.md # This file
```
Want to better understand why and how we've structured this repository? Read
more about it in our [Architecture Documentation][ohif-architecture].
| Name | Description | Links |
| ---------------------------------------------------- | ----------------------------------------------------- | ---------------------- |
| [@ohif/extension-cornerstone][extension-cornerstone] | 2D image viewing, annotation, and segementation tools | [NPM][cornerstone-npm] |
## Acknowledgments
To acknowledge the OHIF Viewer in an academic publication, please cite
+1 -1
View File
@@ -1 +1 @@
7d286a07f2141bf8b8b85ca9d9b5eb3c0d7fc996
1d38fe30a490010c7de487c7a0b1a5bfe3bc75a4
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-rt",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "DICOM RT read workflow",
"author": "OHIF",
"license": "MIT",
@@ -31,10 +31,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/extension-cornerstone": "3.7.0-beta.32",
"@ohif/extension-default": "3.7.0-beta.32",
"@ohif/i18n": "3.7.0-beta.32",
"@ohif/core": "3.6.0",
"@ohif/extension-cornerstone": "3.6.0",
"@ohif/extension-default": "3.6.0",
"@ohif/i18n": "3.6.0",
"prop-types": "^15.6.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
@@ -181,6 +181,12 @@ export default async function loadRTStruct(
ContourGeometricType,
} = ContourSequenceArray[c];
const sopInstanceUID = ContourImageSequence.ReferencedSOPInstanceUID;
const imageId = _getImageId(imageIdSopInstanceUidPairs, sopInstanceUID);
if (!imageId) {
continue;
}
let isSupported = false;
const points = [];
@@ -1,4 +1,3 @@
import { ButtonEnums } from '@ohif/ui';
import hydrateRTDisplaySet from './_hydrateRT';
const RESPONSE = {
@@ -39,12 +38,12 @@ function _askHydrate(uiViewportDialogService, viewportIndex) {
const message = 'Do you want to open this Segmentation?';
const actions = [
{
type: ButtonEnums.type.secondary,
type: 'secondary',
text: 'No',
value: RESPONSE.CANCEL,
},
{
type: ButtonEnums.type.primary,
type: 'primary',
text: 'Yes',
value: RESPONSE.HYDRATE_SEG,
},
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-seg",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "DICOM SEG read workflow",
"author": "OHIF",
"license": "MIT",
@@ -31,10 +31,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/extension-cornerstone": "3.7.0-beta.32",
"@ohif/extension-default": "3.7.0-beta.32",
"@ohif/i18n": "3.7.0-beta.32",
"@ohif/core": "3.6.0",
"@ohif/extension-cornerstone": "3.6.0",
"@ohif/extension-default": "3.6.0",
"@ohif/i18n": "3.6.0",
"prop-types": "^15.6.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
@@ -1,5 +1,5 @@
import React from 'react';
import { Input, Dialog, ButtonEnums } from '@ohif/ui';
import { Input, Dialog } from '@ohif/ui';
function callInputDialog(uiDialogService, label, callback) {
const dialogId = 'enter-segment-label';
@@ -29,8 +29,8 @@ function callInputDialog(uiDialogService, label, callback) {
noCloseButton: true,
onClose: () => uiDialogService.dismiss({ id: dialogId }),
actions: [
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Confirm', type: ButtonEnums.type.primary },
{ id: 'cancel', text: 'Cancel', type: 'primary' },
{ id: 'save', text: 'Confirm', type: 'secondary' },
],
onSubmit: onSubmitHandler,
body: ({ value, setValue }) => {
@@ -1,4 +1,3 @@
import { ButtonEnums } from '@ohif/ui';
import hydrateSEGDisplaySet from './_hydrateSEG';
const RESPONSE = {
@@ -7,7 +6,11 @@ const RESPONSE = {
HYDRATE_SEG: 5,
};
function promptHydrateSEG({ servicesManager, segDisplaySet, viewportIndex }) {
function promptHydrateSEG({
servicesManager,
segDisplaySet,
viewportIndex,
}) {
const { uiViewportDialogService } = servicesManager.services;
return new Promise(async function(resolve, reject) {
@@ -33,12 +36,12 @@ function _askHydrate(uiViewportDialogService, viewportIndex) {
const message = 'Do you want to open this Segmentation?';
const actions = [
{
type: ButtonEnums.type.secondary,
type: 'secondary',
text: 'No',
value: RESPONSE.CANCEL,
},
{
type: ButtonEnums.type.primary,
type: 'primary',
text: 'Yes',
value: RESPONSE.HYDRATE_SEG,
},
@@ -71,8 +71,7 @@ function OHIFCornerstoneSEGViewport(props) {
const referencedDisplaySet = segDisplaySet.getReferenceDisplaySet();
const referencedDisplaySetMetadata = _getReferencedDisplaySetMetadata(
referencedDisplaySet,
segDisplaySet
referencedDisplaySet
);
referencedDisplaySetRef.current = {
@@ -344,10 +343,10 @@ function OHIFCornerstoneSEGViewport(props) {
patientSex: PatientSex || '',
patientAge: PatientAge || '',
MRN: PatientID || '',
thickness: SliceThickness ? `${parseFloat(SliceThickness).toFixed(2)}mm` : '',
thickness: SliceThickness ? `${SliceThickness.toFixed(2)}mm` : '',
spacing:
SpacingBetweenSlices !== undefined
? `${parseFloat(SpacingBetweenSlices).toFixed(2)}mm`
? `${SpacingBetweenSlices.toFixed(2)}mm`
: '',
scanner: ManufacturerModelName || '',
},
@@ -382,28 +381,20 @@ OHIFCornerstoneSEGViewport.defaultProps = {
customProps: {},
};
function _getReferencedDisplaySetMetadata(referencedDisplaySet, segDisplaySet) {
const {
SharedFunctionalGroupsSequence: [SharedFunctionalGroup],
} = segDisplaySet.instance;
const {
PixelMeasuresSequence: [PixelMeasures],
} = SharedFunctionalGroup;
const { SpacingBetweenSlices, SliceThickness } = PixelMeasures;
function _getReferencedDisplaySetMetadata(referencedDisplaySet) {
const image0 = referencedDisplaySet.images[0];
const referencedDisplaySetMetadata = {
PatientID: image0.PatientID,
PatientName: image0.PatientName,
PatientSex: image0.PatientSex,
PatientAge: image0.PatientAge,
SliceThickness: image0.SliceThickness || SliceThickness,
SliceThickness: image0.SliceThickness,
StudyDate: image0.StudyDate,
SeriesDescription: image0.SeriesDescription,
SeriesInstanceUID: image0.SeriesInstanceUID,
SeriesNumber: image0.SeriesNumber,
ManufacturerModelName: image0.ManufacturerModelName,
SpacingBetweenSlices: image0.SpacingBetweenSlices || SpacingBetweenSlices,
SpacingBetweenSlices: image0.SpacingBetweenSlices,
};
return referencedDisplaySetMetadata;
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-sr",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "OHIF extension for an SR Cornerstone Viewport",
"author": "OHIF",
"license": "MIT",
@@ -32,10 +32,10 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/extension-cornerstone": "3.7.0-beta.32",
"@ohif/extension-measurement-tracking": "3.7.0-beta.32",
"@ohif/ui": "3.7.0-beta.32",
"@ohif/core": "3.6.0",
"@ohif/extension-cornerstone": "3.6.0",
"@ohif/extension-measurement-tracking": "3.6.0",
"@ohif/ui": "3.6.0",
"dcmjs": "^0.29.5",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
@@ -44,9 +44,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^1.4.1",
"@cornerstonejs/core": "^1.4.1",
"@cornerstonejs/tools": "^1.4.1",
"@cornerstonejs/adapters": "^1.1.0",
"@cornerstonejs/core": "^1.1.0",
"@cornerstonejs/tools": "^1.1.0",
"classnames": "^2.3.2"
}
}
@@ -225,7 +225,6 @@ function OHIFCornerstoneSRViewport(props) {
}}
onElementEnabled={onElementEnabled}
initialImageIndex={initialImageIndex}
isJumpToMeasurementDisabled={true}
></Component>
);
}, [activeImageDisplaySetData, viewportIndex, measurementSelected]);
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "OHIF extension for Cornerstone",
"author": "OHIF",
"license": "MIT",
@@ -36,9 +36,9 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2",
"@cornerstonejs/codec-openjph": "^2.4.2",
"@cornerstonejs/dicom-image-loader": "^1.4.1",
"@ohif/core": "3.7.0-beta.32",
"@ohif/ui": "3.7.0-beta.32",
"@cornerstonejs/dicom-image-loader": "^0.6.8",
"@ohif/core": "3.6.0",
"@ohif/ui": "3.6.0",
"dcmjs": "^0.29.6",
"dicom-parser": "^1.8.21",
"hammerjs": "^2.0.8",
@@ -52,10 +52,10 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^1.4.1",
"@cornerstonejs/core": "^1.4.1",
"@cornerstonejs/streaming-image-volume-loader": "^1.4.1",
"@cornerstonejs/tools": "^1.4.1",
"@cornerstonejs/adapters": "^1.1.0",
"@cornerstonejs/core": "^1.1.0",
"@cornerstonejs/streaming-image-volume-loader": "^1.1.0",
"@cornerstonejs/tools": "^1.1.0",
"@kitware/vtk.js": "27.3.1",
"html2canvas": "^1.4.1",
"lodash.debounce": "4.0.8",
@@ -119,7 +119,6 @@ const OHIFCornerstoneViewport = React.memo(props => {
servicesManager,
onElementEnabled,
onElementDisabled,
isJumpToMeasurementDisabled,
// Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation
// of the imageData in the OHIFCornerstoneViewport. This prop is used
// to set the initial state of the viewport's first image to render
@@ -455,10 +454,6 @@ const OHIFCornerstoneViewport = React.memo(props => {
* the cache for jumping to see if there is any jump queued, then we jump to the correct slice.
*/
useEffect(() => {
if (isJumpToMeasurementDisabled) {
return;
}
const unsubscribeFromJumpToMeasurementEvents = _subscribeToJumpToMeasurementEvents(
measurementService,
displaySetService,
@@ -721,10 +716,6 @@ function _jumpToMeasurement(
// Component displayName
OHIFCornerstoneViewport.displayName = 'OHIFCornerstoneViewport';
OHIFCornerstoneViewport.defaultProps = {
isJumpToMeasurementDisabled: false,
};
OHIFCornerstoneViewport.propTypes = {
viewportIndex: PropTypes.number.isRequired,
displaySets: PropTypes.array.isRequired,
@@ -733,7 +724,6 @@ OHIFCornerstoneViewport.propTypes = {
displaySetOptions: PropTypes.arrayOf(PropTypes.any),
servicesManager: PropTypes.object.isRequired,
onElementEnabled: PropTypes.func,
isJumpToMeasurementDisabled: PropTypes.bool,
// Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation
// of the imageData in the OHIFCornerstoneViewport. This prop is used
// to set the initial state of the viewport's first image to render
@@ -379,7 +379,7 @@ function _getViewportInstance(viewportData, imageIndex) {
if (viewportData.viewportType === Enums.ViewportType.STACK) {
imageId = viewportData.data.imageIds[imageIndex];
} else if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC) {
const volumes = viewportData.data;
const volumes = viewportData.volumes;
if (volumes && volumes.length == 1) {
const volume = volumes[0];
imageId = volume.imageIds[imageIndex];
+5 -3
View File
@@ -457,9 +457,11 @@ function commandsModule({
const { viewport } = enabledElement;
const { invert } = viewport.getProperties();
viewport.setProperties({ invert: !invert });
viewport.render();
if (viewport instanceof StackViewport) {
const { invert } = viewport.getProperties();
viewport.setProperties({ invert: !invert });
viewport.render();
}
},
resetViewport: () => {
const enabledElement = _getActiveViewportEnabledElement();
@@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
import classNames from 'classnames';
import DicomFileUploader from '../../utils/DicomFileUploader';
import DicomUploadProgress from './DicomUploadProgress';
import { Button, ButtonEnums } from '@ohif/ui';
import { Button } from '@ohif/ui';
import './DicomUpload.css';
type DicomUploadProps = {
@@ -46,7 +46,12 @@ function DicomUpload({
<Dropzone onDrop={onDrop} noDrag>
{({ getRootProps, getInputProps }) => (
<div {...getRootProps()}>
<Button disabled={false} onClick={() => {}}>
<Button
variant="contained"
color="primary"
disabled={false}
onClick={() => {}}
>
{'Add files'}
<input {...getInputProps()} />
</Button>
@@ -57,7 +62,9 @@ function DicomUpload({
{({ getRootProps, getInputProps }) => (
<div {...getRootProps()}>
<Button
type={ButtonEnums.type.secondary}
variant="contained"
color="primaryDark"
border="primaryActive"
disabled={false}
onClick={() => {}}
>
@@ -308,7 +308,13 @@ function DicomUploadProgress({
} ${
dicomFileUploaderArr.length > 1 ? 'files' : 'file'
} completed.`}</span>
<Button disabled={false} className="ml-auto" onClick={onComplete}>
<Button
variant="contained"
color="primary"
disabled={false}
className="ml-auto"
onClick={onComplete}
>
{'Close'}
</Button>
</>
@@ -27,6 +27,7 @@ const DicomUploadProgressItem = memo(
const [failedReason, setFailedReason] = useState('');
const [status, setStatus] = useState(dicomFileUploader.getStatus());
console.info(`${dicomFileUploader.getFileId()}`);
const isComplete = useCallback(() => {
return (
status === UploadStatus.Failed ||
+1
View File
@@ -24,6 +24,7 @@ import { toolNames } from './initCornerstoneTools';
import { getEnabledElement, reset as enabledElementReset } from './state';
import dicomLoaderService from './utils/dicomLoaderService';
import getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement';
import { registerColormap } from './utils/colormap/transferFunctionHelpers';
import { id } from './id';
import * as csWADOImageLoader from './initWADOImageLoader.js';
+5 -3
View File
@@ -26,7 +26,6 @@ import nthLoader from './utils/nthLoader';
import interleaveTopToBottom from './utils/interleaveTopToBottom';
import initContextMenu from './initContextMenu';
import initDoubleClick from './initDoubleClick';
import { CornerstoneServices } from './types';
// TODO: Cypress tests are currently grabbing this from the window?
window.cornerstone = cornerstone;
@@ -70,7 +69,10 @@ export default async function init({
const {
userAuthenticationService,
measurementService,
customizationService,
displaySetService,
uiDialogService,
uiModalService,
uiNotificationService,
cineService,
@@ -79,7 +81,7 @@ export default async function init({
toolGroupService,
viewportGridService,
stateSyncService,
} = servicesManager.services as CornerstoneServices;
} = servicesManager.services;
window.services = servicesManager.services;
window.extensionManager = extensionManager;
@@ -164,7 +166,7 @@ export default async function init({
prefetch: appConfig?.maxNumRequests?.prefetch || 10,
};
initWADOImageLoader(userAuthenticationService, appConfig, extensionManager);
initWADOImageLoader(userAuthenticationService, appConfig);
/* Measurement Service */
this.measurementServiceSource = connectToolsToMeasurementService(
@@ -5,7 +5,7 @@ import dicomImageLoader, {
webWorkerManager,
} from '@cornerstonejs/dicom-image-loader';
import dicomParser from 'dicom-parser';
import { errorHandler, utils } from '@ohif/core';
import { errorHandler } from '@ohif/core';
const { registerVolumeLoader } = volumeLoader;
@@ -35,8 +35,7 @@ function initWebWorkers(appConfig) {
export default function initWADOImageLoader(
userAuthenticationService,
appConfig,
extensionManager
appConfig
) {
dicomImageLoader.external.cornerstone = cornerstone;
dicomImageLoader.external.dicomParser = dicomParser;
@@ -56,18 +55,18 @@ export default function initWADOImageLoader(
convertFloatPixelDataToInt: false,
},
beforeSend: function(xhr) {
//TODO should be removed in the future and request emitted by DicomWebDataSource
const sourceConfig =
extensionManager.getActiveDataSource()?.[0].getConfig() ?? {};
const headers = userAuthenticationService.getAuthorizationHeader();
const acceptHeader = utils.generateAcceptHeader(
sourceConfig.acceptHeader,
sourceConfig.requestTransferSyntaxUID,
sourceConfig.omitQuotationForMultipartRequest
);
// Request:
// JPEG-LS Lossless (1.2.840.10008.1.2.4.80) if available, otherwise accept
// whatever transfer-syntax the origin server provides.
// For now we use image/jls and image/x-jls because some servers still use the old type
// http://dicom.nema.org/medical/dicom/current/output/html/part18.html
const xhrRequestHeaders = {
Accept: acceptHeader,
Accept: appConfig.omitQuotationForMultipartRequest
? 'multipart/related; type=application/octet-stream'
: 'multipart/related; type="application/octet-stream"',
// 'multipart/related; type="image/x-jls", multipart/related; type="image/jls"; transfer-syntax="1.2.840.10008.1.2.4.80", multipart/related; type="image/x-jls", multipart/related; type="application/octet-stream"; transfer-syntax=*',
};
if (headers) {
@@ -117,7 +117,7 @@ class SegmentationService extends PubSubService {
* -- opacity: the opacity of the segment
* -- visibility: the visibility of the segment (boolean)
* -- isLocked: whether the segment is locked for editing
* -- active: whether the segment is currently the active segment to be edited
* -- active: whether the segment is currently the active segment to be edited or not
*/
public addSegment(
segmentationId: string,
@@ -542,7 +542,6 @@ class SegmentationService extends PubSubService {
id: segmentationId,
displaySetInstanceUID: segDisplaySet.displaySetInstanceUID,
type: representationType,
label: segDisplaySet.SeriesDescription,
representationData: {
[LABELMAP]: {
volumeId: segmentationId,
@@ -790,7 +789,6 @@ class SegmentationService extends PubSubService {
id: segmentationId,
displaySetInstanceUID: rtDisplaySetUID,
type: representationType,
label: rtDisplaySet.SeriesDescription,
representationData: {
[CONTOUR]: {
geometryIds,
@@ -818,54 +816,45 @@ class SegmentationService extends PubSubService {
const segmentsCachedStats = {};
const initializeContour = async rtStructData => {
const { data, id, color, segmentIndex, geometryId } = rtStructData;
// catch error instead of failing to allow loading to continue
try {
const geometry = await geometryLoader.createAndCacheGeometry(
geometryId,
{
geometryData: {
data,
id,
color,
frameOfReferenceUID: structureSet.frameOfReferenceUID,
segmentIndex,
},
type: csEnums.GeometryType.CONTOUR,
}
);
const contourSet = geometry.data;
const centroid = contourSet.getCentroid();
segmentsCachedStats[segmentIndex] = {
center: { world: centroid },
modifiedTime: rtDisplaySet.SeriesDate, // we use the SeriesDate as the modifiedTime since this is the first time we are creating the segmentation
};
segmentation.segments[segmentIndex] = {
label: id,
segmentIndex,
const geometry = await geometryLoader.createAndCacheGeometry(geometryId, {
geometryData: {
data,
id,
color,
...SEGMENT_CONSTANT,
};
frameOfReferenceUID: structureSet.frameOfReferenceUID,
segmentIndex,
},
type: csEnums.GeometryType.CONTOUR,
});
const numInitialized = Object.keys(segmentsCachedStats).length;
const contourSet = geometry.data;
const centroid = contourSet.getCentroid();
// Calculate percentage completed
const percentComplete = Math.round(
(numInitialized / allRTStructData.length) * 100
);
segmentsCachedStats[segmentIndex] = {
center: { world: centroid },
modifiedTime: rtDisplaySet.SeriesDate, // we use the SeriesDate as the modifiedTime since this is the first time we are creating the segmentation
};
this._broadcastEvent(EVENTS.SEGMENT_LOADING_COMPLETE, {
percentComplete,
// Note: this is not the geometryIds length since there might be
// some missing ROINumbers
numSegments: allRTStructData.length,
});
} catch (e) {
console.warn(e);
}
segmentation.segments[segmentIndex] = {
label: id,
segmentIndex,
color,
...SEGMENT_CONSTANT,
};
const numInitialized = Object.keys(segmentsCachedStats).length;
// Calculate percentage completed
const percentComplete = Math.round(
(numInitialized / allRTStructData.length) * 100
);
this._broadcastEvent(EVENTS.SEGMENT_LOADING_COMPLETE, {
percentComplete,
// Note: this is not the geometryIds length since there might be
// some missing ROINumbers
numSegments: allRTStructData.length,
});
};
const promiseArray = [];
@@ -15,7 +15,7 @@ const EVENTS = {
* sync group declared.
*/
export type SyncCreator = (
id: string,
type: string,
options?: Record<string, unknown>
) => Synchronizer;
@@ -83,7 +83,7 @@ export default class SyncGroupService {
* @param type is the type of the synchronizer to create
* @param creator
*/
public addSynchronizerType(type: string, creator: SyncCreator): void {
public setSynchronizer(type: string, creator: SyncCreator): void {
this.synchronizerCreators[type.toLowerCase()] = creator;
}
@@ -745,7 +745,7 @@ class CornerstoneViewportService extends PubSubService
const viewport = this.getCornerstoneViewport(viewportId);
const viewportCamera = viewport.getCamera();
if (viewport instanceof VolumeViewport || viewport instanceof VolumeViewport3D) {
if (viewport instanceof VolumeViewport) {
this._setVolumeViewport(viewport, viewportData, viewportInfo).then(() => {
if (keepCamera) {
viewport.setCamera(viewportCamera);
@@ -198,9 +198,7 @@ class ViewportInfo {
// via cornerstoneViewportService
let viewportData = this.getViewportData();
if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC ||
viewportData.viewportType === Enums.ViewportType.VOLUME_3D
) {
if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC) {
viewportData = viewportData as VolumeViewportData;
return viewportData.data.some(
({ displaySetInstanceUID: dsUID }) => dsUID === displaySetInstanceUID
@@ -1,9 +1,9 @@
import { Types } from '@ohif/core';
import ToolGroupService from '../services/ToolGroupService';
import SyncGroupService from '../services/SyncGroupService';
import SegmentationService from '../services/SegmentationService';
import CornerstoneCacheService from '../services/CornerstoneCacheService';
import CornerstoneViewportService from '../services/ViewportService/CornerstoneViewportService';
import ToolGroupService from './services/ToolGroupService';
import SyncGroupService from './services/SyncGroupService';
import SegmentationService from './services/SegmentationService';
import CornerstoneCacheService from './services/CornerstoneCacheService';
import CornerstoneViewportService from './services/ViewportService/CornerstoneViewportService';
interface CornerstoneServices extends Types.Services {
cornerstoneViewportService: CornerstoneViewportService;
@@ -1,5 +1,5 @@
import React from 'react';
import { Input, Dialog, ButtonEnums } from '@ohif/ui';
import { Input, Dialog } from '@ohif/ui';
/**
*
@@ -60,8 +60,8 @@ function callInputDialog(
noCloseButton: true,
onClose: () => uiDialogService.dismiss({ id: dialogId }),
actions: [
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
{ id: 'cancel', text: 'Cancel', type: 'primary' },
{ id: 'save', text: 'Save', type: 'secondary' },
],
onSubmit: onSubmitHandler,
body: ({ value, setValue }) => {
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-default",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "Common/default features and functionality for basic image viewing",
"author": "OHIF Core Team",
"license": "MIT",
@@ -30,8 +30,8 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/i18n": "3.7.0-beta.32",
"@ohif/core": "3.6.0",
"@ohif/i18n": "3.6.0",
"dcmjs": "^0.29.5",
"dicomweb-client": "^0.10.2",
"prop-types": "^15.6.2",
@@ -60,42 +60,15 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
supportsReject,
staticWado,
singlepart,
omitQuotationForMultipartRequest,
acceptHeader,
requestTransferSyntaxUID,
} = dicomWebConfig;
const dicomWebConfigCopy = JSON.parse(JSON.stringify(dicomWebConfig));
const getAuthrorizationHeader = () => {
const xhrRequestHeaders = {};
const authHeaders = userAuthenticationService.getAuthorizationHeader();
if (authHeaders && authHeaders.Authorization) {
xhrRequestHeaders.Authorization = authHeaders.Authorization;
}
return xhrRequestHeaders;
};
const generateWadoHeader = () => {
let authorizationHeader = getAuthrorizationHeader();
//Generate accept header depending on config params
let formattedAcceptHeader = utils.generateAcceptHeader(
acceptHeader,
requestTransferSyntaxUID,
omitQuotationForMultipartRequest
);
return {
...authorizationHeader,
Accept: formattedAcceptHeader,
};
};
const qidoConfig = {
url: qidoRoot,
staticWado,
singlepart,
headers: getAuthrorizationHeader(),
headers: userAuthenticationService.getAuthorizationHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
};
@@ -103,7 +76,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
url: wadoRoot,
staticWado,
singlepart,
headers: generateWadoHeader(),
headers: userAuthenticationService.getAuthorizationHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
};
@@ -137,7 +110,11 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
studies: {
mapParams: mapParams.bind(),
search: async function(origParams) {
qidoDicomWebClient.headers = getAuthrorizationHeader();
const headers = userAuthenticationService.getAuthorizationHeader();
if (headers) {
qidoDicomWebClient.headers = headers;
}
const { studyInstanceUid, seriesInstanceUid, ...mappedParams } =
mapParams(origParams, {
supportsFuzzyMatching,
@@ -158,7 +135,11 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
series: {
// mapParams: mapParams.bind(),
search: async function(studyInstanceUid) {
qidoDicomWebClient.headers = getAuthrorizationHeader();
const headers = userAuthenticationService.getAuthorizationHeader();
if (headers) {
qidoDicomWebClient.headers = headers;
}
const results = await seriesInStudy(
qidoDicomWebClient,
studyInstanceUid
@@ -170,7 +151,11 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
},
instances: {
search: (studyInstanceUid, queryParameters) => {
qidoDicomWebClient.headers = getAuthrorizationHeader();
const headers = userAuthenticationService.getAuthorizationHeader();
if (headers) {
qidoDicomWebClient.headers = headers;
}
qidoSearch.call(
undefined,
qidoDicomWebClient,
@@ -197,7 +182,6 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
return getDirectURL({ wadoRoot, singlepart }, params);
},
bulkDataURI: async ({ StudyInstanceUID, BulkDataURI }) => {
qidoDicomWebClient.headers = getAuthrorizationHeader();
const options = {
multipart: false,
BulkDataURI,
@@ -216,6 +200,11 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
sortFunction,
madeInClient = false,
} = {}) => {
const headers = userAuthenticationService.getAuthorizationHeader();
if (headers) {
wadoDicomWebClient.headers = headers;
}
if (!StudyInstanceUID) {
throw new Error(
'Unable to query for SeriesMetadata without StudyInstanceUID'
@@ -245,12 +234,17 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
store: {
dicom: async (dataset, request) => {
wadoDicomWebClient.headers = getAuthrorizationHeader();
const headers = userAuthenticationService.getAuthorizationHeader();
if (headers) {
wadoDicomWebClient.headers = headers;
}
if (dataset instanceof ArrayBuffer) {
const options = {
datasets: [dataset],
request,
};
await wadoDicomWebClient.storeInstances(options);
} else {
const meta = {
@@ -288,7 +282,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
madeInClient
) => {
const enableStudyLazyLoad = false;
wadoDicomWebClient.headers = generateWadoHeader();
// data is all SOPInstanceUIDs
const data = await retrieveStudyMetadata(
wadoDicomWebClient,
@@ -359,7 +353,6 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
madeInClient = false
) => {
const enableStudyLazyLoad = true;
wadoDicomWebClient.headers = generateWadoHeader();
// Get Series
const {
preLoadData: seriesSummaryMetadata,
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { LegacyButton, ButtonGroup } from '@ohif/ui';
import { Button, ButtonGroup } from '@ohif/ui';
function ActionButtons({ onExportClick, onCreateReportClick }) {
const { t } = useTranslation('MeasurementTable');
@@ -10,16 +10,12 @@ function ActionButtons({ onExportClick, onCreateReportClick }) {
return (
<React.Fragment>
<ButtonGroup color="black" size="inherit">
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
<LegacyButton className="px-2 py-2 text-base" onClick={onExportClick}>
<Button className="px-2 py-2 text-base" onClick={onExportClick}>
{t('Export CSV')}
</LegacyButton>
<LegacyButton
className="px-2 py-2 text-base"
onClick={onCreateReportClick}
>
</Button>
<Button className="px-2 py-2 text-base" onClick={onCreateReportClick}>
{t('Create Report')}
</LegacyButton>
</Button>
</ButtonGroup>
</React.Fragment>
);
@@ -3,7 +3,7 @@ import classnames from 'classnames';
import { useNavigate } from 'react-router-dom';
import { useAppConfig } from '@state';
import { Button, ButtonEnums } from '@ohif/ui';
import { Button } from '@ohif/ui';
function DataSourceSelector() {
const [appConfig] = useAppConfig();
@@ -33,8 +33,7 @@ function DataSourceSelector() {
<div key={ds.sourceName}>
<h1 className="text-white">{ds.friendlyName}</h1>
<Button
type={ButtonEnums.type.primary}
className={classnames('ml-2')}
className={classnames('font-bold', 'ml-2')}
onClick={() => {
navigate({
pathname: '/',
@@ -1,13 +1,7 @@
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { utils, ServicesManager } from '@ohif/core';
import {
MeasurementTable,
Dialog,
Input,
useViewportGrid,
ButtonEnums,
} from '@ohif/ui';
import { MeasurementTable, Dialog, Input, useViewportGrid } from '@ohif/ui';
import ActionButtons from './ActionButtons';
import debounce from 'lodash.debounce';
@@ -195,8 +189,9 @@ export default function PanelMeasurementTable({
);
},
actions: [
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
// temp: swap button types until colors are updated
{ id: 'cancel', text: 'Cancel', type: 'primary' },
{ id: 'save', text: 'Save', type: 'secondary' },
],
onSubmit: onSubmitHandler,
},
@@ -1,6 +1,6 @@
/* eslint-disable react/display-name */
import React from 'react';
import { ButtonEnums, Dialog, Input, Select } from '@ohif/ui';
import { Dialog, Input, Select } from '@ohif/ui';
export const CREATE_REPORT_DIALOG_RESPONSE = {
CANCEL: 0,
@@ -81,8 +81,8 @@ export default function createReportDialogPrompt(
noCloseButton: true,
onClose: _handleClose,
actions: [
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
{ id: 'cancel', text: 'Cancel', type: 'primary' },
{ id: 'save', text: 'Save', type: 'secondary' },
],
// TODO: Should be on button press...
onSubmit: _handleFormSubmit,
+1 -1
View File
@@ -29,7 +29,7 @@ export default function Toolbar({ servicesManager }) {
return (
<>
{toolbarButtons.map(toolDef => {
{toolbarButtons.map((toolDef, index) => {
const { id, Component, componentProps } = toolDef;
// TODO: ...
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-microscopy",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "OHIF extension for DICOM microscopy",
"author": "Bill Wallace, md-prog",
"license": "MIT",
@@ -28,10 +28,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/extension-default": "3.7.0-beta.32",
"@ohif/i18n": "3.7.0-beta.32",
"@ohif/ui": "3.7.0-beta.32",
"@ohif/core": "3.6.0",
"@ohif/extension-default": "3.6.0",
"@ohif/i18n": "3.6.0",
"@ohif/ui": "3.6.0",
"prop-types": "^15.6.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
@@ -1,5 +1,5 @@
import React from 'react';
import { Input, Dialog, ButtonEnums } from '@ohif/ui';
import { Input, Dialog } from '@ohif/ui';
/**
*
@@ -14,7 +14,7 @@ export default function callInputDialog({
uiDialogService,
title = 'Annotation',
defaultValue = '',
callback = (value: string, action: string) => {},
callback = (value: string, action: string) => {}
}) {
const dialogId = 'microscopy-input-dialog';
@@ -43,8 +43,8 @@ export default function callInputDialog({
noCloseButton: true,
onClose: () => uiDialogService.dismiss({ id: dialogId }),
actions: [
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
{ id: 'cancel', text: 'Cancel', type: 'primary' },
{ id: 'save', text: 'Save', type: 'secondary' },
],
onSubmit: onSubmitHandler,
body: ({ value, setValue }) => {
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-pdf",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "OHIF extension for PDF display",
"author": "OHIF",
"license": "MIT",
@@ -28,8 +28,8 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/ui": "3.7.0-beta.32",
"@ohif/core": "3.6.0",
"@ohif/ui": "3.6.0",
"dcmjs": "^0.29.5",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-video",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "OHIF extension for video display",
"author": "OHIF",
"license": "MIT",
@@ -28,8 +28,8 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/ui": "3.7.0-beta.32",
"@ohif/core": "3.6.0",
"@ohif/ui": "3.6.0",
"dcmjs": "^0.29.5",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-measurement-tracking",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "Tracking features and functionality for basic image viewing",
"author": "OHIF Core Team",
"license": "MIT",
@@ -30,11 +30,11 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@cornerstonejs/core": "^1.4.1",
"@cornerstonejs/tools": "^1.4.1",
"@ohif/core": "3.7.0-beta.32",
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.32",
"@ohif/ui": "3.7.0-beta.32",
"@cornerstonejs/core": "^1.1.0",
"@cornerstonejs/tools": "^1.1.0",
"@ohif/core": "3.6.0",
"@ohif/extension-cornerstone-dicom-sr": "3.6.0",
"@ohif/ui": "3.6.0",
"classnames": "^2.3.2",
"dcmjs": "^0.29.5",
"lodash.debounce": "^4.17.21",
@@ -46,7 +46,7 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@ohif/ui": "3.7.0-beta.32",
"@ohif/ui": "3.6.0",
"@xstate/react": "^0.8.1",
"xstate": "^4.10.0"
}
@@ -1,6 +1,6 @@
/* eslint-disable react/display-name */
import React from 'react';
import { ButtonEnums, Dialog, Input } from '@ohif/ui';
import { Dialog, Input } from '@ohif/ui';
import RESPONSE from './PROMPT_RESPONSES';
export default function createReportDialogPrompt(uiDialogService) {
@@ -20,19 +20,12 @@ export default function createReportDialogPrompt(uiDialogService) {
* @param {string} param0.value - value from input field
*/
const _handleFormSubmit = ({ action, value }) => {
uiDialogService.dismiss({ id: dialogId });
switch (action.id) {
case 'save':
// Only save if description is not blank otherwise ignore
if (value.label && value.label.trim() !== '') {
resolve({
action: RESPONSE.CREATE_REPORT,
value: value.label.trim(),
});
uiDialogService.dismiss({ id: dialogId });
}
resolve({ action: RESPONSE.CREATE_REPORT, value: value.label });
break;
case 'cancel':
uiDialogService.dismiss({ id: dialogId });
resolve({ action: RESPONSE.CANCEL, value: undefined });
break;
}
@@ -50,8 +43,8 @@ export default function createReportDialogPrompt(uiDialogService) {
noCloseButton: true,
onClose: _handleClose,
actions: [
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
{ id: 'cancel', text: 'Cancel', type: 'primary' },
{ id: 'save', text: 'Save', type: 'secondary' },
],
// TODO: Should be on button press...
onSubmit: _handleFormSubmit,
@@ -62,8 +55,8 @@ export default function createReportDialogPrompt(uiDialogService) {
};
const onKeyPressHandler = event => {
if (event.key === 'Enter') {
// Trigger form submit
_handleFormSubmit({ action: { id: 'save' }, value });
uiDialogService.dismiss({ id: dialogId });
resolve({ action: RESPONSE.CREATE_REPORT, value: value.label });
}
};
return (
@@ -1,5 +1,3 @@
import { ButtonEnums } from '@ohif/ui';
const RESPONSE = {
NO_NEVER: -1,
CANCEL: 0,
@@ -33,19 +31,19 @@ function _askTrackMeasurements(uiViewportDialogService, viewportIndex) {
const actions = [
{
id: 'prompt-begin-tracking-cancel',
type: ButtonEnums.type.secondary,
type: 'cancel',
text: 'No',
value: RESPONSE.CANCEL,
},
{
id: 'prompt-begin-tracking-no-do-not-ask-again',
type: ButtonEnums.type.secondary,
type: 'secondary',
text: 'No, do not ask again',
value: RESPONSE.NO_NEVER,
},
{
id: 'prompt-begin-tracking-yes',
type: ButtonEnums.type.primary,
type: 'primary',
text: 'Yes',
value: RESPONSE.SET_STUDY_AND_SERIES,
},
@@ -1,5 +1,4 @@
import { hydrateStructuredReport } from '@ohif/extension-cornerstone-dicom-sr';
import { ButtonEnums } from '@ohif/ui';
const RESPONSE = {
NO_NEVER: -1,
@@ -62,12 +61,12 @@ function _askTrackMeasurements(uiViewportDialogService, viewportIndex) {
'Do you want to continue tracking measurements for this study?';
const actions = [
{
type: ButtonEnums.type.secondary,
type: 'secondary',
text: 'No',
value: RESPONSE.CANCEL,
},
{
type: ButtonEnums.type.primary,
type: 'primary',
text: 'Yes',
value: RESPONSE.HYDRATE_REPORT,
},
@@ -1,5 +1,3 @@
import { ButtonEnums } from '@ohif/ui';
const RESPONSE = {
NO_NEVER: -1,
CANCEL: 0,
@@ -40,18 +38,14 @@ function _askShouldAddMeasurements(uiViewportDialogService, viewportIndex) {
const message =
'Do you want to add this measurement to the existing report?';
const actions = [
{ type: 'cancel', text: 'Cancel', value: RESPONSE.CANCEL },
{
type: ButtonEnums.type.secondary,
text: 'Cancel',
value: RESPONSE.CANCEL,
},
{
type: ButtonEnums.type.primary,
type: 'secondary',
text: 'Create new report',
value: RESPONSE.CREATE_REPORT,
},
{
type: ButtonEnums.type.primary,
type: 'primary',
text: 'Add to existing report',
value: RESPONSE.ADD_SERIES,
},
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { Button, ButtonEnums } from '@ohif/ui';
import { Button, ButtonGroup } from '@ohif/ui';
function ActionButtons({ onExportClick, onCreateReportClick, disabled }) {
const { t } = useTranslation('MeasurementTable');
@@ -10,18 +10,23 @@ function ActionButtons({ onExportClick, onCreateReportClick, disabled }) {
return (
<React.Fragment>
<Button
className="text-base px-2 py-2"
size="initial"
variant={disabled ? 'disabled' : 'outlined'}
color="black"
border="primaryActive"
onClick={onExportClick}
disabled={disabled}
type={ButtonEnums.type.secondary}
size={ButtonEnums.size.small}
>
{t('Export')}
</Button>
<Button
className="ml-2"
className="ml-2 px-2 text-base"
variant={disabled ? 'disabled' : 'outlined'}
size="initial"
color="black"
border="primaryActive"
onClick={onCreateReportClick}
type={ButtonEnums.type.secondary}
size={ButtonEnums.size.small}
disabled={disabled}
>
{t('Create Report')}
@@ -6,7 +6,6 @@ import {
Dialog,
Input,
useViewportGrid,
ButtonEnums,
} from '@ohif/ui';
import { DicomMetadataStore, utils } from '@ohif/core';
import { useDebounce } from '@hooks';
@@ -218,8 +217,9 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) {
);
},
actions: [
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
// temp: swap button types until colors are updated
{ id: 'cancel', text: 'Cancel', type: 'primary' },
{ id: 'save', text: 'Save', type: 'secondary' },
],
onSubmit: onSubmitHandler,
},
@@ -1,5 +1,4 @@
import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import PropTypes from 'prop-types';
import { utils } from '@ohif/core';
import {
@@ -7,7 +6,6 @@ import {
useImageViewer,
useViewportGrid,
Dialog,
ButtonEnums,
} from '@ohif/ui';
import { useTrackedMeasurements } from '../../getContextModule';
@@ -25,20 +23,19 @@ function PanelStudyBrowserTracking({
dataSource,
}) {
const {
measurementService,
displaySetService,
uiDialogService,
hangingProtocolService,
uiNotificationService,
} = servicesManager.services;
const { t } = useTranslation('Common');
// Normally you nest the components so the tree isn't so deep, and the data
// doesn't have to have such an intense shape. This works well enough for now.
// Tabs --> Studies --> DisplaySets --> Thumbnails
const { StudyInstanceUIDs } = useImageViewer();
const [
{ activeViewportIndex, viewports },
{ activeViewportIndex, viewports, numCols, numRows },
viewportGridService,
] = useViewportGrid();
const [
@@ -79,6 +76,36 @@ function PanelStudyBrowserTracking({
const activeViewportDisplaySetInstanceUIDs =
viewports[activeViewportIndex]?.displaySetInstanceUIDs;
useEffect(() => {
const added = measurementService.EVENTS.MEASUREMENT_ADDED;
const addedRaw = measurementService.EVENTS.RAW_MEASUREMENT_ADDED;
const subscriptions = [];
[added, addedRaw].forEach(evt => {
subscriptions.push(
measurementService.subscribe(evt, ({ source, measurement }) => {
const {
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
} = measurement;
sendTrackedMeasurementsEvent('SET_DIRTY', { SeriesInstanceUID });
sendTrackedMeasurementsEvent('TRACK_SERIES', {
viewportIndex: activeViewportIndex,
StudyInstanceUID,
SeriesInstanceUID,
});
}).unsubscribe
);
});
return () => {
subscriptions.forEach(unsub => {
unsub();
});
};
}, [measurementService, activeViewportIndex, sendTrackedMeasurementsEvent]);
const { trackedSeries } = trackedMeasurements.context;
// ~~ studyDisplayList
@@ -106,7 +133,7 @@ function PanelStudyBrowserTracking({
const actuallyMappedStudies = mappedStudies.map(qidoStudy => {
return {
studyInstanceUid: qidoStudy.StudyInstanceUID,
date: formatDate(qidoStudy.StudyDate) || t('NoStudyDate'),
date: formatDate(qidoStudy.StudyDate),
description: qidoStudy.StudyDescription,
modalities: qidoStudy.ModalitiesInStudy,
numInstances: qidoStudy.NumInstances,
@@ -480,15 +507,11 @@ function _mapDisplaySets(
</div>
),
actions: [
{
id: 'cancel',
text: 'Cancel',
type: ButtonEnums.type.secondary,
},
{ id: 'cancel', text: 'Cancel', type: 'secondary' },
{
id: 'yes',
text: 'Yes',
type: ButtonEnums.type.primary,
type: 'primary',
classes: ['reject-yes-button'],
},
],
@@ -22,22 +22,17 @@ function TrackedCornerstoneViewport(props) {
viewportOptions,
} = props;
const { t } = useTranslation('Common');
const { t } = useTranslation('TrackedViewport');
const {
measurementService,
cornerstoneViewportService,
viewportGridService,
} = servicesManager.services;
// Todo: handling more than one displaySet on the same viewport
const displaySet = displaySets[0];
const [
trackedMeasurements,
sendTrackedMeasurementsEvent,
] = useTrackedMeasurements();
const [trackedMeasurements] = useTrackedMeasurements();
const [isTracked, setIsTracked] = useState(false);
const [trackedMeasurementUID, setTrackedMeasurementUID] = useState(null);
const [viewportElem, setViewportElem] = useState(null);
@@ -59,7 +54,6 @@ function TrackedCornerstoneViewport(props) {
PatientAge,
SliceThickness,
SpacingBetweenSlices,
StudyDate,
ManufacturerModelName,
} = displaySet.images[0];
@@ -154,55 +148,6 @@ function TrackedCornerstoneViewport(props) {
};
}, [isTracked]);
/**
* The effect for listening to measurement service measurement added events
* and in turn firing an event to update the measurement tracking state machine.
* The TrackedCornerstoneViewport is the best place for this because when
* a measurement is added, at least one TrackedCornerstoneViewport will be in
* the DOM and thus can react to the events fired.
*/
useEffect(() => {
const added = measurementService.EVENTS.MEASUREMENT_ADDED;
const addedRaw = measurementService.EVENTS.RAW_MEASUREMENT_ADDED;
const subscriptions = [];
[added, addedRaw].forEach(evt => {
subscriptions.push(
measurementService.subscribe(evt, ({ source, measurement }) => {
const { activeViewportIndex } = viewportGridService.getState();
// Each TrackedCornerstoneViewport receives the MeasurementService's events.
// Only send the tracked measurements event for the active viewport to avoid
// sending it more than once.
if (viewportIndex === activeViewportIndex) {
const {
referenceStudyUID: StudyInstanceUID,
referenceSeriesUID: SeriesInstanceUID,
} = measurement;
sendTrackedMeasurementsEvent('SET_DIRTY', { SeriesInstanceUID });
sendTrackedMeasurementsEvent('TRACK_SERIES', {
viewportIndex,
StudyInstanceUID,
SeriesInstanceUID,
});
}
}).unsubscribe
);
});
return () => {
subscriptions.forEach(unsub => {
unsub();
});
};
}, [
measurementService,
sendTrackedMeasurementsEvent,
viewportIndex,
viewportGridService,
]);
function switchMeasurement(direction) {
const newTrackedMeasurementUID = _getNextMeasurementUID(
direction,
@@ -249,8 +194,7 @@ function TrackedCornerstoneViewport(props) {
getStatusComponent={() => _getStatusComponent(isTracked)}
studyData={{
label: viewportLabel,
studyDate:
formatDate(SeriesDate) || formatDate(StudyDate) || t('NoStudyDate'),
studyDate: formatDate(SeriesDate), // TODO: This is series date. Is that ok?
currentSeries: SeriesNumber, // TODO - switch entire currentSeries to be UID based or actual position based
seriesDescription: SeriesDescription,
patientInformation: {
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-test",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "OHIF extension used inside e2e testing",
"author": "OHIF",
"license": "MIT",
@@ -28,8 +28,8 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/ui": "3.7.0-beta.32",
"@ohif/core": "3.6.0",
"@ohif/ui": "3.6.0",
"dcmjs": "0.29.4",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-tmtv",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "OHIF extension for Total Metabolic Tumor Volume",
"author": "OHIF",
"license": "MIT",
@@ -28,8 +28,8 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/ui": "3.7.0-beta.32",
"@ohif/core": "3.6.0",
"@ohif/ui": "3.6.0",
"dcmjs": "^0.29.5",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
+3 -1
View File
@@ -225,7 +225,9 @@ export default function PanelPetSUV({ servicesManager, commandsManager }) {
value={metadata.SeriesTime || ''}
onChange={() => {}}
/>
<Button onClick={updateMetadata}>Reload Data</Button>
<Button color="primary" onClick={updateMetadata}>
Reload Data
</Button>
</div>
</div>
}
@@ -1,5 +1,5 @@
import React from 'react';
import { LegacyButton, ButtonGroup } from '@ohif/ui';
import { Button, ButtonGroup } from '@ohif/ui';
import { useTranslation } from 'react-i18next';
function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
@@ -9,9 +9,8 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
<>
{segmentations?.length ? (
<div className="flex justify-center mt-4 space-x-2">
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
<ButtonGroup color="black" size="inherit">
<LegacyButton
<Button
className="px-2 py-2 text-base"
disabled={tmtvValue === null}
onClick={() => {
@@ -23,10 +22,10 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
}}
>
{t('Export CSV')}
</LegacyButton>
</Button>
</ButtonGroup>
<ButtonGroup color="black" size="inherit">
<LegacyButton
<Button
className="px-2 py-2 text-base"
onClick={() => {
commandsManager.runCommand('createTMTVRTReport');
@@ -34,7 +33,7 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
disabled={tmtvValue === null}
>
{t('Create RT Report')}
</LegacyButton>
</Button>
</ButtonGroup>
</div>
) : null}
@@ -181,6 +181,7 @@ export default function PanelRoiThresholdSegmentation({
<div className="overflow-x-hidden overflow-y-auto invisible-scrollbar">
<div className="flex mx-4 my-4 mb-4 space-x-4">
<Button
color="primary"
onClick={() => {
setLabelmapLoading(true);
setTimeout(() => {
@@ -193,7 +194,9 @@ export default function PanelRoiThresholdSegmentation({
>
{labelmapLoading ? 'loading ...' : 'New Label'}
</Button>
<Button onClick={handleROIThresholding}>Run</Button>
<Button color="primary" onClick={handleROIThresholding}>
Run
</Button>
</div>
<div
className="flex items-center justify-around h-8 mb-2 border-t outline-none cursor-pointer select-none bg-secondary-dark first:border-0 border-secondary-light"
@@ -1,5 +1,5 @@
import React from 'react';
import { Input, Label, Select, LegacyButton, ButtonGroup } from '@ohif/ui';
import { Input, Label, Select, Button, ButtonGroup } from '@ohif/ui';
import { useTranslation } from 'react-i18next';
export const ROI_STAT = 'roi_stat';
@@ -38,9 +38,8 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
/>
</div>
<div className="w-1/2">
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
<ButtonGroup>
<LegacyButton
<Button
size="initial"
className="px-2 py-2 text-base text-white"
color="primaryLight"
@@ -48,8 +47,8 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
onClick={() => runCommand('setStartSliceForROIThresholdTool')}
>
{t('Start')}
</LegacyButton>
<LegacyButton
</Button>
<Button
size="initial"
color="primaryLight"
variant="outlined"
@@ -57,7 +56,7 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
onClick={() => runCommand('setEndSliceForROIThresholdTool')}
>
{t('End')}
</LegacyButton>
</Button>
</ButtonGroup>
</div>
</div>
@@ -1,5 +1,5 @@
import React from 'react';
import { Input, Dialog, ButtonEnums } from '@ohif/ui';
import { Input, Dialog } from '@ohif/ui';
function segmentationItemEditHandler({ id, servicesManager }) {
const { segmentationService, uiDialogService } = servicesManager.services;
@@ -44,20 +44,23 @@ function segmentationItemEditHandler({ id, servicesManager }) {
}
};
return (
<Input
autoFocus
className="bg-black border-primary-main"
type="text"
containerClassName="mr-2"
value={value.label}
onChange={onChangeHandler}
onKeyPress={onKeyPressHandler}
/>
<div className="p-4 bg-primary-dark">
<Input
autoFocus
className="mt-2 bg-black border-primary-main"
type="text"
containerClassName="mr-2"
value={value.label}
onChange={onChangeHandler}
onKeyPress={onKeyPressHandler}
/>
</div>
);
},
actions: [
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
// temp: swap button types until colors are updated
{ id: 'cancel', text: 'Cancel', type: 'primary' },
{ id: 'save', text: 'Save', type: 'secondary' },
],
onSubmit: onSubmitHandler,
},
+1 -10
View File
@@ -553,16 +553,7 @@ const commandsModule = ({
commandsManager.runCommand('setViewportColormap', {
viewportIndex,
displaySetInstanceUID: ptDisplaySet.displaySetInstanceUID,
colormap: {
name: colormap,
// TODO: This opacity mapping matches that in hpViewports, but
// ideally making this editable in a side panel would be useful
opacity: [
{ value: 0, opacity: 0 },
{ value: 0.1, opacity: 0.9 },
{ value: 1, opacity: 0.95 },
],
},
colormap,
});
viewports.push(
+6 -18
View File
@@ -254,20 +254,16 @@ const fusionAXIAL = {
id: 'ctDisplaySet',
},
{
id: 'ptDisplaySet',
options: {
colormap: {
name: 'hsv',
opacity: [
{ value: 0, opacity: 0 },
{ value: 0.1, opacity: 0.9 },
{ value: 1, opacity: 0.95 },
],
opacityMapping: [{ value: 0.1, opacity: 0.9 }],
},
voi: {
custom: 'getPTVOIRange',
},
},
id: 'ptDisplaySet',
},
],
};
@@ -314,20 +310,16 @@ const fusionSAGITTAL = {
id: 'ctDisplaySet',
},
{
id: 'ptDisplaySet',
options: {
colormap: {
name: 'hsv',
opacity: [
{ value: 0, opacity: 0 },
{ value: 0.1, opacity: 0.9 },
{ value: 1, opacity: 0.95 },
],
opacityMapping: [{ value: 0.1, opacity: 0.9 }],
},
voi: {
custom: 'getPTVOIRange',
},
},
id: 'ptDisplaySet',
},
],
};
@@ -374,20 +366,16 @@ const fusionCORONAL = {
id: 'ctDisplaySet',
},
{
id: 'ptDisplaySet',
options: {
colormap: {
name: 'hsv',
opacity: [
{ value: 0, opacity: 0 },
{ value: 0.1, opacity: 0.9 },
{ value: 1, opacity: 0.95 },
],
opacityMapping: [{ value: 0.1, opacity: 0.9 }],
},
voi: {
custom: 'getPTVOIRange',
},
},
id: 'ptDisplaySet',
},
],
};
+1 -1
View File
@@ -1,5 +1,5 @@
{
"version": "3.7.0-beta.32",
"version": "3.6.0",
"packages": ["extensions/*", "platform/*", "modes/*"],
"npmClient": "yarn",
"useWorkspaces": true
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/mode-basic-dev-mode",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "Basic OHIF Viewer Using Cornerstone",
"author": "OHIF",
"license": "MIT",
@@ -29,12 +29,12 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/extension-cornerstone": "3.7.0-beta.32",
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.32",
"@ohif/extension-default": "3.7.0-beta.32",
"@ohif/extension-dicom-pdf": "3.7.0-beta.32",
"@ohif/extension-dicom-video": "3.7.0-beta.32"
"@ohif/core": "3.6.0",
"@ohif/extension-cornerstone": "3.6.0",
"@ohif/extension-cornerstone-dicom-sr": "3.6.0",
"@ohif/extension-default": "3.6.0",
"@ohif/extension-dicom-pdf": "3.6.0",
"@ohif/extension-dicom-video": "3.6.0"
},
"dependencies": {
"@babel/runtime": "^7.20.13"
+9 -9
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/mode-test",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "Basic mode for testing",
"author": "OHIF",
"license": "MIT",
@@ -32,14 +32,14 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/extension-cornerstone": "3.7.0-beta.32",
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.32",
"@ohif/extension-default": "3.7.0-beta.32",
"@ohif/extension-dicom-pdf": "3.7.0-beta.32",
"@ohif/extension-dicom-video": "3.7.0-beta.32",
"@ohif/extension-measurement-tracking": "3.7.0-beta.32",
"@ohif/extension-test": "3.7.0-beta.32"
"@ohif/core": "3.6.0",
"@ohif/extension-cornerstone": "3.6.0",
"@ohif/extension-cornerstone-dicom-sr": "3.6.0",
"@ohif/extension-default": "3.6.0",
"@ohif/extension-dicom-pdf": "3.6.0",
"@ohif/extension-dicom-video": "3.6.0",
"@ohif/extension-measurement-tracking": "3.6.0",
"@ohif/extension-test": "3.6.0"
},
"dependencies": {
"@babel/runtime": "^7.20.13"
+10 -10
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/mode-longitudinal",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "Longitudinal Workflow",
"author": "OHIF",
"license": "MIT",
@@ -32,15 +32,15 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/extension-cornerstone": "3.7.0-beta.32",
"@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.32",
"@ohif/extension-cornerstone-dicom-seg": "3.7.0-beta.32",
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.32",
"@ohif/extension-default": "3.7.0-beta.32",
"@ohif/extension-dicom-pdf": "3.7.0-beta.32",
"@ohif/extension-dicom-video": "3.7.0-beta.32",
"@ohif/extension-measurement-tracking": "3.7.0-beta.32"
"@ohif/core": "3.6.0",
"@ohif/extension-cornerstone": "3.6.0",
"@ohif/extension-cornerstone-dicom-rt": "3.6.0",
"@ohif/extension-cornerstone-dicom-seg": "3.6.0",
"@ohif/extension-cornerstone-dicom-sr": "3.6.0",
"@ohif/extension-default": "3.6.0",
"@ohif/extension-dicom-pdf": "3.6.0",
"@ohif/extension-dicom-video": "3.6.0",
"@ohif/extension-measurement-tracking": "3.6.0"
},
"dependencies": {
"@babel/runtime": "^7.20.13"
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/mode-microscopy",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "OHIF mode for DICOM microscopy",
"author": "OHIF",
"license": "MIT",
@@ -33,8 +33,8 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/extension-dicom-microscopy": "3.7.0-beta.32"
"@ohif/core": "3.6.0",
"@ohif/extension-dicom-microscopy": "3.6.0"
},
"dependencies": {
"@babel/runtime": "^7.20.13"
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/mode-tmtv",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "Total Metabolic Tumor Volume Workflow",
"author": "OHIF",
"license": "MIT",
@@ -32,13 +32,13 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.32",
"@ohif/extension-cornerstone": "3.7.0-beta.32",
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.32",
"@ohif/extension-default": "3.7.0-beta.32",
"@ohif/extension-dicom-pdf": "3.7.0-beta.32",
"@ohif/extension-dicom-video": "3.7.0-beta.32",
"@ohif/extension-measurement-tracking": "3.7.0-beta.32"
"@ohif/core": "3.6.0",
"@ohif/extension-cornerstone": "3.6.0",
"@ohif/extension-cornerstone-dicom-sr": "3.6.0",
"@ohif/extension-default": "3.6.0",
"@ohif/extension-dicom-pdf": "3.6.0",
"@ohif/extension-dicom-video": "3.6.0",
"@ohif/extension-measurement-tracking": "3.6.0"
},
"dependencies": {
"@babel/runtime": "^7.20.13"
+1 -2
View File
@@ -220,8 +220,7 @@ function modeFactory({ modeConfiguration }) {
return {
id: ohif.layout,
props: {
leftPanels: [ohif.thumbnailList],
leftPanelDefaultClosed: true,
// leftPanels: [ohif.thumbnailList],
rightPanels: [tmtv.ROIThresholdPanel, tmtv.petSUV],
viewports: [
{
+1 -1
View File
@@ -113,7 +113,7 @@ function _initToolGroups(toolNames, Enums, toolGroupService, commandsManager) {
rotateIncrementDegrees: 0.1,
},
[toolNames.MipJumpToClick]: {
toolGroupId: toolGroupIds.PT,
targetViewportIds: ['ptAXIAL', 'ptCORONAL', 'ptSAGITTAL'],
},
};
+12 -4
View File
@@ -24,8 +24,9 @@ function _createButton(type, id, icon, label, commands, tooltip) {
function _createColormap(label, colormap) {
return {
id: label,
label,
id: label.toString(),
title: label,
subtitle: label,
type: 'action',
commands: [
{
@@ -35,6 +36,13 @@ function _createColormap(label, colormap) {
colormap,
},
},
{
commandName: 'setFusionPTColormap',
commandOptions: {
toolGroupId: toolGroupIds.Fusion,
colormap,
},
},
],
};
}
@@ -305,8 +313,7 @@ const toolbarButtons = [
commandName: 'displayNotification',
commandOptions: {
title: 'RectangleROI Threshold Tip',
text:
'RectangleROI Threshold tool should be used on PT Axial Viewport',
text: 'RectangleROI Threshold tool should be used on PT Axial Viewport',
type: 'info',
},
},
@@ -338,6 +345,7 @@ const toolbarButtons = [
tooltip: 'PET Image Colormap',
},
isAction: true, // ?
renderer: WindowLevelMenuItem,
items: [
_createColormap('HSV', 'hsv'),
_createColormap('Hot Iron', 'hot_iron'),
+1
View File
@@ -149,6 +149,7 @@
]
},
"resolutions": {
"@cornerstonejs/core": "^1.1.0",
"**/@babel/runtime": "^7.20.13",
"commander": "8.3.0",
"nth-check": "^2.1.1",
@@ -1,5 +1,5 @@
describe('OHIF Context Menu', function() {
beforeEach(function() {
describe('OHIF Context Menu', function () {
beforeEach(function () {
cy.checkStudyRouteInViewer(
'1.2.840.113619.2.5.1762583153.215519.978957063.78'
);
@@ -10,10 +10,10 @@ describe('OHIF Context Menu', function() {
cy.resetViewport().wait(50);
});
it('checks context menu customization', function() {
it('checks context menu customization', function () {
// Add length measurement
cy.addLengthMeasurement();
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
cy.get('[data-cy="measurement-item"]').click();
const [x1, y1] = [150, 100];
@@ -113,7 +113,7 @@ describe('OHIF Cornerstone Toolbar', () => {
cy.addLengthMeasurement();
cy.get('[data-cy="viewport-notification"]').should('exist');
cy.get('[data-cy="viewport-notification"]').should('be.visible');
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
//Verify the measurement exists in the table
cy.get('@measurementsPanel').should('be.visible');
@@ -27,7 +27,7 @@ describe('OHIF Measurement Panel', function() {
cy.addLengthMeasurement();
cy.get('[data-cy="viewport-notification"]').should('exist');
cy.get('[data-cy="viewport-notification"]').should('be.visible');
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
cy.get('[data-cy="measurement-item"]').click();
cy.get('[data-cy="measurement-item"]')
@@ -46,7 +46,7 @@ describe('OHIF Measurement Panel', function() {
it('checks if image would jump when clicked on a measurement item', function() {
// Add length measurement
cy.addLengthMeasurement();
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
cy.scrollToIndex(13);
-2
View File
@@ -43,5 +43,3 @@
# COMMENT: For sharedArrayBuffer, see https://developer.chrome.com/blog/enabling-shared-array-buffer/
Cross-Origin-Embedder-Policy = "require-corp"
Cross-Origin-Opener-Policy = "same-origin"
# set CORP to cross-origin for anyone who wants to use the viewer in an iframe
Cross-Origin-Resource-Policy = "cross-origin"
+18 -18
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/app",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"productVersion": "3.4.0",
"description": "OHIF Viewer",
"author": "OHIF Contributors",
@@ -51,23 +51,23 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2",
"@cornerstonejs/codec-openjph": "^2.4.2",
"@cornerstonejs/dicom-image-loader": "^1.4.1",
"@ohif/core": "3.7.0-beta.32",
"@ohif/extension-cornerstone": "3.7.0-beta.32",
"@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.32",
"@ohif/extension-cornerstone-dicom-seg": "3.7.0-beta.32",
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.32",
"@ohif/extension-default": "3.7.0-beta.32",
"@ohif/extension-dicom-microscopy": "3.7.0-beta.32",
"@ohif/extension-dicom-pdf": "3.7.0-beta.32",
"@ohif/extension-dicom-video": "3.7.0-beta.32",
"@ohif/extension-test": "3.7.0-beta.32",
"@ohif/i18n": "3.7.0-beta.32",
"@ohif/mode-basic-dev-mode": "3.7.0-beta.32",
"@ohif/mode-longitudinal": "3.7.0-beta.32",
"@ohif/mode-microscopy": "3.7.0-beta.32",
"@ohif/mode-test": "3.7.0-beta.32",
"@ohif/ui": "3.7.0-beta.32",
"@cornerstonejs/dicom-image-loader": "^0.6.8",
"@ohif/core": "3.6.0",
"@ohif/extension-cornerstone": "3.6.0",
"@ohif/extension-cornerstone-dicom-rt": "3.6.0",
"@ohif/extension-cornerstone-dicom-seg": "3.6.0",
"@ohif/extension-cornerstone-dicom-sr": "3.6.0",
"@ohif/extension-default": "3.6.0",
"@ohif/extension-dicom-microscopy": "3.6.0",
"@ohif/extension-dicom-pdf": "3.6.0",
"@ohif/extension-dicom-video": "3.6.0",
"@ohif/extension-test": "3.6.0",
"@ohif/i18n": "3.6.0",
"@ohif/mode-basic-dev-mode": "3.6.0",
"@ohif/mode-longitudinal": "3.6.0",
"@ohif/mode-microscopy": "3.6.0",
"@ohif/mode-test": "3.6.0",
"@ohif/ui": "3.6.0",
"@types/react": "^17.0.38",
"classnames": "^2.3.2",
"core-js": "^3.16.1",
+1 -2
View File
@@ -4,7 +4,7 @@ window.config = {
modes: [],
showStudyList: true,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -30,7 +30,6 @@ window.config = {
supportsFuzzyMatching: false,
supportsWildcard: false,
staticWado: true,
omitQuotationForMultipartRequest: true,
},
},
{
+2 -1
View File
@@ -11,6 +11,7 @@ window.config = {
// some windows systems have issues with more than 3 web workers
maxNumberOfWebWorkers: 3,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -50,6 +51,7 @@ window.config = {
wadoUriRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
wadoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoSupportsIncludeField: false,
supportsReject: false,
imageRendering: 'wadors',
@@ -66,7 +68,6 @@ window.config = {
enabled: true,
relativeResolution: 'studies',
},
omitQuotationForMultipartRequest: true,
},
},
{
+1 -1
View File
@@ -4,6 +4,7 @@ window.config = {
extensions: [],
showStudyList: true,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
strictZSpacingForVolumeViewport: true,
showCPUFallbackMessage: true,
@@ -24,7 +25,6 @@ window.config = {
bulkDataURI: {
enabled: false,
},
omitQuotationForMultipartRequest: true,
},
},
],
@@ -4,6 +4,7 @@ window.config = {
modes: [],
showStudyList: true,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -27,7 +28,6 @@ window.config = {
enableStudyLazyLoad: true,
supportsFuzzyMatching: false,
supportsWildcard: false,
omitQuotationForMultipartRequest: true,
},
},
{
@@ -5,6 +5,7 @@ window.config = {
showStudyList: true,
maxNumberOfWebWorkers: 3,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -30,7 +31,6 @@ window.config = {
supportsWildcard: true,
staticWado: true,
singlepart: 'bulkdata,video,pdf',
omitQuotationForMultipartRequest: true,
},
},
{
@@ -4,6 +4,7 @@ window.config = {
extensions: [],
modes: [],
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -22,7 +23,6 @@ window.config = {
qidoSupportsIncludeField: false,
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
omitQuotationForMultipartRequest: true,
},
},
{
@@ -2,6 +2,7 @@ window.config = {
routerBasename: '/',
showStudyList: true,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -17,7 +18,6 @@ window.config = {
qidoSupportsIncludeField: false,
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
omitQuotationForMultipartRequest: true,
// REQUIRED TAG:
// TODO: Remove tag after https://github.com/OHIF/ohif-core/pull/19 is merged and we bump version
// requestOptions: {
@@ -4,7 +4,7 @@ window.config = {
extensions: [],
modes: [],
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -23,7 +23,6 @@ window.config = {
qidoSupportsIncludeField: false,
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
omitQuotationForMultipartRequest: true,
},
},
{
+1 -1
View File
@@ -4,6 +4,7 @@ window.config = {
modes: ['@ohif/mode-test'],
showStudyList: true,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
maxNumberOfWebWorkers: 3,
showWarningMessageForCrossOrigin: false,
showCPUFallbackMessage: false,
@@ -30,7 +31,6 @@ window.config = {
supportsFuzzyMatching: false,
supportsWildcard: true,
singlepart: 'video,thumbnail,pdf',
omitQuotationForMultipartRequest: true,
},
},
{
+1 -1
View File
@@ -6,6 +6,7 @@ window.config = {
},
enableGoogleCloudAdapter: false,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -54,7 +55,6 @@ window.config = {
supportsFuzzyMatching: true,
supportsWildcard: false,
dicomUploadEnabled: true,
omitQuotationForMultipartRequest: true,
},
},
{
+1
View File
@@ -2,6 +2,7 @@ window.config = {
routerBasename: '/',
enableGoogleCloudAdapter: true,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
+1 -1
View File
@@ -8,6 +8,7 @@ window.config = {
extensions: [],
modes: [],
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -38,7 +39,6 @@ window.config = {
bulkDataURI: {
enabled: true,
},
omitQuotationForMultipartRequest: true,
},
},
{
+1 -1
View File
@@ -8,6 +8,7 @@ window.config = {
showStudyList: true,
maxNumberOfWebWorkers: 4,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -32,7 +33,6 @@ window.config = {
supportsWildcard: true,
staticWado: true,
singlepart: 'bulkdata,video,pdf',
omitQuotationForMultipartRequest: true,
},
},
{
+1 -1
View File
@@ -16,6 +16,7 @@ window.config = {
showStudyList: true,
maxNumberOfWebWorkers: 4,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -41,7 +42,6 @@ window.config = {
supportsWildcard: true,
staticWado: true,
singlepart: 'bulkdata,video,pdf',
omitQuotationForMultipartRequest: true,
},
},
{
+1 -1
View File
@@ -4,6 +4,7 @@ window.config = {
modes: [],
showStudyList: true,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -37,7 +38,6 @@ window.config = {
enabled: true,
relativeResolution: 'studies',
},
omitQuotationForMultipartRequest: true,
},
},
{
@@ -2,6 +2,7 @@ window.config = {
routerBasename: '/',
showStudyList: true,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
@@ -17,7 +18,6 @@ window.config = {
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
supportsFuzzyMatching: true,
omitQuotationForMultipartRequest: true,
},
],
},
+38 -48
View File
@@ -15,7 +15,7 @@ import { utils, hotkeys, ServicesManager } from '@ohif/core';
import {
Icon,
StudyListExpandedRow,
LegacyButton,
Button,
EmptyStudies,
StudyListTable,
StudyListPagination,
@@ -336,56 +336,46 @@ function WorkList({
: []
}
>
<div className="flex flex-row gap-2">
{appConfig.loadedModes.map((mode, i) => {
const isFirst = i === 0;
{appConfig.loadedModes.map((mode, i) => {
const isFirst = i === 0;
const modalitiesToCheck = modalities.replaceAll('/', '\\');
const modalitiesToCheck = modalities.replaceAll('/', '\\');
const isValidMode = mode.isValidMode({
modalities: modalitiesToCheck,
study,
});
// TODO: Modes need a default/target route? We mostly support a single one for now.
// We should also be using the route path, but currently are not
// mode.routeName
// mode.routes[x].path
// Don't specify default data source, and it should just be picked up... (this may not currently be the case)
// How do we know which params to pass? Today, it's just StudyInstanceUIDs and configUrl if exists
const query = new URLSearchParams();
if (filterValues.configUrl) {
query.append('configUrl', filterValues.configUrl);
}
query.append('StudyInstanceUIDs', studyInstanceUid);
return (
<Link
className={isValidMode ? '' : 'cursor-not-allowed'}
key={i}
to={`${dataPath ? '../../' : ''}${mode.routeName}${dataPath ||
''}?${query.toString()}`}
onClick={event => {
// In case any event bubbles up for an invalid mode, prevent the navigation.
// For example, the event bubbles up when the icon embedded in the disabled button is clicked.
if (!isValidMode) {
event.preventDefault();
}
}}
// to={`${mode.routeName}/dicomweb?StudyInstanceUIDs=${studyInstanceUid}`}
const isValidMode = mode.isValidMode({
modalities: modalitiesToCheck,
study,
});
// TODO: Modes need a default/target route? We mostly support a single one for now.
// We should also be using the route path, but currently are not
// mode.routeName
// mode.routes[x].path
// Don't specify default data source, and it should just be picked up... (this may not currently be the case)
// How do we know which params to pass? Today, it's just StudyInstanceUIDs and configUrl if exists
const query = new URLSearchParams();
if (filterValues.configUrl) {
query.append('configUrl', filterValues.configUrl);
}
query.append('StudyInstanceUIDs', studyInstanceUid);
return (
<Link
key={i}
to={`${dataPath ? '../../' : ''}${mode.routeName}${dataPath ||
''}?${query.toString()}`}
// to={`${mode.routeName}/dicomweb?StudyInstanceUIDs=${studyInstanceUid}`}
>
<Button
rounded="full"
variant={isValidMode ? 'contained' : 'disabled'}
disabled={!isValidMode}
endIcon={<Icon name="launch-arrow" />} // launch-arrow | launch-info
className={classnames('font-medium ', { 'ml-2': !isFirst })}
onClick={() => {}}
>
{/* TODO revisit the completely rounded style of buttons used for launching a mode from the worklist later - for now use LegacyButton*/}
<LegacyButton
rounded="full"
variant={isValidMode ? 'contained' : 'disabled'}
disabled={!isValidMode}
endIcon={<Icon name="launch-arrow" />} // launch-arrow | launch-info
onClick={() => {}}
>
{t(`Modes:${mode.displayName}`)}
</LegacyButton>
</Link>
);
})}
</div>
{t(`Modes:${mode.displayName}`)}
</Button>
</Link>
);
})}
</StudyListExpandedRow>
),
onClickRow: () =>
-7
View File
@@ -74,16 +74,9 @@ module.exports = {
},
customblue: {
10: '#0A163F',
20: '#0B1F54',
30: '#09286e',
40: '#0E307F',
50: '#0F3A94',
80: '#1454D4',
100: '#c4fdff',
200: '#38daff',
300: '#1D204D',
400: '#90A0C1',
},
customgray: {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/cli",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "A CLI to bootstrap new OHIF extension or mode",
"type": "module",
"main": "src/index.js",
@@ -1,26 +1,5 @@
// https://babeljs.io/docs/en/options#babelrcroots
const { extendDefaultPlugins } = require('svgo');
module.exports = {
plugins: [
[
'inline-react-svg',
{
svgo: {
plugins: extendDefaultPlugins([
{
name: 'removeViewBox',
active: false,
},
]),
},
},
],
['@babel/plugin-proposal-class-properties', { loose: true }],
'@babel/plugin-transform-typescript',
['@babel/plugin-proposal-private-property-in-object', { loose: true }],
['@babel/plugin-proposal-private-methods', { loose: true }],
],
plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'],
env: {
test: {
presets: [
@@ -31,16 +10,15 @@ module.exports = {
modules: 'commonjs',
debug: false,
},
"@babel/preset-typescript",
],
'@babel/preset-react',
'@babel/preset-typescript',
],
plugins: [
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-transform-regenerator',
'@babel/plugin-transform-runtime',
'@babel/plugin-transform-typescript',
],
},
production: {
@@ -48,7 +26,7 @@ module.exports = {
// WebPack handles ES6 --> Target Syntax
['@babel/preset-env', { modules: false }],
'@babel/preset-react',
'@babel/preset-typescript',
"@babel/preset-typescript",
],
ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'],
},
@@ -57,7 +35,7 @@ module.exports = {
// WebPack handles ES6 --> Target Syntax
['@babel/preset-env', { modules: false }],
'@babel/preset-react',
'@babel/preset-typescript',
"@babel/preset-typescript",
],
plugins: ['react-hot-loader/babel'],
ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'],
@@ -9,7 +9,7 @@
},
"scripts": {
"dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
"dev:my-extension": "yarn run dev",
"dev:dicom-pdf": "yarn run dev",
"build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
"build:package": "yarn run build",
"start": "yarn run dev"
@@ -40,14 +40,14 @@
"@babel/plugin-transform-arrow-functions": "^7.16.7",
"@babel/plugin-transform-regenerator": "^7.16.7",
"@babel/plugin-transform-runtime": "^7.17.0",
"babel-plugin-inline-react-svg": "^2.0.1",
"@babel/plugin-transform-typescript": "^7.13.0",
"@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"@babel/preset-typescript": "^7.13.0",
"babel-eslint": "9.x",
"babel-loader": "^8.2.4",
"babel-plugin-inline-react-svg": "^2.0.2",
"babel-plugin-module-resolver": "^5.0.0",
"babel-eslint": "^8.0.3",
"babel-loader": "^8.0.0-beta.4",
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^10.2.0",
"cross-env": "^7.0.3",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/core",
"version": "3.7.0-beta.32",
"version": "3.6.0",
"description": "Generic business logic for web-based medical imaging applications",
"author": "OHIF Core Team",
"license": "MIT",
@@ -35,8 +35,8 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2",
"@cornerstonejs/codec-openjph": "^2.4.2",
"@cornerstonejs/dicom-image-loader": "^1.4.1",
"@ohif/ui": "3.7.0-beta.32",
"@cornerstonejs/dicom-image-loader": "^0.6.8",
"@ohif/ui": "3.6.0",
"cornerstone-math": "0.1.9",
"dicom-parser": "^1.8.21"
},
+24 -25
View File
@@ -173,31 +173,30 @@ const bindings = [
label: 'W/L Preset 5',
keys: ['5'],
},
// These don't exist, so don't try applying them....
// {
// commandName: 'setWindowLevel',
// commandOptions: windowLevelPresets[6],
// label: 'W/L Preset 6',
// keys: ['6'],
// },
// {
// commandName: 'setWindowLevel',
// commandOptions: windowLevelPresets[7],
// label: 'W/L Preset 7',
// keys: ['7'],
// },
// {
// commandName: 'setWindowLevel',
// commandOptions: windowLevelPresets[8],
// label: 'W/L Preset 8',
// keys: ['8'],
// },
// {
// commandName: 'setWindowLevel',
// commandOptions: windowLevelPresets[9],
// label: 'W/L Preset 9',
// keys: ['9'],
// },
{
commandName: 'setWindowLevel',
commandOptions: windowLevelPresets[6],
label: 'W/L Preset 6',
keys: ['6'],
},
{
commandName: 'setWindowLevel',
commandOptions: windowLevelPresets[7],
label: 'W/L Preset 7',
keys: ['7'],
},
{
commandName: 'setWindowLevel',
commandOptions: windowLevelPresets[8],
label: 'W/L Preset 8',
keys: ['8'],
},
{
commandName: 'setWindowLevel',
commandOptions: windowLevelPresets[9],
label: 'W/L Preset 9',
keys: ['9'],
},
];
export default bindings;
@@ -695,18 +695,15 @@ export default class HangingProtocolService extends PubSubService {
) {
viewport.displaySets.forEach(displaySet => {
const { id } = displaySet;
const displaySetMatchDetail = displaySetMatchDetails.get(id);
const {
displaySetInstanceUID: oldDisplaySetInstanceUID,
} = displaySetMatchDetails.get(id);
const { displaySetInstanceUID: oldDisplaySetInstanceUID } = displaySetMatchDetail;
const displaySetInstanceUID =
displaySetInstanceUIDs.push(
displaySet.id === displaySetSelectorId
? newDisplaySetInstanceUID
: oldDisplaySetInstanceUID;
displaySetMatchDetail.displaySetInstanceUID = displaySetInstanceUID;
displaySetInstanceUIDs.push(displaySetInstanceUID);
: oldDisplaySetInstanceUID
);
displaySetOptions.push(displaySet);
});
}
@@ -1392,20 +1389,17 @@ export default class HangingProtocolService extends PubSubService {
this.studies.forEach(study => {
// Skip non-active if active only
if (matchActiveOnly && this.activeStudy !== study) return;
const studyDisplaySets = this.displaySets.filter(
it => it.StudyInstanceUID === study.StudyInstanceUID
it => it.StudyInstanceUID === study.StudyInstanceUID
);
const studyMatchDetails = this.protocolEngine.findMatch(
study,
studyMatchingRules,
{
studies: this.studies,
displaySets: studyDisplaySets,
allDisplaySets: this.displaySets,
displaySetMatchDetails: this.displaySetMatchDetails,
}
study,
studyMatchingRules,
{
studies: this.studies,
displaySets: studyDisplaySets,
displaySetMatchDetails: this.displaySetMatchDetails,
}
);
// Prevent bestMatch from being updated if the matchDetails' required attribute check has failed
@@ -1414,10 +1408,10 @@ export default class HangingProtocolService extends PubSubService {
}
this.debug(
'study',
study.StudyInstanceUID,
'display sets #',
studyDisplaySets.length
'study',
study.StudyInstanceUID,
'display sets #',
studyDisplaySets.length
);
studyDisplaySets.forEach(displaySet => {
const {
@@ -1426,15 +1420,15 @@ export default class HangingProtocolService extends PubSubService {
displaySetInstanceUID,
} = displaySet;
const seriesMatchDetails = this.protocolEngine.findMatch(
displaySet,
seriesMatchingRules,
// Todo: why we have images here since the matching type does not have it
{
studies: this.studies,
instance: displaySet.images?.[0],
displaySetMatchDetails: this.displaySetMatchDetails,
displaySets: studyDisplaySets,
}
displaySet,
seriesMatchingRules,
// Todo: why we have images here since the matching type does not have it
{
studies: this.studies,
instance: displaySet.images?.[0],
displaySetMatchDetails: this.displaySetMatchDetails,
displaySets: studyDisplaySets,
}
);
// Prevent bestMatch from being updated if the matchDetails' required attribute check has failed
Loaded 100 of 578 files, more files were not shown because too many files have changed in this diff. Show more