fix: jump to measurement forever (#4867)
This commit is contained in:
parent
eafa2efda5
commit
d7bd36544a
318
bun.lock
318
bun.lock
@ -33,7 +33,7 @@
|
|||||||
},
|
},
|
||||||
"addOns/externals/devDependencies": {
|
"addOns/externals/devDependencies": {
|
||||||
"name": "@externals/devDependencies",
|
"name": "@externals/devDependencies",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@kitware/vtk.js": "32.12.0",
|
"@kitware/vtk.js": "32.12.0",
|
||||||
@ -121,21 +121,21 @@
|
|||||||
},
|
},
|
||||||
"addOns/externals/dicom-microscopy-viewer": {
|
"addOns/externals/dicom-microscopy-viewer": {
|
||||||
"name": "@externals/dicom-microscopy-viewer",
|
"name": "@externals/dicom-microscopy-viewer",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dicom-microscopy-viewer": "^0.46.1",
|
"dicom-microscopy-viewer": "^0.46.1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"extensions/cornerstone": {
|
"extensions/cornerstone": {
|
||||||
"name": "@ohif/extension-cornerstone",
|
"name": "@ohif/extension-cornerstone",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/adapters": "^3.7.16",
|
"@cornerstonejs/adapters": "^3.7.17",
|
||||||
"@cornerstonejs/core": "^3.7.16",
|
"@cornerstonejs/core": "^3.7.17",
|
||||||
"@cornerstonejs/labelmap-interpolation": "^3.7.16",
|
"@cornerstonejs/labelmap-interpolation": "^3.7.17",
|
||||||
"@cornerstonejs/polymorphic-segmentation": "^3.7.16",
|
"@cornerstonejs/polymorphic-segmentation": "^3.7.17",
|
||||||
"@cornerstonejs/tools": "^3.7.16",
|
"@cornerstonejs/tools": "^3.7.17",
|
||||||
"@itk-wasm/morphological-contour-interpolation": "1.1.0",
|
"@itk-wasm/morphological-contour-interpolation": "1.1.0",
|
||||||
"@kitware/vtk.js": "32.12.0",
|
"@kitware/vtk.js": "32.12.0",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
@ -152,9 +152,9 @@
|
|||||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||||
"@cornerstonejs/dicom-image-loader": "^3.7.16",
|
"@cornerstonejs/dicom-image-loader": "^3.7.17",
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/ui": "3.10.0-beta.139",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"dcmjs": "*",
|
"dcmjs": "*",
|
||||||
"dicom-parser": "^1.8.21",
|
"dicom-parser": "^1.8.21",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
@ -166,19 +166,19 @@
|
|||||||
},
|
},
|
||||||
"extensions/cornerstone-dicom-pmap": {
|
"extensions/cornerstone-dicom-pmap": {
|
||||||
"name": "@ohif/extension-cornerstone-dicom-pmap",
|
"name": "@ohif/extension-cornerstone-dicom-pmap",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/adapters": "^3.7.16",
|
"@cornerstonejs/adapters": "^3.7.17",
|
||||||
"@cornerstonejs/core": "^3.7.16",
|
"@cornerstonejs/core": "^3.7.17",
|
||||||
"@kitware/vtk.js": "32.12.0",
|
"@kitware/vtk.js": "32.12.0",
|
||||||
"react-color": "^2.19.3",
|
"react-color": "^2.19.3",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/i18n": "3.10.0-beta.139",
|
"@ohif/i18n": "3.10.0-beta.140",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
@ -189,16 +189,16 @@
|
|||||||
},
|
},
|
||||||
"extensions/cornerstone-dicom-rt": {
|
"extensions/cornerstone-dicom-rt": {
|
||||||
"name": "@ohif/extension-cornerstone-dicom-rt",
|
"name": "@ohif/extension-cornerstone-dicom-rt",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"react-color": "^2.19.3",
|
"react-color": "^2.19.3",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/i18n": "3.10.0-beta.139",
|
"@ohif/i18n": "3.10.0-beta.140",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
@ -209,19 +209,19 @@
|
|||||||
},
|
},
|
||||||
"extensions/cornerstone-dicom-seg": {
|
"extensions/cornerstone-dicom-seg": {
|
||||||
"name": "@ohif/extension-cornerstone-dicom-seg",
|
"name": "@ohif/extension-cornerstone-dicom-seg",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/adapters": "^3.7.16",
|
"@cornerstonejs/adapters": "^3.7.17",
|
||||||
"@cornerstonejs/core": "^3.7.16",
|
"@cornerstonejs/core": "^3.7.17",
|
||||||
"@kitware/vtk.js": "32.12.0",
|
"@kitware/vtk.js": "32.12.0",
|
||||||
"react-color": "^2.19.3",
|
"react-color": "^2.19.3",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/i18n": "3.10.0-beta.139",
|
"@ohif/i18n": "3.10.0-beta.140",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
@ -232,19 +232,19 @@
|
|||||||
},
|
},
|
||||||
"extensions/cornerstone-dicom-sr": {
|
"extensions/cornerstone-dicom-sr": {
|
||||||
"name": "@ohif/extension-cornerstone-dicom-sr",
|
"name": "@ohif/extension-cornerstone-dicom-sr",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/adapters": "^3.7.16",
|
"@cornerstonejs/adapters": "^3.7.17",
|
||||||
"@cornerstonejs/core": "^3.7.16",
|
"@cornerstonejs/core": "^3.7.17",
|
||||||
"@cornerstonejs/tools": "^3.7.16",
|
"@cornerstonejs/tools": "^3.7.17",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.139",
|
"@ohif/extension-measurement-tracking": "3.10.0-beta.140",
|
||||||
"@ohif/ui": "3.10.0-beta.139",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"dcmjs": "*",
|
"dcmjs": "*",
|
||||||
"dicom-parser": "^1.8.9",
|
"dicom-parser": "^1.8.9",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
@ -254,19 +254,19 @@
|
|||||||
},
|
},
|
||||||
"extensions/cornerstone-dynamic-volume": {
|
"extensions/cornerstone-dynamic-volume": {
|
||||||
"name": "@ohif/extension-cornerstone-dynamic-volume",
|
"name": "@ohif/extension-cornerstone-dynamic-volume",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/core": "^3.7.16",
|
"@cornerstonejs/core": "^3.7.17",
|
||||||
"@cornerstonejs/tools": "^3.7.16",
|
"@cornerstonejs/tools": "^3.7.17",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/i18n": "3.10.0-beta.139",
|
"@ohif/i18n": "3.10.0-beta.140",
|
||||||
"@ohif/ui": "3.10.0-beta.139",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"dcmjs": "*",
|
"dcmjs": "*",
|
||||||
"dicom-parser": "^1.8.21",
|
"dicom-parser": "^1.8.21",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
@ -276,7 +276,7 @@
|
|||||||
},
|
},
|
||||||
"extensions/default": {
|
"extensions/default": {
|
||||||
"name": "@ohif/extension-default",
|
"name": "@ohif/extension-default",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/calculate-suv": "^1.1.0",
|
"@cornerstonejs/calculate-suv": "^1.1.0",
|
||||||
@ -284,8 +284,8 @@
|
|||||||
"lodash.uniqby": "^4.7.0",
|
"lodash.uniqby": "^4.7.0",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/i18n": "3.10.0-beta.139",
|
"@ohif/i18n": "3.10.0-beta.140",
|
||||||
"dcmjs": "*",
|
"dcmjs": "*",
|
||||||
"dicomweb-client": "^0.10.4",
|
"dicomweb-client": "^0.10.4",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
@ -299,7 +299,7 @@
|
|||||||
},
|
},
|
||||||
"extensions/dicom-microscopy": {
|
"extensions/dicom-microscopy": {
|
||||||
"name": "@ohif/extension-dicom-microscopy",
|
"name": "@ohif/extension-dicom-microscopy",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/codec-charls": "^1.2.3",
|
"@cornerstonejs/codec-charls": "^1.2.3",
|
||||||
@ -310,10 +310,10 @@
|
|||||||
"mathjs": "^12.4.2",
|
"mathjs": "^12.4.2",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/i18n": "3.10.0-beta.139",
|
"@ohif/i18n": "3.10.0-beta.140",
|
||||||
"@ohif/ui": "3.10.0-beta.139",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
@ -324,14 +324,14 @@
|
|||||||
},
|
},
|
||||||
"extensions/dicom-pdf": {
|
"extensions/dicom-pdf": {
|
||||||
"name": "@ohif/extension-dicom-pdf",
|
"name": "@ohif/extension-dicom-pdf",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/ui": "3.10.0-beta.139",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"dcmjs": "*",
|
"dcmjs": "*",
|
||||||
"dicom-parser": "^1.8.9",
|
"dicom-parser": "^1.8.9",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
@ -341,14 +341,14 @@
|
|||||||
},
|
},
|
||||||
"extensions/dicom-video": {
|
"extensions/dicom-video": {
|
||||||
"name": "@ohif/extension-dicom-video",
|
"name": "@ohif/extension-dicom-video",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/ui": "3.10.0-beta.139",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"dcmjs": "*",
|
"dcmjs": "*",
|
||||||
"dicom-parser": "^1.8.9",
|
"dicom-parser": "^1.8.9",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
@ -358,20 +358,20 @@
|
|||||||
},
|
},
|
||||||
"extensions/measurement-tracking": {
|
"extensions/measurement-tracking": {
|
||||||
"name": "@ohif/extension-measurement-tracking",
|
"name": "@ohif/extension-measurement-tracking",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@ohif/ui": "3.10.0-beta.139",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"@xstate/react": "^3.2.2",
|
"@xstate/react": "^3.2.2",
|
||||||
"xstate": "^4.10.0",
|
"xstate": "^4.10.0",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@cornerstonejs/core": "^3.7.16",
|
"@cornerstonejs/core": "^3.7.17",
|
||||||
"@cornerstonejs/tools": "^3.7.16",
|
"@cornerstonejs/tools": "^3.7.17",
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/ui": "3.10.0-beta.139",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"dcmjs": "*",
|
"dcmjs": "*",
|
||||||
"lodash.debounce": "^4.0.8",
|
"lodash.debounce": "^4.0.8",
|
||||||
@ -384,14 +384,14 @@
|
|||||||
},
|
},
|
||||||
"extensions/test-extension": {
|
"extensions/test-extension": {
|
||||||
"name": "@ohif/extension-test",
|
"name": "@ohif/extension-test",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/ui": "3.10.0-beta.139",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"dcmjs": "0.38.0",
|
"dcmjs": "0.38.0",
|
||||||
"dicom-parser": "^1.8.9",
|
"dicom-parser": "^1.8.9",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
@ -401,14 +401,14 @@
|
|||||||
},
|
},
|
||||||
"extensions/tmtv": {
|
"extensions/tmtv": {
|
||||||
"name": "@ohif/extension-tmtv",
|
"name": "@ohif/extension-tmtv",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/ui": "3.10.0-beta.139",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"dcmjs": "*",
|
"dcmjs": "*",
|
||||||
"dicom-parser": "^1.8.9",
|
"dicom-parser": "^1.8.9",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
@ -418,7 +418,7 @@
|
|||||||
},
|
},
|
||||||
"modes/basic-dev-mode": {
|
"modes/basic-dev-mode": {
|
||||||
"name": "@ohif/mode-basic-dev-mode",
|
"name": "@ohif/mode-basic-dev-mode",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"i18next": "^17.0.3",
|
"i18next": "^17.0.3",
|
||||||
@ -428,17 +428,17 @@
|
|||||||
"webpack-merge": "^5.7.3",
|
"webpack-merge": "^5.7.3",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.139",
|
"@ohif/extension-dicom-pdf": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-video": "3.10.0-beta.139",
|
"@ohif/extension-dicom-video": "3.10.0-beta.140",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"modes/basic-test-mode": {
|
"modes/basic-test-mode": {
|
||||||
"name": "@ohif/mode-test",
|
"name": "@ohif/mode-test",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"i18next": "^17.0.3",
|
"i18next": "^17.0.3",
|
||||||
@ -448,19 +448,19 @@
|
|||||||
"webpack-merge": "^5.7.3",
|
"webpack-merge": "^5.7.3",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.139",
|
"@ohif/extension-dicom-pdf": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-video": "3.10.0-beta.139",
|
"@ohif/extension-dicom-video": "3.10.0-beta.140",
|
||||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.139",
|
"@ohif/extension-measurement-tracking": "3.10.0-beta.140",
|
||||||
"@ohif/extension-test": "3.10.0-beta.139",
|
"@ohif/extension-test": "3.10.0-beta.140",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"modes/longitudinal": {
|
"modes/longitudinal": {
|
||||||
"name": "@ohif/mode-longitudinal",
|
"name": "@ohif/mode-longitudinal",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"i18next": "^17.0.3",
|
"i18next": "^17.0.3",
|
||||||
@ -470,32 +470,32 @@
|
|||||||
"webpack-merge": "^5.7.3",
|
"webpack-merge": "^5.7.3",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.139",
|
"@ohif/extension-dicom-pdf": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-video": "3.10.0-beta.139",
|
"@ohif/extension-dicom-video": "3.10.0-beta.140",
|
||||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.139",
|
"@ohif/extension-measurement-tracking": "3.10.0-beta.140",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"modes/microscopy": {
|
"modes/microscopy": {
|
||||||
"name": "@ohif/mode-microscopy",
|
"name": "@ohif/mode-microscopy",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"i18next": "^17.0.3",
|
"i18next": "^17.0.3",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-microscopy": "3.10.0-beta.139",
|
"@ohif/extension-dicom-microscopy": "3.10.0-beta.140",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"modes/preclinical-4d": {
|
"modes/preclinical-4d": {
|
||||||
"name": "@ohif/mode-preclinical-4d",
|
"name": "@ohif/mode-preclinical-4d",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
},
|
},
|
||||||
@ -504,17 +504,17 @@
|
|||||||
"webpack-merge": "^5.7.3",
|
"webpack-merge": "^5.7.3",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dynamic-volume": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dynamic-volume": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/extension-tmtv": "3.10.0-beta.139",
|
"@ohif/extension-tmtv": "3.10.0-beta.140",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"modes/segmentation": {
|
"modes/segmentation": {
|
||||||
"name": "@ohif/mode-segmentation",
|
"name": "@ohif/mode-segmentation",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"i18next": "^17.0.3",
|
"i18next": "^17.0.3",
|
||||||
@ -546,19 +546,19 @@
|
|||||||
"webpack-merge": "^5.7.3",
|
"webpack-merge": "^5.7.3",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.139",
|
"@ohif/extension-dicom-pdf": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-video": "3.10.0-beta.139",
|
"@ohif/extension-dicom-video": "3.10.0-beta.140",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"modes/tmtv": {
|
"modes/tmtv": {
|
||||||
"name": "@ohif/mode-tmtv",
|
"name": "@ohif/mode-tmtv",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"i18next": "^17.0.3",
|
"i18next": "^17.0.3",
|
||||||
@ -568,43 +568,43 @@
|
|||||||
"webpack-merge": "^5.7.3",
|
"webpack-merge": "^5.7.3",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.139",
|
"@ohif/extension-dicom-pdf": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-video": "3.10.0-beta.139",
|
"@ohif/extension-dicom-video": "3.10.0-beta.140",
|
||||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.139",
|
"@ohif/extension-measurement-tracking": "3.10.0-beta.140",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"platform/app": {
|
"platform/app": {
|
||||||
"name": "@ohif/app",
|
"name": "@ohif/app",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/codec-charls": "^1.2.3",
|
"@cornerstonejs/codec-charls": "^1.2.3",
|
||||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||||
"@cornerstonejs/dicom-image-loader": "^3.7.16",
|
"@cornerstonejs/dicom-image-loader": "^3.7.17",
|
||||||
"@emotion/serialize": "^1.1.3",
|
"@emotion/serialize": "^1.1.3",
|
||||||
"@ohif/core": "3.10.0-beta.139",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
|
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.139",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-microscopy": "3.10.0-beta.139",
|
"@ohif/extension-dicom-microscopy": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.139",
|
"@ohif/extension-dicom-pdf": "3.10.0-beta.140",
|
||||||
"@ohif/extension-dicom-video": "3.10.0-beta.139",
|
"@ohif/extension-dicom-video": "3.10.0-beta.140",
|
||||||
"@ohif/extension-test": "3.10.0-beta.139",
|
"@ohif/extension-test": "3.10.0-beta.140",
|
||||||
"@ohif/i18n": "3.10.0-beta.139",
|
"@ohif/i18n": "3.10.0-beta.140",
|
||||||
"@ohif/mode-basic-dev-mode": "3.10.0-beta.139",
|
"@ohif/mode-basic-dev-mode": "3.10.0-beta.140",
|
||||||
"@ohif/mode-longitudinal": "3.10.0-beta.139",
|
"@ohif/mode-longitudinal": "3.10.0-beta.140",
|
||||||
"@ohif/mode-microscopy": "3.10.0-beta.139",
|
"@ohif/mode-microscopy": "3.10.0-beta.140",
|
||||||
"@ohif/mode-test": "3.10.0-beta.139",
|
"@ohif/mode-test": "3.10.0-beta.140",
|
||||||
"@ohif/ui": "3.10.0-beta.139",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"@ohif/ui-next": "3.10.0-beta.139",
|
"@ohif/ui-next": "3.10.0-beta.140",
|
||||||
"@svgr/webpack": "^8.1.0",
|
"@svgr/webpack": "^8.1.0",
|
||||||
"@types/react": "^18.3.3",
|
"@types/react": "^18.3.3",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
@ -645,7 +645,7 @@
|
|||||||
},
|
},
|
||||||
"platform/cli": {
|
"platform/cli": {
|
||||||
"name": "@ohif/cli",
|
"name": "@ohif/cli",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"bin": {
|
"bin": {
|
||||||
"ohif-cli": "src/index.js",
|
"ohif-cli": "src/index.js",
|
||||||
},
|
},
|
||||||
@ -669,7 +669,7 @@
|
|||||||
},
|
},
|
||||||
"platform/core": {
|
"platform/core": {
|
||||||
"name": "@ohif/core",
|
"name": "@ohif/core",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"dcmjs": "*",
|
"dcmjs": "*",
|
||||||
@ -694,15 +694,15 @@
|
|||||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||||
"@cornerstonejs/dicom-image-loader": "^3.7.16",
|
"@cornerstonejs/dicom-image-loader": "^3.7.17",
|
||||||
"@ohif/ui": "3.10.0-beta.139",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"cornerstone-math": "0.1.9",
|
"cornerstone-math": "0.1.9",
|
||||||
"dicom-parser": "^1.8.21",
|
"dicom-parser": "^1.8.21",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"platform/i18n": {
|
"platform/i18n": {
|
||||||
"name": "@ohif/i18n",
|
"name": "@ohif/i18n",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"i18next-locize-backend": "^2.0.0",
|
"i18next-locize-backend": "^2.0.0",
|
||||||
@ -727,7 +727,7 @@
|
|||||||
},
|
},
|
||||||
"platform/ui": {
|
"platform/ui": {
|
||||||
"name": "@ohif/ui",
|
"name": "@ohif/ui",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@testing-library/react": "^13.1.0",
|
"@testing-library/react": "^13.1.0",
|
||||||
"browser-detect": "^0.2.28",
|
"browser-detect": "^0.2.28",
|
||||||
@ -787,7 +787,7 @@
|
|||||||
},
|
},
|
||||||
"platform/ui-next": {
|
"platform/ui-next": {
|
||||||
"name": "@ohif/ui-next",
|
"name": "@ohif/ui-next",
|
||||||
"version": "3.10.0-beta.139",
|
"version": "3.10.0-beta.140",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-accordion": "^1.2.0",
|
"@radix-ui/react-accordion": "^1.2.0",
|
||||||
"@radix-ui/react-checkbox": "^1.1.1",
|
"@radix-ui/react-checkbox": "^1.1.1",
|
||||||
@ -1095,7 +1095,7 @@
|
|||||||
|
|
||||||
"@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="],
|
"@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="],
|
||||||
|
|
||||||
"@cornerstonejs/adapters": ["@cornerstonejs/adapters@3.7.16", "", { "dependencies": { "@babel/runtime-corejs2": "^7.17.8", "buffer": "^6.0.3", "dcmjs": "^0.29.8", "gl-matrix": "^3.4.3", "ndarray": "^1.0.19" }, "peerDependencies": { "@cornerstonejs/core": "^3.7.16", "@cornerstonejs/tools": "^3.7.16" } }, "sha512-gMLRTZzhIGOwUT9rufpv4uq5iHTJgg2x6GW++eOi/6bEDY2wOiH2peRM8W1EfAoa3cK+lLLoAqEARlVMJq//tg=="],
|
"@cornerstonejs/adapters": ["@cornerstonejs/adapters@3.7.17", "", { "dependencies": { "@babel/runtime-corejs2": "^7.17.8", "buffer": "^6.0.3", "dcmjs": "^0.29.8", "gl-matrix": "^3.4.3", "ndarray": "^1.0.19" }, "peerDependencies": { "@cornerstonejs/core": "^3.7.17", "@cornerstonejs/tools": "^3.7.17" } }, "sha512-K1tz4y5YRgen+z8Yva5mzO3iwn1UZRoqf0wX8VjU1zszx/F4m19DSNcR9H5BJvlGM09DZjpJ42QXK2o9pIvnTg=="],
|
||||||
|
|
||||||
"@cornerstonejs/calculate-suv": ["@cornerstonejs/calculate-suv@1.1.0", "", {}, "sha512-Q9XraiDJif9aMFArD2iEuDO/HXbcRVCqB7KfaHgDrdTTjgDFovS91Psbdim7crypRSvE6dh/+HKeFNHdvNkA6w=="],
|
"@cornerstonejs/calculate-suv": ["@cornerstonejs/calculate-suv@1.1.0", "", {}, "sha512-Q9XraiDJif9aMFArD2iEuDO/HXbcRVCqB7KfaHgDrdTTjgDFovS91Psbdim7crypRSvE6dh/+HKeFNHdvNkA6w=="],
|
||||||
|
|
||||||
@ -1107,15 +1107,15 @@
|
|||||||
|
|
||||||
"@cornerstonejs/codec-openjph": ["@cornerstonejs/codec-openjph@2.4.7", "", {}, "sha512-qvP4q4JDib7mi9r7LqKOwqz7YZ8gjtDX4ZCezeYf8+eb7MBXCz5uXAMeVF3yz9Axw4XiIMdB/pqXkm8tqCl13w=="],
|
"@cornerstonejs/codec-openjph": ["@cornerstonejs/codec-openjph@2.4.7", "", {}, "sha512-qvP4q4JDib7mi9r7LqKOwqz7YZ8gjtDX4ZCezeYf8+eb7MBXCz5uXAMeVF3yz9Axw4XiIMdB/pqXkm8tqCl13w=="],
|
||||||
|
|
||||||
"@cornerstonejs/core": ["@cornerstonejs/core@3.7.16", "", { "dependencies": { "@kitware/vtk.js": "32.12.1", "comlink": "^4.4.1", "gl-matrix": "^3.4.3", "loglevel": "^1.9.2" } }, "sha512-5rc371p1P+hk1rUzpHTByW+7Mp6LyahqWJLJwt/55a4BEiEtbhWyTSAz/XKWcOd5bgq7huAsyHKCmMcWrHx3pg=="],
|
"@cornerstonejs/core": ["@cornerstonejs/core@3.7.17", "", { "dependencies": { "@kitware/vtk.js": "32.12.1", "comlink": "^4.4.1", "gl-matrix": "^3.4.3", "loglevel": "^1.9.2" } }, "sha512-2Z3FqrGJept9k1dmlGeMBPon1MDR/P7CkcTTevpKTlYiT3D7bqQ+Q5xdssLzWRD86et0PkRSJGktBM163WCgGw=="],
|
||||||
|
|
||||||
"@cornerstonejs/dicom-image-loader": ["@cornerstonejs/dicom-image-loader@3.7.16", "", { "dependencies": { "@cornerstonejs/codec-charls": "^1.2.3", "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.5", "comlink": "^4.4.1", "dicom-parser": "^1.8.9", "jpeg-lossless-decoder-js": "^2.1.0", "pako": "^2.0.4", "uuid": "^9.0.0" }, "peerDependencies": { "@cornerstonejs/core": "^3.7.16" } }, "sha512-8O3cd9L54s3AFE3DZUMKOUvuuE9MkYuWZ8NgCPtBE1Qky6d4KNGKdljzwmpj8JJ7y7yGLW1rI0KqQc9DCf4//Q=="],
|
"@cornerstonejs/dicom-image-loader": ["@cornerstonejs/dicom-image-loader@3.7.17", "", { "dependencies": { "@cornerstonejs/codec-charls": "^1.2.3", "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.5", "comlink": "^4.4.1", "dicom-parser": "^1.8.9", "jpeg-lossless-decoder-js": "^2.1.0", "pako": "^2.0.4", "uuid": "^9.0.0" }, "peerDependencies": { "@cornerstonejs/core": "^3.7.17" } }, "sha512-LKHQ7x7S47TtF8M4ZmR4S+afbSsAT+yVMkKD81VU3A8oyuX7hT4+cUO4JlGGck3BxG4FyjgNSGT+T3YxAH1SHw=="],
|
||||||
|
|
||||||
"@cornerstonejs/labelmap-interpolation": ["@cornerstonejs/labelmap-interpolation@3.7.16", "", { "dependencies": { "@itk-wasm/morphological-contour-interpolation": "1.1.0", "itk-wasm": "1.0.0-b.165" }, "peerDependencies": { "@cornerstonejs/core": "^3.7.16", "@cornerstonejs/tools": "^3.7.16", "@kitware/vtk.js": "32.12.1" } }, "sha512-zoL7arbPywNxUksKkkorcICpIwAgcpYbBBEFIGXt4gSS7NPC7cRU12PU1mj3Cgy+59nO2QIohoPkv0Kj/AwXmA=="],
|
"@cornerstonejs/labelmap-interpolation": ["@cornerstonejs/labelmap-interpolation@3.7.17", "", { "dependencies": { "@itk-wasm/morphological-contour-interpolation": "1.1.0", "itk-wasm": "1.0.0-b.165" }, "peerDependencies": { "@cornerstonejs/core": "^3.7.17", "@cornerstonejs/tools": "^3.7.17", "@kitware/vtk.js": "32.12.1" } }, "sha512-K8R11wqv4TFljMArbx+4JbMtsINeMandp0mD8zyrj1rWXA+RY49QcNa7ob6KBnV26xJqXMT0VyJ0k/Ow53TiLQ=="],
|
||||||
|
|
||||||
"@cornerstonejs/polymorphic-segmentation": ["@cornerstonejs/polymorphic-segmentation@3.7.16", "", { "dependencies": { "@icr/polyseg-wasm": "0.4.0" }, "peerDependencies": { "@cornerstonejs/core": "^3.7.16", "@cornerstonejs/tools": "^3.7.16", "@kitware/vtk.js": "32.12.1" } }, "sha512-HW7h9xRWRDKmaYpv4KWqSYcFz4M2EbMnYNaP+JgnLRws/1eoVPM5YYTsWgyINOM8fdR9o6tMmtMdjcioEGsZPg=="],
|
"@cornerstonejs/polymorphic-segmentation": ["@cornerstonejs/polymorphic-segmentation@3.7.17", "", { "dependencies": { "@icr/polyseg-wasm": "0.4.0" }, "peerDependencies": { "@cornerstonejs/core": "^3.7.17", "@cornerstonejs/tools": "^3.7.17", "@kitware/vtk.js": "32.12.1" } }, "sha512-ZI0643arqYbkrjadDSOsGTO2JS1OUtJkF8qEnjjG8MlxqQ7g6sPnTM/atrYRc9ZFoJxFL4kz7D0gOjcBrarYeQ=="],
|
||||||
|
|
||||||
"@cornerstonejs/tools": ["@cornerstonejs/tools@3.7.16", "", { "dependencies": { "@types/offscreencanvas": "2019.7.3", "comlink": "^4.4.1", "lodash.get": "^4.4.2" }, "peerDependencies": { "@cornerstonejs/core": "^3.7.16", "@kitware/vtk.js": "32.12.1", "@types/d3-array": "^3.0.4", "@types/d3-interpolate": "^3.0.1", "d3-array": "^3.2.3", "d3-interpolate": "^3.0.1", "gl-matrix": "^3.4.3" } }, "sha512-hmAAmUiEr8z920btZtkT7jqYgZzQqLT82FijfYZVd591nddR25hb77OXEJ+PPAQbvktwPSUZx0kMBoUuM5VpWw=="],
|
"@cornerstonejs/tools": ["@cornerstonejs/tools@3.7.17", "", { "dependencies": { "@types/offscreencanvas": "2019.7.3", "comlink": "^4.4.1", "lodash.get": "^4.4.2" }, "peerDependencies": { "@cornerstonejs/core": "^3.7.17", "@kitware/vtk.js": "32.12.1", "@types/d3-array": "^3.0.4", "@types/d3-interpolate": "^3.0.1", "d3-array": "^3.2.3", "d3-interpolate": "^3.0.1", "gl-matrix": "^3.4.3" } }, "sha512-ZDMboShGzMDkqnzEDE7Y9UTJgHqGkVQt8l6AL5dCyA/IIlWEXXdxVe1weotJxgjMqaPETiwJ5EtN/3D4+tf1Rg=="],
|
||||||
|
|
||||||
"@csstools/postcss-cascade-layers": ["@csstools/postcss-cascade-layers@1.1.1", "", { "dependencies": { "@csstools/selector-specificity": "^2.0.2", "postcss-selector-parser": "^6.0.10" }, "peerDependencies": { "postcss": "^8.2" } }, "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA=="],
|
"@csstools/postcss-cascade-layers": ["@csstools/postcss-cascade-layers@1.1.1", "", { "dependencies": { "@csstools/selector-specificity": "^2.0.2", "postcss-selector-parser": "^6.0.10" }, "peerDependencies": { "postcss": "^8.2" } }, "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA=="],
|
||||||
|
|
||||||
|
|||||||
@ -46,8 +46,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/adapters": "^3.7.16",
|
"@cornerstonejs/adapters": "^3.7.17",
|
||||||
"@cornerstonejs/core": "^3.7.16",
|
"@cornerstonejs/core": "^3.7.17",
|
||||||
"@kitware/vtk.js": "32.12.0",
|
"@kitware/vtk.js": "32.12.0",
|
||||||
"react-color": "^2.19.3"
|
"react-color": "^2.19.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,8 +46,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/adapters": "^3.7.16",
|
"@cornerstonejs/adapters": "^3.7.17",
|
||||||
"@cornerstonejs/core": "^3.7.16",
|
"@cornerstonejs/core": "^3.7.17",
|
||||||
"@kitware/vtk.js": "32.12.0",
|
"@kitware/vtk.js": "32.12.0",
|
||||||
"react-color": "^2.19.3"
|
"react-color": "^2.19.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,9 +46,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/adapters": "^3.7.16",
|
"@cornerstonejs/adapters": "^3.7.17",
|
||||||
"@cornerstonejs/core": "^3.7.16",
|
"@cornerstonejs/core": "^3.7.17",
|
||||||
"@cornerstonejs/tools": "^3.7.16",
|
"@cornerstonejs/tools": "^3.7.17",
|
||||||
"classnames": "^2.3.2"
|
"classnames": "^2.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -77,28 +77,4 @@ export default function init({
|
|||||||
SRRectangleROI: dashedLine,
|
SRRectangleROI: dashedLine,
|
||||||
global: {},
|
global: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
measurementService.subscribe(
|
|
||||||
MeasurementService.EVENTS.JUMP_TO_MEASUREMENT_LAYOUT,
|
|
||||||
({ viewportId, measurement, isConsumed }) => {
|
|
||||||
if (isConsumed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const currentViewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
||||||
const { viewPlaneNormal } = currentViewport.getCamera();
|
|
||||||
const referencedImageId = csToolsUtils.getClosestImageIdForStackViewport(
|
|
||||||
currentViewport as StackViewport,
|
|
||||||
measurement.points[0],
|
|
||||||
viewPlaneNormal
|
|
||||||
);
|
|
||||||
const imageIndex = (currentViewport as StackViewport)
|
|
||||||
.getImageIds()
|
|
||||||
.indexOf(referencedImageId);
|
|
||||||
csUtils.jumpToSlice(currentViewport.element, { imageIndex });
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('Unable to jump to image based on measurement coordinate', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,8 +42,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/core": "^3.7.16",
|
"@cornerstonejs/core": "^3.7.17",
|
||||||
"@cornerstonejs/tools": "^3.7.16",
|
"@cornerstonejs/tools": "^3.7.17",
|
||||||
"classnames": "^2.3.2"
|
"classnames": "^2.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,7 +38,7 @@
|
|||||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||||
"@cornerstonejs/dicom-image-loader": "^3.7.16",
|
"@cornerstonejs/dicom-image-loader": "^3.7.17",
|
||||||
"@ohif/core": "3.10.0-beta.140",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/ui": "3.10.0-beta.140",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"dcmjs": "*",
|
"dcmjs": "*",
|
||||||
@ -51,11 +51,11 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/adapters": "^3.7.16",
|
"@cornerstonejs/adapters": "^3.7.17",
|
||||||
"@cornerstonejs/core": "^3.7.16",
|
"@cornerstonejs/core": "^3.7.17",
|
||||||
"@cornerstonejs/labelmap-interpolation": "^3.7.16",
|
"@cornerstonejs/labelmap-interpolation": "^3.7.17",
|
||||||
"@cornerstonejs/polymorphic-segmentation": "^3.7.16",
|
"@cornerstonejs/polymorphic-segmentation": "^3.7.17",
|
||||||
"@cornerstonejs/tools": "^3.7.16",
|
"@cornerstonejs/tools": "^3.7.17",
|
||||||
"@itk-wasm/morphological-contour-interpolation": "1.1.0",
|
"@itk-wasm/morphological-contour-interpolation": "1.1.0",
|
||||||
"@kitware/vtk.js": "32.12.0",
|
"@kitware/vtk.js": "32.12.0",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
|
|||||||
@ -23,12 +23,6 @@ import { WITH_NAVIGATION } from '../services/ViewportService/CornerstoneViewport
|
|||||||
|
|
||||||
const STACK = 'stack';
|
const STACK = 'stack';
|
||||||
|
|
||||||
/**
|
|
||||||
* Caches the jump to measurement operation, so that if display set is shown,
|
|
||||||
* it can jump to the measurement.
|
|
||||||
*/
|
|
||||||
let cacheJumpToMeasurementEvent;
|
|
||||||
|
|
||||||
// Todo: This should be done with expose of internal API similar to react-vtkjs-viewport
|
// Todo: This should be done with expose of internal API similar to react-vtkjs-viewport
|
||||||
// Then we don't need to worry about the re-renders if the props change.
|
// Then we don't need to worry about the re-renders if the props change.
|
||||||
const OHIFCornerstoneViewport = React.memo(
|
const OHIFCornerstoneViewport = React.memo(
|
||||||
@ -99,6 +93,7 @@ const OHIFCornerstoneViewport = React.memo(
|
|||||||
cornerstoneCacheService,
|
cornerstoneCacheService,
|
||||||
viewportActionCornersService,
|
viewportActionCornersService,
|
||||||
customizationService,
|
customizationService,
|
||||||
|
measurementService,
|
||||||
} = servicesManager.services;
|
} = servicesManager.services;
|
||||||
|
|
||||||
const [viewportDialogState] = useViewportDialog();
|
const [viewportDialogState] = useViewportDialog();
|
||||||
@ -263,14 +258,6 @@ const OHIFCornerstoneViewport = React.memo(
|
|||||||
|
|
||||||
const presentations = getViewportPresentations(viewportId, viewportOptions);
|
const presentations = getViewportPresentations(viewportId, viewportOptions);
|
||||||
|
|
||||||
let measurement;
|
|
||||||
if (cacheJumpToMeasurementEvent?.viewportId === viewportId) {
|
|
||||||
measurement = cacheJumpToMeasurementEvent.measurement;
|
|
||||||
// Delete the position presentation so that viewport navigates direct
|
|
||||||
presentations.positionPresentation = null;
|
|
||||||
cacheJumpToMeasurementEvent = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: This is a hack to get the grid to re-render the OHIFCornerstoneViewport component
|
// Note: This is a hack to get the grid to re-render the OHIFCornerstoneViewport component
|
||||||
// Used for segmentation hydration right now, since the logic to decide whether
|
// Used for segmentation hydration right now, since the logic to decide whether
|
||||||
// a viewport needs to render a segmentation lives inside the CornerstoneViewportService
|
// a viewport needs to render a segmentation lives inside the CornerstoneViewportService
|
||||||
@ -288,10 +275,6 @@ const OHIFCornerstoneViewport = React.memo(
|
|||||||
displaySetOptions,
|
displaySetOptions,
|
||||||
presentations
|
presentations
|
||||||
);
|
);
|
||||||
|
|
||||||
if (measurement) {
|
|
||||||
cs3DTools.annotation.selection.setAnnotationSelected(measurement.uid);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
loadViewportData();
|
loadViewportData();
|
||||||
@ -312,16 +295,13 @@ const OHIFCornerstoneViewport = React.memo(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsubscribeFromJumpToMeasurementEvents = _subscribeToJumpToMeasurementEvents(
|
const { unsubscribe } = measurementService.subscribe(
|
||||||
elementRef,
|
MeasurementService.EVENTS.JUMP_TO_MEASUREMENT_VIEWPORT,
|
||||||
viewportId,
|
event => handleJumpToMeasurement(event, elementRef, viewportId, cornerstoneViewportService)
|
||||||
servicesManager
|
|
||||||
);
|
);
|
||||||
|
|
||||||
_checkForCachedJumpToMeasurementEvents(elementRef, viewportId, displaySets, servicesManager);
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
unsubscribeFromJumpToMeasurementEvents();
|
unsubscribe();
|
||||||
};
|
};
|
||||||
}, [displaySets, elementRef, viewportId, isJumpToMeasurementDisabled, servicesManager]);
|
}, [displaySets, elementRef, viewportId, isJumpToMeasurementDisabled, servicesManager]);
|
||||||
|
|
||||||
@ -427,99 +407,52 @@ const OHIFCornerstoneViewport = React.memo(
|
|||||||
areEqual
|
areEqual
|
||||||
);
|
);
|
||||||
|
|
||||||
function _subscribeToJumpToMeasurementEvents(elementRef, viewportId, servicesManager) {
|
// Helper function to handle jumping to measurements
|
||||||
const { measurementService, cornerstoneViewportService } = servicesManager.services;
|
function handleJumpToMeasurement(event, elementRef, viewportId, cornerstoneViewportService) {
|
||||||
|
const { measurement, isConsumed } = event;
|
||||||
|
if (!measurement || isConsumed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { unsubscribe } = measurementService.subscribe(
|
const enabledElement = getEnabledElement(elementRef.current);
|
||||||
MeasurementService.EVENTS.JUMP_TO_MEASUREMENT_VIEWPORT,
|
|
||||||
props => {
|
if (!enabledElement) {
|
||||||
cacheJumpToMeasurementEvent = props;
|
return;
|
||||||
const { viewportId: jumpId, measurement, isConsumed } = props;
|
}
|
||||||
if (!measurement || isConsumed) {
|
|
||||||
return;
|
const viewport = enabledElement.viewport as csTypes.IStackViewport | csTypes.IVolumeViewport;
|
||||||
}
|
|
||||||
if (cacheJumpToMeasurementEvent.cornerstoneViewport === undefined) {
|
const { metadata, displaySetInstanceUID } = measurement;
|
||||||
// Decide on which viewport should handle this
|
|
||||||
cacheJumpToMeasurementEvent.cornerstoneViewport =
|
const viewportDisplaySets = cornerstoneViewportService.getViewportDisplaySets(viewportId);
|
||||||
cornerstoneViewportService.getViewportIdToJump(jumpId, {
|
|
||||||
displaySetInstanceUID: measurement.displaySetInstanceUID,
|
const showingDisplaySet = viewportDisplaySets.find(
|
||||||
...measurement.metadata,
|
ds => ds.displaySetInstanceUID === displaySetInstanceUID
|
||||||
referencedImageId:
|
|
||||||
measurement.referencedImageId || measurement.metadata?.referencedImageId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (cacheJumpToMeasurementEvent.cornerstoneViewport !== viewportId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_jumpToMeasurement(measurement, elementRef, viewportId, servicesManager);
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return unsubscribe;
|
let metadataToUse = metadata;
|
||||||
}
|
// if it is not showing the displaySet we need to remove the FOR from the metadata
|
||||||
|
if (!showingDisplaySet) {
|
||||||
|
metadataToUse = {
|
||||||
|
...metadata,
|
||||||
|
FrameOfReferenceUID: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Check if there is a queued jumpToMeasurement event
|
// Todo: make it work with cases where we want to define FOR based measurements too
|
||||||
function _checkForCachedJumpToMeasurementEvents(
|
if (!viewport.isReferenceViewable(metadataToUse, WITH_NAVIGATION)) {
|
||||||
elementRef,
|
|
||||||
viewportId,
|
|
||||||
displaySets,
|
|
||||||
servicesManager
|
|
||||||
) {
|
|
||||||
if (!cacheJumpToMeasurementEvent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (cacheJumpToMeasurementEvent.isConsumed) {
|
|
||||||
cacheJumpToMeasurementEvent = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const displaysUIDs = displaySets.map(displaySet => displaySet.displaySetInstanceUID);
|
|
||||||
if (!displaysUIDs?.length) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump to measurement if the measurement exists
|
try {
|
||||||
const { measurement } = cacheJumpToMeasurementEvent;
|
viewport.setViewReference(metadata);
|
||||||
if (measurement && elementRef) {
|
viewport.render();
|
||||||
if (displaysUIDs.includes(measurement?.displaySetInstanceUID)) {
|
} catch (e) {
|
||||||
_jumpToMeasurement(measurement, elementRef, viewportId, servicesManager);
|
console.warn('Unable to apply', metadata, e);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function _jumpToMeasurement(measurement, targetElementRef, viewportId, servicesManager) {
|
cs3DTools.annotation.selection.setAnnotationSelected(measurement.uid);
|
||||||
const { viewportGridService } = servicesManager.services;
|
event?.consume?.();
|
||||||
|
|
||||||
const targetElement = targetElementRef.current;
|
|
||||||
|
|
||||||
// Todo: setCornerstoneMeasurementActive should be handled by the toolGroupManager
|
|
||||||
// to set it properly
|
|
||||||
// setCornerstoneMeasurementActive(measurement);
|
|
||||||
|
|
||||||
viewportGridService.setActiveViewportId(viewportId);
|
|
||||||
|
|
||||||
const enabledElement = getEnabledElement(targetElement);
|
|
||||||
|
|
||||||
if (enabledElement) {
|
|
||||||
// See how the jumpToSlice() of Cornerstone3D deals with imageIdx param.
|
|
||||||
const viewport = enabledElement.viewport as csTypes.IStackViewport | csTypes.IVolumeViewport;
|
|
||||||
|
|
||||||
const { metadata } = measurement;
|
|
||||||
if (!viewport.isReferenceViewable(metadata, WITH_NAVIGATION)) {
|
|
||||||
console.log("Reference isn't viewable, postponing until updated");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
viewport.setViewReference(metadata);
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('Unable to apply', metadata, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
cs3DTools.annotation.selection.setAnnotationSelected(measurement.uid);
|
|
||||||
// Jump to measurement consumed, remove.
|
|
||||||
cacheJumpToMeasurementEvent?.consume?.();
|
|
||||||
cacheJumpToMeasurementEvent = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _rehydrateSynchronizers(viewportId: string, syncGroupService: any) {
|
function _rehydrateSynchronizers(viewportId: string, syncGroupService: any) {
|
||||||
|
|||||||
@ -215,6 +215,7 @@ function commandsModule({
|
|||||||
viewportId,
|
viewportId,
|
||||||
displaySetInstanceUID,
|
displaySetInstanceUID,
|
||||||
referencedImageId,
|
referencedImageId,
|
||||||
|
options,
|
||||||
}) => {
|
}) => {
|
||||||
const presentations = cornerstoneViewportService.getPresentations(viewportId);
|
const presentations = cornerstoneViewportService.getPresentations(viewportId);
|
||||||
const { positionPresentationStore, setPositionPresentation, getPositionPresentationId } =
|
const { positionPresentationStore, setPositionPresentation, getPositionPresentationId } =
|
||||||
@ -226,16 +227,18 @@ function commandsModule({
|
|||||||
([key, value]) => key.includes(displaySetInstanceUID) && value.viewportId === viewportId
|
([key, value]) => key.includes(displaySetInstanceUID) && value.viewportId === viewportId
|
||||||
)?.[0];
|
)?.[0];
|
||||||
|
|
||||||
if (previousReferencedDisplaySetStoreKey) {
|
// Create presentation data with referencedImageId and options if provided
|
||||||
const presentationData = referencedImageId
|
const presentationData = referencedImageId
|
||||||
? {
|
? {
|
||||||
...presentations.positionPresentation,
|
...presentations.positionPresentation,
|
||||||
viewReference: {
|
viewReference: {
|
||||||
referencedImageId,
|
referencedImageId,
|
||||||
},
|
...options,
|
||||||
}
|
},
|
||||||
: presentations.positionPresentation;
|
}
|
||||||
|
: presentations.positionPresentation;
|
||||||
|
|
||||||
|
if (previousReferencedDisplaySetStoreKey) {
|
||||||
setPositionPresentation(previousReferencedDisplaySetStoreKey, presentationData);
|
setPositionPresentation(previousReferencedDisplaySetStoreKey, presentationData);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -243,13 +246,12 @@ function commandsModule({
|
|||||||
// if not found means we have not visited that referencedDisplaySetInstanceUID before
|
// if not found means we have not visited that referencedDisplaySetInstanceUID before
|
||||||
// so we need to grab the positionPresentationId directly from the store,
|
// so we need to grab the positionPresentationId directly from the store,
|
||||||
// Todo: this is really hacky, we should have a better way for this
|
// Todo: this is really hacky, we should have a better way for this
|
||||||
|
|
||||||
const positionPresentationId = getPositionPresentationId({
|
const positionPresentationId = getPositionPresentationId({
|
||||||
displaySetInstanceUIDs: [displaySetInstanceUID],
|
displaySetInstanceUIDs: [displaySetInstanceUID],
|
||||||
viewportId,
|
viewportId,
|
||||||
});
|
});
|
||||||
|
|
||||||
setPositionPresentation(positionPresentationId, presentations.positionPresentation);
|
setPositionPresentation(positionPresentationId, presentationData);
|
||||||
},
|
},
|
||||||
getNearbyToolData({ nearbyToolData, element, canvasCoordinates }) {
|
getNearbyToolData({ nearbyToolData, element, canvasCoordinates }) {
|
||||||
return nearbyToolData ?? cstUtils.getAnnotationNearPoint(element, canvasCoordinates);
|
return nearbyToolData ?? cstUtils.getAnnotationNearPoint(element, canvasCoordinates);
|
||||||
|
|||||||
@ -173,9 +173,6 @@ const cornerstoneExtension: Types.Extensions.Extension = {
|
|||||||
getHangingProtocolModule,
|
getHangingProtocolModule,
|
||||||
getViewportModule({ servicesManager, commandsManager }) {
|
getViewportModule({ servicesManager, commandsManager }) {
|
||||||
const ExtendedOHIFCornerstoneViewport = props => {
|
const ExtendedOHIFCornerstoneViewport = props => {
|
||||||
// const onNewImageHandler = jumpData => {
|
|
||||||
// commandsManager.runCommand('jumpToImage', jumpData);
|
|
||||||
// };
|
|
||||||
const { toolbarService } = servicesManager.services;
|
const { toolbarService } = servicesManager.services;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -192,6 +189,7 @@ const cornerstoneExtension: Types.Extensions.Extension = {
|
|||||||
{
|
{
|
||||||
name: 'cornerstone',
|
name: 'cornerstone',
|
||||||
component: ExtendedOHIFCornerstoneViewport,
|
component: ExtendedOHIFCornerstoneViewport,
|
||||||
|
isReferenceViewable: props => utils.isReferenceViewable({ ...props, servicesManager }),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|||||||
@ -92,6 +92,7 @@ export default async function init({
|
|||||||
hangingProtocolService,
|
hangingProtocolService,
|
||||||
viewportGridService,
|
viewportGridService,
|
||||||
segmentationService,
|
segmentationService,
|
||||||
|
measurementService,
|
||||||
} = servicesManager.services;
|
} = servicesManager.services;
|
||||||
|
|
||||||
window.services = servicesManager.services;
|
window.services = servicesManager.services;
|
||||||
@ -177,6 +178,17 @@ export default async function init({
|
|||||||
initCineService(servicesManager);
|
initCineService(servicesManager);
|
||||||
initStudyPrefetcherService(servicesManager);
|
initStudyPrefetcherService(servicesManager);
|
||||||
|
|
||||||
|
[
|
||||||
|
measurementService.EVENTS.JUMP_TO_MEASUREMENT_LAYOUT,
|
||||||
|
measurementService.EVENTS.JUMP_TO_MEASUREMENT_VIEWPORT,
|
||||||
|
].forEach(event => {
|
||||||
|
measurementService.subscribe(event, evt => {
|
||||||
|
const { measurement } = evt;
|
||||||
|
const { uid: annotationUID } = measurement;
|
||||||
|
cornerstoneTools.annotation.selection.setAnnotationSelected(annotationUID, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
segmentationService.subscribeDebounced(
|
segmentationService.subscribeDebounced(
|
||||||
segmentationService.EVENTS.SEGMENTATION_DATA_MODIFIED,
|
segmentationService.EVENTS.SEGMENTATION_DATA_MODIFIED,
|
||||||
async ({ segmentationId }) => {
|
async ({ segmentationId }) => {
|
||||||
|
|||||||
@ -38,7 +38,7 @@ const EVENTS = {
|
|||||||
VIEWPORT_VOLUMES_CHANGED: 'event::cornerstoneViewportService:viewportVolumesChanged',
|
VIEWPORT_VOLUMES_CHANGED: 'event::cornerstoneViewportService:viewportVolumesChanged',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WITH_NAVIGATION = { withNavigation: true, withOrientation: true };
|
export const WITH_NAVIGATION = { withNavigation: true, withOrientation: false };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles cornerstone viewport logic including enabling, disabling, and
|
* Handles cornerstone viewport logic including enabling, disabling, and
|
||||||
@ -851,14 +851,18 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
|||||||
viewport.setProperties(properties, volumeId);
|
viewport.setProperties(properties, volumeId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
viewport.render();
|
||||||
|
|
||||||
this.setPresentations(viewport.id, presentations, viewportInfo);
|
this.setPresentations(viewport.id, presentations, viewportInfo);
|
||||||
|
|
||||||
const imageIndex = this._getInitialImageIndexForViewport(viewportInfo);
|
if (!presentations.positionPresentation) {
|
||||||
|
const imageIndex = this._getInitialImageIndexForViewport(viewportInfo);
|
||||||
|
|
||||||
if (imageIndex !== undefined) {
|
if (imageIndex !== undefined) {
|
||||||
csUtils.jumpToSlice(viewport.element, {
|
csUtils.jumpToSlice(viewport.element, {
|
||||||
imageIndex,
|
imageIndex,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewport.render();
|
viewport.render();
|
||||||
@ -1177,6 +1181,20 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the display sets for a given viewport
|
||||||
|
* @param viewportId - The ID of the viewport to get display sets for
|
||||||
|
* @returns Array of display sets for the viewport
|
||||||
|
*/
|
||||||
|
public getViewportDisplaySets(viewportId: string): OhifTypes.DisplaySet[] {
|
||||||
|
const { displaySetService } = this.servicesManager.services;
|
||||||
|
const displaySetInstanceUIDs = this.viewportsDisplaySets.get(viewportId) || [];
|
||||||
|
|
||||||
|
return displaySetInstanceUIDs
|
||||||
|
.map(uid => displaySetService.getDisplaySetByUID(uid))
|
||||||
|
.filter(Boolean);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CornerstoneViewportService;
|
export default CornerstoneViewportService;
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
import { handleSegmentChange } from './segmentUtils';
|
import { handleSegmentChange } from './segmentUtils';
|
||||||
|
import { isReferenceViewable } from './isReferenceViewable';
|
||||||
|
|
||||||
const utils = {
|
const utils = {
|
||||||
handleSegmentChange,
|
handleSegmentChange,
|
||||||
|
isReferenceViewable,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default utils;
|
export default utils;
|
||||||
|
|||||||
98
extensions/cornerstone/src/utils/isReferenceViewable.ts
Normal file
98
extensions/cornerstone/src/utils/isReferenceViewable.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import { vec3 } from 'gl-matrix';
|
||||||
|
import { Enums } from '@cornerstonejs/core';
|
||||||
|
|
||||||
|
import OrientationAxis = Enums.OrientationAxis;
|
||||||
|
|
||||||
|
export const isReferenceViewable = ({
|
||||||
|
viewportId,
|
||||||
|
reference,
|
||||||
|
viewportOptions,
|
||||||
|
servicesManager,
|
||||||
|
}) => {
|
||||||
|
const { cornerstoneViewportService, displaySetService } = servicesManager.services;
|
||||||
|
|
||||||
|
if (!viewportOptions) {
|
||||||
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||||
|
|
||||||
|
// we can make a customization for this to allow
|
||||||
|
const isViewable = viewport.isReferenceViewable(reference, {
|
||||||
|
withNavigation: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return isViewable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (viewportOptions.viewportType === 'stack') {
|
||||||
|
// we only need the viewport to include the referenced imageId
|
||||||
|
const displaySet = displaySetService.getDisplaySetByUID(reference.displaySetInstanceUID);
|
||||||
|
const imageIds = displaySet.instances.map(instance => instance.imageId);
|
||||||
|
return imageIds.includes(reference.referencedImageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for the volume viewports, we need to check orientation
|
||||||
|
const { orientation } = viewportOptions;
|
||||||
|
|
||||||
|
// Todo: handle hanging protocols that have acquisition orientation
|
||||||
|
const closestOrientation = getClosestOrientationFromIOP(
|
||||||
|
displaySetService,
|
||||||
|
reference.displaySetInstanceUID
|
||||||
|
);
|
||||||
|
|
||||||
|
return closestOrientation === orientation;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the plane (orientation) to which the ImageOrientationPatient is most closely aligned
|
||||||
|
*
|
||||||
|
* @param displaySetService
|
||||||
|
* @param displaySetInstanceUID
|
||||||
|
* @returns orientation
|
||||||
|
*/
|
||||||
|
export default function getClosestOrientationFromIOP(
|
||||||
|
displaySetService,
|
||||||
|
displaySetInstanceUID
|
||||||
|
): OrientationAxis {
|
||||||
|
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||||
|
const imageOrientationPatient = displaySet.instances[0].ImageOrientationPatient as Array<number>;
|
||||||
|
// ImageOrientationPatient must be an array of length 6.
|
||||||
|
if (imageOrientationPatient?.length !== 6) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take cross product to get vector coming "out" of image plane
|
||||||
|
const rowCosineVec = vec3.fromValues(
|
||||||
|
imageOrientationPatient[0],
|
||||||
|
imageOrientationPatient[1],
|
||||||
|
imageOrientationPatient[2]
|
||||||
|
);
|
||||||
|
const colCosineVec = vec3.fromValues(
|
||||||
|
imageOrientationPatient[3],
|
||||||
|
imageOrientationPatient[4],
|
||||||
|
imageOrientationPatient[5]
|
||||||
|
);
|
||||||
|
const scanAxisNormal = vec3.cross(vec3.create(), rowCosineVec, colCosineVec);
|
||||||
|
|
||||||
|
// Define the reference vectors for axial, coronal, and sagittal planes
|
||||||
|
const unitVectors = {
|
||||||
|
[OrientationAxis.AXIAL]: vec3.fromValues(0, 0, 1),
|
||||||
|
[OrientationAxis.CORONAL]: vec3.fromValues(0, 1, 0),
|
||||||
|
[OrientationAxis.SAGITTAL]: vec3.fromValues(1, 0, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compute dot products for each reference plane
|
||||||
|
// Because all vectors are normalized, dot product is bounded between -1 and 1
|
||||||
|
let maxDot = 0;
|
||||||
|
let maxOrientation: string = '';
|
||||||
|
for (const [k, v] of Object.entries(unitVectors)) {
|
||||||
|
// Absolute value of dot product because we only care about alignment with the axis
|
||||||
|
// For example, dot product of -1 for a given axis means perfect alignment
|
||||||
|
// but the image is pointing in the "opposite" direction
|
||||||
|
const res = Math.abs(vec3.dot(scanAxisNormal, v));
|
||||||
|
if (res > maxDot) {
|
||||||
|
maxDot = res;
|
||||||
|
maxOrientation = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxOrientation as OrientationAxis;
|
||||||
|
}
|
||||||
@ -82,7 +82,7 @@ function ViewerLayout({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { entry, content: entry.component };
|
return { entry };
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -107,6 +107,7 @@ function ViewerLayout({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
component: entry.component,
|
component: entry.component,
|
||||||
|
isReferenceViewable: entry.isReferenceViewable,
|
||||||
displaySetsToDisplay: viewportComponent.displaySetsToDisplay,
|
displaySetsToDisplay: viewportComponent.displaySetsToDisplay,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,6 +14,7 @@ const getViewportModule = ({
|
|||||||
{
|
{
|
||||||
name: 'chartViewport',
|
name: 'chartViewport',
|
||||||
component: LineChartViewport,
|
component: LineChartViewport,
|
||||||
|
isReferenceViewable: () => false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
@ -32,8 +32,8 @@
|
|||||||
"start": "yarn run dev"
|
"start": "yarn run dev"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@cornerstonejs/core": "^3.7.16",
|
"@cornerstonejs/core": "^3.7.17",
|
||||||
"@cornerstonejs/tools": "^3.7.16",
|
"@cornerstonejs/tools": "^3.7.17",
|
||||||
"@ohif/core": "3.10.0-beta.140",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.140",
|
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.140",
|
||||||
"@ohif/extension-default": "3.10.0-beta.140",
|
"@ohif/extension-default": "3.10.0-beta.140",
|
||||||
|
|||||||
@ -268,12 +268,20 @@ function TrackedMeasurementsContextProvider(
|
|||||||
displaySet.SOPClassHandlerId === SR_SOPCLASSHANDLERID &&
|
displaySet.SOPClassHandlerId === SR_SOPCLASSHANDLERID &&
|
||||||
displaySet.isRehydratable === true
|
displaySet.isRehydratable === true
|
||||||
) {
|
) {
|
||||||
console.log('sending event...', trackedMeasurements);
|
const params = {
|
||||||
sendTrackedMeasurementsEvent('PROMPT_HYDRATE_SR', {
|
|
||||||
displaySetInstanceUID: displaySet.displaySetInstanceUID,
|
displaySetInstanceUID: displaySet.displaySetInstanceUID,
|
||||||
SeriesInstanceUID: displaySet.SeriesInstanceUID,
|
SeriesInstanceUID: displaySet.SeriesInstanceUID,
|
||||||
viewportId: activeViewportId,
|
viewportId: activeViewportId,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// Check if we should bypass the confirmation prompt
|
||||||
|
const disableConfirmationPrompts = appConfig?.disableConfirmationPrompts;
|
||||||
|
|
||||||
|
if (disableConfirmationPrompts) {
|
||||||
|
sendTrackedMeasurementsEvent('HYDRATE_SR', params);
|
||||||
|
} else {
|
||||||
|
sendTrackedMeasurementsEvent('PROMPT_HYDRATE_SR', params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -284,6 +292,7 @@ function TrackedMeasurementsContextProvider(
|
|||||||
sendTrackedMeasurementsEvent,
|
sendTrackedMeasurementsEvent,
|
||||||
servicesManager.services,
|
servicesManager.services,
|
||||||
viewports,
|
viewports,
|
||||||
|
appConfig,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -57,7 +57,6 @@ const machineConfiguration = {
|
|||||||
actions: ['setPreviousState'],
|
actions: ['setPreviousState'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
// Unused? We may only do PROMPT_HYDRATE_SR now?
|
|
||||||
SET_TRACKED_SERIES: [
|
SET_TRACKED_SERIES: [
|
||||||
{
|
{
|
||||||
target: 'tracking',
|
target: 'tracking',
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { utils } from '@ohif/extension-cornerstone';
|
||||||
|
|
||||||
const Component = React.lazy(() => {
|
const Component = React.lazy(() => {
|
||||||
return import(/* webpackPrefetch: true */ './viewports/TrackedCornerstoneViewport');
|
return import(/* webpackPrefetch: true */ './viewports/TrackedCornerstoneViewport');
|
||||||
@ -28,6 +29,7 @@ function getViewportModule({ servicesManager, commandsManager, extensionManager
|
|||||||
{
|
{
|
||||||
name: 'cornerstone-tracked',
|
name: 'cornerstone-tracked',
|
||||||
component: ExtendedOHIFCornerstoneTrackingViewport,
|
component: ExtendedOHIFCornerstoneTrackingViewport,
|
||||||
|
isReferenceViewable: props => utils.isReferenceViewable({ ...props, servicesManager }),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,7 +54,7 @@
|
|||||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||||
"@cornerstonejs/dicom-image-loader": "^3.7.16",
|
"@cornerstonejs/dicom-image-loader": "^3.7.17",
|
||||||
"@emotion/serialize": "^1.1.3",
|
"@emotion/serialize": "^1.1.3",
|
||||||
"@ohif/core": "3.10.0-beta.140",
|
"@ohif/core": "3.10.0-beta.140",
|
||||||
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
"@ohif/extension-cornerstone": "3.10.0-beta.140",
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
import React, { useEffect, useCallback, useRef } from 'react';
|
import React, { useEffect, useCallback, useRef, useMemo } from 'react';
|
||||||
import { useResizeDetector } from 'react-resize-detector';
|
import { useResizeDetector } from 'react-resize-detector';
|
||||||
import { Types, MeasurementService } from '@ohif/core';
|
import { Types, MeasurementService } from '@ohif/core';
|
||||||
import { ViewportGrid, ViewportPane } from '@ohif/ui-next';
|
import { ViewportGrid, ViewportPane } from '@ohif/ui-next';
|
||||||
import { useViewportGrid } from '@ohif/ui-next';
|
import { useViewportGrid } from '@ohif/ui-next';
|
||||||
import EmptyViewport from './EmptyViewport';
|
import EmptyViewport from './EmptyViewport';
|
||||||
import classNames from 'classnames';
|
|
||||||
import { useAppConfig } from '@state';
|
import { useAppConfig } from '@state';
|
||||||
|
|
||||||
function ViewerViewportGrid(props: withAppTypes) {
|
function ViewerViewportGrid(props: withAppTypes) {
|
||||||
const { servicesManager, viewportComponents = [], dataSource } = props;
|
const { servicesManager, viewportComponents = [], dataSource, commandsManager } = props;
|
||||||
const [viewportGrid, viewportGridService] = useViewportGrid();
|
const [viewportGrid, viewportGridService] = useViewportGrid();
|
||||||
const [appConfig] = useAppConfig();
|
const [appConfig] = useAppConfig();
|
||||||
|
|
||||||
@ -167,17 +166,51 @@ function ViewerViewportGrid(props: withAppTypes) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { unsubscribe } = measurementService.subscribe(
|
const { unsubscribe } = measurementService.subscribe(
|
||||||
MeasurementService.EVENTS.JUMP_TO_MEASUREMENT_LAYOUT,
|
MeasurementService.EVENTS.JUMP_TO_MEASUREMENT_LAYOUT,
|
||||||
({ viewportId, measurement, isConsumed }) => {
|
event => {
|
||||||
|
const { viewportId, measurement, isConsumed } = event;
|
||||||
if (isConsumed) {
|
if (isConsumed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// This occurs when no viewport has elected to consume the event
|
|
||||||
// so we need to change layouts into a layout which can consume
|
|
||||||
// the event.
|
|
||||||
const { displaySetInstanceUID: referencedDisplaySetInstanceUID } = measurement;
|
|
||||||
|
|
||||||
|
const { displaySetInstanceUID: referencedDisplaySetInstanceUID } = measurement;
|
||||||
|
const { viewports } = viewportGridService.getState();
|
||||||
|
|
||||||
|
// Check if any viewport can display this measurement
|
||||||
|
let canAnyViewportDisplayMeasurement = false;
|
||||||
|
|
||||||
|
viewports.forEach((viewport, id) => {
|
||||||
|
const displaySetInstanceUIDs = viewport.displaySetInstanceUIDs || [];
|
||||||
|
const viewportHasDisplaySet = displaySetInstanceUIDs.includes(
|
||||||
|
referencedDisplaySetInstanceUID
|
||||||
|
);
|
||||||
|
|
||||||
|
// Extract metadata and prepare reference
|
||||||
|
const { FrameOfReferenceUID, ...metadataRest } = measurement.metadata;
|
||||||
|
const reference = {
|
||||||
|
...(viewportHasDisplaySet ? measurement.metadata : metadataRest),
|
||||||
|
displaySetInstanceUID: referencedDisplaySetInstanceUID,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if viewport can display the reference
|
||||||
|
if (
|
||||||
|
viewport.isReferenceViewable?.({
|
||||||
|
viewportId: id,
|
||||||
|
reference,
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
canAnyViewportDisplayMeasurement = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (canAnyViewportDisplayMeasurement) {
|
||||||
|
// Let the viewports handle the jump
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to change layouts since no viewport consumed the event
|
||||||
const updatedViewports = _getUpdatedViewports(viewportId, referencedDisplaySetInstanceUID);
|
const updatedViewports = _getUpdatedViewports(viewportId, referencedDisplaySetInstanceUID);
|
||||||
if (!updatedViewports[0]) {
|
|
||||||
|
if (!updatedViewports?.[0]) {
|
||||||
console.warn(
|
console.warn(
|
||||||
'ViewportGrid::Unable to navigate to viewport containing',
|
'ViewportGrid::Unable to navigate to viewport containing',
|
||||||
referencedDisplaySetInstanceUID
|
referencedDisplaySetInstanceUID
|
||||||
@ -185,24 +218,35 @@ function ViewerViewportGrid(props: withAppTypes) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arbitrarily assign the viewport to element 0
|
// Find the viewport that can display the measurement
|
||||||
// TODO - this should perform a search to find the most suitable viewport.
|
const viewport = updatedViewports.find(viewport => {
|
||||||
updatedViewports[0] = { ...updatedViewports[0] };
|
const gridViewport = viewportGridService.getViewportState(viewport.viewportId);
|
||||||
const [viewport] = updatedViewports;
|
return gridViewport.isReferenceViewable?.({
|
||||||
|
viewportId: viewport.viewportId,
|
||||||
|
reference: {
|
||||||
|
...measurement.metadata,
|
||||||
|
displaySetInstanceUID: referencedDisplaySetInstanceUID,
|
||||||
|
},
|
||||||
|
viewportOptions: gridViewport.viewportOptions || {},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Copy the viewport options to prevent modifying the internal data
|
if (!viewport) {
|
||||||
viewport.viewportOptions = {
|
console.warn('No suitable viewport found for displaying measurement');
|
||||||
...viewport.viewportOptions,
|
return;
|
||||||
orientation: 'acquisition',
|
}
|
||||||
// The preferred way to jump to the measurement view is to set the
|
|
||||||
// view reference, as this can hold information such as the orientation
|
|
||||||
// or zoom level required to display an annotation. The metadata attribute
|
|
||||||
// of the measurement is a viewReference, so use it to show the measurement.
|
|
||||||
// Longer term this should clear the view reference data
|
|
||||||
viewReference: measurement.metadata,
|
|
||||||
viewportType: measurement.metadata.volumeId ? 'volume' : null,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// Update stored position presentation
|
||||||
|
commandsManager.run('updateStoredPositionPresentation', {
|
||||||
|
viewportId: viewport.viewportId,
|
||||||
|
displaySetInstanceUID: referencedDisplaySetInstanceUID,
|
||||||
|
referencedImageId: measurement.referencedImageId,
|
||||||
|
options: {
|
||||||
|
...measurement.metadata,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
event.consume();
|
||||||
viewportGridService.setDisplaySetsForViewports(updatedViewports);
|
viewportGridService.setDisplaySetsForViewports(updatedViewports);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -210,7 +254,7 @@ function ViewerViewportGrid(props: withAppTypes) {
|
|||||||
return () => {
|
return () => {
|
||||||
unsubscribe();
|
unsubscribe();
|
||||||
};
|
};
|
||||||
}, [viewports]);
|
}, [viewports, _getUpdatedViewports]);
|
||||||
|
|
||||||
const onDropHandler = (viewportId, { displaySetInstanceUID }) => {
|
const onDropHandler = (viewportId, { displaySetInstanceUID }) => {
|
||||||
const customOnDropHandler = customizationService.getCustomization('customOnDropHandler');
|
const customOnDropHandler = customizationService.getCustomization('customOnDropHandler');
|
||||||
@ -229,6 +273,9 @@ function ViewerViewportGrid(props: withAppTypes) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Store previous isReferenceViewable values to avoid infinite loops
|
||||||
|
const prevReferenceViewableMap = useRef(new Map());
|
||||||
|
|
||||||
const getViewportPanes = useCallback(() => {
|
const getViewportPanes = useCallback(() => {
|
||||||
const viewportPanes = [];
|
const viewportPanes = [];
|
||||||
|
|
||||||
@ -260,12 +307,27 @@ function ViewerViewportGrid(props: withAppTypes) {
|
|||||||
return !displaySet?.unsupported;
|
return !displaySet?.unsupported;
|
||||||
});
|
});
|
||||||
|
|
||||||
const ViewportComponent = _getViewportComponent(
|
const { component: ViewportComponent, isReferenceViewable } = _getViewportComponent(
|
||||||
displaySets,
|
displaySets,
|
||||||
viewportComponents,
|
viewportComponents,
|
||||||
uiNotificationService
|
uiNotificationService
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Only update isReferenceViewable if it's changed to avoid render loops
|
||||||
|
// We need to handle both function and non-function values
|
||||||
|
if (viewportId) {
|
||||||
|
const prevValue = prevReferenceViewableMap.current.get(viewportId);
|
||||||
|
const isFunction = typeof isReferenceViewable === 'function';
|
||||||
|
const isSameFunction = isFunction && typeof prevValue === 'function';
|
||||||
|
|
||||||
|
// For non-functions, compare directly. For functions, we treat them as always different
|
||||||
|
// (this is conservative but safe)
|
||||||
|
if (!isSameFunction && prevValue !== isReferenceViewable) {
|
||||||
|
viewportGridService.setIsReferenceViewable(viewportId, isReferenceViewable);
|
||||||
|
prevReferenceViewableMap.current.set(viewportId, isReferenceViewable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// look inside displaySets to see if they need reRendering
|
// look inside displaySets to see if they need reRendering
|
||||||
const displaySetsNeedsRerendering = displaySets.some(displaySet => {
|
const displaySetsNeedsRerendering = displaySets.some(displaySet => {
|
||||||
return displaySet.needsRerendering;
|
return displaySet.needsRerendering;
|
||||||
@ -381,7 +443,7 @@ function ViewerViewportGrid(props: withAppTypes) {
|
|||||||
|
|
||||||
function _getViewportComponent(displaySets, viewportComponents, uiNotificationService) {
|
function _getViewportComponent(displaySets, viewportComponents, uiNotificationService) {
|
||||||
if (!displaySets || !displaySets.length) {
|
if (!displaySets || !displaySets.length) {
|
||||||
return EmptyViewport;
|
return { component: EmptyViewport, isReferenceViewable: () => false };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo: Do we have a viewport that has two different SOPClassHandlerIds?
|
// Todo: Do we have a viewport that has two different SOPClassHandlerIds?
|
||||||
@ -395,8 +457,8 @@ function _getViewportComponent(displaySets, viewportComponents, uiNotificationSe
|
|||||||
throw new Error('displaySetsToDisplay is null');
|
throw new Error('displaySetsToDisplay is null');
|
||||||
}
|
}
|
||||||
if (viewportComponents[i].displaySetsToDisplay.includes(SOPClassHandlerId)) {
|
if (viewportComponents[i].displaySetsToDisplay.includes(SOPClassHandlerId)) {
|
||||||
const { component } = viewportComponents[i];
|
const { component, isReferenceViewable } = viewportComponents[i];
|
||||||
return component;
|
return { component, isReferenceViewable };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,7 +469,7 @@ function _getViewportComponent(displaySets, viewportComponents, uiNotificationSe
|
|||||||
type: 'error',
|
type: 'error',
|
||||||
});
|
});
|
||||||
|
|
||||||
return EmptyViewport;
|
return { component: EmptyViewport, isReferenceViewable: () => false };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ViewerViewportGrid;
|
export default ViewerViewportGrid;
|
||||||
|
|||||||
@ -37,7 +37,7 @@
|
|||||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||||
"@cornerstonejs/dicom-image-loader": "^3.7.16",
|
"@cornerstonejs/dicom-image-loader": "^3.7.17",
|
||||||
"@ohif/ui": "3.10.0-beta.140",
|
"@ohif/ui": "3.10.0-beta.140",
|
||||||
"cornerstone-math": "0.1.9",
|
"cornerstone-math": "0.1.9",
|
||||||
"dicom-parser": "^1.8.21"
|
"dicom-parser": "^1.8.21"
|
||||||
|
|||||||
@ -670,8 +670,11 @@ class MeasurementService extends PubSubService {
|
|||||||
measurement,
|
measurement,
|
||||||
});
|
});
|
||||||
|
|
||||||
this._broadcastEvent(EVENTS.JUMP_TO_MEASUREMENT_VIEWPORT, consumableEvent);
|
// Important: we should broadcast the layout event first, since
|
||||||
|
// in the layout there might be a viewport that we can match and choose
|
||||||
|
// and jump in it before we decide on changing the orientation of different viewports
|
||||||
this._broadcastEvent(EVENTS.JUMP_TO_MEASUREMENT_LAYOUT, consumableEvent);
|
this._broadcastEvent(EVENTS.JUMP_TO_MEASUREMENT_LAYOUT, consumableEvent);
|
||||||
|
this._broadcastEvent(EVENTS.JUMP_TO_MEASUREMENT_VIEWPORT, consumableEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getSourceUID(name, version) {
|
_getSourceUID(name, version) {
|
||||||
|
|||||||
@ -38,6 +38,10 @@ class ViewportGridService extends PubSubService {
|
|||||||
this.presentationIdProviders.set(id, provider);
|
this.presentationIdProviders.set(id, provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setIsReferenceViewable(viewportId: string, isReferenceViewable: boolean): void {
|
||||||
|
this.serviceImplementation._setIsReferenceViewable(viewportId, isReferenceViewable);
|
||||||
|
}
|
||||||
|
|
||||||
public getPresentationId(id: string, viewportId: string): string | null {
|
public getPresentationId(id: string, viewportId: string): string | null {
|
||||||
const state = this.getState();
|
const state = this.getState();
|
||||||
const viewport = state.viewports.get(viewportId);
|
const viewport = state.viewports.get(viewportId);
|
||||||
@ -93,7 +97,12 @@ class ViewportGridService extends PubSubService {
|
|||||||
set: setImplementation,
|
set: setImplementation,
|
||||||
getNumViewportPanes: getNumViewportPanesImplementation,
|
getNumViewportPanes: getNumViewportPanesImplementation,
|
||||||
setViewportIsReady: setViewportIsReadyImplementation,
|
setViewportIsReady: setViewportIsReadyImplementation,
|
||||||
|
setIsReferenceViewable: setIsReferenceViewableImplementation,
|
||||||
|
getViewportState: getViewportStateImplementation,
|
||||||
}): void {
|
}): void {
|
||||||
|
if (getViewportStateImplementation) {
|
||||||
|
this.serviceImplementation._getViewportState = getViewportStateImplementation;
|
||||||
|
}
|
||||||
if (getStateImplementation) {
|
if (getStateImplementation) {
|
||||||
this.serviceImplementation._getState = getStateImplementation;
|
this.serviceImplementation._getState = getStateImplementation;
|
||||||
}
|
}
|
||||||
@ -123,6 +132,9 @@ class ViewportGridService extends PubSubService {
|
|||||||
if (setViewportIsReadyImplementation) {
|
if (setViewportIsReadyImplementation) {
|
||||||
this.serviceImplementation._setViewportIsReady = setViewportIsReadyImplementation;
|
this.serviceImplementation._setViewportIsReady = setViewportIsReadyImplementation;
|
||||||
}
|
}
|
||||||
|
if (setIsReferenceViewableImplementation) {
|
||||||
|
this.serviceImplementation._setIsReferenceViewable = setIsReferenceViewableImplementation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public publishViewportsReady() {
|
public publishViewportsReady() {
|
||||||
@ -148,8 +160,7 @@ class ViewportGridService extends PubSubService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getViewportState(viewportId: string) {
|
public getViewportState(viewportId: string) {
|
||||||
const state = this.getState();
|
return this.serviceImplementation._getViewportState(viewportId);
|
||||||
return state.viewports.get(viewportId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public setViewportIsReady(viewportId, callback) {
|
public setViewportIsReady(viewportId, callback) {
|
||||||
|
|||||||
@ -45,6 +45,10 @@ export interface ViewportGridState {
|
|||||||
activeViewportId: string | null;
|
activeViewportId: string | null;
|
||||||
layout: Layout;
|
layout: Layout;
|
||||||
isHangingProtocolLayout: boolean;
|
isHangingProtocolLayout: boolean;
|
||||||
|
isReferenceViewable: (props: {
|
||||||
|
viewportId: string;
|
||||||
|
reference: Record<string, unknown>;
|
||||||
|
}) => boolean;
|
||||||
viewports: GridViewports;
|
viewports: GridViewports;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
54
platform/core/src/utils/getClosestOrientationFromIOP.ts
Normal file
54
platform/core/src/utils/getClosestOrientationFromIOP.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { vec3 } from 'gl-matrix';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the plane (orientation) to which the ImageOrientationPatient is most closely aligned
|
||||||
|
*
|
||||||
|
* @param displaySetService
|
||||||
|
* @param displaySetInstanceUID
|
||||||
|
* @returns orientation
|
||||||
|
*/
|
||||||
|
export default function getClosestOrientationFromIOP(displaySetService, displaySetInstanceUID) {
|
||||||
|
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||||
|
const imageOrientationPatient = displaySet.instances[0].ImageOrientationPatient as Array<number>;
|
||||||
|
// ImageOrientationPatient must be an array of length 6.
|
||||||
|
if (imageOrientationPatient?.length !== 6) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take cross product to get vector coming "out" of image plane
|
||||||
|
const rowCosineVec = vec3.fromValues(
|
||||||
|
imageOrientationPatient[0],
|
||||||
|
imageOrientationPatient[1],
|
||||||
|
imageOrientationPatient[2]
|
||||||
|
);
|
||||||
|
const colCosineVec = vec3.fromValues(
|
||||||
|
imageOrientationPatient[3],
|
||||||
|
imageOrientationPatient[4],
|
||||||
|
imageOrientationPatient[5]
|
||||||
|
);
|
||||||
|
const scanAxisNormal = vec3.cross(vec3.create(), rowCosineVec, colCosineVec);
|
||||||
|
|
||||||
|
// Define the reference vectors for axial, coronal, and sagittal planes
|
||||||
|
const unitVectors = {
|
||||||
|
axial: vec3.fromValues(0, 0, 1),
|
||||||
|
coronal: vec3.fromValues(0, 1, 0),
|
||||||
|
sagittal: vec3.fromValues(1, 0, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compute dot products for each reference plane
|
||||||
|
// Because all vectors are normalized, dot product is bounded between -1 and 1
|
||||||
|
let maxDot = 0;
|
||||||
|
let maxOrientation: string = '';
|
||||||
|
for (const [k, v] of Object.entries(unitVectors)) {
|
||||||
|
// Absolute value of dot product because we only care about alignment with the axis
|
||||||
|
// For example, dot product of -1 for a given axis means perfect alignment
|
||||||
|
// but the image is pointing in the "opposite" direction
|
||||||
|
const res = Math.abs(vec3.dot(scanAxisNormal, v));
|
||||||
|
if (res > maxDot) {
|
||||||
|
maxDot = res;
|
||||||
|
maxOrientation = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxOrientation;
|
||||||
|
}
|
||||||
@ -1,53 +0,0 @@
|
|||||||
import * as utils from './index';
|
|
||||||
|
|
||||||
describe('Top level exports', () => {
|
|
||||||
test('should export the modules ', () => {
|
|
||||||
const expectedExports = [
|
|
||||||
'guid',
|
|
||||||
'ObjectPath',
|
|
||||||
'absoluteUrl',
|
|
||||||
'seriesSortCriteria',
|
|
||||||
'sortBy',
|
|
||||||
'sortStudy',
|
|
||||||
'sortBySeriesDate',
|
|
||||||
'sortStudyInstances',
|
|
||||||
'sortStudySeries',
|
|
||||||
'sortingCriteria',
|
|
||||||
'splitComma',
|
|
||||||
'getSplitParam',
|
|
||||||
'isLowPriorityModality',
|
|
||||||
'writeScript',
|
|
||||||
'debounce',
|
|
||||||
'downloadCSVReport',
|
|
||||||
'imageIdToURI',
|
|
||||||
'roundNumber',
|
|
||||||
'b64toBlob',
|
|
||||||
'sopClassDictionary',
|
|
||||||
'createStudyBrowserTabs',
|
|
||||||
'formatDate',
|
|
||||||
'formatTime',
|
|
||||||
'formatPN',
|
|
||||||
'generateAcceptHeader',
|
|
||||||
'isEqualWithin',
|
|
||||||
//'loadAndCacheDerivedDisplaySets',
|
|
||||||
'isDisplaySetReconstructable',
|
|
||||||
'isImage',
|
|
||||||
'urlUtil',
|
|
||||||
'makeDeferred',
|
|
||||||
'makeCancelable',
|
|
||||||
'hotkeys',
|
|
||||||
'Queue',
|
|
||||||
'isDicomUid',
|
|
||||||
'resolveObjectPath',
|
|
||||||
'hierarchicalListUtils',
|
|
||||||
'progressTrackingUtils',
|
|
||||||
'uuidv4',
|
|
||||||
'addAccessors',
|
|
||||||
'MeasurementFilters',
|
|
||||||
].sort();
|
|
||||||
|
|
||||||
const exports = Object.keys(utils.default).sort();
|
|
||||||
|
|
||||||
expect(exports).toEqual(expectedExports);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -40,7 +40,7 @@ import { splitComma, getSplitParam } from './splitComma';
|
|||||||
import { createStudyBrowserTabs } from './createStudyBrowserTabs';
|
import { createStudyBrowserTabs } from './createStudyBrowserTabs';
|
||||||
import { sopClassDictionary } from './sopClassDictionary';
|
import { sopClassDictionary } from './sopClassDictionary';
|
||||||
import * as MeasurementFilters from './measurementFilters';
|
import * as MeasurementFilters from './measurementFilters';
|
||||||
|
import getClosestOrientationFromIOP from './getClosestOrientationFromIOP';
|
||||||
// Commented out unused functionality.
|
// Commented out unused functionality.
|
||||||
// Need to implement new mechanism for derived displaySets using the displaySetManager.
|
// Need to implement new mechanism for derived displaySets using the displaySetManager.
|
||||||
|
|
||||||
@ -86,6 +86,7 @@ const utils = {
|
|||||||
generateAcceptHeader,
|
generateAcceptHeader,
|
||||||
createStudyBrowserTabs,
|
createStudyBrowserTabs,
|
||||||
MeasurementFilters,
|
MeasurementFilters,
|
||||||
|
getClosestOrientationFromIOP,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -120,6 +121,7 @@ export {
|
|||||||
generateAcceptHeader,
|
generateAcceptHeader,
|
||||||
createStudyBrowserTabs,
|
createStudyBrowserTabs,
|
||||||
MeasurementFilters,
|
MeasurementFilters,
|
||||||
|
getClosestOrientationFromIOP,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default utils;
|
export default utils;
|
||||||
|
|||||||
@ -141,6 +141,19 @@ interface ViewportGridProviderProps {
|
|||||||
export function ViewportGridProvider({ children, service }: ViewportGridProviderProps) {
|
export function ViewportGridProvider({ children, service }: ViewportGridProviderProps) {
|
||||||
const viewportGridReducer = (state: AppTypes.ViewportGrid.State, action) => {
|
const viewportGridReducer = (state: AppTypes.ViewportGrid.State, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case 'SET_IS_REFERENCE_VIEWABLE': {
|
||||||
|
const { viewportId, isReferenceViewable } = action.payload;
|
||||||
|
const viewports = new Map(state.viewports);
|
||||||
|
const viewport = viewports.get(viewportId);
|
||||||
|
if (!viewport) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
viewports.set(viewportId, {
|
||||||
|
...viewport,
|
||||||
|
isReferenceViewable,
|
||||||
|
});
|
||||||
|
return { ...state, viewports };
|
||||||
|
}
|
||||||
case 'SET_ACTIVE_VIEWPORT_ID': {
|
case 'SET_ACTIVE_VIEWPORT_ID': {
|
||||||
return { ...state, ...{ activeViewportId: action.payload } };
|
return { ...state, ...{ activeViewportId: action.payload } };
|
||||||
}
|
}
|
||||||
@ -378,6 +391,13 @@ export function ViewportGridProvider({ children, service }: ViewportGridProvider
|
|||||||
[dispatch]
|
[dispatch]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const setIsReferenceViewable = useCallback(
|
||||||
|
(viewportId, isReferenceViewable) => {
|
||||||
|
dispatch({ type: 'SET_IS_REFERENCE_VIEWABLE', payload: { viewportId, isReferenceViewable } });
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
const setDisplaySetsForViewports = useCallback(
|
const setDisplaySetsForViewports = useCallback(
|
||||||
viewports =>
|
viewports =>
|
||||||
dispatch({
|
dispatch({
|
||||||
@ -449,6 +469,14 @@ export function ViewportGridProvider({ children, service }: ViewportGridProvider
|
|||||||
[dispatch]
|
[dispatch]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getViewportState = useCallback(
|
||||||
|
viewportId => {
|
||||||
|
const { viewports } = viewportGridState;
|
||||||
|
return viewports.get(viewportId);
|
||||||
|
},
|
||||||
|
[viewportGridState]
|
||||||
|
);
|
||||||
|
|
||||||
const getNumViewportPanes = useCallback(() => {
|
const getNumViewportPanes = useCallback(() => {
|
||||||
const { layout, viewports } = viewportGridState;
|
const { layout, viewports } = viewportGridState;
|
||||||
const { numRows, numCols } = layout;
|
const { numRows, numCols } = layout;
|
||||||
@ -466,12 +494,14 @@ export function ViewportGridProvider({ children, service }: ViewportGridProvider
|
|||||||
getState,
|
getState,
|
||||||
setActiveViewportId,
|
setActiveViewportId,
|
||||||
setDisplaySetsForViewports,
|
setDisplaySetsForViewports,
|
||||||
|
setIsReferenceViewable,
|
||||||
setLayout,
|
setLayout,
|
||||||
reset,
|
reset,
|
||||||
onModeExit: reset,
|
onModeExit: reset,
|
||||||
set,
|
set,
|
||||||
getNumViewportPanes,
|
getNumViewportPanes,
|
||||||
setViewportIsReady,
|
setViewportIsReady,
|
||||||
|
getViewportState,
|
||||||
getGridViewportsReady,
|
getGridViewportsReady,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -480,12 +510,14 @@ export function ViewportGridProvider({ children, service }: ViewportGridProvider
|
|||||||
service,
|
service,
|
||||||
setActiveViewportId,
|
setActiveViewportId,
|
||||||
setDisplaySetsForViewports,
|
setDisplaySetsForViewports,
|
||||||
|
setIsReferenceViewable,
|
||||||
setLayout,
|
setLayout,
|
||||||
reset,
|
reset,
|
||||||
set,
|
set,
|
||||||
getNumViewportPanes,
|
getNumViewportPanes,
|
||||||
setViewportIsReady,
|
setViewportIsReady,
|
||||||
getGridViewportsReady,
|
getGridViewportsReady,
|
||||||
|
getViewportState,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// run many of the calls through the service itself since we want to publish events
|
// run many of the calls through the service itself since we want to publish events
|
||||||
@ -494,7 +526,10 @@ export function ViewportGridProvider({ children, service }: ViewportGridProvider
|
|||||||
setActiveViewportId: index => service.setActiveViewportId(index),
|
setActiveViewportId: index => service.setActiveViewportId(index),
|
||||||
setDisplaySetsForViewport: props => service.setDisplaySetsForViewports([props]),
|
setDisplaySetsForViewport: props => service.setDisplaySetsForViewports([props]),
|
||||||
setDisplaySetsForViewports: props => service.setDisplaySetsForViewports(props),
|
setDisplaySetsForViewports: props => service.setDisplaySetsForViewports(props),
|
||||||
|
setIsReferenceViewable: (viewportId, isReferenceViewable) =>
|
||||||
|
service.setIsReferenceViewable(viewportId, isReferenceViewable),
|
||||||
setLayout: layout => service.setLayout(layout),
|
setLayout: layout => service.setLayout(layout),
|
||||||
|
getViewportState: viewportId => service.getViewportState(viewportId),
|
||||||
reset: () => service.reset(),
|
reset: () => service.reset(),
|
||||||
set: gridLayoutState => service.setState(gridLayoutState), // run it through the service itself since we want to publish events
|
set: gridLayoutState => service.setState(gridLayoutState), // run it through the service itself since we want to publish events
|
||||||
getNumViewportPanes,
|
getNumViewportPanes,
|
||||||
|
|||||||
104
tests/JumpToMeasurementMPR.spec.ts
Normal file
104
tests/JumpToMeasurementMPR.spec.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { test } from '@playwright/test';
|
||||||
|
import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils';
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095258.1';
|
||||||
|
const mode = 'viewer';
|
||||||
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should hydrate in MPR correctly', async ({ page }) => {
|
||||||
|
await page.getByTestId('side-panel-header-right').click();
|
||||||
|
await page.getByTestId('trackedMeasurements-btn').click();
|
||||||
|
|
||||||
|
// get the div that has Body 4.0 Lung I and double click it
|
||||||
|
|
||||||
|
await page.locator(':text("S:7")').first().dblclick();
|
||||||
|
|
||||||
|
await page.evaluate(() => {
|
||||||
|
// Access cornerstone directly from the window object
|
||||||
|
const cornerstone = window.cornerstone;
|
||||||
|
if (!cornerstone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const enabledElements = cornerstone.getEnabledElements();
|
||||||
|
if (enabledElements.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const viewport = enabledElements[0].viewport;
|
||||||
|
if (viewport) {
|
||||||
|
viewport.setImageIdIndex(20);
|
||||||
|
viewport.render();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.getByTestId('MeasurementTools-split-button-secondary').click();
|
||||||
|
await page.getByTestId('Bidirectional').click();
|
||||||
|
const locator = page.getByTestId('viewport-pane').locator('canvas');
|
||||||
|
|
||||||
|
await simulateClicksOnElement({
|
||||||
|
locator,
|
||||||
|
points: [
|
||||||
|
{
|
||||||
|
x: 405,
|
||||||
|
y: 277,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 515,
|
||||||
|
y: 339,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// wait 2 seconds
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
|
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
||||||
|
|
||||||
|
// scroll away
|
||||||
|
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.initialDraw);
|
||||||
|
|
||||||
|
// use mouse wheel to scroll away
|
||||||
|
await page.mouse.wheel(0, 100);
|
||||||
|
|
||||||
|
// wait 2 seconds
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
|
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.scrollAway);
|
||||||
|
|
||||||
|
await page.getByTestId('data-row').first().click();
|
||||||
|
|
||||||
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
|
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.jumpToMeasurementStack);
|
||||||
|
|
||||||
|
await page.getByTestId('Layout').click();
|
||||||
|
await page.locator('div').filter({ hasText: /^MPR$/ }).first().click();
|
||||||
|
|
||||||
|
// wait 2 seconds
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
|
// jump in viewport again
|
||||||
|
await page.getByTestId('data-row').first().click();
|
||||||
|
|
||||||
|
await page.waitForTimeout(3000);
|
||||||
|
|
||||||
|
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.jumpInMPR);
|
||||||
|
|
||||||
|
await page.locator(':text("S:3")').first().dblclick();
|
||||||
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
|
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.changeSeriesInMPR);
|
||||||
|
|
||||||
|
await page.getByTestId('data-row').first().click();
|
||||||
|
|
||||||
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
|
await checkForScreenshot(
|
||||||
|
page,
|
||||||
|
page,
|
||||||
|
screenShotPaths.jumpToMeasurementMPR.jumpToMeasurementAfterSeriesChange
|
||||||
|
);
|
||||||
|
});
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 236 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 221 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 200 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 200 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 221 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 156 KiB |
@ -102,6 +102,16 @@ const screenShotPaths = {
|
|||||||
tmtvRendering: {
|
tmtvRendering: {
|
||||||
tmtvDisplayedCorrectly: 'tmtvDisplayedCorrectly.png',
|
tmtvDisplayedCorrectly: 'tmtvDisplayedCorrectly.png',
|
||||||
},
|
},
|
||||||
|
jumpToMeasurementMPR: {
|
||||||
|
initialDraw: 'jumpToMeasurementMPR-initialDraw.png',
|
||||||
|
scrollAway: 'jumpToMeasurementMPR-scrollAway.png',
|
||||||
|
jumpToMeasurementStack: 'jumpToMeasurementMPR-jumpToMeasurementStack.png',
|
||||||
|
goToMPR: 'jumpToMeasurementMPR-goToMPR.png',
|
||||||
|
jumpInMPR: 'jumpToMeasurementMPR-jumpInMPR.png',
|
||||||
|
changeSeriesInMPR: 'jumpToMeasurementMPR-changeSeriesInMPR.png',
|
||||||
|
jumpToMeasurementAfterSeriesChange:
|
||||||
|
'jumpToMeasurementMPR-jumpToMeasurementAfterSeriesChange.png',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export { screenShotPaths };
|
export { screenShotPaths };
|
||||||
|
|||||||
48
yarn.lock
48
yarn.lock
@ -1393,10 +1393,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
|
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
|
||||||
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
|
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
|
||||||
|
|
||||||
"@cornerstonejs/adapters@^3.7.16":
|
"@cornerstonejs/adapters@^3.7.17":
|
||||||
version "3.7.16"
|
version "3.7.17"
|
||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-3.7.16.tgz#4ac66230ffba5b527abf4ba58c8b10ef46643c45"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-3.7.17.tgz#7e0a84d4010c4757e58c0d350c5604de865d8c56"
|
||||||
integrity sha512-gMLRTZzhIGOwUT9rufpv4uq5iHTJgg2x6GW++eOi/6bEDY2wOiH2peRM8W1EfAoa3cK+lLLoAqEARlVMJq//tg==
|
integrity sha512-K1tz4y5YRgen+z8Yva5mzO3iwn1UZRoqf0wX8VjU1zszx/F4m19DSNcR9H5BJvlGM09DZjpJ42QXK2o9pIvnTg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime-corejs2" "^7.17.8"
|
"@babel/runtime-corejs2" "^7.17.8"
|
||||||
buffer "^6.0.3"
|
buffer "^6.0.3"
|
||||||
@ -1429,20 +1429,20 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.5.tgz#8690b61a86fa53ef38a70eee9d665a79229517c0"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.5.tgz#8690b61a86fa53ef38a70eee9d665a79229517c0"
|
||||||
integrity sha512-MZCUy8VG0VG5Nl1l58+g+kH3LujAzLYTfJqkwpWI2gjSrGXnP6lgwyy4GmPRZWVoS40/B1LDNALK905cNWm+sg==
|
integrity sha512-MZCUy8VG0VG5Nl1l58+g+kH3LujAzLYTfJqkwpWI2gjSrGXnP6lgwyy4GmPRZWVoS40/B1LDNALK905cNWm+sg==
|
||||||
|
|
||||||
"@cornerstonejs/core@^3.7.16":
|
"@cornerstonejs/core@^3.7.17":
|
||||||
version "3.7.16"
|
version "3.7.17"
|
||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-3.7.16.tgz#7b4a1ab6a726482ddc380eee15299ec1f9461ad5"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-3.7.17.tgz#4a7986aa8bb7a68fbff597d3906e96e6b6483fc2"
|
||||||
integrity sha512-5rc371p1P+hk1rUzpHTByW+7Mp6LyahqWJLJwt/55a4BEiEtbhWyTSAz/XKWcOd5bgq7huAsyHKCmMcWrHx3pg==
|
integrity sha512-2Z3FqrGJept9k1dmlGeMBPon1MDR/P7CkcTTevpKTlYiT3D7bqQ+Q5xdssLzWRD86et0PkRSJGktBM163WCgGw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@kitware/vtk.js" "32.12.1"
|
"@kitware/vtk.js" "32.12.1"
|
||||||
comlink "^4.4.1"
|
comlink "^4.4.1"
|
||||||
gl-matrix "^3.4.3"
|
gl-matrix "^3.4.3"
|
||||||
loglevel "^1.9.2"
|
loglevel "^1.9.2"
|
||||||
|
|
||||||
"@cornerstonejs/dicom-image-loader@^3.7.16":
|
"@cornerstonejs/dicom-image-loader@^3.7.17":
|
||||||
version "3.7.16"
|
version "3.7.17"
|
||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-3.7.16.tgz#e0ed7621f81b5a3dd38f3e899ac9b7ba4a2a4ea9"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-3.7.17.tgz#b14ba0cf64ab8a454ac086cd1ed6f2481359d533"
|
||||||
integrity sha512-8O3cd9L54s3AFE3DZUMKOUvuuE9MkYuWZ8NgCPtBE1Qky6d4KNGKdljzwmpj8JJ7y7yGLW1rI0KqQc9DCf4//Q==
|
integrity sha512-LKHQ7x7S47TtF8M4ZmR4S+afbSsAT+yVMkKD81VU3A8oyuX7hT4+cUO4JlGGck3BxG4FyjgNSGT+T3YxAH1SHw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@cornerstonejs/codec-charls" "^1.2.3"
|
"@cornerstonejs/codec-charls" "^1.2.3"
|
||||||
"@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2"
|
"@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2"
|
||||||
@ -1454,25 +1454,25 @@
|
|||||||
pako "^2.0.4"
|
pako "^2.0.4"
|
||||||
uuid "^9.0.0"
|
uuid "^9.0.0"
|
||||||
|
|
||||||
"@cornerstonejs/labelmap-interpolation@^3.7.16":
|
"@cornerstonejs/labelmap-interpolation@^3.7.17":
|
||||||
version "3.7.16"
|
version "3.7.17"
|
||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/labelmap-interpolation/-/labelmap-interpolation-3.7.16.tgz#fffda0b2da7cbb21ecfed8e19dd72371e5bc73fb"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/labelmap-interpolation/-/labelmap-interpolation-3.7.17.tgz#fb57706c19c77cbc8192d81d9f2d6e086be637ae"
|
||||||
integrity sha512-zoL7arbPywNxUksKkkorcICpIwAgcpYbBBEFIGXt4gSS7NPC7cRU12PU1mj3Cgy+59nO2QIohoPkv0Kj/AwXmA==
|
integrity sha512-K8R11wqv4TFljMArbx+4JbMtsINeMandp0mD8zyrj1rWXA+RY49QcNa7ob6KBnV26xJqXMT0VyJ0k/Ow53TiLQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@itk-wasm/morphological-contour-interpolation" "1.1.0"
|
"@itk-wasm/morphological-contour-interpolation" "1.1.0"
|
||||||
itk-wasm "1.0.0-b.165"
|
itk-wasm "1.0.0-b.165"
|
||||||
|
|
||||||
"@cornerstonejs/polymorphic-segmentation@^3.7.16":
|
"@cornerstonejs/polymorphic-segmentation@^3.7.17":
|
||||||
version "3.7.16"
|
version "3.7.17"
|
||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/polymorphic-segmentation/-/polymorphic-segmentation-3.7.16.tgz#75c6b564178e3057075f46e5fa66a1fff3e2c3d5"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/polymorphic-segmentation/-/polymorphic-segmentation-3.7.17.tgz#f6b4f4530996d974d59fff97ec29bd34a7a8cb16"
|
||||||
integrity sha512-HW7h9xRWRDKmaYpv4KWqSYcFz4M2EbMnYNaP+JgnLRws/1eoVPM5YYTsWgyINOM8fdR9o6tMmtMdjcioEGsZPg==
|
integrity sha512-ZI0643arqYbkrjadDSOsGTO2JS1OUtJkF8qEnjjG8MlxqQ7g6sPnTM/atrYRc9ZFoJxFL4kz7D0gOjcBrarYeQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@icr/polyseg-wasm" "0.4.0"
|
"@icr/polyseg-wasm" "0.4.0"
|
||||||
|
|
||||||
"@cornerstonejs/tools@^3.7.16":
|
"@cornerstonejs/tools@^3.7.17":
|
||||||
version "3.7.16"
|
version "3.7.17"
|
||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-3.7.16.tgz#53fd8b8437a63bcfedcb776d9edb0ad7cac414ab"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-3.7.17.tgz#dc758ec14e0016bf76d04f54d3e91bd824ebdc7a"
|
||||||
integrity sha512-hmAAmUiEr8z920btZtkT7jqYgZzQqLT82FijfYZVd591nddR25hb77OXEJ+PPAQbvktwPSUZx0kMBoUuM5VpWw==
|
integrity sha512-ZDMboShGzMDkqnzEDE7Y9UTJgHqGkVQt8l6AL5dCyA/IIlWEXXdxVe1weotJxgjMqaPETiwJ5EtN/3D4+tf1Rg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/offscreencanvas" "2019.7.3"
|
"@types/offscreencanvas" "2019.7.3"
|
||||||
comlink "^4.4.1"
|
comlink "^4.4.1"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user