Compare commits
137
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d104add05 | ||
|
|
924a5478f3 | ||
|
|
d8f628b125 | ||
|
|
cab8d322c2 | ||
|
|
3ef26cc670 | ||
|
|
1efe2db662 | ||
|
|
72933af984 | ||
|
|
2645e3c7aa | ||
|
|
81ab52784a | ||
|
|
09a302250c | ||
|
|
783bab7c9d | ||
|
|
7bbc213f58 | ||
|
|
6d88978710 | ||
|
|
32bb553b05 | ||
|
|
d5cbbb037d | ||
|
|
b904ea0f23 | ||
|
|
839923e578 | ||
|
|
030e1e4104 | ||
|
|
265c1fbb10 | ||
|
|
f3aa8a8b61 | ||
|
|
18156bb7b1 | ||
|
|
93a009f1a6 | ||
|
|
11471e6fc1 | ||
|
|
7d286a07f2 | ||
|
|
19418df8b5 | ||
|
|
c9eb0250dd | ||
|
|
c3cd265430 | ||
|
|
913264d289 | ||
|
|
74acc02c37 | ||
|
|
453ff0be4f | ||
|
|
2e040d550d | ||
|
|
bfa1b1c7c0 | ||
|
|
a3e7ff479a | ||
|
|
87f361516c | ||
|
|
5eaf6168f6 | ||
|
|
5ab74f5020 | ||
|
|
92273b25b3 | ||
|
|
3f296bdeb5 | ||
|
|
0600858055 | ||
|
|
4a184d0be7 | ||
|
|
f3a4f861b4 | ||
|
|
fc19912162 | ||
|
|
61595ce7d6 | ||
|
|
ffd53eff85 | ||
|
|
52a43c771a | ||
|
|
c3c132d268 | ||
|
|
e742328ac1 | ||
|
|
90647b63a0 | ||
|
|
ed44ad7f4b | ||
|
|
b0a456a46c | ||
|
|
8b7db45641 | ||
|
|
b5599dde4e | ||
|
|
f7b7131d70 | ||
|
|
d646c15c27 | ||
|
|
64f8bb580a | ||
|
|
ce29bbe795 | ||
|
|
0bbcb4269d | ||
|
|
3efa793e60 | ||
|
|
3b50bd8cc4 | ||
|
|
cd553e29b2 | ||
|
|
12dd5a2619 | ||
|
|
f7a435c2f3 | ||
|
|
19f1da702f | ||
|
|
14974b6973 | ||
|
|
b4dbe5656b | ||
|
|
c6f7349fd7 | ||
|
|
abe939bd20 | ||
|
|
4d4dd45c23 | ||
|
|
7671b9faf4 | ||
|
|
e653961858 | ||
|
|
aeb61f40da | ||
|
|
b5fb2461dd | ||
|
|
15ad8f29cd | ||
|
|
fa37593696 | ||
|
|
08eed4cdf9 | ||
|
|
b5b7d323c8 | ||
|
|
8a8ae237d2 | ||
|
|
cf1e00fee0 | ||
|
|
ef4f28690a | ||
|
|
c98211ccb5 | ||
|
|
71342fac8f | ||
|
|
52f419d188 | ||
|
|
ca3a0b56f7 | ||
|
|
1a91f210ab | ||
|
|
3503e6e9f4 | ||
|
|
0c51444066 | ||
|
|
83c453d1f3 | ||
|
|
fa73a458bd | ||
|
|
5670a1699d | ||
|
|
c529c0da9c | ||
|
|
d51211f6b9 | ||
|
|
2d8400f9d8 | ||
|
|
e12242a15c | ||
|
|
8baf9deaf0 | ||
|
|
a34a0b1a3a | ||
|
|
e1545b67da | ||
|
|
d75305e70d | ||
|
|
242beb7b46 | ||
|
|
c5d4e97115 | ||
|
|
59cdc4ba9a | ||
|
|
971c594791 | ||
|
|
c55136f55e | ||
|
|
63e12dd651 | ||
|
|
c75c6af22f | ||
|
|
3c777ba58b | ||
|
|
e6f73a2025 | ||
|
|
652e61a417 | ||
|
|
48bcdd6b50 | ||
|
|
cc73f15c8c | ||
|
|
3dce70e624 | ||
|
|
1d00893c49 | ||
|
|
2890635675 | ||
|
|
a6d967a37e | ||
|
|
f23a4500f5 | ||
|
|
cadb559619 | ||
|
|
ad3ef3e8ef | ||
|
|
18c6a47dca | ||
|
|
93f30f06c2 | ||
|
|
50d2640876 | ||
|
|
10e399d7b8 | ||
|
|
e4937e7473 | ||
|
|
62dd2e78bd | ||
|
|
c3654b7ddf | ||
|
|
de60586b71 | ||
|
|
f670678cf0 | ||
|
|
56633a67d9 | ||
|
|
8e2535a308 | ||
|
|
6da1734b6e | ||
|
|
5ae6e9caf4 | ||
|
|
5e4043d99c | ||
|
|
0e991d6bde | ||
|
|
2f63a9db80 | ||
|
|
bedc379e97 | ||
|
|
5b7dc9e9c3 | ||
|
|
00099c0136 | ||
|
|
799d648a90 | ||
|
|
d5c347cecd |
No files matched your search
@@ -1,5 +1,6 @@
|
||||
server {
|
||||
listen ${PORT};
|
||||
listen ${PORT} default_server;
|
||||
listen [::]:${PORT} default_server;
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
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,6 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
envsubst '${PORT}' < /usr/src/default.conf.template > /etc/nginx/conf.d/default.conf
|
||||
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
|
||||
|
||||
if [ -n "$CLIENT_ID" ] || [ -n "$HEALTHCARE_API_ENDPOINT" ]
|
||||
then
|
||||
|
||||
@@ -73,15 +73,6 @@ 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',
|
||||
},
|
||||
|
||||
+6
-1
@@ -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.23.1-alpine as final
|
||||
FROM nginxinc/nginx-unprivileged:1.25-alpine as final
|
||||
#RUN apk add --no-cache bash
|
||||
ENV PORT=80
|
||||
RUN rm /etc/nginx/conf.d/default.conf
|
||||
@@ -69,5 +69,10 @@ 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;"]
|
||||
@@ -34,13 +34,15 @@ provided by the <a href="https://ohif.org/">Open Health Imaging Foundation (OHIF
|
||||
<!-- [](#contributors) -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
| | |
|
||||
| :-: | :--- |
|
||||
| <img src="platform/docs/docs/assets/img/demo-measurements.jpg" alt="Measurement tracking" width="350"/> | Measurement Tracking |
|
||||
| <img src="platform/docs/docs/assets/img/demo-segmentation.png" alt="Segmentations" width="350"/> | Labelmap Segmentations |
|
||||
| <img src="platform/docs/docs/assets/img/demo-ptct.png" alt="Hanging Protocols" width="350"/> | Fusion and Custom Hanging protocols |
|
||||
| <img src="platform/docs/docs/assets/img/demo-microscopy.png" alt="Microscopy" width="350"/> | Slide Microscopy |
|
||||
| <img src="platform/docs/docs/assets/img/demo-volumeRendering.png" alt="Volume Rendering" width="350"/> | Volume Rendering |
|
||||
|
||||
| | | |
|
||||
| :-: | :--- | :--- |
|
||||
| <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) |
|
||||
|
||||
|
||||
|
||||
## About
|
||||
@@ -161,7 +163,7 @@ yarn install
|
||||
|
||||
These commands are available from the root directory. Each project directory
|
||||
also supports a number of commands that can be found in their respective
|
||||
`README.md` and `project.json` files.
|
||||
`README.md` and `package.json` files.
|
||||
|
||||
| Yarn Commands | Description |
|
||||
| ---------------------------- | ------------------------------------------------------------- |
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
14369414cf0193f00243ae5c9f8415cf7079a753
|
||||
d8f628b12501e53eff778e9e0acddb3da7a785b5
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-rt",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"description": "DICOM RT read workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -31,10 +31,10 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.2",
|
||||
"@ohif/extension-default": "3.7.0-beta.2",
|
||||
"@ohif/i18n": "3.7.0-beta.2",
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.39",
|
||||
"@ohif/extension-default": "3.7.0-beta.39",
|
||||
"@ohif/i18n": "3.7.0-beta.39",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
|
||||
@@ -181,12 +181,6 @@ 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,3 +1,4 @@
|
||||
import { ButtonEnums } from '@ohif/ui';
|
||||
import hydrateRTDisplaySet from './_hydrateRT';
|
||||
|
||||
const RESPONSE = {
|
||||
@@ -38,12 +39,12 @@ function _askHydrate(uiViewportDialogService, viewportIndex) {
|
||||
const message = 'Do you want to open this Segmentation?';
|
||||
const actions = [
|
||||
{
|
||||
type: 'secondary',
|
||||
type: ButtonEnums.type.secondary,
|
||||
text: 'No',
|
||||
value: RESPONSE.CANCEL,
|
||||
},
|
||||
{
|
||||
type: 'primary',
|
||||
type: ButtonEnums.type.primary,
|
||||
text: 'Yes',
|
||||
value: RESPONSE.HYDRATE_SEG,
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-seg",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"description": "DICOM SEG read workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -31,10 +31,10 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.2",
|
||||
"@ohif/extension-default": "3.7.0-beta.2",
|
||||
"@ohif/i18n": "3.7.0-beta.2",
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.39",
|
||||
"@ohif/extension-default": "3.7.0-beta.39",
|
||||
"@ohif/i18n": "3.7.0-beta.39",
|
||||
"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 } from '@ohif/ui';
|
||||
import { Input, Dialog, ButtonEnums } 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: 'primary' },
|
||||
{ id: 'save', text: 'Confirm', type: 'secondary' },
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Confirm', type: ButtonEnums.type.primary },
|
||||
],
|
||||
onSubmit: onSubmitHandler,
|
||||
body: ({ value, setValue }) => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ButtonEnums } from '@ohif/ui';
|
||||
import hydrateSEGDisplaySet from './_hydrateSEG';
|
||||
|
||||
const RESPONSE = {
|
||||
@@ -6,11 +7,7 @@ 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) {
|
||||
@@ -36,12 +33,12 @@ function _askHydrate(uiViewportDialogService, viewportIndex) {
|
||||
const message = 'Do you want to open this Segmentation?';
|
||||
const actions = [
|
||||
{
|
||||
type: 'secondary',
|
||||
type: ButtonEnums.type.secondary,
|
||||
text: 'No',
|
||||
value: RESPONSE.CANCEL,
|
||||
},
|
||||
{
|
||||
type: 'primary',
|
||||
type: ButtonEnums.type.primary,
|
||||
text: 'Yes',
|
||||
value: RESPONSE.HYDRATE_SEG,
|
||||
},
|
||||
|
||||
@@ -71,7 +71,8 @@ function OHIFCornerstoneSEGViewport(props) {
|
||||
|
||||
const referencedDisplaySet = segDisplaySet.getReferenceDisplaySet();
|
||||
const referencedDisplaySetMetadata = _getReferencedDisplaySetMetadata(
|
||||
referencedDisplaySet
|
||||
referencedDisplaySet,
|
||||
segDisplaySet
|
||||
);
|
||||
|
||||
referencedDisplaySetRef.current = {
|
||||
@@ -343,10 +344,10 @@ function OHIFCornerstoneSEGViewport(props) {
|
||||
patientSex: PatientSex || '',
|
||||
patientAge: PatientAge || '',
|
||||
MRN: PatientID || '',
|
||||
thickness: SliceThickness ? `${SliceThickness.toFixed(2)}mm` : '',
|
||||
thickness: SliceThickness ? `${parseFloat(SliceThickness).toFixed(2)}mm` : '',
|
||||
spacing:
|
||||
SpacingBetweenSlices !== undefined
|
||||
? `${SpacingBetweenSlices.toFixed(2)}mm`
|
||||
? `${parseFloat(SpacingBetweenSlices).toFixed(2)}mm`
|
||||
: '',
|
||||
scanner: ManufacturerModelName || '',
|
||||
},
|
||||
@@ -381,20 +382,28 @@ OHIFCornerstoneSEGViewport.defaultProps = {
|
||||
customProps: {},
|
||||
};
|
||||
|
||||
function _getReferencedDisplaySetMetadata(referencedDisplaySet) {
|
||||
function _getReferencedDisplaySetMetadata(referencedDisplaySet, segDisplaySet) {
|
||||
const {
|
||||
SharedFunctionalGroupsSequence: [SharedFunctionalGroup],
|
||||
} = segDisplaySet.instance;
|
||||
const {
|
||||
PixelMeasuresSequence: [PixelMeasures],
|
||||
} = SharedFunctionalGroup;
|
||||
const { SpacingBetweenSlices, SliceThickness } = PixelMeasures;
|
||||
|
||||
const image0 = referencedDisplaySet.images[0];
|
||||
const referencedDisplaySetMetadata = {
|
||||
PatientID: image0.PatientID,
|
||||
PatientName: image0.PatientName,
|
||||
PatientSex: image0.PatientSex,
|
||||
PatientAge: image0.PatientAge,
|
||||
SliceThickness: image0.SliceThickness,
|
||||
SliceThickness: image0.SliceThickness || SliceThickness,
|
||||
StudyDate: image0.StudyDate,
|
||||
SeriesDescription: image0.SeriesDescription,
|
||||
SeriesInstanceUID: image0.SeriesInstanceUID,
|
||||
SeriesNumber: image0.SeriesNumber,
|
||||
ManufacturerModelName: image0.ManufacturerModelName,
|
||||
SpacingBetweenSlices: image0.SpacingBetweenSlices,
|
||||
SpacingBetweenSlices: image0.SpacingBetweenSlices || SpacingBetweenSlices,
|
||||
};
|
||||
|
||||
return referencedDisplaySetMetadata;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-sr",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.2",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.2",
|
||||
"@ohif/ui": "3.7.0-beta.2",
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.39",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.39",
|
||||
"@ohif/ui": "3.7.0-beta.39",
|
||||
"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.1.8",
|
||||
"@cornerstonejs/core": "^1.1.8",
|
||||
"@cornerstonejs/tools": "^1.1.8",
|
||||
"@cornerstonejs/adapters": "^1.5.0",
|
||||
"@cornerstonejs/core": "^1.5.0",
|
||||
"@cornerstonejs/tools": "^1.5.0",
|
||||
"classnames": "^2.3.2"
|
||||
}
|
||||
}
|
||||
@@ -225,6 +225,7 @@ function OHIFCornerstoneSRViewport(props) {
|
||||
}}
|
||||
onElementEnabled={onElementEnabled}
|
||||
initialImageIndex={initialImageIndex}
|
||||
isJumpToMeasurementDisabled={true}
|
||||
></Component>
|
||||
);
|
||||
}, [activeImageDisplaySetData, viewportIndex, measurementSelected]);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.1.8",
|
||||
"@ohif/core": "3.7.0-beta.2",
|
||||
"@ohif/ui": "3.7.0-beta.2",
|
||||
"@cornerstonejs/dicom-image-loader": "^1.4.1",
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/ui": "3.7.0-beta.39",
|
||||
"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.1.8",
|
||||
"@cornerstonejs/core": "^1.1.8",
|
||||
"@cornerstonejs/streaming-image-volume-loader": "^1.1.8",
|
||||
"@cornerstonejs/tools": "^1.1.8",
|
||||
"@cornerstonejs/adapters": "^1.5.0",
|
||||
"@cornerstonejs/core": "^1.5.0",
|
||||
"@cornerstonejs/streaming-image-volume-loader": "^1.5.0",
|
||||
"@cornerstonejs/tools": "^1.5.0",
|
||||
"@kitware/vtk.js": "27.3.1",
|
||||
"html2canvas": "^1.4.1",
|
||||
"lodash.debounce": "4.0.8",
|
||||
|
||||
@@ -10,13 +10,7 @@ import {
|
||||
utilities as csUtils,
|
||||
} from '@cornerstonejs/core';
|
||||
import { MeasurementService } from '@ohif/core';
|
||||
import {
|
||||
CinePlayer,
|
||||
useCine,
|
||||
useViewportGrid,
|
||||
Notification,
|
||||
useViewportDialog,
|
||||
} from '@ohif/ui';
|
||||
import { Notification, useViewportDialog } from '@ohif/ui';
|
||||
import {
|
||||
IStackViewport,
|
||||
IVolumeViewport,
|
||||
@@ -28,6 +22,7 @@ import './OHIFCornerstoneViewport.css';
|
||||
import CornerstoneOverlays from './Overlays/CornerstoneOverlays';
|
||||
import getSOPInstanceAttributes from '../utils/measurementServiceMappings/utils/getSOPInstanceAttributes';
|
||||
import CornerstoneServices from '../types/CornerstoneServices';
|
||||
import CinePlayer from '../components/CinePlayer';
|
||||
|
||||
const STACK = 'stack';
|
||||
|
||||
@@ -119,6 +114,7 @@ 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
|
||||
@@ -126,10 +122,7 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
} = props;
|
||||
|
||||
const [scrollbarHeight, setScrollbarHeight] = useState('100px');
|
||||
const [{ isCineEnabled, cines }, cineService] = useCine();
|
||||
const [{ activeViewportIndex }] = useViewportGrid();
|
||||
const [enabledVPElement, setEnabledVPElement] = useState(null);
|
||||
|
||||
const elementRef = useRef();
|
||||
|
||||
const {
|
||||
@@ -145,74 +138,6 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
} = servicesManager.services as CornerstoneServices;
|
||||
|
||||
const [viewportDialogState] = useViewportDialog();
|
||||
|
||||
const cineHandler = () => {
|
||||
if (!cines || !cines[viewportIndex] || !enabledVPElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cine = cines[viewportIndex];
|
||||
const isPlaying = cine.isPlaying || false;
|
||||
const frameRate = cine.frameRate || 24;
|
||||
|
||||
const validFrameRate = Math.max(frameRate, 1);
|
||||
|
||||
if (isPlaying) {
|
||||
cineService.playClip(enabledVPElement, {
|
||||
framesPerSecond: validFrameRate,
|
||||
});
|
||||
} else {
|
||||
cineService.stopClip(enabledVPElement);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
eventTarget.addEventListener(
|
||||
Enums.Events.STACK_VIEWPORT_NEW_STACK,
|
||||
cineHandler
|
||||
);
|
||||
|
||||
return () => {
|
||||
cineService.setCine({ id: viewportIndex, isPlaying: false });
|
||||
eventTarget.removeEventListener(
|
||||
Enums.Events.STACK_VIEWPORT_NEW_STACK,
|
||||
cineHandler
|
||||
);
|
||||
};
|
||||
}, [enabledVPElement]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!cines || !cines[viewportIndex] || !enabledVPElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
cineHandler();
|
||||
|
||||
return () => {
|
||||
if (enabledVPElement && cines?.[viewportIndex]?.isPlaying) {
|
||||
cineService.stopClip(enabledVPElement);
|
||||
}
|
||||
};
|
||||
}, [cines, viewportIndex, cineService, enabledVPElement, cineHandler]);
|
||||
|
||||
const cine = cines[viewportIndex];
|
||||
const isPlaying = (cine && cine.isPlaying) || false;
|
||||
|
||||
const handleCineClose = () => {
|
||||
toolbarService.recordInteraction({
|
||||
groupId: 'MoreTools',
|
||||
itemId: 'cine',
|
||||
interactionType: 'toggle',
|
||||
commands: [
|
||||
{
|
||||
commandName: 'toggleCine',
|
||||
commandOptions: {},
|
||||
context: 'CORNERSTONE',
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
// useCallback for scroll bar height calculation
|
||||
const setImageScrollBarHeight = useCallback(() => {
|
||||
const scrollbarHeight = `${elementRef.current.clientHeight - 20}px`;
|
||||
@@ -434,7 +359,6 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
displaySetOptions,
|
||||
presentations
|
||||
);
|
||||
|
||||
if (measurement) {
|
||||
cs3DTools.annotation.selection.setAnnotationSelected(measurement.uid);
|
||||
}
|
||||
@@ -454,6 +378,10 @@ 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,
|
||||
@@ -479,15 +407,14 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
};
|
||||
}, [displaySets, elementRef, viewportIndex]);
|
||||
|
||||
console.debug('OHIFCornerstoneViewport rendering');
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="viewport-wrapper">
|
||||
<ReactResizeDetector
|
||||
handleWidth
|
||||
handleHeight
|
||||
skipOnMount={true} // Todo: make these configurable
|
||||
refreshMode={'debounce'}
|
||||
refreshRate={200} // transition amount in side panel
|
||||
refreshMode="debounce"
|
||||
refreshRate={50} // Wait 50 ms after last move to render
|
||||
onResize={onResize}
|
||||
targetRef={elementRef.current}
|
||||
/>
|
||||
@@ -505,25 +432,11 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
scrollbarHeight={scrollbarHeight}
|
||||
servicesManager={servicesManager}
|
||||
/>
|
||||
{isCineEnabled && (
|
||||
<CinePlayer
|
||||
className="absolute left-1/2 -translate-x-1/2 bottom-3"
|
||||
isPlaying={isPlaying}
|
||||
onClose={handleCineClose}
|
||||
onPlayPauseChange={isPlaying =>
|
||||
cineService.setCine({
|
||||
id: activeViewportIndex,
|
||||
isPlaying,
|
||||
})
|
||||
}
|
||||
onFrameRateChange={frameRate =>
|
||||
cineService.setCine({
|
||||
id: activeViewportIndex,
|
||||
frameRate,
|
||||
})
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<CinePlayer
|
||||
enabledVPElement={enabledVPElement}
|
||||
viewportIndex={viewportIndex}
|
||||
servicesManager={servicesManager}
|
||||
/>
|
||||
</div>
|
||||
<div className="absolute w-full">
|
||||
{viewportDialogState.viewportIndex === viewportIndex && (
|
||||
@@ -654,7 +567,6 @@ function _jumpToMeasurement(
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfoByIndex(
|
||||
viewportIndex
|
||||
);
|
||||
|
||||
if (enabledElement) {
|
||||
// See how the jumpToSlice() of Cornerstone3D deals with imageIdx param.
|
||||
const viewport = enabledElement.viewport as
|
||||
@@ -716,6 +628,10 @@ function _jumpToMeasurement(
|
||||
// Component displayName
|
||||
OHIFCornerstoneViewport.displayName = 'OHIFCornerstoneViewport';
|
||||
|
||||
OHIFCornerstoneViewport.defaultProps = {
|
||||
isJumpToMeasurementDisabled: false,
|
||||
};
|
||||
|
||||
OHIFCornerstoneViewport.propTypes = {
|
||||
viewportIndex: PropTypes.number.isRequired,
|
||||
displaySets: PropTypes.array.isRequired,
|
||||
@@ -724,6 +640,7 @@ 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.volumes;
|
||||
const volumes = viewportData.data;
|
||||
if (volumes && volumes.length == 1) {
|
||||
const volume = volumes[0];
|
||||
imageId = volume.imageIds[imageIndex];
|
||||
|
||||
@@ -457,11 +457,9 @@ function commandsModule({
|
||||
|
||||
const { viewport } = enabledElement;
|
||||
|
||||
if (viewport instanceof StackViewport) {
|
||||
const { invert } = viewport.getProperties();
|
||||
viewport.setProperties({ invert: !invert });
|
||||
viewport.render();
|
||||
}
|
||||
const { invert } = viewport.getProperties();
|
||||
viewport.setProperties({ invert: !invert });
|
||||
viewport.render();
|
||||
},
|
||||
resetViewport: () => {
|
||||
const enabledElement = _getActiveViewportEnabledElement();
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { CinePlayer, useCine, useViewportGrid } from '@ohif/ui';
|
||||
import { Enums, eventTarget } from '@cornerstonejs/core';
|
||||
|
||||
function WrappedCinePlayer({
|
||||
enabledVPElement,
|
||||
viewportIndex,
|
||||
servicesManager,
|
||||
}) {
|
||||
const { toolbarService, customizationService } = servicesManager.services;
|
||||
const [{ isCineEnabled, cines }, cineService] = useCine();
|
||||
const [{ activeViewportIndex }] = useViewportGrid();
|
||||
|
||||
const { component: CinePlayerComponent = CinePlayer } =
|
||||
customizationService.get('cinePlayer') ?? {};
|
||||
|
||||
const handleCineClose = () => {
|
||||
toolbarService.recordInteraction({
|
||||
groupId: 'MoreTools',
|
||||
itemId: 'cine',
|
||||
interactionType: 'toggle',
|
||||
commands: [
|
||||
{
|
||||
commandName: 'toggleCine',
|
||||
commandOptions: {},
|
||||
context: 'CORNERSTONE',
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
const cineHandler = () => {
|
||||
if (!cines || !cines[viewportIndex] || !enabledVPElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cine = cines[viewportIndex];
|
||||
const isPlaying = cine.isPlaying || false;
|
||||
const frameRate = cine.frameRate || 24;
|
||||
|
||||
const validFrameRate = Math.max(frameRate, 1);
|
||||
|
||||
if (isPlaying) {
|
||||
cineService.playClip(enabledVPElement, {
|
||||
framesPerSecond: validFrameRate,
|
||||
});
|
||||
} else {
|
||||
cineService.stopClip(enabledVPElement);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
eventTarget.addEventListener(
|
||||
Enums.Events.STACK_VIEWPORT_NEW_STACK,
|
||||
cineHandler
|
||||
);
|
||||
|
||||
return () => {
|
||||
cineService.setCine({ id: viewportIndex, isPlaying: false });
|
||||
eventTarget.removeEventListener(
|
||||
Enums.Events.STACK_VIEWPORT_NEW_STACK,
|
||||
cineHandler
|
||||
);
|
||||
};
|
||||
}, [enabledVPElement]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!cines || !cines[viewportIndex] || !enabledVPElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
cineHandler();
|
||||
|
||||
return () => {
|
||||
if (enabledVPElement && cines?.[viewportIndex]?.isPlaying) {
|
||||
cineService.stopClip(enabledVPElement);
|
||||
}
|
||||
};
|
||||
}, [cines, viewportIndex, cineService, enabledVPElement, cineHandler]);
|
||||
|
||||
const cine = cines[viewportIndex];
|
||||
const isPlaying = (cine && cine.isPlaying) || false;
|
||||
|
||||
return (
|
||||
isCineEnabled && (
|
||||
<CinePlayerComponent
|
||||
className="absolute left-1/2 -translate-x-1/2 bottom-3"
|
||||
isPlaying={isPlaying}
|
||||
onClose={handleCineClose}
|
||||
onPlayPauseChange={isPlaying =>
|
||||
cineService.setCine({
|
||||
id: activeViewportIndex,
|
||||
isPlaying,
|
||||
})
|
||||
}
|
||||
onFrameRateChange={frameRate =>
|
||||
cineService.setCine({
|
||||
id: activeViewportIndex,
|
||||
frameRate,
|
||||
})
|
||||
}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default WrappedCinePlayer;
|
||||
@@ -0,0 +1,3 @@
|
||||
import CinePlayer from './CinePlayer';
|
||||
|
||||
export default CinePlayer;
|
||||
@@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import DicomFileUploader from '../../utils/DicomFileUploader';
|
||||
import DicomUploadProgress from './DicomUploadProgress';
|
||||
import { Button } from '@ohif/ui';
|
||||
import { Button, ButtonEnums } from '@ohif/ui';
|
||||
import './DicomUpload.css';
|
||||
|
||||
type DicomUploadProps = {
|
||||
@@ -46,12 +46,7 @@ function DicomUpload({
|
||||
<Dropzone onDrop={onDrop} noDrag>
|
||||
{({ getRootProps, getInputProps }) => (
|
||||
<div {...getRootProps()}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={false}
|
||||
onClick={() => {}}
|
||||
>
|
||||
<Button disabled={false} onClick={() => {}}>
|
||||
{'Add files'}
|
||||
<input {...getInputProps()} />
|
||||
</Button>
|
||||
@@ -62,9 +57,7 @@ function DicomUpload({
|
||||
{({ getRootProps, getInputProps }) => (
|
||||
<div {...getRootProps()}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primaryDark"
|
||||
border="primaryActive"
|
||||
type={ButtonEnums.type.secondary}
|
||||
disabled={false}
|
||||
onClick={() => {}}
|
||||
>
|
||||
|
||||
@@ -308,13 +308,7 @@ function DicomUploadProgress({
|
||||
} ${
|
||||
dicomFileUploaderArr.length > 1 ? 'files' : 'file'
|
||||
} completed.`}</span>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={false}
|
||||
className="ml-auto"
|
||||
onClick={onComplete}
|
||||
>
|
||||
<Button disabled={false} className="ml-auto" onClick={onComplete}>
|
||||
{'Close'}
|
||||
</Button>
|
||||
</>
|
||||
|
||||
@@ -27,7 +27,6 @@ const DicomUploadProgressItem = memo(
|
||||
const [failedReason, setFailedReason] = useState('');
|
||||
const [status, setStatus] = useState(dicomFileUploader.getStatus());
|
||||
|
||||
console.info(`${dicomFileUploader.getFileId()}`);
|
||||
const isComplete = useCallback(() => {
|
||||
return (
|
||||
status === UploadStatus.Failed ||
|
||||
|
||||
@@ -24,7 +24,6 @@ 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';
|
||||
|
||||
@@ -26,6 +26,7 @@ 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;
|
||||
@@ -69,10 +70,7 @@ export default async function init({
|
||||
|
||||
const {
|
||||
userAuthenticationService,
|
||||
measurementService,
|
||||
customizationService,
|
||||
displaySetService,
|
||||
uiDialogService,
|
||||
uiModalService,
|
||||
uiNotificationService,
|
||||
cineService,
|
||||
@@ -81,7 +79,7 @@ export default async function init({
|
||||
toolGroupService,
|
||||
viewportGridService,
|
||||
stateSyncService,
|
||||
} = servicesManager.services;
|
||||
} = servicesManager.services as CornerstoneServices;
|
||||
|
||||
window.services = servicesManager.services;
|
||||
window.extensionManager = extensionManager;
|
||||
@@ -166,7 +164,7 @@ export default async function init({
|
||||
prefetch: appConfig?.maxNumRequests?.prefetch || 10,
|
||||
};
|
||||
|
||||
initWADOImageLoader(userAuthenticationService, appConfig);
|
||||
initWADOImageLoader(userAuthenticationService, appConfig, extensionManager);
|
||||
|
||||
/* Measurement Service */
|
||||
this.measurementServiceSource = connectToolsToMeasurementService(
|
||||
|
||||
@@ -5,7 +5,7 @@ import dicomImageLoader, {
|
||||
webWorkerManager,
|
||||
} from '@cornerstonejs/dicom-image-loader';
|
||||
import dicomParser from 'dicom-parser';
|
||||
import { errorHandler } from '@ohif/core';
|
||||
import { errorHandler, utils } from '@ohif/core';
|
||||
|
||||
const { registerVolumeLoader } = volumeLoader;
|
||||
|
||||
@@ -35,7 +35,8 @@ function initWebWorkers(appConfig) {
|
||||
|
||||
export default function initWADOImageLoader(
|
||||
userAuthenticationService,
|
||||
appConfig
|
||||
appConfig,
|
||||
extensionManager
|
||||
) {
|
||||
dicomImageLoader.external.cornerstone = cornerstone;
|
||||
dicomImageLoader.external.dicomParser = dicomParser;
|
||||
@@ -55,18 +56,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: 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=*',
|
||||
Accept: acceptHeader,
|
||||
};
|
||||
|
||||
if (headers) {
|
||||
|
||||
@@ -542,6 +542,7 @@ class SegmentationService extends PubSubService {
|
||||
id: segmentationId,
|
||||
displaySetInstanceUID: segDisplaySet.displaySetInstanceUID,
|
||||
type: representationType,
|
||||
label: segDisplaySet.SeriesDescription,
|
||||
representationData: {
|
||||
[LABELMAP]: {
|
||||
volumeId: segmentationId,
|
||||
@@ -789,6 +790,7 @@ class SegmentationService extends PubSubService {
|
||||
id: segmentationId,
|
||||
displaySetInstanceUID: rtDisplaySetUID,
|
||||
type: representationType,
|
||||
label: rtDisplaySet.SeriesDescription,
|
||||
representationData: {
|
||||
[CONTOUR]: {
|
||||
geometryIds,
|
||||
@@ -816,45 +818,54 @@ class SegmentationService extends PubSubService {
|
||||
const segmentsCachedStats = {};
|
||||
const initializeContour = async rtStructData => {
|
||||
const { data, id, color, segmentIndex, geometryId } = rtStructData;
|
||||
const geometry = await geometryLoader.createAndCacheGeometry(geometryId, {
|
||||
geometryData: {
|
||||
data,
|
||||
id,
|
||||
color,
|
||||
frameOfReferenceUID: structureSet.frameOfReferenceUID,
|
||||
|
||||
// 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,
|
||||
},
|
||||
type: csEnums.GeometryType.CONTOUR,
|
||||
});
|
||||
color,
|
||||
...SEGMENT_CONSTANT,
|
||||
};
|
||||
|
||||
const contourSet = geometry.data;
|
||||
const centroid = contourSet.getCentroid();
|
||||
const numInitialized = Object.keys(segmentsCachedStats).length;
|
||||
|
||||
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
|
||||
};
|
||||
// Calculate percentage completed
|
||||
const percentComplete = Math.round(
|
||||
(numInitialized / allRTStructData.length) * 100
|
||||
);
|
||||
|
||||
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,
|
||||
});
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
const promiseArray = [];
|
||||
|
||||
@@ -15,7 +15,7 @@ const EVENTS = {
|
||||
* sync group declared.
|
||||
*/
|
||||
export type SyncCreator = (
|
||||
type: string,
|
||||
id: 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 setSynchronizer(type: string, creator: SyncCreator): void {
|
||||
public addSynchronizerType(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) {
|
||||
if (viewport instanceof VolumeViewport || viewport instanceof VolumeViewport3D) {
|
||||
this._setVolumeViewport(viewport, viewportData, viewportInfo).then(() => {
|
||||
if (keepCamera) {
|
||||
viewport.setCamera(viewportCamera);
|
||||
|
||||
@@ -198,7 +198,9 @@ class ViewportInfo {
|
||||
// via cornerstoneViewportService
|
||||
let viewportData = this.getViewportData();
|
||||
|
||||
if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC) {
|
||||
if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC ||
|
||||
viewportData.viewportType === Enums.ViewportType.VOLUME_3D
|
||||
) {
|
||||
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 } from '@ohif/ui';
|
||||
import { Input, Dialog, ButtonEnums } from '@ohif/ui';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -60,8 +60,8 @@ function callInputDialog(
|
||||
noCloseButton: true,
|
||||
onClose: () => uiDialogService.dismiss({ id: dialogId }),
|
||||
actions: [
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
],
|
||||
onSubmit: onSubmitHandler,
|
||||
body: ({ value, setValue }) => {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import SUPPORTED_TOOLS from './constants/supportedTools';
|
||||
import getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';
|
||||
import getModalityUnit from './utils/getModalityUnit';
|
||||
import { utils } from '@ohif/core';
|
||||
|
||||
const CircleROI = {
|
||||
@@ -112,8 +111,7 @@ function getMappedAnnotations(annotation, DisplaySetService) {
|
||||
);
|
||||
|
||||
const { SeriesNumber } = displaySet;
|
||||
const { mean, stdDev, max, area, Modality } = targetStats;
|
||||
const unit = getModalityUnit(Modality);
|
||||
const { mean, stdDev, max, area, Modality, modalityUnit } = targetStats;
|
||||
|
||||
annotations.push({
|
||||
SeriesInstanceUID,
|
||||
@@ -121,7 +119,7 @@ function getMappedAnnotations(annotation, DisplaySetService) {
|
||||
SeriesNumber,
|
||||
frameNumber,
|
||||
Modality,
|
||||
unit,
|
||||
unit: modalityUnit,
|
||||
mean,
|
||||
stdDev,
|
||||
max,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import SUPPORTED_TOOLS from './constants/supportedTools';
|
||||
import getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';
|
||||
import getModalityUnit from './utils/getModalityUnit';
|
||||
import { utils } from '@ohif/core';
|
||||
|
||||
const EllipticalROI = {
|
||||
@@ -112,8 +111,7 @@ function getMappedAnnotations(annotation, displaySetService) {
|
||||
);
|
||||
|
||||
const { SeriesNumber } = displaySet;
|
||||
const { mean, stdDev, max, area, Modality } = targetStats;
|
||||
const unit = getModalityUnit(Modality);
|
||||
const { mean, stdDev, max, area, Modality, modalityUnit } = targetStats;
|
||||
|
||||
annotations.push({
|
||||
SeriesInstanceUID,
|
||||
@@ -121,7 +119,7 @@ function getMappedAnnotations(annotation, displaySetService) {
|
||||
SeriesNumber,
|
||||
frameNumber,
|
||||
Modality,
|
||||
unit,
|
||||
unit: modalityUnit,
|
||||
mean,
|
||||
stdDev,
|
||||
max,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import SUPPORTED_TOOLS from './constants/supportedTools';
|
||||
import getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';
|
||||
import getModalityUnit from './utils/getModalityUnit';
|
||||
import { utils } from '@ohif/core';
|
||||
|
||||
const RectangleROI = {
|
||||
@@ -106,8 +105,7 @@ function getMappedAnnotations(annotation, DisplaySetService) {
|
||||
);
|
||||
|
||||
const { SeriesNumber } = displaySet;
|
||||
const { mean, stdDev, max, area, Modality } = targetStats;
|
||||
const unit = getModalityUnit(Modality);
|
||||
const { mean, stdDev, max, area, Modality, modalityUnit } = targetStats;
|
||||
|
||||
annotations.push({
|
||||
SeriesInstanceUID,
|
||||
@@ -115,7 +113,7 @@ function getMappedAnnotations(annotation, DisplaySetService) {
|
||||
SeriesNumber,
|
||||
frameNumber,
|
||||
Modality,
|
||||
unit,
|
||||
unit: modalityUnit,
|
||||
mean,
|
||||
stdDev,
|
||||
max,
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
function getModalityUnit(modality) {
|
||||
if (modality === 'CT') {
|
||||
return 'HU';
|
||||
} else if (modality === 'PT') {
|
||||
return 'SUV';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export default getModalityUnit;
|
||||
@@ -4,11 +4,9 @@ import {
|
||||
setAnnotationSelected,
|
||||
getFirstAnnotationSelected,
|
||||
} from './selection';
|
||||
import getModalityUnit from './getModalityUnit';
|
||||
import getSOPInstanceAttributes from './getSOPInstanceAttributes';
|
||||
|
||||
export {
|
||||
getModalityUnit,
|
||||
getHandlesFromPoints,
|
||||
getSOPInstanceAttributes,
|
||||
isAnnotationSelected,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-default",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/i18n": "3.7.0-beta.2",
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/i18n": "3.7.0-beta.39",
|
||||
"dcmjs": "^0.29.5",
|
||||
"dicomweb-client": "^0.10.2",
|
||||
"prop-types": "^15.6.2",
|
||||
|
||||
@@ -13,6 +13,7 @@ const mappings = {
|
||||
|
||||
let _store = {
|
||||
urls: [],
|
||||
studyInstanceUIDMap: new Map(), // map of urls to array of study instance UIDs
|
||||
// {
|
||||
// url: url1
|
||||
// studies: [Study1, Study2], // if multiple studies
|
||||
@@ -41,10 +42,10 @@ const findStudies = (key, value) => {
|
||||
};
|
||||
|
||||
function createDicomJSONApi(dicomJsonConfig) {
|
||||
const { name, wadoRoot } = dicomJsonConfig;
|
||||
const { wadoRoot } = dicomJsonConfig;
|
||||
|
||||
const implementation = {
|
||||
initialize: async ({ params, query, url }) => {
|
||||
initialize: async ({ query, url }) => {
|
||||
if (!url) url = query.get('url');
|
||||
let metaData = getMetaDataByURL(url);
|
||||
|
||||
@@ -58,11 +59,7 @@ function createDicomJSONApi(dicomJsonConfig) {
|
||||
}
|
||||
|
||||
const response = await fetch(url);
|
||||
let data = await response.json();
|
||||
|
||||
const studyInstanceUIDs = data.studies.map(
|
||||
study => study.StudyInstanceUID
|
||||
);
|
||||
const data = await response.json();
|
||||
|
||||
let StudyInstanceUID;
|
||||
let SeriesInstanceUID;
|
||||
@@ -89,12 +86,14 @@ function createDicomJSONApi(dicomJsonConfig) {
|
||||
url,
|
||||
studies: [...data.studies],
|
||||
});
|
||||
|
||||
return studyInstanceUIDs;
|
||||
_store.studyInstanceUIDMap.set(
|
||||
url,
|
||||
data.studies.map(study => study.StudyInstanceUID)
|
||||
);
|
||||
},
|
||||
query: {
|
||||
studies: {
|
||||
mapParams: () => { },
|
||||
mapParams: () => {},
|
||||
search: async param => {
|
||||
const [key, value] = Object.entries(param)[0];
|
||||
const mappedParam = mappings[key];
|
||||
@@ -252,12 +251,13 @@ function createDicomJSONApi(dicomJsonConfig) {
|
||||
return imageIds;
|
||||
},
|
||||
getImageIdsForInstance({ instance, frame }) {
|
||||
const imageIds = getImageId({
|
||||
instance,
|
||||
frame,
|
||||
});
|
||||
const imageIds = getImageId({ instance, frame });
|
||||
return imageIds;
|
||||
},
|
||||
getStudyInstanceUIDs: ({ params, query }) => {
|
||||
const url = query.get('url');
|
||||
return _store.studyInstanceUIDMap.get(url);
|
||||
},
|
||||
};
|
||||
return IWebApiDataSource.create(implementation);
|
||||
}
|
||||
|
||||
@@ -41,25 +41,7 @@ function createDicomLocalApi(dicomLocalConfig) {
|
||||
const { name } = dicomLocalConfig;
|
||||
|
||||
const implementation = {
|
||||
initialize: ({ params, query }) => {
|
||||
const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;
|
||||
const queryStudyInstanceUIDs = query.getAll('StudyInstanceUIDs');
|
||||
|
||||
const StudyInstanceUIDs =
|
||||
queryStudyInstanceUIDs || paramsStudyInstanceUIDs;
|
||||
const StudyInstanceUIDsAsArray =
|
||||
StudyInstanceUIDs && Array.isArray(StudyInstanceUIDs)
|
||||
? StudyInstanceUIDs
|
||||
: [StudyInstanceUIDs];
|
||||
|
||||
// Put SRs at the end of series list to make sure images are loaded first
|
||||
StudyInstanceUIDsAsArray.forEach(StudyInstanceUID => {
|
||||
const study = DicomMetadataStore.getStudy(StudyInstanceUID);
|
||||
study.series = study.series.sort(customSort);
|
||||
});
|
||||
|
||||
return StudyInstanceUIDsAsArray;
|
||||
},
|
||||
initialize: ({ params, query }) => {},
|
||||
query: {
|
||||
studies: {
|
||||
mapParams: () => {},
|
||||
@@ -246,6 +228,29 @@ function createDicomLocalApi(dicomLocalConfig) {
|
||||
deleteStudyMetadataPromise() {
|
||||
console.log('deleteStudyMetadataPromise not implemented');
|
||||
},
|
||||
getStudyInstanceUIDs: ({ params, query }) => {
|
||||
const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;
|
||||
const queryStudyInstanceUIDs = query.getAll('StudyInstanceUIDs');
|
||||
|
||||
const StudyInstanceUIDs =
|
||||
queryStudyInstanceUIDs || paramsStudyInstanceUIDs;
|
||||
const StudyInstanceUIDsAsArray =
|
||||
StudyInstanceUIDs && Array.isArray(StudyInstanceUIDs)
|
||||
? StudyInstanceUIDs
|
||||
: [StudyInstanceUIDs];
|
||||
|
||||
// Put SRs at the end of series list to make sure images are loaded first
|
||||
let isStudyInCache = false;
|
||||
StudyInstanceUIDsAsArray.forEach(StudyInstanceUID => {
|
||||
const study = DicomMetadataStore.getStudy(StudyInstanceUID);
|
||||
if (study) {
|
||||
study.series = study.series.sort(customSort);
|
||||
isStudyInCache = true;
|
||||
}
|
||||
});
|
||||
|
||||
return isStudyInCache ? StudyInstanceUIDsAsArray : [];
|
||||
},
|
||||
};
|
||||
return IWebApiDataSource.create(implementation);
|
||||
}
|
||||
|
||||
@@ -51,74 +51,87 @@ const metadataProvider = classes.MetadataProvider;
|
||||
* @param {string|bool} singlepart - indicates of the retrieves can fetch singlepart. Options are bulkdata, video, image or boolean true
|
||||
*/
|
||||
function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
const {
|
||||
qidoRoot,
|
||||
wadoRoot,
|
||||
enableStudyLazyLoad,
|
||||
supportsFuzzyMatching,
|
||||
supportsWildcard,
|
||||
supportsReject,
|
||||
staticWado,
|
||||
singlepart,
|
||||
} = dicomWebConfig;
|
||||
|
||||
const dicomWebConfigCopy = JSON.parse(JSON.stringify(dicomWebConfig));
|
||||
|
||||
const qidoConfig = {
|
||||
url: qidoRoot,
|
||||
staticWado,
|
||||
singlepart,
|
||||
headers: userAuthenticationService.getAuthorizationHeader(),
|
||||
errorInterceptor: errorHandler.getHTTPErrorHandler(),
|
||||
};
|
||||
|
||||
const wadoConfig = {
|
||||
url: wadoRoot,
|
||||
staticWado,
|
||||
singlepart,
|
||||
headers: userAuthenticationService.getAuthorizationHeader(),
|
||||
errorInterceptor: errorHandler.getHTTPErrorHandler(),
|
||||
};
|
||||
|
||||
// TODO -> Two clients sucks, but its better than 1000.
|
||||
// TODO -> We'll need to merge auth later.
|
||||
const qidoDicomWebClient = staticWado
|
||||
? new StaticWadoClient(qidoConfig)
|
||||
: new api.DICOMwebClient(qidoConfig);
|
||||
|
||||
const wadoDicomWebClient = staticWado
|
||||
? new StaticWadoClient(wadoConfig)
|
||||
: new api.DICOMwebClient(wadoConfig);
|
||||
let dicomWebConfigCopy,
|
||||
qidoConfig,
|
||||
wadoConfig,
|
||||
qidoDicomWebClient,
|
||||
wadoDicomWebClient,
|
||||
getAuthrorizationHeader,
|
||||
generateWadoHeader;
|
||||
|
||||
const implementation = {
|
||||
initialize: ({ params, query }) => {
|
||||
const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;
|
||||
const queryStudyInstanceUIDs = utils.splitComma(
|
||||
query.getAll('StudyInstanceUIDs')
|
||||
);
|
||||
if (
|
||||
dicomWebConfig.onConfiguration &&
|
||||
typeof dicomWebConfig.onConfiguration === 'function'
|
||||
) {
|
||||
dicomWebConfig = dicomWebConfig.onConfiguration(dicomWebConfig, {
|
||||
params,
|
||||
query,
|
||||
});
|
||||
}
|
||||
|
||||
const StudyInstanceUIDs =
|
||||
(queryStudyInstanceUIDs.length && queryStudyInstanceUIDs) ||
|
||||
paramsStudyInstanceUIDs;
|
||||
const StudyInstanceUIDsAsArray =
|
||||
StudyInstanceUIDs && Array.isArray(StudyInstanceUIDs)
|
||||
? StudyInstanceUIDs
|
||||
: [StudyInstanceUIDs];
|
||||
return StudyInstanceUIDsAsArray;
|
||||
dicomWebConfigCopy = JSON.parse(JSON.stringify(dicomWebConfig));
|
||||
|
||||
getAuthrorizationHeader = () => {
|
||||
const xhrRequestHeaders = {};
|
||||
const authHeaders = userAuthenticationService.getAuthorizationHeader();
|
||||
if (authHeaders && authHeaders.Authorization) {
|
||||
xhrRequestHeaders.Authorization = authHeaders.Authorization;
|
||||
}
|
||||
return xhrRequestHeaders;
|
||||
};
|
||||
|
||||
generateWadoHeader = () => {
|
||||
let authorizationHeader = getAuthrorizationHeader();
|
||||
//Generate accept header depending on config params
|
||||
let formattedAcceptHeader = utils.generateAcceptHeader(
|
||||
dicomWebConfig.acceptHeader,
|
||||
dicomWebConfig.requestTransferSyntaxUID,
|
||||
dicomWebConfig.omitQuotationForMultipartRequest
|
||||
);
|
||||
|
||||
return {
|
||||
...authorizationHeader,
|
||||
Accept: formattedAcceptHeader,
|
||||
};
|
||||
};
|
||||
|
||||
qidoConfig = {
|
||||
url: dicomWebConfig.qidoRoot,
|
||||
staticWado: dicomWebConfig.staticWado,
|
||||
singlepart: dicomWebConfig.singlepart,
|
||||
headers: userAuthenticationService.getAuthorizationHeader(),
|
||||
errorInterceptor: errorHandler.getHTTPErrorHandler(),
|
||||
};
|
||||
|
||||
wadoConfig = {
|
||||
url: dicomWebConfig.wadoRoot,
|
||||
staticWado: dicomWebConfig.staticWado,
|
||||
singlepart: dicomWebConfig.singlepart,
|
||||
headers: userAuthenticationService.getAuthorizationHeader(),
|
||||
errorInterceptor: errorHandler.getHTTPErrorHandler(),
|
||||
};
|
||||
|
||||
// TODO -> Two clients sucks, but its better than 1000.
|
||||
// TODO -> We'll need to merge auth later.
|
||||
qidoDicomWebClient = dicomWebConfig.staticWado
|
||||
? new StaticWadoClient(qidoConfig)
|
||||
: new api.DICOMwebClient(qidoConfig);
|
||||
|
||||
wadoDicomWebClient = dicomWebConfig.staticWado
|
||||
? new StaticWadoClient(wadoConfig)
|
||||
: new api.DICOMwebClient(wadoConfig);
|
||||
},
|
||||
query: {
|
||||
studies: {
|
||||
mapParams: mapParams.bind(),
|
||||
search: async function(origParams) {
|
||||
const headers = userAuthenticationService.getAuthorizationHeader();
|
||||
if (headers) {
|
||||
qidoDicomWebClient.headers = headers;
|
||||
}
|
||||
|
||||
qidoDicomWebClient.headers = getAuthrorizationHeader();
|
||||
const { studyInstanceUid, seriesInstanceUid, ...mappedParams } =
|
||||
mapParams(origParams, {
|
||||
supportsFuzzyMatching,
|
||||
supportsWildcard,
|
||||
supportsFuzzyMatching: dicomWebConfig.supportsFuzzyMatching,
|
||||
supportsWildcard: dicomWebConfig.supportsWildcard,
|
||||
}) || {};
|
||||
|
||||
const results = await qidoSearch(
|
||||
@@ -135,11 +148,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
series: {
|
||||
// mapParams: mapParams.bind(),
|
||||
search: async function(studyInstanceUid) {
|
||||
const headers = userAuthenticationService.getAuthorizationHeader();
|
||||
if (headers) {
|
||||
qidoDicomWebClient.headers = headers;
|
||||
}
|
||||
|
||||
qidoDicomWebClient.headers = getAuthrorizationHeader();
|
||||
const results = await seriesInStudy(
|
||||
qidoDicomWebClient,
|
||||
studyInstanceUid
|
||||
@@ -151,11 +160,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
},
|
||||
instances: {
|
||||
search: (studyInstanceUid, queryParameters) => {
|
||||
const headers = userAuthenticationService.getAuthorizationHeader();
|
||||
if (headers) {
|
||||
qidoDicomWebClient.headers = headers;
|
||||
}
|
||||
|
||||
qidoDicomWebClient.headers = getAuthrorizationHeader();
|
||||
qidoSearch.call(
|
||||
undefined,
|
||||
qidoDicomWebClient,
|
||||
@@ -179,9 +184,16 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
* or is already retrieved, or a promise to a URL for such use if a BulkDataURI
|
||||
*/
|
||||
directURL: params => {
|
||||
return getDirectURL({ wadoRoot, singlepart }, params);
|
||||
return getDirectURL(
|
||||
{
|
||||
wadoRoot: dicomWebConfig.wadoRoot,
|
||||
singlepart: dicomWebConfig.singlepart,
|
||||
},
|
||||
params
|
||||
);
|
||||
},
|
||||
bulkDataURI: async ({ StudyInstanceUID, BulkDataURI }) => {
|
||||
qidoDicomWebClient.headers = getAuthrorizationHeader();
|
||||
const options = {
|
||||
multipart: false,
|
||||
BulkDataURI,
|
||||
@@ -200,18 +212,13 @@ 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'
|
||||
);
|
||||
}
|
||||
|
||||
if (enableStudyLazyLoad) {
|
||||
if (dicomWebConfig.enableStudyLazyLoad) {
|
||||
return implementation._retrieveSeriesMetadataAsync(
|
||||
StudyInstanceUID,
|
||||
filters,
|
||||
@@ -234,17 +241,12 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
|
||||
store: {
|
||||
dicom: async (dataset, request) => {
|
||||
const headers = userAuthenticationService.getAuthorizationHeader();
|
||||
if (headers) {
|
||||
wadoDicomWebClient.headers = headers;
|
||||
}
|
||||
|
||||
wadoDicomWebClient.headers = getAuthrorizationHeader();
|
||||
if (dataset instanceof ArrayBuffer) {
|
||||
const options = {
|
||||
datasets: [dataset],
|
||||
request,
|
||||
};
|
||||
|
||||
await wadoDicomWebClient.storeInstances(options);
|
||||
} else {
|
||||
const meta = {
|
||||
@@ -282,7 +284,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
madeInClient
|
||||
) => {
|
||||
const enableStudyLazyLoad = false;
|
||||
|
||||
wadoDicomWebClient.headers = generateWadoHeader();
|
||||
// data is all SOPInstanceUIDs
|
||||
const data = await retrieveStudyMetadata(
|
||||
wadoDicomWebClient,
|
||||
@@ -353,6 +355,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
madeInClient = false
|
||||
) => {
|
||||
const enableStudyLazyLoad = true;
|
||||
wadoDicomWebClient.headers = generateWadoHeader();
|
||||
// Get Series
|
||||
const {
|
||||
preLoadData: seriesSummaryMetadata,
|
||||
@@ -515,10 +518,26 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
getConfig() {
|
||||
return dicomWebConfigCopy;
|
||||
},
|
||||
getStudyInstanceUIDs({ params, query }) {
|
||||
const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;
|
||||
const queryStudyInstanceUIDs = utils.splitComma(
|
||||
query.getAll('StudyInstanceUIDs')
|
||||
);
|
||||
|
||||
const StudyInstanceUIDs =
|
||||
(queryStudyInstanceUIDs.length && queryStudyInstanceUIDs) ||
|
||||
paramsStudyInstanceUIDs;
|
||||
const StudyInstanceUIDsAsArray =
|
||||
StudyInstanceUIDs && Array.isArray(StudyInstanceUIDs)
|
||||
? StudyInstanceUIDs
|
||||
: [StudyInstanceUIDs];
|
||||
|
||||
return StudyInstanceUIDsAsArray;
|
||||
},
|
||||
};
|
||||
|
||||
if (supportsReject) {
|
||||
implementation.reject = dcm4cheeReject(wadoRoot);
|
||||
if (dicomWebConfig.supportsReject) {
|
||||
implementation.reject = dcm4cheeReject(dicomWebConfig.wadoRoot);
|
||||
}
|
||||
|
||||
return IWebApiDataSource.create(implementation);
|
||||
|
||||
@@ -18,15 +18,6 @@ function createDicomWebProxyApi(
|
||||
|
||||
const implementation = {
|
||||
initialize: async ({ params, query }) => {
|
||||
let studyInstanceUIDs = [];
|
||||
|
||||
// there seem to be a couple of variations of the case for this parameter
|
||||
const queryStudyInstanceUIDs =
|
||||
query.get('studyInstanceUIDs') || query.get('studyInstanceUids');
|
||||
if (!queryStudyInstanceUIDs) {
|
||||
throw new Error(`No studyInstanceUids in request for '${name}'`);
|
||||
}
|
||||
|
||||
const url = query.get('url');
|
||||
|
||||
if (!url) {
|
||||
@@ -39,12 +30,11 @@ function createDicomWebProxyApi(
|
||||
}
|
||||
|
||||
dicomWebDelegate = createDicomWebApi(
|
||||
data.servers.dicomWeb[0],
|
||||
data.servers.dicomWeb[0].configuration,
|
||||
UserAuthenticationService
|
||||
);
|
||||
studyInstanceUIDs = queryStudyInstanceUIDs.split(';');
|
||||
dicomWebDelegate.initialize({ params, query });
|
||||
}
|
||||
return studyInstanceUIDs;
|
||||
},
|
||||
query: {
|
||||
studies: {
|
||||
@@ -77,6 +67,18 @@ function createDicomWebProxyApi(
|
||||
dicomWebDelegate.getImageIdsForDisplaySet(...args),
|
||||
getImageIdsForInstance: (...args) =>
|
||||
dicomWebDelegate.getImageIdsForInstance(...args),
|
||||
getStudyInstanceUIDs({ params, query }) {
|
||||
let studyInstanceUIDs = [];
|
||||
|
||||
// there seem to be a couple of variations of the case for this parameter
|
||||
const queryStudyInstanceUIDs =
|
||||
query.get('studyInstanceUIDs') || query.get('studyInstanceUids');
|
||||
if (!queryStudyInstanceUIDs) {
|
||||
throw new Error(`No studyInstanceUids in request for '${name}'`);
|
||||
}
|
||||
studyInstanceUIDs = queryStudyInstanceUIDs.split(';');
|
||||
return studyInstanceUIDs;
|
||||
},
|
||||
};
|
||||
return IWebApiDataSource.create(implementation);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Button, ButtonGroup } from '@ohif/ui';
|
||||
import { LegacyButton, ButtonGroup } from '@ohif/ui';
|
||||
|
||||
function ActionButtons({ onExportClick, onCreateReportClick }) {
|
||||
const { t } = useTranslation('MeasurementTable');
|
||||
@@ -10,12 +10,16 @@ function ActionButtons({ onExportClick, onCreateReportClick }) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ButtonGroup color="black" size="inherit">
|
||||
<Button className="px-2 py-2 text-base" onClick={onExportClick}>
|
||||
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
|
||||
<LegacyButton className="px-2 py-2 text-base" onClick={onExportClick}>
|
||||
{t('Export CSV')}
|
||||
</Button>
|
||||
<Button className="px-2 py-2 text-base" onClick={onCreateReportClick}>
|
||||
</LegacyButton>
|
||||
<LegacyButton
|
||||
className="px-2 py-2 text-base"
|
||||
onClick={onCreateReportClick}
|
||||
>
|
||||
{t('Create Report')}
|
||||
</Button>
|
||||
</LegacyButton>
|
||||
</ButtonGroup>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,7 @@ import classnames from 'classnames';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useAppConfig } from '@state';
|
||||
|
||||
import { Button } from '@ohif/ui';
|
||||
import { Button, ButtonEnums } from '@ohif/ui';
|
||||
|
||||
function DataSourceSelector() {
|
||||
const [appConfig] = useAppConfig();
|
||||
@@ -31,9 +31,12 @@ function DataSourceSelector() {
|
||||
)
|
||||
.map(ds => (
|
||||
<div key={ds.sourceName}>
|
||||
<h1 className="text-white">{ds.friendlyName}</h1>
|
||||
<h1 className="text-white">
|
||||
{ds.configuration?.friendlyName || ds.friendlyName}
|
||||
</h1>
|
||||
<Button
|
||||
className={classnames('font-bold', 'ml-2')}
|
||||
type={ButtonEnums.type.primary}
|
||||
className={classnames('ml-2')}
|
||||
onClick={() => {
|
||||
navigate({
|
||||
pathname: '/',
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { utils, ServicesManager } from '@ohif/core';
|
||||
import { MeasurementTable, Dialog, Input, useViewportGrid } from '@ohif/ui';
|
||||
import {
|
||||
MeasurementTable,
|
||||
Dialog,
|
||||
Input,
|
||||
useViewportGrid,
|
||||
ButtonEnums,
|
||||
} from '@ohif/ui';
|
||||
import ActionButtons from './ActionButtons';
|
||||
import debounce from 'lodash.debounce';
|
||||
|
||||
@@ -189,9 +195,8 @@ export default function PanelMeasurementTable({
|
||||
);
|
||||
},
|
||||
actions: [
|
||||
// temp: swap button types until colors are updated
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
],
|
||||
onSubmit: onSubmitHandler,
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable react/display-name */
|
||||
import React from 'react';
|
||||
import { Dialog, Input, Select } from '@ohif/ui';
|
||||
import { ButtonEnums, 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: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
],
|
||||
// TODO: Should be on button press...
|
||||
onSubmit: _handleFormSubmit,
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function Toolbar({ servicesManager }) {
|
||||
|
||||
return (
|
||||
<>
|
||||
{toolbarButtons.map((toolDef, index) => {
|
||||
{toolbarButtons.map(toolDef => {
|
||||
const { id, Component, componentProps } = toolDef;
|
||||
// TODO: ...
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-microscopy",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/extension-default": "3.7.0-beta.2",
|
||||
"@ohif/i18n": "3.7.0-beta.2",
|
||||
"@ohif/ui": "3.7.0-beta.2",
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/extension-default": "3.7.0-beta.39",
|
||||
"@ohif/i18n": "3.7.0-beta.39",
|
||||
"@ohif/ui": "3.7.0-beta.39",
|
||||
"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 } from '@ohif/ui';
|
||||
import { Input, Dialog, ButtonEnums } 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: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
],
|
||||
onSubmit: onSubmitHandler,
|
||||
body: ({ value, setValue }) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-pdf",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/ui": "3.7.0-beta.2",
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/ui": "3.7.0-beta.39",
|
||||
"dcmjs": "^0.29.5",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-video",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/ui": "3.7.0-beta.2",
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/ui": "3.7.0-beta.39",
|
||||
"dcmjs": "^0.29.5",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-measurement-tracking",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.1.8",
|
||||
"@cornerstonejs/tools": "^1.1.8",
|
||||
"@ohif/core": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.2",
|
||||
"@ohif/ui": "3.7.0-beta.2",
|
||||
"@cornerstonejs/core": "^1.5.0",
|
||||
"@cornerstonejs/tools": "^1.5.0",
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.39",
|
||||
"@ohif/ui": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/ui": "3.7.0-beta.39",
|
||||
"@xstate/react": "^0.8.1",
|
||||
"xstate": "^4.10.0"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable react/display-name */
|
||||
import React from 'react';
|
||||
import { Dialog, Input } from '@ohif/ui';
|
||||
import { ButtonEnums, Dialog, Input } from '@ohif/ui';
|
||||
import RESPONSE from './PROMPT_RESPONSES';
|
||||
|
||||
export default function createReportDialogPrompt(uiDialogService) {
|
||||
@@ -20,12 +20,19 @@ 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':
|
||||
resolve({ action: RESPONSE.CREATE_REPORT, value: value.label });
|
||||
// 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 });
|
||||
}
|
||||
break;
|
||||
case 'cancel':
|
||||
uiDialogService.dismiss({ id: dialogId });
|
||||
resolve({ action: RESPONSE.CANCEL, value: undefined });
|
||||
break;
|
||||
}
|
||||
@@ -43,8 +50,8 @@ export default function createReportDialogPrompt(uiDialogService) {
|
||||
noCloseButton: true,
|
||||
onClose: _handleClose,
|
||||
actions: [
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
],
|
||||
// TODO: Should be on button press...
|
||||
onSubmit: _handleFormSubmit,
|
||||
@@ -55,8 +62,8 @@ export default function createReportDialogPrompt(uiDialogService) {
|
||||
};
|
||||
const onKeyPressHandler = event => {
|
||||
if (event.key === 'Enter') {
|
||||
uiDialogService.dismiss({ id: dialogId });
|
||||
resolve({ action: RESPONSE.CREATE_REPORT, value: value.label });
|
||||
// Trigger form submit
|
||||
_handleFormSubmit({ action: { id: 'save' }, value });
|
||||
}
|
||||
};
|
||||
return (
|
||||
|
||||
+5
-3
@@ -1,3 +1,5 @@
|
||||
import { ButtonEnums } from '@ohif/ui';
|
||||
|
||||
const RESPONSE = {
|
||||
NO_NEVER: -1,
|
||||
CANCEL: 0,
|
||||
@@ -31,19 +33,19 @@ function _askTrackMeasurements(uiViewportDialogService, viewportIndex) {
|
||||
const actions = [
|
||||
{
|
||||
id: 'prompt-begin-tracking-cancel',
|
||||
type: 'cancel',
|
||||
type: ButtonEnums.type.secondary,
|
||||
text: 'No',
|
||||
value: RESPONSE.CANCEL,
|
||||
},
|
||||
{
|
||||
id: 'prompt-begin-tracking-no-do-not-ask-again',
|
||||
type: 'secondary',
|
||||
type: ButtonEnums.type.secondary,
|
||||
text: 'No, do not ask again',
|
||||
value: RESPONSE.NO_NEVER,
|
||||
},
|
||||
{
|
||||
id: 'prompt-begin-tracking-yes',
|
||||
type: 'primary',
|
||||
type: ButtonEnums.type.primary,
|
||||
text: 'Yes',
|
||||
value: RESPONSE.SET_STUDY_AND_SERIES,
|
||||
},
|
||||
|
||||
+3
-2
@@ -1,4 +1,5 @@
|
||||
import { hydrateStructuredReport } from '@ohif/extension-cornerstone-dicom-sr';
|
||||
import { ButtonEnums } from '@ohif/ui';
|
||||
|
||||
const RESPONSE = {
|
||||
NO_NEVER: -1,
|
||||
@@ -61,12 +62,12 @@ function _askTrackMeasurements(uiViewportDialogService, viewportIndex) {
|
||||
'Do you want to continue tracking measurements for this study?';
|
||||
const actions = [
|
||||
{
|
||||
type: 'secondary',
|
||||
type: ButtonEnums.type.secondary,
|
||||
text: 'No',
|
||||
value: RESPONSE.CANCEL,
|
||||
},
|
||||
{
|
||||
type: 'primary',
|
||||
type: ButtonEnums.type.primary,
|
||||
text: 'Yes',
|
||||
value: RESPONSE.HYDRATE_REPORT,
|
||||
},
|
||||
|
||||
+9
-3
@@ -1,3 +1,5 @@
|
||||
import { ButtonEnums } from '@ohif/ui';
|
||||
|
||||
const RESPONSE = {
|
||||
NO_NEVER: -1,
|
||||
CANCEL: 0,
|
||||
@@ -38,14 +40,18 @@ 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: 'secondary',
|
||||
type: ButtonEnums.type.secondary,
|
||||
text: 'Cancel',
|
||||
value: RESPONSE.CANCEL,
|
||||
},
|
||||
{
|
||||
type: ButtonEnums.type.primary,
|
||||
text: 'Create new report',
|
||||
value: RESPONSE.CREATE_REPORT,
|
||||
},
|
||||
{
|
||||
type: 'primary',
|
||||
type: ButtonEnums.type.primary,
|
||||
text: 'Add to existing report',
|
||||
value: RESPONSE.ADD_SERIES,
|
||||
},
|
||||
|
||||
+6
-11
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Button, ButtonGroup } from '@ohif/ui';
|
||||
import { Button, ButtonEnums } from '@ohif/ui';
|
||||
|
||||
function ActionButtons({ onExportClick, onCreateReportClick, disabled }) {
|
||||
const { t } = useTranslation('MeasurementTable');
|
||||
@@ -10,23 +10,18 @@ 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 px-2 text-base"
|
||||
variant={disabled ? 'disabled' : 'outlined'}
|
||||
size="initial"
|
||||
color="black"
|
||||
border="primaryActive"
|
||||
className="ml-2"
|
||||
onClick={onCreateReportClick}
|
||||
type={ButtonEnums.type.secondary}
|
||||
size={ButtonEnums.size.small}
|
||||
disabled={disabled}
|
||||
>
|
||||
{t('Create Report')}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Dialog,
|
||||
Input,
|
||||
useViewportGrid,
|
||||
ButtonEnums,
|
||||
} from '@ohif/ui';
|
||||
import { DicomMetadataStore, utils } from '@ohif/core';
|
||||
import { useDebounce } from '@hooks';
|
||||
@@ -217,9 +218,8 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) {
|
||||
);
|
||||
},
|
||||
actions: [
|
||||
// temp: swap button types until colors are updated
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
],
|
||||
onSubmit: onSubmitHandler,
|
||||
},
|
||||
|
||||
+12
-35
@@ -1,4 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import PropTypes from 'prop-types';
|
||||
import { utils } from '@ohif/core';
|
||||
import {
|
||||
@@ -6,6 +7,7 @@ import {
|
||||
useImageViewer,
|
||||
useViewportGrid,
|
||||
Dialog,
|
||||
ButtonEnums,
|
||||
} from '@ohif/ui';
|
||||
import { useTrackedMeasurements } from '../../getContextModule';
|
||||
|
||||
@@ -23,19 +25,20 @@ 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, numCols, numRows },
|
||||
{ activeViewportIndex, viewports },
|
||||
viewportGridService,
|
||||
] = useViewportGrid();
|
||||
const [
|
||||
@@ -76,36 +79,6 @@ 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
|
||||
@@ -133,7 +106,7 @@ function PanelStudyBrowserTracking({
|
||||
const actuallyMappedStudies = mappedStudies.map(qidoStudy => {
|
||||
return {
|
||||
studyInstanceUid: qidoStudy.StudyInstanceUID,
|
||||
date: formatDate(qidoStudy.StudyDate),
|
||||
date: formatDate(qidoStudy.StudyDate) || t('NoStudyDate'),
|
||||
description: qidoStudy.StudyDescription,
|
||||
modalities: qidoStudy.ModalitiesInStudy,
|
||||
numInstances: qidoStudy.NumInstances,
|
||||
@@ -507,11 +480,15 @@ function _mapDisplaySets(
|
||||
</div>
|
||||
),
|
||||
actions: [
|
||||
{ id: 'cancel', text: 'Cancel', type: 'secondary' },
|
||||
{
|
||||
id: 'cancel',
|
||||
text: 'Cancel',
|
||||
type: ButtonEnums.type.secondary,
|
||||
},
|
||||
{
|
||||
id: 'yes',
|
||||
text: 'Yes',
|
||||
type: 'primary',
|
||||
type: ButtonEnums.type.primary,
|
||||
classes: ['reject-yes-button'],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -22,17 +22,22 @@ function TrackedCornerstoneViewport(props) {
|
||||
viewportOptions,
|
||||
} = props;
|
||||
|
||||
const { t } = useTranslation('TrackedViewport');
|
||||
const { t } = useTranslation('Common');
|
||||
|
||||
const {
|
||||
measurementService,
|
||||
cornerstoneViewportService,
|
||||
viewportGridService,
|
||||
} = servicesManager.services;
|
||||
|
||||
// Todo: handling more than one displaySet on the same viewport
|
||||
const displaySet = displaySets[0];
|
||||
|
||||
const [trackedMeasurements] = useTrackedMeasurements();
|
||||
const [
|
||||
trackedMeasurements,
|
||||
sendTrackedMeasurementsEvent,
|
||||
] = useTrackedMeasurements();
|
||||
|
||||
const [isTracked, setIsTracked] = useState(false);
|
||||
const [trackedMeasurementUID, setTrackedMeasurementUID] = useState(null);
|
||||
const [viewportElem, setViewportElem] = useState(null);
|
||||
@@ -54,6 +59,7 @@ function TrackedCornerstoneViewport(props) {
|
||||
PatientAge,
|
||||
SliceThickness,
|
||||
SpacingBetweenSlices,
|
||||
StudyDate,
|
||||
ManufacturerModelName,
|
||||
} = displaySet.images[0];
|
||||
|
||||
@@ -148,6 +154,55 @@ 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,
|
||||
@@ -194,7 +249,8 @@ function TrackedCornerstoneViewport(props) {
|
||||
getStatusComponent={() => _getStatusComponent(isTracked)}
|
||||
studyData={{
|
||||
label: viewportLabel,
|
||||
studyDate: formatDate(SeriesDate), // TODO: This is series date. Is that ok?
|
||||
studyDate:
|
||||
formatDate(SeriesDate) || formatDate(StudyDate) || t('NoStudyDate'),
|
||||
currentSeries: SeriesNumber, // TODO - switch entire currentSeries to be UID based or actual position based
|
||||
seriesDescription: SeriesDescription,
|
||||
patientInformation: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-test",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/ui": "3.7.0-beta.2",
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/ui": "3.7.0-beta.39",
|
||||
"dcmjs": "0.29.4",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-tmtv",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/ui": "3.7.0-beta.2",
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/ui": "3.7.0-beta.39",
|
||||
"dcmjs": "^0.29.5",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -225,9 +225,7 @@ export default function PanelPetSUV({ servicesManager, commandsManager }) {
|
||||
value={metadata.SeriesTime || ''}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<Button color="primary" onClick={updateMetadata}>
|
||||
Reload Data
|
||||
</Button>
|
||||
<Button onClick={updateMetadata}>Reload Data</Button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Button, ButtonGroup } from '@ohif/ui';
|
||||
import { LegacyButton, ButtonGroup } from '@ohif/ui';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
|
||||
@@ -9,8 +9,9 @@ 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">
|
||||
<Button
|
||||
<LegacyButton
|
||||
className="px-2 py-2 text-base"
|
||||
disabled={tmtvValue === null}
|
||||
onClick={() => {
|
||||
@@ -22,10 +23,10 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
|
||||
}}
|
||||
>
|
||||
{t('Export CSV')}
|
||||
</Button>
|
||||
</LegacyButton>
|
||||
</ButtonGroup>
|
||||
<ButtonGroup color="black" size="inherit">
|
||||
<Button
|
||||
<LegacyButton
|
||||
className="px-2 py-2 text-base"
|
||||
onClick={() => {
|
||||
commandsManager.runCommand('createTMTVRTReport');
|
||||
@@ -33,7 +34,7 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
|
||||
disabled={tmtvValue === null}
|
||||
>
|
||||
{t('Create RT Report')}
|
||||
</Button>
|
||||
</LegacyButton>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
+1
-4
@@ -181,7 +181,6 @@ 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(() => {
|
||||
@@ -194,9 +193,7 @@ export default function PanelRoiThresholdSegmentation({
|
||||
>
|
||||
{labelmapLoading ? 'loading ...' : 'New Label'}
|
||||
</Button>
|
||||
<Button color="primary" onClick={handleROIThresholding}>
|
||||
Run
|
||||
</Button>
|
||||
<Button 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"
|
||||
|
||||
+6
-5
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Input, Label, Select, Button, ButtonGroup } from '@ohif/ui';
|
||||
import { Input, Label, Select, LegacyButton, ButtonGroup } from '@ohif/ui';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const ROI_STAT = 'roi_stat';
|
||||
@@ -38,8 +38,9 @@ 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>
|
||||
<Button
|
||||
<LegacyButton
|
||||
size="initial"
|
||||
className="px-2 py-2 text-base text-white"
|
||||
color="primaryLight"
|
||||
@@ -47,8 +48,8 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
|
||||
onClick={() => runCommand('setStartSliceForROIThresholdTool')}
|
||||
>
|
||||
{t('Start')}
|
||||
</Button>
|
||||
<Button
|
||||
</LegacyButton>
|
||||
<LegacyButton
|
||||
size="initial"
|
||||
color="primaryLight"
|
||||
variant="outlined"
|
||||
@@ -56,7 +57,7 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
|
||||
onClick={() => runCommand('setEndSliceForROIThresholdTool')}
|
||||
>
|
||||
{t('End')}
|
||||
</Button>
|
||||
</LegacyButton>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+12
-15
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Input, Dialog } from '@ohif/ui';
|
||||
import { Input, Dialog, ButtonEnums } from '@ohif/ui';
|
||||
|
||||
function segmentationItemEditHandler({ id, servicesManager }) {
|
||||
const { segmentationService, uiDialogService } = servicesManager.services;
|
||||
@@ -44,23 +44,20 @@ function segmentationItemEditHandler({ id, servicesManager }) {
|
||||
}
|
||||
};
|
||||
return (
|
||||
<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>
|
||||
<Input
|
||||
autoFocus
|
||||
className="bg-black border-primary-main"
|
||||
type="text"
|
||||
containerClassName="mr-2"
|
||||
value={value.label}
|
||||
onChange={onChangeHandler}
|
||||
onKeyPress={onKeyPressHandler}
|
||||
/>
|
||||
);
|
||||
},
|
||||
actions: [
|
||||
// temp: swap button types until colors are updated
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
],
|
||||
onSubmit: onSubmitHandler,
|
||||
},
|
||||
|
||||
@@ -553,7 +553,16 @@ const commandsModule = ({
|
||||
commandsManager.runCommand('setViewportColormap', {
|
||||
viewportIndex,
|
||||
displaySetInstanceUID: ptDisplaySet.displaySetInstanceUID,
|
||||
colormap,
|
||||
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 },
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
viewports.push(
|
||||
|
||||
@@ -254,16 +254,20 @@ const fusionAXIAL = {
|
||||
id: 'ctDisplaySet',
|
||||
},
|
||||
{
|
||||
id: 'ptDisplaySet',
|
||||
options: {
|
||||
colormap: {
|
||||
name: 'hsv',
|
||||
opacityMapping: [{ value: 0.1, opacity: 0.9 }],
|
||||
opacity: [
|
||||
{ value: 0, opacity: 0 },
|
||||
{ value: 0.1, opacity: 0.9 },
|
||||
{ value: 1, opacity: 0.95 },
|
||||
],
|
||||
},
|
||||
voi: {
|
||||
custom: 'getPTVOIRange',
|
||||
},
|
||||
},
|
||||
id: 'ptDisplaySet',
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -310,16 +314,20 @@ const fusionSAGITTAL = {
|
||||
id: 'ctDisplaySet',
|
||||
},
|
||||
{
|
||||
id: 'ptDisplaySet',
|
||||
options: {
|
||||
colormap: {
|
||||
name: 'hsv',
|
||||
opacityMapping: [{ value: 0.1, opacity: 0.9 }],
|
||||
opacity: [
|
||||
{ value: 0, opacity: 0 },
|
||||
{ value: 0.1, opacity: 0.9 },
|
||||
{ value: 1, opacity: 0.95 },
|
||||
],
|
||||
},
|
||||
voi: {
|
||||
custom: 'getPTVOIRange',
|
||||
},
|
||||
},
|
||||
id: 'ptDisplaySet',
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -366,16 +374,20 @@ const fusionCORONAL = {
|
||||
id: 'ctDisplaySet',
|
||||
},
|
||||
{
|
||||
id: 'ptDisplaySet',
|
||||
options: {
|
||||
colormap: {
|
||||
name: 'hsv',
|
||||
opacityMapping: [{ value: 0.1, opacity: 0.9 }],
|
||||
opacity: [
|
||||
{ value: 0, opacity: 0 },
|
||||
{ value: 0.1, opacity: 0.9 },
|
||||
{ value: 1, opacity: 0.95 },
|
||||
],
|
||||
},
|
||||
voi: {
|
||||
custom: 'getPTVOIRange',
|
||||
},
|
||||
},
|
||||
id: 'ptDisplaySet',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"packages": ["extensions/*", "platform/*", "modes/*"],
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/mode-basic-dev-mode",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.2",
|
||||
"@ohif/extension-default": "3.7.0-beta.2",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.2",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.2"
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.39",
|
||||
"@ohif/extension-default": "3.7.0-beta.39",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.39",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.39"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/mode-test",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.2",
|
||||
"@ohif/extension-default": "3.7.0-beta.2",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.2",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.2",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.2",
|
||||
"@ohif/extension-test": "3.7.0-beta.2"
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.39",
|
||||
"@ohif/extension-default": "3.7.0-beta.39",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.39",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.39",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.39",
|
||||
"@ohif/extension-test": "3.7.0-beta.39"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/mode-longitudinal",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.2",
|
||||
"@ohif/extension-default": "3.7.0-beta.2",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.2",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.2",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.2"
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.39",
|
||||
"@ohif/extension-default": "3.7.0-beta.39",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.39",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.39",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.39"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/mode-microscopy",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/extension-dicom-microscopy": "3.7.0-beta.2"
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/extension-dicom-microscopy": "3.7.0-beta.39"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/mode-tmtv",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.2",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.2",
|
||||
"@ohif/extension-default": "3.7.0-beta.2",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.2",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.2",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.2"
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.39",
|
||||
"@ohif/extension-default": "3.7.0-beta.39",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.39",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.39",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.39"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13"
|
||||
|
||||
@@ -220,7 +220,8 @@ function modeFactory({ modeConfiguration }) {
|
||||
return {
|
||||
id: ohif.layout,
|
||||
props: {
|
||||
// leftPanels: [ohif.thumbnailList],
|
||||
leftPanels: [ohif.thumbnailList],
|
||||
leftPanelDefaultClosed: true,
|
||||
rightPanels: [tmtv.ROIThresholdPanel, tmtv.petSUV],
|
||||
viewports: [
|
||||
{
|
||||
|
||||
@@ -113,7 +113,7 @@ function _initToolGroups(toolNames, Enums, toolGroupService, commandsManager) {
|
||||
rotateIncrementDegrees: 0.1,
|
||||
},
|
||||
[toolNames.MipJumpToClick]: {
|
||||
targetViewportIds: ['ptAXIAL', 'ptCORONAL', 'ptSAGITTAL'],
|
||||
toolGroupId: toolGroupIds.PT,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -24,9 +24,8 @@ function _createButton(type, id, icon, label, commands, tooltip) {
|
||||
|
||||
function _createColormap(label, colormap) {
|
||||
return {
|
||||
id: label.toString(),
|
||||
title: label,
|
||||
subtitle: label,
|
||||
id: label,
|
||||
label,
|
||||
type: 'action',
|
||||
commands: [
|
||||
{
|
||||
@@ -36,13 +35,6 @@ function _createColormap(label, colormap) {
|
||||
colormap,
|
||||
},
|
||||
},
|
||||
{
|
||||
commandName: 'setFusionPTColormap',
|
||||
commandOptions: {
|
||||
toolGroupId: toolGroupIds.Fusion,
|
||||
colormap,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -313,7 +305,8 @@ 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',
|
||||
},
|
||||
},
|
||||
@@ -345,7 +338,6 @@ const toolbarButtons = [
|
||||
tooltip: 'PET Image Colormap',
|
||||
},
|
||||
isAction: true, // ?
|
||||
renderer: WindowLevelMenuItem,
|
||||
items: [
|
||||
_createColormap('HSV', 'hsv'),
|
||||
_createColormap('Hot Iron', 'hot_iron'),
|
||||
|
||||
@@ -149,7 +149,6 @@
|
||||
]
|
||||
},
|
||||
"resolutions": {
|
||||
"@cornerstonejs/core": "^1.1.8",
|
||||
"**/@babel/runtime": "^7.20.13",
|
||||
"commander": "8.3.0",
|
||||
"nth-check": "^2.1.1",
|
||||
|
||||
+4
-4
@@ -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"]').click();
|
||||
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
|
||||
cy.get('[data-cy="measurement-item"]').click();
|
||||
|
||||
const [x1, y1] = [150, 100];
|
||||
|
||||
+1
-1
@@ -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"]').click();
|
||||
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').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"]').click();
|
||||
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').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"]').click();
|
||||
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
|
||||
|
||||
cy.scrollToIndex(13);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ Cypress.Commands.add('openStudy', PatientName => {
|
||||
cy.openStudyList();
|
||||
cy.get('#filter-patientNameOrId').type(PatientName);
|
||||
// cy.get('@getStudies').then(() => {
|
||||
cy.wait(1000);
|
||||
cy.waitQueryList();
|
||||
|
||||
cy.get('[data-cy="study-list-results"]', { timeout: 5000 })
|
||||
.contains(PatientName)
|
||||
@@ -65,7 +65,8 @@ Cypress.Commands.add(
|
||||
) {
|
||||
cy.openStudyInViewer(StudyInstanceUID, otherParams);
|
||||
cy.waitDicomImage();
|
||||
cy.wait(2000);
|
||||
// Very short wait to ensure pending updates are handled
|
||||
cy.wait(25);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -78,6 +79,9 @@ Cypress.Commands.add(
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add('waitQueryList', () => {
|
||||
cy.get('[data-querying="false"]');
|
||||
});
|
||||
/**
|
||||
* Command to search for a Modality and open the study.
|
||||
*
|
||||
@@ -89,7 +93,7 @@ Cypress.Commands.add('openStudyModality', Modality => {
|
||||
|
||||
cy.get('#filter-accessionOrModalityOrDescription')
|
||||
.type(Modality)
|
||||
.wait(2000);
|
||||
.waitQueryList();
|
||||
|
||||
cy.get('[data-cy="study-list-results"]')
|
||||
.contains(Modality)
|
||||
@@ -113,7 +117,7 @@ Cypress.Commands.add('openStudyList', () => {
|
||||
// For some reason cypress 12.x does not like to stub the network request
|
||||
// so we just wait herer for 1 second
|
||||
// cy.wait('@getStudies');
|
||||
cy.wait(1000);
|
||||
cy.waitQueryList();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('waitStudyList', () => {
|
||||
@@ -198,54 +202,27 @@ Cypress.Commands.add('expectMinimumThumbnails', (seriesToWait = 1) => {
|
||||
});
|
||||
|
||||
//Command to wait DICOM image to load into the viewport
|
||||
Cypress.Commands.add('waitDicomImage', (timeout = 50000) => {
|
||||
const loaded = cy.isPageLoaded();
|
||||
|
||||
if (loaded) {
|
||||
cy.window()
|
||||
.its('cornerstone')
|
||||
.then({ timeout }, $cornerstone => {
|
||||
return new Cypress.Promise(resolve => {
|
||||
const onEvent = renderedEvt => {
|
||||
const element = renderedEvt.detail.element;
|
||||
|
||||
element.removeEventListener(
|
||||
$cornerstone.Enums.Events.IMAGE_RENDERED,
|
||||
onEvent
|
||||
);
|
||||
$cornerstone.eventTarget.removeEventListener(
|
||||
$cornerstone.Enums.Events.IMAGE_RENDERED,
|
||||
onEvent
|
||||
);
|
||||
resolve();
|
||||
};
|
||||
const onEnabled = enabledEvt => {
|
||||
const element = enabledEvt.detail.element;
|
||||
|
||||
element.addEventListener(
|
||||
$cornerstone.Enums.Events.IMAGE_RENDERED,
|
||||
onEvent
|
||||
);
|
||||
|
||||
$cornerstone.eventTarget.removeEventListener(
|
||||
$cornerstone.Enums.Events.ELEMENT_ENABLED,
|
||||
onEnabled
|
||||
);
|
||||
};
|
||||
const enabledElements = $cornerstone.getEnabledElements();
|
||||
if (enabledElements && enabledElements.length) {
|
||||
// Sometimes the page finishes rendering before this gets run,
|
||||
// if so, just resolve immediately.
|
||||
resolve();
|
||||
} else {
|
||||
$cornerstone.eventTarget.addEventListener(
|
||||
$cornerstone.Enums.Events.ELEMENT_ENABLED,
|
||||
onEnabled
|
||||
Cypress.Commands.add('waitDicomImage', () => {
|
||||
cy.window()
|
||||
.its('cornerstone')
|
||||
.should($cornerstone => {
|
||||
const enabled = $cornerstone.getEnabledElements();
|
||||
if (enabled?.length) {
|
||||
enabled.forEach((item, i) => {
|
||||
if (
|
||||
item.viewport.viewportStatus !==
|
||||
$cornerstone.Enums.ViewportStatus.RENDERED
|
||||
) {
|
||||
throw new Error(
|
||||
`Viewport ${i} in state ${item.viewport.viewportStatus}`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
throw new Error('No enabled elements');
|
||||
}
|
||||
});
|
||||
cy.log('DICOM image loaded');
|
||||
});
|
||||
|
||||
//Command to reset and clear all the changes made to the viewport
|
||||
@@ -401,7 +378,8 @@ Cypress.Commands.add('setLayout', (columns = 1, rows = 1) => {
|
||||
.eq(columns - 1)
|
||||
.click();
|
||||
|
||||
cy.wait(1000);
|
||||
cy.wait(10);
|
||||
cy.waitDicomImage();
|
||||
});
|
||||
|
||||
function convertCanvas(documentClone) {
|
||||
|
||||
@@ -43,3 +43,5 @@
|
||||
# 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
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/app",
|
||||
"version": "3.7.0-beta.2",
|
||||
"version": "3.7.0-beta.39",
|
||||
"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.1.8",
|
||||
"@ohif/core": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.7.0-beta.2",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.2",
|
||||
"@ohif/extension-default": "3.7.0-beta.2",
|
||||
"@ohif/extension-dicom-microscopy": "3.7.0-beta.2",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.2",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.2",
|
||||
"@ohif/extension-test": "3.7.0-beta.2",
|
||||
"@ohif/i18n": "3.7.0-beta.2",
|
||||
"@ohif/mode-basic-dev-mode": "3.7.0-beta.2",
|
||||
"@ohif/mode-longitudinal": "3.7.0-beta.2",
|
||||
"@ohif/mode-microscopy": "3.7.0-beta.2",
|
||||
"@ohif/mode-test": "3.7.0-beta.2",
|
||||
"@ohif/ui": "3.7.0-beta.2",
|
||||
"@cornerstonejs/dicom-image-loader": "^1.4.4",
|
||||
"@ohif/core": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.7.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.39",
|
||||
"@ohif/extension-default": "3.7.0-beta.39",
|
||||
"@ohif/extension-dicom-microscopy": "3.7.0-beta.39",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.39",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.39",
|
||||
"@ohif/extension-test": "3.7.0-beta.39",
|
||||
"@ohif/i18n": "3.7.0-beta.39",
|
||||
"@ohif/mode-basic-dev-mode": "3.7.0-beta.39",
|
||||
"@ohif/mode-longitudinal": "3.7.0-beta.39",
|
||||
"@ohif/mode-microscopy": "3.7.0-beta.39",
|
||||
"@ohif/mode-test": "3.7.0-beta.39",
|
||||
"@ohif/ui": "3.7.0-beta.39",
|
||||
"@types/react": "^17.0.38",
|
||||
"classnames": "^2.3.2",
|
||||
"core-js": "^3.16.1",
|
||||
|
||||
@@ -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,
|
||||
@@ -13,10 +13,10 @@ window.config = {
|
||||
defaultDataSourceName: 'dicomweb',
|
||||
dataSources: [
|
||||
{
|
||||
friendlyName: 'dcmjs DICOMWeb Server',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'dicomweb',
|
||||
configuration: {
|
||||
friendlyName: 'dcmjs DICOMWeb Server',
|
||||
name: 'DCM4CHEE',
|
||||
// Something here to check build
|
||||
wadoUriRoot: 'https://myserver.com/dicomweb',
|
||||
@@ -30,21 +30,23 @@ window.config = {
|
||||
supportsFuzzyMatching: false,
|
||||
supportsWildcard: false,
|
||||
staticWado: true,
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom json',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
|
||||
sourceName: 'dicomjson',
|
||||
configuration: {
|
||||
friendlyName: 'dicom json',
|
||||
name: 'json',
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom local',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomlocal',
|
||||
sourceName: 'dicomlocal',
|
||||
configuration: {},
|
||||
configuration: {
|
||||
friendlyName: 'dicom local',
|
||||
},
|
||||
},
|
||||
],
|
||||
httpErrorHandler: error => {
|
||||
|
||||
@@ -11,7 +11,6 @@ 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,
|
||||
@@ -37,10 +36,10 @@ window.config = {
|
||||
// },
|
||||
dataSources: [
|
||||
{
|
||||
friendlyName: 'dcmjs DICOMWeb Server',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'dicomweb',
|
||||
configuration: {
|
||||
friendlyName: 'dcmjs DICOMWeb Server',
|
||||
name: 'aws',
|
||||
// old server
|
||||
// wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado',
|
||||
@@ -51,7 +50,6 @@ 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',
|
||||
@@ -68,29 +66,31 @@ window.config = {
|
||||
enabled: true,
|
||||
relativeResolution: 'studies',
|
||||
},
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicomweb delegating proxy',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomwebproxy',
|
||||
sourceName: 'dicomwebproxy',
|
||||
configuration: {
|
||||
friendlyName: 'dicomweb delegating proxy',
|
||||
name: 'dicomwebproxy',
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom json',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
|
||||
sourceName: 'dicomjson',
|
||||
configuration: {
|
||||
friendlyName: 'dicom json',
|
||||
name: 'json',
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom local',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomlocal',
|
||||
sourceName: 'dicomlocal',
|
||||
configuration: {},
|
||||
configuration: {
|
||||
friendlyName: 'dicom local',
|
||||
},
|
||||
},
|
||||
],
|
||||
httpErrorHandler: error => {
|
||||
|
||||
@@ -4,17 +4,16 @@ 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,
|
||||
defaultDataSourceName: 'dicomweb',
|
||||
dataSources: [
|
||||
{
|
||||
friendlyName: 'DCM4CHEE Server',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'dicomweb',
|
||||
configuration: {
|
||||
friendlyName: 'DCM4CHEE Server',
|
||||
name: 'DCM4CHEE',
|
||||
wadoUriRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
|
||||
qidoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
|
||||
@@ -25,6 +24,7 @@ window.config = {
|
||||
bulkDataURI: {
|
||||
enabled: false,
|
||||
},
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -4,7 +4,6 @@ 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,
|
||||
@@ -13,10 +12,10 @@ window.config = {
|
||||
defaultDataSourceName: 'dicomweb',
|
||||
dataSources: [
|
||||
{
|
||||
friendlyName: 'dcmjs DICOMWeb Server',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'dicomweb',
|
||||
configuration: {
|
||||
friendlyName: 'dcmjs DICOMWeb Server',
|
||||
name: 'DCM4CHEE',
|
||||
wadoUriRoot: 'http://localhost:5985',
|
||||
qidoRoot: 'http://localhost:5985',
|
||||
@@ -28,21 +27,23 @@ window.config = {
|
||||
enableStudyLazyLoad: true,
|
||||
supportsFuzzyMatching: false,
|
||||
supportsWildcard: false,
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom json',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
|
||||
sourceName: 'dicomjson',
|
||||
configuration: {
|
||||
friendlyName: 'dicom json',
|
||||
name: 'json',
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom local',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomlocal',
|
||||
sourceName: 'dicomlocal',
|
||||
configuration: {},
|
||||
configuration: {
|
||||
friendlyName: 'dicom local',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -5,7 +5,6 @@ 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,
|
||||
@@ -14,10 +13,10 @@ window.config = {
|
||||
defaultDataSourceName: 'dicomweb',
|
||||
dataSources: [
|
||||
{
|
||||
friendlyName: 'Static WADO Local Data',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'dicomweb',
|
||||
configuration: {
|
||||
friendlyName: 'Static WADO Local Data',
|
||||
name: 'DCM4CHEE',
|
||||
wadoUriRoot: '/dicomweb',
|
||||
qidoRoot: '/dicomweb',
|
||||
@@ -31,21 +30,23 @@ window.config = {
|
||||
supportsWildcard: true,
|
||||
staticWado: true,
|
||||
singlepart: 'bulkdata,video,pdf',
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom json',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
|
||||
sourceName: 'dicomjson',
|
||||
configuration: {
|
||||
friendlyName: 'dicom json',
|
||||
name: 'json',
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom local',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomlocal',
|
||||
sourceName: 'dicomlocal',
|
||||
configuration: {},
|
||||
configuration: {
|
||||
friendlyName: 'dicom local',
|
||||
},
|
||||
},
|
||||
],
|
||||
httpErrorHandler: error => {
|
||||
|
||||
@@ -4,7 +4,6 @@ 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,
|
||||
@@ -12,10 +11,10 @@ window.config = {
|
||||
defaultDataSourceName: 'dicomweb',
|
||||
dataSources: [
|
||||
{
|
||||
friendlyName: 'Orthanc Server',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'dicomweb',
|
||||
configuration: {
|
||||
friendlyName: 'Orthanc Server',
|
||||
name: 'Orthanc',
|
||||
wadoUriRoot: '/wado',
|
||||
qidoRoot: '/dicom-web',
|
||||
@@ -23,21 +22,23 @@ window.config = {
|
||||
qidoSupportsIncludeField: false,
|
||||
imageRendering: 'wadors',
|
||||
thumbnailRendering: 'wadors',
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom json',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
|
||||
sourceName: 'dicomjson',
|
||||
configuration: {
|
||||
friendlyName: 'dicom json',
|
||||
name: 'json',
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom local',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomlocal',
|
||||
sourceName: 'dicomlocal',
|
||||
configuration: {},
|
||||
configuration: {
|
||||
friendlyName: 'dicom local',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -2,7 +2,6 @@ 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,
|
||||
@@ -18,6 +17,7 @@ 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,
|
||||
@@ -12,10 +12,10 @@ window.config = {
|
||||
defaultDataSourceName: 'dicomweb',
|
||||
dataSources: [
|
||||
{
|
||||
friendlyName: 'Orthanc Server',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'dicomweb',
|
||||
configuration: {
|
||||
friendlyName: 'Orthanc Server',
|
||||
name: 'Orthanc',
|
||||
wadoUriRoot: 'http://127.0.0.1/pacs/wado',
|
||||
qidoRoot: 'http://127.0.0.1/pacs/dicom-web',
|
||||
@@ -23,21 +23,23 @@ window.config = {
|
||||
qidoSupportsIncludeField: false,
|
||||
imageRendering: 'wadors',
|
||||
thumbnailRendering: 'wadors',
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom json',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
|
||||
sourceName: 'dicomjson',
|
||||
configuration: {
|
||||
friendlyName: 'dicom json',
|
||||
name: 'json',
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom local',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomlocal',
|
||||
sourceName: 'dicomlocal',
|
||||
configuration: {},
|
||||
configuration: {
|
||||
friendlyName: 'dicom local',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -4,7 +4,6 @@ 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,
|
||||
@@ -13,10 +12,10 @@ window.config = {
|
||||
defaultDataSourceName: 'e2e',
|
||||
dataSources: [
|
||||
{
|
||||
friendlyName: 'StaticWado test data',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'e2e',
|
||||
configuration: {
|
||||
friendlyName: 'StaticWado test data',
|
||||
// The most important field to set for static WADO
|
||||
staticWado: true,
|
||||
name: 'StaticWADO',
|
||||
@@ -31,13 +30,14 @@ window.config = {
|
||||
supportsFuzzyMatching: false,
|
||||
supportsWildcard: true,
|
||||
singlepart: 'video,thumbnail,pdf',
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'Static WADO Local Data',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'local',
|
||||
configuration: {
|
||||
friendlyName: 'Static WADO Local Data',
|
||||
name: 'DCM4CHEE',
|
||||
qidoRoot: '/dicomweb',
|
||||
wadoRoot: '/dicomweb',
|
||||
@@ -54,10 +54,10 @@ window.config = {
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dcmjs DICOMWeb Server',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'ohif',
|
||||
configuration: {
|
||||
friendlyName: 'dcmjs DICOMWeb Server',
|
||||
name: 'aws',
|
||||
// old server
|
||||
// wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado',
|
||||
@@ -98,18 +98,19 @@ window.config = {
|
||||
// },
|
||||
// },
|
||||
{
|
||||
friendlyName: 'dicom json',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
|
||||
sourceName: 'dicomjson',
|
||||
configuration: {
|
||||
friendlyName: 'dicom json',
|
||||
name: 'json',
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom local',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomlocal',
|
||||
sourceName: 'dicomlocal',
|
||||
configuration: {},
|
||||
configuration: {
|
||||
friendlyName: 'dicom local',
|
||||
},
|
||||
},
|
||||
],
|
||||
httpErrorHandler: error => {
|
||||
|
||||
@@ -6,7 +6,6 @@ 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,
|
||||
@@ -37,10 +36,10 @@ window.config = {
|
||||
defaultDataSourceName: 'dicomweb',
|
||||
dataSources: [
|
||||
{
|
||||
friendlyName: 'dcmjs DICOMWeb Server',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'dicomweb',
|
||||
configuration: {
|
||||
friendlyName: 'dcmjs DICOMWeb Server',
|
||||
name: 'GCP',
|
||||
wadoUriRoot:
|
||||
'https://healthcare.googleapis.com/v1/projects/ohif-cloud-healthcare/locations/us-east4/datasets/ohif-qa-dataset/dicomStores/ohif-qa-2/dicomWeb',
|
||||
@@ -55,21 +54,23 @@ window.config = {
|
||||
supportsFuzzyMatching: true,
|
||||
supportsWildcard: false,
|
||||
dicomUploadEnabled: true,
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom json',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
|
||||
sourceName: 'dicomjson',
|
||||
configuration: {
|
||||
friendlyName: 'dicom json',
|
||||
name: 'json',
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom local',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomlocal',
|
||||
sourceName: 'dicomlocal',
|
||||
configuration: {},
|
||||
configuration: {
|
||||
friendlyName: 'dicom local',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -2,7 +2,6 @@ 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,
|
||||
|
||||
@@ -8,7 +8,6 @@ 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,
|
||||
@@ -16,10 +15,10 @@ window.config = {
|
||||
defaultDataSourceName: 'dicomweb',
|
||||
dataSources: [
|
||||
{
|
||||
friendlyName: 'DCM4CHEE Server',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'dicomweb',
|
||||
configuration: {
|
||||
friendlyName: 'DCM4CHEE Server',
|
||||
name: 'DCM4CHEE',
|
||||
wadoUriRoot: 'http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/wado',
|
||||
qidoRoot: 'http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||
@@ -39,21 +38,23 @@ window.config = {
|
||||
bulkDataURI: {
|
||||
enabled: true,
|
||||
},
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom json',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
|
||||
sourceName: 'dicomjson',
|
||||
configuration: {
|
||||
friendlyName: 'dicom json',
|
||||
name: 'json',
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom local',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomlocal',
|
||||
sourceName: 'dicomlocal',
|
||||
configuration: {},
|
||||
configuration: {
|
||||
friendlyName: 'dicom local',
|
||||
},
|
||||
},
|
||||
],
|
||||
studyListFunctionsEnabled: true,
|
||||
|
||||
@@ -16,10 +16,10 @@ window.config = {
|
||||
defaultDataSourceName: 'dicomweb',
|
||||
dataSources: [
|
||||
{
|
||||
friendlyName: 'dcmjs DICOMWeb Server',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
|
||||
sourceName: 'dicomweb',
|
||||
configuration: {
|
||||
friendlyName: 'dcmjs DICOMWeb Server',
|
||||
name: 'DCM4CHEE',
|
||||
wadoUriRoot: 'http://localhost/dicom-web',
|
||||
qidoRoot: 'http://localhost/dicom-web',
|
||||
@@ -38,18 +38,19 @@ window.config = {
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom json',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
|
||||
sourceName: 'dicomjson',
|
||||
configuration: {
|
||||
friendlyName: 'dicom json',
|
||||
name: 'json',
|
||||
},
|
||||
},
|
||||
{
|
||||
friendlyName: 'dicom local',
|
||||
namespace: '@ohif/extension-default.dataSourcesModule.dicomlocal',
|
||||
sourceName: 'dicomlocal',
|
||||
configuration: {},
|
||||
configuration: {
|
||||
friendlyName: 'dicom local',
|
||||
},
|
||||
},
|
||||
],
|
||||
httpErrorHandler: error => {
|
||||
|
||||
Loaded 100 of 602 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user