fix(core): Address 3D reconstruction and Android compatibility issues and clean up 4D data mode (#4762)
This commit is contained in:
parent
4d06a7d286
commit
149d6d049c
@ -2,7 +2,7 @@ version: 2.1
|
||||
|
||||
orbs:
|
||||
codecov: codecov/codecov@1.0.5
|
||||
cypress: cypress-io/cypress@3.3.1
|
||||
cypress: cypress-io/cypress@3.4.2
|
||||
|
||||
defaults: &defaults
|
||||
docker:
|
||||
|
||||
310
bun.lock
310
bun.lock
@ -32,7 +32,7 @@
|
||||
},
|
||||
"addOns/externals/devDependencies": {
|
||||
"name": "@externals/devDependencies",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@kitware/vtk.js": "32.1.1",
|
||||
@ -120,19 +120,19 @@
|
||||
},
|
||||
"addOns/externals/dicom-microscopy-viewer": {
|
||||
"name": "@externals/dicom-microscopy-viewer",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"dicom-microscopy-viewer": "^0.46.1",
|
||||
},
|
||||
},
|
||||
"extensions/cornerstone": {
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^2.17.2",
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/tools": "^2.17.2",
|
||||
"@cornerstonejs/adapters": "^2.19.3",
|
||||
"@cornerstonejs/core": "^2.19.3",
|
||||
"@cornerstonejs/tools": "^2.19.3",
|
||||
"@icr/polyseg-wasm": "^0.4.0",
|
||||
"@itk-wasm/morphological-contour-interpolation": "1.1.0",
|
||||
"@kitware/vtk.js": "32.1.1",
|
||||
@ -150,9 +150,9 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.17.2",
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/ui": "3.10.0-beta.82",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.19.3",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"dcmjs": "*",
|
||||
"dicom-parser": "^1.8.21",
|
||||
"hammerjs": "^2.0.8",
|
||||
@ -164,19 +164,19 @@
|
||||
},
|
||||
"extensions/cornerstone-dicom-pmap": {
|
||||
"name": "@ohif/extension-cornerstone-dicom-pmap",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^2.17.2",
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/adapters": "^2.19.3",
|
||||
"@cornerstonejs/core": "^2.19.3",
|
||||
"@kitware/vtk.js": "32.1.1",
|
||||
"react-color": "^2.19.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/i18n": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/i18n": "3.10.0-beta.91",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
@ -187,16 +187,16 @@
|
||||
},
|
||||
"extensions/cornerstone-dicom-rt": {
|
||||
"name": "@ohif/extension-cornerstone-dicom-rt",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"react-color": "^2.19.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/i18n": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/i18n": "3.10.0-beta.91",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
@ -207,19 +207,19 @@
|
||||
},
|
||||
"extensions/cornerstone-dicom-seg": {
|
||||
"name": "@ohif/extension-cornerstone-dicom-seg",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^2.17.2",
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/adapters": "^2.19.3",
|
||||
"@cornerstonejs/core": "^2.19.3",
|
||||
"@kitware/vtk.js": "32.1.1",
|
||||
"react-color": "^2.19.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/i18n": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/i18n": "3.10.0-beta.91",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
@ -230,19 +230,19 @@
|
||||
},
|
||||
"extensions/cornerstone-dicom-sr": {
|
||||
"name": "@ohif/extension-cornerstone-dicom-sr",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^2.17.2",
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/tools": "^2.17.2",
|
||||
"@cornerstonejs/adapters": "^2.19.3",
|
||||
"@cornerstonejs/core": "^2.19.3",
|
||||
"@cornerstonejs/tools": "^2.19.3",
|
||||
"classnames": "^2.3.2",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.82",
|
||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.82",
|
||||
"@ohif/ui": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.91",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"dcmjs": "*",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
@ -252,19 +252,19 @@
|
||||
},
|
||||
"extensions/cornerstone-dynamic-volume": {
|
||||
"name": "@ohif/extension-cornerstone-dynamic-volume",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/tools": "^2.17.2",
|
||||
"@cornerstonejs/core": "^2.19.3",
|
||||
"@cornerstonejs/tools": "^2.19.3",
|
||||
"classnames": "^2.3.2",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/i18n": "3.10.0-beta.82",
|
||||
"@ohif/ui": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/i18n": "3.10.0-beta.91",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"dcmjs": "*",
|
||||
"dicom-parser": "^1.8.21",
|
||||
"hammerjs": "^2.0.8",
|
||||
@ -274,14 +274,14 @@
|
||||
},
|
||||
"extensions/default": {
|
||||
"name": "@ohif/extension-default",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/calculate-suv": "^1.1.0",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/i18n": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/i18n": "3.10.0-beta.91",
|
||||
"dcmjs": "*",
|
||||
"dicomweb-client": "^0.10.4",
|
||||
"prop-types": "^15.6.2",
|
||||
@ -295,7 +295,7 @@
|
||||
},
|
||||
"extensions/dicom-microscopy": {
|
||||
"name": "@ohif/extension-dicom-microscopy",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/codec-charls": "^1.2.3",
|
||||
@ -305,10 +305,10 @@
|
||||
"mathjs": "^12.4.2",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/i18n": "3.10.0-beta.82",
|
||||
"@ohif/ui": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/i18n": "3.10.0-beta.91",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
@ -319,14 +319,14 @@
|
||||
},
|
||||
"extensions/dicom-pdf": {
|
||||
"name": "@ohif/extension-dicom-pdf",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"classnames": "^2.3.2",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/ui": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"dcmjs": "*",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
@ -336,14 +336,14 @@
|
||||
},
|
||||
"extensions/dicom-video": {
|
||||
"name": "@ohif/extension-dicom-video",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"classnames": "^2.3.2",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/ui": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"dcmjs": "*",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
@ -353,20 +353,20 @@
|
||||
},
|
||||
"extensions/measurement-tracking": {
|
||||
"name": "@ohif/extension-measurement-tracking",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@ohif/ui": "3.10.0-beta.82",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"@xstate/react": "^3.2.2",
|
||||
"xstate": "^4.10.0",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/tools": "^2.17.2",
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/ui": "3.10.0-beta.82",
|
||||
"@cornerstonejs/core": "^2.19.3",
|
||||
"@cornerstonejs/tools": "^2.19.3",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"classnames": "^2.3.2",
|
||||
"dcmjs": "*",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
@ -379,14 +379,14 @@
|
||||
},
|
||||
"extensions/test-extension": {
|
||||
"name": "@ohif/extension-test",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"classnames": "^2.3.2",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/ui": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"dcmjs": "0.38.0",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
@ -396,14 +396,14 @@
|
||||
},
|
||||
"extensions/tmtv": {
|
||||
"name": "@ohif/extension-tmtv",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"classnames": "^2.3.2",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/ui": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"dcmjs": "*",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
@ -413,7 +413,7 @@
|
||||
},
|
||||
"modes/basic-dev-mode": {
|
||||
"name": "@ohif/mode-basic-dev-mode",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"i18next": "^17.0.3",
|
||||
@ -423,17 +423,17 @@
|
||||
"webpack-merge": "^5.7.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-video": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-video": "3.10.0-beta.91",
|
||||
},
|
||||
},
|
||||
"modes/basic-test-mode": {
|
||||
"name": "@ohif/mode-test",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"i18next": "^17.0.3",
|
||||
@ -443,19 +443,19 @@
|
||||
"webpack-merge": "^5.7.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-video": "3.10.0-beta.82",
|
||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.82",
|
||||
"@ohif/extension-test": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-video": "3.10.0-beta.91",
|
||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.91",
|
||||
"@ohif/extension-test": "3.10.0-beta.91",
|
||||
},
|
||||
},
|
||||
"modes/longitudinal": {
|
||||
"name": "@ohif/mode-longitudinal",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"i18next": "^17.0.3",
|
||||
@ -465,32 +465,32 @@
|
||||
"webpack-merge": "^5.7.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-video": "3.10.0-beta.82",
|
||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-video": "3.10.0-beta.91",
|
||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.91",
|
||||
},
|
||||
},
|
||||
"modes/microscopy": {
|
||||
"name": "@ohif/mode-microscopy",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"i18next": "^17.0.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-microscopy": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-microscopy": "3.10.0-beta.91",
|
||||
},
|
||||
},
|
||||
"modes/preclinical-4d": {
|
||||
"name": "@ohif/mode-preclinical-4d",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
},
|
||||
@ -499,17 +499,17 @@
|
||||
"webpack-merge": "^5.7.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dynamic-volume": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/extension-tmtv": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dynamic-volume": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/extension-tmtv": "3.10.0-beta.91",
|
||||
},
|
||||
},
|
||||
"modes/segmentation": {
|
||||
"name": "@ohif/mode-segmentation",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"i18next": "^17.0.3",
|
||||
@ -541,19 +541,19 @@
|
||||
"webpack-merge": "^5.7.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-video": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-video": "3.10.0-beta.91",
|
||||
},
|
||||
},
|
||||
"modes/tmtv": {
|
||||
"name": "@ohif/mode-tmtv",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"i18next": "^17.0.3",
|
||||
@ -563,43 +563,43 @@
|
||||
"webpack-merge": "^5.7.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-video": "3.10.0-beta.82",
|
||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-video": "3.10.0-beta.91",
|
||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.91",
|
||||
},
|
||||
},
|
||||
"platform/app": {
|
||||
"name": "@ohif/app",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/codec-charls": "^1.2.3",
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.17.2",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.19.3",
|
||||
"@emotion/serialize": "^1.1.3",
|
||||
"@ohif/core": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.82",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.82",
|
||||
"@ohif/extension-default": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-microscopy": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.82",
|
||||
"@ohif/extension-dicom-video": "3.10.0-beta.82",
|
||||
"@ohif/extension-test": "3.10.0-beta.82",
|
||||
"@ohif/i18n": "3.10.0-beta.82",
|
||||
"@ohif/mode-basic-dev-mode": "3.10.0-beta.82",
|
||||
"@ohif/mode-longitudinal": "3.10.0-beta.82",
|
||||
"@ohif/mode-microscopy": "3.10.0-beta.82",
|
||||
"@ohif/mode-test": "3.10.0-beta.82",
|
||||
"@ohif/ui": "3.10.0-beta.82",
|
||||
"@ohif/ui-next": "3.10.0-beta.82",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-microscopy": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-pdf": "3.10.0-beta.91",
|
||||
"@ohif/extension-dicom-video": "3.10.0-beta.91",
|
||||
"@ohif/extension-test": "3.10.0-beta.91",
|
||||
"@ohif/i18n": "3.10.0-beta.91",
|
||||
"@ohif/mode-basic-dev-mode": "3.10.0-beta.91",
|
||||
"@ohif/mode-longitudinal": "3.10.0-beta.91",
|
||||
"@ohif/mode-microscopy": "3.10.0-beta.91",
|
||||
"@ohif/mode-test": "3.10.0-beta.91",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"@ohif/ui-next": "3.10.0-beta.91",
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@types/react": "^18.3.3",
|
||||
"classnames": "^2.3.2",
|
||||
@ -641,7 +641,7 @@
|
||||
},
|
||||
"platform/cli": {
|
||||
"name": "@ohif/cli",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"bin": {
|
||||
"ohif-cli": "src/index.js"
|
||||
},
|
||||
@ -665,7 +665,7 @@
|
||||
},
|
||||
"platform/core": {
|
||||
"name": "@ohif/core",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"dcmjs": "*",
|
||||
@ -691,15 +691,15 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.17.2",
|
||||
"@ohif/ui": "3.10.0-beta.82",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.19.3",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"cornerstone-math": "0.1.9",
|
||||
"dicom-parser": "^1.8.21",
|
||||
},
|
||||
},
|
||||
"platform/i18n": {
|
||||
"name": "@ohif/i18n",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"i18next-locize-backend": "^2.0.0",
|
||||
@ -724,7 +724,7 @@
|
||||
},
|
||||
"platform/ui": {
|
||||
"name": "@ohif/ui",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@testing-library/react": "^13.1.0",
|
||||
"browser-detect": "^0.2.28",
|
||||
@ -782,7 +782,7 @@
|
||||
},
|
||||
"platform/ui-next": {
|
||||
"name": "@ohif/ui-next",
|
||||
"version": "3.10.0-beta.82",
|
||||
"version": "3.10.0-beta.91",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-accordion": "^1.2.0",
|
||||
"@radix-ui/react-checkbox": "^1.1.1",
|
||||
@ -1091,7 +1091,7 @@
|
||||
|
||||
"@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="],
|
||||
|
||||
"@cornerstonejs/adapters": ["@cornerstonejs/adapters@2.18.2", "", { "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": "^2.18.2", "@cornerstonejs/tools": "^2.18.2" } }, "sha512-Tm2izseStXcPQwrXmD6T3X8ybnFwjPyGltVTYvqwwlzLw4quuPw1B60scvY13rKrg3Pl04smYNqfw37nzIFjQQ=="],
|
||||
"@cornerstonejs/adapters": ["@cornerstonejs/adapters@2.19.3", "", { "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": "^2.19.3", "@cornerstonejs/tools": "^2.19.3" } }, "sha512-QuugcUCelTW9bxhO1yewuuf6UHbIufiWMU+plNp40RwR92hgWi1SB9K/gFhtSRxVBqnkbG3Sh6mZRSuS3KcP1A=="],
|
||||
|
||||
"@cornerstonejs/calculate-suv": ["@cornerstonejs/calculate-suv@1.1.0", "", {}, "sha512-Q9XraiDJif9aMFArD2iEuDO/HXbcRVCqB7KfaHgDrdTTjgDFovS91Psbdim7crypRSvE6dh/+HKeFNHdvNkA6w=="],
|
||||
|
||||
@ -1103,11 +1103,11 @@
|
||||
|
||||
"@cornerstonejs/codec-openjph": ["@cornerstonejs/codec-openjph@2.4.7", "", {}, "sha512-qvP4q4JDib7mi9r7LqKOwqz7YZ8gjtDX4ZCezeYf8+eb7MBXCz5uXAMeVF3yz9Axw4XiIMdB/pqXkm8tqCl13w=="],
|
||||
|
||||
"@cornerstonejs/core": ["@cornerstonejs/core@2.18.2", "", { "dependencies": { "@kitware/vtk.js": "32.9.0", "comlink": "^4.4.1", "gl-matrix": "^3.4.3" } }, "sha512-nlkWBL56I9gYFy/77loFyPjFGe7R72kQFRPtcIcGZ89Jnz3nwZSjGma7taJJjiSfb2YnUUhmT4HvzsqQlClPdg=="],
|
||||
"@cornerstonejs/core": ["@cornerstonejs/core@2.19.3", "", { "dependencies": { "@kitware/vtk.js": "32.9.0", "comlink": "^4.4.1", "gl-matrix": "^3.4.3" } }, "sha512-yqPFpfzKCNj9U94q1do8oE3adg7+/t+bc4uBHrNPCvbUyOqaWZzentw5+79cj5hhHif2OG0jVNRSPr+kbBBk2Q=="],
|
||||
|
||||
"@cornerstonejs/dicom-image-loader": ["@cornerstonejs/dicom-image-loader@2.18.2", "", { "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", "jpeg-lossless-decoder-js": "^2.1.0", "pako": "^2.0.4", "uuid": "^9.0.0" }, "peerDependencies": { "@cornerstonejs/core": "^2.18.2", "dicom-parser": "^1.8.9" } }, "sha512-m9GFwsrChJdWGYG8OZGGeSft89cUaPLlkw2pd5kDLxJz0874nJQgTp27L7o/mjRXqEijQhiPNtWdSvwUZv60pg=="],
|
||||
"@cornerstonejs/dicom-image-loader": ["@cornerstonejs/dicom-image-loader@2.19.3", "", { "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", "jpeg-lossless-decoder-js": "^2.1.0", "pako": "^2.0.4", "uuid": "^9.0.0" }, "peerDependencies": { "@cornerstonejs/core": "^2.19.3", "dicom-parser": "^1.8.9" } }, "sha512-/VTmaDabIqF8lBzPq0yK3yF6TIb3vTEoMeyvXTQWpPG1wjiTRAaYql5uQjCgE1p/xCXVA3Iq+h2rk90HWFu6nA=="],
|
||||
|
||||
"@cornerstonejs/tools": ["@cornerstonejs/tools@2.18.2", "", { "dependencies": { "@types/offscreencanvas": "2019.7.3", "comlink": "^4.4.1", "lodash.get": "^4.4.2" }, "peerDependencies": { "@cornerstonejs/core": "^2.18.2", "@kitware/vtk.js": "32.9.0", "@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-Xxfl3JWB86tN/GAawFwKApfglu+3rFZyRSKyvnpUl8aAPomjhvbt93l2H8VDliw+JuCEgrUwCu0LQl0wumpR2Q=="],
|
||||
"@cornerstonejs/tools": ["@cornerstonejs/tools@2.19.3", "", { "dependencies": { "@types/offscreencanvas": "2019.7.3", "comlink": "^4.4.1", "lodash.get": "^4.4.2" }, "peerDependencies": { "@cornerstonejs/core": "^2.19.3", "@kitware/vtk.js": "32.9.0", "@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-bJFhE2b1B2k8enZT9vZqspLXmSHqCLAOFwib5FWi4/9AtNydVaDBIafAYq/gCXTcF8YcbsUhBhWQL1LU7ejkWg=="],
|
||||
|
||||
"@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": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^2.17.2",
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/adapters": "^2.19.3",
|
||||
"@cornerstonejs/core": "^2.19.3",
|
||||
"@kitware/vtk.js": "32.1.1",
|
||||
"react-color": "^2.19.3"
|
||||
}
|
||||
|
||||
@ -46,8 +46,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^2.17.2",
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/adapters": "^2.19.3",
|
||||
"@cornerstonejs/core": "^2.19.3",
|
||||
"@kitware/vtk.js": "32.1.1",
|
||||
"react-color": "^2.19.3"
|
||||
}
|
||||
|
||||
@ -46,9 +46,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^2.17.2",
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/tools": "^2.17.2",
|
||||
"@cornerstonejs/adapters": "^2.19.3",
|
||||
"@cornerstonejs/core": "^2.19.3",
|
||||
"@cornerstonejs/tools": "^2.19.3",
|
||||
"classnames": "^2.3.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,8 +42,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/tools": "^2.17.2",
|
||||
"@cornerstonejs/core": "^2.19.3",
|
||||
"@cornerstonejs/tools": "^2.19.3",
|
||||
"classnames": "^2.3.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Button, PanelSection, ButtonGroup, IconButton, InputNumber } from '@ohif/ui';
|
||||
import { DoubleSlider, Icons, Tooltip, TooltipTrigger, TooltipContent } from '@ohif/ui-next';
|
||||
import { Icons, Tooltip, TooltipTrigger, TooltipContent, Numeric } from '@ohif/ui-next';
|
||||
import { Enums } from '@cornerstonejs/core';
|
||||
|
||||
const controlClassNames = {
|
||||
@ -20,7 +20,10 @@ const Header = ({ title, tooltip }) => (
|
||||
/>
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent sideOffset={4} className="max-w-xs p-2 bg-primary-dark text-white">
|
||||
<TooltipContent
|
||||
sideOffset={4}
|
||||
className="bg-primary-dark max-w-xs p-2 text-white"
|
||||
>
|
||||
<div>{tooltip}</div>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
@ -37,23 +40,16 @@ const DynamicVolumeControls = ({
|
||||
minFps,
|
||||
maxFps,
|
||||
// Frames
|
||||
currentFrameIndex,
|
||||
onFrameChange,
|
||||
framesLength,
|
||||
currentDimensionGroupNumber,
|
||||
onDimensionGroupChange,
|
||||
numDimensionGroups,
|
||||
onGenerate,
|
||||
onDoubleRangeChange,
|
||||
rangeValues,
|
||||
onDynamicClick,
|
||||
}) => {
|
||||
const [computedView, setComputedView] = useState(false);
|
||||
const [computeViewMode, setComputeViewMode] = useState(Enums.DynamicOperatorType.SUM);
|
||||
const [sliderRangeValues, setSliderRangeValues] = useState([0, framesLength - 1]);
|
||||
|
||||
const handleSliderChange = newValues => {
|
||||
onDoubleRangeChange(newValues);
|
||||
setSliderRangeValues(newValues);
|
||||
};
|
||||
|
||||
const formatLabel = value => Math.round(value);
|
||||
|
||||
return (
|
||||
<div className="flex select-none flex-col">
|
||||
@ -89,7 +85,7 @@ const DynamicVolumeControls = ({
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
<div>
|
||||
<FrameControls
|
||||
<DimensionGroupControls
|
||||
onPlayPauseChange={onPlayPauseChange}
|
||||
isPlaying={isPlaying}
|
||||
computedView={computedView}
|
||||
@ -99,9 +95,9 @@ const DynamicVolumeControls = ({
|
||||
minFps={minFps}
|
||||
maxFps={maxFps}
|
||||
//
|
||||
framesLength={framesLength}
|
||||
onFrameChange={onFrameChange}
|
||||
currentFrameIndex={currentFrameIndex}
|
||||
numDimensionGroups={numDimensionGroups}
|
||||
onDimensionGroupChange={onDimensionGroupChange}
|
||||
currentDimensionGroupNumber={currentDimensionGroupNumber}
|
||||
/>
|
||||
</div>
|
||||
<div className={`mt-6 flex flex-col ${computedView ? '' : 'ohif-disabled'}`}>
|
||||
@ -111,9 +107,10 @@ const DynamicVolumeControls = ({
|
||||
<div>
|
||||
Operation Buttons (SUM, AVERAGE, SUBTRACT): Select the mathematical operation to be
|
||||
applied to the data set.
|
||||
<br /> Range Slider: Choose the numeric range within which the operation will be
|
||||
performed.
|
||||
<br />Generate Button: Execute the chosen operation on the specified range of data.
|
||||
<br /> Range Slider: Choose the numeric range of dimension groups within which the
|
||||
operation will be performed.
|
||||
<br />
|
||||
Generate Button: Execute the chosen operation on the specified range of data.
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
@ -141,15 +138,15 @@ const DynamicVolumeControls = ({
|
||||
</button>
|
||||
</ButtonGroup>
|
||||
<div className="mt-2 w-full">
|
||||
<DoubleSlider
|
||||
min={0}
|
||||
max={framesLength - 1}
|
||||
step={1}
|
||||
defaultValue={sliderRangeValues}
|
||||
onValueChange={handleSliderChange}
|
||||
formatLabel={formatLabel}
|
||||
className="w-full"
|
||||
/>
|
||||
<Numeric.Container
|
||||
mode="doubleRange"
|
||||
min={1}
|
||||
max={numDimensionGroups}
|
||||
values={rangeValues}
|
||||
onChange={onDoubleRangeChange}
|
||||
>
|
||||
<Numeric.DoubleRange showNumberInputs />
|
||||
</Numeric.Container>
|
||||
</div>
|
||||
<Button
|
||||
className="mt-2 !h-[26px] !w-[115px] self-start !p-0"
|
||||
@ -167,16 +164,16 @@ const DynamicVolumeControls = ({
|
||||
|
||||
export default DynamicVolumeControls;
|
||||
|
||||
function FrameControls({
|
||||
function DimensionGroupControls({
|
||||
isPlaying,
|
||||
onPlayPauseChange,
|
||||
fps,
|
||||
minFps,
|
||||
maxFps,
|
||||
onFpsChange,
|
||||
framesLength,
|
||||
onFrameChange,
|
||||
currentFrameIndex,
|
||||
numDimensionGroups,
|
||||
onDimensionGroupChange,
|
||||
currentDimensionGroupNumber,
|
||||
computedView,
|
||||
}) {
|
||||
const getPlayPauseIconName = () => (isPlaying ? 'icon-pause' : 'icon-play');
|
||||
@ -187,14 +184,16 @@ function FrameControls({
|
||||
title="4D Controls"
|
||||
tooltip={
|
||||
<div>
|
||||
Play/Pause Button: Begin or pause the animation of the 4D visualization. <br /> Frame
|
||||
Selector: Navigate through individual frames of the 4D data. <br /> FPS (Frames Per
|
||||
Second) Selector: Adjust the playback speed of the animation.
|
||||
Play/Pause Button: Begin or pause the animation of the 4D visualization. <br />
|
||||
Dimension Group Selector: Navigate through individual dimension groups of the 4D data.{' '}
|
||||
<br />
|
||||
FPS (Frames Per Second) Selector: Adjust the playback speed of the animation.
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<div className="mt-3 flex justify-between">
|
||||
<IconButton
|
||||
id="play-pause-button"
|
||||
className="bg-customblue-30 h-[26px] w-[58px] rounded-[4px]"
|
||||
onClick={() => onPlayPauseChange(!isPlaying)}
|
||||
>
|
||||
@ -204,11 +203,11 @@ function FrameControls({
|
||||
/>
|
||||
</IconButton>
|
||||
<InputNumber
|
||||
value={currentFrameIndex}
|
||||
onChange={onFrameChange}
|
||||
minValue={0}
|
||||
maxValue={framesLength - 1}
|
||||
label="Frame"
|
||||
value={currentDimensionGroupNumber}
|
||||
onChange={onDimensionGroupChange}
|
||||
minValue={1}
|
||||
maxValue={numDimensionGroups}
|
||||
label="Group"
|
||||
{...controlClassNames}
|
||||
/>
|
||||
<InputNumber
|
||||
@ -222,4 +221,4 @@ function FrameControls({
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,13 +15,12 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
|
||||
const [{ activeViewportId }] = useViewportGrid();
|
||||
|
||||
//
|
||||
const [timePointsRange, setTimePointsRange] = useState([0, 0]);
|
||||
const [timePointsRangeToUseForGenerate, setTimePointsRangeToUseForGenerate] = useState([0, 0]);
|
||||
const [dimensionGroupRange, setDimensionGroupRange] = useState([1, 1]);
|
||||
const [computedDisplaySet, setComputedDisplaySet] = useState(null);
|
||||
const [dynamicVolume, setDynamicVolume] = useState(null);
|
||||
const [frameRate, setFrameRate] = useState(20);
|
||||
const [isPlaying, setIsPlaying] = useState(isCineEnabled);
|
||||
const [timePointRendered, setTimePointRendered] = useState(null);
|
||||
const [dimensionGroupNumberRendered, setDimensionGroupNumberRendered] = useState(null);
|
||||
const [displayingComputed, setDisplayingComputed] = useState(false);
|
||||
|
||||
//
|
||||
@ -38,9 +37,8 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
|
||||
if (volumeData.volume?.isDynamicVolume()) {
|
||||
setDynamicVolume(volumeData.volume);
|
||||
uuidDynamicVolume.current = volumeData.displaySetInstanceUID;
|
||||
const newRange = [1, volumeData.volume.numTimePoints];
|
||||
setTimePointsRange(newRange);
|
||||
setTimePointsRangeToUseForGenerate(newRange);
|
||||
const newRange = [1, volumeData.volume.numDimensionGroups];
|
||||
setDimensionGroupRange(newRange);
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -65,10 +63,10 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
|
||||
}, [cornerstoneViewportService, cineService, servicesManager.services.cineService]);
|
||||
|
||||
useEffect(() => {
|
||||
const evt = Enums.Events.DYNAMIC_VOLUME_TIME_POINT_INDEX_CHANGED;
|
||||
const evt = Enums.Events.DYNAMIC_VOLUME_DIMENSION_GROUP_CHANGED;
|
||||
|
||||
const callback = evt => {
|
||||
setTimePointRendered(evt.detail.timePointIndex);
|
||||
setDimensionGroupNumberRendered(evt.detail.dimensionGroupNumber);
|
||||
};
|
||||
|
||||
eventTarget.addEventListener(evt, callback);
|
||||
@ -76,7 +74,7 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
|
||||
return () => {
|
||||
eventTarget.removeEventListener(evt, callback);
|
||||
};
|
||||
}, [cornerstoneViewportService]);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(activeViewportId);
|
||||
@ -102,9 +100,7 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
|
||||
|
||||
setDynamicVolume(dynamicVolume);
|
||||
uuidDynamicVolume.current = dynamicVolumeDisplaySet.displaySetInstanceUID;
|
||||
const newRange = [1, dynamicVolume.numTimePoints];
|
||||
setTimePointsRange(newRange);
|
||||
setTimePointsRangeToUseForGenerate(newRange);
|
||||
setDimensionGroupRange([1, dynamicVolume.numDimensionGroups]);
|
||||
}, [
|
||||
activeViewportId,
|
||||
viewportGridService,
|
||||
@ -141,11 +137,12 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
|
||||
volumeId: computedVolumeId,
|
||||
});
|
||||
}
|
||||
const [start, end] = timePointsRangeToUseForGenerate;
|
||||
const frameNumbers = Array.from({ length: end - start + 1 }, (_, i) => i + start - 1);
|
||||
const [start, end] = dimensionGroupRange;
|
||||
// from start to end, with steps of 1
|
||||
const frameNumbers = Array.from({ length: end - start + 1 }, (_, i) => start + i);
|
||||
|
||||
const options = {
|
||||
frameNumbers: operationName === 'SUBTRACT' ? [start, end - 1] : frameNumbers,
|
||||
dimensionGroupNumbers: operationName === 'SUBTRACT' ? [start, end] : frameNumbers,
|
||||
targetVolume: computedVolume,
|
||||
};
|
||||
|
||||
@ -207,17 +204,6 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
|
||||
handlePlay();
|
||||
};
|
||||
|
||||
function handleSliderChange(newValues) {
|
||||
if (
|
||||
newValues[0] === timePointsRangeToUseForGenerate[0] &&
|
||||
newValues[1] === timePointsRangeToUseForGenerate[1]
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTimePointsRangeToUseForGenerate(newValues);
|
||||
}
|
||||
|
||||
return (
|
||||
<DynamicVolumeControls
|
||||
fps={frameRate}
|
||||
@ -225,16 +211,16 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
|
||||
onPlayPauseChange={onPlayPauseChange}
|
||||
minFps={1}
|
||||
maxFps={50}
|
||||
currentFrameIndex={timePointRendered}
|
||||
onFpsChange={handleSetFrameRate}
|
||||
framesLength={timePointsRange[1]}
|
||||
onFrameChange={timePointIndex => {
|
||||
dynamicVolume.timePointIndex = timePointIndex;
|
||||
currentDimensionGroupNumber={dimensionGroupNumberRendered}
|
||||
numDimensionGroups={dynamicVolume?.numDimensionGroups || 1}
|
||||
onDimensionGroupChange={dimensionGroupNumber => {
|
||||
dynamicVolume.dimensionGroupNumber = dimensionGroupNumber;
|
||||
}}
|
||||
onGenerate={onGenerateImage}
|
||||
onDynamicClick={displayingComputed ? () => renderDynamicImage(computedDisplaySet) : null}
|
||||
onDoubleRangeChange={handleSliderChange}
|
||||
initialRangeValues={timePointsRangeToUseForGenerate}
|
||||
onDoubleRangeChange={setDimensionGroupRange}
|
||||
rangeValues={dimensionGroupRange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.17.2",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.19.3",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"dcmjs": "*",
|
||||
@ -54,9 +54,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^2.17.2",
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/tools": "^2.17.2",
|
||||
"@cornerstonejs/adapters": "^2.19.3",
|
||||
"@cornerstonejs/core": "^2.19.3",
|
||||
"@cornerstonejs/tools": "^2.19.3",
|
||||
"@icr/polyseg-wasm": "^0.4.0",
|
||||
"@itk-wasm/morphological-contour-interpolation": "1.1.0",
|
||||
"@kitware/vtk.js": "32.1.1",
|
||||
|
||||
@ -53,13 +53,13 @@ function WrappedCinePlayer({
|
||||
// check if the displaySet is dynamic and set the dynamic info
|
||||
if (displaySet.isDynamicVolume) {
|
||||
const { dynamicVolumeInfo } = displaySet;
|
||||
const numTimePoints = dynamicVolumeInfo.timePoints.length;
|
||||
const numDimensionGroups = dynamicVolumeInfo.timePoints.length;
|
||||
const label = dynamicVolumeInfo.splittingTag;
|
||||
const timePointIndex = dynamicVolumeInfo.timePointIndex || 0;
|
||||
const dimensionGroupNumber = dynamicVolumeInfo.dimensionGroupNumber || 1;
|
||||
setDynamicInfo({
|
||||
volumeId: displaySet.displaySetInstanceUID,
|
||||
timePointIndex,
|
||||
numTimePoints,
|
||||
dimensionGroupNumber,
|
||||
numDimensionGroups,
|
||||
label,
|
||||
});
|
||||
} else {
|
||||
@ -176,20 +176,20 @@ function RenderCinePlayer({
|
||||
return;
|
||||
}
|
||||
|
||||
const handleTimePointIndexChange = evt => {
|
||||
const { volumeId, timePointIndex, numTimePoints, splittingTag } = evt.detail;
|
||||
setDynamicInfo({ volumeId, timePointIndex, numTimePoints, label: splittingTag });
|
||||
const handleDimensionGroupChange = evt => {
|
||||
const { volumeId, dimensionGroupNumber, numDimensionGroups, splittingTag } = evt.detail;
|
||||
setDynamicInfo({ volumeId, dimensionGroupNumber, numDimensionGroups, label: splittingTag });
|
||||
};
|
||||
|
||||
eventTarget.addEventListener(
|
||||
Enums.Events.DYNAMIC_VOLUME_TIME_POINT_INDEX_CHANGED,
|
||||
handleTimePointIndexChange
|
||||
Enums.Events.DYNAMIC_VOLUME_DIMENSION_GROUP_CHANGED,
|
||||
handleDimensionGroupChange
|
||||
);
|
||||
|
||||
return () => {
|
||||
eventTarget.removeEventListener(
|
||||
Enums.Events.DYNAMIC_VOLUME_TIME_POINT_INDEX_CHANGED,
|
||||
handleTimePointIndexChange
|
||||
Enums.Events.DYNAMIC_VOLUME_DIMENSION_GROUP_CHANGED,
|
||||
handleDimensionGroupChange
|
||||
);
|
||||
};
|
||||
}, [dynamicInfo]);
|
||||
@ -199,17 +199,17 @@ function RenderCinePlayer({
|
||||
return;
|
||||
}
|
||||
|
||||
const { volumeId, timePointIndex, numTimePoints, splittingTag } = dynamicInfo || {};
|
||||
const { volumeId, dimensionGroupNumber, numDimensionGroups, splittingTag } = dynamicInfo || {};
|
||||
const volume = cache.getVolume(volumeId, true);
|
||||
volume.timePointIndex = timePointIndex;
|
||||
volume.dimensionGroupNumber = dimensionGroupNumber;
|
||||
|
||||
setDynamicInfo({ volumeId, timePointIndex, numTimePoints, label: splittingTag });
|
||||
setDynamicInfo({ volumeId, dimensionGroupNumber, numDimensionGroups, label: splittingTag });
|
||||
}, []);
|
||||
|
||||
const updateDynamicInfo = useCallback(props => {
|
||||
const { volumeId, timePointIndex } = props;
|
||||
const { volumeId, dimensionGroupNumber } = props;
|
||||
const volume = cache.getVolume(volumeId, true);
|
||||
volume.timePointIndex = timePointIndex;
|
||||
volume.dimensionGroupNumber = dimensionGroupNumber;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
|
||||
|
||||
export const fourUp = {
|
||||
id: 'fourUp',
|
||||
locked: true,
|
||||
@ -46,17 +48,7 @@ export const fourUp = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
@ -72,6 +64,7 @@ export const fourUp = {
|
||||
customViewportProps: {
|
||||
hideOverlays: true,
|
||||
},
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
@ -94,17 +87,7 @@ export const fourUp = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
@ -120,17 +103,7 @@ export const fourUp = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
|
||||
|
||||
export const main3D = {
|
||||
id: 'main3D',
|
||||
locked: true,
|
||||
@ -94,17 +96,7 @@ export const main3D = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
@ -120,17 +112,7 @@ export const main3D = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
@ -146,17 +128,7 @@ export const main3D = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Types } from '@ohif/core';
|
||||
|
||||
const VOI_SYNC_GROUP = {
|
||||
export const VOI_SYNC_GROUP = {
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
@ -10,7 +10,7 @@ const VOI_SYNC_GROUP = {
|
||||
},
|
||||
};
|
||||
|
||||
const HYDRATE_SEG_SYNC_GROUP = {
|
||||
export const HYDRATE_SEG_SYNC_GROUP = {
|
||||
type: 'hydrateseg',
|
||||
id: 'sameFORId',
|
||||
source: true,
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
|
||||
|
||||
export const mprAnd3DVolumeViewport = {
|
||||
id: 'mprAnd3DVolumeViewport',
|
||||
locked: true,
|
||||
@ -53,17 +55,7 @@ export const mprAnd3DVolumeViewport = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
@ -79,6 +71,7 @@ export const mprAnd3DVolumeViewport = {
|
||||
customViewportProps: {
|
||||
hideOverlays: true,
|
||||
},
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
@ -101,17 +94,7 @@ export const mprAnd3DVolumeViewport = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
@ -127,17 +110,7 @@ export const mprAnd3DVolumeViewport = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
|
||||
|
||||
export const only3D = {
|
||||
id: 'only3D',
|
||||
locked: true,
|
||||
@ -45,6 +47,7 @@ export const only3D = {
|
||||
orientation: 'coronal',
|
||||
customViewportProps: {
|
||||
hideOverlays: true,
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
},
|
||||
displaySets: [
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
|
||||
|
||||
export const primary3D = {
|
||||
id: 'primary3D',
|
||||
locked: true,
|
||||
@ -94,17 +96,7 @@ export const primary3D = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
@ -120,17 +112,7 @@ export const primary3D = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
@ -146,17 +128,7 @@ export const primary3D = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
|
||||
|
||||
export const primaryAxial = {
|
||||
id: 'primaryAxial',
|
||||
locked: true,
|
||||
@ -66,17 +68,7 @@ export const primaryAxial = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
@ -92,17 +84,7 @@ export const primaryAxial = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
@ -118,17 +100,7 @@ export const primaryAxial = {
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
options: {
|
||||
syncColormap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
|
||||
@ -1,22 +1,18 @@
|
||||
import { useEffect, useState, memo } from 'react';
|
||||
import { useEffect, useState, memo, useCallback } from 'react';
|
||||
|
||||
const ActiveViewportBehavior = memo(
|
||||
({ servicesManager, viewportId }: withAppTypes<{ viewportId: string }>) => {
|
||||
const { displaySetService, cineService, viewportGridService, customizationService } =
|
||||
servicesManager.services;
|
||||
const {
|
||||
displaySetService,
|
||||
cineService,
|
||||
viewportGridService,
|
||||
customizationService,
|
||||
cornerstoneViewportService,
|
||||
} = servicesManager.services;
|
||||
|
||||
const [activeViewportId, setActiveViewportId] = useState(viewportId);
|
||||
|
||||
useEffect(() => {
|
||||
const subscription = viewportGridService.subscribe(
|
||||
viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED,
|
||||
({ viewportId }) => setActiveViewportId(viewportId)
|
||||
);
|
||||
|
||||
return () => subscription.unsubscribe();
|
||||
}, [viewportId, viewportGridService]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleCineEnable = useCallback(() => {
|
||||
if (cineService.isViewportCineClosed(activeViewportId)) {
|
||||
return;
|
||||
}
|
||||
@ -54,6 +50,32 @@ const ActiveViewportBehavior = memo(
|
||||
customizationService,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const subscription = viewportGridService.subscribe(
|
||||
viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED,
|
||||
({ viewportId }) => setActiveViewportId(viewportId)
|
||||
);
|
||||
|
||||
return () => subscription.unsubscribe();
|
||||
}, [viewportId, viewportGridService]);
|
||||
|
||||
useEffect(() => {
|
||||
const subscription = cornerstoneViewportService.subscribe(
|
||||
cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED,
|
||||
() => {
|
||||
const activeViewportId = viewportGridService.getActiveViewportId();
|
||||
setActiveViewportId(activeViewportId);
|
||||
handleCineEnable();
|
||||
}
|
||||
);
|
||||
|
||||
return () => subscription.unsubscribe();
|
||||
}, [viewportId, cornerstoneViewportService, viewportGridService, handleCineEnable]);
|
||||
|
||||
useEffect(() => {
|
||||
handleCineEnable();
|
||||
}, [handleCineEnable]);
|
||||
|
||||
return null;
|
||||
},
|
||||
arePropsEqual
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
import { MeasurementItem } from '@ohif/ui';
|
||||
|
||||
export default {
|
||||
'microscopyPanel.measurementItem': MeasurementItem,
|
||||
};
|
||||
12
extensions/dicom-microscopy/src/getCustomizationModule.ts
Normal file
12
extensions/dicom-microscopy/src/getCustomizationModule.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import panelMeasurementItem from './customizations/panelMeasurementItem';
|
||||
|
||||
export default function getCustomizationModule() {
|
||||
return [
|
||||
{
|
||||
name: 'default',
|
||||
value: {
|
||||
...panelMeasurementItem,
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
@ -2,6 +2,7 @@ import { id } from './id';
|
||||
import React, { Suspense, useMemo } from 'react';
|
||||
import getPanelModule from './getPanelModule';
|
||||
import getCommandsModule from './getCommandsModule';
|
||||
import getCustomizationModule from './getCustomizationModule';
|
||||
import { Types } from '@ohif/core';
|
||||
|
||||
import { useViewportGrid } from '@ohif/ui-next';
|
||||
@ -158,6 +159,8 @@ const extension: Types.Extensions.Extension = {
|
||||
getPanelModule,
|
||||
|
||||
getCommandsModule,
|
||||
|
||||
getCustomizationModule,
|
||||
};
|
||||
|
||||
export default extension;
|
||||
|
||||
@ -32,8 +32,8 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/tools": "^2.17.2",
|
||||
"@cornerstonejs/core": "^2.19.3",
|
||||
"@cornerstonejs/tools": "^2.19.3",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.91",
|
||||
"@ohif/extension-default": "3.10.0-beta.91",
|
||||
|
||||
@ -54,7 +54,7 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.17.2",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.19.3",
|
||||
"@emotion/serialize": "^1.1.3",
|
||||
"@ohif/core": "3.10.0-beta.91",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.91",
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.17.2",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.19.3",
|
||||
"@ohif/ui": "3.10.0-beta.91",
|
||||
"cornerstone-math": "0.1.9",
|
||||
"dicom-parser": "^1.8.21"
|
||||
|
||||
@ -285,14 +285,25 @@ export default class HangingProtocolService extends PubSubService {
|
||||
* @param protocolId - the id of the protocol
|
||||
* @returns protocol - the protocol with the given id
|
||||
*/
|
||||
public getProtocolById(protocolId: string): HangingProtocol.Protocol {
|
||||
public getProtocolById(protocolId: string, caseInsensitive = true): HangingProtocol.Protocol {
|
||||
if (!protocolId) {
|
||||
return;
|
||||
}
|
||||
if (protocolId === this.protocol?.id) {
|
||||
return this.protocol;
|
||||
}
|
||||
const protocol = this.protocols.get(protocolId);
|
||||
|
||||
let protocol = this.protocols.get(protocolId);
|
||||
if (!protocol && caseInsensitive) {
|
||||
const lowerCaseId = protocolId.toLowerCase();
|
||||
for (const [key] of this.protocols) {
|
||||
if (key.toLowerCase() === lowerCaseId) {
|
||||
protocol = this.getProtocolById(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!protocol) {
|
||||
throw new Error(`No protocol ${protocolId} found`);
|
||||
}
|
||||
@ -533,8 +544,7 @@ export default class HangingProtocolService extends PubSubService {
|
||||
}
|
||||
|
||||
_validateProtocol(protocol: HangingProtocol.Protocol): HangingProtocol.Protocol {
|
||||
protocol.id = protocol.id || protocol.name;
|
||||
protocol.name = protocol.name || protocol.id;
|
||||
protocol.name = protocol.name ?? protocol.id;
|
||||
const { stages } = protocol;
|
||||
|
||||
if (!stages) {
|
||||
|
||||
@ -15,7 +15,6 @@ be centered, and not draggable. They're commonly used when:
|
||||
If you're curious about the DOs and DON'Ts of dialogs and modals, check out this
|
||||
article: ["Best Practices for Modals / Overlays / Dialog Windows"][ux-article]
|
||||
|
||||
customComponent: The modal service allows users to provide their own Modal UI using the customComponents.
|
||||
|
||||
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
@ -38,12 +37,17 @@ is expected to support, [check out it's interface in `@ohif/core`][interface]
|
||||
| Implementation | Consumer |
|
||||
| ---------------------------------- | --------- |
|
||||
| [Modal Provider][modal-provider]\* | Modal.jsx |
|
||||
| customComponent | user extensions via setServiceImplementation({customComponent: Modal}) |
|
||||
|
||||
`*` - Denotes maintained by OHIF
|
||||
| customComponent | user extensions via `setServiceImplementation({customComponent: Modal})` |
|
||||
|
||||
|
||||
|
||||
### Custom Component
|
||||
If you would like to customize the modal component that OHIF uses, you can register your own
|
||||
component with the `customComponent` property.
|
||||
|
||||
```js
|
||||
setServiceImplementation({customComponent: Modal})
|
||||
```
|
||||
|
||||
|
||||
> 3rd Party implementers may be added to this table via pull requests.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import Numeric from '../../../../ui-next/src/components/Numeric';
|
||||
import Icons from '../../../../ui-next/src/components/Icons';
|
||||
import ShowcaseRow from './ShowcaseRow';
|
||||
@ -7,6 +7,9 @@ import ShowcaseRow from './ShowcaseRow';
|
||||
* NumericShowcase component displays Numeric variants and examples
|
||||
*/
|
||||
export default function NumericShowcase() {
|
||||
const [controlledValue, setControlledValue] = useState(0);
|
||||
const [controlledValues, setControlledValues] = useState([0, 100] as [number, number]);
|
||||
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
{/* Basic Number Input */}
|
||||
@ -14,19 +17,26 @@ export default function NumericShowcase() {
|
||||
title="Numeric - Number Input"
|
||||
description="Basic number input with min, max and a label"
|
||||
code={`
|
||||
<Numeric.Container mode="number" min={0} max={10} onChange={onChange}>
|
||||
<Numeric.Container mode="number" min={0} max={10} onChange={val => console.debug('Value changed:', val)}>
|
||||
<div className="flex flex-row items-center space-x-2">
|
||||
<Numeric.Label>Width</Numeric.Label>
|
||||
<Numeric.NumberInput />
|
||||
</div>
|
||||
</Numeric.Container>
|
||||
|
||||
<Numeric.Container mode="number" min={0} max={100} onChange={onChange}>
|
||||
<Numeric.Label className="text-secondary-foreground text-sm font-bold">Bolder</Numeric.Label>
|
||||
<Numeric.Container mode="number" className="space-y-1" min={0} max={100} onChange={val => console.debug('Value changed:', val)}>
|
||||
<Numeric.Label className="text-muted-foreground text-sm font-bold">Bolder</Numeric.Label>
|
||||
<Numeric.NumberInput className="w-12" />
|
||||
</Numeric.Container>
|
||||
|
||||
<Numeric.Container mode="number" className="flex flex-row items-center justify-between" onChange={onChange} min={0} value={123465789} max={10000000000000}>
|
||||
<Numeric.Container
|
||||
mode="number"
|
||||
className="flex flex-row items-center justify-between"
|
||||
onChange={val => console.debug('Value changed:', val)}
|
||||
min={0}
|
||||
value={123465789}
|
||||
max={10000000000000}
|
||||
>
|
||||
<Numeric.Label className="flex flex-row items-center">
|
||||
<Icons.Add />
|
||||
With Icon
|
||||
@ -82,18 +92,37 @@ export default function NumericShowcase() {
|
||||
title="Numeric - Single Range"
|
||||
description="Single range slider with optional number input"
|
||||
code={`
|
||||
<Numeric.Container mode="singleRange" min={0} max={100} step={1} value={50} onChange={onChange}>
|
||||
// For controlled component
|
||||
const [controlledValue, setControlledValue] = useState(0);
|
||||
|
||||
<Numeric.Container mode="singleRange" min={0} max={100} onChange={val => console.debug('Value changed:', val)}>
|
||||
<Numeric.Label>Brightness</Numeric.Label>
|
||||
<Numeric.SingleRange showNumberInput />
|
||||
</Numeric.Container>
|
||||
|
||||
<Numeric.Container mode="singleRange" min={-50} max={50} step={1} value={0} className="flex flex-row items-center" onChange={onChange}>
|
||||
<Numeric.Container
|
||||
mode="singleRange"
|
||||
min={-50}
|
||||
max={50}
|
||||
step={1}
|
||||
defaultValue={0}
|
||||
className="flex flex-row items-center"
|
||||
onChange={val => console.debug('Value changed:', val)}
|
||||
>
|
||||
<Numeric.Label showValue>Contrast</Numeric.Label>
|
||||
<Numeric.SingleRange />
|
||||
</Numeric.Container>
|
||||
|
||||
<Numeric.Container mode="singleRange" min={0} max={100} step={1} value={50} className="flex flex-row items-center space-x-2" onChange={onChange}>
|
||||
<Numeric.Label>Something Else </Numeric.Label>
|
||||
<Numeric.Container
|
||||
mode="singleRange"
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
value={controlledValue}
|
||||
className="flex flex-row items-center space-x-2"
|
||||
onChange={val => setControlledValue(val as number)}
|
||||
>
|
||||
<Numeric.Label>Controlled State (Parent) </Numeric.Label>
|
||||
<Numeric.SingleRange showNumberInput />
|
||||
</Numeric.Container>`}
|
||||
>
|
||||
@ -102,8 +131,6 @@ export default function NumericShowcase() {
|
||||
mode="singleRange"
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
value={50}
|
||||
onChange={val => console.debug('Value changed:', val)}
|
||||
>
|
||||
<Numeric.Label>Brightness</Numeric.Label>
|
||||
@ -115,7 +142,7 @@ export default function NumericShowcase() {
|
||||
min={-50}
|
||||
max={50}
|
||||
step={1}
|
||||
value={0}
|
||||
defaultValue={0}
|
||||
className="flex flex-row items-center"
|
||||
onChange={val => console.debug('Value changed:', val)}
|
||||
>
|
||||
@ -128,11 +155,11 @@ export default function NumericShowcase() {
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
value={50}
|
||||
value={controlledValue}
|
||||
className="flex flex-row items-center space-x-2"
|
||||
onChange={val => console.debug('Value changed:', val)}
|
||||
onChange={val => setControlledValue(val as number)}
|
||||
>
|
||||
<Numeric.Label>Something Else </Numeric.Label>
|
||||
<Numeric.Label>Controlled State (Parent) </Numeric.Label>
|
||||
<Numeric.SingleRange showNumberInput />
|
||||
</Numeric.Container>
|
||||
</div>
|
||||
@ -143,18 +170,44 @@ export default function NumericShowcase() {
|
||||
title="Numeric - Double Range"
|
||||
description="Double range slider for selecting a range of values"
|
||||
code={`
|
||||
<Numeric.Container mode="doubleRange" min={0} max={100} step={1} values={[30, 70]} onChange={onChange}>
|
||||
// For controlled component
|
||||
const [controlledValues, setControlledValues] = useState<[number, number]>([0, 100]);
|
||||
|
||||
<Numeric.Container
|
||||
mode="doubleRange"
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
className="space-y-1"
|
||||
onChange={vals => console.debug('Values changed:', vals)}
|
||||
>
|
||||
<Numeric.Label showValue>Window Width/Level</Numeric.Label>
|
||||
<Numeric.DoubleRange />
|
||||
</Numeric.Container>
|
||||
|
||||
<Numeric.Container mode="doubleRange" min={0} max={100} step={1} values={[30, 70]}>
|
||||
<Numeric.Container
|
||||
mode="doubleRange"
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
defaultValues={[30, 70]}
|
||||
className="space-y-1"
|
||||
onChange={vals => console.debug('Values changed:', vals)}
|
||||
>
|
||||
<Numeric.Label>Window Width/Level</Numeric.Label>
|
||||
<Numeric.DoubleRange showNumberInputs />
|
||||
</Numeric.Container>
|
||||
|
||||
<Numeric.Container mode="doubleRange" min={0} max={100} step={1} values={[30, 70]} className="flex flex-row items-center space-x-2" onChange={onChange}>
|
||||
<Numeric.Label>Inline double slider</Numeric.Label>
|
||||
<Numeric.Container
|
||||
mode="doubleRange"
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
values={controlledValues}
|
||||
className="flex flex-row items-center space-x-2"
|
||||
onChange={vals => setControlledValues(vals as [number, number])}
|
||||
>
|
||||
<Numeric.Label>Controlled State (Parent) </Numeric.Label>
|
||||
<Numeric.DoubleRange />
|
||||
</Numeric.Container>`}
|
||||
>
|
||||
@ -164,7 +217,6 @@ export default function NumericShowcase() {
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
values={[30, 70]}
|
||||
className="space-y-1"
|
||||
onChange={vals => console.debug('Values changed:', vals)}
|
||||
>
|
||||
@ -177,8 +229,9 @@ export default function NumericShowcase() {
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
values={[30, 70]}
|
||||
defaultValues={[30, 70]}
|
||||
className="space-y-1"
|
||||
onChange={vals => console.debug('Values changed:', vals)}
|
||||
>
|
||||
<Numeric.Label>Window Width/Level</Numeric.Label>
|
||||
<Numeric.DoubleRange showNumberInputs />
|
||||
@ -189,11 +242,11 @@ export default function NumericShowcase() {
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
values={[30, 70]}
|
||||
values={controlledValues}
|
||||
className="flex flex-row items-center space-x-2"
|
||||
onChange={vals => console.debug('Values changed:', vals)}
|
||||
onChange={vals => setControlledValues(vals as [number, number])}
|
||||
>
|
||||
<Numeric.Label>Inline double slider</Numeric.Label>
|
||||
<Numeric.Label>Controlled State (Parent) </Numeric.Label>
|
||||
<Numeric.DoubleRange />
|
||||
</Numeric.Container>
|
||||
</div>
|
||||
@ -204,17 +257,35 @@ export default function NumericShowcase() {
|
||||
title="Numeric - Combined Examples"
|
||||
description="Different modes and configurations working together"
|
||||
code={`
|
||||
<Numeric.Container mode="number" min={0} max={10} step={0.1}>
|
||||
<Numeric.Container
|
||||
mode="number"
|
||||
min={0}
|
||||
max={10}
|
||||
step={0.1}
|
||||
className="space-y-1"
|
||||
>
|
||||
<Numeric.Label>Zoom Factor</Numeric.Label>
|
||||
<Numeric.NumberInput />
|
||||
</Numeric.Container>
|
||||
|
||||
<Numeric.Container mode="singleRange" min={0} max={360} step={1}>
|
||||
<Numeric.Container
|
||||
mode="singleRange"
|
||||
min={0}
|
||||
max={360}
|
||||
step={1}
|
||||
className="space-y-1"
|
||||
>
|
||||
<Numeric.Label showValue>Rotation</Numeric.Label>
|
||||
<Numeric.SingleRange showNumberInput />
|
||||
</Numeric.Container>
|
||||
|
||||
<Numeric.Container mode="doubleRange" min={-1000} max={3000} values={[1000, 2000]} step={10}>
|
||||
<Numeric.Container
|
||||
mode="doubleRange"
|
||||
min={-1000}
|
||||
max={3000}
|
||||
step={10}
|
||||
className="space-y-1"
|
||||
>
|
||||
<Numeric.Label showValue>CT Window</Numeric.Label>
|
||||
<Numeric.DoubleRange showNumberInputs />
|
||||
</Numeric.Container>`}
|
||||
@ -246,7 +317,6 @@ export default function NumericShowcase() {
|
||||
mode="doubleRange"
|
||||
min={-1000}
|
||||
max={3000}
|
||||
values={[1000, 2000]}
|
||||
step={10}
|
||||
className="space-y-1"
|
||||
>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
// Numeric.tsx
|
||||
import React, { createContext, useContext, useState, useCallback, PropsWithChildren } from 'react';
|
||||
import React, { createContext, useContext, useCallback, PropsWithChildren } from 'react';
|
||||
import { useControllableState } from '@radix-ui/react-use-controllable-state';
|
||||
import { cn } from '../../lib/utils';
|
||||
import { Input } from '../Input/Input';
|
||||
import { Slider } from '../Slider/Slider';
|
||||
@ -23,8 +24,10 @@ const NumericMetaContext = createContext<NumericMetaContextValue | null>(null);
|
||||
---------------------------------------------------------------------------*/
|
||||
interface NumericMetaContainerProps {
|
||||
mode: 'number' | 'singleRange' | 'doubleRange';
|
||||
value?: number; // for single-value usage
|
||||
values?: [number, number]; // for double-range usage
|
||||
value?: number; // for controlled single-value usage from parent
|
||||
defaultValue?: number; // for uncontrolled single-value usage
|
||||
values?: [number, number]; // for controlled double-range usage from parent
|
||||
defaultValues?: [number, number]; // for uncontrolled double-range usage
|
||||
onChange?: (val: number | [number, number]) => void;
|
||||
min?: number;
|
||||
max?: number;
|
||||
@ -34,8 +37,10 @@ interface NumericMetaContainerProps {
|
||||
|
||||
function NumericMetaContainer({
|
||||
mode,
|
||||
value = 0,
|
||||
values = [0, 100],
|
||||
value,
|
||||
defaultValue,
|
||||
values,
|
||||
defaultValues,
|
||||
onChange,
|
||||
min = 0,
|
||||
max = 100,
|
||||
@ -43,26 +48,46 @@ function NumericMetaContainer({
|
||||
className,
|
||||
children,
|
||||
}: PropsWithChildren<NumericMetaContainerProps>) {
|
||||
// Initialize state with props but don't update automatically
|
||||
const [internalSingleValue, setInternalSingleValue] = useState<number>(value);
|
||||
const [internalDoubleValue, setInternalDoubleValue] = useState<[number, number]>(values);
|
||||
// Calculate default values based on min and max
|
||||
const calculatedDefaultValue = defaultValue ?? min + (max - min) / 2;
|
||||
const calculatedDefaultValues = defaultValues ?? [
|
||||
min + (max - min) * 0.3,
|
||||
min + (max - min) * 0.7,
|
||||
];
|
||||
|
||||
// Use useControllableState for both single and double values
|
||||
const [internalSingleValue, setInternalSingleValue] = useControllableState({
|
||||
prop: mode === 'number' || mode === 'singleRange' ? value : undefined,
|
||||
defaultProp: calculatedDefaultValue,
|
||||
onChange: newVal => {
|
||||
if (mode === 'number' || mode === 'singleRange') {
|
||||
onChange?.(newVal);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const [internalDoubleValue, setInternalDoubleValue] = useControllableState({
|
||||
prop: mode === 'doubleRange' ? values : undefined,
|
||||
defaultProp: calculatedDefaultValues,
|
||||
onChange: newVals => {
|
||||
if (mode === 'doubleRange') {
|
||||
onChange?.(newVals);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const handleSingleChange = useCallback(
|
||||
(newVal: number) => {
|
||||
setInternalSingleValue(newVal);
|
||||
onChange?.(newVal);
|
||||
},
|
||||
[onChange]
|
||||
[setInternalSingleValue]
|
||||
);
|
||||
|
||||
const handleDoubleChange = useCallback(
|
||||
(newVals: [number, number]) => {
|
||||
// Update internal state
|
||||
setInternalDoubleValue(newVals);
|
||||
// Notify parent if onChange is provided
|
||||
onChange?.(newVals);
|
||||
},
|
||||
[onChange]
|
||||
[setInternalDoubleValue]
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@ -99,6 +99,7 @@ import {
|
||||
ToolButtonListItem,
|
||||
ToolButtonListDivider,
|
||||
Toolbox,
|
||||
Numeric,
|
||||
} from './components';
|
||||
import { DataRow } from './components/DataRow';
|
||||
|
||||
@ -223,4 +224,5 @@ export {
|
||||
Toolbox,
|
||||
useToolbox,
|
||||
utils,
|
||||
Numeric,
|
||||
};
|
||||
|
||||
@ -19,8 +19,8 @@ export type CinePlayerProps = {
|
||||
onClose: () => void;
|
||||
updateDynamicInfo?: () => void;
|
||||
dynamicInfo?: {
|
||||
timePointIndex: number;
|
||||
numTimePoints: number;
|
||||
dimensionGroupNumber: number;
|
||||
numDimensionGroups: number;
|
||||
label?: string;
|
||||
};
|
||||
};
|
||||
@ -41,7 +41,7 @@ const CinePlayer: React.FC<CinePlayerProps> = ({
|
||||
dynamicInfo = {},
|
||||
updateDynamicInfo,
|
||||
}) => {
|
||||
const isDynamic = !!dynamicInfo?.numTimePoints;
|
||||
const isDynamic = !!dynamicInfo?.numDimensionGroups;
|
||||
const [frameRate, setFrameRate] = useState(defaultFrameRate);
|
||||
const debouncedSetFrameRate = useCallback(debounce(onFrameRateChange, 100), [onFrameRateChange]);
|
||||
|
||||
@ -59,14 +59,14 @@ const CinePlayer: React.FC<CinePlayerProps> = ({
|
||||
setFrameRate(defaultFrameRate);
|
||||
}, [defaultFrameRate]);
|
||||
|
||||
const handleTimePointChange = useCallback(
|
||||
(newIndex: number) => {
|
||||
const handleDimensionGroupNumberChange = useCallback(
|
||||
(newGroupNumber: number) => {
|
||||
if (isDynamic && dynamicInfo) {
|
||||
// Here, you would update the component's state or context that controls the current time point index
|
||||
// For demonstration, assuming a hypothetical function that updates the time point index
|
||||
updateDynamicInfo({
|
||||
...dynamicInfo,
|
||||
timePointIndex: newIndex,
|
||||
dimensionGroupNumber: newGroupNumber,
|
||||
});
|
||||
}
|
||||
},
|
||||
@ -77,10 +77,10 @@ const CinePlayer: React.FC<CinePlayerProps> = ({
|
||||
<div className={className}>
|
||||
{isDynamic && dynamicInfo && (
|
||||
<InputRange
|
||||
value={dynamicInfo.timePointIndex}
|
||||
onChange={handleTimePointChange}
|
||||
minValue={0}
|
||||
maxValue={dynamicInfo.numTimePoints - 1}
|
||||
value={dynamicInfo.dimensionGroupNumber}
|
||||
onChange={handleDimensionGroupNumberChange}
|
||||
minValue={1}
|
||||
maxValue={dynamicInfo.numDimensionGroups}
|
||||
step={1}
|
||||
containerClassName="mb-3 w-full"
|
||||
labelClassName="text-xs text-white"
|
||||
@ -107,8 +107,8 @@ const CinePlayer: React.FC<CinePlayerProps> = ({
|
||||
<div className="min-w-16 max-w-44 flex flex-col text-white">
|
||||
{/* Add Tailwind classes for monospace font and center alignment */}
|
||||
<div className="text-[11px]">
|
||||
<span className="w-2 text-white">{dynamicInfo.timePointIndex}</span>{' '}
|
||||
<span className="text-aqua-pale">{`/${dynamicInfo.numTimePoints}`}</span>
|
||||
<span className="w-2 text-white">{dynamicInfo.dimensionGroupNumber}</span>{' '}
|
||||
<span className="text-aqua-pale">{`/${dynamicInfo.numDimensionGroups}`}</span>
|
||||
</div>
|
||||
<div className="text-aqua-pale text-xs">{dynamicInfo.label}</div>
|
||||
</div>
|
||||
@ -180,8 +180,8 @@ CinePlayer.propTypes = {
|
||||
onClose: PropTypes.func,
|
||||
isDynamic: PropTypes.bool,
|
||||
dynamicInfo: PropTypes.shape({
|
||||
timePointIndex: PropTypes.number,
|
||||
numTimePoints: PropTypes.number,
|
||||
dimensionGroupNumber: PropTypes.number,
|
||||
numDimensionGroups: PropTypes.number,
|
||||
label: PropTypes.string,
|
||||
}),
|
||||
};
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Types } from '@ohif/core';
|
||||
|
||||
import MeasurementItem from './MeasurementItem';
|
||||
|
||||
const MeasurementTable = ({
|
||||
data = [],
|
||||
@ -17,9 +14,9 @@ const MeasurementTable = ({
|
||||
const { t } = useTranslation('MeasurementTable');
|
||||
const amount = data.length;
|
||||
|
||||
const itemCustomization = customizationService.getCustomization('MeasurementItem');
|
||||
|
||||
const CustomMeasurementItem = itemCustomization.content;
|
||||
const CustomMeasurementItem = customizationService.getCustomization(
|
||||
'microscopyPanel.measurementItem'
|
||||
);
|
||||
|
||||
const onMeasurementDeleteHandler = ({ uid }) => {
|
||||
const measurement = measurementService.getMeasurement(uid);
|
||||
|
||||
32
yarn.lock
32
yarn.lock
@ -1393,10 +1393,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
|
||||
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
|
||||
|
||||
"@cornerstonejs/adapters@^2.17.2":
|
||||
version "2.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-2.17.2.tgz#a6fd4fc24bd8820faa171d56c3917e73d9da1de7"
|
||||
integrity sha512-XPOdTU1dbPIFSH/51y/nSvcFKXGc5xJyOqhsArjPrhGfhShEqXguvXvvTG01XH4rpX6BXfOuHEf66DLSB9Axxg==
|
||||
"@cornerstonejs/adapters@^2.19.3":
|
||||
version "2.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-2.19.3.tgz#237f4e1adae5f2b77a17426ebbbb601fe65b2bbe"
|
||||
integrity sha512-QuugcUCelTW9bxhO1yewuuf6UHbIufiWMU+plNp40RwR92hgWi1SB9K/gFhtSRxVBqnkbG3Sh6mZRSuS3KcP1A==
|
||||
dependencies:
|
||||
"@babel/runtime-corejs2" "^7.17.8"
|
||||
buffer "^6.0.3"
|
||||
@ -1429,19 +1429,19 @@
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.5.tgz#8690b61a86fa53ef38a70eee9d665a79229517c0"
|
||||
integrity sha512-MZCUy8VG0VG5Nl1l58+g+kH3LujAzLYTfJqkwpWI2gjSrGXnP6lgwyy4GmPRZWVoS40/B1LDNALK905cNWm+sg==
|
||||
|
||||
"@cornerstonejs/core@^2.17.2":
|
||||
version "2.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-2.17.2.tgz#0ce18b3efd94ecbd99778f5d60afe25772528035"
|
||||
integrity sha512-NjQHVXI2bfiNDUv4R0qOsWiL/rdgZMzgPLKsF9nNgji2GS+3wUZsdjXZgd5esD3nIENExZRFWYCCSMVhg+9sxA==
|
||||
"@cornerstonejs/core@^2.19.3":
|
||||
version "2.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-2.19.3.tgz#709eb794f26be6b768964b1546dcdd42a62686af"
|
||||
integrity sha512-yqPFpfzKCNj9U94q1do8oE3adg7+/t+bc4uBHrNPCvbUyOqaWZzentw5+79cj5hhHif2OG0jVNRSPr+kbBBk2Q==
|
||||
dependencies:
|
||||
"@kitware/vtk.js" "32.9.0"
|
||||
comlink "^4.4.1"
|
||||
gl-matrix "^3.4.3"
|
||||
|
||||
"@cornerstonejs/dicom-image-loader@^2.17.2":
|
||||
version "2.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-2.17.2.tgz#8abf7f6467cce265349f452ff43b0a39c1a95726"
|
||||
integrity sha512-SjOSe9RLVoX2Qj6nQEhkuuphiWX4mq67dr5JMcKifEUe8TCBRECpxHcUc7G4QuVkazR7teQLt0JD8h4yqQ5hTQ==
|
||||
"@cornerstonejs/dicom-image-loader@^2.19.3":
|
||||
version "2.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-2.19.3.tgz#10d4fe3bdee3c2f255d7f55c70b59760f26d84f1"
|
||||
integrity sha512-/VTmaDabIqF8lBzPq0yK3yF6TIb3vTEoMeyvXTQWpPG1wjiTRAaYql5uQjCgE1p/xCXVA3Iq+h2rk90HWFu6nA==
|
||||
dependencies:
|
||||
"@cornerstonejs/codec-charls" "^1.2.3"
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2"
|
||||
@ -1452,10 +1452,10 @@
|
||||
pako "^2.0.4"
|
||||
uuid "^9.0.0"
|
||||
|
||||
"@cornerstonejs/tools@^2.17.2":
|
||||
version "2.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-2.17.2.tgz#c2ef6b776dd53915ad35f6336643ade97c220093"
|
||||
integrity sha512-IuS4P3ErxQ8o+SFnpPiZvtvHTA4aN2hwGn5BwuAZScZkBcOgEGAGJ3FBjFcV0fzZBvIORG5KCwUK82HxTQ1b8w==
|
||||
"@cornerstonejs/tools@^2.19.3":
|
||||
version "2.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-2.19.3.tgz#1f4a7045298772184e95043b99ff98ce5ae6686e"
|
||||
integrity sha512-bJFhE2b1B2k8enZT9vZqspLXmSHqCLAOFwib5FWi4/9AtNydVaDBIafAYq/gCXTcF8YcbsUhBhWQL1LU7ejkWg==
|
||||
dependencies:
|
||||
"@types/offscreencanvas" "2019.7.3"
|
||||
comlink "^4.4.1"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user