Compare commits

...
92 Commits
Author SHA1 Message Date
ohif-bot 2e9eb99b62 chore(version): Update package versions [skip ci] 2024-06-14 18:05:58 +00:00
ohif-bot 1ac149a2de chore(version): version.json [skip ci] 2024-06-14 18:05:50 +00:00
Alireza 339299113c fix(cli): version txt had a new line which it should not 2024-06-14 13:39:09 -04:00
ohif-bot 1a57e54f74 chore(version): Update package versions [skip ci] 2024-06-11 17:50:40 +00:00
ohif-bot aebcf962bb chore(version): version.json [skip ci] 2024-06-11 17:50:31 +00:00
Alireza b7ebb0aa8f fix(us): logic for color conversion 2024-06-05 12:12:52 -04:00
Alireza 29c02121df set view 2024-06-03 15:05:38 -04:00
Alireza a3d7f88b03 fix: segmentation creation and segmentation mode viewport rendering (#4193) 2024-06-03 14:31:56 -04:00
Alireza a3d8129089 fix(tmtv): crosshairs should not have viewport indicators (#4197) 2024-06-03 14:31:15 -04:00
Ibrahim b427af622e upgrade cs3d 2024-06-03 10:05:49 -04:00
IbrahimandAlireza 634abf353f fix(rt): dont convert to volume for RTSTRUCT (#4157)
Co-authored-by: Alireza <ar.sedghi@gmail.com>
2024-05-31 11:42:04 -04:00
Ibrahim 471e6a1559 fix(contour): set renderFill to false for contour (#4186) 2024-05-31 11:41:19 -04:00
Alireza 2f811470a8 update yarn lock 2024-05-31 11:41:03 -04:00
Alireza 6262a7f9d4 fix(seg): should be able to navigate outside toolbox and come back later (#4196) 2024-05-31 11:36:16 -04:00
Alireza 53c2740d75 fix(docker): docker build was broken because of imports (#4192) 2024-05-31 11:35:31 -04:00
Ibrahim 85a82fac0e fix(tmtv): side panel crashing when activeToolOptions is not an array (#4189) 2024-05-31 11:35:23 -04:00
Ibrahim 4c8a808a12 feat(types): typed app config (#4171) 2024-05-31 11:34:38 -04:00
Alireza 711c177cf2 chore: Update version.txt to 3.8.1 2024-05-24 11:04:30 -04:00
Alireza f82ab4fda4 update yarn lock 2024-05-24 10:59:10 -04:00
IbrahimandAlireza 2d4e049d8a fix(crosshairs): reset angle, position, and slabthickness for crosshairs when reset viewport tool is used (#4113)
Co-authored-by: Alireza <ar.sedghi@gmail.com>
2024-05-24 10:57:41 -04:00
Alireza 9f5165de47 fix: dicom json for orthanc by Update package versions for @cornerstonejs dependencies (#4165) 2024-05-24 10:57:04 -04:00
Alireza 1b290bdaa1 fix(segmentation): Address issue where segmentation creation failed on layout change (#4153) 2024-05-24 10:55:30 -04:00
Ibrahim 8feef28bff fix(select): utilize react portals for select component (#4144) 2024-05-24 10:53:33 -04:00
Alireza 60d68e3410 update yarn lock 2024-05-16 16:57:29 -04:00
Ibrahim 3539e04019 feat(typings): Enhance typing support with withAppTypes and custom services throughout OHIF (#4090) 2024-05-16 16:54:33 -04:00
Ibrahim c11c3b7e61 fix(tmtv): threshold was crashing the side panel (#4119) 2024-05-16 16:52:45 -04:00
Alireza 4029a8445b chore: Update CircleCI workflow to include approval step before NPM publish for release branches (#4138) 2024-05-16 16:35:42 -04:00
ohif-bot 19bdcbb453 chore(version): Update package versions [skip ci] 2024-04-29 16:49:17 +00:00
ohif-bot 0386c29480 chore(version): version.json [skip ci] 2024-04-29 16:49:07 +00:00
Alireza 1dcdc9dabe feat(v3p8): advanced 3D layouts and 4d data support (#4071) 2024-04-29 12:36:12 -04:00
Alireza feaebd7f61 Merge branch 'release' of github.com:OHIF/Viewers into candidate-3p8-rc-6 2024-04-29 12:16:39 -04:00
ohif-bot 6a8f4b9f38 chore(version): Update package versions [skip ci] 2024-04-29 16:09:24 +00:00
ohif-bot 956fff4e5b chore(version): version.json [skip ci] 2024-04-29 16:09:14 +00:00
Alireza f1a736d193 fix(toolbox): Preserve user-specified tool state and streamline command execution (#4063) 2024-04-29 11:58:03 -04:00
ohif-bot 4784638717 chore(version): Update package versions [skip ci] 2024-04-28 02:01:58 +00:00
ohif-bot 49e82f4756 chore(version): version.json [skip ci] 2024-04-28 02:01:50 +00:00
Ibrahim c09311d3b7 fix(bugs): fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change (#4068) 2024-04-27 21:50:28 -04:00
ohif-bot b4ed80d99b chore(version): Update package versions [skip ci] 2024-04-25 15:57:15 +00:00
ohif-bot c87081d924 chore(version): version.json [skip ci] 2024-04-25 15:57:08 +00:00
Ibrahim f09dfaf911 docs: updates images (#4064) 2024-04-25 11:45:50 -04:00
ohif-bot 11a4ba3c99 chore(version): Update package versions [skip ci] 2024-04-22 19:20:46 +00:00
ohif-bot 56ccb4f7e0 chore(version): version.json [skip ci] 2024-04-22 19:20:37 +00:00
Mateus Freira dos Santos 6ebd2cc7cb fix(viewport-sync): Enable re-sync image slices in a different position when needed (#3984) 2024-04-22 15:08:03 -04:00
ohif-bot 25c01fc66c chore(version): Update package versions [skip ci] 2024-04-22 18:56:10 +00:00
ohif-bot 2ea882e299 chore(version): version.json [skip ci] 2024-04-22 18:56:02 +00:00
Alireza 52a0c59294 fix(viewport-webworker-segmentation): Resolve issues with viewport detection, webworker termination, and segmentation panel layout change (#4059) 2024-04-22 14:43:26 -04:00
Mateus Freira dos Santos 3ec7e51216 fix(vewport): Add missing blendmodes from cornerstonejs (#4055) 2024-04-22 14:33:52 -04:00
ohif-bot 1b366c92ee chore(version): Update package versions [skip ci] 2024-04-22 14:06:09 +00:00
ohif-bot 13d67d90fc chore(version): version.json [skip ci] 2024-04-22 14:06:01 +00:00
Bill Wallace f0ed3fd7b9 fix(hp): Fails to display any layouts in the layout selector if first layout has multiple stages (#4058) 2024-04-22 09:53:10 -04:00
ohif-bot 65d419dd52 chore(version): Update package versions [skip ci] 2024-04-19 19:23:01 +00:00
ohif-bot 4349fc1085 chore(version): version.json [skip ci] 2024-04-19 19:22:53 +00:00
Alireza 8192e348ec feat(tmtv-mode): Add Brush tools and move SUV peak calculation to web worker (#4053) 2024-04-19 15:11:31 -04:00
ohif-bot 8c5ab942b9 chore(version): Update package versions [skip ci] 2024-04-19 03:32:31 +00:00
ohif-bot ab19d9c0a2 chore(version): version.json [skip ci] 2024-04-19 03:32:23 +00:00
Alireza d250d04580 fix(layouts): and fix thumbnail in touch and update migration guide for 3.8 release (#4052) 2024-04-18 23:21:02 -04:00
ohif-bot 28bc8914a8 chore(version): Update package versions [skip ci] 2024-04-18 15:07:19 +00:00
ohif-bot 3952d465dc chore(version): version.json [skip ci] 2024-04-18 15:07:08 +00:00
Pavel Klochkov 1a013909a1 docs(link): Fix wrong link for the components library in the architecture.md (#4045) 2024-04-18 10:53:21 -04:00
ohif-bot 8f42baf36e chore(version): Update package versions [skip ci] 2024-04-18 02:11:12 +00:00
ohif-bot 2633ef7323 chore(version): version.json [skip ci] 2024-04-18 02:11:05 +00:00
Alireza da7c1a5d8c fix(bugs): and replace seriesInstanceUID and seriesInstanceUIDs URL with seriesInstanceUIDs (#4049) 2024-04-17 21:59:47 -04:00
ohif-bot 058da93863 chore(version): Update package versions [skip ci] 2024-04-18 01:58:25 +00:00
ohif-bot bc819409b3 chore(version): version.json [skip ci] 2024-04-18 01:58:17 +00:00
Ibrahim 170bb96983 fix(bugs): enhancements and bug fixes - final (#4048) 2024-04-17 21:47:09 -04:00
ohif-bot c4e6556259 chore(version): Update package versions [skip ci] 2024-04-17 18:54:51 +00:00
ohif-bot ab61cc9b1f chore(version): version.json [skip ci] 2024-04-17 18:54:41 +00:00
Ibrahim 3754c224b4 fix(bugs): enhancements and bug fixes - more (#4043) 2024-04-17 14:42:40 -04:00
ohif-bot d3cdfd8506 chore(version): Update package versions [skip ci] 2024-04-16 15:17:07 +00:00
ohif-bot aa572daa2c chore(version): version.json [skip ci] 2024-04-16 15:16:59 +00:00
Alireza f99a0bfb31 fix(viewport): Reset viewport state and fix CINE looping, thumbnail resolution, and dynamic tool settings (#4037) 2024-04-16 11:04:48 -04:00
ohif-bot a6c6fff43a chore(version): Update package versions [skip ci] 2024-04-16 13:13:50 +00:00
ohif-bot e687384933 chore(version): version.json [skip ci] 2024-04-16 13:13:42 +00:00
Ibrahim e80fc6f477 fix(bugs): enhancements and bug fixes (#4036) 2024-04-16 09:01:06 -04:00
ohif-bot 41a8d105f1 chore(version): Update package versions [skip ci] 2024-04-10 17:55:21 +00:00
ohif-bot 60b2f69334 chore(version): version.json [skip ci] 2024-04-10 17:55:12 +00:00
Alireza df49a653be feat(SM): remove SM measurements from measurement panel (#4022) 2024-04-10 13:44:25 -04:00
ohif-bot 77693ddef4 chore(version): Update package versions [skip ci] 2024-04-10 15:45:03 +00:00
ohif-bot 6a757f69d8 chore(version): version.json [skip ci] 2024-04-10 15:44:55 +00:00
Ibrahim 2b83393f91 fix(general): enhancements and bug fixes (#4018) 2024-04-10 11:34:13 -04:00
ohif-bot df32a05a4d chore(version): Update package versions [skip ci] 2023-10-11 16:59:05 +00:00
ohif-bot e205bf5c4e chore(version): version.json [skip ci] 2023-10-11 16:58:56 +00:00
Alireza 5ddf8a1602 feat(v3p7): segmentation mode and cloud server configuration (#3720) 2023-10-11 12:49:12 -04:00
Alireza 83fccad46b Merge branch 'release' of github.com:OHIF/Viewers into candidate-3p7-rc-5 2023-10-11 12:18:10 -04:00
ohif-bot 72ec0bffb5 chore(version): Update package versions [skip ci] 2023-06-07 20:01:22 +00:00
ohif-bot 82c6c3c353 chore(version): version.json [skip ci] 2023-06-07 20:01:18 +00:00
Alireza 1d38fe30a4 feat(app): modal headers and fix storybook (#3460) 2023-06-07 15:54:08 -04:00
Alireza 666964b6d7 Merge branch 'release' of github.com:OHIF/Viewers into release-fore-newsletter 2023-06-07 13:26:13 -04:00
ohif-bot fa4ee5c559 chore(version): Update package versions [skip ci] 2023-06-07 00:14:02 +00:00
ohif-bot cd58560e9c chore(version): version.json [skip ci] 2023-06-07 00:13:59 +00:00
Alireza 16afa740b6 feat(app): change ohif viewer to ohif app (#3451) 2023-06-06 20:06:31 -04:00
Alireza 6715ad9bd6 chore(build): try to build demo and docs 2023-06-01 08:13:36 -04:00
385 changed files with 9954 additions and 2586 deletions

No files matched your search

+7 -2
View File
@@ -495,13 +495,18 @@ workflows:
- BUILD:
filters:
branches:
only: release
- NPM_PUBLISH:
only: /^release\/.*/
- HOLD_FOR_APPROVAL:
type: approval
requires:
- BUILD
- NPM_PUBLISH:
requires:
- HOLD_FOR_APPROVAL
- DOCKER_RELEASE_PUBLISH:
requires:
- NPM_PUBLISH
###
# Unit and E2E tests have already run for PR_CHECKS
# Re-running should not gain us any confidence here
-25
View File
@@ -1,25 +0,0 @@
# ABOUT:
# https://docs.codecov.io/docs/codecov-yaml
#
#
# COMMIT STATUS:
# https://docs.codecov.io/docs/commit-status
coverage:
status:
project:
default:
threshold: 0.5%
core:
flags: core
threshold: 0.5%
viewer:
flags: viewer
threshold: 0.5%
patch: off
flags:
core:
paths:
- platform/core
viewer:
paths:
- platform/app
+234
View File
@@ -3,6 +3,240 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.8.2](https://github.com/OHIF/Viewers/compare/v3.8.1...v3.8.2) (2024-06-14)
### Bug Fixes
* **cli:** version txt had a new line which it should not ([3392991](https://github.com/OHIF/Viewers/commit/339299113c65b5ce4032b02b5b4043a8968107ed))
## [3.8.1](https://github.com/OHIF/Viewers/compare/v3.8.0...v3.8.1) (2024-06-11)
### Bug Fixes
* **contour:** set renderFill to false for contour ([#4186](https://github.com/OHIF/Viewers/issues/4186)) ([471e6a1](https://github.com/OHIF/Viewers/commit/471e6a1559d983267448058b8e17461f79130c79))
* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([2d4e049](https://github.com/OHIF/Viewers/commit/2d4e049d8a54ca25c9dc02f29f2e53a6968d82e1))
* dicom json for orthanc by Update package versions for [@cornerstonejs](https://github.com/cornerstonejs) dependencies ([#4165](https://github.com/OHIF/Viewers/issues/4165)) ([9f5165d](https://github.com/OHIF/Viewers/commit/9f5165de47ed547919683498cfae87909de94786))
* **docker:** docker build was broken because of imports ([#4192](https://github.com/OHIF/Viewers/issues/4192)) ([53c2740](https://github.com/OHIF/Viewers/commit/53c2740d7589439f5fa6de20baf00b766680ddee))
* **rt:** dont convert to volume for RTSTRUCT ([#4157](https://github.com/OHIF/Viewers/issues/4157)) ([634abf3](https://github.com/OHIF/Viewers/commit/634abf353f02cffec462e341d594741fdefb6f22))
* segmentation creation and segmentation mode viewport rendering ([#4193](https://github.com/OHIF/Viewers/issues/4193)) ([a3d7f88](https://github.com/OHIF/Viewers/commit/a3d7f88b038fdb8c9dbe5358402a159cdadd41c8))
* **segmentation:** Address issue where segmentation creation failed on layout change ([#4153](https://github.com/OHIF/Viewers/issues/4153)) ([1b290bd](https://github.com/OHIF/Viewers/commit/1b290bdaa1a0ba750a4e5f539a51a636de529240))
* **seg:** should be able to navigate outside toolbox and come back later ([#4196](https://github.com/OHIF/Viewers/issues/4196)) ([6262a7f](https://github.com/OHIF/Viewers/commit/6262a7f9d4cb71d2dd9615ccc8fe25c947da65dd))
* **select:** utilize react portals for select component ([#4144](https://github.com/OHIF/Viewers/issues/4144)) ([8feef28](https://github.com/OHIF/Viewers/commit/8feef28bff1ef4547ff744b64ffbbbfdb93d4c72))
* **tmtv:** crosshairs should not have viewport indicators ([#4197](https://github.com/OHIF/Viewers/issues/4197)) ([a3d8129](https://github.com/OHIF/Viewers/commit/a3d81290897397634a246910a30190301066580c))
* **tmtv:** side panel crashing when activeToolOptions is not an array ([#4189](https://github.com/OHIF/Viewers/issues/4189)) ([85a82fa](https://github.com/OHIF/Viewers/commit/85a82fac0e1700eb2b9964078a90aadb1877853b))
* **tmtv:** threshold was crashing the side panel ([#4119](https://github.com/OHIF/Viewers/issues/4119)) ([c11c3b7](https://github.com/OHIF/Viewers/commit/c11c3b7e611af231773c5d52320b8b777c7c717d))
* **us:** logic for color conversion ([b7ebb0a](https://github.com/OHIF/Viewers/commit/b7ebb0aa8f814427045b7d5e7568dc0298ab0973))
### Features
* **types:** typed app config ([#4171](https://github.com/OHIF/Viewers/issues/4171)) ([4c8a808](https://github.com/OHIF/Viewers/commit/4c8a808a12718865501e362ce37c2d2f75a1a687))
* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([3539e04](https://github.com/OHIF/Viewers/commit/3539e040193369b8011254d0c67804ef67d83a6c))
# [3.8.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0) (2024-04-29)
# [3.7.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.7.0) (2023-10-11)
# [3.6.0](https://github.com/OHIF/Viewers/compare/v3.6.0-beta.3...v3.6.0) (2023-06-07)
# [3.5.0](https://github.com/OHIF/Viewers/compare/v3.5.0-beta.1...v3.5.0) (2023-06-07)
### Features
* **app:** change ohif viewer to ohif app ([#3451](https://github.com/OHIF/Viewers/issues/3451)) ([16afa74](https://github.com/OHIF/Viewers/commit/16afa740b60b31037100444ef9311b80ffea2f67))
# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29)
### Bug Fixes
* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f))
# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28)
### Bug Fixes
* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0))
# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22)
### Bug Fixes
* **viewport-sync:** Enable re-sync image slices in a different position when needed ([#3984](https://github.com/OHIF/Viewers/issues/3984)) ([6ebd2cc](https://github.com/OHIF/Viewers/commit/6ebd2cc7cb70cd88fd01dc1e516077f27b201943))
# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22)
### Bug Fixes
* **vewport:** Add missing blendmodes from cornerstonejs ([#4055](https://github.com/OHIF/Viewers/issues/4055)) ([3ec7e51](https://github.com/OHIF/Viewers/commit/3ec7e512169a07506388902acb5b2c118093fa50))
* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951))
# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22)
### Bug Fixes
* **hp:** Fails to display any layouts in the layout selector if first layout has multiple stages ([#4058](https://github.com/OHIF/Viewers/issues/4058)) ([f0ed3fd](https://github.com/OHIF/Viewers/commit/f0ed3fd7b99b0e4e00b261ceb9888ba94726719c))
# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19)
### Features
* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb))
# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19)
### Bug Fixes
* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af))
# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18)
### Bug Fixes
* **bugs:** and replace seriesInstanceUID and seriesInstanceUIDs URL with seriesInstanceUIDs ([#4049](https://github.com/OHIF/Viewers/issues/4049)) ([da7c1a5](https://github.com/OHIF/Viewers/commit/da7c1a5d8c54bfa1d3f97bbc500386bf76e7fd9d))
# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18)
### Bug Fixes
* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02))
# [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17)
### Bug Fixes
* **bugs:** enhancements and bug fixes - more ([#4043](https://github.com/OHIF/Viewers/issues/4043)) ([3754c22](https://github.com/OHIF/Viewers/commit/3754c224b4dab28182adb0a41e37d890942144d8))
# [3.8.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.80...v3.8.0-beta.81) (2024-04-16)
### Bug Fixes
* **viewport:** Reset viewport state and fix CINE looping, thumbnail resolution, and dynamic tool settings ([#4037](https://github.com/OHIF/Viewers/issues/4037)) ([f99a0bf](https://github.com/OHIF/Viewers/commit/f99a0bfb31434aa137bbb3ed1f9eef1dfcc09025))
# [3.8.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.79...v3.8.0-beta.80) (2024-04-16)
### Bug Fixes
* **bugs:** enhancements and bug fixes ([#4036](https://github.com/OHIF/Viewers/issues/4036)) ([e80fc6f](https://github.com/OHIF/Viewers/commit/e80fc6f47708e1d6b1a1e1de438196a4b74ec637))
# [3.8.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.78...v3.8.0-beta.79) (2024-04-10)
### Features
* **SM:** remove SM measurements from measurement panel ([#4022](https://github.com/OHIF/Viewers/issues/4022)) ([df49a65](https://github.com/OHIF/Viewers/commit/df49a653be61a93f6e9fb3663aabe9775c31fd13))
# [3.8.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.77...v3.8.0-beta.78) (2024-04-10)
### Bug Fixes
* **general:** enhancements and bug fixes ([#4018](https://github.com/OHIF/Viewers/issues/4018)) ([2b83393](https://github.com/OHIF/Viewers/commit/2b83393f91cb16ea06821d79d14ff60f80c29c90))
# [3.8.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.76...v3.8.0-beta.77) (2024-04-10)
+9 -6
View File
@@ -41,12 +41,15 @@ provided by the <a href="https://ohif.org/">Open Health Imaging Foundation (OHIF
| | | |
| :-: | :--- | :--- |
| <img src="platform/docs/docs/assets/img/demo-measurements.jpg" alt="Measurement tracking" width="350"/> | Measurement Tracking | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5) |
| <img src="platform/docs/docs/assets/img/demo-segmentation.png" alt="Segmentations" width="350"/> | Labelmap Segmentations | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046) |
| <img src="platform/docs/docs/assets/img/demo-ptct.png" alt="Hanging Protocols" width="350"/> | Fusion and Custom Hanging protocols | [Demo](https://viewer.ohif.org/tmtv?StudyInstanceUIDs=1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463) |
| <img src="platform/docs/docs/assets/img/demo-microscopy.png" alt="Microscopy" width="350"/> | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.275741864483510678566144889372061815320) |
| <img src="platform/docs/docs/assets/img/demo-volumeRendering.png" alt="Volume Rendering" width="350"/> | Volume Rendering | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingprotocolId=mprAnd3DVolumeViewport) |
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-measurements.webp?raw=true" alt="Measurement tracking" width="350"/> | Measurement Tracking | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5) |
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-segmentation.webp?raw=true" alt="Segmentations" width="350"/> | Labelmap Segmentations | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046) |
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-ptct.webp?raw=true" alt="Hanging Protocols" width="350"/> | Fusion and Custom Hanging protocols | [Demo](https://viewer.ohif.org/tmtv?StudyInstanceUIDs=1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463) |
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-volume-rendering.webp?raw=true" alt="Volume Rendering" width="350"/> | Volume Rendering | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingprotocolId=mprAnd3DVolumeViewport) |
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-pdf.webp?raw=true" alt="PDF" width="350"/> | PDF | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.317377619501274872606137091638706705333) |
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-rtstruct.webp?raw=true" alt="RTSTRUCT" width="350"/> | RT STRUCT | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0) |
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-4d.webp?raw=true" alt="4D" width="350"/> | 4D | [Demo](https://viewer.ohif.org/dynamic-volume?StudyInstanceUIDs=2.25.232704420736447710317909004159492840763) |
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-video.webp?raw=true" alt="VIDEO" width="350"/> | Video | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.96975534054447904995905761963464388233) |
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/microscopy.webp?raw=true" alt="microscopy" width="350"/> | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.141277760791347900862109212450152067508) |
## About
+1 -1
View File
@@ -1 +1 @@
4f99244d864427d69be6f863cb7a6a78411adb12
339299113c65b5ce4032b02b5b4043a8968107ed
@@ -3,6 +3,172 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.8.2](https://github.com/OHIF/Viewers/compare/v3.8.1...v3.8.2) (2024-06-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
## [3.8.1](https://github.com/OHIF/Viewers/compare/v3.8.0...v3.8.1) (2024-06-11)
### Bug Fixes
* **rt:** dont convert to volume for RTSTRUCT ([#4157](https://github.com/OHIF/Viewers/issues/4157)) ([634abf3](https://github.com/OHIF/Viewers/commit/634abf353f02cffec462e341d594741fdefb6f22))
### Features
* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([3539e04](https://github.com/OHIF/Viewers/commit/3539e040193369b8011254d0c67804ef67d83a6c))
# [3.8.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0) (2024-04-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.80...v3.8.0-beta.81) (2024-04-16)
### Bug Fixes
* **viewport:** Reset viewport state and fix CINE looping, thumbnail resolution, and dynamic tool settings ([#4037](https://github.com/OHIF/Viewers/issues/4037)) ([f99a0bf](https://github.com/OHIF/Viewers/commit/f99a0bfb31434aa137bbb3ed1f9eef1dfcc09025))
# [3.8.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.79...v3.8.0-beta.80) (2024-04-16)
### Bug Fixes
* **bugs:** enhancements and bug fixes ([#4036](https://github.com/OHIF/Viewers/issues/4036)) ([e80fc6f](https://github.com/OHIF/Viewers/commit/e80fc6f47708e1d6b1a1e1de438196a4b74ec637))
# [3.8.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.78...v3.8.0-beta.79) (2024-04-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.77...v3.8.0-beta.78) (2024-04-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.76...v3.8.0-beta.77) (2024-04-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-rt",
"version": "3.8.0-beta.77",
"version": "3.8.2",
"description": "DICOM RT read workflow",
"author": "OHIF",
"license": "MIT",
@@ -33,10 +33,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.8.0-beta.77",
"@ohif/extension-cornerstone": "3.8.0-beta.77",
"@ohif/extension-default": "3.8.0-beta.77",
"@ohif/i18n": "3.8.0-beta.77",
"@ohif/core": "3.8.2\n",
"@ohif/extension-cornerstone": "3.8.2\n",
"@ohif/extension-default": "3.8.2\n",
"@ohif/i18n": "3.8.2\n",
"prop-types": "^15.6.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
@@ -5,9 +5,13 @@ import loadRTStruct from './loadRTStruct';
const sopClassUids = ['1.2.840.10008.5.1.4.1.1.481.3'];
let loadPromises = {};
const loadPromises = {};
function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager) {
function _getDisplaySetsFromSeries(
instances,
servicesManager: AppTypes.ServicesManager,
extensionManager
) {
const instance = instances[0];
const {
@@ -69,8 +73,8 @@ function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager)
displaySet.referencedSeriesInstanceUID = referencedSeries.SeriesInstanceUID;
displaySet.getReferenceDisplaySet = () => {
const { DisplaySetService } = servicesManager.services;
const referencedDisplaySets = DisplaySetService.getDisplaySetsForSeries(
const { displaySetService } = servicesManager.services;
const referencedDisplaySets = displaySetService.getDisplaySetsForSeries(
displaySet.referencedSeriesInstanceUID
);
@@ -90,7 +94,7 @@ function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager)
return [displaySet];
}
function _load(rtDisplaySet, servicesManager, extensionManager, headers) {
function _load(rtDisplaySet, servicesManager: AppTypes.ServicesManager, extensionManager, headers) {
const { SOPInstanceUID } = rtDisplaySet;
const { segmentationService } = servicesManager.services;
if (
@@ -168,7 +172,10 @@ function _deriveReferencedSeriesSequenceFromFrameOfReferenceSequence(
return ReferencedSeriesSequence;
}
function _segmentationExistsInCache(rtDisplaySet, segmentationService) {
function _segmentationExistsInCache(
rtDisplaySet,
segmentationService: AppTypes.SegmentationService
) {
// Todo: fix this
return false;
// This should be abstracted with the CornerstoneCacheService
@@ -13,7 +13,7 @@ function promptHydrateRT({
toolGroupId = 'default',
preHydrateCallbacks,
hydrateRTDisplaySet,
}) {
}: withAppTypes) {
const { uiViewportDialogService } = servicesManager.services;
return new Promise(async function (resolve, reject) {
@@ -36,7 +36,7 @@ function promptHydrateRT({
});
}
function _askHydrate(uiViewportDialogService, viewportId) {
function _askHydrate(uiViewportDialogService: AppTypes.UIViewportDialogService, viewportId) {
return new Promise(function (resolve, reject) {
const message = 'Do you want to open this Segmentation?';
const actions = [
@@ -57,6 +57,7 @@ function _askHydrate(uiViewportDialogService, viewportId) {
};
uiViewportDialogService.show({
id: 'promptHydrateRT',
viewportId,
type: 'info',
message,
@@ -66,6 +67,11 @@ function _askHydrate(uiViewportDialogService, viewportId) {
uiViewportDialogService.hide();
resolve(RESPONSE.CANCEL);
},
onKeyPress: event => {
if (event.key === 'Enter') {
onSubmit(RESPONSE.HYDRATE_SEG);
}
},
});
});
}
@@ -8,7 +8,7 @@ import createRTToolGroupAndAddTools from '../utils/initRTToolGroup';
const RT_TOOLGROUP_BASE_NAME = 'RTToolGroup';
function OHIFCornerstoneRTViewport(props) {
function OHIFCornerstoneRTViewport(props: withAppTypes) {
const {
children,
displaySets,
@@ -111,12 +111,15 @@ function OHIFCornerstoneRTViewport(props) {
{...props}
displaySets={[referencedDisplaySet, rtDisplaySet]}
viewportOptions={{
viewportType: 'volume',
viewportType: 'stack',
toolGroupId: toolGroupId,
orientation: viewportOptions.orientation,
viewportId: viewportOptions.viewportId,
}}
onElementEnabled={onElementEnabled}
onElementEnabled={evt => {
props.onElementEnabled?.(evt);
onElementEnabled(evt);
}}
onElementDisabled={onElementDisabled}
></Component>
);
@@ -3,6 +3,198 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.8.2](https://github.com/OHIF/Viewers/compare/v3.8.1...v3.8.2) (2024-06-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
## [3.8.1](https://github.com/OHIF/Viewers/compare/v3.8.0...v3.8.1) (2024-06-11)
### Bug Fixes
* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([2d4e049](https://github.com/OHIF/Viewers/commit/2d4e049d8a54ca25c9dc02f29f2e53a6968d82e1))
* dicom json for orthanc by Update package versions for [@cornerstonejs](https://github.com/cornerstonejs) dependencies ([#4165](https://github.com/OHIF/Viewers/issues/4165)) ([9f5165d](https://github.com/OHIF/Viewers/commit/9f5165de47ed547919683498cfae87909de94786))
* **rt:** dont convert to volume for RTSTRUCT ([#4157](https://github.com/OHIF/Viewers/issues/4157)) ([634abf3](https://github.com/OHIF/Viewers/commit/634abf353f02cffec462e341d594741fdefb6f22))
* segmentation creation and segmentation mode viewport rendering ([#4193](https://github.com/OHIF/Viewers/issues/4193)) ([a3d7f88](https://github.com/OHIF/Viewers/commit/a3d7f88b038fdb8c9dbe5358402a159cdadd41c8))
* **segmentation:** Address issue where segmentation creation failed on layout change ([#4153](https://github.com/OHIF/Viewers/issues/4153)) ([1b290bd](https://github.com/OHIF/Viewers/commit/1b290bdaa1a0ba750a4e5f539a51a636de529240))
* **us:** logic for color conversion ([b7ebb0a](https://github.com/OHIF/Viewers/commit/b7ebb0aa8f814427045b7d5e7568dc0298ab0973))
### Features
* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([3539e04](https://github.com/OHIF/Viewers/commit/3539e040193369b8011254d0c67804ef67d83a6c))
# [3.8.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0) (2024-04-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29)
### Bug Fixes
* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f))
# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28)
### Bug Fixes
* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0))
# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22)
### Bug Fixes
* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951))
# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19)
### Features
* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb))
# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19)
### Bug Fixes
* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af))
# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18)
### Bug Fixes
* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02))
# [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.80...v3.8.0-beta.81) (2024-04-16)
### Bug Fixes
* **viewport:** Reset viewport state and fix CINE looping, thumbnail resolution, and dynamic tool settings ([#4037](https://github.com/OHIF/Viewers/issues/4037)) ([f99a0bf](https://github.com/OHIF/Viewers/commit/f99a0bfb31434aa137bbb3ed1f9eef1dfcc09025))
# [3.8.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.79...v3.8.0-beta.80) (2024-04-16)
### Bug Fixes
* **bugs:** enhancements and bug fixes ([#4036](https://github.com/OHIF/Viewers/issues/4036)) ([e80fc6f](https://github.com/OHIF/Viewers/commit/e80fc6f47708e1d6b1a1e1de438196a4b74ec637))
# [3.8.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.78...v3.8.0-beta.79) (2024-04-10)
### Features
* **SM:** remove SM measurements from measurement panel ([#4022](https://github.com/OHIF/Viewers/issues/4022)) ([df49a65](https://github.com/OHIF/Viewers/commit/df49a653be61a93f6e9fb3663aabe9775c31fd13))
# [3.8.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.77...v3.8.0-beta.78) (2024-04-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.76...v3.8.0-beta.77) (2024-04-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-seg",
"version": "3.8.0-beta.77",
"version": "3.8.2",
"description": "DICOM SEG read workflow",
"author": "OHIF",
"license": "MIT",
@@ -33,10 +33,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.8.0-beta.77",
"@ohif/extension-cornerstone": "3.8.0-beta.77",
"@ohif/extension-default": "3.8.0-beta.77",
"@ohif/i18n": "3.8.0-beta.77",
"@ohif/core": "3.8.2\n",
"@ohif/extension-cornerstone": "3.8.2\n",
"@ohif/extension-default": "3.8.2\n",
"@ohif/i18n": "3.8.2\n",
"prop-types": "^15.6.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
@@ -46,9 +46,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^1.70.0",
"@cornerstonejs/core": "^1.70.0",
"@kitware/vtk.js": "30.3.1",
"@cornerstonejs/adapters": "^1.77.6",
"@cornerstonejs/core": "^1.77.6",
"@kitware/vtk.js": "30.4.1",
"react-color": "^2.19.3"
}
}
@@ -1,6 +1,6 @@
import dcmjs from 'dcmjs';
import { createReportDialogPrompt } from '@ohif/extension-default';
import { ServicesManager, Types } from '@ohif/core';
import { Types } from '@ohif/core';
import { cache, metaData } from '@cornerstonejs/core';
import {
segmentation as cornerstoneToolsSegmentation,
@@ -48,7 +48,7 @@ const commandsModule = ({
displaySetService,
viewportGridService,
toolGroupService,
} = (servicesManager as ServicesManager).services;
} = servicesManager.services;
const actions = {
/**
@@ -94,6 +94,7 @@ const commandsModule = ({
updateViewportsForSegmentationRendering({
viewportId,
servicesManager,
displaySet,
loadFn: async () => {
const currentSegmentations = segmentationService.getSegmentations();
const segmentationId = await segmentationService.createSegmentationForDisplaySet(
@@ -213,7 +214,7 @@ const commandsModule = ({
updateViewportsForSegmentationRendering({
viewportId,
servicesManager,
referencedDisplaySetInstanceUID: displaySet.referencedDisplaySetInstanceUID,
displaySet,
loadFn: async () => {
const segDisplaySet = displaySet;
const suppressEvents = false;
@@ -434,30 +435,6 @@ const commandsModule = ({
});
});
},
toggleThresholdRangeAndDynamic() {
const toolGroupIds = toolGroupService.getToolGroupIds();
if (!toolGroupIds) {
return;
}
toolGroupIds.forEach(toolGroupId => {
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
const brushInstances = segmentationUtils.getBrushToolInstances(toolGroup.id);
brushInstances.forEach(({ configuration }) => {
const { activeStrategy, strategySpecificConfiguration } = configuration;
if (activeStrategy.startsWith('THRESHOLD')) {
const thresholdConfig = strategySpecificConfiguration.THRESHOLD;
if (thresholdConfig) {
thresholdConfig.isDynamic = !thresholdConfig.isDynamic;
}
}
});
});
},
};
const definitions = {
@@ -491,9 +468,6 @@ const commandsModule = ({
setThresholdRange: {
commandFn: actions.setThresholdRange,
},
toggleThresholdRangeAndDynamic: {
commandFn: actions.toggleThresholdRangeAndDynamic,
},
};
return {
@@ -10,7 +10,7 @@ const getPanelModule = ({
extensionManager,
configuration,
title,
}) => {
}: withAppTypes) => {
const { customizationService } = servicesManager.services;
const wrappedPanelSegmentation = configuration => {
@@ -8,9 +8,13 @@ import { dicomlabToRGB } from './utils/dicomlabToRGB';
const sopClassUids = ['1.2.840.10008.5.1.4.1.1.66.4'];
let loadPromises = {};
const loadPromises = {};
function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager) {
function _getDisplaySetsFromSeries(
instances,
servicesManager: AppTypes.ServicesManager,
extensionManager
) {
const instance = instances[0];
const {
@@ -95,7 +99,12 @@ function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager)
return [displaySet];
}
function _load(segDisplaySet, servicesManager, extensionManager, headers) {
function _load(
segDisplaySet,
servicesManager: AppTypes.ServicesManager,
extensionManager,
headers
) {
const { SOPInstanceUID } = segDisplaySet;
const { segmentationService } = servicesManager.services;
@@ -137,7 +146,12 @@ function _load(segDisplaySet, servicesManager, extensionManager, headers) {
return loadPromises[SOPInstanceUID];
}
async function _loadSegments({ extensionManager, servicesManager, segDisplaySet, headers }) {
async function _loadSegments({
extensionManager,
servicesManager,
segDisplaySet,
headers,
}: withAppTypes) {
const utilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.common'
);
@@ -212,7 +226,7 @@ async function _loadSegments({ extensionManager, servicesManager, segDisplaySet,
Object.assign(segDisplaySet, results);
}
function _segmentationExists(segDisplaySet, segmentationService) {
function _segmentationExists(segDisplaySet, segmentationService: AppTypes.SegmentationService) {
// This should be abstracted with the CornerstoneCacheService
return segmentationService.getSegmentation(segDisplaySet.displaySetInstanceUID);
}
@@ -1,5 +1,5 @@
export function getToolbarModule({ commandsManager, servicesManager }) {
const { segmentationService, toolGroupService } = servicesManager.services;
export function getToolbarModule({ servicesManager }: withAppTypes) {
const { segmentationService, toolbarService, toolGroupService } = servicesManager.services;
return [
{
name: 'evaluate.cornerstone.segmentation',
@@ -20,12 +20,16 @@ export function getToolbarModule({ commandsManager, servicesManager }) {
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
if (!toolGroup) {
return;
return {
disabled: true,
className: '!text-common-bright ohif-disabled',
disabledText: disabledText ?? 'Not available on the current viewport',
};
}
const toolName = getToolNameForButton(button);
const toolName = toolbarService.getToolNameForButton(button);
if (!toolGroup || !toolGroup.hasTool(toolName)) {
if (!toolGroup.hasTool(toolName) && !toolNames) {
return {
disabled: true,
className: '!text-common-bright ohif-disabled',
@@ -51,23 +55,3 @@ export function getToolbarModule({ commandsManager, servicesManager }) {
},
];
}
// Todo: this is duplicate, we should move it to a shared location
function getToolNameForButton(button) {
const { props } = button;
const commands = props?.commands || button.commands;
const commandsArray = Array.isArray(commands) ? commands : [commands];
const firstCommand = commandsArray[0];
if (typeof firstCommand === 'string') {
// likely not a cornerstone tool
return null;
}
if ('commandOptions' in firstCommand) {
return firstCommand.commandOptions.toolName ?? props?.id ?? button.id;
}
// use id as a fallback for toolName
return props?.id ?? button.id;
}
@@ -17,12 +17,19 @@ export default function PanelSegmentation({
commandsManager,
extensionManager,
configuration,
}) {
const { segmentationService, viewportGridService, uiDialogService } = servicesManager.services;
}: withAppTypes) {
const {
segmentationService,
viewportGridService,
uiDialogService,
displaySetService,
cornerstoneViewportService,
} = servicesManager.services;
const { t } = useTranslation('PanelSegmentation');
const [selectedSegmentationId, setSelectedSegmentationId] = useState(null);
const [addSegmentationClassName, setAddSegmentationClassName] = useState('');
const [segmentationConfiguration, setSegmentationConfiguration] = useState(
segmentationService.getConfiguration()
);
@@ -52,6 +59,64 @@ export default function PanelSegmentation({
};
}, []);
// temporary measure to not allow add segmentation when the selected viewport
// is stack viewport
useEffect(() => {
const handleActiveViewportChange = viewportId => {
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(
viewportId || viewportGridService.getActiveViewportId()
);
if (!displaySetUIDs) {
return;
}
const isReconstructable =
displaySetUIDs?.some(displaySetUID => {
const displaySet = displaySetService.getDisplaySetByUID(displaySetUID);
return displaySet?.isReconstructable;
}) || false;
if (isReconstructable) {
setAddSegmentationClassName('');
} else {
setAddSegmentationClassName('ohif-disabled');
}
};
// Handle initial state
handleActiveViewportChange();
const changedGrid = viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED;
const ready = viewportGridService.EVENTS.VIEWPORTS_READY;
const subsGrid = [];
[ready, changedGrid].forEach(evt => {
const { unsubscribe } = viewportGridService.subscribe(evt, ({ viewportId }) => {
handleActiveViewportChange(viewportId);
});
subsGrid.push(unsubscribe);
});
const changedData = cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED;
const subsData = [];
[changedData].forEach(evt => {
const { unsubscribe } = cornerstoneViewportService.subscribe(evt, () => {
handleActiveViewportChange();
});
subsData.push(unsubscribe);
});
// Clean up
return () => {
subsGrid.forEach(unsub => unsub());
subsData.forEach(unsub => unsub());
};
}, []);
const getToolGroupIds = segmentationId => {
const toolGroupIds = segmentationService.getToolGroupIdsWithSegmentation(segmentationId);
@@ -59,7 +124,9 @@ export default function PanelSegmentation({
};
const onSegmentationAdd = async () => {
commandsManager.runCommand('createEmptySegmentationForViewport');
commandsManager.runCommand('createEmptySegmentationForViewport', {
viewportId: viewportGridService.getActiveViewportId(),
});
};
const onSegmentationClick = (segmentationId: string) => {
@@ -152,6 +219,7 @@ export default function PanelSegmentation({
segmentationService.removeSegment(segmentationId, segmentIndex);
};
// segment hide
const onToggleSegmentVisibility = (segmentationId, segmentIndex) => {
const segmentation = segmentationService.getSegmentation(segmentationId);
const segmentInfo = segmentation.segments[segmentIndex];
@@ -257,6 +325,7 @@ export default function PanelSegmentation({
disableEditing={configuration.disableEditing}
activeSegmentationId={selectedSegmentationId || ''}
onSegmentationAdd={onSegmentationAddWrapper}
addSegmentationClassName={addSegmentationClassName}
showAddSegment={allowAddSegment}
onSegmentationClick={onSegmentationClick}
onSegmentationDelete={onSegmentationDelete}
@@ -10,7 +10,7 @@ import { Enums, cache } from '@cornerstonejs/core';
* @param params.viewportId - ID of the viewport to be updated.
* @param params.loadFn - Function to load the segmentation data.
* @param params.servicesManager - The services manager.
* @param params.referencedDisplaySetInstanceUID - Optional UID for the referenced display set instance.
* @param params.displaySet - the display set.
*
* @returns Returns true upon successful update of viewports for segmentation rendering.
*/
@@ -18,12 +18,12 @@ async function updateViewportsForSegmentationRendering({
viewportId,
loadFn,
servicesManager,
referencedDisplaySetInstanceUID,
displaySet,
}: {
viewportId: string;
loadFn: () => Promise<string>;
servicesManager: any;
referencedDisplaySetInstanceUID?: string;
servicesManager: AppTypes.ServicesManager;
displaySet?: any;
}) {
const { cornerstoneViewportService, segmentationService, viewportGridService } =
servicesManager.services;
@@ -31,13 +31,13 @@ async function updateViewportsForSegmentationRendering({
const viewport = getTargetViewport({ viewportId, viewportGridService });
const targetViewportId = viewport.viewportOptions.viewportId;
referencedDisplaySetInstanceUID =
referencedDisplaySetInstanceUID || viewport?.displaySetInstanceUIDs[0];
const referencedDisplaySetInstanceUID =
displaySet?.referencedDisplaySetInstanceUID || viewport?.displaySetInstanceUIDs[0];
const updatedViewports = getUpdatedViewportsForSegmentation({
servicesManager,
viewportId,
referencedDisplaySetInstanceUID,
servicesManager,
displaySet,
});
// create Segmentation callback which needs to be waited until
@@ -56,7 +56,7 @@ async function updateViewportsForSegmentationRendering({
updatedViewports.forEach(async viewport => {
viewport.viewportOptions = {
...viewport.viewportOptions,
viewportType: 'volume',
viewportType: displaySet?.Modality === 'RTSTRUCT' ? 'stack' : 'volume',
needsRerendering: true,
};
const viewportId = viewport.viewportId;
@@ -66,7 +66,7 @@ async function updateViewportsForSegmentationRendering({
// only run the createSegmentationForVolume for the targetViewportId
// since the rest will get handled by cornerstoneViewportService
if (volumeExists && viewportId === targetViewportId) {
if ((volumeExists || displaySet.Modality === 'RTSTRUCT') && viewportId === targetViewportId) {
await createSegmentationForVolume();
return;
}
@@ -126,19 +126,19 @@ const getTargetViewport = ({ viewportId, viewportGridService }) => {
* @param {Object} params - Parameters for the function.
* @param params.viewportId - the ID of the viewport to be updated.
* @param params.servicesManager - The services manager
* @param params.referencedDisplaySetInstanceUID - Optional UID for the referenced display set instance.
* @param params.displaySet - the display set.
*
* @returns {Array} Returns an array of viewports that require updates for segmentation rendering.
*/
function getUpdatedViewportsForSegmentation({
viewportId,
servicesManager,
referencedDisplaySetInstanceUID,
}) {
displaySet,
}: withAppTypes) {
const { hangingProtocolService, displaySetService, segmentationService, viewportGridService } =
servicesManager.services;
const { viewports } = viewportGridService.getState();
const { viewports, isHangingProtocolLayout } = viewportGridService.getState();
const viewport = getTargetViewport({ viewportId, viewportGridService });
const targetViewportId = viewport.viewportOptions.viewportId;
@@ -146,14 +146,15 @@ function getUpdatedViewportsForSegmentation({
const displaySetInstanceUIDs = viewports.get(targetViewportId).displaySetInstanceUIDs;
const referenceDisplaySetInstanceUID =
referencedDisplaySetInstanceUID || displaySetInstanceUIDs[0];
displaySet?.referencedDisplaySetInstanceUID || displaySetInstanceUIDs[0];
const referencedDisplaySet = displaySetService.getDisplaySetByUID(referenceDisplaySetInstanceUID);
const segmentationFrameOfReferenceUID = referencedDisplaySet.instances[0].FrameOfReferenceUID;
const updatedViewports = hangingProtocolService.getViewportsRequireUpdate(
targetViewportId,
referenceDisplaySetInstanceUID
referenceDisplaySetInstanceUID,
isHangingProtocolLayout
);
viewports.forEach((viewport, viewportId) => {
@@ -174,7 +175,7 @@ function getUpdatedViewportsForSegmentation({
viewportId,
displaySetInstanceUIDs: viewport.displaySetInstanceUIDs,
viewportOptions: {
viewportType: 'volume',
viewportType: displaySet?.Modality === 'RTSTRUCT' ? 'stack' : 'volume',
needsRerendering: true,
},
});
@@ -12,7 +12,7 @@ function promptHydrateSEG({
viewportId,
preHydrateCallbacks,
hydrateSEGDisplaySet,
}) {
}: withAppTypes) {
const { uiViewportDialogService } = servicesManager.services;
return new Promise(async function (resolve, reject) {
@@ -63,6 +63,11 @@ function _askHydrate(uiViewportDialogService, viewportId) {
uiViewportDialogService.hide();
resolve(RESPONSE.CANCEL);
},
onKeyPress: event => {
if (event.key === 'Enter') {
onSubmit(RESPONSE.HYDRATE_SEG);
}
},
});
});
}
@@ -8,7 +8,7 @@ import _getStatusComponent from './_getStatusComponent';
const SEG_TOOLGROUP_BASE_NAME = 'SEGToolGroup';
function OHIFCornerstoneSEGViewport(props) {
function OHIFCornerstoneSEGViewport(props: withAppTypes) {
const {
children,
displaySets,
@@ -25,7 +25,6 @@ function OHIFCornerstoneSEGViewport(props) {
displaySetService,
toolGroupService,
segmentationService,
uiNotificationService,
customizationService,
viewportActionCornersService,
} = servicesManager.services;
@@ -112,7 +111,10 @@ function OHIFCornerstoneSEGViewport(props) {
orientation: viewportOptions.orientation,
viewportId: viewportOptions.viewportId,
}}
onElementEnabled={onElementEnabled}
onElementEnabled={evt => {
props.onElementEnabled?.(evt);
onElementEnabled(evt);
}}
onElementDisabled={onElementDisabled}
></Component>
);
@@ -3,6 +3,193 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.8.2](https://github.com/OHIF/Viewers/compare/v3.8.1...v3.8.2) (2024-06-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
## [3.8.1](https://github.com/OHIF/Viewers/compare/v3.8.0...v3.8.1) (2024-06-11)
### Bug Fixes
* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([2d4e049](https://github.com/OHIF/Viewers/commit/2d4e049d8a54ca25c9dc02f29f2e53a6968d82e1))
* dicom json for orthanc by Update package versions for [@cornerstonejs](https://github.com/cornerstonejs) dependencies ([#4165](https://github.com/OHIF/Viewers/issues/4165)) ([9f5165d](https://github.com/OHIF/Viewers/commit/9f5165de47ed547919683498cfae87909de94786))
* **segmentation:** Address issue where segmentation creation failed on layout change ([#4153](https://github.com/OHIF/Viewers/issues/4153)) ([1b290bd](https://github.com/OHIF/Viewers/commit/1b290bdaa1a0ba750a4e5f539a51a636de529240))
* **us:** logic for color conversion ([b7ebb0a](https://github.com/OHIF/Viewers/commit/b7ebb0aa8f814427045b7d5e7568dc0298ab0973))
### Features
* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([3539e04](https://github.com/OHIF/Viewers/commit/3539e040193369b8011254d0c67804ef67d83a6c))
# [3.8.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0) (2024-04-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29)
### Bug Fixes
* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f))
# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28)
### Bug Fixes
* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0))
# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22)
### Bug Fixes
* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951))
# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19)
### Features
* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb))
# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19)
### Bug Fixes
* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af))
# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18)
### Bug Fixes
* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02))
# [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.80...v3.8.0-beta.81) (2024-04-16)
### Bug Fixes
* **viewport:** Reset viewport state and fix CINE looping, thumbnail resolution, and dynamic tool settings ([#4037](https://github.com/OHIF/Viewers/issues/4037)) ([f99a0bf](https://github.com/OHIF/Viewers/commit/f99a0bfb31434aa137bbb3ed1f9eef1dfcc09025))
# [3.8.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.79...v3.8.0-beta.80) (2024-04-16)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.78...v3.8.0-beta.79) (2024-04-10)
### Features
* **SM:** remove SM measurements from measurement panel ([#4022](https://github.com/OHIF/Viewers/issues/4022)) ([df49a65](https://github.com/OHIF/Viewers/commit/df49a653be61a93f6e9fb3663aabe9775c31fd13))
# [3.8.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.77...v3.8.0-beta.78) (2024-04-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.76...v3.8.0-beta.77) (2024-04-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-sr",
"version": "3.8.0-beta.77",
"version": "3.8.2",
"description": "OHIF extension for an SR Cornerstone Viewport",
"author": "OHIF",
"license": "MIT",
@@ -34,10 +34,10 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.8.0-beta.77",
"@ohif/extension-cornerstone": "3.8.0-beta.77",
"@ohif/extension-measurement-tracking": "3.8.0-beta.77",
"@ohif/ui": "3.8.0-beta.77",
"@ohif/core": "3.8.2\n",
"@ohif/extension-cornerstone": "3.8.2\n",
"@ohif/extension-measurement-tracking": "3.8.2\n",
"@ohif/ui": "3.8.2\n",
"dcmjs": "^0.29.12",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
@@ -46,9 +46,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^1.70.0",
"@cornerstonejs/core": "^1.70.0",
"@cornerstonejs/tools": "^1.70.0",
"@cornerstonejs/adapters": "^1.77.6",
"@cornerstonejs/core": "^1.77.6",
"@cornerstonejs/tools": "^1.77.6",
"classnames": "^2.3.2"
}
}
@@ -40,7 +40,7 @@ const _generateReport = (measurementData, additionalFindingTypes, options = {})
return dataset;
};
const commandsModule = props => {
const commandsModule = (props: withAppTypes) => {
const { servicesManager } = props;
const { customizationService } = servicesManager.services;
const actions = {
@@ -57,7 +57,7 @@ const commandsModule = props => {
const reportBlob = dcmjs.data.datasetToBlob(srDataset);
//Create a URL for the binary.
var objectUrl = URL.createObjectURL(reportBlob);
const objectUrl = URL.createObjectURL(reportBlob);
window.location.assign(objectUrl);
},
@@ -85,7 +85,11 @@ function addInstances(instances: InstanceMetadata[], displaySetService: DisplayS
* @param servicesManager is the services that can be used for creating
* @returns The list of display sets created for the given instances object
*/
function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager) {
function _getDisplaySetsFromSeries(
instances,
servicesManager: AppTypes.ServicesManager,
extensionManager
) {
// If the series has no instances, stop here
if (!instances || !instances.length) {
throw new Error('No instances were provided');
@@ -150,7 +154,7 @@ function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager)
return [displaySet];
}
async function _load(displaySet, servicesManager, extensionManager) {
async function _load(displaySet, servicesManager: AppTypes.ServicesManager, extensionManager) {
const { displaySetService, measurementService } = servicesManager.services;
const dataSources = extensionManager.getDataSources();
const dataSource = dataSources[0];
@@ -223,7 +227,7 @@ function _checkIfCanAddMeasurementsToDisplaySet(
srDisplaySet,
newDisplaySet,
dataSource,
servicesManager
servicesManager: AppTypes.ServicesManager
) {
const { customizationService } = servicesManager.services;
let unloadedMeasurements = srDisplaySet.measurements.filter(
@@ -65,7 +65,7 @@ export default class DICOMSRDisplayTool extends AnnotationTool {
// Filter toolData to only render the data for the active SR.
const filteredAnnotations = annotations.filter(annotation =>
trackingUniqueIdentifiers.includes(annotation.data?.cachedStats?.TrackingUniqueIdentifier)
trackingUniqueIdentifiers.includes(annotation.data?.TrackingUniqueIdentifier)
);
if (!viewport._actors?.size) {
@@ -82,8 +82,7 @@ export default class DICOMSRDisplayTool extends AnnotationTool {
for (let i = 0; i < filteredAnnotations.length; i++) {
const annotation = filteredAnnotations[i];
const annotationUID = annotation.annotationUID;
const { renderableData } = annotation.data.cachedStats;
const { cachedStats } = annotation.data;
const { renderableData, TrackingUniqueIdentifier } = annotation.data;
const { referencedImageId } = annotation.metadata;
styleSpecifier.annotationUID = annotationUID;
@@ -95,7 +94,7 @@ export default class DICOMSRDisplayTool extends AnnotationTool {
const lineWidth = this.getStyle('lineWidth', styleSpecifier, annotation);
const lineDash = this.getStyle('lineDash', styleSpecifier, annotation);
const color =
cachedStats.TrackingUniqueIdentifier === activeTrackingUniqueIdentifier
TrackingUniqueIdentifier === activeTrackingUniqueIdentifier
? 'rgb(0, 255, 0)'
: this.getStyle('color', styleSpecifier, annotation);
@@ -51,10 +51,9 @@ export default function addDICOMSRDisplayAnnotation(measurement, imageId, frameN
handles: {
textBox: measurement.textBox ?? {},
},
cachedStats: {
TrackingUniqueIdentifier: measurementData.TrackingUniqueIdentifier,
renderableData: measurementData.renderableData,
},
cachedStats: {},
TrackingUniqueIdentifier: measurementData.TrackingUniqueIdentifier,
renderableData: measurementData.renderableData,
frameNumber,
},
};
@@ -43,7 +43,7 @@ const convertSites = (codingValues, sites) => {
*
*/
export default function hydrateStructuredReport(
{ servicesManager, extensionManager, appConfig },
{ servicesManager, extensionManager, appConfig }: withAppTypes,
displaySetInstanceUID
) {
const annotationManager = CsAnnotation.state.getAnnotationManager();
@@ -1,19 +1,20 @@
import PropTypes from 'prop-types';
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ServicesManager, ExtensionManager } from '@ohif/core';
import { ExtensionManager } from '@ohif/core';
import { setTrackingUniqueIdentifiersForElement } from '../tools/modules/dicomSRModule';
import { Icon, Tooltip, useViewportGrid, ViewportActionArrows } from '@ohif/ui';
import hydrateStructuredReport from '../utils/hydrateStructuredReport';
import { useAppConfig } from '@state';
import createReferencedImageDisplaySet from '../utils/createReferencedImageDisplaySet';
const MEASUREMENT_TRACKING_EXTENSION_ID = '@ohif/extension-measurement-tracking';
const SR_TOOLGROUP_BASE_NAME = 'SRToolGroup';
function OHIFCornerstoneSRViewport(props) {
function OHIFCornerstoneSRViewport(props: withAppTypes) {
const { children, dataSource, displaySets, viewportOptions, servicesManager, extensionManager } =
props;
@@ -203,7 +204,10 @@ function OHIFCornerstoneSRViewport(props) {
// The positionIds for the viewport aren't meaningful for the child display sets
positionIds: null,
}}
onElementEnabled={onElementEnabled}
onElementEnabled={evt => {
props.onElementEnabled?.(evt);
onElementEnabled(evt);
}}
initialImageIndex={initialImageIndex}
isJumpToMeasurementDisabled={true}
></Component>
@@ -365,7 +369,7 @@ OHIFCornerstoneSRViewport.propTypes = {
viewportLabel: PropTypes.string,
customProps: PropTypes.object,
viewportOptions: PropTypes.object,
servicesManager: PropTypes.instanceOf(ServicesManager).isRequired,
servicesManager: PropTypes.object.isRequired,
extensionManager: PropTypes.instanceOf(ExtensionManager).isRequired,
};
@@ -378,6 +382,10 @@ async function _getViewportReferencedDisplaySetData(
measurementSelected,
displaySetService
) {
const { measurements } = displaySet;
const measurement = measurements[measurementSelected];
const { displaySetInstanceUID } = measurement;
if (!displaySet.keyImageDisplaySet) {
// Create a new display set, and preserve a reference to it here,
// so that it can be re-displayed and shown inside the SR viewport.
@@ -3,6 +3,202 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.8.2](https://github.com/OHIF/Viewers/compare/v3.8.1...v3.8.2) (2024-06-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
## [3.8.1](https://github.com/OHIF/Viewers/compare/v3.8.0...v3.8.1) (2024-06-11)
### Bug Fixes
* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([2d4e049](https://github.com/OHIF/Viewers/commit/2d4e049d8a54ca25c9dc02f29f2e53a6968d82e1))
* dicom json for orthanc by Update package versions for [@cornerstonejs](https://github.com/cornerstonejs) dependencies ([#4165](https://github.com/OHIF/Viewers/issues/4165)) ([9f5165d](https://github.com/OHIF/Viewers/commit/9f5165de47ed547919683498cfae87909de94786))
* **segmentation:** Address issue where segmentation creation failed on layout change ([#4153](https://github.com/OHIF/Viewers/issues/4153)) ([1b290bd](https://github.com/OHIF/Viewers/commit/1b290bdaa1a0ba750a4e5f539a51a636de529240))
* **us:** logic for color conversion ([b7ebb0a](https://github.com/OHIF/Viewers/commit/b7ebb0aa8f814427045b7d5e7568dc0298ab0973))
### Features
* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([3539e04](https://github.com/OHIF/Viewers/commit/3539e040193369b8011254d0c67804ef67d83a6c))
# [3.8.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0) (2024-04-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29)
### Bug Fixes
* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f))
# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28)
### Bug Fixes
* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0))
# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22)
### Bug Fixes
* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951))
# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19)
### Features
* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb))
# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19)
### Bug Fixes
* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af))
# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18)
### Bug Fixes
* **bugs:** and replace seriesInstanceUID and seriesInstanceUIDs URL with seriesInstanceUIDs ([#4049](https://github.com/OHIF/Viewers/issues/4049)) ([da7c1a5](https://github.com/OHIF/Viewers/commit/da7c1a5d8c54bfa1d3f97bbc500386bf76e7fd9d))
# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18)
### Bug Fixes
* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02))
# [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17)
### Bug Fixes
* **bugs:** enhancements and bug fixes - more ([#4043](https://github.com/OHIF/Viewers/issues/4043)) ([3754c22](https://github.com/OHIF/Viewers/commit/3754c224b4dab28182adb0a41e37d890942144d8))
# [3.8.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.80...v3.8.0-beta.81) (2024-04-16)
### Bug Fixes
* **viewport:** Reset viewport state and fix CINE looping, thumbnail resolution, and dynamic tool settings ([#4037](https://github.com/OHIF/Viewers/issues/4037)) ([f99a0bf](https://github.com/OHIF/Viewers/commit/f99a0bfb31434aa137bbb3ed1f9eef1dfcc09025))
# [3.8.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.79...v3.8.0-beta.80) (2024-04-16)
### Bug Fixes
* **bugs:** enhancements and bug fixes ([#4036](https://github.com/OHIF/Viewers/issues/4036)) ([e80fc6f](https://github.com/OHIF/Viewers/commit/e80fc6f47708e1d6b1a1e1de438196a4b74ec637))
# [3.8.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.78...v3.8.0-beta.79) (2024-04-10)
### Features
* **SM:** remove SM measurements from measurement panel ([#4022](https://github.com/OHIF/Viewers/issues/4022)) ([df49a65](https://github.com/OHIF/Viewers/commit/df49a653be61a93f6e9fb3663aabe9775c31fd13))
# [3.8.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.77...v3.8.0-beta.78) (2024-04-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.8.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.76...v3.8.0-beta.77) (2024-04-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dynamic-volume",
"version": "3.8.0-beta.77",
"version": "3.8.2",
"description": "OHIF extension for 4D volumes data",
"author": "OHIF",
"license": "MIT",
@@ -29,11 +29,11 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.8.0-beta.77",
"@ohif/extension-cornerstone": "3.8.0-beta.77",
"@ohif/extension-default": "3.8.0-beta.77",
"@ohif/i18n": "3.8.0-beta.77",
"@ohif/ui": "3.8.0-beta.77",
"@ohif/core": "3.8.2\n",
"@ohif/extension-cornerstone": "3.8.2\n",
"@ohif/extension-default": "3.8.2\n",
"@ohif/i18n": "3.8.2\n",
"@ohif/ui": "3.8.2\n",
"dcmjs": "^0.29.5",
"dicom-parser": "^1.8.21",
"hammerjs": "^2.0.8",
@@ -42,9 +42,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/core": "^1.70.0",
"@cornerstonejs/streaming-image-volume-loader": "^1.70.0",
"@cornerstonejs/tools": "^1.70.0",
"@cornerstonejs/core": "^1.77.6",
"@cornerstonejs/streaming-image-volume-loader": "^1.77.6",
"@cornerstonejs/tools": "^1.77.6",
"classnames": "^2.3.2"
}
}
@@ -265,7 +265,7 @@ function _getInstanceFromSegmentations(segmentations, displaySetService) {
return { seriesMetadata, instance };
}
function updateSegmentationsChartDisplaySet({ servicesManager }): void {
function updateSegmentationsChartDisplaySet({ servicesManager }: withAppTypes): void {
const { segmentationService, displaySetService } = servicesManager.services;
const segmentations = segmentationService.getSegmentations();
const { seriesMetadata, instance } =
@@ -4,7 +4,7 @@ import { cache } from '@cornerstonejs/core';
const LABELMAP = Enums.SegmentationRepresentations.Labelmap;
const commandsModule = ({ commandsManager, servicesManager }) => {
const commandsModule = ({ commandsManager, servicesManager }: withAppTypes) => {
const services = servicesManager.services;
const { displaySetService, viewportGridService, segmentationService } = services;
@@ -43,21 +43,21 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager })
return [
{
name: 'dynamic-volume',
iconName: 'group-layers',
iconName: 'tab-4d',
iconLabel: '4D Workflow',
label: '4D Workflow',
component: wrappedDynamicDataPanel,
},
{
name: 'dynamic-toolbox',
iconName: 'group-layers',
iconName: 'tab-4d',
iconLabel: '4D Workflow',
label: 'Dynamic Toolbox',
component: wrappedDynamicToolbox,
},
{
name: 'dynamic-export',
iconName: 'group-layers',
iconName: 'tab-4d',
iconLabel: '4D Workflow',
label: '4D Workflow',
component: wrappedDynamicExport,
@@ -4,7 +4,7 @@ import PanelGenerateImage from './PanelGenerateImage';
function DynamicDataPanel({ servicesManager, commandsManager }) {
return (
<div
className="flex flex-auto flex-col text-white"
className="flex flex-col text-white"
data-cy={'dynamic-volume-panel'}
>
<PanelGenerateImage
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import { ActionButtons } from '@ohif/ui';
import { useTranslation } from 'react-i18next';
function DynamicExport({ commandsManager, servicesManager, extensionManager }) {
function DynamicExport({ commandsManager, servicesManager, extensionManager }: withAppTypes) {
const { segmentationService } = servicesManager.services;
const { t } = useTranslation('dynamicExport');
@@ -22,9 +22,9 @@ const Header = ({ title, tooltip }) => (
<div className="flex items-center space-x-1">
<Tooltip
content={<div className="text-white">{tooltip}</div>}
position="bottom"
position="bottom-left"
tight={true}
tooltipBoxClassName="max-w-xs"
tooltipBoxClassName="max-w-xs p-2"
>
<Icon
name="info-link"
@@ -88,7 +88,7 @@ const DynamicVolumeControls = ({
className="w-1/2"
onClick={() => {
setComputedView(false);
onDynamicClick();
onDynamicClick?.();
}}
>
4D
@@ -120,7 +120,19 @@ const DynamicVolumeControls = ({
/>
</div>
<div className={`mt-6 flex flex-col ${computedView ? '' : 'ohif-disabled'}`}>
<Header title="Computed Operation" />
<Header
title="Computed Operation"
tooltip={
<div>
Operation Buttons (SUM, AVERAGE, SUBTRACT): Select the mathematical operation to be
applied to the data set.
<br></br> Range Slider: Choose the numeric range within which the operation will be
performed.
<br></br>Generate Button: Execute the chosen operation on the specified range of
data.{' '}
</div>
}
/>
<ButtonGroup
className={`mt-2 w-full `}
separated={true}
@@ -187,7 +199,16 @@ function FrameControls({
return (
<div className={computedView && 'ohif-disabled'}>
<Header title="4D Controls" />
<Header
title="4D Controls"
tooltip={
<div>
Play/Pause Button: Begin or pause the animation of the 4D visualization. <br></br> Frame
Selector: Navigate through individual frames of the 4D data. <br></br> FPS (Frames Per
Second) Selector: Adjust the playback speed of the animation.
</div>
}
/>
<div className="mt-3 flex justify-between">
<IconButton
className="bg-customblue-30 h-[26px] w-[58px] rounded-[4px]"
@@ -8,7 +8,7 @@ import DynamicVolumeControls from './DynamicVolumeControls';
const SOPClassHandlerId = '@ohif/extension-default.sopClassHandlerModule.stack';
export default function PanelGenerateImage({ servicesManager, commandsManager }) {
export default function PanelGenerateImage({ servicesManager, commandsManager }: withAppTypes) {
const { cornerstoneViewportService, viewportGridService, displaySetService } =
servicesManager.services;
@@ -202,7 +202,7 @@ export default function PanelGenerateImage({ servicesManager, commandsManager })
}
const { element } = viewportInfo;
cineService.playClip(element, { framesPerSecond: frameRate });
cineService.playClip(element, { framesPerSecond: frameRate, viewportId: activeViewportId });
};
const handleStop = () => {
+208
View File
@@ -3,6 +3,214 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.8.2](https://github.com/OHIF/Viewers/compare/v3.8.1...v3.8.2) (2024-06-14)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [3.8.1](https://github.com/OHIF/Viewers/compare/v3.8.0...v3.8.1) (2024-06-11)
### Bug Fixes
* **contour:** set renderFill to false for contour ([#4186](https://github.com/OHIF/Viewers/issues/4186)) ([471e6a1](https://github.com/OHIF/Viewers/commit/471e6a1559d983267448058b8e17461f79130c79))
* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([2d4e049](https://github.com/OHIF/Viewers/commit/2d4e049d8a54ca25c9dc02f29f2e53a6968d82e1))
* dicom json for orthanc by Update package versions for [@cornerstonejs](https://github.com/cornerstonejs) dependencies ([#4165](https://github.com/OHIF/Viewers/issues/4165)) ([9f5165d](https://github.com/OHIF/Viewers/commit/9f5165de47ed547919683498cfae87909de94786))
* **rt:** dont convert to volume for RTSTRUCT ([#4157](https://github.com/OHIF/Viewers/issues/4157)) ([634abf3](https://github.com/OHIF/Viewers/commit/634abf353f02cffec462e341d594741fdefb6f22))
* **segmentation:** Address issue where segmentation creation failed on layout change ([#4153](https://github.com/OHIF/Viewers/issues/4153)) ([1b290bd](https://github.com/OHIF/Viewers/commit/1b290bdaa1a0ba750a4e5f539a51a636de529240))
* **us:** logic for color conversion ([b7ebb0a](https://github.com/OHIF/Viewers/commit/b7ebb0aa8f814427045b7d5e7568dc0298ab0973))
### Features
* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([3539e04](https://github.com/OHIF/Viewers/commit/3539e040193369b8011254d0c67804ef67d83a6c))
# [3.8.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0) (2024-04-29)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29)
### Bug Fixes
* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f))
# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28)
### Bug Fixes
* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0))
# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22)
### Bug Fixes
* **viewport-sync:** Enable re-sync image slices in a different position when needed ([#3984](https://github.com/OHIF/Viewers/issues/3984)) ([6ebd2cc](https://github.com/OHIF/Viewers/commit/6ebd2cc7cb70cd88fd01dc1e516077f27b201943))
# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22)
### Bug Fixes
* **vewport:** Add missing blendmodes from cornerstonejs ([#4055](https://github.com/OHIF/Viewers/issues/4055)) ([3ec7e51](https://github.com/OHIF/Viewers/commit/3ec7e512169a07506388902acb5b2c118093fa50))
* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951))
# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22)
### Bug Fixes
* **hp:** Fails to display any layouts in the layout selector if first layout has multiple stages ([#4058](https://github.com/OHIF/Viewers/issues/4058)) ([f0ed3fd](https://github.com/OHIF/Viewers/commit/f0ed3fd7b99b0e4e00b261ceb9888ba94726719c))
# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19)
### Features
* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb))
# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19)
### Bug Fixes
* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af))
# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18)
### Bug Fixes
* **bugs:** and replace seriesInstanceUID and seriesInstanceUIDs URL with seriesInstanceUIDs ([#4049](https://github.com/OHIF/Viewers/issues/4049)) ([da7c1a5](https://github.com/OHIF/Viewers/commit/da7c1a5d8c54bfa1d3f97bbc500386bf76e7fd9d))
# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18)
### Bug Fixes
* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02))
# [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17)
### Bug Fixes
* **bugs:** enhancements and bug fixes - more ([#4043](https://github.com/OHIF/Viewers/issues/4043)) ([3754c22](https://github.com/OHIF/Viewers/commit/3754c224b4dab28182adb0a41e37d890942144d8))
# [3.8.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.80...v3.8.0-beta.81) (2024-04-16)
### Bug Fixes
* **viewport:** Reset viewport state and fix CINE looping, thumbnail resolution, and dynamic tool settings ([#4037](https://github.com/OHIF/Viewers/issues/4037)) ([f99a0bf](https://github.com/OHIF/Viewers/commit/f99a0bfb31434aa137bbb3ed1f9eef1dfcc09025))
# [3.8.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.79...v3.8.0-beta.80) (2024-04-16)
### Bug Fixes
* **bugs:** enhancements and bug fixes ([#4036](https://github.com/OHIF/Viewers/issues/4036)) ([e80fc6f](https://github.com/OHIF/Viewers/commit/e80fc6f47708e1d6b1a1e1de438196a4b74ec637))
# [3.8.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.78...v3.8.0-beta.79) (2024-04-10)
### Features
* **SM:** remove SM measurements from measurement panel ([#4022](https://github.com/OHIF/Viewers/issues/4022)) ([df49a65](https://github.com/OHIF/Viewers/commit/df49a653be61a93f6e9fb3663aabe9775c31fd13))
# [3.8.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.77...v3.8.0-beta.78) (2024-04-10)
### Bug Fixes
* **general:** enhancements and bug fixes ([#4018](https://github.com/OHIF/Viewers/issues/4018)) ([2b83393](https://github.com/OHIF/Viewers/commit/2b83393f91cb16ea06821d79d14ff60f80c29c90))
# [3.8.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.76...v3.8.0-beta.77) (2024-04-10)
**Note:** Version bump only for package @ohif/extension-cornerstone
+9 -9
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone",
"version": "3.8.0-beta.77",
"version": "3.8.2",
"description": "OHIF extension for Cornerstone",
"author": "OHIF",
"license": "MIT",
@@ -38,10 +38,10 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2",
"@cornerstonejs/codec-openjph": "^2.4.2",
"@cornerstonejs/dicom-image-loader": "^1.70.0",
"@cornerstonejs/dicom-image-loader": "^1.77.6",
"@icr/polyseg-wasm": "^0.4.0",
"@ohif/core": "3.8.0-beta.77",
"@ohif/ui": "3.8.0-beta.77",
"@ohif/core": "3.8.2\n",
"@ohif/ui": "3.8.2\n",
"dcmjs": "^0.29.12",
"dicom-parser": "^1.8.21",
"hammerjs": "^2.0.8",
@@ -55,12 +55,12 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^1.70.0",
"@cornerstonejs/core": "^1.70.0",
"@cornerstonejs/streaming-image-volume-loader": "^1.70.0",
"@cornerstonejs/tools": "^1.70.0",
"@cornerstonejs/adapters": "^1.77.6",
"@cornerstonejs/core": "^1.77.6",
"@cornerstonejs/streaming-image-volume-loader": "^1.77.6",
"@cornerstonejs/tools": "^1.77.6",
"@icr/polyseg-wasm": "^0.4.0",
"@kitware/vtk.js": "30.3.1",
"@kitware/vtk.js": "30.4.1",
"html2canvas": "^1.4.1",
"lodash.debounce": "4.0.8",
"lodash.merge": "^4.6.2",
@@ -10,7 +10,7 @@ import {
utilities as csUtils,
} from '@cornerstonejs/core';
import { MeasurementService } from '@ohif/core';
import { Notification, useViewportDialog, Types as UITypes, AllInOneMenu } from '@ohif/ui';
import { Notification, useViewportDialog, AllInOneMenu } from '@ohif/ui';
import { IStackViewport, IVolumeViewport } from '@cornerstonejs/core/dist/esm/types';
import { setEnabledElement } from '../state';
@@ -18,7 +18,6 @@ import { setEnabledElement } from '../state';
import './OHIFCornerstoneViewport.css';
import CornerstoneOverlays from './Overlays/CornerstoneOverlays';
import getSOPInstanceAttributes from '../utils/measurementServiceMappings/utils/getSOPInstanceAttributes';
import CornerstoneServices from '../types/CornerstoneServices';
import CinePlayer from '../components/CinePlayer';
import { Types } from '@ohif/core';
@@ -100,7 +99,7 @@ function areEqual(prevProps, nextProps) {
// 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.
const OHIFCornerstoneViewport = React.memo(props => {
const OHIFCornerstoneViewport = React.memo((props: withAppTypes) => {
const {
displaySets,
dataSource,
@@ -108,21 +107,34 @@ const OHIFCornerstoneViewport = React.memo(props => {
displaySetOptions,
servicesManager,
onElementEnabled,
// eslint-disable-next-line react/prop-types
onElementDisabled,
isJumpToMeasurementDisabled,
// Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation
// of the imageData in the OHIFCornerstoneViewport. This prop is used
// to set the initial state of the viewport's first image to render
// eslint-disable-next-line react/prop-types
initialImageIndex,
onReady,
// if the viewport is part of a hanging protocol layout
// we should not really rely on the old synchronizers and
// you see below we only rehydrate the synchronizers if the viewport
// is not part of the hanging protocol layout. HPs should
// define their own synchronizers. Since the synchronizers are
// viewportId dependent and
// eslint-disable-next-line react/prop-types
isHangingProtocolLayout,
} = props;
const viewportId = viewportOptions.viewportId;
if (!viewportId) {
throw new Error('Viewport ID is required');
}
// Since we only have support for dynamic data in volume viewports, we should
// handle this case here and set the viewportType to volume if any of the
// displaySets are dynamic volumes
viewportOptions.viewportType = displaySets.some(ds => ds.isDynamicVolume)
viewportOptions.viewportType = displaySets.some(ds => ds.isDynamicVolume && ds.isReconstructable)
? 'volume'
: viewportOptions.viewportType;
@@ -142,8 +154,7 @@ const OHIFCornerstoneViewport = React.memo(props => {
viewportGridService,
stateSyncService,
viewportActionCornersService,
customizationService,
} = servicesManager.services as CornerstoneServices;
} = servicesManager.services;
const [viewportDialogState] = useViewportDialog();
// useCallback for scroll bar height calculation
@@ -196,14 +207,13 @@ const OHIFCornerstoneViewport = React.memo(props => {
const synchronizersStore = stateSyncService.getState().synchronizersStore;
if (synchronizersStore?.[viewportId]?.length) {
if (synchronizersStore?.[viewportId]?.length && !isHangingProtocolLayout) {
// If the viewport used to have a synchronizer, re apply it again
_rehydrateSynchronizers(synchronizersStore, viewportId, syncGroupService);
}
if (onElementEnabled) {
onElementEnabled(evt);
onReady?.(evt);
}
},
[viewportId, onElementEnabled, toolGroupService]
@@ -444,6 +454,7 @@ const OHIFCornerstoneViewport = React.memo(props => {
actions={viewportDialogState.actions}
onSubmit={viewportDialogState.onSubmit}
onOutsideClick={viewportDialogState.onOutsideClick}
onKeyPress={viewportDialogState.onKeyPress}
/>
)}
</div>
@@ -476,7 +487,10 @@ function _subscribeToJumpToMeasurementEvents(
cornerstoneViewportService.getViewportIdToJump(
jumpId,
measurement.displaySetInstanceUID,
{ referencedImageId: measurement.referencedImageId }
{
referencedImageId:
measurement.referencedImageId || measurement.metadata?.referencedImageId,
}
);
}
if (cacheJumpToMeasurementEvent.cornerstoneViewport !== viewportId) {
@@ -585,6 +599,9 @@ function _jumpToMeasurement(
i => i.SOPInstanceUID === SOPInstanceUID
);
// the index is reversed in the volume viewport
// imageIdIndex = referencedDisplaySet.images.length - 1 - imageIdIndex;
const { viewPlaneNormal: viewportViewPlane } = viewport.getCamera();
// should compare abs for both planes since the direction can be flipped
@@ -5,7 +5,7 @@ import CustomizableViewportOverlay from './CustomizableViewportOverlay';
import ViewportOrientationMarkers from './ViewportOrientationMarkers';
import ViewportImageSliceLoadingIndicator from './ViewportImageSliceLoadingIndicator';
function CornerstoneOverlays(props) {
function CornerstoneOverlays(props: withAppTypes) {
const { viewportId, element, scrollbarHeight, servicesManager } = props;
const { cornerstoneViewportService } = servicesManager.services;
const [imageSliceData, setImageSliceData] = useState({
@@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
import { metaData, Enums, utilities } from '@cornerstonejs/core';
import { ImageSliceData } from '@cornerstonejs/core/dist/esm/types';
import { ViewportOverlay } from '@ohif/ui';
import { ServicesManager } from '@ohif/core';
import { InstanceMetadata } from '@ohif/core/src/types';
import { formatPN, formatDICOMDate, formatDICOMTime, formatNumberPrecision } from './utils';
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
@@ -19,7 +18,7 @@ interface OverlayItemProps {
element: HTMLElement;
viewportData: ViewportData;
imageSliceData: ImageSliceData;
servicesManager: ServicesManager;
servicesManager: AppTypes.ServicesManager;
viewportId: string;
instance: InstanceMetadata;
customization: any;
@@ -59,7 +58,7 @@ function CustomizableViewportOverlay({
viewportData: ViewportData;
imageSliceData: ImageSliceData;
viewportId: string;
servicesManager: ServicesManager;
servicesManager: AppTypes.ServicesManager;
}) {
const { cornerstoneViewportService, customizationService, toolGroupService } =
servicesManager.services;
@@ -318,7 +317,7 @@ function CustomizableViewportOverlay({
function _getViewportInstances(viewportData) {
const imageIds = [];
if (viewportData.viewportType === Enums.ViewportType.STACK) {
imageIds.push(viewportData.data.imageIds[0]);
imageIds.push(viewportData.data[0].imageIds[0]);
} else if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC) {
const volumes = viewportData.data;
volumes.forEach(volume => {
@@ -358,7 +357,7 @@ const getInstanceNumber = (viewportData, viewportId, imageIndex, cornerstoneView
};
function _getInstanceNumberFromStack(viewportData, imageIndex) {
const imageIds = viewportData.data.imageIds;
const imageIds = viewportData.data[0].imageIds;
const imageId = imageIds[imageIndex];
if (!imageId) {
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import { Enums, Types, utilities } from '@cornerstonejs/core';
import { utilities as csToolsUtils } from '@cornerstonejs/tools';
import { ImageScrollbar } from '@ohif/ui';
import { ServicesManger } from '@ohif/core';
function CornerstoneImageScrollbar({
viewportData,
@@ -13,8 +12,8 @@ function CornerstoneImageScrollbar({
setImageSliceData,
scrollbarHeight,
servicesManager,
}) {
const { cineService, cornerstoneViewportService } = (servicesManager as ServicesManger).services;
}: withAppTypes) {
const { cineService, cornerstoneViewportService } = servicesManager.services;
const onImageScrollbarChange = (imageIndex, viewportId) => {
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
@@ -23,7 +22,7 @@ function CornerstoneImageScrollbar({
if (isCineEnabled) {
// on image scrollbar change, stop the CINE if it is playing
cineService.stopClip(element);
cineService.stopClip(element, { viewportId });
cineService.setCine({ id: viewportId, isPlaying: false });
}
@@ -49,7 +48,7 @@ function CornerstoneImageScrollbar({
setImageSliceData({
imageIndex: imageIndex,
numberOfSlices: viewportData.data.imageIds.length,
numberOfSlices: viewportData.data[0].imageIds.length,
});
return;
@@ -79,7 +78,7 @@ function CornerstoneImageScrollbar({
// find the index of imageId in the imageIds
setImageSliceData({
imageIndex: newImageIdIndex,
numberOfSlices: viewportData.data.imageIds.length,
numberOfSlices: viewportData.data[0].imageIds.length,
});
};
@@ -22,7 +22,7 @@ function ViewportOrientationMarkers({
viewportId,
servicesManager,
orientationMarkers = ['top', 'left'],
}) {
}: withAppTypes) {
// Rotation is in degrees
const [rotation, setRotation] = useState(0);
const [flipHorizontal, setFlipHorizontal] = useState(false);
@@ -67,7 +67,7 @@ function ViewportOrientationMarkers({
let rowCosines, columnCosines;
if (viewportData.viewportType === 'stack') {
const imageIndex = imageSliceData.imageIndex;
const imageId = viewportData.data.imageIds?.[imageIndex];
const imageId = viewportData.data[0].imageIds?.[imageIndex];
// Workaround for below TODO stub
if (!imageId) {
+51 -44
View File
@@ -20,7 +20,6 @@ import { callLabelAutocompleteDialog, showLabelAnnotationPopup } from './utils/c
import toggleImageSliceSync from './utils/imageSliceSync/toggleImageSliceSync';
import { getFirstAnnotationSelected } from './utils/measurementServiceMappings/utils/selection';
import getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement';
import { CornerstoneServices } from './types';
import toggleVOISliceSync from './utils/toggleVOISliceSync';
const toggleSyncFunctions = {
@@ -44,13 +43,19 @@ function commandsModule({
colorbarService,
hangingProtocolService,
syncGroupService,
} = servicesManager.services as CornerstoneServices;
} = servicesManager.services;
const { measurementServiceSource } = this;
function _getActiveViewportEnabledElement() {
return getActiveViewportEnabledElement(viewportGridService);
}
function _getActiveViewportToolGroupId() {
const viewport = _getActiveViewportEnabledElement();
return toolGroupService.getToolGroupForViewport(viewport.id);
}
const actions = {
/**
* Generates the selector props for the context menu, specific to
@@ -275,16 +280,16 @@ function commandsModule({
actions.setViewportWindowLevel({ ...props, viewportId });
},
setToolEnabled: ({ toolName, toggle }) => {
setToolEnabled: ({ toolName, toggle, toolGroupId }) => {
const { viewports } = viewportGridService.getState();
if (!viewports.size) {
return;
}
const toolGroup = toolGroupService.getToolGroup(null);
const toolGroup = toolGroupService.getToolGroup(toolGroupId ?? null);
if (!toolGroup) {
if (!toolGroup || !toolGroup.hasTool(toolName)) {
return;
}
@@ -293,51 +298,56 @@ function commandsModule({
// Toggle the tool's state only if the toggle is true
if (toggle) {
toolIsEnabled ? toolGroup.setToolDisabled(toolName) : toolGroup.setToolEnabled(toolName);
} else {
toolGroup.setToolEnabled(toolName);
}
const renderingEngine = cornerstoneViewportService.getRenderingEngine();
renderingEngine.render();
},
toggleEnabledDisabledToolbar({ value, itemId, toolGroupIds = [] }) {
toggleEnabledDisabledToolbar({ value, itemId, toolGroupId }) {
const toolName = itemId || value;
toolGroupIds = toolGroupIds.length ? toolGroupIds : toolGroupService.getToolGroupIds();
toolGroupIds.forEach(toolGroupId => {
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
if (!toolGroup || !toolGroup.hasTool(toolName)) {
return;
}
toolGroupId = toolGroupId ?? _getActiveViewportToolGroupId();
const toolIsEnabled = toolGroup.getToolOptions(toolName).mode === Enums.ToolModes.Enabled;
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
if (!toolGroup || !toolGroup.hasTool(toolName)) {
return;
}
toolIsEnabled ? toolGroup.setToolDisabled(toolName) : toolGroup.setToolEnabled(toolName);
});
const toolIsEnabled = toolGroup.getToolOptions(toolName).mode === Enums.ToolModes.Enabled;
toolIsEnabled ? toolGroup.setToolDisabled(toolName) : toolGroup.setToolEnabled(toolName);
},
toggleActiveDisabledToolbar({ value, itemId, toolGroupIds = [] }) {
toggleActiveDisabledToolbar({ value, itemId, toolGroupId }) {
const toolName = itemId || value;
toolGroupIds = toolGroupIds.length ? toolGroupIds : toolGroupService.getToolGroupIds();
toolGroupIds.forEach(toolGroupId => {
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
if (!toolGroup || !toolGroup.hasTool(toolName)) {
return;
}
toolGroupId = toolGroupId ?? _getActiveViewportToolGroupId();
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
if (!toolGroup || !toolGroup.hasTool(toolName)) {
return;
}
const toolIsActive = toolGroup.getToolOptions(toolName).mode === Enums.ToolModes.Active;
const toolIsActive = [
Enums.ToolModes.Active,
Enums.ToolModes.Enabled,
Enums.ToolModes.Passive,
].includes(toolGroup.getToolOptions(toolName).mode);
toolIsActive
? toolGroup.setToolDisabled(toolName)
: actions.setToolActive({ toolName, toolGroupId });
toolIsActive
? toolGroup.setToolDisabled(toolName)
: actions.setToolActive({ toolName, toolGroupId });
// we should set the previously active tool to active after we set the
// current tool disabled
if (toolIsActive) {
const prevToolName = toolGroup.getPrevActivePrimaryToolName();
// we should set the previously active tool to active after we set the
// current tool disabled
if (toolIsActive) {
const prevToolName = toolGroup.getPrevActivePrimaryToolName();
if (prevToolName !== toolName) {
actions.setToolActive({ toolName: prevToolName, toolGroupId });
}
});
}
},
setToolActiveToolbar: ({ value, itemId, toolGroupIds = [] }) => {
setToolActiveToolbar: ({ value, itemId, toolName, toolGroupIds = [] }) => {
// Sometimes it is passed as value (tools with options), sometimes as itemId (toolbar buttons)
const toolName = itemId || value;
toolName = toolName || itemId || value;
toolGroupIds = toolGroupIds.length ? toolGroupIds : toolGroupService.getToolGroupIds();
@@ -404,6 +414,7 @@ function commandsModule({
onClose: uiModalService.hide,
cornerstoneViewportService,
},
containerDimensions: 'w-[70%] max-w-[900px]',
});
}
},
@@ -439,11 +450,9 @@ function commandsModule({
const { viewport } = enabledElement;
if (viewport instanceof StackViewport) {
const { flipHorizontal } = viewport.getCamera();
viewport.setCamera({ flipHorizontal: !flipHorizontal });
viewport.render();
}
const { flipHorizontal } = viewport.getCamera();
viewport.setCamera({ flipHorizontal: !flipHorizontal });
viewport.render();
},
flipViewportVertical: () => {
const enabledElement = _getActiveViewportEnabledElement();
@@ -454,11 +463,9 @@ function commandsModule({
const { viewport } = enabledElement;
if (viewport instanceof StackViewport) {
const { flipVertical } = viewport.getCamera();
viewport.setCamera({ flipVertical: !flipVertical });
viewport.render();
}
const { flipVertical } = viewport.getCamera();
viewport.setCamera({ flipVertical: !flipVertical });
viewport.render();
},
invertViewport: ({ element }) => {
let enabledElement;
@@ -817,7 +824,7 @@ function commandsModule({
}
crosshairInstances.forEach(ins => {
ins.resetCrosshairs();
ins?.resetCrosshairs();
});
},
};
@@ -1,14 +1,9 @@
import React, { ReactElement } from 'react';
import PropTypes from 'prop-types';
import { ServicesManager } from '@ohif/core';
import { useViewportGrid } from '@ohif/ui';
import ViewportWindowLevel from '../ViewportWindowLevel/ViewportWindowLevel';
const ActiveViewportWindowLevel = ({
servicesManager,
}: {
servicesManager: ServicesManager;
}): ReactElement => {
const ActiveViewportWindowLevel = ({ servicesManager }: withAppTypes): ReactElement => {
const [viewportGrid] = useViewportGrid();
const { activeViewportId } = viewportGrid;
@@ -25,7 +20,7 @@ const ActiveViewportWindowLevel = ({
};
ActiveViewportWindowLevel.propTypes = {
servicesManager: PropTypes.instanceOf(ServicesManager),
servicesManager: PropTypes.object.isRequired,
};
export default ActiveViewportWindowLevel;
@@ -4,7 +4,14 @@ import { Enums, eventTarget, cache } from '@cornerstonejs/core';
import { Enums as StreamingEnums } from '@cornerstonejs/streaming-image-volume-loader';
import { useAppConfig } from '@state';
function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
function WrappedCinePlayer({
enabledVPElement,
viewportId,
servicesManager,
}: withAppTypes<{
enabledVPElement: HTMLElement;
viewportId: string;
}>) {
const { customizationService, displaySetService, viewportGridService } = servicesManager.services;
const [{ isCineEnabled, cines }, cineService] = useCine();
const [newStackFrameRate, setNewStackFrameRate] = useState(24);
@@ -21,7 +28,7 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
const validFrameRate = Math.max(frameRate, 1);
return isPlaying
? cineService.playClip(enabledVPElement, { framesPerSecond: validFrameRate })
? cineService.playClip(enabledVPElement, { framesPerSecond: validFrameRate, viewportId })
: cineService.stopClip(enabledVPElement);
};
@@ -66,7 +73,7 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
}
cineService.setCine({ id: viewportId, isPlaying, frameRate });
setNewStackFrameRate(frameRate);
}, [displaySetService, viewportId, viewportGridService, cines, isCineEnabled]);
}, [displaySetService, viewportId, viewportGridService, cines, isCineEnabled, enabledVPElement]);
useEffect(() => {
isMountedRef.current = true;
@@ -78,6 +85,14 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
};
}, [isCineEnabled, newDisplaySetHandler]);
useEffect(() => {
if (!isCineEnabled) {
return;
}
cineHandler();
}, [isCineEnabled, cineHandler, enabledVPElement]);
/**
* Use effect for handling new display set
*/
@@ -112,7 +127,7 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
cineHandler();
return () => {
cineService.stopClip(enabledVPElement);
cineService.stopClip(enabledVPElement, { viewportId });
};
}, [cines, viewportId, cineService, enabledVPElement, cineHandler]);
@@ -1,7 +1,6 @@
import React, { useEffect, useCallback, useState, ReactElement } from 'react';
import PropTypes from 'prop-types';
import debounce from 'lodash.debounce';
import { ServicesManager } from '@ohif/core';
import { PanelSection, WindowLevel } from '@ohif/ui';
import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps';
import { Enums, eventTarget, cache as cs3DCache, utilities as csUtils } from '@cornerstonejs/core';
@@ -12,10 +11,9 @@ const { Events } = Enums;
const ViewportWindowLevel = ({
servicesManager,
viewportId,
}: {
servicesManager: ServicesManager;
}: withAppTypes<{
viewportId: string;
}): ReactElement => {
}>): ReactElement => {
const { cornerstoneViewportService } = servicesManager.services;
const [windowLevels, setWindowLevels] = useState([]);
const [cachedHistograms, setCachedHistograms] = useState({});
@@ -380,7 +378,7 @@ const ViewportWindowLevel = ({
};
ViewportWindowLevel.propTypes = {
servicesManager: PropTypes.instanceOf(ServicesManager),
servicesManager: PropTypes.object.isRequired,
viewportId: PropTypes.string.isRequired,
};
@@ -2,10 +2,12 @@ import { getWebWorkerManager } from '@cornerstonejs/core';
const workerManager = getWebWorkerManager();
const options = {
// maxWorkerInstances: 1,
// overwrite: false
autoTerminationOnIdle: 1000,
const WorkerOptions = {
maxWorkerInstances: 1,
autoTerminateOnIdle: {
enabled: true,
idleTimeThreshold: 1000,
},
};
// Register the task
@@ -15,9 +17,9 @@ const workerFn = () => {
});
};
workerManager.registerWorker('histogram-worker', workerFn, options);
const getViewportVolumeHistogram = async (viewport, volume, options?) => {
workerManager.registerWorker('histogram-worker', workerFn, WorkerOptions);
if (!volume?.loadStatus.loaded) {
return undefined;
}
@@ -8,10 +8,10 @@ export function setViewportColorbar(
viewportId,
displaySets,
commandsManager,
serviceManager,
servicesManager: AppTypes.ServicesManager,
colorbarOptions
) {
const { cornerstoneViewportService } = serviceManager.services;
const { cornerstoneViewportService } = servicesManager.services;
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
@@ -59,10 +59,10 @@ export function Colorbar({
viewportId,
displaySets,
commandsManager,
serviceManager,
servicesManager,
colorbarProperties,
}: ColorbarProps): ReactElement {
const { colorbarService } = serviceManager.services;
}: withAppTypes<ColorbarProps>): ReactElement {
const { colorbarService } = servicesManager.services;
const {
width: colorbarWidth,
colorbarTickPosition,
@@ -73,7 +73,7 @@ export function Colorbar({
const [showColorbar, setShowColorbar] = useState(colorbarService.hasColorbar(viewportId));
const onSetColorbar = useCallback(() => {
setViewportColorbar(viewportId, displaySets, commandsManager, serviceManager, {
setViewportColorbar(viewportId, displaySets, commandsManager, servicesManager, {
viewportId,
colormaps,
ticks: {
@@ -102,6 +102,7 @@ export function Colorbar({
return (
<div className="all-in-one-menu-item flex w-full justify-center">
<div className="mr-2 w-[28px]"></div>
<SwitchButton
label="Display Color bar"
checked={showColorbar}
@@ -8,9 +8,9 @@ export function Colormap({
viewportId,
displaySets,
commandsManager,
serviceManager,
servicesManager,
}: ColormapProps): ReactElement {
const { cornerstoneViewportService } = serviceManager.services;
const { cornerstoneViewportService } = servicesManager.services;
const [activeDisplaySet, setActiveDisplaySet] = useState(displaySets[0]);
@@ -68,6 +68,11 @@ export function Colormap({
key: index,
style: {
minWidth: `calc(100% / ${displaySets.length})`,
fontSize: '0.8rem',
textAlign: 'center',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
},
}));
}, [displaySets]);
@@ -2,11 +2,11 @@ import React, { ReactElement, useState, useEffect, useCallback } from 'react';
import { VolumeLightingProps } from '../../types/ViewportPresets';
export function VolumeLighting({
serviceManager,
servicesManager,
commandsManager,
viewportId,
}: VolumeLightingProps): ReactElement {
const { cornerstoneViewportService } = serviceManager.services;
const { cornerstoneViewportService } = servicesManager.services;
const [ambient, setAmbient] = useState(null);
const [diffuse, setDiffuse] = useState(null);
const [specular, setSpecular] = useState(null);
@@ -60,7 +60,11 @@ export function VolumeLighting({
min={0}
type="range"
step={0.1}
style={{ background: calculateBackground(ambient) }}
style={{
background: calculateBackground(ambient),
'--thumb-inner-color': '#5acce6',
'--thumb-outer-color': '#090c29',
}}
/>
)}
</div>
@@ -84,7 +88,11 @@ export function VolumeLighting({
min={0}
type="range"
step={0.1}
style={{ background: calculateBackground(diffuse) }}
style={{
background: calculateBackground(diffuse),
'--thumb-inner-color': '#5acce6',
'--thumb-outer-color': '#090c29',
}}
/>
)}
</div>
@@ -109,7 +117,11 @@ export function VolumeLighting({
min={0}
type="range"
step={0.1}
style={{ background: calculateBackground(specular) }}
style={{
background: calculateBackground(specular),
'--thumb-inner-color': '#5acce6',
'--thumb-outer-color': '#090c29',
}}
/>
)}
</div>
@@ -9,37 +9,37 @@ export function VolumeRenderingOptions({
viewportId,
commandsManager,
volumeRenderingQualityRange,
serviceManager,
servicesManager,
}: VolumeRenderingOptionsProps): ReactElement {
return (
<AllInOneMenu.ItemPanel>
<VolumeRenderingQuality
viewportId={viewportId}
commandsManager={commandsManager}
serviceManager={serviceManager}
servicesManager={servicesManager}
volumeRenderingQualityRange={volumeRenderingQualityRange}
/>
<VolumeShift
viewportId={viewportId}
commandsManager={commandsManager}
serviceManager={serviceManager}
servicesManager={servicesManager}
/>
<div className="all-in-one-menu-item flex w-full justify-start">
<div className="all-in-one-menu-item mt-2 flex !h-[20px] w-full justify-start">
<div className="text-aqua-pale text-[13px]">LIGHTING</div>
</div>
<AllInOneMenu.DividerItem />
<div className="bg-primary-dark mt-1 mb-1 h-[2px] w-full"></div>
<div className="all-in-one-menu-item flex w-full justify-center">
<VolumeShade
commandsManager={commandsManager}
serviceManager={serviceManager}
servicesManager={servicesManager}
viewportId={viewportId}
/>
</div>
<VolumeLighting
viewportId={viewportId}
commandsManager={commandsManager}
serviceManager={serviceManager}
servicesManager={servicesManager}
/>
</AllInOneMenu.ItemPanel>
);
@@ -5,11 +5,11 @@ import { VolumeRenderingPresetsContent } from './VolumeRenderingPresetsContent';
export function VolumeRenderingPresets({
viewportId,
serviceManager,
servicesManager,
commandsManager,
volumeRenderingPresets,
}: VolumeRenderingPresetsProps): ReactElement {
const { uiModalService } = serviceManager.services;
const { uiModalService } = servicesManager.services;
const onClickPresets = () => {
uiModalService.show({
@@ -23,7 +23,7 @@ export function VolumeRenderingPresets({
commandsManager,
},
containerDimensions: 'h-[543px] w-[460px]',
contentDimensions: 'h-[493px] w-[460px] pl-[12px]',
contentDimensions: 'h-[493px] w-[460px] pl-[12px] pr-[12px]',
});
};
@@ -4,10 +4,10 @@ import { VolumeRenderingQualityProps } from '../../types/ViewportPresets';
export function VolumeRenderingQuality({
volumeRenderingQualityRange,
commandsManager,
serviceManager,
servicesManager,
viewportId,
}: VolumeRenderingQualityProps): ReactElement {
const { cornerstoneViewportService } = serviceManager.services;
const { cornerstoneViewportService } = servicesManager.services;
const { min, max, step } = volumeRenderingQualityRange;
const [quality, setQuality] = useState(null);
@@ -60,7 +60,11 @@ export function VolumeRenderingQuality({
type="range"
step={step}
onChange={e => onChange(parseInt(e.target.value, 10))}
style={{ background: calculateBackground((quality - min) / (max - min)) }}
style={{
background: calculateBackground((quality - min) / (max - min)),
'--thumb-inner-color': '#5acce6',
'--thumb-outer-color': '#090c29',
}}
/>
)}
</div>
@@ -5,9 +5,9 @@ import { VolumeShadeProps } from '../../types/ViewportPresets';
export function VolumeShade({
commandsManager,
viewportId,
serviceManager,
servicesManager,
}: VolumeShadeProps): ReactElement {
const { cornerstoneViewportService } = serviceManager.services;
const { cornerstoneViewportService } = servicesManager.services;
const [shade, setShade] = useState(true);
const [key, setKey] = useState(0);
@@ -4,9 +4,9 @@ import { VolumeShiftProps } from '../../types/ViewportPresets';
export function VolumeShift({
viewportId,
commandsManager,
serviceManager,
servicesManager,
}: VolumeShiftProps): ReactElement {
const { cornerstoneViewportService } = serviceManager.services;
const { cornerstoneViewportService } = servicesManager.services;
const [minShift, setMinShift] = useState<number | null>(null);
const [maxShift, setMaxShift] = useState<number | null>(null);
const [shift, setShift] = useState<number | null>(
@@ -82,6 +82,8 @@ export function VolumeShift({
step={step}
style={{
background: calculateBackground((shift - minShift) / (maxShift - minShift)),
'--thumb-inner-color': '#5acce6',
'--thumb-outer-color': '#090c29',
}}
/>
)}
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
export type WindowLevelProps = {
viewportId: string;
presets: Record<string, Array<WindowLevelPreset>>;
presets: Array<Record<string, Array<WindowLevelPreset>>>;
commandsManager: CommandsManager;
};
@@ -23,25 +23,34 @@ export function WindowLevel({
commandName: 'setViewportWindowLevel',
commandOptions: {
...props,
viewportId,
},
context: 'CORNERSTONE',
});
},
[commandsManager]
[commandsManager, viewportId]
);
return (
<AllInOneMenu.ItemPanel>
<AllInOneMenu.HeaderItem>
{t('Modality Presets', { modality: Object.keys(presets)[0] })}
</AllInOneMenu.HeaderItem>
{Object.values(presets)[0].map((preset, index) => (
<AllInOneMenu.Item
key={index}
label={preset.description}
secondaryLabel={`${preset.window} / ${preset.level}`}
onClick={() => onSetWindowLevel({ ...preset, viewportId })}
></AllInOneMenu.Item>
{presets.map((modalityPresets, modalityIndex) => (
<React.Fragment key={modalityIndex}>
{Object.entries(modalityPresets).map(([modality, presetsArray]) => (
<React.Fragment key={modality}>
<AllInOneMenu.HeaderItem>
{t('Modality Presets', { modality })}
</AllInOneMenu.HeaderItem>
{presetsArray.map((preset, index) => (
<AllInOneMenu.Item
key={`${modality}-${index}`}
label={preset.description}
secondaryLabel={`${preset.window} / ${preset.level}`}
onClick={() => onSetWindowLevel(preset)}
/>
))}
</React.Fragment>
))}
</React.Fragment>
))}
</AllInOneMenu.ItemPanel>
);
@@ -2,7 +2,6 @@ import React, { ReactElement, useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import classNames from 'classnames';
import { AllInOneMenu, useViewportGrid } from '@ohif/ui';
import { CommandsManager, ServicesManager } from '@ohif/core';
import { Colormap } from './Colormap';
import { Colorbar } from './Colorbar';
import { setViewportColorbar } from './Colorbar';
@@ -19,11 +18,9 @@ import { utilities } from '@cornerstonejs/core';
export type WindowLevelActionMenuProps = {
viewportId: string;
element: HTMLElement;
presets: Record<string, Array<WindowLevelPreset>>;
presets: Array<Record<string, Array<WindowLevelPreset>>>;
verticalDirection: AllInOneMenu.VerticalDirection;
horizontalDirection: AllInOneMenu.HorizontalDirection;
commandsManager: CommandsManager;
serviceManager: ServicesManager;
colorbarProperties: ColorbarProperties;
displaySets: Array<any>;
volumeRenderingPresets: Array<ViewportPreset>;
@@ -37,12 +34,12 @@ export function WindowLevelActionMenu({
verticalDirection,
horizontalDirection,
commandsManager,
serviceManager,
servicesManager,
colorbarProperties,
displaySets,
volumeRenderingPresets,
volumeRenderingQualityRange,
}: WindowLevelActionMenuProps): ReactElement {
}: withAppTypes<WindowLevelActionMenuProps>): ReactElement {
const {
colormaps,
colorbarContainerPosition,
@@ -50,8 +47,9 @@ export function WindowLevelActionMenu({
colorbarTickPosition,
width: colorbarWidth,
} = colorbarProperties;
const { colorbarService, cornerstoneViewportService } = serviceManager.services;
const { colorbarService, cornerstoneViewportService } = servicesManager.services;
const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
const backgroundColor = viewportInfo.getViewportOptions().background;
const isLight = backgroundColor ? utilities.isEqual(backgroundColor, [1, 1, 1]) : false;
@@ -67,7 +65,7 @@ export function WindowLevelActionMenu({
const [is3DVolume, setIs3DVolume] = useState(false);
const onSetColorbar = useCallback(() => {
setViewportColorbar(viewportId, displaySets, commandsManager, serviceManager, {
setViewportColorbar(viewportId, displaySets, commandsManager, servicesManager, {
colormaps,
ticks: {
position: colorbarTickPosition,
@@ -93,13 +91,7 @@ export function WindowLevelActionMenu({
colorbarService.removeColorbar(viewportId);
onSetColorbar();
}, 0);
}, [viewportId]);
useEffect(() => {
if (colorbarService.hasColorbar(viewportId)) {
colorbarService.removeColorbar(viewportId);
}
}, [displaySets]);
}, [viewportId, displaySets, viewport]);
useEffect(() => {
setMenuKey(menuKey + 1);
@@ -128,10 +120,8 @@ export function WindowLevelActionMenu({
iconClassName={classNames(
// Visible on hover and for the active viewport
activeViewportId === viewportId ? 'visible' : 'invisible group-hover:visible',
'flex shrink-0 cursor-pointer rounded active:text-white',
isLight
? 'text-aqua-pale hover:bg-secondary-dark'
: 'text-primary-light hover:bg-secondary-light/60'
'flex shrink-0 cursor-pointer rounded active:text-white text-primary-light',
isLight ? ' hover:bg-secondary-dark' : 'hover:bg-secondary-light/60'
)}
menuStyle={{ maxHeight: vpHeight - 32, minWidth: 218 }}
onVisibilityChange={() => {
@@ -145,7 +135,7 @@ export function WindowLevelActionMenu({
viewportId={viewportId}
displaySets={displaySets.filter(ds => !nonImageModalities.includes(ds.Modality))}
commandsManager={commandsManager}
serviceManager={serviceManager}
servicesManager={servicesManager}
colorbarProperties={colorbarProperties}
/>
)}
@@ -161,15 +151,15 @@ export function WindowLevelActionMenu({
viewportId={viewportId}
displaySets={displaySets.filter(ds => !nonImageModalities.includes(ds.Modality))}
commandsManager={commandsManager}
serviceManager={serviceManager}
servicesManager={servicesManager}
/>
</AllInOneMenu.SubMenu>
)}
{presets && !is3DVolume && (
{presets && presets.length > 0 && !is3DVolume && (
<AllInOneMenu.SubMenu
key="windowLevelPresets"
itemLabel={t('Modality Window Presets', { modality: Object.keys(presets)[0] })}
itemLabel={t('Modality Window Presets')}
itemIcon="viewport-window-level"
>
<WindowLevel
@@ -182,7 +172,7 @@ export function WindowLevelActionMenu({
{volumeRenderingPresets && is3DVolume && (
<VolumeRenderingPresets
serviceManager={serviceManager}
servicesManager={servicesManager}
viewportId={viewportId}
commandsManager={commandsManager}
volumeRenderingPresets={volumeRenderingPresets}
@@ -195,7 +185,7 @@ export function WindowLevelActionMenu({
viewportId={viewportId}
commandsManager={commandsManager}
volumeRenderingQualityRange={volumeRenderingQualityRange}
serviceManager={serviceManager}
servicesManager={servicesManager}
/>
</AllInOneMenu.SubMenu>
)}
@@ -9,7 +9,7 @@ export function getWindowLevelActionMenu({
commandsManager,
verticalDirection,
horizontalDirection,
}): ReactNode {
}: withAppTypes): ReactNode {
const { customizationService } = servicesManager.services;
const { presets } = customizationService.get('cornerstone.windowLevelPresets');
@@ -24,21 +24,19 @@ export function getWindowLevelActionMenu({
return { [displaySet.Modality]: presets[displaySet.Modality] };
});
const hasMenu = displaySetPresets.length > 0;
return hasMenu ? (
return (
<WindowLevelActionMenu
viewportId={viewportId}
element={element}
presets={displaySetPresets[0]}
presets={displaySetPresets}
verticalDirection={verticalDirection}
horizontalDirection={horizontalDirection}
commandsManager={commandsManager}
serviceManager={servicesManager}
servicesManager={servicesManager}
colorbarProperties={colorbarProperties}
displaySets={displaySets}
volumeRenderingPresets={volumeRenderingPresets}
volumeRenderingQualityRange={volumeRenderingQualityRange}
/>
) : null;
);
}
@@ -64,6 +64,136 @@ function getCustomizationModule() {
step: 1,
},
},
{
id: 'cornerstone.measurements',
Angle: {
displayText: [],
report: [],
},
CobbAngle: {
displayText: [],
report: [],
},
ArrowAnnotate: {
displayText: [],
report: [],
},
RectangleROi: {
displayText: [],
report: [],
},
CircleROI: {
displayText: [],
report: [],
},
EllipticalROI: {
displayText: [],
report: [],
},
Bidirectional: {
displayText: [],
report: [],
},
Length: {
displayText: [],
report: [],
},
LivewireContour: {
displayText: [],
report: [],
},
SplineROI: {
displayText: [
{
displayName: 'Area',
value: 'area',
type: 'value',
},
{
value: 'areaUnit',
for: ['area'],
type: 'unit',
},
/**
{
displayName: 'Modality',
value: 'Modality',
type: 'value',
},
*/
],
report: [
{
displayName: 'Area',
value: 'area',
type: 'value',
},
{
displayName: 'Unit',
value: 'areaUnit',
type: 'value',
},
],
},
PlanarFreehandROI: {
displayText: [
{
displayName: 'Mean',
value: 'mean',
type: 'value',
},
{
displayName: 'Max',
value: 'max',
type: 'value',
},
{
displayName: 'Area',
value: 'area',
type: 'value',
},
{
value: 'modalityUnit',
for: ['mean', 'max' /** 'stdDev **/],
type: 'unit',
},
{
value: 'areaUnit',
for: ['area'],
type: 'unit',
},
/**
{
displayName: 'Std Dev',
value: 'stdDev',
type: 'value',
},
*/
],
report: [
{
displayName: 'Mean',
value: 'mean',
type: 'value',
},
{
displayName: 'Max',
value: 'max',
type: 'value',
},
{
displayName: 'Area',
value: 'area',
type: 'value',
},
{
displayName: 'Unit',
value: 'unit',
type: 'value',
},
],
},
},
],
},
];
+61 -46
View File
@@ -6,9 +6,10 @@ const getToggledClassName = (isToggled: boolean) => {
: '!text-common-bright hover:!bg-primary-dark hover:text-primary-light';
};
export default function getToolbarModule({ commandsManager, servicesManager }) {
export default function getToolbarModule({ commandsManager, servicesManager }: withAppTypes) {
const {
toolGroupService,
toolbarService,
syncGroupService,
cornerstoneViewportService,
hangingProtocolService,
@@ -21,16 +22,16 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
// enabled or not
{
name: 'evaluate.cornerstoneTool',
evaluate: ({ viewportId, button, disabledText }) => {
evaluate: ({ viewportId, button, toolNames, disabledText }) => {
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
if (!toolGroup) {
return;
}
const toolName = getToolNameForButton(button);
const toolName = toolbarService.getToolNameForButton(button);
if (!toolGroup || !toolGroup.hasTool(toolName)) {
if (!toolGroup || (!toolGroup.hasTool(toolName) && !toolNames)) {
return {
disabled: true,
className: '!text-common-bright ohif-disabled',
@@ -38,13 +39,15 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
};
}
const isPrimaryActive = toolGroup.getActivePrimaryMouseButtonTool() === toolName;
const isPrimaryActive = toolNames
? toolNames.includes(toolGroup.getActivePrimaryMouseButtonTool())
: toolGroup.getActivePrimaryMouseButtonTool() === toolName;
return {
disabled: false,
className: isPrimaryActive
? '!text-black bg-primary-light'
: '!text-common-bright hover:!bg-primary-dark hover:!text-primary-light',
? '!text-black bg-primary-light rounded'
: '!text-common-bright hover:!bg-primary-dark hover:!text-primary-light rounded',
// Todo: isActive right now is used for nested buttons where the primary
// button needs to be fully rounded (vs partial rounded) when active
// otherwise it does not have any other use
@@ -71,7 +74,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
// check if the active toolName is part of the items then we need
// to move it to the primary button
const activeToolIndex = items.findIndex(item => {
const toolName = getToolNameForButton(item);
const toolName = toolbarService.getToolNameForButton(item);
return toolName === activeToolName;
});
@@ -108,32 +111,29 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
};
},
},
{
name: 'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled',
evaluate: ({ viewportId, button, disabledText }) =>
_evaluateToggle({
viewportId,
button,
toolbarService,
disabledText,
offModes: [Enums.ToolModes.Disabled],
toolGroupService,
}),
},
{
name: 'evaluate.cornerstoneTool.toggle',
evaluate: ({ viewportId, button, disabledText }) => {
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
if (!toolGroup) {
return;
}
const toolName = getToolNameForButton(button);
if (!toolGroup || !toolGroup.hasTool(toolName)) {
return {
disabled: true,
className: '!text-common-bright ohif-disabled',
disabledText: disabledText ?? 'Not available on the current viewport',
};
}
const isOff = [Enums.ToolModes.Disabled, Enums.ToolModes.Passive].includes(
toolGroup.getToolOptions(toolName).mode
);
return {
className: getToggledClassName(!isOff),
};
},
evaluate: ({ viewportId, button, disabledText }) =>
_evaluateToggle({
viewportId,
button,
toolbarService,
disabledText,
offModes: [Enums.ToolModes.Disabled, Enums.ToolModes.Passive],
toolGroupService,
}),
},
{
name: 'evaluate.cornerstone.synchronizer',
@@ -146,7 +146,11 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
};
}
const synchronizerType = button?.commands?.[0]?.commandOptions?.type;
const isArray = Array.isArray(button.commands);
const synchronizerType = isArray
? button.commands?.[0].commandOptions.type
: button.commands?.commandOptions.type;
synchronizers = syncGroupService.getSynchronizersOfType(synchronizerType);
@@ -268,21 +272,32 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
];
}
function getToolNameForButton(button) {
const { props } = button;
function _evaluateToggle({
viewportId,
toolbarService,
button,
disabledText,
offModes,
toolGroupService,
}) {
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
const commands = props?.commands || button.commands;
const commandsArray = Array.isArray(commands) ? commands : [commands];
const firstCommand = commandsArray[0];
if (typeof firstCommand === 'string') {
// likely not a cornerstone tool
return null;
if (!toolGroup) {
return;
}
const toolName = toolbarService.getToolNameForButton(button);
if (!toolGroup.hasTool(toolName)) {
return {
disabled: true,
className: '!text-common-bright ohif-disabled',
disabledText: disabledText ?? 'Not available on the current viewport',
};
}
if ('commandOptions' in firstCommand) {
return firstCommand.commandOptions.toolName ?? props?.id ?? button.id;
}
const isOff = offModes.includes(toolGroup.getToolOptions(toolName).mode);
// use id as a fallback for toolName
return props?.id ?? button.id;
return {
className: getToggledClassName(!isOff),
};
}
+5 -2
View File
@@ -77,8 +77,11 @@ export const fourUp = {
{
id: 'mprDisplaySet',
options: {
// ToDo: choose appropriate preset
displayPreset: 'CT-Bone',
displayPreset: {
CT: 'CT-Bone',
MR: 'MR-Default',
default: 'CT-Bone',
},
},
},
],
+5 -2
View File
@@ -77,8 +77,11 @@ export const main3D = {
{
id: 'mprDisplaySet',
options: {
// ToDo: choose appropriate preset
displayPreset: 'CT-Bone',
displayPreset: {
CT: 'CT-Bone',
MR: 'MR-Default',
default: 'CT-Bone',
},
},
},
],
+1 -11
View File
@@ -14,17 +14,7 @@ export const mpr: Types.HangingProtocol.Protocol = {
numberOfPriorsReferenced: 0,
protocolMatchingRules: [],
imageLoadStrategy: 'nth',
callbacks: {
// Switches out of MPR mode when the layout change button is used
onLayoutChange: [
{
commandName: 'toggleHangingProtocol',
commandOptions: { protocolId: 'mpr' },
context: 'DEFAULT',
},
],
// Turns off crosshairs when switching out of MPR mode
},
callbacks: {},
displaySetSelectors: {
activeDisplaySet: {
seriesMatchingRules: [
@@ -84,7 +84,11 @@ export const mprAnd3DVolumeViewport = {
{
id: 'mprDisplaySet',
options: {
displayPreset: 'CT-Bone',
displayPreset: {
CT: 'CT-Bone',
MR: 'MR-Default',
default: 'CT-Bone',
},
},
},
],
+5 -2
View File
@@ -51,8 +51,11 @@ export const only3D = {
{
id: 'mprDisplaySet',
options: {
// ToDo: choose appropriate preset
displayPreset: 'CT-Bone',
displayPreset: {
CT: 'CT-Bone',
MR: 'MR-Default',
default: 'CT-Bone',
},
},
},
],
+5 -2
View File
@@ -77,8 +77,11 @@ export const primary3D = {
{
id: 'mprDisplaySet',
options: {
// ToDo: choose appropriate preset
displayPreset: 'CT-Bone',
displayPreset: {
CT: 'CT-Bone',
MR: 'MR-Default',
default: 'CT-Bone',
},
},
},
],
+24 -3
View File
@@ -8,7 +8,7 @@ import {
} from '@cornerstonejs/core';
import * as csStreamingImageVolumeLoader from '@cornerstonejs/streaming-image-volume-loader';
import { Enums as cs3DToolsEnums } from '@cornerstonejs/tools';
import { ServicesManager, Types } from '@ohif/core';
import { Types } from '@ohif/core';
import init from './init';
import getCustomizationModule from './getCustomizationModule';
@@ -61,7 +61,26 @@ const cornerstoneExtension: Types.Extensions.Extension = {
*/
id,
onModeExit: (): void => {
onModeEnter: ({ servicesManager }: withAppTypes): void => {
const { cornerstoneViewportService, toolbarService, segmentationService } =
servicesManager.services;
toolbarService.registerEventForToolbarUpdate(cornerstoneViewportService, [
cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED,
]);
toolbarService.registerEventForToolbarUpdate(segmentationService, [
segmentationService.EVENTS.SEGMENTATION_ADDED,
segmentationService.EVENTS.SEGMENTATION_REMOVED,
segmentationService.EVENTS.SEGMENTATION_UPDATED,
]);
toolbarService.registerEventForToolbarUpdate(cornerstone.eventTarget, [
cornerstoneTools.Enums.Events.TOOL_ACTIVATED,
]);
},
onModeExit: ({ servicesManager }: withAppTypes): void => {
const { cineService } = servicesManager.services;
// Empty out the image load and retrieval pools to prevent memory leaks
// on the mode exits
Object.values(cs3DEnums.RequestType).forEach(type => {
@@ -69,6 +88,8 @@ const cornerstoneExtension: Types.Extensions.Extension = {
imageRetrievalPoolManager.clearRequestStack(type);
});
cineService.setIsCineEnabled(false);
enabledElementReset();
},
@@ -111,7 +132,7 @@ const cornerstoneExtension: Types.Extensions.Extension = {
// const onNewImageHandler = jumpData => {
// commandsManager.runCommand('jumpToImage', jumpData);
// };
const { toolbarService } = (servicesManager as ServicesManager).services;
const { toolbarService } = servicesManager.services;
return (
<OHIFCornerstoneViewport
+20 -21
View File
@@ -15,7 +15,6 @@ import {
utilities as csUtilities,
Enums as csEnums,
} from '@cornerstonejs/core';
import { utilities } from '@cornerstonejs/tools';
import {
cornerstoneStreamingImageVolumeLoader,
cornerstoneStreamingDynamicImageVolumeLoader,
@@ -31,7 +30,6 @@ import nthLoader from './utils/nthLoader';
import interleaveTopToBottom from './utils/interleaveTopToBottom';
import initContextMenu from './initContextMenu';
import initDoubleClick from './initDoubleClick';
import { CornerstoneServices } from './types';
import initViewTiming from './utils/initViewTiming';
import { colormaps } from './utils/colormaps';
@@ -98,25 +96,9 @@ export default async function init({
uiNotificationService,
cornerstoneViewportService,
hangingProtocolService,
toolbarService,
viewportGridService,
stateSyncService,
segmentationService,
} = servicesManager.services as CornerstoneServices;
toolbarService.registerEventForToolbarUpdate(cornerstoneViewportService, [
cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED,
]);
toolbarService.registerEventForToolbarUpdate(segmentationService, [
segmentationService.EVENTS.SEGMENTATION_ADDED,
segmentationService.EVENTS.SEGMENTATION_REMOVED,
segmentationService.EVENTS.SEGMENTATION_UPDATED,
]);
toolbarService.registerEventForToolbarUpdate(eventTarget, [
cornerstoneTools.Enums.Events.TOOL_ACTIVATED,
]);
} = servicesManager.services;
window.services = servicesManager.services;
window.extensionManager = extensionManager;
@@ -159,14 +141,19 @@ export default async function init({
});
const labelmapRepresentation = cornerstoneTools.Enums.SegmentationRepresentations.Labelmap;
const contourRepresentation = cornerstoneTools.Enums.SegmentationRepresentations.Contour;
cornerstoneTools.segmentation.config.setGlobalRepresentationConfig(labelmapRepresentation, {
fillAlpha: 0.3,
fillAlpha: 0.5,
fillAlphaInactive: 0.2,
outlineOpacity: 1,
outlineOpacityInactive: 0.65,
});
cornerstoneTools.segmentation.config.setGlobalRepresentationConfig(contourRepresentation, {
renderFill: false,
});
const metadataProvider = OHIF.classes.MetadataProvider;
volumeLoader.registerVolumeLoader(
@@ -292,8 +279,20 @@ export default async function init({
eventTarget.addEventListener(EVENTS.ELEMENT_ENABLED, elementEnabledHandler.bind(null));
eventTarget.addEventListener(EVENTS.ELEMENT_DISABLED, elementDisabledHandler.bind(null));
colormaps.forEach(registerColormap);
// Event listener
eventTarget.addEventListenerDebounced(
EVENTS.ERROR_EVENT,
({ detail }) => {
uiNotificationService.show({
title: detail.type,
message: detail.message,
type: 'error',
});
},
1000
);
}
function CPUModal() {
@@ -19,7 +19,7 @@ function _getVolumeFromViewport(viewport) {
* @param srcViewportIndex Source viewport index
* @returns array with viewport information.
*/
function _getSyncedViewports(servicesManager, srcViewportId) {
function _getSyncedViewports(servicesManager: AppTypes.ServicesManager, srcViewportId) {
const { viewportGridService, cornerstoneViewportService } = servicesManager.services;
const { viewports: viewportsStates } = viewportGridService.getState();
@@ -48,7 +48,7 @@ function _getSyncedViewports(servicesManager, srcViewportId) {
.map(({ viewportId }) => ({ viewportId }));
}
function initCineService(servicesManager) {
function initCineService(servicesManager: AppTypes.ServicesManager) {
const { cineService } = servicesManager.services;
const getSyncedViewports = viewportId => {
@@ -59,8 +59,8 @@ function initCineService(servicesManager) {
return utilities.cine.playClip(element, playClipOptions);
};
const stopClip = element => {
return utilities.cine.stopClip(element);
const stopClip = (element, stopClipOptions) => {
return utilities.cine.stopClip(element, stopClipOptions);
};
cineService.setServiceImplementation({
@@ -35,6 +35,7 @@ import {
PlanarFreehandROITool,
SplineROITool,
LivewireContourTool,
OrientationMarkerTool,
} from '@cornerstonejs/tools';
import CalibrationLineTool from './tools/CalibrationLineTool';
@@ -43,6 +44,7 @@ import ImageOverlayViewerTool from './tools/ImageOverlayViewerTool';
export default function initCornerstoneTools(configuration = {}) {
CrosshairsTool.isAnnotation = false;
ReferenceLinesTool.isAnnotation = false;
AdvancedMagnifyTool.isAnnotation = false;
init(configuration);
addTool(PanTool);
@@ -80,6 +82,7 @@ export default function initCornerstoneTools(configuration = {}) {
addTool(PlanarFreehandROITool);
addTool(SplineROITool);
addTool(LivewireContourTool);
addTool(OrientationMarkerTool);
// Modify annotation tools to use dashed lines on SR
const annotationStyle = {
@@ -132,6 +135,7 @@ const toolNames = {
SplineROI: SplineROITool.toolName,
LivewireContour: LivewireContourTool.toolName,
PlanarFreehandROI: PlanarFreehandROITool.toolName,
OrientationMarker: OrientationMarkerTool.toolName,
};
export { toolNames };
@@ -17,7 +17,8 @@ const CORNERSTONE_3D_TOOLS_SOURCE_VERSION = '0.1';
const initMeasurementService = (
measurementService,
displaySetService,
cornerstoneViewportService
cornerstoneViewportService,
customizationService
) => {
/* Initialization */
const {
@@ -30,10 +31,15 @@ const initMeasurementService = (
CobbAngle,
RectangleROI,
PlanarFreehandROI,
SplineROI,
LivewireContour,
Probe,
UltrasoundDirectional,
} = measurementServiceMappingsFactory(
measurementService,
displaySetService,
cornerstoneViewportService
cornerstoneViewportService,
customizationService
);
const csTools3DVer1MeasurementSource = measurementService.createSource(
CORNERSTONE_3D_TOOLS_SOURCE_NAME,
@@ -127,6 +133,14 @@ const initMeasurementService = (
PlanarFreehandROI.toMeasurement
);
measurementService.addMapping(
csTools3DVer1MeasurementSource,
'SplineROI',
SplineROI.matchingCriteria,
SplineROI.toAnnotation,
SplineROI.toMeasurement
);
// On the UI side, the Calibration Line tool will work almost the same as the
// Length tool
measurementService.addMapping(
@@ -137,16 +151,45 @@ const initMeasurementService = (
Length.toMeasurement
);
measurementService.addMapping(
csTools3DVer1MeasurementSource,
'LivewireContour',
LivewireContour.matchingCriteria,
LivewireContour.toAnnotation,
LivewireContour.toMeasurement
);
measurementService.addMapping(
csTools3DVer1MeasurementSource,
'Probe',
Probe.matchingCriteria,
Probe.toAnnotation,
Probe.toMeasurement
);
measurementService.addMapping(
csTools3DVer1MeasurementSource,
'UltrasoundDirectionalTool',
UltrasoundDirectional.matchingCriteria,
UltrasoundDirectional.toAnnotation,
UltrasoundDirectional.toMeasurement
);
return csTools3DVer1MeasurementSource;
};
const connectToolsToMeasurementService = servicesManager => {
const { measurementService, displaySetService, cornerstoneViewportService } =
servicesManager.services;
const connectToolsToMeasurementService = (servicesManager: AppTypes.ServicesManager) => {
const {
measurementService,
displaySetService,
cornerstoneViewportService,
customizationService,
} = servicesManager.services;
const csTools3DVer1MeasurementSource = initMeasurementService(
measurementService,
displaySetService,
cornerstoneViewportService
cornerstoneViewportService,
customizationService
);
connectMeasurementServiceToTools(
measurementService,
@@ -75,10 +75,7 @@ export default class ColorbarService extends PubSubService {
displaySetInstanceUIDs.forEach((displaySetInstanceUID, index) => {
const actorEntry = actorEntries.find(entry => entry.uid.includes(displaySetInstanceUID));
if (!actorEntry) {
return;
}
const { uid: volumeId } = actorEntry;
const volumeId = actorEntry?.uid;
const properties = viewport?.getProperties(volumeId);
const colormap = properties?.colormap;
// if there's an initial colormap set, and no colormap on the viewport, set it
@@ -194,8 +191,10 @@ export default class ColorbarService extends PubSubService {
private setViewportColormap(viewportId, displaySetInstanceUID, colormap, immediate = false) {
const renderingEngine = getRenderingEngine(RENDERING_ENGINE_ID);
const viewport = renderingEngine.getViewport(viewportId);
const actorEntries = viewport.getActors();
const actorEntries = viewport?.getActors();
if (!viewport || !actorEntries || actorEntries.length === 0) {
return;
}
const setViewportProperties = (viewport, uid) => {
const actorEntry = actorEntries.find(entry => entry.uid.includes(uid));
const { actor: volumeActor, uid: volumeId } = actorEntry;
@@ -1,4 +1,4 @@
import { ServicesManager, Types } from '@ohif/core';
import { Types } from '@ohif/core';
import { cache as cs3DCache, Enums, volumeLoader, utilities as utils } from '@cornerstonejs/core';
import getCornerstoneViewportType from '../../utils/getCornerstoneViewportType';
@@ -17,9 +17,9 @@ class CornerstoneCacheService {
stackImageIds: Map<string, string[]> = new Map();
volumeImageIds: Map<string, string[]> = new Map();
readonly servicesManager: ServicesManager;
readonly servicesManager: AppTypes.ServicesManager;
constructor(servicesManager: ServicesManager) {
constructor(servicesManager: AppTypes.ServicesManager) {
this.servicesManager = servicesManager;
}
@@ -45,7 +45,11 @@ class CornerstoneCacheService {
// as a reference volume, if so, we should hang a volume viewport
// instead of a stack viewport
if (this._shouldRenderSegmentation(displaySets)) {
viewportType = 'volume';
// if the viewport type is volume 3D, we should let it be as it is
// Todo: in future here we should kick start the conversion of the
// segmentation to closed surface
viewportType =
viewportType === Enums.ViewportType.VOLUME_3D ? Enums.ViewportType.VOLUME_3D : 'volume';
// update viewportOptions to reflect the new viewport type
viewportOptions.viewportType = viewportType;
@@ -94,7 +98,21 @@ class CornerstoneCacheService {
const volume = cs3DCache.getVolume(volumeId);
if (volume) {
cs3DCache.removeVolumeLoadObject(volumeId);
if (volume.imageIds) {
// also for each imageId in the volume, remove the imageId from the cache
// since that will hold the old metadata as well
volume.imageIds.forEach(imageId => {
if (cs3DCache.getImageLoadObject(imageId)) {
cs3DCache.removeImageLoadObject(imageId);
}
});
}
// this shouldn't be via removeVolumeLoadObject, since that will
// remove the texture as well, but here we really just need a remove
// from registry so that we load it again
cs3DCache._volumeCache.delete(volumeId);
this.volumeImageIds.delete(volumeId);
}
@@ -111,14 +129,25 @@ class CornerstoneCacheService {
return newViewportData;
}
private _getStackViewportData(
private async _getStackViewportData(
dataSource,
displaySets,
initialImageIndex,
viewportType: Enums.ViewportType
): StackViewportData {
// For Stack Viewport we don't have fusion currently
const displaySet = displaySets[0];
): Promise<StackViewportData> {
const overlayDisplaySets = displaySets.filter(ds => ds.isOverlayDisplaySet);
const nonOverlayDisplaySets = displaySets.filter(ds => !ds.isOverlayDisplaySet);
// load overlays if they are not loaded
for (const overlayDisplaySet of overlayDisplaySets) {
if (overlayDisplaySet.load && overlayDisplaySet.load instanceof Function) {
const { userAuthenticationService } = this.servicesManager.services;
const headers = userAuthenticationService.getAuthorizationHeader();
await overlayDisplaySet.load({ headers });
}
}
const displaySet = nonOverlayDisplaySets[0];
let stackImageIds = this.stackImageIds.get(displaySet.displaySetInstanceUID);
@@ -127,23 +156,23 @@ class CornerstoneCacheService {
this.stackImageIds.set(displaySet.displaySetInstanceUID, stackImageIds);
}
const { displaySetInstanceUID, StudyInstanceUID, isCompositeStack } = displaySet;
// Ensuring the first non-overlay `displaySet` is always the primary one
const StackViewportData = [displaySet, ...overlayDisplaySets].map(ds => {
const { displaySetInstanceUID, StudyInstanceUID, isCompositeStack } = ds;
const StackViewportData: StackViewportData = {
viewportType,
data: {
return {
StudyInstanceUID,
displaySetInstanceUID,
isCompositeStack,
imageIds: stackImageIds,
},
initialImageIndex,
};
});
return {
viewportType,
data: StackViewportData,
};
if (typeof initialImageIndex === 'number') {
StackViewportData.data.initialImageIndex = initialImageIndex;
}
return StackViewportData;
}
private async _getVolumeViewportData(
@@ -1,4 +1,4 @@
import { Types as OhifTypes, ServicesManager, PubSubService } from '@ohif/core';
import { Types as OhifTypes, PubSubService } from '@ohif/core';
import {
cache,
Enums as csEnums,
@@ -60,7 +60,7 @@ class SegmentationService extends PubSubService {
};
segmentations: Record<string, Segmentation>;
readonly servicesManager: ServicesManager;
readonly servicesManager: AppTypes.ServicesManager;
highlightIntervalId = null;
readonly EVENTS = EVENTS;
@@ -1015,6 +1015,8 @@ class SegmentationService extends PubSubService {
): Promise<void> => {
const segmentation = this.getSegmentation(segmentationId);
toolGroupId = toolGroupId || this._getApplicableToolGroupId();
if (!segmentation) {
throw new Error(`Segmentation with segmentationId ${segmentationId} not found.`);
}
@@ -1147,6 +1149,10 @@ class SegmentationService extends PubSubService {
displaySet.isHydrated = isHydrated;
displaySetService.setDisplaySetMetadataInvalidated(displaySetUID, false);
this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {
segmentation: this.getSegmentation(displaySetUID),
});
}
private _highlightLabelmap(
@@ -1,7 +1,7 @@
import { synchronizers, SynchronizerManager, Synchronizer } from '@cornerstonejs/tools';
import { getRenderingEngines } from '@cornerstonejs/core';
import { getRenderingEngines, utilities } from '@cornerstonejs/core';
import { pubSubServiceInterface, Types, ServicesManager } from '@ohif/core';
import { pubSubServiceInterface, Types } from '@ohif/core';
const EVENTS = {
TOOL_GROUP_CREATED: 'event::cornerstone::syncgroupservice:toolgroupcreated',
@@ -40,7 +40,7 @@ export default class SyncGroupService {
},
};
servicesManager: ServicesManager;
servicesManager: AppTypes.ServicesManager;
listeners: { [key: string]: (...args: any[]) => void } = {};
EVENTS: { [key: string]: string };
synchronizerCreators: Record<string, SyncCreator> = {
@@ -55,8 +55,8 @@ export default class SyncGroupService {
synchronizersByType: { [key: string]: Synchronizer[] } = {};
constructor(serviceManager: ServicesManager) {
this.servicesManager = serviceManager;
constructor(servicesManager: AppTypes.ServicesManager) {
this.servicesManager = servicesManager;
this.listeners = {};
this.EVENTS = EVENTS;
//
@@ -184,6 +184,11 @@ export default class SyncGroupService {
return;
}
// Only image slice synchronizer register spatial registration
if (this.isImageSliceSyncronizer(synchronizer)) {
this.unRegisterSpatialRegistration(synchronizer);
}
synchronizer.remove({
viewportId,
renderingEngineId,
@@ -198,4 +203,45 @@ export default class SyncGroupService {
}
});
}
/**
* Clean up the spatial registration metadata created by synchronizer
* This is needed to be able to re-sync images slices if needed
* @param synchronizer
*/
unRegisterSpatialRegistration(synchronizer: Synchronizer) {
const sourceViewports = synchronizer.getSourceViewports().map(vp => vp.viewportId);
const targetViewports = synchronizer.getTargetViewports().map(vp => vp.viewportId);
// Create an array of pair of viewports to remove from spatialRegistrationMetadataProvider
// All sourceViewports combined with all targetViewports
const toUnregister = sourceViewports
.map((sourceViewportId: string) => {
return targetViewports.map(targetViewportId => [targetViewportId, sourceViewportId]);
})
.reduce((acc, c) => acc.concat(c), []);
toUnregister.forEach(viewportIdPair => {
utilities.spatialRegistrationMetadataProvider.add(viewportIdPair, undefined);
});
}
/**
* Check if the synchronizer type is IMAGE_SLICE
* Need to convert to lowercase here because the types are lowercase
* e.g: synchronizerCreators
* @param synchronizer
*/
isImageSliceSyncronizer(synchronizer: Synchronizer) {
return this.getSynchronizerType(synchronizer).toLowerCase() === IMAGE_SLICE;
}
/**
* Returns the syncronizer type
* @param synchronizer
*/
getSynchronizerType(synchronizer: Synchronizer): string {
const synchronizerTypes = Object.keys(this.synchronizersByType);
const syncType = synchronizerTypes.find(syncType =>
this.getSynchronizersOfType(syncType).includes(synchronizer)
);
return syncType;
}
}
@@ -32,7 +32,10 @@ export default class ToolGroupService {
},
};
serviceManager: any;
servicesManager: AppTypes.ServicesManager;
cornerstoneViewportService: any;
viewportGridService: any;
uiNotificationService: any;
private toolGroupIds: Set<string> = new Set();
/**
* Service-specific
@@ -40,9 +43,9 @@ export default class ToolGroupService {
listeners: { [key: string]: Function[] };
EVENTS: { [key: string]: string };
constructor(serviceManager) {
constructor(servicesManager: AppTypes.ServicesManager) {
const { cornerstoneViewportService, viewportGridService, uiNotificationService } =
serviceManager.services;
servicesManager.services;
this.cornerstoneViewportService = cornerstoneViewportService;
this.viewportGridService = viewportGridService;
this.uiNotificationService = uiNotificationService;
@@ -1,4 +1,4 @@
import { PubSubService, ServicesManager } from '@ohif/core';
import { PubSubService } from '@ohif/core';
import * as OhifTypes from '@ohif/core/types';
import {
RenderingEngine,
@@ -52,14 +52,14 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
enableResizeDetector: true;
resizeRefreshRateMs: 200;
resizeRefreshMode: 'debounce';
servicesManager = null;
servicesManager: AppTypes.ServicesManager = null;
resizeQueue = [];
viewportResizeTimer = null;
gridResizeDelay = 50;
gridResizeTimeOut = null;
constructor(servicesManager: ServicesManager) {
constructor(servicesManager: AppTypes.ServicesManager) {
super(EVENTS);
this.renderingEngine = null;
this.viewportGridResizeObserver = null;
@@ -183,7 +183,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
const { lutPresentation, positionPresentation } = presentations;
if (lutPresentation) {
const { presentation } = lutPresentation;
if (viewport instanceof VolumeViewport) {
if (viewport instanceof BaseVolumeViewport) {
if (presentation instanceof Map) {
presentation.forEach((properties, volumeId) => {
viewport.setProperties(properties, volumeId);
@@ -532,6 +532,11 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
cameraProps: unknown
): string {
const viewportInfo = this.getViewportInfo(activeViewportId);
if (viewportInfo.getViewportType() === csEnums.ViewportType.VOLUME_3D) {
return null;
}
const { referencedImageId } = cameraProps;
if (viewportInfo?.contains(displaySetInstanceUID, referencedImageId)) {
return activeViewportId;
@@ -552,9 +557,14 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
): Promise<void> {
const displaySetOptions = viewportInfo.getDisplaySetOptions();
const { imageIds, initialImageIndex, displaySetInstanceUID } = viewportData.data;
const displaySetInstanceUIDs = viewportData.data.map(data => data.displaySetInstanceUID);
this.viewportsDisplaySets.set(viewport.id, [displaySetInstanceUID]);
// based on the cache service construct always the first one is the non-overlay
// and the rest are overlays
this.viewportsDisplaySets.set(viewport.id, [...displaySetInstanceUIDs]);
const { initialImageIndex, imageIds } = viewportData.data[0];
let initialImageIndexToUse =
presentations?.positionPresentation?.initialImageIndex ?? initialImageIndex;
@@ -583,6 +593,8 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
}
}
this._handleOverlays(viewport);
return viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
viewport.setProperties({ ...properties });
this.setPresentations(viewport.id, presentations);
@@ -721,10 +733,14 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
}
public async setVolumesForViewport(viewport, volumeInputArray, presentations) {
const { displaySetService, toolGroupService } = this.servicesManager.services;
const { displaySetService, toolGroupService, viewportGridService } =
this.servicesManager.services;
const viewportInfo = this.getViewportInfo(viewport.id);
const displaySetOptions = viewportInfo.getDisplaySetOptions();
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewport.id);
const displaySet = displaySetService.getDisplaySetByUID(displaySetUIDs[0]);
const displaySetModality = displaySet?.Modality;
// Todo: use presentations states
const volumesProperties = volumeInputArray.map((volumeInput, index) => {
@@ -750,7 +766,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
}
if (displayPreset !== undefined) {
properties.preset = displayPreset;
properties.preset = displayPreset[displaySetModality] || displayPreset.default;
}
return { properties, volumeId };
@@ -763,24 +779,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
this.setPresentations(viewport.id, presentations);
// load any secondary displaySets
const displaySetInstanceUIDs = this.viewportsDisplaySets.get(viewport.id);
// can be SEG or RTSTRUCT for now
const overlayDisplaySet = displaySetInstanceUIDs
.map(displaySetService.getDisplaySetByUID)
.find(displaySet => displaySet?.isOverlayDisplaySet);
if (overlayDisplaySet) {
this.addOverlayRepresentationForDisplaySet(overlayDisplaySet, viewport);
} else {
// If the displaySet is not a SEG displaySet we assume it is a primary displaySet
// and we can look into hydrated segmentations to check if any of them are
// associated with the primary displaySet
// get segmentations only returns the hydrated segmentations
this._addSegmentationRepresentationToToolGroupIfNecessary(displaySetInstanceUIDs, viewport);
}
this._handleOverlays(viewport);
const toolGroup = toolGroupService.getToolGroupForViewport(viewport.id);
csToolsUtils.segmentation.triggerSegmentationRender(toolGroup.id);
@@ -800,6 +799,28 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
});
}
private _handleOverlays(viewport: Types.IStackViewport | Types.IVolumeViewport) {
const { displaySetService } = this.servicesManager.services;
// load any secondary displaySets
const displaySetInstanceUIDs = this.viewportsDisplaySets.get(viewport.id);
// can be SEG or RTSTRUCT for now
const overlayDisplaySet = displaySetInstanceUIDs
.map(displaySetService.getDisplaySetByUID)
.find(displaySet => displaySet?.isOverlayDisplaySet);
if (overlayDisplaySet) {
this.addOverlayRepresentationForDisplaySet(overlayDisplaySet, viewport);
} else {
// If the displaySet is not a SEG displaySet we assume it is a primary displaySet
// and we can look into hydrated segmentations to check if any of them are
// associated with the primary displaySet
// get segmentations only returns the hydrated segmentations
this._addSegmentationRepresentationToToolGroupIfNecessary(displaySetInstanceUIDs, viewport);
}
}
private _addSegmentationRepresentationToToolGroupIfNecessary(
displaySetInstanceUIDs: string[],
viewport: any
@@ -1030,28 +1051,33 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
private performResize() {
const isImmediate = false;
const viewports = this.getRenderingEngine().getViewports();
try {
const viewports = this.getRenderingEngine().getViewports();
// Store the current position presentations for each viewport.
viewports.forEach(({ id }) => {
const presentation = this.getPositionPresentation(id);
this.beforeResizePositionPresentations.set(id, presentation);
});
// Store the current position presentations for each viewport.
viewports.forEach(({ id }) => {
const presentation = this.getPositionPresentation(id);
this.beforeResizePositionPresentations.set(id, presentation);
});
// Resize the rendering engine and render.
const renderingEngine = this.renderingEngine;
renderingEngine.resize(isImmediate);
renderingEngine.render();
// Resize the rendering engine and render.
const renderingEngine = this.renderingEngine;
renderingEngine.resize(isImmediate);
renderingEngine.render();
// Reset the camera for viewports that should reset their camera on resize,
// which means only those viewports that have a zoom level of 1.
this.beforeResizePositionPresentations.forEach((positionPresentation, viewportId) => {
this.setPresentations(viewportId, { positionPresentation });
});
// Reset the camera for viewports that should reset their camera on resize,
// which means only those viewports that have a zoom level of 1.
this.beforeResizePositionPresentations.forEach((positionPresentation, viewportId) => {
this.setPresentations(viewportId, { positionPresentation });
});
// Resize and render the rendering engine again.
renderingEngine.resize(isImmediate);
renderingEngine.render();
// Resize and render the rendering engine again.
renderingEngine.resize(isImmediate);
renderingEngine.render();
} catch (e) {
// This can happen if the resize is too close to navigation or shutdown
console.warn('Caught resize exception', e);
}
}
private resetGridResizeTimeout() {
@@ -8,7 +8,7 @@ import { Presentations } from '../../types/Presentation';
* updating the viewport.
*/
export interface IViewportService {
servicesManager: unknown;
servicesManager: AppTypes.ServicesManager;
hangingProtocolService: unknown;
renderingEngine: unknown;
viewportGridResizeObserver: unknown;
@@ -1,4 +1,10 @@
import { Types, Enums } from '@cornerstonejs/core';
import {
Types,
Enums,
getEnabledElementByViewportId,
VolumeViewport,
utilities,
} from '@cornerstonejs/core';
import { Types as CoreTypes } from '@ohif/core';
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
import getCornerstoneBlendMode from '../../utils/getCornerstoneBlendMode';
@@ -89,13 +95,30 @@ const DEFAULT_TOOLGROUP_ID = 'default';
// Return true if the data contains the given display set UID OR the imageId
// if it is a composite object.
const dataContains = (data, displaySetUID: string, imageId?: string): boolean => {
if (data.displaySetInstanceUID === displaySetUID) {
return true;
}
const dataContains = ({ data, displaySetUID, imageId, viewport }): boolean => {
if (imageId && data.isCompositeStack && data.imageIds) {
return !!data.imageIds.find(dataId => dataId === imageId);
}
if (imageId && (data.volumeId || viewport instanceof VolumeViewport)) {
const isAcquisition = !!viewport.getCurrentImageId();
if (!isAcquisition) {
return false;
}
const imageURI = utilities.imageIdToURI(imageId);
const hasImageId = viewport.hasImageURI(imageURI);
if (hasImageId) {
return true;
}
}
if (data.displaySetInstanceUID === displaySetUID) {
return true;
}
return false;
};
@@ -122,10 +145,20 @@ class ViewportInfo {
return false;
}
const { viewport } = getEnabledElementByViewportId(this.viewportId) || {};
if (this.viewportData.data.length) {
return !!this.viewportData.data.find(data => dataContains(data, displaySetUID, imageId));
return !!this.viewportData.data.find(data =>
dataContains({ data, displaySetUID, imageId, viewport })
);
}
return dataContains(this.viewportData.data, displaySetUID, imageId);
return dataContains({
data: this.viewportData.data,
displaySetUID,
imageId,
viewport,
});
}
public destroy = (): void => {
@@ -1,4 +1,3 @@
import { metaData } from '@cornerstonejs/core';
import { LengthTool, utilities } from '@cornerstonejs/tools';
import callInputDialog from '../utils/callInputDialog';
import getActiveViewportEnabledElement from '../utils/getActiveViewportEnabledElement';
@@ -49,7 +48,10 @@ function calculateLength3(pos1, pos2) {
export default CalibrationLineTool;
export function onCompletedCalibrationLine(servicesManager, csToolsEvent) {
export function onCompletedCalibrationLine(
servicesManager: AppTypes.ServicesManager,
csToolsEvent
) {
const { uiDialogService, viewportGridService } = servicesManager.services;
// calculate length (mm) with the current Pixel Spacing
@@ -0,0 +1,29 @@
/* eslint-disable @typescript-eslint/no-namespace */
import CornerstoneCacheServiceType from '../services/CornerstoneCacheService';
import CornerstoneViewportServiceType from '../services/ViewportService/CornerstoneViewportService';
import SegmentationServiceType from '../services/SegmentationService';
import SyncGroupServiceType from '../services/SyncGroupService';
import ToolGroupServiceType from '../services/ToolGroupService';
import ViewportActionCornersServiceType from '../services/ViewportActionCornersService/ViewportActionCornersService';
import ColorbarServiceType from '../services/ColorbarService';
declare global {
namespace AppTypes {
export type CornerstoneCacheService = CornerstoneCacheServiceType;
export type CornerstoneViewportService = CornerstoneViewportServiceType;
export type SegmentationService = SegmentationServiceType;
export type SyncGroupService = SyncGroupServiceType;
export type ToolGroupService = ToolGroupServiceType;
export type ViewportActionCornersService = ViewportActionCornersServiceType;
export type ColorbarService = ColorbarServiceType;
export interface Services {
cornerstoneViewportService?: CornerstoneViewportServiceType;
toolGroupService?: ToolGroupServiceType;
syncGroupService?: SyncGroupServiceType;
segmentationService?: SegmentationServiceType;
cornerstoneCacheService?: CornerstoneCacheServiceType;
viewportActionCornersService?: ViewportActionCornersServiceType;
colorbarService?: ColorbarServiceType;
}
}
}
@@ -1,5 +1,4 @@
import { ColorMapPreset } from './Colormap';
import { CommandsManager, ServicesManager } from '@ohif/core';
export type ColorbarOptions = {
position: string;
@@ -11,8 +10,6 @@ export type ColorbarOptions = {
export type ColorbarProps = {
viewportId: string;
commandsManager: CommandsManager;
serviceManager: ServicesManager;
displaySets: Array<any>;
colorbarProperties: ColorbarProperties;
};
+2 -2
View File
@@ -1,4 +1,4 @@
import { CommandsManager, ServicesManager } from '@ohif/core';
import { CommandsManager } from '@ohif/core';
export type ColorMapPreset = {
ColorSpace;
@@ -10,7 +10,7 @@ export type ColorMapPreset = {
export type ColormapProps = {
viewportId: string;
commandsManager: CommandsManager;
serviceManager: ServicesManager;
servicesManager: AppTypes.ServicesManager;
colormaps: Array<ColorMapPreset>;
displaySets: Array<any>;
};
@@ -22,7 +22,7 @@ type VolumeData = {
type StackViewportData = {
viewportType: Enums.ViewportType;
data: StackData;
data: StackData[];
};
type VolumeViewportData = {
@@ -5,6 +5,7 @@ import SegmentationService from '../services/SegmentationService';
import CornerstoneCacheService from '../services/CornerstoneCacheService';
import CornerstoneViewportService from '../services/ViewportService/CornerstoneViewportService';
import ViewportActionCornersService from '../services/ViewportActionCornersService/ViewportActionCornersService';
import ColorbarService from '../services/ColorbarService';
interface CornerstoneServices extends Types.Services {
cornerstoneViewportService: CornerstoneViewportService;
@@ -13,6 +14,7 @@ interface CornerstoneServices extends Types.Services {
segmentationService: SegmentationService;
cornerstoneCacheService: CornerstoneCacheService;
viewportActionCornersService: ViewportActionCornersService;
colorbarService: ColorbarService;
}
export default CornerstoneServices;
@@ -1,4 +1,4 @@
import { ServicesManager, CommandsManager } from '@ohif/core';
import { CommandsManager } from '@ohif/core';
export type ViewportPreset = {
name: string;
@@ -15,7 +15,7 @@ export type ViewportPreset = {
export type VolumeRenderingPresetsProps = {
viewportId: string;
serviceManager: ServicesManager;
servicesManager: AppTypes.ServicesManager;
commandsManager: CommandsManager;
volumeRenderingPresets: ViewportPreset[];
};
@@ -30,7 +30,7 @@ export type VolumeRenderingPresetsContentProps = {
export type VolumeRenderingOptionsProps = {
viewportId: string;
commandsManager: CommandsManager;
serviceManager: ServicesManager;
servicesManager: AppTypes.ServicesManager;
volumeRenderingQualityRange: VolumeRenderingQualityRange;
};
@@ -43,24 +43,24 @@ export type VolumeRenderingQualityRange = {
export type VolumeRenderingQualityProps = {
viewportId: string;
commandsManager: CommandsManager;
serviceManager: ServicesManager;
servicesManager: AppTypes.ServicesManager;
volumeRenderingQualityRange: VolumeRenderingQualityRange;
};
export type VolumeShiftProps = {
viewportId: string;
commandsManager: CommandsManager;
serviceManager: ServicesManager;
servicesManager: AppTypes.ServicesManager;
};
export type VolumeShadeProps = {
viewportId: string;
commandsManager: CommandsManager;
serviceManager: ServicesManager;
servicesManager: AppTypes.ServicesManager;
};
export type VolumeLightingProps = {
viewportId: string;
commandsManager: CommandsManager;
serviceManager: ServicesManager;
servicesManager: AppTypes.ServicesManager;
};
@@ -27,7 +27,11 @@ const CornerstoneViewportDownloadForm = ({
const activeViewportElement = enabledElement?.element;
const activeViewportEnabledElement = getEnabledElement(activeViewportElement);
const { viewportId: activeViewportId, renderingEngineId } = activeViewportEnabledElement;
const {
viewportId: activeViewportId,
renderingEngineId,
viewport: activeViewport,
} = activeViewportEnabledElement;
const toolGroup = ToolGroupManager.getToolGroupForViewport(activeViewportId, renderingEngineId);
@@ -93,7 +97,7 @@ const CornerstoneViewportDownloadForm = ({
renderingEngine.resize();
// Trigger the render on the viewport to update the on screen
downloadViewport.resetCamera();
// downloadViewport.resetCamera();
downloadViewport.render();
downloadViewportElement.addEventListener(
@@ -120,6 +124,12 @@ const CornerstoneViewportDownloadForm = ({
resolve({ dataUrl, width: newWidth, height: newHeight });
downloadViewportElement.removeEventListener(Enums.Events.IMAGE_RENDERED, updateViewport);
// for some reason we need a reset camera here, and I don't know why
downloadViewport.resetCamera();
const presentation = activeViewport.getViewPresentation();
downloadViewport.setViewPresentation(presentation);
downloadViewport.render();
}
);
});
@@ -161,7 +171,6 @@ const CornerstoneViewportDownloadForm = ({
downloadViewport.addActor(actor);
});
downloadViewport.setCamera(viewport.getCamera());
downloadViewport.render();
const newWidth = Math.min(width || image.width, MAX_TEXTURE_SIZE);
@@ -109,13 +109,10 @@ export function callLabelAutocompleteDialog(uiDialogService, callback, dialogCon
uiDialogService.create({
id: 'select-annotation',
centralize: true,
isDraggable: false,
showOverlay: true,
content: LabellingFlow,
defaultPosition: {
x: window.innerWidth / 2,
y: window.innerHeight / 2,
},
contentProps: {
labellingDoneCallback: labellingDoneCallback,
measurementData: { label: '' },
+16 -16
View File
@@ -1,4 +1,20 @@
const colormaps = [
{
ColorSpace: 'RGB',
Name: 'Grayscale',
name: 'Grayscale',
NanColor: [1, 0, 0],
RGBPoints: [0, 0, 0, 0, 1, 1, 1, 1],
description: 'Grayscale',
},
{
ColorSpace: 'RGB',
Name: 'X Ray',
name: 'X Ray',
NanColor: [1, 0, 0],
RGBPoints: [0, 1, 1, 1, 1, 0, 0, 0],
description: 'X Ray',
},
{
ColorSpace: 'RGB',
Name: 'hsv',
@@ -1579,22 +1595,6 @@ const colormaps = [
],
description: 'Siemens',
},
{
ColorSpace: 'RGB',
Name: 'X Ray',
name: 'X Ray',
NanColor: [1, 0, 0],
RGBPoints: [0, 1, 1, 1, 1, 0, 0, 0],
description: 'X Ray',
},
{
ColorSpace: 'RGB',
Name: 'Grayscale',
name: 'Grayscale',
NanColor: [1, 0, 0],
RGBPoints: [0, 0, 0, 0, 1, 1, 1, 1],
description: 'Grayscale',
},
];
export { colormaps };
@@ -1,6 +1,8 @@
import { Enums } from '@cornerstonejs/core';
const MIP = 'mip';
const MINIP = 'minip';
const AVG = 'avg';
export default function getCornerstoneBlendMode(blendMode: string): Enums.BlendModes {
if (!blendMode) {
@@ -11,5 +13,13 @@ export default function getCornerstoneBlendMode(blendMode: string): Enums.BlendM
return Enums.BlendModes.MAXIMUM_INTENSITY_BLEND;
}
throw new Error();
if (blendMode.toLowerCase() === MINIP) {
return Enums.BlendModes.MINIMUM_INTENSITY_BLEND;
}
if (blendMode.toLowerCase() === AVG) {
return Enums.BlendModes.AVERAGE_INTENSITY_BLEND;
}
throw new Error(`Unsupported blend mode: ${blendMode}`);
}
@@ -1,10 +1,12 @@
import { DisplaySetService, ViewportGridService } from '@ohif/core';
const IMAGE_SLICE_SYNC_NAME = 'IMAGE_SLICE_SYNC';
export default function toggleImageSliceSync({
servicesManager,
viewports: providedViewports,
syncId,
}) {
}: withAppTypes) {
const { syncGroupService, viewportGridService, displaySetService, cornerstoneViewportService } =
servicesManager.services;
@@ -46,7 +48,7 @@ export default function toggleImageSliceSync({
});
}
function disableSync(syncName, servicesManager) {
function disableSync(syncName, servicesManager: AppTypes.ServicesManager) {
const { syncGroupService, viewportGridService, displaySetService, cornerstoneViewportService } =
servicesManager.services;
const viewports = getReconstructableStackViewports(viewportGridService, displaySetService);
@@ -68,7 +70,10 @@ function disableSync(syncName, servicesManager) {
* Gets the consistent spacing stack viewport types, which are the ones which
* can be navigated using the stack image sync right now.
*/
function getReconstructableStackViewports(viewportGridService, displaySetService) {
function getReconstructableStackViewports(
viewportGridService: ViewportGridService,
displaySetService: DisplaySetService
) {
let { viewports } = viewportGridService.getState();
viewports = [...viewports.values()];
@@ -51,20 +51,27 @@ export default function interleaveCenterLoader({
* listen to it and as the other viewports are created we can set the volumes for them
* since volumes are already started loading.
*/
if (matchDetails.size !== viewportIdVolumeInputArrayMap.size) {
const uniqueViewportVolumeDisplaySetUIDs = new Set();
viewportIdVolumeInputArrayMap.forEach((volumeInputArray, viewportId) => {
volumeInputArray.forEach(volumeInput => {
const { volumeId } = volumeInput;
uniqueViewportVolumeDisplaySetUIDs.add(volumeId);
});
});
const uniqueMatchedDisplaySetUIDs = new Set();
matchDetails.forEach(matchDetail => {
const { displaySetsInfo } = matchDetail;
displaySetsInfo.forEach(({ displaySetInstanceUID }) => {
uniqueMatchedDisplaySetUIDs.add(displaySetInstanceUID);
});
});
if (uniqueViewportVolumeDisplaySetUIDs.size !== uniqueMatchedDisplaySetUIDs.size) {
return;
}
// Check if all the matched volumes are loaded
for (const [_, details] of displaySetsMatchDetails.entries()) {
const { SeriesInstanceUID } = details;
// HangingProtocol has matched, but don't have all the volumes created yet, so return
if (!Array.from(volumeIdMapsToLoad.values()).includes(SeriesInstanceUID)) {
return;
}
}
const volumeIds = Array.from(volumeIdMapsToLoad.keys()).slice();
// get volumes from cache
const volumes = volumeIds.map(volumeId => {
@@ -75,23 +75,27 @@ export default function interleaveTopToBottom({
* listen to it and as the other viewports are created we can set the volumes for them
* since volumes are already started loading.
*/
if (filteredMatchDetails.length !== viewportIdVolumeInputArrayMap.size) {
const uniqueViewportVolumeDisplaySetUIDs = new Set();
viewportIdVolumeInputArrayMap.forEach((volumeInputArray, viewportId) => {
volumeInputArray.forEach(volumeInput => {
const { volumeId } = volumeInput;
uniqueViewportVolumeDisplaySetUIDs.add(volumeId);
});
});
const uniqueMatchedDisplaySetUIDs = new Set();
matchDetails.forEach(matchDetail => {
const { displaySetsInfo } = matchDetail;
displaySetsInfo.forEach(({ displaySetInstanceUID }) => {
uniqueMatchedDisplaySetUIDs.add(displaySetInstanceUID);
});
});
if (uniqueViewportVolumeDisplaySetUIDs.size !== uniqueMatchedDisplaySetUIDs.size) {
return;
}
// Check if all the matched volumes are loaded
for (const [_, details] of displaySetsMatchDetails.entries()) {
const { SeriesInstanceUID, displaySetInstanceUID } = details;
// HangingProtocol has matched, but don't have all the volumes created yet, so return
if (
displaySetsToLoad.has(displaySetInstanceUID) &&
!Array.from(volumeIdMapsToLoad.values()).includes(SeriesInstanceUID)
) {
return;
}
}
const volumeIds = Array.from(volumeIdMapsToLoad.keys()).slice();
// get volumes from cache
const volumes = volumeIds.map(volumeId => {
@@ -16,7 +16,8 @@ const Angle = {
csToolsEventDetail,
displaySetService,
CornerstoneViewportService,
getValueTypeFromToolType
getValueTypeFromToolType,
customizationService
) => {
const { annotation, viewportId } = csToolsEventDetail;
const { metadata, data, annotationUID } = annotation;
@@ -54,8 +55,9 @@ const Angle = {
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
const displayText = getDisplayText(mappedAnnotations, displaySet);
const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);
const displayText = getDisplayText(mappedAnnotations, displaySet, customizationService);
const getReport = () =>
_getReport(mappedAnnotations, points, FrameOfReferenceUID, customizationService);
return {
uid: annotationUID,
@@ -127,7 +129,7 @@ This function is used to convert the measurement data to a format that is
suitable for the report generation (e.g. for the csv report). The report
returns a list of columns and corresponding values.
*/
function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
function _getReport(mappedAnnotations, points, FrameOfReferenceUID, customizationService) {
const columns = [];
const values = [];
@@ -160,7 +162,7 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
};
}
function getDisplayText(mappedAnnotations, displaySet) {
function getDisplayText(mappedAnnotations, displaySet, customizationService) {
if (!mappedAnnotations || !mappedAnnotations.length) {
return '';
}
@@ -14,7 +14,8 @@ const Length = {
csToolsEventDetail,
displaySetService,
cornerstoneViewportService,
getValueTypeFromToolType
getValueTypeFromToolType,
customizationService
) => {
const { annotation, viewportId } = csToolsEventDetail;
const { metadata, data, annotationUID } = annotation;
@@ -52,7 +53,7 @@ const Length = {
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
const displayText = getDisplayText(mappedAnnotations, displaySet);
const displayText = getDisplayText(mappedAnnotations, displaySet, customizationService);
return {
uid: annotationUID,
@@ -106,7 +107,7 @@ function getMappedAnnotations(annotation, displaySetService) {
return annotations;
}
function getDisplayText(mappedAnnotations, displaySet) {
function getDisplayText(mappedAnnotations, displaySet, customizationService) {
if (!mappedAnnotations) {
return '';
}
@@ -11,7 +11,8 @@ const Bidirectional = {
csToolsEventDetail,
displaySetService,
cornerstoneViewportService,
getValueTypeFromToolType
getValueTypeFromToolType,
customizationService
) => {
const { annotation, viewportId } = csToolsEventDetail;
const { metadata, data, annotationUID } = annotation;
@@ -49,8 +50,9 @@ const Bidirectional = {
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
const displayText = getDisplayText(mappedAnnotations, displaySet);
const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);
const displayText = getDisplayText(mappedAnnotations, displaySet, customizationService);
const getReport = () =>
_getReport(mappedAnnotations, points, FrameOfReferenceUID, customizationService);
return {
uid: annotationUID,
@@ -122,7 +124,7 @@ This function is used to convert the measurement data to a format that is
suitable for the report generation (e.g. for the csv report). The report
returns a list of columns and corresponding values.
*/
function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
function _getReport(mappedAnnotations, points, FrameOfReferenceUID, customizationService) {
const columns = [];
const values = [];
@@ -155,7 +157,7 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
};
}
function getDisplayText(mappedAnnotations, displaySet) {
function getDisplayText(mappedAnnotations, displaySet, customizationService) {
if (!mappedAnnotations || !mappedAnnotations.length) {
return '';
}
@@ -2,6 +2,7 @@ import SUPPORTED_TOOLS from './constants/supportedTools';
import { getDisplayUnit } from './utils';
import getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';
import { utils } from '@ohif/core';
import { getStatisticDisplayString } from './utils/getValueDisplayString';
const CircleROI = {
toAnnotation: measurement => {},
@@ -9,7 +10,8 @@ const CircleROI = {
csToolsEventDetail,
DisplaySetService,
CornerstoneViewportService,
getValueTypeFromToolType
getValueTypeFromToolType,
customizationService
) => {
const { annotation, viewportId } = csToolsEventDetail;
const { metadata, data, annotationUID } = annotation;
@@ -47,8 +49,9 @@ const CircleROI = {
const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);
const displayText = getDisplayText(mappedAnnotations, displaySet);
const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);
const displayText = getDisplayText(mappedAnnotations, displaySet, customizationService);
const getReport = () =>
_getReport(mappedAnnotations, points, FrameOfReferenceUID, customizationService);
return {
uid: annotationUID,
@@ -125,7 +128,7 @@ This function is used to convert the measurement data to a format that is
suitable for the report generation (e.g. for the csv report). The report
returns a list of columns and corresponding values.
*/
function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
function _getReport(mappedAnnotations, points, FrameOfReferenceUID, customizationService) {
const columns = [];
const values = [];
@@ -163,7 +166,7 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
};
}
function getDisplayText(mappedAnnotations, displaySet) {
function getDisplayText(mappedAnnotations, displaySet, customizationService) {
if (!mappedAnnotations || !mappedAnnotations.length) {
return '';
}
@@ -191,11 +194,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
mappedAnnotations.forEach(mappedAnnotation => {
const { unit, max, SeriesNumber } = mappedAnnotation;
let maxStr = '';
if (max) {
const roundedMax = utils.roundNumber(max, 2);
maxStr = `Max: ${roundedMax} <small>${getDisplayUnit(unit)}</small> `;
}
const maxStr = getStatisticDisplayString(max, unit, 'max');
const str = `${maxStr}(S:${SeriesNumber}${instanceText}${frameText})`;
if (!displayText.includes(str)) {
@@ -16,7 +16,8 @@ const CobbAngle = {
csToolsEventDetail,
displaySetService,
CornerstoneViewportService,
getValueTypeFromToolType
getValueTypeFromToolType,
customizationService
) => {
const { annotation, viewportId } = csToolsEventDetail;
const { metadata, data, annotationUID } = annotation;
@@ -54,8 +55,9 @@ const CobbAngle = {
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
const displayText = getDisplayText(mappedAnnotations, displaySet);
const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);
const displayText = getDisplayText(mappedAnnotations, displaySet, customizationService);
const getReport = () =>
_getReport(mappedAnnotations, points, FrameOfReferenceUID, customizationService);
return {
uid: annotationUID,
@@ -127,7 +129,7 @@ This function is used to convert the measurement data to a format that is
suitable for the report generation (e.g. for the csv report). The report
returns a list of columns and corresponding values.
*/
function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
function _getReport(mappedAnnotations, points, FrameOfReferenceUID, customizationService) {
const columns = [];
const values = [];
@@ -160,7 +162,7 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
};
}
function getDisplayText(mappedAnnotations, displaySet) {
function getDisplayText(mappedAnnotations, displaySet, customizationService) {
if (!mappedAnnotations || !mappedAnnotations.length) {
return '';
}
Loaded 100 of 385 files, more files were not shown because too many files have changed in this diff. Show more