Compare commits

..
Author SHA1 Message Date
ohif-bot 79d5c36bda chore(version): Update package versions [skip ci] 2024-03-25 15:44:13 +00:00
ohif-bot f47a94317d chore(version): version.json [skip ci] 2024-03-25 15:44:04 +00:00
Ibrahim 45b68e841d feat(worklist): new investigational use text (#3999) 2024-03-25 11:33:24 -04:00
ohif-bot d70aae3233 chore(version): Update package versions [skip ci] 2024-03-19 00:37:56 +00:00
ohif-bot 345b137bec chore(version): version.json [skip ci] 2024-03-19 00:37:48 +00:00
Ibrahim 9bcd1ae6f5 feat(worklist): New worklist buttons and tooltips (#3989) 2024-03-18 20:27:12 -04:00
ohif-bot 6b79dff5c1 chore(version): Update package versions [skip ci] 2024-03-18 18:38:23 +00:00
ohif-bot 88859f75d5 chore(version): version.json [skip ci] 2024-03-18 18:38:16 +00:00
Alireza feed2304c1 fix(SR display): and the token based navigation (#3995) 2024-03-18 14:27:17 -04:00
ohif-bot 08815909c7 chore(version): Update package versions [skip ci] 2024-03-15 13:52:45 +00:00
ohif-bot ed2234a67c chore(version): version.json [skip ci] 2024-03-15 13:52:34 +00:00
Pedro H. Köhler f7fe91c5f6 feat(delete measurement): icon for measurement table (#3775) 2024-03-15 09:35:29 -04:00
ohif-bot 21ec6860f2 chore(version): Update package versions [skip ci] 2024-03-08 13:38:48 +00:00
ohif-bot ac474b7f8f chore(version): version.json [skip ci] 2024-03-08 13:38:41 +00:00
EricB e485d68fd4 fix(cli): mode creation template (#3876) (#3981) 2024-03-08 08:27:37 -05:00
ohif-bot 5089229ff9 chore(version): Update package versions [skip ci] 2024-03-05 16:15:56 +00:00
ohif-bot df09176d63 chore(version): version.json [skip ci] 2024-03-05 16:15:48 +00:00
EricB bb603bd1f8 docs: Typo (#3975) 2024-03-05 11:04:28 -05:00
ohif-bot 82a4a7d377 chore(version): Update package versions [skip ci] 2024-02-28 17:25:27 +00:00
ohif-bot c27fa9c802 chore(version): version.json [skip ci] 2024-02-28 17:25:19 +00:00
EricB 4cdfdae814 fix(docs): Minor typos in hpModule.md (#3962) 2024-02-28 12:13:46 -05:00
ohif-bot 596340803a chore(version): Update package versions [skip ci] 2024-02-22 19:54:20 +00:00
ohif-bot ff4e17f5c2 chore(version): version.json [skip ci] 2024-02-22 19:54:11 +00:00
Bill Wallace 21e8a2bd0b fix(demo): Deploy issue (#3951) 2024-02-22 14:42:46 -05:00
ohif-bot 2a442e30eb chore(version): Update package versions [skip ci] 2024-02-21 18:59:56 +00:00
ohif-bot 8e8a66bd29 chore(version): version.json [skip ci] 2024-02-21 18:59:49 +00:00
Alireza b3a0faf5f5 feat(resize): Optimize resizing process and maintain zoom level (#3889) 2024-02-21 13:49:23 -05:00
ohif-bot a2a0090eeb chore(version): Update package versions [skip ci] 2024-02-14 14:02:25 +00:00
ohif-bot ea552027c5 chore(version): version.json [skip ci] 2024-02-14 14:02:17 +00:00
Ibrahim 0eac386a31 feat(errorboundary): format stack trace properly (#3931) 2024-02-14 08:51:17 -05:00
ohif-bot 40b590d75a chore(version): Update package versions [skip ci] 2024-02-05 19:01:43 +00:00
ohif-bot 01df1763ce chore(version): version.json [skip ci] 2024-02-05 19:01:34 +00:00
Igor Octaviano 5bba98ed84 fix: 🐛 Sort merge results based on default data source (input) (#3903) 2024-02-05 13:46:47 -05:00
ohif-bot 16785936d9 chore(version): Update package versions [skip ci] 2024-01-22 20:52:46 +00:00
ohif-bot 3deb73d642 chore(version): version.json [skip ci] 2024-01-22 20:52:38 +00:00
m00n620 ef46b5a704 fix toggleHpTools to support split primary button (#3900)
Fixes a small bug in toggling buttons with hanging protocols.
2024-01-22 15:42:51 -05:00
ohif-bot ed2bf23cd2 chore(version): Update package versions [skip ci] 2024-01-22 15:07:51 +00:00
ohif-bot 2ff2f3f34d chore(version): version.json [skip ci] 2024-01-22 15:07:43 +00:00
Patrick Wespi a47aeb8bd7 fix: catch errors in getPTImageIdInstanceMetadata (#3897) 2024-01-22 09:58:22 -05:00
ohif-bot 94f40192f5 chore(version): Update package versions [skip ci] 2024-01-22 14:55:27 +00:00
ohif-bot 1c43aa791a chore(version): version.json [skip ci] 2024-01-22 14:55:17 +00:00
Alireza e4a116b074 fix(viewport-sync): remember synced viewports bw stack and volume and RENAME StackImageSync to ImageSliceSync (#3849) 2024-01-22 09:44:35 -05:00
ohif-bot 2460d28afc chore(version): Update package versions [skip ci] 2024-01-19 13:30:55 +00:00
ohif-bot 4a958b8989 chore(version): version.json [skip ci] 2024-01-19 13:30:47 +00:00
Pedro H. Köhler 31b837fa90 fix: is same orientaiton (#3905) 2024-01-19 08:21:22 -05:00
ohif-bot 9bb00d71fa chore(version): Update package versions [skip ci] 2024-01-17 16:01:31 +00:00
ohif-bot 40bbe33a9d chore(version): version.json [skip ci] 2024-01-17 16:01:24 +00:00
Igor Octaviano 911d672835 fix: 🐛 Check merge key for merge data source (#3901) 2024-01-17 10:51:49 -05:00
ohif-bot 9c553fded4 chore(version): Update package versions [skip ci] 2024-01-12 16:10:06 +00:00
ohif-bot 144dd39393 chore(version): version.json [skip ci] 2024-01-12 16:09:58 +00:00
AbishekBista9 df2f50748e docs: Update architecture.md (#3891) 2024-01-12 11:00:17 -05:00
ohif-bot 83a1523408 chore(version): Update package versions [skip ci] 2024-01-12 13:58:08 +00:00
ohif-bot 5a62a983e5 chore(version): version.json [skip ci] 2024-01-12 13:57:58 +00:00
Bill Wallace d00a86b022 fix: Update CS3D to fix second render (#3892) 2024-01-12 08:48:15 -05:00
ohif-bot 710a2dca72 chore(version): Update package versions [skip ci] 2024-01-09 19:31:20 +00:00
ohif-bot 9100b1f02e chore(version): version.json [skip ci] 2024-01-09 19:31:10 +00:00
0049f4c030 feat(hp): enable OHIF to run with partial metadata for large studies at the cost of less effective hanging protocol (#3804)
Co-authored-by: rodrigobasilio2022 <rodrigo.basilio@radicalimaging.com>
Co-authored-by: rodrigobasilio2022 <114958722+rodrigobasilio2022@users.noreply.github.com>
2024-01-09 14:22:00 -05:00
ohif-bot b5cdf88a57 chore(version): Update package versions [skip ci] 2024-01-09 17:45:39 +00:00
ohif-bot c793df727b chore(version): version.json [skip ci] 2024-01-09 17:45:30 +00:00
Alireza 1456a493d6 feat(transferSyntax): prefer server transcoded transfer syntax for all images (#3883) 2024-01-09 12:36:29 -05:00
ohif-bot 7c551f5043 chore(version): Update package versions [skip ci] 2024-01-09 15:24:36 +00:00
ohif-bot 0b2c2a235f chore(version): version.json [skip ci] 2024-01-09 15:24:28 +00:00
Alireza b1efe40aa1 fix(segmentation): upgrade cs3d to fix various segmentation bugs (#3885) 2024-01-09 10:15:56 -05:00
ohif-bot a8a0bdb2df chore(version): Update package versions [skip ci] 2024-01-08 19:34:59 +00:00
ohif-bot 6878c1a264 chore(version): version.json [skip ci] 2024-01-08 19:34:49 +00:00
AbishekBista9 d181eb4fdc docs: Update user-account-control.md (#3877) 2024-01-08 14:24:42 -05:00
ohif-bot fd809e4a0b chore(version): Update package versions [skip ci] 2024-01-08 19:21:13 +00:00
ohif-bot 4c29670d76 chore(version): version.json [skip ci] 2024-01-08 19:21:04 +00:00
Igor Octaviano f58725ce40 feat: Add on mode init hook (#3882) 2024-01-08 14:12:26 -05:00
ohif-bot 5a1cb842f0 chore(version): Update package versions [skip ci] 2024-01-08 19:08:04 +00:00
ohif-bot c5bd79552a chore(version): version.json [skip ci] 2024-01-08 19:07:56 +00:00
Sofien-Sellami 61bf22c6f8 feat(ui): sidePanel expandedWidth (#3728) 2024-01-08 13:59:20 -05:00
ohif-bot 3d98548072 chore(version): Update package versions [skip ci] 2024-01-08 18:53:43 +00:00
ohif-bot bf9770a55c chore(version): version.json [skip ci] 2024-01-08 18:53:35 +00:00
Pedro H. KöhlerandIgor Octaviano 2049c0936c feat: improve disableEditing flag (#3875)
Co-authored-by: Igor Octaviano <igoroctaviano@gmail.com>
2024-01-08 13:45:24 -05:00
ohif-bot 7d5607073d chore(version): Update package versions [skip ci] 2024-01-08 18:24:06 +00:00
ohif-bot 1b6910bf76 chore(version): version.json [skip ci] 2024-01-08 18:23:58 +00:00
Bill WallaceandAlireza 98650302c7 fix: PDF display request in v3 (#3878)
Co-authored-by: Alireza <ar.sedghi@gmail.com>
2024-01-08 13:15:54 -05:00
Salim Kanoun bf846c94c3 fix: convert radian to degree value for mip rotation (#3881) 2024-01-08 13:09:22 -05:00
ohif-bot b5dc9047ba chore(version): Update package versions [skip ci] 2024-01-08 17:37:17 +00:00
ohif-bot 636d8b0458 chore(version): version.json [skip ci] 2024-01-08 17:37:08 +00:00
Celian-abd e8858f3eb5 fix: colormap for stack viewports via HangingProtocol (#3866) 2024-01-08 12:28:22 -05:00
ohif-bot eb7c950d7e chore(version): Update package versions [skip ci] 2023-12-15 02:56:03 +00:00
ohif-bot c6214d66b9 chore(version): version.json [skip ci] 2023-12-15 02:55:55 +00:00
Alireza 0eb502aaf0 chore(version): upgrade cornerstone3D versions to fix orientation (#3854) 2023-12-14 21:47:15 -05:00
ohif-bot 44a5a24d4f chore(version): Update package versions [skip ci] 2023-12-14 03:48:22 +00:00
ohif-bot b0bf5dc780 chore(version): version.json [skip ci] 2023-12-14 03:48:15 +00:00
Alireza 5915fada83 chore(version): upgrade cornerstone3D versions (#3853) 2023-12-13 22:39:41 -05:00
ohif-bot 2fa335c6d9 chore(version): Update package versions [skip ci] 2023-12-13 21:37:11 +00:00
ohif-bot de4ad88a09 chore(version): version.json [skip ci] 2023-12-13 21:37:03 +00:00
Sofien-Sellami 6ca13c0a4c fix(icon-style): Ensure consistent icon dimensions (#3727) 2023-12-13 16:28:20 -05:00
Pedro H. Köhler 0177b625ba feat(overlay): add inline binary overlays (#3852) 2023-12-13 16:18:49 -05:00
ohif-bot c4064acfbc chore(version): Update package versions [skip ci] 2023-12-13 20:27:22 +00:00
ohif-bot 7a05d169ef chore(version): version.json [skip ci] 2023-12-13 20:27:14 +00:00
dxlin 13d0c883f8 docs: Update HangingProtocolService.md doc sameAs example to contain constr… (#3765) 2023-12-13 15:18:15 -05:00
ohif-bot c45f60dce2 chore(version): Update package versions [skip ci] 2023-12-13 20:11:48 +00:00
ohif-bot 7bb2713c5c chore(version): version.json [skip ci] 2023-12-13 20:11:39 +00:00
Celian-abdandAlireza 97cb1f94e1 fix(dicom-seg) : Fix the missing color tag when loading Dicom-Seg (#3822)
Co-authored-by: Alireza <ar.sedghi@gmail.com>
2023-12-13 15:03:09 -05:00
ohif-bot f99645f3a1 chore(version): Update package versions [skip ci] 2023-12-13 19:55:36 +00:00
ohif-bot ae16c7f972 chore(version): version.json [skip ci] 2023-12-13 19:55:28 +00:00
Salim Kanoun 9c6e1cd305 Fix(HPService): custom image load performed is now reset to false on HP exit (#3809) 2023-12-13 14:47:12 -05:00
ohif-bot 7f0ca857fa chore(version): Update package versions [skip ci] 2023-12-13 19:29:55 +00:00
ohif-bot 920256d3a4 chore(version): version.json [skip ci] 2023-12-13 19:29:48 +00:00
Pedro H. Köhler e1f55e65f2 feat(customizationService): Enable saving and loading of private tags in SRs (#3842) 2023-12-13 14:21:46 -05:00
ohif-bot d1c07d90f0 chore(version): Update package versions [skip ci] 2023-12-13 15:29:16 +00:00
ohif-bot b1a04ecac3 chore(version): version.json [skip ci] 2023-12-13 15:29:09 +00:00
Sofien-Sellami f707b4ebc9 feat(config): Add activateViewportBeforeInteraction parameter for viewport interaction customization (#3847) 2023-12-13 10:17:48 -05:00
Pedro H. Köhler 805c53270f fix: address and improve system vulnerabilities (#3851) 2023-12-13 09:25:41 -05:00
Pavel d14a8f0199 feat(i18n): enhanced i18n support (#3761) 2023-12-11 09:43:58 -05:00
ohif-bot 5a5c4f58af chore(version): Update package versions [skip ci] 2023-12-08 14:35:30 +00:00
ohif-bot 6e5d8b691e chore(version): version.json [skip ci] 2023-12-08 14:35:23 +00:00
Joe Boccanfuso 59576d695d feat(HP): Added new 3D hanging protocols to be used in the new layout selector (#3844) 2023-12-08 09:25:57 -05:00
ohif-bot 78d4bea04d chore(version): Update package versions [skip ci] 2023-12-06 13:37:37 +00:00
ohif-bot 806c2f4b36 chore(version): version.json [skip ci] 2023-12-06 13:37:29 +00:00
Alireza 6651008fbb fix(auth): fix the issue with oauth at a non root path (#3840) 2023-12-06 08:28:02 -05:00
ohif-bot 74c98b6e9f chore(version): Update package versions [skip ci] 2023-11-28 18:18:13 +00:00
ohif-bot ecee25b1d5 chore(version): version.json [skip ci] 2023-11-28 18:18:03 +00:00
Alireza f1a67647ae fix(SM): drag and drop is now fixed for SM (#3813) 2023-11-28 13:04:30 -05:00
ohif-bot 4f9a00f872 chore(version): Update package versions [skip ci] 2023-11-27 13:36:36 +00:00
ohif-bot 7673a887e4 chore(version): version.json [skip ci] 2023-11-27 13:36:29 +00:00
Joe Boccanfuso 924affa7b5 fix(cine): Set cine disabled on mode exit. (#3812) 2023-11-27 08:27:38 -05:00
ohif-bot abac6f583e chore(version): Update package versions [skip ci] 2023-11-24 22:41:51 +00:00
ohif-bot 36ba20d6e8 chore(version): version.json [skip ci] 2023-11-24 22:41:42 +00:00
Bill Wallace 9d1884d7d8 fix: Update the CS3D packages to add the most recent HTJ2K TSUIDS (#3806) 2023-11-24 17:32:19 -05:00
ohif-bot 622f18bd3e chore(version): Update package versions [skip ci] 2023-11-24 13:56:33 +00:00
ohif-bot 8b6256e76f chore(version): version.json [skip ci] 2023-11-24 13:56:24 +00:00
Igor Octaviano c4ff2c2f09 feat: Merge Data Source (#3788)
Add the ability to merge two different series queries to generate a complete study query result.  Provides basic support for other types of merges, but those aren't yet added as full features.
2023-11-24 08:46:54 -05:00
ohif-bot 1be5613946 chore(version): Update package versions [skip ci] 2023-11-21 17:47:19 +00:00
ohif-bot 6edb1c1e4c chore(version): version.json [skip ci] 2023-11-21 17:47:12 +00:00
Pedro H. Köhler 404b0a5d53 feat(events): broadcast series summary metadata (#3798) 2023-11-21 12:38:08 -05:00
ohif-bot 786898fd63 chore(version): Update package versions [skip ci] 2023-11-21 14:15:45 +00:00
ohif-bot dfa851600c chore(version): version.json [skip ci] 2023-11-21 14:15:37 +00:00
Bill Wallace 00e751933a fix(DICOM Overlay): The overlay data wasn't being refreshed on change (#3793) 2023-11-21 09:05:25 -05:00
ohif-bot c4e22c251f chore(version): Update package versions [skip ci] 2023-11-21 02:33:40 +00:00
ohif-bot 3cf4b6dea5 chore(version): version.json [skip ci] 2023-11-21 02:33:32 +00:00
Bill Wallace 8c8924af37 fix(metadata): to handle cornerstone3D update for htj2k (#3783) 2023-11-20 21:23:42 -05:00
ohif-bot 04121e3713 chore(version): Update package versions [skip ci] 2023-11-18 01:18:27 +00:00
ohif-bot d1eef6dbdb chore(version): version.json [skip ci] 2023-11-18 01:18:18 +00:00
Joe Boccanfuso d83beb7c62 feat(docs): Added various training videos to support the OHIF CLI tools (#3794) 2023-11-17 20:08:38 -05:00
ohif-bot 7867b29742 chore(version): Update package versions [skip ci] 2023-11-15 14:46:52 +00:00
ohif-bot 4a6f1bd407 chore(version): version.json [skip ci] 2023-11-15 14:46:44 +00:00
Igor Octaviano b694228dd5 feat(url): Add SeriesInstanceUIDs wado query param (#3746) 2023-11-15 09:37:09 -05:00
ohif-bot 013068bcb0 chore(version): Update package versions [skip ci] 2023-11-13 15:52:59 +00:00
ohif-bot 3fbc23b04c chore(version): version.json [skip ci] 2023-11-13 15:52:50 +00:00
Igor Octaviano 323401418e fix: 🐛 Run error handler for failed image requests (#3773) 2023-11-13 10:42:55 -05:00
ohif-bot fc438e90ae chore(version): Update package versions [skip ci] 2023-11-13 14:00:34 +00:00
ohif-bot 9b7f38467b chore(version): version.json [skip ci] 2023-11-13 14:00:27 +00:00
Bill Wallace fd1251f751 fix(overlay): Overlays aren't shown on undefined origin (#3781) 2023-11-13 08:50:58 -05:00
ohif-bot 14793493a4 chore(version): Update package versions [skip ci] 2023-11-10 22:00:19 +00:00
ohif-bot 73d8848707 chore(version): version.json [skip ci] 2023-11-10 22:00:11 +00:00
Alireza 43b1c17209 feat(dicomJSON): Add Loading Other Display Sets and JSON Metadata Generation script (#3777) 2023-11-10 16:51:23 -05:00
ohif-bot 5b513fd30e chore(version): Update package versions [skip ci] 2023-11-10 14:07:30 +00:00
ohif-bot 26c9567c38 chore(version): version.json [skip ci] 2023-11-10 14:07:23 +00:00
Pedro H. Köhler 8bbcd0e692 fix(path): upgrade docusaurus for security (#3780) 2023-11-10 08:54:40 -05:00
ohif-bot 8c2f495405 chore(version): Update package versions [skip ci] 2023-11-09 04:13:50 +00:00
ohif-bot e1e1e60b7d chore(version): version.json [skip ci] 2023-11-09 04:13:43 +00:00
edwardyangxin 8af1046803 fix(arrow): ArrowAnnotate text key cause validation error (#3771) 2023-11-08 23:04:55 -05:00
ohif-bot 4bbba871f5 chore(version): Update package versions [skip ci] 2023-11-08 21:09:51 +00:00
ohif-bot 73e804c311 chore(version): version.json [skip ci] 2023-11-08 21:09:42 +00:00
Pedro H. Köhler 442f99d5eb feat: add VolumeViewport rotation (#3776) 2023-11-08 16:00:18 -05:00
ohif-bot 9575a6f54c chore(version): Update package versions [skip ci] 2023-11-08 14:28:55 +00:00
ohif-bot dc345d1875 chore(version): version.json [skip ci] 2023-11-08 14:28:48 +00:00
AlirezaandOuwen Huang bf252bcec2 feat(hp callback): Add viewport ready callback (#3772)
Co-authored-by: Ouwen Huang <ouwen.huang@duke.edu>
2023-11-08 09:19:49 -05:00
ohif-bot 1a68c06c3b chore(version): Update package versions [skip ci] 2023-11-03 16:29:50 +00:00
ohif-bot a2361fa615 chore(version): version.json [skip ci] 2023-11-03 16:29:42 +00:00
Alireza ee67bcc0f5 docs(faq): FAQ and Segmentation Mode Fix for some studies (#3762) 2023-11-03 12:19:24 -04:00
ohif-bot f9f16bc69f chore(version): Update package versions [skip ci] 2023-11-02 16:17:30 +00:00
ohif-bot a29f5bc9d3 chore(version): version.json [skip ci] 2023-11-02 16:17:20 +00:00
Joe Boccanfuso b23eeff937 fix(thumbnail): Avoid multiple promise creations for thumbnails (#3756) 2023-11-02 12:07:52 -04:00
ohif-bot 09ff293f5f chore(version): Update package versions [skip ci] 2023-10-31 19:49:41 +00:00
ohif-bot 71a30dc9f2 chore(version): version.json [skip ci] 2023-10-31 19:49:31 +00:00
Pavel 330e11c7ff feat(i18n): enhanced i18n support (#3730) 2023-10-31 15:36:45 -04:00
ohif-bot c73a403cdc chore(version): Update package versions [skip ci] 2023-10-30 15:01:05 +00:00
ohif-bot 5b3b6eed16 chore(version): version.json [skip ci] 2023-10-30 15:00:58 +00:00
Joe Boccanfusoandladeirarodolfo 2a15ef0e44 feat(filters): save worklist query filters to session storage so that they persist between navigation to the viewer and back (#3749)
Co-authored-by: ladeirarodolfo <39910206+ladeirarodolfo@users.noreply.github.com>
2023-10-30 10:47:43 -04:00
Joe Boccanfuso db395852b6 fix(measurement service): Implemented correct check of schema keys in _isValidMeasurment. (#3750) 2023-10-30 10:44:21 -04:00
ohif-bot 423ba7c269 chore(version): Update package versions [skip ci] 2023-10-25 17:17:55 +00:00
ohif-bot cafba997bf chore(version): version.json [skip ci] 2023-10-25 17:17:47 +00:00
Bill WallaceandJoe Boccanfuso dd6d9768bb fix(toolbar): allow customizable toolbar for active viewport and allow active tool to be deactivated via a click (#3608)
Co-authored-by: Joe Boccanfuso <joe.boccanfuso@radicalimaging.com>
2023-10-25 13:08:12 -04:00
ohif-bot 2145b42920 chore(version): Update package versions [skip ci] 2023-10-24 17:20:41 +00:00
ohif-bot a5ad1cc02a chore(version): version.json [skip ci] 2023-10-24 17:20:32 +00:00
Joe Boccanfuso d98439fe7f fix(sr): dcm4chee requires the patient name for an SR to match what is in the original study (#3739) 2023-10-24 13:06:12 -04:00
ohif-bot 3bbbcea0d7 chore(version): Update package versions [skip ci] 2023-10-23 14:03:11 +00:00
ohif-bot 6e993511b7 chore(version): version.json [skip ci] 2023-10-23 14:03:01 +00:00
bluesteel23 eec9c33b76 docs(azure): Azure static Deployment details (#3740) 2023-10-23 09:53:43 -04:00
ohif-bot c31c7f8e79 chore(version): Update package versions [skip ci] 2023-10-23 13:23:07 +00:00
ohif-bot a7125f9385 chore(version): version.json [skip ci] 2023-10-23 13:22:59 +00:00
edwardyangxin 49514aedfe fix(recipes): package.json script orthanc:up docker-compose path (#3741) 2023-10-23 09:13:24 -04:00
ohif-bot 43c882ac87 chore(version): Update package versions [skip ci] 2023-10-19 17:39:23 +00:00
ohif-bot 912b3c7c53 chore(version): version.json [skip ci] 2023-10-19 17:39:15 +00:00
d9258eca70 fix(cine): Use the frame rate specified in DICOM and optionally auto play cine (#3735)
Co-authored-by: rareramos <rareramos1126@gmail.com>
Co-authored-by: Doug Horner <horner@mieweb.com>
Co-authored-by: Rehan <58819707+Rayhan-011@users.noreply.github.com>
2023-10-19 13:29:44 -04:00
ohif-bot fa599d05fb chore(version): Update package versions [skip ci] 2023-10-19 17:10:43 +00:00
ohif-bot 5f8325e338 chore(version): version.json [skip ci] 2023-10-19 17:10:36 +00:00
Joe Boccanfuso 93d798db99 fix(calibration): No calibration popup caused by perhaps an unused code optimization for production builds (#3736) 2023-10-19 13:02:03 -04:00
ohif-bot 33f1259408 chore(version): Update package versions [skip ci] 2023-10-12 21:18:38 +00:00
ohif-bot c54658a320 chore(version): version.json [skip ci] 2023-10-12 21:18:31 +00:00
Alireza 55002fbd71 chore(version): move to the next beta version [BUMP BETA] 2023-10-12 17:09:44 -04:00
ohif-bot 3f9ee1451b chore(version): Update package versions [skip ci] 2023-10-11 16:10:32 +00:00
ohif-bot 70ea13ec1f chore(version): version.json [skip ci] 2023-10-11 16:10:25 +00:00
Alireza 157b88c909 fix(display messages): broken after timings (#3719) 2023-10-11 12:01:32 -04:00
ohif-bot 75c3f94177 chore(version): Update package versions [skip ci] 2023-10-11 14:19:25 +00:00
ohif-bot 6874d5f0b9 chore(version): version.json [skip ci] 2023-10-11 14:19:16 +00:00
Alireza a3f2a1a7b0 fix(export): wrong export for the tmtv RT function (#3715) 2023-10-11 10:10:29 -04:00
ohif-bot 8067f0c62c chore(version): Update package versions [skip ci] 2023-10-10 19:30:50 +00:00
ohif-bot a894b6ffc5 chore(version): version.json [skip ci] 2023-10-10 19:30:41 +00:00
Joe Boccanfuso c3a5847dcd fix(i18n): display set(s) are two words for English messages (#3711) 2023-10-10 15:20:47 -04:00
ohif-bot 132938bbe0 chore(version): Update package versions [skip ci] 2023-10-10 17:32:24 +00:00
ohif-bot 5ba63bd010 chore(version): version.json [skip ci] 2023-10-10 17:32:14 +00:00
Alireza 7c57f67844 fix(modules): add stylus loader as an option to be uncommented (#3710) 2023-10-10 13:21:17 -04:00
ohif-bot dc929d3df5 chore(version): Update package versions [skip ci] 2023-10-10 14:36:12 +00:00
ohif-bot 5a3af83168 chore(version): version.json [skip ci] 2023-10-10 14:36:03 +00:00
Joe Boccanfuso a9a6ad50ea fix(segmentation): Various fixes for segmentation mode and other (#3709) 2023-10-10 10:25:30 -04:00
ohif-bot f8455056cd chore(version): Update package versions [skip ci] 2023-10-10 00:58:12 +00:00
ohif-bot f9c3d510d3 chore(version): version.json [skip ci] 2023-10-10 00:58:05 +00:00
Alireza 52f34c64d0 fix(voi): should publish voi change event on reset (#3707) 2023-10-09 20:49:10 -04:00
ohif-bot 7d87766ac4 chore(version): Update package versions [skip ci] 2023-10-09 17:58:57 +00:00
ohif-bot 820bb83b70 chore(version): version.json [skip ci] 2023-10-09 17:58:49 +00:00
Alireza 0a42d573bb fix(modality unit): fix the modality unit per target via upgrade of cs3d (#3706) 2023-10-09 13:48:31 -04:00
ohif-bot f9f33f74c1 chore(version): Update package versions [skip ci] 2023-10-09 15:13:37 +00:00
ohif-bot 6a5fe59136 chore(version): version.json [skip ci] 2023-10-09 15:13:28 +00:00
Alireza 4911e4796c fix(segmentation): do not use SAB if not specified (#3705) 2023-10-09 11:02:49 -04:00
ohif-bot 349c503f04 chore(version): Update package versions [skip ci] 2023-10-06 19:14:47 +00:00
ohif-bot a6a6aed361 chore(version): version.json [skip ci] 2023-10-06 19:14:40 +00:00
dxlinandAlireza 40673f64b3 feat(Segmentation): download RTSS from Labelmap(#3692)
Co-authored-by: Alireza <ar.sedghi@gmail.com>
2023-10-06 15:00:04 -04:00
373 changed files with 26278 additions and 6657 deletions

No files matched your search

+1 -1
View File
@@ -13,7 +13,7 @@ version: 2.1
##
orbs:
codecov: codecov/codecov@1.0.5
cypress: cypress-io/cypress@3.1.4
cypress: cypress-io/cypress@3.2.1
executors:
cypress-custom:
+265
View File
@@ -0,0 +1,265 @@
/*
* This script uses nodejs to generate a JSON file from a DICOM study folder.
* You need to have dcmjs installed in your project.
* The JSON file can be used to load the study into the OHIF Viewer. You can get more detail
* in the DICOM JSON Data source on docs.ohif.org
*
* Usage: node dicomStudyToJSONLaunch.js <studyFolder> <urlPrefix> <outputJSONPath>
*
* params:
* - studyFolder: path to the study folder
* - urlPrefix: prefix to the url that will be used to load the study into the viewer. For instance
* we use https://ohif-assets.s3.us-east-2.amazonaws.com/dicom-json/data as the urlPrefix for the
* example since the data is hosted on S3 and each study is in a folder. So the url in the generated
* json file for the first instance of the first series of the first study will be
* dicomweb:https://ohif-assets.s3.us-east-2.amazonaws.com/dicom-json/data/Series1/Instance1
* - outputJSONPath: path to the output JSON file
*/
const dcmjs = require('dcmjs');
const path = require('path');
const fs = require('fs').promises;
const args = process.argv.slice(2);
const [studyDirectory, urlPrefix, outputPath] = args;
if (args.length !== 3) {
console.error('Usage: node dicomStudyToJSONLaunch.js <studyFolder> <urlPrefix> <outputJSONPath>');
process.exit(1);
}
const model = {
studies: [],
};
async function convertDICOMToJSON(studyDirectory, urlPrefix, outputPath) {
try {
const files = await recursiveReadDir(studyDirectory);
console.debug('Processing...');
for (const file of files) {
if (!file.includes('.DS_Store') && !file.includes('.xml')) {
const arrayBuffer = await fs.readFile(file);
const dicomDict = dcmjs.data.DicomMessage.readFile(arrayBuffer.buffer);
const instance = dcmjs.data.DicomMetaDictionary.naturalizeDataset(dicomDict.dict);
instance.fileLocation = createImageId(file, urlPrefix, studyDirectory);
processInstance(instance);
}
}
console.log('Successfully loaded data');
model.studies.forEach(study => {
study.NumInstances = findInstancesNumber(study);
study.Modalities = findModalities(study).join('/');
});
await fs.writeFile(outputPath, JSON.stringify(model, null, 2));
console.log('JSON saved');
} catch (error) {
console.error(error);
}
}
async function recursiveReadDir(dir) {
let results = [];
const list = await fs.readdir(dir);
for (const file of list) {
const filePath = path.resolve(dir, file);
const stat = await fs.stat(filePath);
if (stat.isDirectory()) {
const res = await recursiveReadDir(filePath);
results = results.concat(res);
} else {
results.push(filePath);
}
}
return results;
}
function createImageId(fileLocation, urlPrefix, studyDirectory) {
const relativePath = path.relative(studyDirectory, fileLocation);
const normalizedPath = path.normalize(relativePath).replace(/\\/g, '/');
return `dicomweb:${urlPrefix}${normalizedPath}`;
}
function processInstance(instance) {
const { StudyInstanceUID, SeriesInstanceUID } = instance;
let study = getStudy(StudyInstanceUID);
if (!study) {
study = createStudyMetadata(StudyInstanceUID, instance);
model.studies.push(study);
}
let series = getSeries(StudyInstanceUID, SeriesInstanceUID);
if (!series) {
series = createSeriesMetadata(instance);
study.series.push(series);
}
const instanceMetaData =
instance.NumberOfFrames > 1
? createInstanceMetaDataMultiFrame(instance)
: createInstanceMetaData(instance);
series.instances.push(...[].concat(instanceMetaData));
}
function getStudy(StudyInstanceUID) {
return model.studies.find(study => study.StudyInstanceUID === StudyInstanceUID);
}
function getSeries(StudyInstanceUID, SeriesInstanceUID) {
const study = getStudy(StudyInstanceUID);
return study
? study.series.find(series => series.SeriesInstanceUID === SeriesInstanceUID)
: undefined;
}
const findInstancesNumber = study => {
let numInstances = 0;
study.series.forEach(aSeries => {
numInstances = numInstances + aSeries.instances.length;
});
return numInstances;
};
const findModalities = study => {
let modalities = new Set();
study.series.forEach(aSeries => {
modalities.add(aSeries.Modality);
});
return Array.from(modalities);
};
function createStudyMetadata(StudyInstanceUID, instance) {
return {
StudyInstanceUID,
StudyDescription: instance.StudyDescription,
StudyDate: instance.StudyDate,
StudyTime: instance.StudyTime,
PatientName: instance.PatientName,
PatientID: instance.PatientID || '1234', // this is critical to have
AccessionNumber: instance.AccessionNumber,
PatientAge: instance.PatientAge,
PatientSex: instance.PatientSex,
PatientWeight: instance.PatientWeight,
series: [],
};
}
function createSeriesMetadata(instance) {
return {
SeriesInstanceUID: instance.SeriesInstanceUID,
SeriesDescription: instance.SeriesDescription,
SeriesNumber: instance.SeriesNumber,
SeriesTime: instance.SeriesTime,
Modality: instance.Modality,
SliceThickness: instance.SliceThickness,
instances: [],
};
}
function commonMetaData(instance) {
return {
Columns: instance.Columns,
Rows: instance.Rows,
InstanceNumber: instance.InstanceNumber,
SOPClassUID: instance.SOPClassUID,
AcquisitionNumber: instance.AcquisitionNumber,
PhotometricInterpretation: instance.PhotometricInterpretation,
BitsAllocated: instance.BitsAllocated,
BitsStored: instance.BitsStored,
PixelRepresentation: instance.PixelRepresentation,
SamplesPerPixel: instance.SamplesPerPixel,
PixelSpacing: instance.PixelSpacing,
HighBit: instance.HighBit,
ImageOrientationPatient: instance.ImageOrientationPatient,
ImagePositionPatient: instance.ImagePositionPatient,
FrameOfReferenceUID: instance.FrameOfReferenceUID,
ImageType: instance.ImageType,
Modality: instance.Modality,
SOPInstanceUID: instance.SOPInstanceUID,
SeriesInstanceUID: instance.SeriesInstanceUID,
StudyInstanceUID: instance.StudyInstanceUID,
WindowCenter: instance.WindowCenter,
WindowWidth: instance.WindowWidth,
RescaleIntercept: instance.RescaleIntercept,
RescaleSlope: instance.RescaleSlope,
};
}
function conditionalMetaData(instance) {
return {
...(instance.ConceptNameCodeSequence && {
ConceptNameCodeSequence: instance.ConceptNameCodeSequence,
}),
...(instance.SeriesDate && { SeriesDate: instance.SeriesDate }),
...(instance.ReferencedSeriesSequence && {
ReferencedSeriesSequence: instance.ReferencedSeriesSequence,
}),
...(instance.SharedFunctionalGroupsSequence && {
SharedFunctionalGroupsSequence: instance.SharedFunctionalGroupsSequence,
}),
...(instance.PerFrameFunctionalGroupsSequence && {
PerFrameFunctionalGroupsSequence: instance.PerFrameFunctionalGroupsSequence,
}),
...(instance.ContentSequence && { ContentSequence: instance.ContentSequence }),
...(instance.ContentTemplateSequence && {
ContentTemplateSequence: instance.ContentTemplateSequence,
}),
...(instance.CurrentRequestedProcedureEvidenceSequence && {
CurrentRequestedProcedureEvidenceSequence: instance.CurrentRequestedProcedureEvidenceSequence,
}),
...(instance.CodingSchemeIdentificationSequence && {
CodingSchemeIdentificationSequence: instance.CodingSchemeIdentificationSequence,
}),
...(instance.RadiopharmaceuticalInformationSequence && {
RadiopharmaceuticalInformationSequence: instance.RadiopharmaceuticalInformationSequence,
}),
...(instance.ROIContourSequence && {
ROIContourSequence: instance.ROIContourSequence,
}),
...(instance.StructureSetROISequence && {
StructureSetROISequence: instance.StructureSetROISequence,
}),
...(instance.ReferencedFrameOfReferenceSequence && {
ReferencedFrameOfReferenceSequence: instance.ReferencedFrameOfReferenceSequence,
}),
...(instance.CorrectedImage && { CorrectedImage: instance.CorrectedImage }),
...(instance.Units && { Units: instance.Units }),
...(instance.DecayCorrection && { DecayCorrection: instance.DecayCorrection }),
...(instance.AcquisitionDate && { AcquisitionDate: instance.AcquisitionDate }),
...(instance.AcquisitionTime && { AcquisitionTime: instance.AcquisitionTime }),
...(instance.PatientWeight && { PatientWeight: instance.PatientWeight }),
...(instance.NumberOfFrames && { NumberOfFrames: instance.NumberOfFrames }),
...(instance.FrameTime && { FrameTime: instance.FrameTime }),
...(instance.EncapsulatedDocument && { EncapsulatedDocument: instance.EncapsulatedDocument }),
...(instance.SequenceOfUltrasoundRegions && {
SequenceOfUltrasoundRegions: instance.SequenceOfUltrasoundRegions,
}),
};
}
function createInstanceMetaData(instance) {
const metadata = {
...commonMetaData(instance),
...conditionalMetaData(instance),
};
return { metadata, url: instance.fileLocation };
}
function createInstanceMetaDataMultiFrame(instance) {
const instances = [];
const commonData = commonMetaData(instance);
const conditionalData = conditionalMetaData(instance);
for (let i = 1; i <= instance.NumberOfFrames; i++) {
const metadata = { ...commonData, ...conditionalData };
const result = { metadata, url: instance.fileLocation + `?frame=${i}` };
instances.push(result);
}
return instances;
}
convertDICOMToJSON(studyDirectory, urlPrefix, outputPath);
+1 -1
View File
@@ -31,6 +31,6 @@
"prettier.endOfLine": "lf",
"workbench.colorCustomizations": {},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.eslint": "explicit"
}
}
+10
View File
@@ -0,0 +1,10 @@
const stylusToJavaScript = {
test: /\.styl$/,
use: [
{ loader: 'style-loader' }, // 3. Style nodes from JS Strings
{ loader: 'css-loader' }, // 2. CSS to CommonJS
{ loader: 'stylus-loader' }, // 1. Stylus to CSS
],
};
module.exports = stylusToJavaScript;
+4
View File
@@ -18,6 +18,7 @@ const loadShadersRule = require('./rules/loadShaders.js');
const loadWebWorkersRule = require('./rules/loadWebWorkers.js');
const transpileJavaScriptRule = require('./rules/transpileJavaScript.js');
const cssToJavaScript = require('./rules/cssToJavaScript.js');
const stylusToJavaScript = require('./rules/stylusToJavaScript.js');
// ~~ ENV VARS
const NODE_ENV = process.env.NODE_ENV;
@@ -112,6 +113,9 @@ module.exports = (env, argv, { SRC_DIR, ENTRY }) => {
},
},
cssToJavaScript,
// Note: Only uncomment the following if you are using the old style of stylus in v2
// Also you need to uncomment this platform/app/.webpack/rules/extractStyleChunks.js
// stylusToJavaScript,
{
test: /\.wasm/,
type: 'asset/resource',
+784
View File
@@ -3,6 +3,790 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.8.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.62...v3.8.0-beta.63) (2024-03-25)
### Features
* **worklist:** new investigational use text ([#3999](https://github.com/OHIF/Viewers/issues/3999)) ([45b68e8](https://github.com/OHIF/Viewers/commit/45b68e841dcb9e28a2ea991c37ee7ac4a8c5b71e))
# [3.8.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.61...v3.8.0-beta.62) (2024-03-19)
### Features
* **worklist:** New worklist buttons and tooltips ([#3989](https://github.com/OHIF/Viewers/issues/3989)) ([9bcd1ae](https://github.com/OHIF/Viewers/commit/9bcd1ae6f51d61786cc1e99624f396b56a47cd69))
# [3.8.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.60...v3.8.0-beta.61) (2024-03-18)
### Bug Fixes
* **SR display:** and the token based navigation ([#3995](https://github.com/OHIF/Viewers/issues/3995)) ([feed230](https://github.com/OHIF/Viewers/commit/feed2304c124dc2facc7a7371ed9851548c223c5))
# [3.8.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.59...v3.8.0-beta.60) (2024-03-15)
### Features
* **delete measurement:** icon for measurement table ([#3775](https://github.com/OHIF/Viewers/issues/3775)) ([f7fe91c](https://github.com/OHIF/Viewers/commit/f7fe91c5f6c4f05f3f3f5f640d3a119bd40a5870))
# [3.8.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.58...v3.8.0-beta.59) (2024-03-08)
### Bug Fixes
* **cli:** mode creation template ([#3876](https://github.com/OHIF/Viewers/issues/3876)) ([#3981](https://github.com/OHIF/Viewers/issues/3981)) ([e485d68](https://github.com/OHIF/Viewers/commit/e485d68fd4619ce7187113cbe59e47f9523dbcc8))
# [3.8.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.57...v3.8.0-beta.58) (2024-03-05)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.56...v3.8.0-beta.57) (2024-02-28)
### Bug Fixes
* **docs:** Minor typos in hpModule.md ([#3962](https://github.com/OHIF/Viewers/issues/3962)) ([4cdfdae](https://github.com/OHIF/Viewers/commit/4cdfdae8149166cf9dc91a55c0d7f2a224e55d8f))
# [3.8.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.55...v3.8.0-beta.56) (2024-02-22)
### Bug Fixes
* **demo:** Deploy issue ([#3951](https://github.com/OHIF/Viewers/issues/3951)) ([21e8a2b](https://github.com/OHIF/Viewers/commit/21e8a2bd0b7cc72f90a31e472d285d761be15d30))
# [3.8.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.54...v3.8.0-beta.55) (2024-02-21)
### Features
* **resize:** Optimize resizing process and maintain zoom level ([#3889](https://github.com/OHIF/Viewers/issues/3889)) ([b3a0faf](https://github.com/OHIF/Viewers/commit/b3a0faf5f5f0a1993b2b017eb4cc1216164ea2c6))
# [3.8.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.53...v3.8.0-beta.54) (2024-02-14)
### Features
* **errorboundary:** format stack trace properly ([#3931](https://github.com/OHIF/Viewers/issues/3931)) ([0eac386](https://github.com/OHIF/Viewers/commit/0eac386a31a5d6965536360aa65a44769c1a5740))
# [3.8.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.52...v3.8.0-beta.53) (2024-02-05)
### Bug Fixes
* 🐛 Sort merge results based on default data source (input) ([#3903](https://github.com/OHIF/Viewers/issues/3903)) ([5bba98e](https://github.com/OHIF/Viewers/commit/5bba98ed848bdf46b5ba4fc4708527cced3308b5))
# [3.8.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.51...v3.8.0-beta.52) (2024-01-22)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.50...v3.8.0-beta.51) (2024-01-22)
### Bug Fixes
* catch errors in getPTImageIdInstanceMetadata ([#3897](https://github.com/OHIF/Viewers/issues/3897)) ([a47aeb8](https://github.com/OHIF/Viewers/commit/a47aeb8bd729dcb8d2cfc13b27a31b0dd88f11ad))
# [3.8.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.49...v3.8.0-beta.50) (2024-01-22)
### Bug Fixes
* **viewport-sync:** remember synced viewports bw stack and volume and RENAME StackImageSync to ImageSliceSync ([#3849](https://github.com/OHIF/Viewers/issues/3849)) ([e4a116b](https://github.com/OHIF/Viewers/commit/e4a116b074fcb85c8cbcc9db44fdec565f3386db))
# [3.8.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.48...v3.8.0-beta.49) (2024-01-19)
### Bug Fixes
* is same orientaiton ([#3905](https://github.com/OHIF/Viewers/issues/3905)) ([31b837f](https://github.com/OHIF/Viewers/commit/31b837fa90f631d4984482c6e952373fbb8bdbfc))
# [3.8.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.47...v3.8.0-beta.48) (2024-01-17)
### Bug Fixes
* 🐛 Check merge key for merge data source ([#3901](https://github.com/OHIF/Viewers/issues/3901)) ([911d672](https://github.com/OHIF/Viewers/commit/911d67283536b2fe7930948f2819ea0ad66e2a32))
# [3.8.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.46...v3.8.0-beta.47) (2024-01-12)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.45...v3.8.0-beta.46) (2024-01-12)
### Bug Fixes
* Update CS3D to fix second render ([#3892](https://github.com/OHIF/Viewers/issues/3892)) ([d00a86b](https://github.com/OHIF/Viewers/commit/d00a86b022742ea089d246d06cfd691f43b64412))
# [3.8.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.44...v3.8.0-beta.45) (2024-01-09)
### Features
* **hp:** enable OHIF to run with partial metadata for large studies at the cost of less effective hanging protocol ([#3804](https://github.com/OHIF/Viewers/issues/3804)) ([0049f4c](https://github.com/OHIF/Viewers/commit/0049f4c0303f0b6ea995972326fc8784259f5a47))
# [3.8.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.43...v3.8.0-beta.44) (2024-01-09)
### Features
* **transferSyntax:** prefer server transcoded transfer syntax for all images ([#3883](https://github.com/OHIF/Viewers/issues/3883)) ([1456a49](https://github.com/OHIF/Viewers/commit/1456a493d66c90c787b022256c9f2846afb115fc))
# [3.8.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.42...v3.8.0-beta.43) (2024-01-09)
### Bug Fixes
* **segmentation:** upgrade cs3d to fix various segmentation bugs ([#3885](https://github.com/OHIF/Viewers/issues/3885)) ([b1efe40](https://github.com/OHIF/Viewers/commit/b1efe40aa146e4052cc47b3f774cabbb47a8d1a6))
# [3.8.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.41...v3.8.0-beta.42) (2024-01-08)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.40...v3.8.0-beta.41) (2024-01-08)
### Features
* Add on mode init hook ([#3882](https://github.com/OHIF/Viewers/issues/3882)) ([f58725c](https://github.com/OHIF/Viewers/commit/f58725ce40685f7297181ef98d81bc28420c8291))
# [3.8.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.39...v3.8.0-beta.40) (2024-01-08)
### Features
* **ui:** sidePanel expandedWidth ([#3728](https://github.com/OHIF/Viewers/issues/3728)) ([61bf22c](https://github.com/OHIF/Viewers/commit/61bf22c6f80e764bdf5c3b56bb0124a95aa0f793))
# [3.8.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.38...v3.8.0-beta.39) (2024-01-08)
### Features
* improve disableEditing flag ([#3875](https://github.com/OHIF/Viewers/issues/3875)) ([2049c09](https://github.com/OHIF/Viewers/commit/2049c0936c86f819604c243d3dc7b3fe971b5b2c))
# [3.8.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.37...v3.8.0-beta.38) (2024-01-08)
### Bug Fixes
* convert radian to degree value for mip rotation ([#3881](https://github.com/OHIF/Viewers/issues/3881)) ([bf846c9](https://github.com/OHIF/Viewers/commit/bf846c94c378f04b9f44dcd71be3f056dbcfe0b5))
* PDF display request in v3 ([#3878](https://github.com/OHIF/Viewers/issues/3878)) ([9865030](https://github.com/OHIF/Viewers/commit/98650302c7575f0aea386e32cfc4112c378035e6))
# [3.8.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.36...v3.8.0-beta.37) (2024-01-08)
### Bug Fixes
* colormap for stack viewports via HangingProtocol ([#3866](https://github.com/OHIF/Viewers/issues/3866)) ([e8858f3](https://github.com/OHIF/Viewers/commit/e8858f3eb55552f695af4a55980f9ae2e9af7291))
# [3.8.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.35...v3.8.0-beta.36) (2023-12-15)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.34...v3.8.0-beta.35) (2023-12-14)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.33...v3.8.0-beta.34) (2023-12-13)
### Bug Fixes
* **icon-style:** Ensure consistent icon dimensions ([#3727](https://github.com/OHIF/Viewers/issues/3727)) ([6ca13c0](https://github.com/OHIF/Viewers/commit/6ca13c0a4cb5a95bbb52b0db902b5dbf72f8aa6e))
### Features
* **overlay:** add inline binary overlays ([#3852](https://github.com/OHIF/Viewers/issues/3852)) ([0177b62](https://github.com/OHIF/Viewers/commit/0177b625ba86760168bc4db58c8a109aa9ee83cb))
# [3.8.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.32...v3.8.0-beta.33) (2023-12-13)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.31...v3.8.0-beta.32) (2023-12-13)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.30...v3.8.0-beta.31) (2023-12-13)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.29...v3.8.0-beta.30) (2023-12-13)
### Features
* **customizationService:** Enable saving and loading of private tags in SRs ([#3842](https://github.com/OHIF/Viewers/issues/3842)) ([e1f55e6](https://github.com/OHIF/Viewers/commit/e1f55e65f2d2a34136ad5d0b1ada77d337a0ea23))
# [3.8.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.28...v3.8.0-beta.29) (2023-12-13)
### Bug Fixes
* address and improve system vulnerabilities ([#3851](https://github.com/OHIF/Viewers/issues/3851)) ([805c532](https://github.com/OHIF/Viewers/commit/805c53270f243ec61f142a3ffa0af500021cd5ec))
### Features
* **config:** Add activateViewportBeforeInteraction parameter for viewport interaction customization ([#3847](https://github.com/OHIF/Viewers/issues/3847)) ([f707b4e](https://github.com/OHIF/Viewers/commit/f707b4ebc996f379cd30337badc06b07e6e35ac5))
* **i18n:** enhanced i18n support ([#3761](https://github.com/OHIF/Viewers/issues/3761)) ([d14a8f0](https://github.com/OHIF/Viewers/commit/d14a8f0199db95cd9e85866a011b64d6bf830d57))
# [3.8.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.27...v3.8.0-beta.28) (2023-12-08)
### Features
* **HP:** Added new 3D hanging protocols to be used in the new layout selector ([#3844](https://github.com/OHIF/Viewers/issues/3844)) ([59576d6](https://github.com/OHIF/Viewers/commit/59576d695d4d26601d35c43f73d602f0b12d72bf))
# [3.8.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.26...v3.8.0-beta.27) (2023-12-06)
### Bug Fixes
* **auth:** fix the issue with oauth at a non root path ([#3840](https://github.com/OHIF/Viewers/issues/3840)) ([6651008](https://github.com/OHIF/Viewers/commit/6651008fbb35dabd5991c7f61128e6ef324012df))
# [3.8.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.25...v3.8.0-beta.26) (2023-11-28)
### Bug Fixes
* **SM:** drag and drop is now fixed for SM ([#3813](https://github.com/OHIF/Viewers/issues/3813)) ([f1a6764](https://github.com/OHIF/Viewers/commit/f1a67647aed635437b188cea7cf5d5a8fb974bbe))
# [3.8.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.24...v3.8.0-beta.25) (2023-11-27)
### Bug Fixes
* **cine:** Set cine disabled on mode exit. ([#3812](https://github.com/OHIF/Viewers/issues/3812)) ([924affa](https://github.com/OHIF/Viewers/commit/924affa7b5d420c2f91522a075cecbb3c78e8f52))
# [3.8.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.23...v3.8.0-beta.24) (2023-11-24)
### Bug Fixes
* Update the CS3D packages to add the most recent HTJ2K TSUIDS ([#3806](https://github.com/OHIF/Viewers/issues/3806)) ([9d1884d](https://github.com/OHIF/Viewers/commit/9d1884d7d8b6b2a1cdc26965a96995838aa72682))
# [3.8.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.22...v3.8.0-beta.23) (2023-11-24)
### Features
* Merge Data Source ([#3788](https://github.com/OHIF/Viewers/issues/3788)) ([c4ff2c2](https://github.com/OHIF/Viewers/commit/c4ff2c2f09546ce8b72eab9c5e7beed611e3cab0))
# [3.8.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.21...v3.8.0-beta.22) (2023-11-21)
### Features
* **events:** broadcast series summary metadata ([#3798](https://github.com/OHIF/Viewers/issues/3798)) ([404b0a5](https://github.com/OHIF/Viewers/commit/404b0a5d535182d1ae44e33f7232db500a7b2c16))
# [3.8.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.20...v3.8.0-beta.21) (2023-11-21)
### Bug Fixes
* **DICOM Overlay:** The overlay data wasn't being refreshed on change ([#3793](https://github.com/OHIF/Viewers/issues/3793)) ([00e7519](https://github.com/OHIF/Viewers/commit/00e751933ac6d611a34773fa69594243f1b99082))
# [3.8.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.19...v3.8.0-beta.20) (2023-11-21)
### Bug Fixes
* **metadata:** to handle cornerstone3D update for htj2k ([#3783](https://github.com/OHIF/Viewers/issues/3783)) ([8c8924a](https://github.com/OHIF/Viewers/commit/8c8924af373d906773f5db20defe38628cacd4a0))
# [3.8.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.18...v3.8.0-beta.19) (2023-11-18)
### Features
* **docs:** Added various training videos to support the OHIF CLI tools ([#3794](https://github.com/OHIF/Viewers/issues/3794)) ([d83beb7](https://github.com/OHIF/Viewers/commit/d83beb7c62c1d5be19c54e08d23883f112147fe1))
# [3.8.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.17...v3.8.0-beta.18) (2023-11-15)
### Features
* **url:** Add SeriesInstanceUIDs wado query param ([#3746](https://github.com/OHIF/Viewers/issues/3746)) ([b694228](https://github.com/OHIF/Viewers/commit/b694228dd535e4b97cb86a1dc085b6e8716bdaf3))
# [3.8.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.16...v3.8.0-beta.17) (2023-11-13)
### Bug Fixes
* 🐛 Run error handler for failed image requests ([#3773](https://github.com/OHIF/Viewers/issues/3773)) ([3234014](https://github.com/OHIF/Viewers/commit/323401418e7ccab74655ba02f990bbe0ed4e523b))
# [3.8.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.15...v3.8.0-beta.16) (2023-11-13)
### Bug Fixes
* **overlay:** Overlays aren't shown on undefined origin ([#3781](https://github.com/OHIF/Viewers/issues/3781)) ([fd1251f](https://github.com/OHIF/Viewers/commit/fd1251f751d8147b8a78c7f4d81c67ba69769afa))
# [3.8.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.14...v3.8.0-beta.15) (2023-11-10)
### Features
* **dicomJSON:** Add Loading Other Display Sets and JSON Metadata Generation script ([#3777](https://github.com/OHIF/Viewers/issues/3777)) ([43b1c17](https://github.com/OHIF/Viewers/commit/43b1c17209502e4876ad59bae09ed9442eda8024))
# [3.8.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.13...v3.8.0-beta.14) (2023-11-10)
### Bug Fixes
* **path:** upgrade docusaurus for security ([#3780](https://github.com/OHIF/Viewers/issues/3780)) ([8bbcd0e](https://github.com/OHIF/Viewers/commit/8bbcd0e692e25917c1b6dd94a39fac834c812fca))
# [3.8.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.12...v3.8.0-beta.13) (2023-11-09)
### Bug Fixes
* **arrow:** ArrowAnnotate text key cause validation error ([#3771](https://github.com/OHIF/Viewers/issues/3771)) ([8af1046](https://github.com/OHIF/Viewers/commit/8af10468035f1f59e0a21e579d50ad63c8cbf7ad))
# [3.8.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.11...v3.8.0-beta.12) (2023-11-08)
### Features
* add VolumeViewport rotation ([#3776](https://github.com/OHIF/Viewers/issues/3776)) ([442f99d](https://github.com/OHIF/Viewers/commit/442f99d5eb2ceece7def20e14da59af1dd7d8442))
# [3.8.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.10...v3.8.0-beta.11) (2023-11-08)
### Features
* **hp callback:** Add viewport ready callback ([#3772](https://github.com/OHIF/Viewers/issues/3772)) ([bf252bc](https://github.com/OHIF/Viewers/commit/bf252bcec2aae3a00479fdcb732110b344bcf2c0))
# [3.8.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.9...v3.8.0-beta.10) (2023-11-03)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.8...v3.8.0-beta.9) (2023-11-02)
### Bug Fixes
* **thumbnail:** Avoid multiple promise creations for thumbnails ([#3756](https://github.com/OHIF/Viewers/issues/3756)) ([b23eeff](https://github.com/OHIF/Viewers/commit/b23eeff93745769e67e60c33d75293d6242c5ec9))
# [3.8.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.7...v3.8.0-beta.8) (2023-10-31)
### Features
* **i18n:** enhanced i18n support ([#3730](https://github.com/OHIF/Viewers/issues/3730)) ([330e11c](https://github.com/OHIF/Viewers/commit/330e11c7ff0151e1096e19b8ffdae7d64cae280e))
# [3.8.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.6...v3.8.0-beta.7) (2023-10-30)
### Bug Fixes
* **measurement service:** Implemented correct check of schema keys in _isValidMeasurment. ([#3750](https://github.com/OHIF/Viewers/issues/3750)) ([db39585](https://github.com/OHIF/Viewers/commit/db395852b6fc6cd5c265a9282e5eee5bd6f951b7))
### Features
* **filters:** save worklist query filters to session storage so that they persist between navigation to the viewer and back ([#3749](https://github.com/OHIF/Viewers/issues/3749)) ([2a15ef0](https://github.com/OHIF/Viewers/commit/2a15ef0e44b7b4d8bbf5cb9363db6e523201c681))
# [3.8.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.5...v3.8.0-beta.6) (2023-10-25)
### Bug Fixes
* **toolbar:** allow customizable toolbar for active viewport and allow active tool to be deactivated via a click ([#3608](https://github.com/OHIF/Viewers/issues/3608)) ([dd6d976](https://github.com/OHIF/Viewers/commit/dd6d9768bbca1d3cc472e8c1e6d85822500b96ef))
# [3.8.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.4...v3.8.0-beta.5) (2023-10-24)
### Bug Fixes
* **sr:** dcm4chee requires the patient name for an SR to match what is in the original study ([#3739](https://github.com/OHIF/Viewers/issues/3739)) ([d98439f](https://github.com/OHIF/Viewers/commit/d98439fe7f3825076dbc87b664a1d1480ff414d3))
# [3.8.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.3...v3.8.0-beta.4) (2023-10-23)
**Note:** Version bump only for package ohif-monorepo-root
# [3.8.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.2...v3.8.0-beta.3) (2023-10-23)
### Bug Fixes
* **recipes:** package.json script orthanc:up docker-compose path ([#3741](https://github.com/OHIF/Viewers/issues/3741)) ([49514ae](https://github.com/OHIF/Viewers/commit/49514aedfe0498b5bd505193106a9745a6a5b5e6))
# [3.8.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.1...v3.8.0-beta.2) (2023-10-19)
### Bug Fixes
* **cine:** Use the frame rate specified in DICOM and optionally auto play cine ([#3735](https://github.com/OHIF/Viewers/issues/3735)) ([d9258ec](https://github.com/OHIF/Viewers/commit/d9258eca70587cf4dc18be4e56c79b16bae73d6d))
# [3.8.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.0...v3.8.0-beta.1) (2023-10-19)
### Bug Fixes
* **calibration:** No calibration popup caused by perhaps an unused code optimization for production builds ([#3736](https://github.com/OHIF/Viewers/issues/3736)) ([93d798d](https://github.com/OHIF/Viewers/commit/93d798db99c0dee53ef73c376f8a74ac3049cf3f))
# [3.8.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.8.0-beta.0) (2023-10-12)
**Note:** Version bump only for package ohif-monorepo-root
# [3.7.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.109...v3.7.0-beta.110) (2023-10-11)
### Bug Fixes
* **display messages:** broken after timings ([#3719](https://github.com/OHIF/Viewers/issues/3719)) ([157b88c](https://github.com/OHIF/Viewers/commit/157b88c909d3289cb89ace731c1f9a19d40797ac))
# [3.7.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.108...v3.7.0-beta.109) (2023-10-11)
### Bug Fixes
* **export:** wrong export for the tmtv RT function ([#3715](https://github.com/OHIF/Viewers/issues/3715)) ([a3f2a1a](https://github.com/OHIF/Viewers/commit/a3f2a1a7b0d16bfcc0ecddc2ab731e54c5e377c8))
# [3.7.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.107...v3.7.0-beta.108) (2023-10-10)
### Bug Fixes
* **i18n:** display set(s) are two words for English messages ([#3711](https://github.com/OHIF/Viewers/issues/3711)) ([c3a5847](https://github.com/OHIF/Viewers/commit/c3a5847dcd3dce4f1c8d8b11af95f79e3f93f70d))
# [3.7.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.106...v3.7.0-beta.107) (2023-10-10)
### Bug Fixes
* **modules:** add stylus loader as an option to be uncommented ([#3710](https://github.com/OHIF/Viewers/issues/3710)) ([7c57f67](https://github.com/OHIF/Viewers/commit/7c57f67844b790fc6e47ac3f9708bf9d576389c8))
# [3.7.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.105...v3.7.0-beta.106) (2023-10-10)
### Bug Fixes
* **segmentation:** Various fixes for segmentation mode and other ([#3709](https://github.com/OHIF/Viewers/issues/3709)) ([a9a6ad5](https://github.com/OHIF/Viewers/commit/a9a6ad50eae67b43b8b34efc07182d788cacdcfe))
# [3.7.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.104...v3.7.0-beta.105) (2023-10-10)
### Bug Fixes
* **voi:** should publish voi change event on reset ([#3707](https://github.com/OHIF/Viewers/issues/3707)) ([52f34c6](https://github.com/OHIF/Viewers/commit/52f34c64d014f433ec1661a39b47e7fb27f15332))
# [3.7.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.103...v3.7.0-beta.104) (2023-10-09)
### Bug Fixes
* **modality unit:** fix the modality unit per target via upgrade of cs3d ([#3706](https://github.com/OHIF/Viewers/issues/3706)) ([0a42d57](https://github.com/OHIF/Viewers/commit/0a42d573bbca7f2551a831a46d3aa6b56674a580))
# [3.7.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.102...v3.7.0-beta.103) (2023-10-09)
### Bug Fixes
* **segmentation:** do not use SAB if not specified ([#3705](https://github.com/OHIF/Viewers/issues/3705)) ([4911e47](https://github.com/OHIF/Viewers/commit/4911e4796cef5e22cb7cc0ca73dc5c956bc75339))
# [3.7.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.101...v3.7.0-beta.102) (2023-10-06)
### Features
* **Segmentation:** download RTSS from Labelmap([#3692](https://github.com/OHIF/Viewers/issues/3692)) ([40673f6](https://github.com/OHIF/Viewers/commit/40673f64b36b1150149c55632aa1825178a39e65))
# [3.7.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.100...v3.7.0-beta.101) (2023-10-06)
+4
View File
@@ -17,6 +17,10 @@ provided by the <a href="https://ohif.org/">Open Health Imaging Foundation (OHIF
<div align="center">
📰 <a href="https://ohif.org/news/"><strong>Join OHIF Newsletter</strong></a> 📰
</div>
<div align="center">
📰 <a href="https://ohif.org/news/"><strong>Join OHIF Newsletter</strong></a> 📰
</div>
<hr />
+2
View File
@@ -26,6 +26,7 @@ module.exports = {
'@babel/plugin-transform-typescript',
['@babel/plugin-proposal-private-property-in-object', { loose: true }],
['@babel/plugin-proposal-private-methods', { loose: true }],
'@babel/plugin-transform-class-static-block',
],
env: {
test: {
@@ -45,6 +46,7 @@ module.exports = {
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-transform-regenerator',
'@babel/transform-destructuring',
'@babel/plugin-transform-runtime',
'@babel/plugin-transform-typescript',
],
+1 -1
View File
@@ -1 +1 @@
8bc12a37d0353160ae5ea4624dc0b244b7d59c07
45b68e841dcb9e28a2ea991c37ee7ac4a8c5b71e
@@ -3,6 +3,599 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.8.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.62...v3.8.0-beta.63) (2024-03-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.61...v3.8.0-beta.62) (2024-03-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.60...v3.8.0-beta.61) (2024-03-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.59...v3.8.0-beta.60) (2024-03-15)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.58...v3.8.0-beta.59) (2024-03-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.57...v3.8.0-beta.58) (2024-03-05)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.56...v3.8.0-beta.57) (2024-02-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.55...v3.8.0-beta.56) (2024-02-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.54...v3.8.0-beta.55) (2024-02-21)
### Features
* **resize:** Optimize resizing process and maintain zoom level ([#3889](https://github.com/OHIF/Viewers/issues/3889)) ([b3a0faf](https://github.com/OHIF/Viewers/commit/b3a0faf5f5f0a1993b2b017eb4cc1216164ea2c6))
# [3.8.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.53...v3.8.0-beta.54) (2024-02-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.52...v3.8.0-beta.53) (2024-02-05)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.51...v3.8.0-beta.52) (2024-01-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.50...v3.8.0-beta.51) (2024-01-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.49...v3.8.0-beta.50) (2024-01-22)
### Bug Fixes
* **viewport-sync:** remember synced viewports bw stack and volume and RENAME StackImageSync to ImageSliceSync ([#3849](https://github.com/OHIF/Viewers/issues/3849)) ([e4a116b](https://github.com/OHIF/Viewers/commit/e4a116b074fcb85c8cbcc9db44fdec565f3386db))
# [3.8.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.48...v3.8.0-beta.49) (2024-01-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.47...v3.8.0-beta.48) (2024-01-17)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.46...v3.8.0-beta.47) (2024-01-12)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.45...v3.8.0-beta.46) (2024-01-12)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.44...v3.8.0-beta.45) (2024-01-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.43...v3.8.0-beta.44) (2024-01-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.42...v3.8.0-beta.43) (2024-01-09)
### Bug Fixes
* **segmentation:** upgrade cs3d to fix various segmentation bugs ([#3885](https://github.com/OHIF/Viewers/issues/3885)) ([b1efe40](https://github.com/OHIF/Viewers/commit/b1efe40aa146e4052cc47b3f774cabbb47a8d1a6))
# [3.8.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.41...v3.8.0-beta.42) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.40...v3.8.0-beta.41) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.39...v3.8.0-beta.40) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.38...v3.8.0-beta.39) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.37...v3.8.0-beta.38) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.36...v3.8.0-beta.37) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.35...v3.8.0-beta.36) (2023-12-15)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.34...v3.8.0-beta.35) (2023-12-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.33...v3.8.0-beta.34) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.32...v3.8.0-beta.33) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.31...v3.8.0-beta.32) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.30...v3.8.0-beta.31) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.29...v3.8.0-beta.30) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.28...v3.8.0-beta.29) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.27...v3.8.0-beta.28) (2023-12-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.26...v3.8.0-beta.27) (2023-12-06)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.25...v3.8.0-beta.26) (2023-11-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.24...v3.8.0-beta.25) (2023-11-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.23...v3.8.0-beta.24) (2023-11-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.22...v3.8.0-beta.23) (2023-11-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.21...v3.8.0-beta.22) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.20...v3.8.0-beta.21) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.19...v3.8.0-beta.20) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.18...v3.8.0-beta.19) (2023-11-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.17...v3.8.0-beta.18) (2023-11-15)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.16...v3.8.0-beta.17) (2023-11-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.15...v3.8.0-beta.16) (2023-11-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.14...v3.8.0-beta.15) (2023-11-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.13...v3.8.0-beta.14) (2023-11-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.12...v3.8.0-beta.13) (2023-11-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.11...v3.8.0-beta.12) (2023-11-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.10...v3.8.0-beta.11) (2023-11-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.9...v3.8.0-beta.10) (2023-11-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.8...v3.8.0-beta.9) (2023-11-02)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.7...v3.8.0-beta.8) (2023-10-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.6...v3.8.0-beta.7) (2023-10-30)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.5...v3.8.0-beta.6) (2023-10-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.4...v3.8.0-beta.5) (2023-10-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.3...v3.8.0-beta.4) (2023-10-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.2...v3.8.0-beta.3) (2023-10-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.1...v3.8.0-beta.2) (2023-10-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.0...v3.8.0-beta.1) (2023-10-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.8.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.8.0-beta.0) (2023-10-12)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.7.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.109...v3.7.0-beta.110) (2023-10-11)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.7.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.108...v3.7.0-beta.109) (2023-10-11)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.7.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.107...v3.7.0-beta.108) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.7.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.106...v3.7.0-beta.107) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.7.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.105...v3.7.0-beta.106) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.7.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.104...v3.7.0-beta.105) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.7.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.103...v3.7.0-beta.104) (2023-10-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.7.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.102...v3.7.0-beta.103) (2023-10-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.7.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.101...v3.7.0-beta.102) (2023-10-06)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.7.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.100...v3.7.0-beta.101) (2023-10-06)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
+7 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-rt",
"version": "3.7.0-beta.101",
"version": "3.8.0-beta.63",
"description": "DICOM RT read workflow",
"author": "OHIF",
"license": "MIT",
@@ -24,6 +24,8 @@
"yarn": ">=1.18.0"
},
"scripts": {
"clean": "shx rm -rf dist",
"clean:deep": "yarn run clean && shx rm -rf node_modules",
"dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
"dev:dicom-seg": "yarn run dev",
"build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
@@ -31,10 +33,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.101",
"@ohif/extension-cornerstone": "3.7.0-beta.101",
"@ohif/extension-default": "3.7.0-beta.101",
"@ohif/i18n": "3.7.0-beta.101",
"@ohif/core": "3.8.0-beta.63",
"@ohif/extension-cornerstone": "3.8.0-beta.63",
"@ohif/extension-default": "3.8.0-beta.63",
"@ohif/i18n": "3.8.0-beta.63",
"prop-types": "^15.6.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
@@ -168,6 +168,8 @@ function OHIFCornerstoneRTViewport(props) {
}, [servicesManager, viewportId, rtDisplaySet, rtIsLoading]);
useEffect(() => {
// I'm not sure what is this, since in RT we support Overlapping segments
// via contours
const { unsubscribe } = segmentationService.subscribe(
segmentationService.EVENTS.SEGMENTATION_LOADING_COMPLETE,
evt => {
@@ -3,6 +3,620 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.8.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.62...v3.8.0-beta.63) (2024-03-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.61...v3.8.0-beta.62) (2024-03-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.60...v3.8.0-beta.61) (2024-03-18)
### Bug Fixes
* **SR display:** and the token based navigation ([#3995](https://github.com/OHIF/Viewers/issues/3995)) ([feed230](https://github.com/OHIF/Viewers/commit/feed2304c124dc2facc7a7371ed9851548c223c5))
# [3.8.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.59...v3.8.0-beta.60) (2024-03-15)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.58...v3.8.0-beta.59) (2024-03-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.57...v3.8.0-beta.58) (2024-03-05)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.56...v3.8.0-beta.57) (2024-02-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.55...v3.8.0-beta.56) (2024-02-22)
### Bug Fixes
* **demo:** Deploy issue ([#3951](https://github.com/OHIF/Viewers/issues/3951)) ([21e8a2b](https://github.com/OHIF/Viewers/commit/21e8a2bd0b7cc72f90a31e472d285d761be15d30))
# [3.8.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.54...v3.8.0-beta.55) (2024-02-21)
### Features
* **resize:** Optimize resizing process and maintain zoom level ([#3889](https://github.com/OHIF/Viewers/issues/3889)) ([b3a0faf](https://github.com/OHIF/Viewers/commit/b3a0faf5f5f0a1993b2b017eb4cc1216164ea2c6))
# [3.8.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.53...v3.8.0-beta.54) (2024-02-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.52...v3.8.0-beta.53) (2024-02-05)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.51...v3.8.0-beta.52) (2024-01-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.50...v3.8.0-beta.51) (2024-01-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.49...v3.8.0-beta.50) (2024-01-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.48...v3.8.0-beta.49) (2024-01-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.47...v3.8.0-beta.48) (2024-01-17)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.46...v3.8.0-beta.47) (2024-01-12)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.45...v3.8.0-beta.46) (2024-01-12)
### Bug Fixes
* Update CS3D to fix second render ([#3892](https://github.com/OHIF/Viewers/issues/3892)) ([d00a86b](https://github.com/OHIF/Viewers/commit/d00a86b022742ea089d246d06cfd691f43b64412))
# [3.8.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.44...v3.8.0-beta.45) (2024-01-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.43...v3.8.0-beta.44) (2024-01-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.42...v3.8.0-beta.43) (2024-01-09)
### Bug Fixes
* **segmentation:** upgrade cs3d to fix various segmentation bugs ([#3885](https://github.com/OHIF/Viewers/issues/3885)) ([b1efe40](https://github.com/OHIF/Viewers/commit/b1efe40aa146e4052cc47b3f774cabbb47a8d1a6))
# [3.8.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.41...v3.8.0-beta.42) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.40...v3.8.0-beta.41) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.39...v3.8.0-beta.40) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.38...v3.8.0-beta.39) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.37...v3.8.0-beta.38) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.36...v3.8.0-beta.37) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.35...v3.8.0-beta.36) (2023-12-15)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.34...v3.8.0-beta.35) (2023-12-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.33...v3.8.0-beta.34) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.32...v3.8.0-beta.33) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.31...v3.8.0-beta.32) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.30...v3.8.0-beta.31) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.29...v3.8.0-beta.30) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.28...v3.8.0-beta.29) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.27...v3.8.0-beta.28) (2023-12-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.26...v3.8.0-beta.27) (2023-12-06)
### Bug Fixes
* **auth:** fix the issue with oauth at a non root path ([#3840](https://github.com/OHIF/Viewers/issues/3840)) ([6651008](https://github.com/OHIF/Viewers/commit/6651008fbb35dabd5991c7f61128e6ef324012df))
# [3.8.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.25...v3.8.0-beta.26) (2023-11-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.24...v3.8.0-beta.25) (2023-11-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.23...v3.8.0-beta.24) (2023-11-24)
### Bug Fixes
* Update the CS3D packages to add the most recent HTJ2K TSUIDS ([#3806](https://github.com/OHIF/Viewers/issues/3806)) ([9d1884d](https://github.com/OHIF/Viewers/commit/9d1884d7d8b6b2a1cdc26965a96995838aa72682))
# [3.8.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.22...v3.8.0-beta.23) (2023-11-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.21...v3.8.0-beta.22) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.20...v3.8.0-beta.21) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.19...v3.8.0-beta.20) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.18...v3.8.0-beta.19) (2023-11-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.17...v3.8.0-beta.18) (2023-11-15)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.16...v3.8.0-beta.17) (2023-11-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.15...v3.8.0-beta.16) (2023-11-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.14...v3.8.0-beta.15) (2023-11-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.13...v3.8.0-beta.14) (2023-11-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.12...v3.8.0-beta.13) (2023-11-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.11...v3.8.0-beta.12) (2023-11-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.10...v3.8.0-beta.11) (2023-11-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.9...v3.8.0-beta.10) (2023-11-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.8...v3.8.0-beta.9) (2023-11-02)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.7...v3.8.0-beta.8) (2023-10-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.6...v3.8.0-beta.7) (2023-10-30)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.5...v3.8.0-beta.6) (2023-10-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.4...v3.8.0-beta.5) (2023-10-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.3...v3.8.0-beta.4) (2023-10-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.2...v3.8.0-beta.3) (2023-10-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.1...v3.8.0-beta.2) (2023-10-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.0...v3.8.0-beta.1) (2023-10-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.8.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.8.0-beta.0) (2023-10-12)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.7.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.109...v3.7.0-beta.110) (2023-10-11)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.7.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.108...v3.7.0-beta.109) (2023-10-11)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.7.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.107...v3.7.0-beta.108) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.7.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.106...v3.7.0-beta.107) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.7.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.105...v3.7.0-beta.106) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.7.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.104...v3.7.0-beta.105) (2023-10-10)
### Bug Fixes
* **voi:** should publish voi change event on reset ([#3707](https://github.com/OHIF/Viewers/issues/3707)) ([52f34c6](https://github.com/OHIF/Viewers/commit/52f34c64d014f433ec1661a39b47e7fb27f15332))
# [3.7.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.103...v3.7.0-beta.104) (2023-10-09)
### Bug Fixes
* **modality unit:** fix the modality unit per target via upgrade of cs3d ([#3706](https://github.com/OHIF/Viewers/issues/3706)) ([0a42d57](https://github.com/OHIF/Viewers/commit/0a42d573bbca7f2551a831a46d3aa6b56674a580))
# [3.7.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.102...v3.7.0-beta.103) (2023-10-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.7.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.101...v3.7.0-beta.102) (2023-10-06)
### Features
* **Segmentation:** download RTSS from Labelmap([#3692](https://github.com/OHIF/Viewers/issues/3692)) ([40673f6](https://github.com/OHIF/Viewers/commit/40673f64b36b1150149c55632aa1825178a39e65))
# [3.7.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.100...v3.7.0-beta.101) (2023-10-06)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
+10 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-seg",
"version": "3.7.0-beta.101",
"version": "3.8.0-beta.63",
"description": "DICOM SEG read workflow",
"author": "OHIF",
"license": "MIT",
@@ -24,6 +24,8 @@
"yarn": ">=1.18.0"
},
"scripts": {
"clean": "shx rm -rf dist",
"clean:deep": "yarn run clean && shx rm -rf node_modules",
"dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
"dev:dicom-seg": "yarn run dev",
"build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
@@ -31,10 +33,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.101",
"@ohif/extension-cornerstone": "3.7.0-beta.101",
"@ohif/extension-default": "3.7.0-beta.101",
"@ohif/i18n": "3.7.0-beta.101",
"@ohif/core": "3.8.0-beta.63",
"@ohif/extension-cornerstone": "3.8.0-beta.63",
"@ohif/extension-default": "3.8.0-beta.63",
"@ohif/i18n": "3.8.0-beta.63",
"prop-types": "^15.6.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
@@ -44,7 +46,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/tools": "^1.19.4",
"@cornerstonejs/adapters": "^1.66.7",
"@cornerstonejs/core": "^1.66.7",
"@kitware/vtk.js": "29.7.0",
"react-color": "^2.19.3"
}
}
@@ -2,9 +2,16 @@ import dcmjs from 'dcmjs';
import { createReportDialogPrompt } from '@ohif/extension-default';
import { ServicesManager, Types } from '@ohif/core';
import { cache, metaData } from '@cornerstonejs/core';
import { segmentation as cornerstoneToolsSegmentation } from '@cornerstonejs/tools';
import { adaptersSEG, helpers } from '@cornerstonejs/adapters';
import { DicomMetadataStore } from '@ohif/core';
import {
segmentation as cornerstoneToolsSegmentation,
Enums as cornerstoneToolsEnums,
} from '@cornerstonejs/tools';
import { adaptersRT, helpers, adaptersSEG } from '@cornerstonejs/adapters';
import { classes, DicomMetadataStore } from '@ohif/core';
import vtkImageMarchingSquares from '@kitware/vtk.js/Filters/General/ImageMarchingSquares';
import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
import {
updateViewportsForSegmentationRendering,
@@ -12,12 +19,20 @@ import {
getTargetViewport,
} from './utils/hydrationUtils';
const { datasetToBlob } = dcmjs.data;
const {
Cornerstone3D: {
Segmentation: { generateLabelMaps2DFrom3D, generateSegmentation },
},
} = adaptersSEG;
const {
Cornerstone3D: {
RTSS: { generateRTSSFromSegmentations },
},
} = adaptersRT;
const { downloadDICOMData } = helpers;
const commandsModule = ({
@@ -348,6 +363,40 @@ const commandsModule = ({
return naturalizedReport;
},
/**
* Converts segmentations into RTSS for download.
* This sample function retrieves all segentations and passes to
* cornerstone tool adapter to convert to DICOM RTSS format. It then
* converts dataset to downloadable blob.
*
*/
downloadRTSS: ({ segmentationId }) => {
const segmentations = segmentationService.getSegmentation(segmentationId);
const vtkUtils = {
vtkImageMarchingSquares,
vtkDataArray,
vtkImageData,
};
const RTSS = generateRTSSFromSegmentations(
segmentations,
classes.MetadataProvider,
DicomMetadataStore,
cache,
cornerstoneToolsEnums,
vtkUtils
);
try {
const reportBlob = datasetToBlob(RTSS);
//Create a URL for the binary.
const objectUrl = URL.createObjectURL(reportBlob);
window.location.assign(objectUrl);
} catch (e) {
console.warn(e);
}
},
};
const definitions = {
@@ -372,6 +421,9 @@ const commandsModule = ({
storeSegmentation: {
commandFn: actions.storeSegmentation,
},
downloadRTSS: {
commandFn: actions.downloadRTSS,
},
};
return {
@@ -1,5 +1,6 @@
import { utils } from '@ohif/core';
import { metaData, cache, triggerEvent, eventTarget } from '@cornerstonejs/core';
import { CONSTANTS } from '@cornerstonejs/tools';
import { adaptersSEG, Enums } from '@cornerstonejs/adapters';
import { SOPClassHandlerId } from './id';
@@ -141,7 +142,7 @@ async function _loadSegments({ extensionManager, servicesManager, segDisplaySet,
'@ohif/extension-cornerstone.utilityModule.common'
);
const { segmentationService } = servicesManager.services;
const { segmentationService, uiNotificationService } = servicesManager.services;
const { dicomLoaderService } = utilityModule.exports;
const arrayBuffer = await dicomLoaderService.findDicomDataPromise(segDisplaySet, null, headers);
@@ -174,12 +175,40 @@ async function _loadSegments({ extensionManager, servicesManager, segDisplaySet,
{ skipOverlapping, tolerance, eventTarget, triggerEvent }
);
let usedRecommendedDisplayCIELabValue = true;
results.segMetadata.data.forEach((data, i) => {
if (i > 0) {
data.rgba = dicomlabToRGB(data.RecommendedDisplayCIELabValue);
data.rgba = data.RecommendedDisplayCIELabValue;
if (data.rgba) {
data.rgba = dicomlabToRGB(data.rgba);
} else {
usedRecommendedDisplayCIELabValue = false;
data.rgba = CONSTANTS.COLOR_LUT[i % CONSTANTS.COLOR_LUT.length];
}
}
});
if (results.overlappingSegments) {
uiNotificationService.show({
title: 'Overlapping Segments',
message:
'Unsupported overlapping segments detected, segmentation rendering results may be incorrect.',
type: 'warning',
});
}
if (!usedRecommendedDisplayCIELabValue) {
// Display a notification about the non-utilization of RecommendedDisplayCIELabValue
uiNotificationService.show({
title: 'DICOM SEG import',
message:
'RecommendedDisplayCIELabValue not found for one or more segments. The default color was used instead.',
type: 'warning',
duration: 5000,
});
}
Object.assign(segDisplaySet, results);
}
@@ -215,6 +215,12 @@ export default function PanelSegmentation({
}
};
const onSegmentationDownloadRTSS = segmentationId => {
commandsManager.runCommand('downloadRTSS', {
segmentationId,
});
};
return (
<>
<div className="ohif-scrollbar flex min-h-0 flex-auto select-none flex-col justify-between overflow-auto">
@@ -227,6 +233,7 @@ export default function PanelSegmentation({
onSegmentationClick={onSegmentationClick}
onSegmentationDelete={onSegmentationDelete}
onSegmentationDownload={onSegmentationDownload}
onSegmentationDownloadRTSS={onSegmentationDownloadRTSS}
storeSegmentation={storeSegmentation}
onSegmentationEdit={onSegmentationEdit}
onSegmentClick={onSegmentClick}
@@ -10,9 +10,9 @@ const TOOL_TYPES = {
SPHERE_BRUSH: 'SphereBrush',
CIRCULAR_ERASER: 'CircularEraser',
SPHERE_ERASER: 'SphereEraser',
CIRCLE_SCISSOR: 'CircleScissor',
RECTANGLE_SCISSOR: 'RectangleScissor',
SPHERE_SCISSOR: 'SphereScissor',
CIRCLE_SHAPE: 'CircleScissor',
RECTANGLE_SHAPE: 'RectangleScissor',
SPHERE_SHAPE: 'SphereScissor',
THRESHOLD_CIRCULAR_BRUSH: 'ThresholdCircularBrush',
THRESHOLD_SPHERE_BRUSH: 'ThresholdSphereBrush',
};
@@ -31,13 +31,13 @@ const initialState = {
brushSize: 15,
mode: 'CircularEraser', // Can be 'CircularEraser' or 'SphereEraser'
},
Scissors: {
Shapes: {
brushSize: 15,
mode: 'CircleScissor', // E.g., 'CircleScissor', 'RectangleScissor', or 'SphereScissor'
},
ThresholdBrush: {
brushSize: 15,
thresholdRange: [-500, 500],
thresholdRange: null,
},
activeTool: null,
};
@@ -88,6 +88,8 @@ function SegmentationToolbox({ servicesManager, extensionManager }) {
const setToolActive = useCallback(
toolName => {
initializeThresholdValue(toolName);
toolbarService.recordInteraction({
interactionType: 'tool',
commands: [
@@ -178,6 +180,24 @@ function SegmentationToolbox({ servicesManager, extensionManager }) {
[toolGroupService]
);
function initializeThresholdValue(toolName: any) {
if (state.ThresholdBrush.thresholdRange === null) {
// set the default threshold range from the tool configuration
const toolGroupIds = toolGroupService.getToolGroupIds();
const toolGroupId = toolGroupIds[0];
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
const toolConfig = toolGroup.getToolConfiguration(toolName);
const defaultThresholdRange = toolConfig?.strategySpecificConfiguration?.THRESHOLD?.threshold;
dispatch({
type: ACTIONS.SET_TOOL_CONFIG,
payload: {
tool: 'ThresholdBrush',
config: { thresholdRange: defaultThresholdRange },
},
});
}
}
const onBrushSizeChange = useCallback(
(valueAsStringOrNumber, toolCategory) => {
const value = Number(valueAsStringOrNumber);
@@ -200,8 +220,8 @@ function SegmentationToolbox({ servicesManager, extensionManager }) {
const handleRangeChange = useCallback(
newRange => {
if (
newRange[0] === state.ThresholdBrush.thresholdRange[0] &&
newRange[1] === state.ThresholdBrush.thresholdRange[1]
newRange[0] === state.ThresholdBrush.thresholdRange?.[0] &&
newRange[1] === state.ThresholdBrush.thresholdRange?.[1]
) {
return;
}
@@ -213,7 +233,7 @@ function SegmentationToolbox({ servicesManager, extensionManager }) {
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
toolGroup.setToolConfiguration(toolName, {
strategySpecificConfiguration: {
THRESHOLD_INSIDE_CIRCLE: {
THRESHOLD: {
threshold: newRange,
},
},
@@ -301,24 +321,24 @@ function SegmentationToolbox({ servicesManager, extensionManager }) {
],
},
{
name: 'Scissor',
icon: 'icon-tool-scissor',
name: 'Shapes',
icon: 'icon-tool-shape',
disabled: !toolsEnabled,
active:
state.activeTool === TOOL_TYPES.CIRCLE_SCISSOR ||
state.activeTool === TOOL_TYPES.RECTANGLE_SCISSOR ||
state.activeTool === TOOL_TYPES.SPHERE_SCISSOR,
onClick: () => setToolActive(TOOL_TYPES.CIRCLE_SCISSOR),
state.activeTool === TOOL_TYPES.CIRCLE_SHAPE ||
state.activeTool === TOOL_TYPES.RECTANGLE_SHAPE ||
state.activeTool === TOOL_TYPES.SPHERE_SHAPE,
onClick: () => setToolActive(TOOL_TYPES.CIRCLE_SHAPE),
options: [
{
name: 'Mode',
type: 'radio',
value: state.Scissors.mode,
id: 'scissor-mode',
value: state.Shapes.mode,
id: 'shape-mode',
values: [
{ value: TOOL_TYPES.CIRCLE_SCISSOR, label: 'Circle' },
{ value: TOOL_TYPES.RECTANGLE_SCISSOR, label: 'Rectangle' },
{ value: TOOL_TYPES.SPHERE_SCISSOR, label: 'Sphere' },
{ value: TOOL_TYPES.CIRCLE_SHAPE, label: 'Circle' },
{ value: TOOL_TYPES.RECTANGLE_SHAPE, label: 'Rectangle' },
{ value: TOOL_TYPES.SPHERE_SHAPE, label: 'Sphere' },
],
onChange: value => setToolActive(value),
},
@@ -365,7 +385,7 @@ function SegmentationToolbox({ servicesManager, extensionManager }) {
<InputDoubleRange
values={state.ThresholdBrush.thresholdRange}
onChange={handleRangeChange}
minValue={-1000}
minValue={-1000} // Todo: these should be configurable
maxValue={1000}
step={1}
showLabel={true}
@@ -116,7 +116,6 @@ function OHIFCornerstoneSEGViewport(props) {
}}
onElementEnabled={onElementEnabled}
onElementDisabled={onElementDisabled}
// initialImageIndex={initialImageIndex}
></Component>
);
}, [viewportId, segDisplaySet, toolGroupId]);
@@ -172,14 +171,6 @@ function OHIFCornerstoneSEGViewport(props) {
if (evt.segDisplaySet.displaySetInstanceUID === segDisplaySet.displaySetInstanceUID) {
setSegIsLoading(false);
}
if (evt.overlappingSegments) {
uiNotificationService.show({
title: 'Overlapping Segments',
message: 'Overlapping segments detected which is not currently supported',
type: 'warning',
});
}
}
);
@@ -3,6 +3,629 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.8.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.62...v3.8.0-beta.63) (2024-03-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.61...v3.8.0-beta.62) (2024-03-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.60...v3.8.0-beta.61) (2024-03-18)
### Bug Fixes
* **SR display:** and the token based navigation ([#3995](https://github.com/OHIF/Viewers/issues/3995)) ([feed230](https://github.com/OHIF/Viewers/commit/feed2304c124dc2facc7a7371ed9851548c223c5))
# [3.8.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.59...v3.8.0-beta.60) (2024-03-15)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.58...v3.8.0-beta.59) (2024-03-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.57...v3.8.0-beta.58) (2024-03-05)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.56...v3.8.0-beta.57) (2024-02-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.55...v3.8.0-beta.56) (2024-02-22)
### Bug Fixes
* **demo:** Deploy issue ([#3951](https://github.com/OHIF/Viewers/issues/3951)) ([21e8a2b](https://github.com/OHIF/Viewers/commit/21e8a2bd0b7cc72f90a31e472d285d761be15d30))
# [3.8.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.54...v3.8.0-beta.55) (2024-02-21)
### Features
* **resize:** Optimize resizing process and maintain zoom level ([#3889](https://github.com/OHIF/Viewers/issues/3889)) ([b3a0faf](https://github.com/OHIF/Viewers/commit/b3a0faf5f5f0a1993b2b017eb4cc1216164ea2c6))
# [3.8.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.53...v3.8.0-beta.54) (2024-02-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.52...v3.8.0-beta.53) (2024-02-05)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.51...v3.8.0-beta.52) (2024-01-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.50...v3.8.0-beta.51) (2024-01-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.49...v3.8.0-beta.50) (2024-01-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.48...v3.8.0-beta.49) (2024-01-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.47...v3.8.0-beta.48) (2024-01-17)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.46...v3.8.0-beta.47) (2024-01-12)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.45...v3.8.0-beta.46) (2024-01-12)
### Bug Fixes
* Update CS3D to fix second render ([#3892](https://github.com/OHIF/Viewers/issues/3892)) ([d00a86b](https://github.com/OHIF/Viewers/commit/d00a86b022742ea089d246d06cfd691f43b64412))
# [3.8.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.44...v3.8.0-beta.45) (2024-01-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.43...v3.8.0-beta.44) (2024-01-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.42...v3.8.0-beta.43) (2024-01-09)
### Bug Fixes
* **segmentation:** upgrade cs3d to fix various segmentation bugs ([#3885](https://github.com/OHIF/Viewers/issues/3885)) ([b1efe40](https://github.com/OHIF/Viewers/commit/b1efe40aa146e4052cc47b3f774cabbb47a8d1a6))
# [3.8.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.41...v3.8.0-beta.42) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.40...v3.8.0-beta.41) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.39...v3.8.0-beta.40) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.38...v3.8.0-beta.39) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.37...v3.8.0-beta.38) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.36...v3.8.0-beta.37) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.35...v3.8.0-beta.36) (2023-12-15)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.34...v3.8.0-beta.35) (2023-12-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.33...v3.8.0-beta.34) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.32...v3.8.0-beta.33) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.31...v3.8.0-beta.32) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.30...v3.8.0-beta.31) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.29...v3.8.0-beta.30) (2023-12-13)
### Features
* **customizationService:** Enable saving and loading of private tags in SRs ([#3842](https://github.com/OHIF/Viewers/issues/3842)) ([e1f55e6](https://github.com/OHIF/Viewers/commit/e1f55e65f2d2a34136ad5d0b1ada77d337a0ea23))
# [3.8.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.28...v3.8.0-beta.29) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.27...v3.8.0-beta.28) (2023-12-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.26...v3.8.0-beta.27) (2023-12-06)
### Bug Fixes
* **auth:** fix the issue with oauth at a non root path ([#3840](https://github.com/OHIF/Viewers/issues/3840)) ([6651008](https://github.com/OHIF/Viewers/commit/6651008fbb35dabd5991c7f61128e6ef324012df))
# [3.8.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.25...v3.8.0-beta.26) (2023-11-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.24...v3.8.0-beta.25) (2023-11-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.23...v3.8.0-beta.24) (2023-11-24)
### Bug Fixes
* Update the CS3D packages to add the most recent HTJ2K TSUIDS ([#3806](https://github.com/OHIF/Viewers/issues/3806)) ([9d1884d](https://github.com/OHIF/Viewers/commit/9d1884d7d8b6b2a1cdc26965a96995838aa72682))
# [3.8.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.22...v3.8.0-beta.23) (2023-11-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.21...v3.8.0-beta.22) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.20...v3.8.0-beta.21) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.19...v3.8.0-beta.20) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.18...v3.8.0-beta.19) (2023-11-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.17...v3.8.0-beta.18) (2023-11-15)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.16...v3.8.0-beta.17) (2023-11-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.15...v3.8.0-beta.16) (2023-11-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.14...v3.8.0-beta.15) (2023-11-10)
### Features
* **dicomJSON:** Add Loading Other Display Sets and JSON Metadata Generation script ([#3777](https://github.com/OHIF/Viewers/issues/3777)) ([43b1c17](https://github.com/OHIF/Viewers/commit/43b1c17209502e4876ad59bae09ed9442eda8024))
# [3.8.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.13...v3.8.0-beta.14) (2023-11-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.12...v3.8.0-beta.13) (2023-11-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.11...v3.8.0-beta.12) (2023-11-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.10...v3.8.0-beta.11) (2023-11-08)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.9...v3.8.0-beta.10) (2023-11-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.8...v3.8.0-beta.9) (2023-11-02)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.7...v3.8.0-beta.8) (2023-10-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.6...v3.8.0-beta.7) (2023-10-30)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.5...v3.8.0-beta.6) (2023-10-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.4...v3.8.0-beta.5) (2023-10-24)
### Bug Fixes
* **sr:** dcm4chee requires the patient name for an SR to match what is in the original study ([#3739](https://github.com/OHIF/Viewers/issues/3739)) ([d98439f](https://github.com/OHIF/Viewers/commit/d98439fe7f3825076dbc87b664a1d1480ff414d3))
# [3.8.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.3...v3.8.0-beta.4) (2023-10-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.2...v3.8.0-beta.3) (2023-10-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.1...v3.8.0-beta.2) (2023-10-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.0...v3.8.0-beta.1) (2023-10-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.8.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.8.0-beta.0) (2023-10-12)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.7.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.109...v3.7.0-beta.110) (2023-10-11)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.7.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.108...v3.7.0-beta.109) (2023-10-11)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.7.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.107...v3.7.0-beta.108) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.7.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.106...v3.7.0-beta.107) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.7.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.105...v3.7.0-beta.106) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.7.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.104...v3.7.0-beta.105) (2023-10-10)
### Bug Fixes
* **voi:** should publish voi change event on reset ([#3707](https://github.com/OHIF/Viewers/issues/3707)) ([52f34c6](https://github.com/OHIF/Viewers/commit/52f34c64d014f433ec1661a39b47e7fb27f15332))
# [3.7.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.103...v3.7.0-beta.104) (2023-10-09)
### Bug Fixes
* **modality unit:** fix the modality unit per target via upgrade of cs3d ([#3706](https://github.com/OHIF/Viewers/issues/3706)) ([0a42d57](https://github.com/OHIF/Viewers/commit/0a42d573bbca7f2551a831a46d3aa6b56674a580))
# [3.7.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.102...v3.7.0-beta.103) (2023-10-09)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.7.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.101...v3.7.0-beta.102) (2023-10-06)
### Features
* **Segmentation:** download RTSS from Labelmap([#3692](https://github.com/OHIF/Viewers/issues/3692)) ([40673f6](https://github.com/OHIF/Viewers/commit/40673f64b36b1150149c55632aa1825178a39e65))
# [3.7.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.100...v3.7.0-beta.101) (2023-10-06)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
+11 -9
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-sr",
"version": "3.7.0-beta.101",
"version": "3.8.0-beta.63",
"description": "OHIF extension for an SR Cornerstone Viewport",
"author": "OHIF",
"license": "MIT",
@@ -23,6 +23,8 @@
"ohif-extension"
],
"scripts": {
"clean": "shx rm -rf dist",
"clean:deep": "yarn run clean && shx rm -rf node_modules",
"dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
"dev:cornerstone": "yarn run dev",
"build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
@@ -32,11 +34,11 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.101",
"@ohif/extension-cornerstone": "3.7.0-beta.101",
"@ohif/extension-measurement-tracking": "3.7.0-beta.101",
"@ohif/ui": "3.7.0-beta.101",
"dcmjs": "^0.29.5",
"@ohif/core": "3.8.0-beta.63",
"@ohif/extension-cornerstone": "3.8.0-beta.63",
"@ohif/extension-measurement-tracking": "3.8.0-beta.63",
"@ohif/ui": "3.8.0-beta.63",
"dcmjs": "^0.29.12",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
"prop-types": "^15.6.2",
@@ -44,9 +46,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^1.19.4",
"@cornerstonejs/core": "^1.19.4",
"@cornerstonejs/tools": "^1.19.4",
"@cornerstonejs/adapters": "^1.66.7",
"@cornerstonejs/core": "^1.66.7",
"@cornerstonejs/tools": "^1.66.7",
"classnames": "^2.3.2"
}
}
@@ -40,7 +40,9 @@ const _generateReport = (measurementData, additionalFindingTypes, options = {})
return dataset;
};
const commandsModule = ({}) => {
const commandsModule = props => {
const { servicesManager } = props;
const { customizationService } = servicesManager.services;
const actions = {
/**
*
@@ -95,7 +97,15 @@ const commandsModule = ({}) => {
throw new Error('Invalid report, no content');
}
await dataSource.store.dicom(naturalizedReport);
const onBeforeDicomStore =
customizationService.getModeCustomization('onBeforeDicomStore')?.value;
let dicomDict;
if (typeof onBeforeDicomStore === 'function') {
dicomDict = onBeforeDicomStore({ measurementData, naturalizedReport });
}
await dataSource.store.dicom(naturalizedReport, null, dicomDict);
if (StudyInstanceUID) {
dataSource.deleteStudyMetadataPromise(StudyInstanceUID);
@@ -171,7 +171,12 @@ function _load(displaySet, servicesManager, extensionManager) {
// Check currently added displaySets and add measurements if the sources exist.
displaySetService.activeDisplaySets.forEach(activeDisplaySet => {
_checkIfCanAddMeasurementsToDisplaySet(displaySet, activeDisplaySet, dataSource);
_checkIfCanAddMeasurementsToDisplaySet(
displaySet,
activeDisplaySet,
dataSource,
servicesManager
);
});
// Subscribe to new displaySets as the source may come in after.
@@ -180,12 +185,23 @@ function _load(displaySet, servicesManager, extensionManager) {
// If there are still some measurements that have not yet been loaded into cornerstone,
// See if we can load them onto any of the new displaySets.
displaySetsAdded.forEach(newDisplaySet => {
_checkIfCanAddMeasurementsToDisplaySet(displaySet, newDisplaySet, dataSource);
_checkIfCanAddMeasurementsToDisplaySet(
displaySet,
newDisplaySet,
dataSource,
servicesManager
);
});
});
}
function _checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, newDisplaySet, dataSource) {
function _checkIfCanAddMeasurementsToDisplaySet(
srDisplaySet,
newDisplaySet,
dataSource,
servicesManager
) {
const { customizationService } = servicesManager.services;
let unloadedMeasurements = srDisplaySet.measurements.filter(
measurement => measurement.loaded === false
);
@@ -200,7 +216,11 @@ function _checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, newDisplaySet, dat
return;
}
const { sopClassUids, images } = newDisplaySet;
if (newDisplaySet.unsupported) {
return;
}
const { sopClassUids } = newDisplaySet;
// Check if any have the newDisplaySet is the correct SOPClass.
unloadedMeasurements = unloadedMeasurements.filter(measurement =>
@@ -240,7 +260,20 @@ function _checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, newDisplaySet, dat
if (SOPInstanceUIDs.includes(SOPInstanceUID)) {
for (let j = unloadedMeasurements.length - 1; j >= 0; j--) {
const measurement = unloadedMeasurements[j];
let measurement = unloadedMeasurements[j];
const onBeforeSRAddMeasurement = customizationService.getModeCustomization(
'onBeforeSRAddMeasurement'
)?.value;
if (typeof onBeforeSRAddMeasurement === 'function') {
measurement = onBeforeSRAddMeasurement({
measurement,
StudyInstanceUID: srDisplaySet.StudyInstanceUID,
SeriesInstanceUID: srDisplaySet.SeriesInstanceUID,
});
}
if (_measurementReferencesSOPInstanceUID(measurement, SOPInstanceUID, frameNumber)) {
addMeasurement(measurement, imageId, newDisplaySet.displaySetInstanceUID);
@@ -339,7 +339,9 @@ export default class DICOMSRDisplayTool extends AnnotationTool {
const textLines = this._getTextBoxLinesFromLabels(label);
const canvasTextBoxCoords = utilities.drawing.getTextBoxCoordsCanvas(adaptedCanvasCoordinates);
annotation.data.handles.textBox.worldPosition = viewport.canvasToWorld(canvasTextBoxCoords);
if (!annotation.data?.handles?.textBox?.worldPosition) {
annotation.data.handles.textBox.worldPosition = viewport.canvasToWorld(canvasTextBoxCoords);
}
const textBoxPosition = viewport.worldToCanvas(annotation.data.handles.textBox.worldPosition);
@@ -52,7 +52,7 @@ export default function addMeasurement(measurement, imageId, displaySetInstanceU
data: {
label: measurement.labels,
handles: {
textBox: {},
textBox: measurement.textBox ?? {},
},
cachedStats: {
TrackingUniqueIdentifier: measurementData.TrackingUniqueIdentifier,
@@ -90,7 +90,7 @@ export default function hydrateStructuredReport(
const datasetToUse = _mapLegacyDataSet(instance);
// Use dcmjs to generate toolState.
const storedMeasurementByAnnotationType = MeasurementReport.generateToolState(
let storedMeasurementByAnnotationType = MeasurementReport.generateToolState(
datasetToUse,
// NOTE: we need to pass in the imageIds to dcmjs since the we use them
// for the imageToWorld transformation. The following assumes that the order
@@ -101,6 +101,16 @@ export default function hydrateStructuredReport(
metaData
);
const onBeforeSRHydration =
customizationService.getModeCustomization('onBeforeSRHydration')?.value;
if (typeof onBeforeSRHydration === 'function') {
storedMeasurementByAnnotationType = onBeforeSRHydration({
storedMeasurementByAnnotationType,
displaySet,
});
}
// Filter what is found by DICOM SR to measurements we support.
const mappingDefinitions = mappings.map(m => m.annotationType);
const hydratableMeasurementsInSR = {};
@@ -360,7 +360,7 @@ function OHIFCornerstoneSRViewport(props) {
patientSex: PatientSex || '',
patientAge: PatientAge || '',
MRN: PatientID || '',
thickness: SliceThickness ? `${SliceThickness.toFixed(2)}mm` : '',
thickness: SliceThickness ? `${parseFloat(SliceThickness).toFixed(2)}mm` : '',
spacing:
SpacingBetweenSlices !== undefined ? `${SpacingBetweenSlices.toFixed(2)}mm` : '',
scanner: ManufacturerModelName || '',
+671
View File
@@ -3,6 +3,677 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.8.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.62...v3.8.0-beta.63) (2024-03-25)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.61...v3.8.0-beta.62) (2024-03-19)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.60...v3.8.0-beta.61) (2024-03-18)
### Bug Fixes
* **SR display:** and the token based navigation ([#3995](https://github.com/OHIF/Viewers/issues/3995)) ([feed230](https://github.com/OHIF/Viewers/commit/feed2304c124dc2facc7a7371ed9851548c223c5))
# [3.8.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.59...v3.8.0-beta.60) (2024-03-15)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.58...v3.8.0-beta.59) (2024-03-08)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.57...v3.8.0-beta.58) (2024-03-05)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.56...v3.8.0-beta.57) (2024-02-28)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.55...v3.8.0-beta.56) (2024-02-22)
### Bug Fixes
* **demo:** Deploy issue ([#3951](https://github.com/OHIF/Viewers/issues/3951)) ([21e8a2b](https://github.com/OHIF/Viewers/commit/21e8a2bd0b7cc72f90a31e472d285d761be15d30))
# [3.8.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.54...v3.8.0-beta.55) (2024-02-21)
### Features
* **resize:** Optimize resizing process and maintain zoom level ([#3889](https://github.com/OHIF/Viewers/issues/3889)) ([b3a0faf](https://github.com/OHIF/Viewers/commit/b3a0faf5f5f0a1993b2b017eb4cc1216164ea2c6))
# [3.8.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.53...v3.8.0-beta.54) (2024-02-14)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.52...v3.8.0-beta.53) (2024-02-05)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.51...v3.8.0-beta.52) (2024-01-22)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.50...v3.8.0-beta.51) (2024-01-22)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.49...v3.8.0-beta.50) (2024-01-22)
### Bug Fixes
* **viewport-sync:** remember synced viewports bw stack and volume and RENAME StackImageSync to ImageSliceSync ([#3849](https://github.com/OHIF/Viewers/issues/3849)) ([e4a116b](https://github.com/OHIF/Viewers/commit/e4a116b074fcb85c8cbcc9db44fdec565f3386db))
# [3.8.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.48...v3.8.0-beta.49) (2024-01-19)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.47...v3.8.0-beta.48) (2024-01-17)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.46...v3.8.0-beta.47) (2024-01-12)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.45...v3.8.0-beta.46) (2024-01-12)
### Bug Fixes
* Update CS3D to fix second render ([#3892](https://github.com/OHIF/Viewers/issues/3892)) ([d00a86b](https://github.com/OHIF/Viewers/commit/d00a86b022742ea089d246d06cfd691f43b64412))
# [3.8.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.44...v3.8.0-beta.45) (2024-01-09)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.43...v3.8.0-beta.44) (2024-01-09)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.42...v3.8.0-beta.43) (2024-01-09)
### Bug Fixes
* **segmentation:** upgrade cs3d to fix various segmentation bugs ([#3885](https://github.com/OHIF/Viewers/issues/3885)) ([b1efe40](https://github.com/OHIF/Viewers/commit/b1efe40aa146e4052cc47b3f774cabbb47a8d1a6))
# [3.8.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.41...v3.8.0-beta.42) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.40...v3.8.0-beta.41) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.39...v3.8.0-beta.40) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.38...v3.8.0-beta.39) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.37...v3.8.0-beta.38) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.36...v3.8.0-beta.37) (2024-01-08)
### Bug Fixes
* colormap for stack viewports via HangingProtocol ([#3866](https://github.com/OHIF/Viewers/issues/3866)) ([e8858f3](https://github.com/OHIF/Viewers/commit/e8858f3eb55552f695af4a55980f9ae2e9af7291))
# [3.8.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.35...v3.8.0-beta.36) (2023-12-15)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.34...v3.8.0-beta.35) (2023-12-14)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.33...v3.8.0-beta.34) (2023-12-13)
### Features
* **overlay:** add inline binary overlays ([#3852](https://github.com/OHIF/Viewers/issues/3852)) ([0177b62](https://github.com/OHIF/Viewers/commit/0177b625ba86760168bc4db58c8a109aa9ee83cb))
# [3.8.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.32...v3.8.0-beta.33) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.31...v3.8.0-beta.32) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.30...v3.8.0-beta.31) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.29...v3.8.0-beta.30) (2023-12-13)
### Features
* **customizationService:** Enable saving and loading of private tags in SRs ([#3842](https://github.com/OHIF/Viewers/issues/3842)) ([e1f55e6](https://github.com/OHIF/Viewers/commit/e1f55e65f2d2a34136ad5d0b1ada77d337a0ea23))
# [3.8.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.28...v3.8.0-beta.29) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.27...v3.8.0-beta.28) (2023-12-08)
### Features
* **HP:** Added new 3D hanging protocols to be used in the new layout selector ([#3844](https://github.com/OHIF/Viewers/issues/3844)) ([59576d6](https://github.com/OHIF/Viewers/commit/59576d695d4d26601d35c43f73d602f0b12d72bf))
# [3.8.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.26...v3.8.0-beta.27) (2023-12-06)
### Bug Fixes
* **auth:** fix the issue with oauth at a non root path ([#3840](https://github.com/OHIF/Viewers/issues/3840)) ([6651008](https://github.com/OHIF/Viewers/commit/6651008fbb35dabd5991c7f61128e6ef324012df))
# [3.8.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.25...v3.8.0-beta.26) (2023-11-28)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.24...v3.8.0-beta.25) (2023-11-27)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.23...v3.8.0-beta.24) (2023-11-24)
### Bug Fixes
* Update the CS3D packages to add the most recent HTJ2K TSUIDS ([#3806](https://github.com/OHIF/Viewers/issues/3806)) ([9d1884d](https://github.com/OHIF/Viewers/commit/9d1884d7d8b6b2a1cdc26965a96995838aa72682))
# [3.8.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.22...v3.8.0-beta.23) (2023-11-24)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.21...v3.8.0-beta.22) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.20...v3.8.0-beta.21) (2023-11-21)
### Bug Fixes
* **DICOM Overlay:** The overlay data wasn't being refreshed on change ([#3793](https://github.com/OHIF/Viewers/issues/3793)) ([00e7519](https://github.com/OHIF/Viewers/commit/00e751933ac6d611a34773fa69594243f1b99082))
# [3.8.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.19...v3.8.0-beta.20) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.18...v3.8.0-beta.19) (2023-11-18)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.17...v3.8.0-beta.18) (2023-11-15)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.16...v3.8.0-beta.17) (2023-11-13)
### Bug Fixes
* 🐛 Run error handler for failed image requests ([#3773](https://github.com/OHIF/Viewers/issues/3773)) ([3234014](https://github.com/OHIF/Viewers/commit/323401418e7ccab74655ba02f990bbe0ed4e523b))
# [3.8.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.15...v3.8.0-beta.16) (2023-11-13)
### Bug Fixes
* **overlay:** Overlays aren't shown on undefined origin ([#3781](https://github.com/OHIF/Viewers/issues/3781)) ([fd1251f](https://github.com/OHIF/Viewers/commit/fd1251f751d8147b8a78c7f4d81c67ba69769afa))
# [3.8.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.14...v3.8.0-beta.15) (2023-11-10)
### Features
* **dicomJSON:** Add Loading Other Display Sets and JSON Metadata Generation script ([#3777](https://github.com/OHIF/Viewers/issues/3777)) ([43b1c17](https://github.com/OHIF/Viewers/commit/43b1c17209502e4876ad59bae09ed9442eda8024))
# [3.8.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.13...v3.8.0-beta.14) (2023-11-10)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.12...v3.8.0-beta.13) (2023-11-09)
### Bug Fixes
* **arrow:** ArrowAnnotate text key cause validation error ([#3771](https://github.com/OHIF/Viewers/issues/3771)) ([8af1046](https://github.com/OHIF/Viewers/commit/8af10468035f1f59e0a21e579d50ad63c8cbf7ad))
# [3.8.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.11...v3.8.0-beta.12) (2023-11-08)
### Features
* add VolumeViewport rotation ([#3776](https://github.com/OHIF/Viewers/issues/3776)) ([442f99d](https://github.com/OHIF/Viewers/commit/442f99d5eb2ceece7def20e14da59af1dd7d8442))
# [3.8.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.10...v3.8.0-beta.11) (2023-11-08)
### Features
* **hp callback:** Add viewport ready callback ([#3772](https://github.com/OHIF/Viewers/issues/3772)) ([bf252bc](https://github.com/OHIF/Viewers/commit/bf252bcec2aae3a00479fdcb732110b344bcf2c0))
# [3.8.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.9...v3.8.0-beta.10) (2023-11-03)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.8...v3.8.0-beta.9) (2023-11-02)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.7...v3.8.0-beta.8) (2023-10-31)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.6...v3.8.0-beta.7) (2023-10-30)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.5...v3.8.0-beta.6) (2023-10-25)
### Bug Fixes
* **toolbar:** allow customizable toolbar for active viewport and allow active tool to be deactivated via a click ([#3608](https://github.com/OHIF/Viewers/issues/3608)) ([dd6d976](https://github.com/OHIF/Viewers/commit/dd6d9768bbca1d3cc472e8c1e6d85822500b96ef))
# [3.8.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.4...v3.8.0-beta.5) (2023-10-24)
### Bug Fixes
* **sr:** dcm4chee requires the patient name for an SR to match what is in the original study ([#3739](https://github.com/OHIF/Viewers/issues/3739)) ([d98439f](https://github.com/OHIF/Viewers/commit/d98439fe7f3825076dbc87b664a1d1480ff414d3))
# [3.8.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.3...v3.8.0-beta.4) (2023-10-23)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.2...v3.8.0-beta.3) (2023-10-23)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.8.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.1...v3.8.0-beta.2) (2023-10-19)
### Bug Fixes
* **cine:** Use the frame rate specified in DICOM and optionally auto play cine ([#3735](https://github.com/OHIF/Viewers/issues/3735)) ([d9258ec](https://github.com/OHIF/Viewers/commit/d9258eca70587cf4dc18be4e56c79b16bae73d6d))
# [3.8.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.0...v3.8.0-beta.1) (2023-10-19)
### Bug Fixes
* **calibration:** No calibration popup caused by perhaps an unused code optimization for production builds ([#3736](https://github.com/OHIF/Viewers/issues/3736)) ([93d798d](https://github.com/OHIF/Viewers/commit/93d798db99c0dee53ef73c376f8a74ac3049cf3f))
# [3.8.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.8.0-beta.0) (2023-10-12)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.7.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.109...v3.7.0-beta.110) (2023-10-11)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.7.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.108...v3.7.0-beta.109) (2023-10-11)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.7.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.107...v3.7.0-beta.108) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.7.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.106...v3.7.0-beta.107) (2023-10-10)
### Bug Fixes
* **modules:** add stylus loader as an option to be uncommented ([#3710](https://github.com/OHIF/Viewers/issues/3710)) ([7c57f67](https://github.com/OHIF/Viewers/commit/7c57f67844b790fc6e47ac3f9708bf9d576389c8))
# [3.7.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.105...v3.7.0-beta.106) (2023-10-10)
### Bug Fixes
* **segmentation:** Various fixes for segmentation mode and other ([#3709](https://github.com/OHIF/Viewers/issues/3709)) ([a9a6ad5](https://github.com/OHIF/Viewers/commit/a9a6ad50eae67b43b8b34efc07182d788cacdcfe))
# [3.7.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.104...v3.7.0-beta.105) (2023-10-10)
### Bug Fixes
* **voi:** should publish voi change event on reset ([#3707](https://github.com/OHIF/Viewers/issues/3707)) ([52f34c6](https://github.com/OHIF/Viewers/commit/52f34c64d014f433ec1661a39b47e7fb27f15332))
# [3.7.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.103...v3.7.0-beta.104) (2023-10-09)
### Bug Fixes
* **modality unit:** fix the modality unit per target via upgrade of cs3d ([#3706](https://github.com/OHIF/Viewers/issues/3706)) ([0a42d57](https://github.com/OHIF/Viewers/commit/0a42d573bbca7f2551a831a46d3aa6b56674a580))
# [3.7.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.102...v3.7.0-beta.103) (2023-10-09)
### Bug Fixes
* **segmentation:** do not use SAB if not specified ([#3705](https://github.com/OHIF/Viewers/issues/3705)) ([4911e47](https://github.com/OHIF/Viewers/commit/4911e4796cef5e22cb7cc0ca73dc5c956bc75339))
# [3.7.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.101...v3.7.0-beta.102) (2023-10-06)
### Features
* **Segmentation:** download RTSS from Labelmap([#3692](https://github.com/OHIF/Viewers/issues/3692)) ([40673f6](https://github.com/OHIF/Viewers/commit/40673f64b36b1150149c55632aa1825178a39e65))
# [3.7.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.100...v3.7.0-beta.101) (2023-10-06)
+12 -10
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone",
"version": "3.7.0-beta.101",
"version": "3.8.0-beta.63",
"description": "OHIF extension for Cornerstone",
"author": "OHIF",
"license": "MIT",
@@ -25,6 +25,8 @@
"access": "public"
},
"scripts": {
"clean": "shx rm -rf dist",
"clean:deep": "yarn run clean && shx rm -rf node_modules",
"dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
"dev:cornerstone": "yarn run dev",
"build": "cross-env NODE_ENV=production webpack --progress --config .webpack/webpack.prod.js",
@@ -36,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.19.4",
"@ohif/core": "3.7.0-beta.101",
"@ohif/ui": "3.7.0-beta.101",
"dcmjs": "^0.29.6",
"@cornerstonejs/dicom-image-loader": "^1.66.7",
"@ohif/core": "3.8.0-beta.63",
"@ohif/ui": "3.8.0-beta.63",
"dcmjs": "^0.29.12",
"dicom-parser": "^1.8.21",
"hammerjs": "^2.0.8",
"prop-types": "^15.6.2",
@@ -52,11 +54,11 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^1.19.4",
"@cornerstonejs/core": "^1.19.4",
"@cornerstonejs/streaming-image-volume-loader": "^1.19.4",
"@cornerstonejs/tools": "^1.19.4",
"@kitware/vtk.js": "27.3.1",
"@cornerstonejs/adapters": "^1.66.7",
"@cornerstonejs/core": "^1.66.7",
"@cornerstonejs/streaming-image-volume-loader": "^1.66.7",
"@cornerstonejs/tools": "^1.66.7",
"@kitware/vtk.js": "29.7.0",
"html2canvas": "^1.4.1",
"lodash.debounce": "4.0.8",
"lodash.merge": "^4.6.2",
@@ -21,6 +21,7 @@ import getSOPInstanceAttributes from '../utils/measurementServiceMappings/utils/
import CornerstoneServices from '../types/CornerstoneServices';
import CinePlayer from '../components/CinePlayer';
import { Types } from '@ohif/core';
import { LutPresentation, PositionPresentation } from '../types/Presentation';
const STACK = 'stack';
@@ -101,7 +102,6 @@ const OHIFCornerstoneViewport = React.memo(props => {
viewportOptions,
displaySetOptions,
servicesManager,
commandsManager,
onElementEnabled,
onElementDisabled,
isJumpToMeasurementDisabled,
@@ -175,6 +175,13 @@ const OHIFCornerstoneViewport = React.memo(props => {
syncGroupService.addViewportToSyncGroup(viewportId, renderingEngineId, syncGroups);
const synchronizersStore = stateSyncService.getState().synchronizersStore;
if (synchronizersStore?.[viewportId]?.length) {
// If the viewport used to have a synchronizer, re apply it again
_rehydrateSynchronizers(synchronizersStore, viewportId, syncGroupService);
}
if (onElementEnabled) {
onElementEnabled(evt);
}
@@ -197,13 +204,18 @@ const OHIFCornerstoneViewport = React.memo(props => {
return;
}
cleanUpServices(viewportInfo);
cornerstoneViewportService.storePresentation({ viewportId });
// This should be done after the store presentation since synchronizers
// will get cleaned up and they need the viewportInfo to be present
cleanUpServices(viewportInfo);
if (onElementDisabled) {
onElementDisabled(viewportInfo);
}
cornerstoneViewportService.disableElement(viewportId);
eventTarget.removeEventListener(Enums.Events.ELEMENT_ENABLED, elementEnabledHandler);
};
}, []);
@@ -265,7 +277,10 @@ const OHIFCornerstoneViewport = React.memo(props => {
// The presentation state will have been stored previously by closing
// a viewport. Otherwise, this viewport will be unchanged and the
// presentation information will be directly carried over.
const { lutPresentationStore, positionPresentationStore } = stateSyncService.getState();
const state = stateSyncService.getState();
const lutPresentationStore = state.lutPresentationStore as LutPresentation;
const positionPresentationStore = state.positionPresentationStore as PositionPresentation;
const { presentationIds } = viewportOptions;
const presentations = {
positionPresentation: positionPresentationStore[presentationIds?.positionPresentationId],
@@ -348,8 +363,6 @@ const OHIFCornerstoneViewport = React.memo(props => {
<React.Fragment>
<div className="viewport-wrapper">
<ReactResizeDetector
refreshMode="debounce"
refreshRate={50} // Wait 50 ms after last move to render
onResize={onResize}
targetRef={elementRef.current}
/>
@@ -547,6 +560,58 @@ function _jumpToMeasurement(
}
}
function _rehydrateSynchronizers(
synchronizersStore: { [key: string]: unknown },
viewportId: string,
syncGroupService: any
) {
synchronizersStore[viewportId].forEach(synchronizerObj => {
if (!synchronizerObj.id) {
return;
}
const { id, sourceViewports, targetViewports } = synchronizerObj;
const synchronizer = syncGroupService.getSynchronizer(id);
if (!synchronizer) {
return;
}
const sourceViewportInfo = sourceViewports.find(
sourceViewport => sourceViewport.viewportId === viewportId
);
const targetViewportInfo = targetViewports.find(
targetViewport => targetViewport.viewportId === viewportId
);
const isSourceViewportInSynchronizer = synchronizer
.getSourceViewports()
.find(sourceViewport => sourceViewport.viewportId === viewportId);
const isTargetViewportInSynchronizer = synchronizer
.getTargetViewports()
.find(targetViewport => targetViewport.viewportId === viewportId);
// if the viewport was previously a source viewport, add it again
if (sourceViewportInfo && !isSourceViewportInSynchronizer) {
synchronizer.addSource({
viewportId: sourceViewportInfo.viewportId,
renderingEngineId: sourceViewportInfo.renderingEngineId,
});
}
// if the viewport was previously a target viewport, add it again
if (targetViewportInfo && !isTargetViewportInSynchronizer) {
synchronizer.addTarget({
viewportId: targetViewportInfo.viewportId,
renderingEngineId: targetViewportInfo.renderingEngineId,
});
}
});
}
// Component displayName
OHIFCornerstoneViewport.displayName = 'OHIFCornerstoneViewport';
+40 -15
View File
@@ -3,6 +3,8 @@ import {
StackViewport,
VolumeViewport,
utilities as csUtils,
Types as CoreTypes,
BaseVolumeViewport,
} from '@cornerstonejs/core';
import {
ToolGroupManager,
@@ -11,10 +13,11 @@ import {
ReferenceLinesTool,
} from '@cornerstonejs/tools';
import { Types as OhifTypes } from '@ohif/core';
import { vec3, mat4 } from 'gl-matrix';
import CornerstoneViewportDownloadForm from './utils/CornerstoneViewportDownloadForm';
import callInputDialog from './utils/callInputDialog';
import toggleStackImageSync from './utils/stackSync/toggleStackImageSync';
import toggleImageSliceSync from './utils/imageSliceSync/toggleImageSliceSync';
import { getFirstAnnotationSelected } from './utils/measurementServiceMappings/utils/selection';
import getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement';
import { CornerstoneServices } from './types';
@@ -391,8 +394,16 @@ function commandsModule({
const { viewport } = enabledElement;
if (viewport instanceof StackViewport) {
const { rotation: currentRotation } = viewport.getProperties();
if (viewport instanceof BaseVolumeViewport) {
const camera = viewport.getCamera();
const rotAngle = (rotation * Math.PI) / 180;
const rotMat = mat4.identity(new Float32Array(16));
mat4.rotate(rotMat, rotMat, rotAngle, camera.viewPlaneNormal);
const rotatedViewUp = vec3.transformMat4(vec3.create(), camera.viewUp, rotMat);
viewport.setCamera({ viewUp: rotatedViewUp as CoreTypes.Point3 });
viewport.render();
} else if (viewport.getRotation !== undefined) {
const currentRotation = viewport.getRotation();
const newRotation = (currentRotation + rotation) % 360;
viewport.setProperties({ rotation: newRotation });
viewport.render();
@@ -456,13 +467,8 @@ function commandsModule({
const { viewport } = enabledElement;
if (viewport instanceof StackViewport) {
viewport.resetProperties();
viewport.resetCamera();
} else {
// Todo: add reset properties for volume viewport
viewport.resetCamera();
}
viewport.resetProperties?.();
viewport.resetCamera();
viewport.render();
},
@@ -560,8 +566,8 @@ function commandsModule({
viewportGridService.setActiveViewportId(viewportIds[nextViewportIndex] as string);
},
toggleStackImageSync: ({ toggledState }) => {
toggleStackImageSync({
toggleImageSliceSync: ({ toggledState }) => {
toggleImageSliceSync({
servicesManager,
toggledState,
});
@@ -585,6 +591,23 @@ function commandsModule({
storePresentation: ({ viewportId }) => {
cornerstoneViewportService.storePresentation({ viewportId });
},
attachProtocolViewportDataListener: ({ protocol, stageIndex }) => {
const EVENT = cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED;
const command = protocol.callbacks.onViewportDataInitialized;
const numPanes = protocol.stages?.[stageIndex]?.viewports.length ?? 1;
let numPanesWithData = 0;
const { unsubscribe } = cornerstoneViewportService.subscribe(EVENT, evt => {
numPanesWithData++;
if (numPanesWithData === numPanes) {
commandsManager.run(...command);
// Unsubscribe from the event
unsubscribe(EVENT);
}
});
},
};
const definitions = {
@@ -611,7 +634,6 @@ function commandsModule({
storeContexts: [],
options: {},
},
deleteMeasurement: {
commandFn: actions.deleteMeasurement,
},
@@ -704,8 +726,8 @@ function commandsModule({
setViewportColormap: {
commandFn: actions.setViewportColormap,
},
toggleStackImageSync: {
commandFn: actions.toggleStackImageSync,
toggleImageSliceSync: {
commandFn: actions.toggleImageSliceSync,
},
setSourceViewportForReferenceLinesTool: {
commandFn: actions.setSourceViewportForReferenceLinesTool,
@@ -719,6 +741,9 @@ function commandsModule({
cleanUpCrosshairs: {
commandFn: actions.cleanUpCrosshairs,
},
attachProtocolViewportDataListener: {
commandFn: actions.attachProtocolViewportDataListener,
},
};
return {
@@ -1,11 +1,19 @@
import React, { useEffect } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { CinePlayer, useCine, useViewportGrid } from '@ohif/ui';
import { Enums, eventTarget } from '@cornerstonejs/core';
import { useAppConfig } from '@state';
function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
const { toolbarService, customizationService } = servicesManager.services;
const [{ isCineEnabled, cines }, cineService] = useCine();
const [{ activeViewportId }] = useViewportGrid();
const {
toolbarService,
customizationService,
displaySetService,
viewportGridService,
cineService,
} = servicesManager.services;
const [{ isCineEnabled, cines }] = useCine();
const [newStackFrameRate, setNewStackFrameRate] = useState(24);
const [appConfig] = useAppConfig();
const { component: CinePlayerComponent = CinePlayer } =
customizationService.get('cinePlayer') ?? {};
@@ -45,14 +53,37 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
}
};
const newStackCineHandler = useCallback(() => {
const { viewports } = viewportGridService.getState();
const { displaySetInstanceUIDs } = viewports.get(viewportId);
let frameRate = 24;
let isPlaying = cines[viewportId].isPlaying;
displaySetInstanceUIDs.forEach(displaySetInstanceUID => {
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
if (displaySet.FrameRate) {
// displaySet.FrameRate corresponds to DICOM tag (0018,1063) which is defined as the the frame time in milliseconds
// So a bit of math to get the actual frame rate.
frameRate = Math.round(1000 / displaySet.FrameRate);
isPlaying ||= !!appConfig.autoPlayCine;
}
});
if (isPlaying) {
cineService.setIsCineEnabled(isPlaying);
}
cineService.setCine({ id: viewportId, isPlaying, frameRate });
setNewStackFrameRate(frameRate);
}, [cineService, displaySetService, viewportId, viewportGridService, cines]);
useEffect(() => {
eventTarget.addEventListener(Enums.Events.STACK_VIEWPORT_NEW_STACK, cineHandler);
eventTarget.addEventListener(Enums.Events.STACK_VIEWPORT_NEW_STACK, newStackCineHandler);
return () => {
cineService.setCine({ id: viewportId, isPlaying: false });
eventTarget.removeEventListener(Enums.Events.STACK_VIEWPORT_NEW_STACK, cineHandler);
eventTarget.removeEventListener(Enums.Events.STACK_VIEWPORT_NEW_STACK, newStackCineHandler);
};
}, [enabledVPElement]);
}, [enabledVPElement, newStackCineHandler]);
useEffect(() => {
if (!cines || !cines[viewportId] || !enabledVPElement) {
@@ -75,17 +106,18 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
isCineEnabled && (
<CinePlayerComponent
className="absolute left-1/2 bottom-3 -translate-x-1/2"
frameRate={newStackFrameRate}
isPlaying={isPlaying}
onClose={handleCineClose}
onPlayPauseChange={isPlaying =>
cineService.setCine({
id: activeViewportId,
id: viewportId,
isPlaying,
})
}
onFrameRateChange={frameRate =>
cineService.setCine({
id: activeViewportId,
id: viewportId,
frameRate,
})
}
@@ -1,295 +1,10 @@
import { Types } from '@ohif/core';
const mpr: Types.HangingProtocol.Protocol = {
id: 'mpr',
name: 'Multi-Planar Reconstruction',
locked: true,
createdDate: '2021-02-23',
modifiedDate: '2023-08-15',
availableTo: {},
editableBy: {},
// Unknown number of priors referenced - so just match any study
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
onProtocolExit: [
{
commandName: 'cleanUpCrosshairs',
},
],
},
displaySetSelectors: {
activeDisplaySet: {
seriesMatchingRules: [
{
weight: 1,
attribute: 'isReconstructable',
constraint: {
equals: {
value: true,
},
},
required: true,
},
],
},
},
stages: [
{
name: 'MPR 1x3',
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 1,
columns: 3,
layoutOptions: [
{
x: 0,
y: 0,
width: 1 / 3,
height: 1,
},
{
x: 1 / 3,
y: 0,
width: 1 / 3,
height: 1,
},
{
x: 2 / 3,
y: 0,
width: 1 / 3,
height: 1,
},
],
},
},
viewports: [
{
viewportOptions: {
viewportId: 'mpr-axial',
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'axial',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'activeDisplaySet',
},
],
},
{
viewportOptions: {
viewportId: 'mpr-sagittal',
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'sagittal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'activeDisplaySet',
},
],
},
{
viewportOptions: {
viewportId: 'mpr-coronal',
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'coronal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'activeDisplaySet',
},
],
},
],
},
],
};
const mprAnd3DVolumeViewport = {
id: 'mprAnd3DVolumeViewport',
locked: true,
name: 'mpr',
createdDate: '2023-03-15T10:29:44.894Z',
modifiedDate: '2023-03-15T10:29:44.894Z',
availableTo: {},
editableBy: {},
protocolMatchingRules: [],
imageLoadStrategy: 'interleaveCenter',
displaySetSelectors: {
mprDisplaySet: {
seriesMatchingRules: [
{
weight: 1,
attribute: 'isReconstructable',
constraint: {
equals: {
value: true,
},
},
required: true,
},
{
attribute: 'Modality',
constraint: {
equals: {
value: 'CT',
},
},
required: true,
},
],
},
},
stages: [
{
id: 'mpr3Stage',
name: 'mpr',
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 2,
columns: 2,
},
},
viewports: [
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'axial',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
{
viewportOptions: {
toolGroupId: 'volume3d',
viewportType: 'volume3d',
orientation: 'coronal',
customViewportProps: {
hideOverlays: true,
},
},
displaySets: [
{
id: 'mprDisplaySet',
options: {
displayPreset: 'CT-Bone',
},
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'coronal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'sagittal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
],
},
],
};
import { fourUp } from './hps/fourUp';
import { main3D } from './hps/main3D';
import { mpr } from './hps/mpr';
import { mprAnd3DVolumeViewport } from './hps/mprAnd3DVolumeViewport';
import { only3D } from './hps/only3D';
import { primary3D } from './hps/primary3D';
import { primaryAxial } from './hps/primaryAxial';
function getHangingProtocolModule() {
return [
@@ -301,6 +16,26 @@ function getHangingProtocolModule() {
name: mprAnd3DVolumeViewport.id,
protocol: mprAnd3DVolumeViewport,
},
{
name: fourUp.id,
protocol: fourUp,
},
{
name: main3D.id,
protocol: main3D,
},
{
name: primaryAxial.id,
protocol: primaryAxial,
},
{
name: only3D.id,
protocol: only3D,
},
{
name: primary3D.id,
protocol: primary3D,
},
];
}
+130
View File
@@ -0,0 +1,130 @@
export const fourUp = {
id: 'fourUp',
locked: true,
name: 'fourUp',
createdDate: '2023-03-15T10:29:44.894Z',
modifiedDate: '2023-03-15T10:29:44.894Z',
availableTo: {},
editableBy: {},
protocolMatchingRules: [],
imageLoadStrategy: 'interleaveCenter',
displaySetSelectors: {
mprDisplaySet: {
seriesMatchingRules: [
{
weight: 1,
attribute: 'isReconstructable',
constraint: {
equals: {
value: true,
},
},
required: true,
},
],
},
},
stages: [
{
id: 'fourUpStage',
name: 'fourUp',
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 2,
columns: 2,
},
},
viewports: [
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'axial',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
{
viewportOptions: {
toolGroupId: 'volume3d',
viewportType: 'volume3d',
orientation: 'coronal',
customViewportProps: {
hideOverlays: true,
},
},
displaySets: [
{
id: 'mprDisplaySet',
options: {
// ToDo: choose appropriate preset
displayPreset: 'CT-Bone',
},
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'coronal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'sagittal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
],
},
],
};
+156
View File
@@ -0,0 +1,156 @@
export const main3D = {
id: 'main3D',
locked: true,
name: 'main3D',
createdDate: '2023-03-15T10:29:44.894Z',
modifiedDate: '2023-03-15T10:29:44.894Z',
availableTo: {},
editableBy: {},
protocolMatchingRules: [],
imageLoadStrategy: 'interleaveCenter',
displaySetSelectors: {
mprDisplaySet: {
seriesMatchingRules: [
{
weight: 1,
attribute: 'isReconstructable',
constraint: {
equals: {
value: true,
},
},
required: true,
},
],
},
},
stages: [
{
id: 'main3DStage',
name: 'main3D',
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 2,
columns: 3,
layoutOptions: [
{
x: 0,
y: 0,
width: 1,
height: 1 / 2,
},
{
x: 0,
y: 1 / 2,
width: 1 / 3,
height: 1 / 2,
},
{
x: 1 / 3,
y: 1 / 2,
width: 1 / 3,
height: 1 / 2,
},
{
x: 2 / 3,
y: 1 / 2,
width: 1 / 3,
height: 1 / 2,
},
],
},
},
viewports: [
{
viewportOptions: {
toolGroupId: 'volume3d',
viewportType: 'volume3d',
orientation: 'coronal',
customViewportProps: {
hideOverlays: true,
},
},
displaySets: [
{
id: 'mprDisplaySet',
options: {
// ToDo: choose appropriate preset
displayPreset: 'CT-Bone',
},
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'axial',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'coronal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'sagittal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
],
},
],
};
+153
View File
@@ -0,0 +1,153 @@
import { Types } from '@ohif/core';
export const mpr: Types.HangingProtocol.Protocol = {
id: 'mpr',
name: 'Multi-Planar Reconstruction',
locked: true,
createdDate: '2021-02-23',
modifiedDate: '2023-08-15',
availableTo: {},
editableBy: {},
// Unknown number of priors referenced - so just match any study
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
onProtocolExit: [
{
commandName: 'cleanUpCrosshairs',
},
],
},
displaySetSelectors: {
activeDisplaySet: {
seriesMatchingRules: [
{
weight: 1,
attribute: 'isReconstructable',
constraint: {
equals: {
value: true,
},
},
required: true,
},
],
},
},
stages: [
{
name: 'MPR 1x3',
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 1,
columns: 3,
layoutOptions: [
{
x: 0,
y: 0,
width: 1 / 3,
height: 1,
},
{
x: 1 / 3,
y: 0,
width: 1 / 3,
height: 1,
},
{
x: 2 / 3,
y: 0,
width: 1 / 3,
height: 1,
},
],
},
},
viewports: [
{
viewportOptions: {
viewportId: 'mpr-axial',
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'axial',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'activeDisplaySet',
},
],
},
{
viewportOptions: {
viewportId: 'mpr-sagittal',
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'sagittal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'activeDisplaySet',
},
],
},
{
viewportOptions: {
viewportId: 'mpr-coronal',
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'coronal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'activeDisplaySet',
},
],
},
],
},
],
};
@@ -0,0 +1,138 @@
export const mprAnd3DVolumeViewport = {
id: 'mprAnd3DVolumeViewport',
locked: true,
name: 'mpr',
createdDate: '2023-03-15T10:29:44.894Z',
modifiedDate: '2023-03-15T10:29:44.894Z',
availableTo: {},
editableBy: {},
protocolMatchingRules: [],
imageLoadStrategy: 'interleaveCenter',
displaySetSelectors: {
mprDisplaySet: {
seriesMatchingRules: [
{
weight: 1,
attribute: 'isReconstructable',
constraint: {
equals: {
value: true,
},
},
required: true,
},
{
attribute: 'Modality',
constraint: {
equals: {
value: 'CT',
},
},
required: true,
},
],
},
},
stages: [
{
id: 'mpr3Stage',
name: 'mpr',
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 2,
columns: 2,
},
},
viewports: [
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'axial',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
{
viewportOptions: {
toolGroupId: 'volume3d',
viewportType: 'volume3d',
orientation: 'coronal',
customViewportProps: {
hideOverlays: true,
},
},
displaySets: [
{
id: 'mprDisplaySet',
options: {
displayPreset: 'CT-Bone',
},
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'coronal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'sagittal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
],
},
],
};
+61
View File
@@ -0,0 +1,61 @@
export const only3D = {
id: 'only3D',
locked: true,
name: 'only3D',
createdDate: '2023-03-15T10:29:44.894Z',
modifiedDate: '2023-03-15T10:29:44.894Z',
availableTo: {},
editableBy: {},
protocolMatchingRules: [],
imageLoadStrategy: 'interleaveCenter',
displaySetSelectors: {
mprDisplaySet: {
seriesMatchingRules: [
{
weight: 1,
attribute: 'isReconstructable',
constraint: {
equals: {
value: true,
},
},
required: true,
},
],
},
},
stages: [
{
id: 'only3DStage',
name: 'only3D',
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 1,
columns: 1,
},
},
viewports: [
{
viewportOptions: {
toolGroupId: 'volume3d',
viewportType: 'volume3d',
orientation: 'coronal',
customViewportProps: {
hideOverlays: true,
},
},
displaySets: [
{
id: 'mprDisplaySet',
options: {
// ToDo: choose appropriate preset
displayPreset: 'CT-Bone',
},
},
],
},
],
},
],
};
+156
View File
@@ -0,0 +1,156 @@
export const primary3D = {
id: 'primary3D',
locked: true,
name: 'primary3D',
createdDate: '2023-03-15T10:29:44.894Z',
modifiedDate: '2023-03-15T10:29:44.894Z',
availableTo: {},
editableBy: {},
protocolMatchingRules: [],
imageLoadStrategy: 'interleaveCenter',
displaySetSelectors: {
mprDisplaySet: {
seriesMatchingRules: [
{
weight: 1,
attribute: 'isReconstructable',
constraint: {
equals: {
value: true,
},
},
required: true,
},
],
},
},
stages: [
{
id: 'primary3DStage',
name: 'primary3D',
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 3,
columns: 3,
layoutOptions: [
{
x: 0,
y: 0,
width: 2 / 3,
height: 1,
},
{
x: 2 / 3,
y: 0,
width: 1 / 3,
height: 1 / 3,
},
{
x: 2 / 3,
y: 1 / 3,
width: 1 / 3,
height: 1 / 3,
},
{
x: 2 / 3,
y: 2 / 3,
width: 1 / 3,
height: 1 / 3,
},
],
},
},
viewports: [
{
viewportOptions: {
toolGroupId: 'volume3d',
viewportType: 'volume3d',
orientation: 'coronal',
customViewportProps: {
hideOverlays: true,
},
},
displaySets: [
{
id: 'mprDisplaySet',
options: {
// ToDo: choose appropriate preset
displayPreset: 'CT-Bone',
},
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'axial',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'coronal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'sagittal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
],
},
],
};
@@ -0,0 +1,131 @@
export const primaryAxial = {
id: 'primaryAxial',
locked: true,
name: 'primaryAxial',
createdDate: '2023-03-15T10:29:44.894Z',
modifiedDate: '2023-03-15T10:29:44.894Z',
availableTo: {},
editableBy: {},
protocolMatchingRules: [],
imageLoadStrategy: 'interleaveCenter',
displaySetSelectors: {
mprDisplaySet: {
seriesMatchingRules: [
{
weight: 1,
attribute: 'isReconstructable',
constraint: {
equals: {
value: true,
},
},
required: true,
},
],
},
},
stages: [
{
id: 'primaryAxialStage',
name: 'primaryAxial',
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 2,
columns: 3,
layoutOptions: [
{
x: 0,
y: 0,
width: 2 / 3,
height: 1,
},
{
x: 2 / 3,
y: 0,
width: 1 / 3,
height: 1 / 2,
},
{
x: 2 / 3,
y: 1 / 2,
width: 1 / 3,
height: 1 / 2,
},
],
},
},
viewports: [
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'axial',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'sagittal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
{
viewportOptions: {
toolGroupId: 'mpr',
viewportType: 'volume',
orientation: 'coronal',
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
},
],
},
displaySets: [
{
id: 'mprDisplaySet',
},
],
},
],
},
],
};
+2
View File
@@ -29,6 +29,7 @@ import { id } from './id';
import * as csWADOImageLoader from './initWADOImageLoader.js';
import { measurementMappingUtils } from './utils/measurementServiceMappings';
import type { PublicViewportOptions } from './services/ViewportService/Viewport';
import ImageOverlayViewerTool from './tools/ImageOverlayViewerTool';
const Component = React.lazy(() => {
return import(/* webpackPrefetch: true */ './Viewport/OHIFCornerstoneViewport');
@@ -140,5 +141,6 @@ export {
CornerstoneExtensionTypes as Types,
toolNames,
getActiveViewportEnabledElement,
ImageOverlayViewerTool,
};
export default cornerstoneExtension;
+32 -5
View File
@@ -1,4 +1,4 @@
import OHIF, { Types } from '@ohif/core';
import OHIF, { Types, errorHandler } from '@ohif/core';
import React from 'react';
import * as cornerstone from '@cornerstonejs/core';
@@ -10,6 +10,7 @@ import {
metaData,
volumeLoader,
imageLoadPoolManager,
getEnabledElement,
Settings,
utilities as csUtilities,
Enums as csEnums,
@@ -59,8 +60,8 @@ export default async function init({
await cs3DInit({
rendering: {
preferSizeOverAccuracy: Boolean(appConfig.use16BitDataType),
useNorm16Texture: Boolean(appConfig.use16BitDataType),
preferSizeOverAccuracy: Boolean(appConfig.preferSizeOverAccuracy),
useNorm16Texture: Boolean(appConfig.useNorm16Texture),
},
});
@@ -97,6 +98,7 @@ export default async function init({
toolbarService,
viewportGridService,
stateSyncService,
syncGroupService,
} = servicesManager.services as CornerstoneServices;
window.services = servicesManager.services;
@@ -124,6 +126,9 @@ export default async function init({
// an OHIFCornerstoneViewport can be redisplayed with the same LUT
stateSyncService.register('lutPresentationStore', { clearOnModeExit: true });
// Stores synchronizers state to be restored
stateSyncService.register('synchronizersStore', { clearOnModeExit: true });
// Stores a map from `positionPresentationId` to a Presentation object so that
// an OHIFCornerstoneViewport can be redisplayed with the same position
stateSyncService.register('positionPresentationStore', {
@@ -199,6 +204,16 @@ export default async function init({
}
);
// resize the cornerstone viewport service when the grid size changes
// IMPORTANT: this should happen outside of the OHIFCornerstoneViewport
// since it will trigger a rerender of each viewport and each resizing
// the offscreen canvas which would result in a performance hit, this should
// done only once per grid resize here. Doing it once here, allows us to reduce
// the refreshRage(in ms) to 10 from 50. I tried with even 1 or 5 ms it worked fine
viewportGridService.subscribe(viewportGridService.EVENTS.GRID_SIZE_CHANGED, () => {
cornerstoneViewportService.resize(true);
});
initContextMenu({
cornerstoneViewportService,
customizationService,
@@ -251,6 +266,15 @@ export default async function init({
});
};
/**
* Runs error handler for failed requests.
* @param event
*/
const imageLoadFailedHandler = ({ detail }) => {
const handler = errorHandler.getHTTPErrorHandler();
handler(detail.error);
};
const resetCrosshairs = evt => {
const { element } = evt.detail;
const { viewportId, renderingEngineId } = cornerstone.getEnabledElement(element);
@@ -279,9 +303,12 @@ export default async function init({
const { element } = evt.detail;
cornerstoneTools.utilities.stackContextPrefetch.enable(element);
});
eventTarget.addEventListener(EVENTS.IMAGE_LOAD_FAILED, imageLoadFailedHandler);
eventTarget.addEventListener(EVENTS.IMAGE_LOAD_ERROR, imageLoadFailedHandler);
function elementEnabledHandler(evt) {
const { element } = evt.detail;
element.addEventListener(EVENTS.CAMERA_RESET, resetCrosshairs);
eventTarget.addEventListener(EVENTS.STACK_VIEWPORT_NEW_STACK, toolbarEventListener);
@@ -308,8 +335,8 @@ export default async function init({
viewportGridService.subscribe(
viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED,
activeViewportEventListener
);
}
);
}
function CPUModal() {
return (
@@ -49,7 +49,8 @@ export default function initWADOImageLoader(
// Until the default is set to true (which is the case for cornerstone3D),
// we should set this flag to false.
convertFloatPixelDataToInt: false,
use16BitDataType: Boolean(appConfig.use16BitDataType),
use16BitDataType:
Boolean(appConfig.useNorm16Texture) || Boolean(appConfig.preferSizeOverAccuracy),
},
beforeSend: function (xhr) {
//TODO should be removed in the future and request emitted by DicomWebDataSource
@@ -1,5 +1,3 @@
import cloneDeep from 'lodash.clonedeep';
import { Types as OhifTypes, ServicesManager, PubSubService } from '@ohif/core';
import {
cache,
@@ -7,12 +5,10 @@ import {
geometryLoader,
eventTarget,
getEnabledElementByIds,
metaData,
utilities as csUtils,
volumeLoader,
} from '@cornerstonejs/core';
import {
CONSTANTS as cstConstants,
Enums as csToolsEnums,
segmentation as cstSegmentation,
Types as cstTypes,
@@ -24,7 +20,6 @@ import { easeInOutBell, reverseEaseInOutBell } from '../../utils/transitions';
import { Segment, Segmentation, SegmentationConfig } from './SegmentationServiceTypes';
import { mapROIContoursToRTStructData } from './RTSTRUCT/mapROIContoursToRTStructData';
const { COLOR_LUT } = cstConstants;
const LABELMAP = csToolsEnums.SegmentationRepresentations.Labelmap;
const CONTOUR = csToolsEnums.SegmentationRepresentations.Contour;
@@ -41,7 +36,7 @@ const EVENTS = {
SEGMENTATION_CONFIGURATION_CHANGED: 'event::segmentation_configuration_changed',
// fired when the active segment is loaded in SEG or RTSTRUCT
SEGMENT_LOADING_COMPLETE: 'event::segment_loading_complete',
// for all segments
// loading completed for all segments
SEGMENTATION_LOADING_COMPLETE: 'event::segmentation_loading_complete',
};
@@ -131,7 +126,7 @@ class SegmentationService extends PubSubService {
throw new Error('Segment index 0 is reserved for "no label"');
}
const toolGroupId = config.toolGroupId ?? this._getFirstToolGroupId();
const toolGroupId = config.toolGroupId ?? this._getApplicableToolGroupId();
const { segmentationRepresentationUID, segmentation } = this._getSegmentationInfo(
segmentationId,
@@ -190,7 +185,7 @@ class SegmentationService extends PubSubService {
);
}
if (active !== undefined) {
if (active === true) {
this._setActiveSegment(segmentationId, segmentIndex, suppressEvents);
}
@@ -362,7 +357,7 @@ class SegmentationService extends PubSubService {
}
public setActiveSegmentationForToolGroup(segmentationId: string, toolGroupId?: string): void {
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();
const suppressEvents = false;
this._setActiveSegmentationForToolGroup(segmentationId, toolGroupId, suppressEvents);
@@ -400,6 +395,23 @@ class SegmentationService extends PubSubService {
return segmentations && segmentations.map(m => this.segmentations[Object.keys(m)[0]]);
}
public getActiveSegmentation(): Segmentation {
const segmentations = this.getSegmentations();
return segmentations.find(segmentation => segmentation.isActive);
}
public getActiveSegment() {
const activeSegmentation = this.getActiveSegmentation();
const { activeSegmentIndex, segments } = activeSegmentation;
if (activeSegmentIndex === null) {
return;
}
return segments[activeSegmentIndex];
}
/**
* Get specific segmentation by its id.
*
@@ -449,15 +461,6 @@ class SegmentationService extends PubSubService {
},
]);
// if first segmentation, we can use the default colorLUT, otherwise
// we need to generate a new one and use a new colorLUT
const colorLUTIndex = 0;
if (Object.keys(this.segmentations).length !== 0) {
const newColorLUT = this.generateNewColorLUT();
const colorLUTIndex = this.getNextColorLUTIndex();
cstSegmentation.config.color.addColorLUT(newColorLUT, colorLUTIndex);
}
this.segmentations[segmentationId] = {
...segmentation,
label: segmentation.label || '',
@@ -466,7 +469,6 @@ class SegmentationService extends PubSubService {
segmentCount: segmentation.segmentCount ?? 0,
isActive: false,
isVisible: true,
colorLUTIndex,
};
cachedSegmentation = this.segmentations[segmentationId];
@@ -543,7 +545,7 @@ class SegmentationService extends PubSubService {
volumeId: segmentationId,
targetBuffer: {
type: 'Uint8Array',
sharedArrayBuffer: true,
sharedArrayBuffer: window.SharedArrayBuffer,
},
});
const derivedVolumeScalarData = derivedVolume.getScalarData();
@@ -913,7 +915,7 @@ class SegmentationService extends PubSubService {
}
const segmentation = this.getSegmentation(segmentationId);
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();
const segmentationRepresentation = this._getSegmentationRepresentation(
segmentationId,
@@ -964,7 +966,7 @@ class SegmentationService extends PubSubService {
volumeId: segmentationId,
targetBuffer: {
type: 'Uint8Array',
sharedArrayBuffer: true,
sharedArrayBuffer: window.SharedArrayBuffer,
},
});
@@ -1021,8 +1023,6 @@ class SegmentationService extends PubSubService {
segmentation.hydrated = true;
}
const { colorLUTIndex } = segmentation;
// Based on the segmentationId, set the colorLUTIndex.
const segmentationRepresentationUIDs = await cstSegmentation.addSegmentationRepresentations(
toolGroupId,
@@ -1041,12 +1041,6 @@ class SegmentationService extends PubSubService {
segmentationRepresentationUIDs[0]
);
cstSegmentation.config.color.setColorLUT(
toolGroupId,
segmentationRepresentationUIDs[0],
colorLUTIndex
);
// add the segmentation segments properly
for (const segment of segmentation.segments) {
if (segment === null || segment === undefined) {
@@ -1314,7 +1308,7 @@ class SegmentationService extends PubSubService {
if (remainingHydratedSegmentations.length) {
const { id } = remainingHydratedSegmentations[0];
this._setActiveSegmentationForToolGroup(id, this._getFirstToolGroupId(), false);
this._setActiveSegmentationForToolGroup(id, this._getApplicableToolGroupId(), false);
}
}
@@ -1326,7 +1320,7 @@ class SegmentationService extends PubSubService {
}
public getConfiguration = (toolGroupId?: string): SegmentationConfig => {
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();
const brushSize = 1;
// const brushSize = cstUtils.segmentation.getBrushSizeForToolGroup(
@@ -1514,7 +1508,6 @@ class SegmentationService extends PubSubService {
segments: [],
isVisible: true,
isActive: false,
colorLUTIndex: 0,
};
}
@@ -1621,7 +1614,7 @@ class SegmentationService extends PubSubService {
throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);
}
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();
const segmentationRepresentation = this._getSegmentationRepresentation(
segmentationId,
@@ -1715,7 +1708,7 @@ class SegmentationService extends PubSubService {
toolGroupId?: string,
suppressEvents = false
) {
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();
const { segmentationRepresentationUID, segmentation } = this._getSegmentationInfo(
segmentationId,
@@ -1774,7 +1767,7 @@ class SegmentationService extends PubSubService {
throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);
}
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();
const segmentationRepresentation = this._getSegmentationRepresentation(
segmentationId,
@@ -2091,30 +2084,23 @@ class SegmentationService extends PubSubService {
}
}
private _getFirstToolGroupId = () => {
const { toolGroupService } = this.servicesManager.services;
const toolGroupIds = toolGroupService.getToolGroupIds();
private _getApplicableToolGroupId = () => {
const { toolGroupService, viewportGridService, cornerstoneViewportService } =
this.servicesManager.services;
return toolGroupIds[0];
};
const viewportInfo = cornerstoneViewportService.getViewportInfo(
viewportGridService.getActiveViewportId()
);
private getNextColorLUTIndex = (): number => {
let i = 0;
while (true) {
if (cstSegmentation.state.getColorLUT(i) === undefined) {
return i;
}
if (!viewportInfo) {
const toolGroupIds = toolGroupService.getToolGroupIds();
i++;
return toolGroupIds[0];
}
return viewportInfo.getToolGroupId();
};
private generateNewColorLUT() {
const newColorLUT = cloneDeep(COLOR_LUT);
return newColorLUT;
}
/**
* Converts object of objects to array.
*
@@ -67,4 +67,4 @@ type SegmentationRepresentationData = {
LABELMAP?: LabelmapSegmentationData;
};
export { SegmentationConfig, Segment, Segmentation };
export type { SegmentationConfig, Segment, Segmentation };
@@ -45,7 +45,7 @@ export default class SyncGroupService {
[POSITION]: synchronizers.createCameraPositionSynchronizer,
[VOI]: synchronizers.createVOISynchronizer,
[ZOOMPAN]: synchronizers.createZoomPanSynchronizer,
[STACKIMAGE]: synchronizers.createStackImageSynchronizer,
[STACKIMAGE]: synchronizers.createImageSliceSynchronizer,
};
constructor(serviceManager: ServicesManager) {
@@ -74,6 +74,10 @@ export default class SyncGroupService {
this.synchronizerCreators[type.toLowerCase()] = creator;
}
public getSynchronizer(id: string): Synchronizer | void {
return SynchronizerManager.getSynchronizer(id);
}
protected _getOrCreateSynchronizer(
type: string,
id: string,
@@ -121,6 +125,17 @@ export default class SyncGroupService {
SynchronizerManager.destroy();
}
public getSynchronizersForViewport(
viewportId: string,
renderingEngineId: string
): Synchronizer[] {
return SynchronizerManager.getAllSynchronizers().filter(
s =>
s.hasSourceViewport(renderingEngineId, viewportId) ||
s.hasTargetViewport(renderingEngineId, viewportId)
);
}
public removeViewportFromSyncGroup(
viewportId: string,
renderingEngineId: string,
@@ -10,6 +10,7 @@ import {
VolumeViewport3D,
cache,
Enums as csEnums,
BaseVolumeViewport,
} from '@cornerstonejs/core';
import { utilities as csToolsUtils, Enums as csToolsEnums } from '@cornerstonejs/tools';
@@ -17,7 +18,7 @@ import { IViewportService } from './IViewportService';
import { RENDERING_ENGINE_ID } from './constants';
import ViewportInfo, { DisplaySetOptions, PublicViewportOptions } from './Viewport';
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
import { Presentation, Presentations } from '../../types/Presentation';
import { LutPresentation, PositionPresentation, Presentations } from '../../types/Presentation';
import JumpPresets from '../../utils/JumpPresets';
@@ -44,6 +45,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
viewportsById: Map<string, ViewportInfo> = new Map();
viewportGridResizeObserver: ResizeObserver | null;
viewportsDisplaySets: Map<string, string[]> = new Map();
beforeResizePositionPresentations: Map<string, PositionPresentation> = new Map();
// Some configs
enableResizeDetector: true;
@@ -51,6 +53,11 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
resizeRefreshMode: 'debounce';
servicesManager = null;
resizeQueue = [];
viewportResizeTimer = null;
gridResizeDelay = 50;
gridResizeTimeOut = null;
constructor(servicesManager: ServicesManager) {
super(EVENTS);
this.renderingEngine = null;
@@ -94,14 +101,28 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
}
/**
* It triggers the resize on the rendering engine.
* It triggers the resize on the rendering engine, and renders the viewports
*
* @param isGridResize - if the resize is triggered by a grid resize
* this is used to avoid double resize of the viewports since if the
* grid is resized, all viewports will be resized so there is no need
* to resize them individually which will get triggered by their
* individual resize observers
*/
public resize() {
const immediate = true;
const keepCamera = true;
this.renderingEngine.resize(immediate, keepCamera);
this.renderingEngine.render();
public resize(isGridResize = false) {
// if there is a grid resize happening, it means the viewport grid
// has been manipulated (e.g., panels closed, added, etc.) and we need
// to resize all viewports, so we will add a timeout here to make sure
// we don't double resize the viewports when viewports in the grid are
// resized individually
if (isGridResize) {
this.performResize();
this.resetGridResizeTimeout();
this.resizeQueue = [];
clearTimeout(this.viewportResizeTimer);
} else {
this.enqueueViewportResizeRequest();
}
}
/**
@@ -138,74 +159,239 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
this.viewportsDisplaySets.delete(viewportId);
}
public setPresentations(viewport, presentations?: Presentations): void {
const properties = presentations?.lutPresentation?.properties;
if (properties) {
viewport.setProperties(properties);
/**
* Sets the presentations for a given viewport. Presentations is an object
* that can define the lut or position for a viewport.
*
* @param viewportId - The ID of the viewport.
* @param presentations - The presentations to apply to the viewport.
*/
public setPresentations(viewportId: string, presentations?: Presentations): void {
const viewport = this.getCornerstoneViewport(viewportId) as
| Types.IStackViewport
| Types.IVolumeViewport;
if (!viewport) {
return;
}
const camera = presentations?.positionPresentation?.camera;
if (camera) {
viewport.setCamera(camera);
if (!presentations) {
return;
}
const { lutPresentation, positionPresentation } = presentations;
if (lutPresentation) {
const { presentation } = lutPresentation;
if (viewport instanceof BaseVolumeViewport) {
Object.entries(presentation).forEach(
([volumeId, properties]: [string, Types.ViewportProperties]) => {
viewport.setProperties(properties, volumeId);
}
);
} else {
viewport.setProperties(presentation);
}
}
if (positionPresentation) {
const { viewPlaneNormal, viewUp, zoom, pan } = positionPresentation.presentation;
viewport.setCamera({ viewPlaneNormal, viewUp });
if (zoom !== undefined) {
viewport.setZoom(zoom);
}
if (pan !== undefined) {
viewport.setPan(pan);
}
}
}
public getPresentation(viewportId: string): Presentation {
/**
* Retrieves the position presentation information for a given viewport.
* @param viewportId The ID of the viewport.
* @returns The position presentation object containing various properties
* such as ID, viewport type, initial image index, view plane normal, view up, zoom, and pan.
*/
public getPositionPresentation(viewportId: string): PositionPresentation {
const viewportInfo = this.viewportsById.get(viewportId);
if (!viewportInfo) {
return;
}
const { viewportType, presentationIds } = viewportInfo.getViewportOptions();
const presentationIds = viewportInfo.getPresentationIds();
if (!presentationIds) {
return;
}
const { positionPresentationId } = presentationIds;
const csViewport = this.getCornerstoneViewport(viewportId);
if (!csViewport) {
return;
}
const properties = csViewport.getProperties();
if (properties.isComputedVOI) {
delete properties.voiRange;
delete properties.VOILUTFunction;
}
const { viewPlaneNormal, viewUp } = csViewport.getCamera();
const initialImageIndex = csViewport.getCurrentImageIdIndex();
const camera = csViewport.getCamera();
const zoom = csViewport.getZoom();
const pan = csViewport.getPan();
return {
presentationIds,
viewportType: !viewportType || viewportType === 'stack' ? 'stack' : 'volume',
properties,
initialImageIndex,
camera,
id: positionPresentationId,
viewportType: viewportInfo.getViewportType(),
presentation: {
initialImageIndex,
viewUp,
viewPlaneNormal,
zoom,
pan,
},
};
}
public storePresentation({ viewportId }) {
const stateSyncService = this.servicesManager.services.stateSyncService;
let presentation;
try {
presentation = this.getPresentation(viewportId);
} catch (error) {
console.warn(error);
}
if (!presentation || !presentation.presentationIds) {
/**
* Retrieves the LUT (Lookup Table) presentation for a given viewport.
* @param viewportId The ID of the viewport.
* @returns The LUT presentation object, or undefined if the viewport does not exist.
*/
public getLutPresentation(viewportId: string): LutPresentation {
const viewportInfo = this.viewportsById.get(viewportId);
if (!viewportInfo) {
return;
}
const { lutPresentationStore, positionPresentationStore } = stateSyncService.getState();
const { presentationIds } = presentation;
const { lutPresentationId, positionPresentationId } = presentationIds || {};
const storeState = {};
const presentationIds = viewportInfo.getPresentationIds();
if (!presentationIds) {
return;
}
const { lutPresentationId } = presentationIds;
const csViewport = this.getCornerstoneViewport(viewportId) as
| Types.IStackViewport
| Types.IVolumeViewport;
if (!csViewport) {
return;
}
const cleanProperties = properties => {
if (properties.isComputedVOI) {
delete properties.voiRange;
delete properties.VOILUTFunction;
}
return properties;
};
const presentation =
csViewport instanceof BaseVolumeViewport
? new Map()
: cleanProperties(csViewport.getProperties());
if (presentation instanceof Map) {
csViewport.getActors().forEach(({ uid: volumeId }) => {
const properties = cleanProperties(csViewport.getProperties(volumeId));
presentation.set(volumeId, properties);
});
}
return {
id: lutPresentationId,
viewportType: viewportInfo.getViewportType(),
presentation,
};
}
/**
* Retrieves the presentations for a given viewport.
* @param viewportId - The ID of the viewport.
* @returns The presentations for the viewport.
*/
public getPresentations(viewportId: string): Presentations {
const viewportInfo = this.viewportsById.get(viewportId);
if (!viewportInfo) {
return;
}
const positionPresentation = this.getPositionPresentation(viewportId);
const lutPresentation = this.getLutPresentation(viewportId);
return {
positionPresentation,
lutPresentation,
};
}
/**
* Stores the presentation state for a given viewport inside the
* stateSyncService. This is used to persist the presentation state
* across different scenarios e.g., when the viewport is changing the
* display set, or when the viewport is moving to a different layout.
*
* @param viewportId The ID of the viewport.
*/
public storePresentation({ viewportId }) {
let presentations = null as Presentations;
try {
presentations = this.getPresentations(viewportId);
if (!presentations?.positionPresentation && !presentations?.lutPresentation) {
return;
}
} catch (error) {
console.warn(error);
return;
}
const { stateSyncService, syncGroupService } = this.servicesManager.services;
const synchronizers = syncGroupService.getSynchronizersForViewport(
viewportId,
this.renderingEngine.id
);
const { positionPresentationStore, synchronizersStore, lutPresentationStore } =
stateSyncService.getState();
const { lutPresentation, positionPresentation } = presentations;
const { id: positionPresentationId } = positionPresentation;
const { id: lutPresentationId } = lutPresentation;
const updateStore = (store, id, value) => ({ ...store, [id]: value });
const newState = {} as { [key: string]: any };
if (lutPresentationId) {
storeState.lutPresentationStore = {
...lutPresentationStore,
[lutPresentationId]: presentation,
};
newState.lutPresentationStore = updateStore(
lutPresentationStore,
lutPresentationId,
lutPresentation
);
}
if (positionPresentationId) {
storeState.positionPresentationStore = {
...positionPresentationStore,
[positionPresentationId]: presentation,
};
newState.positionPresentationStore = updateStore(
positionPresentationStore,
positionPresentationId,
positionPresentation
);
}
stateSyncService.store(storeState);
if (synchronizers?.length) {
newState.synchronizersStore = updateStore(
synchronizersStore,
viewportId,
synchronizers.map(synchronizer => ({
id: synchronizer.id,
sourceViewports: [...synchronizer.getSourceViewports()],
targetViewports: [...synchronizer.getTargetViewports()],
}))
);
}
stateSyncService.store(newState);
}
/**
@@ -283,20 +469,31 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
this.viewportsById.set(viewportId, viewportInfo);
const viewport = renderingEngine.getViewport(viewportId);
this._setDisplaySets(viewport, viewportData, viewportInfo, presentations);
const displaySetPromise = this._setDisplaySets(
viewport,
viewportData,
viewportInfo,
presentations
);
// The broadcast event here ensures that listeners have a valid, up to date
// viewport to access. Doing it too early can result in exceptions or
// invalid data.
this._broadcastEvent(this.EVENTS.VIEWPORT_DATA_CHANGED, {
viewportData,
viewportId,
displaySetPromise.then(() => {
this._broadcastEvent(this.EVENTS.VIEWPORT_DATA_CHANGED, {
viewportData,
viewportId,
});
});
}
public getCornerstoneViewport(
viewportId: string
): Types.IStackViewport | Types.IVolumeViewport | null {
/**
* Retrieves the Cornerstone viewport with the specified ID.
*
* @param viewportId - The ID of the viewport.
* @returns The Cornerstone viewport object if found, otherwise null.
*/
public getCornerstoneViewport(viewportId: string): Types.IViewport | null {
const viewportInfo = this.getViewportInfo(viewportId);
if (!viewportInfo || !this.renderingEngine || this.renderingEngine.hasBeenDestroyed) {
@@ -308,16 +505,52 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
return viewport;
}
/**
* Retrieves the viewport information for a given viewport ID. The viewport information
* is the OHIF construct that holds different options and data for a given viewport and
* is different from the cornerstone viewport.
*
* @param viewportId The ID of the viewport.
* @returns The viewport information.
*/
public getViewportInfo(viewportId: string): ViewportInfo {
return this.viewportsById.get(viewportId);
}
_setStackViewport(
/**
* Looks through the viewports to see if the specified measurement can be
* displayed in one of the viewports.
*
* @param measurement
* The measurement that is desired to view.
* @param activeViewportId - the index that was active at the time the jump
* was initiated.
* @return the viewportId that the measurement should be displayed in.
*/
public getViewportIdToJump(
activeViewportId: string,
displaySetInstanceUID: string,
cameraProps: unknown
): string {
const viewportInfo = this.getViewportInfo(activeViewportId);
const { referencedImageId } = cameraProps;
if (viewportInfo?.contains(displaySetInstanceUID, referencedImageId)) {
return activeViewportId;
}
return (
[...this.viewportsById.values()].find(viewportInfo =>
viewportInfo.contains(displaySetInstanceUID, referencedImageId)
)?.viewportId ?? null
);
}
private async _setStackViewport(
viewport: Types.IStackViewport,
viewportData: StackViewportData,
viewportInfo: ViewportInfo,
presentations: Presentations
): void {
presentations: Presentations = {}
): Promise<void> {
const displaySetOptions = viewportInfo.getDisplaySetOptions();
const { imageIds, initialImageIndex, displaySetInstanceUID } = viewportData.data;
@@ -333,7 +566,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
const properties = { ...presentations.lutPresentation?.properties };
if (!presentations.lutPresentation?.properties) {
const { voi, voiInverted } = displaySetOptions[0];
const { voi, voiInverted, colormap } = displaySetOptions[0];
if (voi && (voi.windowWidth || voi.windowCenter)) {
const { lower, upper } = csUtils.windowLevel.toLowHighRange(
voi.windowWidth,
@@ -345,14 +578,15 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
if (voiInverted !== undefined) {
properties.invert = voiInverted;
}
if (colormap !== undefined) {
properties.colormap = colormap;
}
}
viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
return viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
viewport.setProperties({ ...properties });
const camera = presentations.positionPresentation?.camera;
if (camera) {
viewport.setCamera(camera);
}
this.setPresentations(viewport.id, presentations);
});
}
@@ -420,7 +654,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
viewport: Types.IVolumeViewport,
viewportData: VolumeViewportData,
viewportInfo: ViewportInfo,
presentations: Presentations
presentations: Presentations = {}
): Promise<void> {
// TODO: We need to overhaul the way data sources work so requests can be made
// async. I think we should follow the image loader pattern which is async and
@@ -524,7 +758,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
viewport.setProperties(properties, volumeId);
});
this.setPresentations(viewport, presentations);
this.setPresentations(viewport.id, presentations);
// load any secondary displaySets
const displaySetInstanceUIDs = this.viewportsDisplaySets.get(viewport.id);
@@ -654,46 +888,54 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
const viewport = this.getCornerstoneViewport(viewportId);
const viewportCamera = viewport.getCamera();
let displaySetPromise;
if (viewport instanceof VolumeViewport || viewport instanceof VolumeViewport3D) {
this._setVolumeViewport(viewport, viewportData, viewportInfo).then(() => {
displaySetPromise = this._setVolumeViewport(viewport, viewportData, viewportInfo).then(() => {
if (keepCamera) {
viewport.setCamera(viewportCamera);
viewport.render();
}
});
return;
}
if (viewport instanceof StackViewport) {
this._setStackViewport(viewport, viewportData, viewportInfo);
return;
displaySetPromise = this._setStackViewport(viewport, viewportData, viewportInfo);
}
displaySetPromise.then(() => {
this._broadcastEvent(this.EVENTS.VIEWPORT_DATA_CHANGED, {
viewportData,
viewportId,
});
});
}
_setDisplaySets(
viewport: StackViewport | VolumeViewport,
viewport: Types.IViewport,
viewportData: StackViewportData | VolumeViewportData,
viewportInfo: ViewportInfo,
presentations: Presentations = {}
): void {
): Promise<void> {
if (viewport instanceof StackViewport) {
this._setStackViewport(
return this._setStackViewport(
viewport,
viewportData as StackViewportData,
viewportInfo,
presentations
);
} else if (viewport instanceof VolumeViewport || viewport instanceof VolumeViewport3D) {
this._setVolumeViewport(
viewport,
}
if ([VolumeViewport, VolumeViewport3D].some(type => viewport instanceof type)) {
return this._setVolumeViewport(
viewport as Types.IVolumeViewport,
viewportData as VolumeViewportData,
viewportInfo,
presentations
);
} else {
throw new Error('Unknown viewport type');
}
throw new Error('Unknown viewport type');
}
/**
@@ -759,32 +1001,57 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
}
}
/**
* Looks through the viewports to see if the specified measurement can be
* displayed in one of the viewports.
*
* @param measurement
* The measurement that is desired to view.
* @param activeViewportId - the index that was active at the time the jump
* was initiated.
* @return the viewportId that the measurement should be displayed in.
*/
public getViewportIdToJump(
activeViewportId: string,
displaySetInstanceUID: string,
cameraProps: unknown
): string {
const viewportInfo = this.getViewportInfo(activeViewportId);
const { referencedImageId } = cameraProps;
if (viewportInfo?.contains(displaySetInstanceUID, referencedImageId)) {
return activeViewportId;
private enqueueViewportResizeRequest() {
this.resizeQueue.push(false); // false indicates viewport resize
clearTimeout(this.viewportResizeTimer);
this.viewportResizeTimer = setTimeout(() => {
this.processViewportResizeQueue();
}, this.gridResizeDelay);
}
private processViewportResizeQueue() {
const isGridResizeInQueue = this.resizeQueue.some(isGridResize => isGridResize);
if (this.resizeQueue.length > 0 && !isGridResizeInQueue && !this.gridResizeTimeOut) {
this.performResize();
}
return (
[...this.viewportsById.values()].find(viewportInfo =>
viewportInfo.contains(displaySetInstanceUID, referencedImageId)
)?.viewportId ?? null
);
// Clear the queue after processing viewport resizes
this.resizeQueue = [];
}
private performResize() {
const isImmediate = false;
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);
});
// 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 });
});
// Resize and render the rendering engine again.
renderingEngine.resize(isImmediate);
renderingEngine.render();
}
private resetGridResizeTimeout() {
clearTimeout(this.gridResizeTimeOut);
this.gridResizeTimeOut = setTimeout(() => {
this.gridResizeTimeOut = null;
}, this.gridResizeDelay);
}
}
@@ -1,6 +1,7 @@
import { Types } from '@cornerstonejs/core';
import { StackData, VolumeData } from '../../types/CornerstoneCacheService';
import { DisplaySetOptions, PublicViewportOptions, ViewportOptions } from './Viewport';
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
import { DisplaySetOptions, PublicViewportOptions } from './Viewport';
import { Presentations } from '../../types/Presentation';
/**
* Handles cornerstone viewport logic including enabling, disabling, and
@@ -36,7 +37,7 @@ export interface IViewportService {
* the element for resizing events
* @param {*} elementRef
*/
resize(element: HTMLDivElement): void;
resize(isGridResize: boolean): void;
/**
* Removes the viewport from cornerstone, and destroys the rendering engine
*/
@@ -55,8 +56,10 @@ export interface IViewportService {
* @returns
*/
setViewportData(
viewportData: StackData | VolumeData,
viewportId: string,
viewportData: StackViewportData | VolumeViewportData,
publicViewportOptions: PublicViewportOptions,
publicDisplaySetOptions: DisplaySetOptions[]
publicDisplaySetOptions: DisplaySetOptions[],
presentations?: Presentations
): void;
}
@@ -1,5 +1,5 @@
import { Types, Enums } from '@cornerstonejs/core';
import { Types as UITypes } from '@ohif/ui';
import { Types as CoreTypes } from '@ohif/core';
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
import getCornerstoneBlendMode from '../../utils/getCornerstoneBlendMode';
import getCornerstoneOrientation from '../../utils/getCornerstoneOrientation';
@@ -18,7 +18,7 @@ export type ViewportOptions = {
toolGroupId: string;
viewportId: string;
// Presentation ID to store/load presentation state from
presentationIds?: UITypes.PresentationIds;
presentationIds?: CoreTypes.PresentationIds;
orientation?: Enums.OrientationAxis;
background?: Types.Point3;
displayArea?: Types.DisplayArea;
@@ -36,7 +36,7 @@ export type PublicViewportOptions = {
id?: string;
viewportType?: string;
toolGroupId?: string;
presentationIds?: UITypes.PresentationIds;
presentationIds?: CoreTypes.PresentationIds;
viewportId?: string;
orientation?: Enums.OrientationAxis;
background?: Types.Point3;
@@ -71,7 +71,7 @@ export type DisplaySetOptions = {
voiInverted: boolean;
blendMode?: Enums.BlendModes;
slabThickness?: number;
colormap?: string;
colormap?: { name: string; opacity?: number };
displayPreset?: string;
};
@@ -238,6 +238,11 @@ class ViewportInfo {
return this.viewportOptions;
}
public getPresentationIds(): CoreTypes.PresentationIds {
const { presentationIds } = this.viewportOptions;
return presentationIds;
}
public setDisplaySetOptions(displaySetOptions: Array<DisplaySetOptions>): void {
this.displaySetOptions = displaySetOptions;
}
@@ -66,14 +66,6 @@ export function onCompletedCalibrationLine(servicesManager, csToolsEvent) {
calculateLength3(annotationData.handles.points[0], annotationData.handles.points[1]) * 100
) / 100;
// calculate the currently applied pixel spacing on the viewport
const calibratedPixelSpacing = metaData.get('calibratedPixelSpacing', imageId);
const imagePlaneModule = metaData.get('imagePlaneModule', imageId);
const currentRowPixelSpacing =
calibratedPixelSpacing?.[0] || imagePlaneModule?.rowPixelSpacing || 1;
const currentColumnPixelSpacing =
calibratedPixelSpacing?.[1] || imagePlaneModule?.columnPixelSpacing || 1;
const adjustCalibration = newLength => {
const spacingScale = newLength / length;
@@ -1,8 +1,8 @@
import { VolumeViewport, metaData } from '@cornerstonejs/core';
import { utilities } from '@cornerstonejs/core';
import { VolumeViewport, metaData, utilities } from '@cornerstonejs/core';
import { IStackViewport, IVolumeViewport, Point3 } from '@cornerstonejs/core/dist/esm/types';
import { AnnotationDisplayTool, drawing } from '@cornerstonejs/tools';
import { guid } from '@ohif/core/src/utils';
import { guid, b64toBlob } from '@ohif/core/src/utils';
import OverlayPlaneModuleProvider from './OverlayPlaneModuleProvider';
interface CachedStat {
color: number[]; // [r, g, b, a]
@@ -27,8 +27,12 @@ interface CachedStat {
*/
class ImageOverlayViewerTool extends AnnotationDisplayTool {
static toolName = 'ImageOverlayViewer';
private _cachedOverlayMetadata: Map<string, any[]> = new Map();
private _cachedStats: { [key: string]: CachedStat } = {};
/**
* The overlay plane module provider add method is exposed here to be used
* when updating the overlay for this tool to use for displaying data.
*/
public static addOverlayPlaneModule = OverlayPlaneModuleProvider.add;
constructor(
toolProps = {},
@@ -42,10 +46,7 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
super(toolProps, defaultToolProps);
}
onSetToolDisabled = (): void => {
this._cachedStats = {};
this._cachedOverlayMetadata = new Map();
};
onSetToolDisabled = (): void => {};
protected getReferencedImageId(viewport: IStackViewport | IVolumeViewport): string {
if (viewport instanceof VolumeViewport) {
@@ -64,18 +65,24 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
return;
}
const overlays =
this._cachedOverlayMetadata.get(imageId) ??
metaData.get('overlayPlaneModule', imageId)?.overlays;
const overlayMetadata = metaData.get('overlayPlaneModule', imageId);
const overlays = overlayMetadata?.overlays;
// no overlays
if (!overlays?.length) {
return;
}
this._cachedOverlayMetadata.set(imageId, overlays);
// Fix the x, y positions
overlays.forEach(overlay => {
overlay.x ||= 0;
overlay.y ||= 0;
});
this._getCachedStat(imageId, overlays, this.configuration.fillColor).then(cachedStat => {
// Will clear cached stat data when the overlay data changes
ImageOverlayViewerTool.addOverlayPlaneModule(imageId, overlayMetadata);
this._getCachedStat(imageId, overlayMetadata, this.configuration.fillColor).then(cachedStat => {
cachedStat.overlays.forEach(overlay => {
this._renderOverlay(enabledElement, svgDrawingHelper, overlay);
});
@@ -146,15 +153,18 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
private async _getCachedStat(
imageId: string,
overlayMetadata: any[],
overlayMetadata,
color: number[]
): Promise<CachedStat> {
if (this._cachedStats[imageId] && this._isSameColor(this._cachedStats[imageId].color, color)) {
return this._cachedStats[imageId];
const missingOverlay = overlayMetadata.overlays.filter(
overlay => overlay.pixelData && !overlay.dataUrl
);
if (missingOverlay.length === 0) {
return overlayMetadata;
}
const overlays = await Promise.all(
overlayMetadata
overlayMetadata.overlays
.filter(overlay => overlay.pixelData)
.map(async (overlay, idx) => {
let pixelData = null;
@@ -164,6 +174,10 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
pixelData = overlay.pixelData[0];
} else if (overlay.pixelData.retrieveBulkData) {
pixelData = await overlay.pixelData.retrieveBulkData();
} else if (overlay.pixelData.InlineBinary) {
const blob = b64toBlob(overlay.pixelData.InlineBinary);
const arrayBuffer = await blob.arrayBuffer();
pixelData = arrayBuffer;
}
if (!pixelData) {
@@ -172,7 +186,7 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
const dataUrl = this._renderOverlayToDataUrl(
{ width: overlay.columns, height: overlay.rows },
color,
overlay.color || color,
pixelData
);
@@ -184,13 +198,9 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
};
})
);
overlayMetadata.overlays = overlays;
this._cachedStats[imageId] = {
color: color,
overlays: overlays.filter(overlay => overlay),
};
return this._cachedStats[imageId];
return overlayMetadata;
}
/**
@@ -0,0 +1,40 @@
import { metaData } from '@cornerstonejs/core';
const _cachedOverlayMetadata: Map<string, any[]> = new Map();
/**
* Image Overlay Viewer tool is not a traditional tool that requires user interactin.
* But it is used to display Pixel Overlays. And it will provide toggling capability.
*
* The documentation for Overlay Plane Module of DICOM can be found in [C.9.2 of
* Part-3 of DICOM standard](https://dicom.nema.org/medical/dicom/2018b/output/chtml/part03/sect_C.9.2.html)
*
* Image Overlay rendered by this tool can be toggled on and off using
* toolGroup.setToolEnabled() and toolGroup.setToolDisabled()
*/
const OverlayPlaneModuleProvider = {
/** Adds the metadata for overlayPlaneModule */
add: (imageId, metadata) => {
if (_cachedOverlayMetadata.get(imageId) === metadata) {
// This is a no-op here as the tool re-caches the data
return;
}
_cachedOverlayMetadata.set(imageId, metadata);
},
/** Standard getter for metadata */
get: (type: string, query: string | string[]) => {
if (Array.isArray(query)) {
return;
}
if (type !== 'overlayPlaneModule') {
return;
}
return _cachedOverlayMetadata.get(query);
},
};
// Needs to be higher priority than default provider
metaData.addProvider(OverlayPlaneModuleProvider.get, 10_000);
export default OverlayPlaneModuleProvider;
@@ -1,23 +1,45 @@
/** Store presentation data for either stack viewports or volume viewports */
import { Types } from '@cornerstonejs/core';
import { Types as UITypes } from '@ohif/ui';
import type { Types } from '@cornerstonejs/core';
/**
* Has information on the presentation of the viewport.
* Represents a position presentation in a viewport. This is basically
* viewport specific camera position and zoom, and not the display set
*/
export interface Presentation extends Types.StackViewportProperties {
presentationIds: UITypes.PresentationIds;
export type PositionPresentation = {
id: string;
viewportType: string;
initialImageIndex: number;
camera: Types.ICamera;
properties: Types.StackViewportProperties | Types.VolumeViewportProperties;
zoom?: number;
pan?: [number, number];
presentation: {
initialImageIndex: number;
viewUp: Types.Point3;
viewPlaneNormal: Types.Point3;
zoom?: number;
pan?: Types.Point2;
};
};
/**
* Represents a LUT presentation in a viewport, and is really related
* to displaySets and not the viewport itself. So that is why it can
* be an object with volumeId keys, or a single object with the properties
* itself
*/
export interface LutPresentation {
id: string;
viewportType: string;
presentation: Record<string, Types.ViewportProperties> | Types.ViewportProperties;
}
/**
* Presentation can be a PositionPresentation or a LutPresentation.
*/
type Presentation = PositionPresentation | LutPresentation;
/**
* Viewport presentations object that can contain a positionPresentation
* and or a lutPresentation.
*/
export type Presentations = {
positionPresentation?: Presentation;
lutPresentation?: Presentation;
positionPresentation?: PositionPresentation;
lutPresentation?: LutPresentation;
};
export default Presentation;
@@ -93,6 +93,7 @@ const CornerstoneViewportDownloadForm = ({
renderingEngine.resize();
// Trigger the render on the viewport to update the on screen
downloadViewport.resetCamera();
downloadViewport.render();
downloadViewportElement.addEventListener(
@@ -223,7 +224,6 @@ const CornerstoneViewportDownloadForm = ({
minimumSize={MINIMUM_SIZE}
maximumSize={MAX_TEXTURE_SIZE}
defaultSize={DEFAULT_SIZE}
canvasClass={'cornerstone-canvas'}
activeViewportElement={activeViewportElement}
enableViewport={enableViewport}
disableViewport={disableViewport}
@@ -176,6 +176,7 @@ class DicomLoaderService {
authorizationHeaders,
wadoRoot,
wadoUri,
instance,
} = dataset;
// Retrieve wadors or just try to fetch wadouri
if (!someInvalidStrings(wadoRoot)) {
@@ -188,6 +189,13 @@ class DicomLoaderService {
);
} else if (!someInvalidStrings(wadoUri)) {
return fetchIt(wadoUri, { headers: authorizationHeaders });
} else if (!someInvalidStrings(instance?.url)) {
// make sure the url is absolute, remove the scope
// from it if it is not absolute. For instance it might be dicomweb:http://....
// and we need to remove the dicomweb: part
const url = instance.url;
const absoluteUrl = url.startsWith('http') ? url : url.substring(url.indexOf(':') + 1);
return fetchIt(absoluteUrl, { headers: authorizationHeaders });
}
}
@@ -1,18 +1,19 @@
const STACK_SYNC_NAME = 'stackImageSync';
const IMAGE_SLICE_SYNC_NAME = 'IMAGE_SLICE_SYNC';
export default function toggleStackImageSync({
export default function toggleImageSliceSync({
toggledState,
servicesManager,
viewports: providedViewports,
}) {
if (!toggledState) {
return disableSync(STACK_SYNC_NAME, servicesManager);
return disableSync(IMAGE_SLICE_SYNC_NAME, servicesManager);
}
const { syncGroupService, viewportGridService, displaySetService, cornerstoneViewportService } =
servicesManager.services;
const viewports = providedViewports || getReconstructableStackViewports(viewportGridService, displaySetService);
const viewports =
providedViewports || getReconstructableStackViewports(viewportGridService, displaySetService);
// create synchronization group and add the viewports to it.
viewports.forEach(gridViewport => {
@@ -23,7 +24,7 @@ export default function toggleStackImageSync({
}
syncGroupService.addViewportToSyncGroup(viewportId, viewport.getRenderingEngine().id, {
type: 'stackimage',
id: STACK_SYNC_NAME,
id: IMAGE_SLICE_SYNC_NAME,
source: true,
target: true,
});
@@ -46,7 +47,7 @@ function disableSync(syncName, servicesManager) {
syncName
);
});
};
}
/**
* Gets the consistent spacing stack viewport types, which are the ones which
@@ -77,4 +78,4 @@ function getReconstructableStackViewports(viewportGridService, displaySetService
}
});
return viewports;
};
}
@@ -1,13 +1,7 @@
import { log, Types } from '@ohif/core';
import { log, Enums } from '@ohif/core';
import { EVENTS } from '@cornerstonejs/core';
const { TimingEnum } = Types;
const IMAGE_TIMING_KEYS = [
TimingEnum.DISPLAY_SETS_TO_ALL_IMAGES,
TimingEnum.DISPLAY_SETS_TO_FIRST_IMAGE,
TimingEnum.STUDY_TO_FIRST_IMAGE,
];
const IMAGE_TIMING_KEYS = [];
const imageTiming = {
viewportsWaiting: 0,
@@ -23,6 +17,18 @@ const imageTiming = {
*/
export default function initViewTiming({ element }) {
if (!IMAGE_TIMING_KEYS.length) {
// Work around a bug in WebPack that doesn't getting the enums initialized
// quite fast enough to be declared statically.
const { TimingEnum } = Enums;
IMAGE_TIMING_KEYS.push(
TimingEnum.DISPLAY_SETS_TO_ALL_IMAGES,
TimingEnum.DISPLAY_SETS_TO_FIRST_IMAGE,
TimingEnum.STUDY_TO_FIRST_IMAGE,
);
}
if (!IMAGE_TIMING_KEYS.find(key => log.timingKeys[key])) {
return;
}
@@ -34,6 +40,7 @@ function imageRenderedListener(evt) {
if (evt.detail.viewportStatus === 'preRender') {
return;
}
const { TimingEnum } = Enums;
log.timeEnd(TimingEnum.DISPLAY_SETS_TO_FIRST_IMAGE);
log.timeEnd(TimingEnum.STUDY_TO_FIRST_IMAGE);
log.timeEnd(TimingEnum.SCRIPT_TO_VIEW);
@@ -50,7 +50,7 @@ const Angle = {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}
const { points } = data.handles;
const { points, textBox } = data.handles;
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
@@ -62,6 +62,7 @@ const Angle = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
@@ -48,7 +48,7 @@ const Length = {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}
const { points } = data.handles;
const { points, textBox } = data.handles;
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
@@ -59,6 +59,7 @@ const Length = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
@@ -66,7 +67,6 @@ const Length = {
toolName: metadata.toolName,
displaySetInstanceUID: displaySet.displaySetInstanceUID,
label: data.text,
text: data.text,
displayText: displayText,
data: data.cachedStats,
type: getValueTypeFromToolType(toolName),
@@ -45,7 +45,7 @@ const Bidirectional = {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}
const { points } = data.handles;
const { points, textBox } = data.handles;
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
@@ -57,6 +57,7 @@ const Bidirectional = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
@@ -43,7 +43,7 @@ const CircleROI = {
displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}
const { points } = data.handles;
const { points, textBox } = data.handles;
const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);
@@ -55,6 +55,7 @@ const CircleROI = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
@@ -50,7 +50,7 @@ const CobbAngle = {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}
const { points } = data.handles;
const { points, textBox } = data.handles;
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
@@ -62,6 +62,7 @@ const CobbAngle = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
@@ -43,7 +43,7 @@ const EllipticalROI = {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}
const { points } = data.handles;
const { points, textBox } = data.handles;
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
@@ -55,6 +55,7 @@ const EllipticalROI = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
@@ -53,7 +53,7 @@ const Length = {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}
const { points } = data.handles;
const { points, textBox } = data.handles;
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
@@ -65,6 +65,7 @@ const Length = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
@@ -48,7 +48,7 @@ const PlanarFreehandROI = {
displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}
const { points } = data.handles;
const { points, textBox } = data.handles;
const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);
@@ -60,6 +60,7 @@ const PlanarFreehandROI = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
@@ -43,7 +43,7 @@ const RectangleROI = {
displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}
const { points } = data.handles;
const { points, textBox } = data.handles;
const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);
@@ -55,6 +55,7 @@ const RectangleROI = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
+653
View File
@@ -3,6 +3,659 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.8.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.62...v3.8.0-beta.63) (2024-03-25)
### Features
* **worklist:** new investigational use text ([#3999](https://github.com/OHIF/Viewers/issues/3999)) ([45b68e8](https://github.com/OHIF/Viewers/commit/45b68e841dcb9e28a2ea991c37ee7ac4a8c5b71e))
# [3.8.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.61...v3.8.0-beta.62) (2024-03-19)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.60...v3.8.0-beta.61) (2024-03-18)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.59...v3.8.0-beta.60) (2024-03-15)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.58...v3.8.0-beta.59) (2024-03-08)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.57...v3.8.0-beta.58) (2024-03-05)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.56...v3.8.0-beta.57) (2024-02-28)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.55...v3.8.0-beta.56) (2024-02-22)
### Bug Fixes
* **demo:** Deploy issue ([#3951](https://github.com/OHIF/Viewers/issues/3951)) ([21e8a2b](https://github.com/OHIF/Viewers/commit/21e8a2bd0b7cc72f90a31e472d285d761be15d30))
# [3.8.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.54...v3.8.0-beta.55) (2024-02-21)
### Features
* **resize:** Optimize resizing process and maintain zoom level ([#3889](https://github.com/OHIF/Viewers/issues/3889)) ([b3a0faf](https://github.com/OHIF/Viewers/commit/b3a0faf5f5f0a1993b2b017eb4cc1216164ea2c6))
# [3.8.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.53...v3.8.0-beta.54) (2024-02-14)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.52...v3.8.0-beta.53) (2024-02-05)
### Bug Fixes
* 🐛 Sort merge results based on default data source (input) ([#3903](https://github.com/OHIF/Viewers/issues/3903)) ([5bba98e](https://github.com/OHIF/Viewers/commit/5bba98ed848bdf46b5ba4fc4708527cced3308b5))
# [3.8.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.51...v3.8.0-beta.52) (2024-01-22)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.50...v3.8.0-beta.51) (2024-01-22)
### Bug Fixes
* catch errors in getPTImageIdInstanceMetadata ([#3897](https://github.com/OHIF/Viewers/issues/3897)) ([a47aeb8](https://github.com/OHIF/Viewers/commit/a47aeb8bd729dcb8d2cfc13b27a31b0dd88f11ad))
# [3.8.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.49...v3.8.0-beta.50) (2024-01-22)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.48...v3.8.0-beta.49) (2024-01-19)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.47...v3.8.0-beta.48) (2024-01-17)
### Bug Fixes
* 🐛 Check merge key for merge data source ([#3901](https://github.com/OHIF/Viewers/issues/3901)) ([911d672](https://github.com/OHIF/Viewers/commit/911d67283536b2fe7930948f2819ea0ad66e2a32))
# [3.8.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.46...v3.8.0-beta.47) (2024-01-12)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.45...v3.8.0-beta.46) (2024-01-12)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.44...v3.8.0-beta.45) (2024-01-09)
### Features
* **hp:** enable OHIF to run with partial metadata for large studies at the cost of less effective hanging protocol ([#3804](https://github.com/OHIF/Viewers/issues/3804)) ([0049f4c](https://github.com/OHIF/Viewers/commit/0049f4c0303f0b6ea995972326fc8784259f5a47))
# [3.8.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.43...v3.8.0-beta.44) (2024-01-09)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.42...v3.8.0-beta.43) (2024-01-09)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.41...v3.8.0-beta.42) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.40...v3.8.0-beta.41) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.39...v3.8.0-beta.40) (2024-01-08)
### Features
* **ui:** sidePanel expandedWidth ([#3728](https://github.com/OHIF/Viewers/issues/3728)) ([61bf22c](https://github.com/OHIF/Viewers/commit/61bf22c6f80e764bdf5c3b56bb0124a95aa0f793))
# [3.8.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.38...v3.8.0-beta.39) (2024-01-08)
### Features
* improve disableEditing flag ([#3875](https://github.com/OHIF/Viewers/issues/3875)) ([2049c09](https://github.com/OHIF/Viewers/commit/2049c0936c86f819604c243d3dc7b3fe971b5b2c))
# [3.8.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.37...v3.8.0-beta.38) (2024-01-08)
### Bug Fixes
* PDF display request in v3 ([#3878](https://github.com/OHIF/Viewers/issues/3878)) ([9865030](https://github.com/OHIF/Viewers/commit/98650302c7575f0aea386e32cfc4112c378035e6))
# [3.8.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.36...v3.8.0-beta.37) (2024-01-08)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.35...v3.8.0-beta.36) (2023-12-15)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.34...v3.8.0-beta.35) (2023-12-14)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.33...v3.8.0-beta.34) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.32...v3.8.0-beta.33) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.31...v3.8.0-beta.32) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.30...v3.8.0-beta.31) (2023-12-13)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.29...v3.8.0-beta.30) (2023-12-13)
### Features
* **customizationService:** Enable saving and loading of private tags in SRs ([#3842](https://github.com/OHIF/Viewers/issues/3842)) ([e1f55e6](https://github.com/OHIF/Viewers/commit/e1f55e65f2d2a34136ad5d0b1ada77d337a0ea23))
# [3.8.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.28...v3.8.0-beta.29) (2023-12-13)
### Features
* **i18n:** enhanced i18n support ([#3761](https://github.com/OHIF/Viewers/issues/3761)) ([d14a8f0](https://github.com/OHIF/Viewers/commit/d14a8f0199db95cd9e85866a011b64d6bf830d57))
# [3.8.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.27...v3.8.0-beta.28) (2023-12-08)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.26...v3.8.0-beta.27) (2023-12-06)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.25...v3.8.0-beta.26) (2023-11-28)
### Bug Fixes
* **SM:** drag and drop is now fixed for SM ([#3813](https://github.com/OHIF/Viewers/issues/3813)) ([f1a6764](https://github.com/OHIF/Viewers/commit/f1a67647aed635437b188cea7cf5d5a8fb974bbe))
# [3.8.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.24...v3.8.0-beta.25) (2023-11-27)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.23...v3.8.0-beta.24) (2023-11-24)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.22...v3.8.0-beta.23) (2023-11-24)
### Features
* Merge Data Source ([#3788](https://github.com/OHIF/Viewers/issues/3788)) ([c4ff2c2](https://github.com/OHIF/Viewers/commit/c4ff2c2f09546ce8b72eab9c5e7beed611e3cab0))
# [3.8.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.21...v3.8.0-beta.22) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.20...v3.8.0-beta.21) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.19...v3.8.0-beta.20) (2023-11-21)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.18...v3.8.0-beta.19) (2023-11-18)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.17...v3.8.0-beta.18) (2023-11-15)
### Features
* **url:** Add SeriesInstanceUIDs wado query param ([#3746](https://github.com/OHIF/Viewers/issues/3746)) ([b694228](https://github.com/OHIF/Viewers/commit/b694228dd535e4b97cb86a1dc085b6e8716bdaf3))
# [3.8.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.16...v3.8.0-beta.17) (2023-11-13)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.15...v3.8.0-beta.16) (2023-11-13)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.14...v3.8.0-beta.15) (2023-11-10)
### Features
* **dicomJSON:** Add Loading Other Display Sets and JSON Metadata Generation script ([#3777](https://github.com/OHIF/Viewers/issues/3777)) ([43b1c17](https://github.com/OHIF/Viewers/commit/43b1c17209502e4876ad59bae09ed9442eda8024))
# [3.8.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.13...v3.8.0-beta.14) (2023-11-10)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.12...v3.8.0-beta.13) (2023-11-09)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.11...v3.8.0-beta.12) (2023-11-08)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.10...v3.8.0-beta.11) (2023-11-08)
### Features
* **hp callback:** Add viewport ready callback ([#3772](https://github.com/OHIF/Viewers/issues/3772)) ([bf252bc](https://github.com/OHIF/Viewers/commit/bf252bcec2aae3a00479fdcb732110b344bcf2c0))
# [3.8.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.9...v3.8.0-beta.10) (2023-11-03)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.8...v3.8.0-beta.9) (2023-11-02)
### Bug Fixes
* **thumbnail:** Avoid multiple promise creations for thumbnails ([#3756](https://github.com/OHIF/Viewers/issues/3756)) ([b23eeff](https://github.com/OHIF/Viewers/commit/b23eeff93745769e67e60c33d75293d6242c5ec9))
# [3.8.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.7...v3.8.0-beta.8) (2023-10-31)
### Features
* **i18n:** enhanced i18n support ([#3730](https://github.com/OHIF/Viewers/issues/3730)) ([330e11c](https://github.com/OHIF/Viewers/commit/330e11c7ff0151e1096e19b8ffdae7d64cae280e))
# [3.8.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.6...v3.8.0-beta.7) (2023-10-30)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.5...v3.8.0-beta.6) (2023-10-25)
### Bug Fixes
* **toolbar:** allow customizable toolbar for active viewport and allow active tool to be deactivated via a click ([#3608](https://github.com/OHIF/Viewers/issues/3608)) ([dd6d976](https://github.com/OHIF/Viewers/commit/dd6d9768bbca1d3cc472e8c1e6d85822500b96ef))
# [3.8.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.4...v3.8.0-beta.5) (2023-10-24)
### Bug Fixes
* **sr:** dcm4chee requires the patient name for an SR to match what is in the original study ([#3739](https://github.com/OHIF/Viewers/issues/3739)) ([d98439f](https://github.com/OHIF/Viewers/commit/d98439fe7f3825076dbc87b664a1d1480ff414d3))
# [3.8.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.3...v3.8.0-beta.4) (2023-10-23)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.2...v3.8.0-beta.3) (2023-10-23)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.1...v3.8.0-beta.2) (2023-10-19)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.0...v3.8.0-beta.1) (2023-10-19)
**Note:** Version bump only for package @ohif/extension-default
# [3.8.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.8.0-beta.0) (2023-10-12)
**Note:** Version bump only for package @ohif/extension-default
# [3.7.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.109...v3.7.0-beta.110) (2023-10-11)
### Bug Fixes
* **display messages:** broken after timings ([#3719](https://github.com/OHIF/Viewers/issues/3719)) ([157b88c](https://github.com/OHIF/Viewers/commit/157b88c909d3289cb89ace731c1f9a19d40797ac))
# [3.7.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.108...v3.7.0-beta.109) (2023-10-11)
### Bug Fixes
* **export:** wrong export for the tmtv RT function ([#3715](https://github.com/OHIF/Viewers/issues/3715)) ([a3f2a1a](https://github.com/OHIF/Viewers/commit/a3f2a1a7b0d16bfcc0ecddc2ab731e54c5e377c8))
# [3.7.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.107...v3.7.0-beta.108) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-default
# [3.7.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.106...v3.7.0-beta.107) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-default
# [3.7.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.105...v3.7.0-beta.106) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-default
# [3.7.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.104...v3.7.0-beta.105) (2023-10-10)
**Note:** Version bump only for package @ohif/extension-default
# [3.7.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.103...v3.7.0-beta.104) (2023-10-09)
**Note:** Version bump only for package @ohif/extension-default
# [3.7.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.102...v3.7.0-beta.103) (2023-10-09)
**Note:** Version bump only for package @ohif/extension-default
# [3.7.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.101...v3.7.0-beta.102) (2023-10-06)
**Note:** Version bump only for package @ohif/extension-default
# [3.7.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.100...v3.7.0-beta.101) (2023-10-06)
+1
View File
@@ -0,0 +1 @@
module.exports = require('../../babel.config.js');
+17
View File
@@ -0,0 +1,17 @@
const base = require('../../jest.config.base.js');
const pkg = require('./package');
module.exports = {
...base,
name: pkg.name,
displayName: pkg.name,
moduleNameMapper: {
...base.moduleNameMapper,
'@ohif/(.*)': '<rootDir>/../../platform/$1/src',
},
// rootDir: "../.."
// testMatch: [
// //`<rootDir>/platform/${pack.name}/**/*.spec.js`
// "<rootDir>/platform/app/**/*.test.js"
// ]
};
+7 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-default",
"version": "3.7.0-beta.101",
"version": "3.8.0-beta.63",
"description": "Common/default features and functionality for basic image viewing",
"author": "OHIF Core Team",
"license": "MIT",
@@ -23,6 +23,8 @@
"ohif-extension"
],
"scripts": {
"clean": "shx rm -rf dist",
"clean:deep": "yarn run clean && shx rm -rf node_modules",
"dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
"dev:dicom-pdf": "yarn run dev",
"build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
@@ -30,10 +32,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.7.0-beta.101",
"@ohif/i18n": "3.7.0-beta.101",
"dcmjs": "^0.29.5",
"dicomweb-client": "^0.10.2",
"@ohif/core": "3.8.0-beta.63",
"@ohif/i18n": "3.8.0-beta.63",
"dcmjs": "^0.29.12",
"dicomweb-client": "^0.10.4",
"prop-types": "^15.6.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
@@ -8,6 +8,7 @@ export type SidePanelWithServicesProps = {
className: string;
activeTabIndex: number;
tabs: any;
expandedWidth?: number;
};
const SidePanelWithServices = ({
@@ -16,7 +17,8 @@ const SidePanelWithServices = ({
className,
activeTabIndex: activeTabIndexProp,
tabs,
}) => {
expandedWidth,
}: SidePanelWithServicesProps) => {
const panelService: PanelService = servicesManager?.services?.panelService;
// Tracks whether this SidePanel has been opened at least once since this SidePanel was inserted into the DOM.
@@ -53,6 +55,7 @@ const SidePanelWithServices = ({
onOpen={() => {
setHasBeenOpened(true);
}}
expandedWidth={expandedWidth}
></SidePanel>
);
};
@@ -1,6 +1,7 @@
import * as ContextMenuItemsBuilder from './ContextMenuItemsBuilder';
import ContextMenu from '../../../../platform/ui/src/components/ContextMenu/ContextMenu';
import { CommandsManager, ServicesManager, Types } from '@ohif/core';
import { annotation as CsAnnotation } from '@cornerstonejs/tools';
import { Menu, MenuItem, Point, ContextMenuProps } from './types';
/**
@@ -47,6 +48,18 @@ export default class ContextMenuController {
const { event, subMenu, menuId, menus, selectorProps } = contextMenuProps;
const annotationManager = CsAnnotation.state.getAnnotationManager();
const { locking } = CsAnnotation;
const targetAnnotationId = selectorProps?.nearbyToolData?.annotationUID as string;
const isLocked = locking.isAnnotationLocked(
annotationManager.getAnnotation(targetAnnotationId)
);
if (isLocked) {
console.warn('Annotation is locked.');
return;
}
console.log('Getting items from', menus);
const items = ContextMenuItemsBuilder.getMenuItems(
selectorProps || contextMenuProps,
@@ -1,14 +1,14 @@
import ContextMenuItemsBuilder from './ContextMenuItemsBuilder';
import * as ContextMenuItemsBuilder from './ContextMenuItemsBuilder';
const menus = [
{
id: 'one',
selector: ({ value }) => value === 'one',
selector: ({ value } = {}) => value === 'one',
items: [],
},
{
id: 'two',
selector: ({ value }) => value === 'two',
selector: ({ value } = {}) => value === 'two',
items: [],
},
{
@@ -17,13 +17,13 @@ const menus = [
},
];
const menuBuilder = new ContextMenuItemsBuilder();
describe('ContextMenuItemsBuilder', () => {
test('findMenuDefault', () => {
expect(menuBuilder.findMenuDefault(menus, {})).toBe(menus[2]);
expect(menuBuilder.findMenuDefault(menus, { value: 'two' })).toBe(menus[1]);
expect(menuBuilder.findMenuDefault([], {})).toBeUndefined();
expect(menuBuilder.findMenuDefault(undefined, undefined)).toBeNull();
expect(ContextMenuItemsBuilder.findMenuDefault(menus, {})).toBe(menus[2]);
expect(
ContextMenuItemsBuilder.findMenuDefault(menus, { selectorProps: { value: 'two' } })
).toBe(menus[1]);
expect(ContextMenuItemsBuilder.findMenuDefault([], {})).toBeUndefined();
expect(ContextMenuItemsBuilder.findMenuDefault(undefined, undefined)).toBeNull();
});
});
@@ -25,6 +25,23 @@ let _store = {
// }
};
function wrapSequences(obj) {
return Object.keys(obj).reduce(
(acc, key) => {
if (typeof obj[key] === 'object' && obj[key] !== null) {
// Recursively wrap sequences for nested objects
acc[key] = wrapSequences(obj[key]);
} else {
acc[key] = obj[key];
}
if (key.endsWith('Sequence')) {
acc[key] = OHIF.utils.addAccessors(acc[key]);
}
return acc;
},
Array.isArray(obj) ? [] : {}
);
}
const getMetaDataByURL = url => {
return _store.urls.find(metaData => metaData.url === url);
};
@@ -190,8 +207,14 @@ function createDicomJSONApi(dicomJsonConfig) {
const numberOfSeries = series.length;
series.forEach((series, index) => {
const instances = series.instances.map(instance => {
// for instance.metadata if the key ends with sequence then
// we need to add a proxy to the first item in the sequence
// so that we can access the value of the sequence
// by using sequenceName.value
const modifiedMetadata = wrapSequences(instance.metadata);
const obj = {
...instance.metadata,
...modifiedMetadata,
url: instance.url,
imageId: instance.url,
...series,
@@ -28,19 +28,38 @@ const EXPLICIT_VR_LITTLE_ENDIAN = '1.2.840.10008.1.2.1';
const metadataProvider = classes.MetadataProvider;
/**
* Creates a DICOM Web API based on the provided configuration.
*
* @param {string} name - Data source name
* @param {string} wadoUriRoot - Legacy? (potentially unused/replaced)
* @param {string} qidoRoot - Base URL to use for QIDO requests
* @param {string} wadoRoot - Base URL to use for WADO requests
* @param {boolean} qidoSupportsIncludeField - Whether QIDO supports the "Include" option to request additional fields in response
* @param {string} imageRengering - wadors | ? (unsure of where/how this is used)
* @param {string} thumbnailRendering - wadors | ? (unsure of where/how this is used)
* @param {bool} supportsReject - Whether the server supports reject calls (i.e. DCM4CHEE)
* @param {bool} lazyLoadStudy - "enableStudyLazyLoad"; Request series meta async instead of blocking
* @param {string|bool} singlepart - indicates of the retrieves can fetch singlepart. Options are bulkdata, video, image or boolean true
* @param {object} dicomWebConfig - Configuration for the DICOM Web API
* @param {string} dicomWebConfig.name - Data source name
* @param {string} dicomWebConfig.wadoUriRoot - Legacy? (potentially unused/replaced)
* @param {string} dicomWebConfig.qidoRoot - Base URL to use for QIDO requests
* @param {string} dicomWebConfig.wadoRoot - Base URL to use for WADO requests
* @param {string} dicomWebConfig.wadoUri - Base URL to use for WADO URI requests
* @param {boolean} dicomWebConfig.qidoSupportsIncludeField - Whether QIDO supports the "Include" option to request additional fields in response
* @param {string} dicomWebConfig.imageRendering - wadors | ? (unsure of where/how this is used)
* @param {string} dicomWebConfig.thumbnailRendering - wadors | ? (unsure of where/how this is used)
* @param {boolean} dicomWebConfig.supportsReject - Whether the server supports reject calls (i.e. DCM4CHEE)
* @param {boolean} dicomWebConfig.lazyLoadStudy - "enableStudyLazyLoad"; Request series meta async instead of blocking
* @param {string|boolean} dicomWebConfig.singlepart - indicates if the retrieves can fetch singlepart. Options are bulkdata, video, image, or boolean true
* @param {string} dicomWebConfig.requestTransferSyntaxUID - Transfer syntax to request from the server
* @param {object} dicomWebConfig.acceptHeader - Accept header to use for requests
* @param {boolean} dicomWebConfig.omitQuotationForMultipartRequest - Whether to omit quotation marks for multipart requests
* @param {boolean} dicomWebConfig.supportsFuzzyMatching - Whether the server supports fuzzy matching
* @param {boolean} dicomWebConfig.supportsWildcard - Whether the server supports wildcard matching
* @param {boolean} dicomWebConfig.supportsNativeDICOMModel - Whether the server supports the native DICOM model
* @param {boolean} dicomWebConfig.enableStudyLazyLoad - Whether to enable study lazy loading
* @param {boolean} dicomWebConfig.enableRequestTag - Whether to enable request tag
* @param {boolean} dicomWebConfig.enableStudyLazyLoad - Whether to enable study lazy loading
* @param {boolean} dicomWebConfig.bulkDataURI - Whether to enable bulkDataURI
* @param {function} dicomWebConfig.onConfiguration - Function that is called after the configuration is initialized
* @param {boolean} dicomWebConfig.staticWado - Whether to use the static WADO client
* @param {object} userAuthenticationService - User authentication service
* @param {object} userAuthenticationService.getAuthorizationHeader - Function that returns the authorization header
* @returns {object} - DICOM Web API object
*/
function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
function createDicomWebApi(dicomWebConfig, servicesManager) {
const { userAuthenticationService, customizationService } = servicesManager.services;
let dicomWebConfigCopy,
qidoConfig,
wadoConfig,
@@ -140,7 +159,13 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
instances: {
search: (studyInstanceUid, queryParameters) => {
qidoDicomWebClient.headers = getAuthrorizationHeader();
qidoSearch.call(undefined, qidoDicomWebClient, studyInstanceUid, null, queryParameters);
return qidoSearch.call(
undefined,
qidoDicomWebClient,
studyInstanceUid,
null,
queryParameters
);
},
},
},
@@ -184,6 +209,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
sortCriteria,
sortFunction,
madeInClient = false,
returnPromises = false,
} = {}) => {
if (!StudyInstanceUID) {
throw new Error('Unable to query for SeriesMetadata without StudyInstanceUID');
@@ -195,7 +221,8 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
filters,
sortCriteria,
sortFunction,
madeInClient
madeInClient,
returnPromises
);
}
@@ -211,7 +238,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
},
store: {
dicom: async (dataset, request) => {
dicom: async (dataset, request, dicomDict) => {
wadoDicomWebClient.headers = getAuthrorizationHeader();
if (dataset instanceof ArrayBuffer) {
const options = {
@@ -220,21 +247,26 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
};
await wadoDicomWebClient.storeInstances(options);
} else {
const meta = {
FileMetaInformationVersion: dataset._meta?.FileMetaInformationVersion?.Value,
MediaStorageSOPClassUID: dataset.SOPClassUID,
MediaStorageSOPInstanceUID: dataset.SOPInstanceUID,
TransferSyntaxUID: EXPLICIT_VR_LITTLE_ENDIAN,
ImplementationClassUID,
ImplementationVersionName,
};
let effectiveDicomDict = dicomDict;
const denaturalized = denaturalizeDataset(meta);
const dicomDict = new DicomDict(denaturalized);
if (!dicomDict) {
const meta = {
FileMetaInformationVersion: dataset._meta?.FileMetaInformationVersion?.Value,
MediaStorageSOPClassUID: dataset.SOPClassUID,
MediaStorageSOPInstanceUID: dataset.SOPInstanceUID,
TransferSyntaxUID: EXPLICIT_VR_LITTLE_ENDIAN,
ImplementationClassUID,
ImplementationVersionName,
};
dicomDict.dict = denaturalizeDataset(dataset);
const denaturalized = denaturalizeDataset(meta);
const defaultDicomDict = new DicomDict(denaturalized);
defaultDicomDict.dict = denaturalizeDataset(dataset);
const part10Buffer = dicomDict.write();
effectiveDicomDict = defaultDicomDict;
}
const part10Buffer = effectiveDicomDict.write();
const options = {
datasets: [part10Buffer],
@@ -262,7 +294,8 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
enableStudyLazyLoad,
filters,
sortCriteria,
sortFunction
sortFunction,
dicomWebConfig
);
// first naturalize the data
@@ -314,6 +347,8 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
Object.keys(instancesPerSeries).forEach(seriesInstanceUID =>
DicomMetadataStore.addInstances(instancesPerSeries[seriesInstanceUID], madeInClient)
);
return seriesSummaryMetadata;
},
_retrieveSeriesMetadataAsync: async (
@@ -321,7 +356,8 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
filters,
sortCriteria,
sortFunction,
madeInClient = false
madeInClient = false,
returnPromises = false
) => {
const enableStudyLazyLoad = true;
wadoDicomWebClient.headers = generateWadoHeader();
@@ -333,7 +369,8 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
enableStudyLazyLoad,
filters,
sortCriteria,
sortFunction
sortFunction,
dicomWebConfig
);
/**
@@ -357,11 +394,12 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
// in which case it isn't necessary to re-read this.
if (value && value.BulkDataURI && !value.Value) {
// Provide a method to fetch bulkdata
value.retrieveBulkData = () => {
value.retrieveBulkData = (options = {}) => {
// handle the scenarios where bulkDataURI is relative path
fixBulkDataURI(value, naturalized, dicomWebConfig);
const options = {
const { mediaType } = options;
const useOptions = {
// The bulkdata fetches work with either multipart or
// singlepart, so set multipart to false to let the server
// decide which type to respond with.
@@ -372,9 +410,13 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
// isn't well specified in the standard, but is needed in
// any implementation that stores static copies of the metadata
StudyInstanceUID: naturalized.StudyInstanceUID,
mediaTypes: mediaType
? [{ mediaType }, { mediaType: 'application/octet-stream' }]
: undefined,
...options,
};
// Todo: this needs to be from wado dicom web client
return qidoDicomWebClient.retrieveBulkData(options).then(val => {
return qidoDicomWebClient.retrieveBulkData(useOptions).then(val => {
// There are DICOM PDF cases where the first ArrayBuffer in the array is
// the bulk data and DICOM video cases where the second ArrayBuffer is
// the bulk data. Here we play it safe and do a find.
@@ -395,7 +437,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
const naturalizedInstances = instances.map(addRetrieveBulkData);
// Adding instanceMetadata to OHIF MetadataProvider
naturalizedInstances.forEach((instance, index) => {
naturalizedInstances.forEach(instance => {
instance.wadoRoot = dicomWebConfig.wadoRoot;
instance.wadoUri = dicomWebConfig.wadoUri;
@@ -422,7 +464,10 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
}
function setSuccessFlag() {
const study = DicomMetadataStore.getStudy(StudyInstanceUID, madeInClient);
const study = DicomMetadataStore.getStudy(StudyInstanceUID);
if (!study) {
return;
}
study.isLoaded = true;
}
@@ -434,13 +479,24 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
DicomMetadataStore.addSeriesMetadata(seriesSummaryMetadata, madeInClient);
const seriesDeliveredPromises = seriesPromises.map(promise =>
promise.then(instances => {
const seriesDeliveredPromises = seriesPromises.map(promise => {
if (!returnPromises) {
promise?.start();
}
return promise.then(instances => {
storeInstances(instances);
})
);
await Promise.all(seriesDeliveredPromises);
setSuccessFlag();
});
});
if (returnPromises) {
Promise.all(seriesDeliveredPromises).then(() => setSuccessFlag());
return seriesPromises;
} else {
await Promise.all(seriesDeliveredPromises);
setSuccessFlag();
}
return seriesSummaryMetadata;
},
deleteStudyMetadataPromise,
getImageIdsForDisplaySet(displaySet) {
@@ -470,7 +526,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
return imageIds;
},
getImageIdsForInstance({ instance, frame }) {
getImageIdsForInstance({ instance, frame = undefined }) {
const imageIds = getImageId({
instance,
frame,
@@ -1,3 +1,4 @@
import retrieveMetadataFiltered from './utils/retrieveMetadataFiltered.js';
import RetrieveMetadata from './wado/retrieveMetadata.js';
const moduleName = 'RetrieveStudyMetadata';
@@ -5,14 +6,17 @@ const moduleName = 'RetrieveStudyMetadata';
const StudyMetaDataPromises = new Map();
/**
* Retrieves study metadata
* Retrieves study metadata.
*
* @param {Object} server Object with server configuration parameters
* @param {Object} dicomWebClient The DICOMWebClient instance to be used for series load
* @param {string} StudyInstanceUID The UID of the Study to be retrieved
* @param {boolean} enabledStudyLazyLoad Whether the study metadata should be loaded asynchronously.
* @param {function} storeInstancesCallback A callback used to store the retrieved instance metadata.
* @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process
* @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against
* @param {boolean} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously.
* @param {Object} [filters] Object containing filters to be applied on retrieve metadata process
* @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against
* @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against
* @param {function} [sortCriteria] Sort criteria function
* @param {function} [sortFunction] Sort function
*
* @returns {Promise} that will be resolved with the metadata or rejected with the error
*/
export function retrieveStudyMetadata(
@@ -21,7 +25,8 @@ export function retrieveStudyMetadata(
enableStudyLazyLoad,
filters,
sortCriteria,
sortFunction
sortFunction,
dicomWebConfig = {}
) {
// @TODO: Whenever a study metadata request has failed, its related promise will be rejected once and for all
// and further requests for that metadata will always fail. On failure, we probably need to remove the
@@ -34,37 +39,51 @@ export function retrieveStudyMetadata(
throw new Error(`${moduleName}: Required 'StudyInstanceUID' parameter not provided.`);
}
const promiseId = `${dicomWebConfig.name}:${StudyInstanceUID}`;
// Already waiting on result? Return cached promise
if (StudyMetaDataPromises.has(StudyInstanceUID)) {
return StudyMetaDataPromises.get(StudyInstanceUID);
if (StudyMetaDataPromises.has(promiseId)) {
return StudyMetaDataPromises.get(promiseId);
}
// Create a promise to handle the data retrieval
const promise = new Promise((resolve, reject) => {
RetrieveMetadata(
let promise;
if (filters && filters.SeriesInstanceUIDs) {
promise = retrieveMetadataFiltered(
dicomWebClient,
StudyInstanceUID,
enableStudyLazyLoad,
filters,
sortCriteria,
sortFunction
).then(function (data) {
resolve(data);
}, reject);
});
);
} else {
// Create a promise to handle the data retrieval
promise = new Promise((resolve, reject) => {
RetrieveMetadata(
dicomWebClient,
StudyInstanceUID,
enableStudyLazyLoad,
filters,
sortCriteria,
sortFunction
).then(function (data) {
resolve(data);
}, reject);
});
}
// Store the promise in cache
StudyMetaDataPromises.set(StudyInstanceUID, promise);
StudyMetaDataPromises.set(promiseId, promise);
return promise;
}
/**
* Delete the cached study metadata retrieval promise to ensure that the browser will
* re-retrieve the study metadata when it is next requested
* re-retrieve the study metadata when it is next requested.
*
* @param {String} StudyInstanceUID The UID of the Study to be removed from cache
*
*/
export function deleteStudyMetadataPromise(StudyInstanceUID) {
if (StudyMetaDataPromises.has(StudyInstanceUID)) {
@@ -7,6 +7,7 @@ import { api } from 'dicomweb-client';
* performing searches doesn't work. This version fixes the query issue
* by manually implementing a query option.
*/
export default class StaticWadoClient extends api.DICOMwebClient {
static studyFilterKeys = {
studyinstanceuid: '0020000D',
@@ -0,0 +1,56 @@
import RetrieveMetadata from '../wado/retrieveMetadata';
/**
* Retrieve metadata filtered.
*
* @param {*} dicomWebClient The DICOMWebClient instance to be used for series load
* @param {*} StudyInstanceUID The UID of the Study to be retrieved
* @param {*} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously
* @param {object} filters Object containing filters to be applied on retrieve metadata process
* @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against
* @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against
* @param {function} [sortCriteria] Sort criteria function
* @param {function} [sortFunction] Sort function
*
* @returns
*/
function retrieveMetadataFiltered(
dicomWebClient,
StudyInstanceUID,
enableStudyLazyLoad,
filters,
sortCriteria,
sortFunction
) {
const { SeriesInstanceUIDs } = filters;
return new Promise((resolve, reject) => {
const promises = SeriesInstanceUIDs.map(uid => {
const seriesSpecificFilters = Object.assign({}, filters, {
seriesInstanceUID: uid,
});
return RetrieveMetadata(
dicomWebClient,
StudyInstanceUID,
enableStudyLazyLoad,
seriesSpecificFilters,
sortCriteria,
sortFunction
);
});
Promise.all(promises).then(results => {
const aggregatedResult = { preLoadData: [], promises: [] };
results.forEach(({ preLoadData, promises }) => {
aggregatedResult.preLoadData = aggregatedResult.preLoadData.concat(preLoadData);
aggregatedResult.promises = aggregatedResult.promises.concat(promises);
});
resolve(aggregatedResult);
}, reject);
});
}
export default retrieveMetadataFiltered;
@@ -5,15 +5,20 @@ import RetrieveMetadataLoaderAsync from './retrieveMetadataLoaderAsync';
* Retrieve Study metadata from a DICOM server. If the server is configured to use lazy load, only the first series
* will be loaded and the property "studyLoader" will be set to let consumer load remaining series as needed.
*
* @param {Object} dicomWebClient The dicomweb-client.
* @param {string} studyInstanceUid The Study Instance UID of the study which needs to be loaded
* @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process
* @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against
* @returns {Object} A study descriptor object
* @param {*} dicomWebClient The DICOMWebClient instance to be used for series load
* @param {*} StudyInstanceUID The UID of the Study to be retrieved
* @param {*} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously
* @param {object} filters Object containing filters to be applied on retrieve metadata process
* @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against
* @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against
* @param {function} [sortCriteria] Sort criteria function
* @param {function} [sortFunction] Sort function
*
* @returns {Promise} A promises that resolves the study descriptor object
*/
async function RetrieveMetadata(
dicomWebClient,
studyInstanceUid,
StudyInstanceUID,
enableStudyLazyLoad,
filters = {},
sortCriteria,
@@ -24,7 +29,7 @@ async function RetrieveMetadata(
const retrieveMetadataLoader = new RetrieveMetadataLoader(
dicomWebClient,
studyInstanceUid,
StudyInstanceUID,
filters,
sortCriteria,
sortFunction
@@ -11,10 +11,17 @@ export default class RetrieveMetadataLoader {
* @param {Object} client The dicomweb-client.
* @param {Array} studyInstanceUID Study instance ui to be retrieved
* @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process
* @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against
* @param {Function} [sortSeries] - Custom sort function for series
* @param {string} [filters.seriesInstanceUID] - series instance uid to filter results against
* @param {Object} [sortCriteria] - Custom sort criteria used for series
* @param {Function} [sortFunction] - Custom sort function for series
*/
constructor(client, studyInstanceUID, filters = {}, sortCriteria, sortFunction) {
constructor(
client,
studyInstanceUID,
filters = {},
sortCriteria = undefined,
sortFunction = undefined
) {
this.client = client;
this.studyInstanceUID = studyInstanceUID;
this.filters = filters;
@@ -26,7 +33,6 @@ export default class RetrieveMetadataLoader {
const preLoadData = await this.preLoad();
const loadData = await this.load(preLoadData);
const postLoadData = await this.posLoad(loadData);
return postLoadData;
}
@@ -37,13 +43,9 @@ export default class RetrieveMetadataLoader {
async runLoaders(loaders) {
let result;
for (const loader of loaders) {
try {
result = await loader();
if (result && result.length) {
break; // closes iterator in case data is retrieved successfully
}
} catch (e) {
throw e;
result = await loader();
if (result && result.length) {
break; // closes iterator in case data is retrieved successfully
}
}
@@ -1,12 +1,65 @@
import dcmjs from 'dcmjs';
import { sortStudySeries, sortingCriteria } from '@ohif/core/src/utils/sortStudy';
import { sortStudySeries } from '@ohif/core/src/utils/sortStudy';
import RetrieveMetadataLoader from './retrieveMetadataLoader';
// Series Date, Series Time, Series Description and Series Number to be included
// in the series metadata query result
const includeField = ['00080021', '00080031', '0008103E', '00200011'].join(',');
export class DeferredPromise {
metadata = undefined;
processFunction = undefined;
internalPromise = undefined;
thenFunction = undefined;
rejectFunction = undefined;
setMetadata(metadata) {
this.metadata = metadata;
}
setProcessFunction(func) {
this.processFunction = func;
}
getPromise() {
return this.start();
}
start() {
if (this.internalPromise) {
return this.internalPromise;
}
this.internalPromise = this.processFunction();
// in case then and reject functions called before start
if (this.thenFunction) {
this.then(this.thenFunction);
this.thenFunction = undefined;
}
if (this.rejectFunction) {
this.reject(this.rejectFunction);
this.rejectFunction = undefined;
}
return this.internalPromise;
}
then(func) {
if (this.internalPromise) {
return this.internalPromise.then(func);
} else {
this.thenFunction = func;
}
}
reject(func) {
if (this.internalPromise) {
return this.internalPromise.reject(func);
} else {
this.rejectFunction = func;
}
}
}
/**
* Creates an immutable series loader object which loads each series sequentially using the iterator interface
* Creates an immutable series loader object which loads each series sequentially using the iterator interface.
*
* @param {DICOMWebClient} dicomWebClient The DICOMWebClient instance to be used for series load
* @param {string} studyInstanceUID The Study Instance UID from which series will be loaded
* @param {Array} seriesInstanceUIDList A list of Series Instance UIDs
*
* @returns {Object} Returns an object which supports loading of instances from each of given Series Instance UID
*/
function makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDList) {
@@ -14,12 +67,17 @@ function makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDList)
hasNext() {
return seriesInstanceUIDList.length > 0;
},
async next() {
const seriesInstanceUID = seriesInstanceUIDList.shift();
return client.retrieveSeriesMetadata({
studyInstanceUID,
seriesInstanceUID,
next() {
const { seriesInstanceUID, metadata } = seriesInstanceUIDList.shift();
const promise = new DeferredPromise();
promise.setMetadata(metadata);
promise.setProcessFunction(() => {
return client.retrieveSeriesMetadata({
studyInstanceUID,
seriesInstanceUID,
});
});
return promise;
},
});
}
@@ -38,15 +96,22 @@ export default class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader
const preLoaders = [];
const { studyInstanceUID, filters: { seriesInstanceUID } = {}, client } = this;
// asking to include Series Date, Series Time, Series Description
// and Series Number in the series metadata returned to better sort series
// in preLoad function
let options = {
studyInstanceUID,
queryParams: {
includefield: includeField,
},
};
if (seriesInstanceUID) {
const options = {
studyInstanceUID,
queryParams: { SeriesInstanceUID: seriesInstanceUID },
};
options.queryParams.SeriesInstanceUID = seriesInstanceUID;
preLoaders.push(client.searchForSeries.bind(client, options));
}
// Fallback preloader
preLoaders.push(client.searchForSeries.bind(client, { studyInstanceUID }));
preLoaders.push(client.searchForSeries.bind(client, options));
yield* preLoaders;
}
@@ -60,24 +125,23 @@ export default class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader
const { naturalizeDataset } = dcmjs.data.DicomMetaDictionary;
const naturalized = result.map(naturalizeDataset);
return sortStudySeries(
naturalized,
sortCriteria || sortingCriteria.seriesSortCriteria.seriesInfoSortingCriteria,
sortFunction
);
return sortStudySeries(naturalized, sortCriteria, sortFunction);
}
async load(preLoadData) {
const { client, studyInstanceUID } = this;
const seriesInstanceUIDs = preLoadData.map(s => s.SeriesInstanceUID);
const seriesInstanceUIDs = preLoadData.map(seriesMetadata => {
return { seriesInstanceUID: seriesMetadata.SeriesInstanceUID, metadata: seriesMetadata };
});
const seriesAsyncLoader = makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDs);
const promises = [];
while (seriesAsyncLoader.hasNext()) {
promises.push(seriesAsyncLoader.next());
const promise = seriesAsyncLoader.next();
promises.push(promise);
}
return {
@@ -9,7 +9,7 @@ import { createDicomWebApi } from '../DicomWebDataSource/index';
* dicomWeb configuration array
*
*/
function createDicomWebProxyApi(dicomWebProxyConfig, UserAuthenticationService) {
function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) {
const { name } = dicomWebProxyConfig;
let dicomWebDelegate = undefined;
@@ -28,7 +28,7 @@ function createDicomWebProxyApi(dicomWebProxyConfig, UserAuthenticationService)
dicomWebDelegate = createDicomWebApi(
data.servers.dicomWeb[0].configuration,
UserAuthenticationService
servicesManager
);
dicomWebDelegate.initialize({ params, query });
}
@@ -0,0 +1,203 @@
import { DicomMetadataStore, IWebApiDataSource } from '@ohif/core';
import {
mergeMap,
callForAllDataSourcesAsync,
callForAllDataSources,
callForDefaultDataSource,
callByRetrieveAETitle,
createMergeDataSourceApi,
} from './index';
jest.mock('@ohif/core');
describe('MergeDataSource', () => {
let path,
sourceName,
mergeConfig,
extensionManager,
series1,
series2,
series3,
series4,
mergeKey,
tagFunc,
dataSourceAndSeriesMap,
dataSourceAndUIDsMap,
dataSourceAndDSMap,
pathSync;
beforeAll(() => {
path = 'query.series.search';
pathSync = 'getImageIdsForInstance';
tagFunc = jest.fn((data, sourceName) =>
data.map(item => ({ ...item, RetrieveAETitle: sourceName }))
);
sourceName = 'dicomweb1';
mergeKey = 'seriesInstanceUid';
series1 = { [mergeKey]: '123' };
series2 = { [mergeKey]: '234' };
series3 = { [mergeKey]: '345' };
series4 = { [mergeKey]: '456' };
mergeConfig = {
seriesMerge: {
dataSourceNames: ['dicomweb1', 'dicomweb2'],
defaultDataSourceName: 'dicomweb1',
},
};
dataSourceAndSeriesMap = {
dataSource1: series1,
dataSource2: series2,
dataSource3: series3,
};
dataSourceAndUIDsMap = {
dataSource1: ['123'],
dataSource2: ['234'],
dataSource3: ['345'],
};
dataSourceAndDSMap = {
dataSource1: {
displaySet: {
StudyInstanceUID: '123',
SeriesInstanceUID: '123',
},
},
dataSource2: {
displaySet: {
StudyInstanceUID: '234',
SeriesInstanceUID: '234',
},
},
dataSource3: {
displaySet: {
StudyInstanceUID: '345',
SeriesInstanceUID: '345',
},
},
};
extensionManager = {
dataSourceDefs: {
dataSource1: {
sourceName: 'dataSource1',
configuration: {},
},
dataSource2: {
sourceName: 'dataSource2',
configuration: {},
},
dataSource3: {
sourceName: 'dataSource3',
configuration: {},
},
},
getDataSources: jest.fn(dataSourceName => [
{
[path]: jest.fn().mockResolvedValue([dataSourceAndSeriesMap[dataSourceName]]),
},
]),
};
});
afterEach(() => {
jest.clearAllMocks();
});
describe('callForAllDataSourcesAsync', () => {
it('should call the correct functions and return the merged data', async () => {
/** Arrange */
extensionManager.getDataSources = jest.fn(dataSourceName => [
{
[path]: jest.fn().mockResolvedValue([dataSourceAndSeriesMap[dataSourceName]]),
},
]);
/** Act */
const data = await callForAllDataSourcesAsync({
mergeMap,
path,
args: [],
extensionManager,
dataSourceNames: ['dataSource1', 'dataSource2'],
});
/** Assert */
expect(extensionManager.getDataSources).toHaveBeenCalledTimes(2);
expect(extensionManager.getDataSources).toHaveBeenCalledWith('dataSource1');
expect(extensionManager.getDataSources).toHaveBeenCalledWith('dataSource2');
expect(data).toEqual([series1, series2]);
});
});
describe('callForAllDataSources', () => {
it('should call the correct functions and return the merged data', () => {
/** Arrange */
extensionManager.getDataSources = jest.fn(dataSourceName => [
{
[pathSync]: () => dataSourceAndUIDsMap[dataSourceName],
},
]);
/** Act */
const data = callForAllDataSources({
path: pathSync,
args: [],
extensionManager,
dataSourceNames: ['dataSource2', 'dataSource3'],
});
/** Assert */
expect(extensionManager.getDataSources).toHaveBeenCalledTimes(2);
expect(extensionManager.getDataSources).toHaveBeenCalledWith('dataSource2');
expect(extensionManager.getDataSources).toHaveBeenCalledWith('dataSource3');
expect(data).toEqual(['234', '345']);
});
});
describe('callForDefaultDataSource', () => {
it('should call the correct function and return the data', () => {
/** Arrange */
extensionManager.getDataSources = jest.fn(dataSourceName => [
{
[pathSync]: () => dataSourceAndUIDsMap[dataSourceName],
},
]);
/** Act */
const data = callForDefaultDataSource({
path: pathSync,
args: [],
extensionManager,
defaultDataSourceName: 'dataSource2',
});
/** Assert */
expect(extensionManager.getDataSources).toHaveBeenCalledTimes(1);
expect(extensionManager.getDataSources).toHaveBeenCalledWith('dataSource2');
expect(data).toEqual(['234']);
});
});
describe('callByRetrieveAETitle', () => {
it('should call the correct function and return the data', () => {
/** Arrange */
DicomMetadataStore.getSeries.mockImplementationOnce(() => [series2]);
extensionManager.getDataSources = jest.fn(dataSourceName => [
{
[pathSync]: () => dataSourceAndUIDsMap[dataSourceName],
},
]);
/** Act */
const data = callByRetrieveAETitle({
path: pathSync,
args: [dataSourceAndDSMap['dataSource2']],
extensionManager,
defaultDataSourceName: 'dataSource2',
});
/** Assert */
expect(extensionManager.getDataSources).toHaveBeenCalledTimes(1);
expect(extensionManager.getDataSources).toHaveBeenCalledWith('dataSource2');
expect(data).toEqual(['234']);
});
});
});
@@ -0,0 +1,293 @@
import { DicomMetadataStore, IWebApiDataSource } from '@ohif/core';
import { get, uniqBy } from 'lodash';
import {
MergeConfig,
CallForAllDataSourcesAsyncOptions,
CallForAllDataSourcesOptions,
CallForDefaultDataSourceOptions,
CallByRetrieveAETitleOptions,
MergeMap,
} from './types';
export const mergeMap: MergeMap = {
'query.studies.search': {
mergeKey: 'studyInstanceUid',
tagFunc: x => x,
},
'query.series.search': {
mergeKey: 'seriesInstanceUid',
tagFunc: (series, sourceName) => {
series.forEach(series => {
series.RetrieveAETitle = sourceName;
DicomMetadataStore.updateSeriesMetadata(series);
});
return series;
},
},
};
/**
* Calls all data sources asynchronously and merges the results.
* @param {CallForAllDataSourcesAsyncOptions} options - The options for calling all data sources.
* @param {string} options.path - The path to the function to be called on each data source.
* @param {unknown[]} options.args - The arguments to be passed to the function.
* @param {ExtensionManager} options.extensionManager - The extension manager.
* @param {string[]} options.dataSourceNames - The names of the data sources to be called.
* @param {string} options.defaultDataSourceName - The name of the default data source.
* @returns {Promise<unknown[]>} - A promise that resolves to the merged data from all data sources.
*/
export const callForAllDataSourcesAsync = async ({
mergeMap,
path,
args,
extensionManager,
dataSourceNames,
defaultDataSourceName,
}: CallForAllDataSourcesAsyncOptions) => {
const { mergeKey, tagFunc } = mergeMap[path] || { tagFunc: x => x };
/** Sort by default data source */
const defs = Object.values(extensionManager.dataSourceDefs);
const defaultDataSourceDef = defs.find(def => def.sourceName === defaultDataSourceName);
const dataSourceDefs = defs.filter(def => def.sourceName !== defaultDataSourceName);
if (defaultDataSourceDef) {
dataSourceDefs.unshift(defaultDataSourceDef);
}
const promises = [];
const sourceNames = [];
for (const dataSourceDef of dataSourceDefs) {
const { configuration, sourceName } = dataSourceDef;
if (!!configuration && dataSourceNames.includes(sourceName)) {
const [dataSource] = extensionManager.getDataSources(sourceName);
const func = get(dataSource, path);
const promise = func.apply(dataSource, args);
promises.push(promise);
sourceNames.push(sourceName);
}
}
const data = await Promise.allSettled(promises);
const mergedData = data.map((data, i) => tagFunc(data.value, sourceNames[i]));
let results = [];
if (mergeKey) {
results = uniqBy(mergedData.flat(), obj => get(obj, mergeKey));
} else {
results = mergedData.flat();
}
return results;
};
/**
* Calls all data sources that match the provided names and merges their data.
* @param options - The options for calling all data sources.
* @param options.path - The path to the function to be called on each data source.
* @param options.args - The arguments to be passed to the function.
* @param options.extensionManager - The extension manager instance.
* @param options.dataSourceNames - The names of the data sources to be called.
* @param options.defaultDataSourceName - The name of the default data source.
* @returns The merged data from all the matching data sources.
*/
export const callForAllDataSources = ({
path,
args,
extensionManager,
dataSourceNames,
defaultDataSourceName,
}: CallForAllDataSourcesOptions) => {
/** Sort by default data source */
const defs = Object.values(extensionManager.dataSourceDefs);
const defaultDataSourceDef = defs.find(def => def.sourceName === defaultDataSourceName);
const dataSourceDefs = defs.filter(def => def.sourceName !== defaultDataSourceName);
if (defaultDataSourceDef) {
dataSourceDefs.unshift(defaultDataSourceDef);
}
const mergedData = [];
for (const dataSourceDef of dataSourceDefs) {
const { configuration, sourceName } = dataSourceDef;
if (!!configuration && dataSourceNames.includes(sourceName)) {
const [dataSource] = extensionManager.getDataSources(sourceName);
const func = get(dataSource, path);
const data = func.apply(dataSource, args);
mergedData.push(data);
}
}
return mergedData.flat();
};
/**
* Calls the default data source function specified by the given path with the provided arguments.
* @param {CallForDefaultDataSourceOptions} options - The options for calling the default data source.
* @param {string} options.path - The path to the function within the default data source.
* @param {unknown[]} options.args - The arguments to pass to the function.
* @param {string} options.defaultDataSourceName - The name of the default data source.
* @param {ExtensionManager} options.extensionManager - The extension manager instance.
* @returns {unknown} - The result of calling the default data source function.
*/
export const callForDefaultDataSource = ({
path,
args,
defaultDataSourceName,
extensionManager,
}: CallForDefaultDataSourceOptions) => {
const [dataSource] = extensionManager.getDataSources(defaultDataSourceName);
const func = get(dataSource, path);
return func.apply(dataSource, args);
};
/**
* Calls the data source specified by the RetrieveAETitle of the given display set.
* @typedef {Object} CallByRetrieveAETitleOptions
* @property {string} path - The path of the method to call on the data source.
* @property {any[]} args - The arguments to pass to the method.
* @property {string} defaultDataSourceName - The name of the default data source.
* @property {ExtensionManager} extensionManager - The extension manager.
*/
export const callByRetrieveAETitle = ({
path,
args,
defaultDataSourceName,
extensionManager,
}: CallByRetrieveAETitleOptions) => {
const [displaySet] = args;
const seriesMetadata = DicomMetadataStore.getSeries(
displaySet.StudyInstanceUID,
displaySet.SeriesInstanceUID
);
const [dataSource] = extensionManager.getDataSources(
seriesMetadata.RetrieveAETitle || defaultDataSourceName
);
return dataSource[path](...args);
};
function createMergeDataSourceApi(
mergeConfig: MergeConfig,
servicesManager: unknown,
extensionManager
) {
const { seriesMerge } = mergeConfig;
const { dataSourceNames, defaultDataSourceName } = seriesMerge;
const implementation = {
initialize: (...args: unknown[]) =>
callForAllDataSources({
path: 'initialize',
args,
extensionManager,
dataSourceNames,
defaultDataSourceName,
}),
query: {
studies: {
search: (...args: unknown[]) =>
callForAllDataSourcesAsync({
mergeMap,
path: 'query.studies.search',
args,
extensionManager,
dataSourceNames,
defaultDataSourceName,
}),
},
series: {
search: (...args: unknown[]) =>
callForAllDataSourcesAsync({
mergeMap,
path: 'query.series.search',
args,
extensionManager,
dataSourceNames,
defaultDataSourceName,
}),
},
instances: {
search: (...args: unknown[]) =>
callForAllDataSourcesAsync({
mergeMap,
path: 'query.instances.search',
args,
extensionManager,
dataSourceNames,
defaultDataSourceName,
}),
},
},
retrieve: {
bulkDataURI: (...args: unknown[]) =>
callForAllDataSourcesAsync({
mergeMap,
path: 'retrieve.bulkDataURI',
args,
extensionManager,
dataSourceNames,
defaultDataSourceName,
}),
directURL: (...args: unknown[]) =>
callForDefaultDataSource({
path: 'retrieve.directURL',
args,
defaultDataSourceName,
extensionManager,
}),
series: {
metadata: (...args: unknown[]) =>
callForAllDataSourcesAsync({
mergeMap,
path: 'retrieve.series.metadata',
args,
extensionManager,
dataSourceNames,
defaultDataSourceName,
}),
},
},
store: {
dicom: (...args: unknown[]) =>
callForDefaultDataSource({
path: 'store.dicom',
args,
defaultDataSourceName,
extensionManager,
}),
},
deleteStudyMetadataPromise: (...args: unknown[]) =>
callForAllDataSources({
path: 'deleteStudyMetadataPromise',
args,
extensionManager,
dataSourceNames,
defaultDataSourceName,
}),
getImageIdsForDisplaySet: (...args: unknown[]) =>
callByRetrieveAETitle({
path: 'getImageIdsForDisplaySet',
args,
defaultDataSourceName,
extensionManager,
}),
getImageIdsForInstance: (...args: unknown[]) =>
callByRetrieveAETitle({
path: 'getImageIdsForDisplaySet',
args,
defaultDataSourceName,
extensionManager,
}),
getStudyInstanceUIDs: (...args: unknown[]) =>
callForAllDataSources({
path: 'getStudyInstanceUIDs',
args,
extensionManager,
dataSourceNames,
defaultDataSourceName,
}),
};
return IWebApiDataSource.create(implementation);
}
export { createMergeDataSourceApi };
@@ -0,0 +1,46 @@
import { ExtensionManager } from '@ohif/core';
export type MergeMap = {
[key: string]: {
mergeKey: string;
tagFunc: (data: unknown[], sourceName: string) => unknown[];
};
};
export type CallForAllDataSourcesAsyncOptions = {
mergeMap: object;
path: string;
args: unknown[];
dataSourceNames: string[];
extensionManager: ExtensionManager;
defaultDataSourceName: string;
};
export type CallForAllDataSourcesOptions = {
path: string;
args: unknown[];
dataSourceNames: string[];
extensionManager: ExtensionManager;
defaultDataSourceName: string;
};
export type CallForDefaultDataSourceOptions = {
path: string;
args: unknown[];
defaultDataSourceName: string;
extensionManager: ExtensionManager;
};
export type CallByRetrieveAETitleOptions = {
path: string;
args: unknown[];
defaultDataSourceName: string;
extensionManager: ExtensionManager;
};
export type MergeConfig = {
seriesMerge: {
dataSourceNames: string[];
defaultDataSourceName: string;
};
};
@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { utils, ServicesManager } from '@ohif/core';
import { MeasurementTable, Dialog, Input, useViewportGrid, ButtonEnums } from '@ohif/ui';
import ActionButtons from './ActionButtons';
@@ -18,6 +19,8 @@ export default function PanelMeasurementTable({
commandsManager,
extensionManager,
}): React.FunctionComponent {
const { t } = useTranslation('MeasurementTable');
const [viewportGrid, viewportGridService] = useViewportGrid();
const { activeViewportId, viewports } = viewportGrid;
const { measurementService, uiDialogService, uiNotificationService, displaySetService } = (
@@ -209,7 +212,7 @@ export default function PanelMeasurementTable({
data-cy={'measurements-panel'}
>
<MeasurementTable
title="Measurements"
title={t("Measurements")}
servicesManager={servicesManager}
data={displayMeasurements}
onClick={jumpToImage}
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
//
import PanelStudyBrowser from './PanelStudyBrowser';
@@ -18,7 +18,10 @@ function WrappedPanelStudyBrowser({ commandsManager, extensionManager, servicesM
// already determined our datasource
const dataSource = extensionManager.getDataSources()[0];
const _getStudiesForPatientByMRN = getStudiesForPatientByMRN.bind(null, dataSource);
const _getImageSrcFromImageId = _createGetImageSrcFromImageIdFn(extensionManager);
const _getImageSrcFromImageId = useCallback(
_createGetImageSrcFromImageIdFn(extensionManager),
[]
);
const _requestDisplaySetCreationForStudy = requestDisplaySetCreationForStudy.bind(
null,
dataSource
@@ -1,5 +1,5 @@
/* eslint-disable react/display-name */
import React from 'react';
import { ButtonEnums, Dialog, Input, Select } from '@ohif/ui';
export const CREATE_REPORT_DIALOG_RESPONSE = {
@@ -7,7 +7,7 @@ export const CREATE_REPORT_DIALOG_RESPONSE = {
CREATE_REPORT: 1,
};
export default function createReportDialogPrompt(uiDialogService, { extensionManager }) {
export default function CreateReportDialogPrompt(uiDialogService, { extensionManager }) {
return new Promise(function (resolve, reject) {
let dialogId = undefined;
@@ -97,33 +97,38 @@ export default function createReportDialogPrompt(uiDialogService, { extensionMan
};
return (
<>
{dataSourcesOpts.length > 1 && (
<Select
closeMenuOnSelect={true}
className="border-primary-main mr-2 bg-black"
options={dataSourcesOpts}
placeholder={
dataSourcesOpts.find(option => option.value === value.dataSourceName)
.placeHolder
}
value={value.dataSourceName}
onChange={evt => {
setValue(v => ({ ...v, dataSourceName: evt.value }));
}}
isClearable={false}
/>
{dataSourcesOpts.length > 1 && window.config?.allowMultiSelectExport && (
<div>
<label className="text-[14px] leading-[1.2] text-white">Data Source</label>
<Select
closeMenuOnSelect={true}
className="border-primary-main mt-2 bg-black"
options={dataSourcesOpts}
placeholder={
dataSourcesOpts.find(option => option.value === value.dataSourceName)
.placeHolder
}
value={value.dataSourceName}
onChange={evt => {
setValue(v => ({ ...v, dataSourceName: evt.value }));
}}
isClearable={false}
/>
</div>
)}
<Input
autoFocus
label="Enter the report name"
labelClassName="text-white text-[14px] leading-[1.2]"
className="border-primary-main bg-black"
type="text"
value={value.label}
onChange={onChangeHandler}
onKeyPress={onKeyPressHandler}
required
/>
<div className="mt-3">
<Input
autoFocus
label="Enter the report name"
labelClassName="text-white text-[14px] leading-[1.2]"
className="border-primary-main bg-black"
type="text"
value={value.label}
onChange={onChangeHandler}
onKeyPress={onKeyPressHandler}
required
/>
</div>
</>
);
},
+20 -5
View File
@@ -1,19 +1,34 @@
import React, { useEffect, useState, useCallback } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import classnames from 'classnames';
import { useViewportGrid } from '@ohif/ui';
export default function Toolbar({ servicesManager }) {
export default function Toolbar({
servicesManager,
}: Types.Extensions.ExtensionParams): React.ReactElement {
const { toolbarService } = servicesManager.services;
const [viewportGrid, viewportGridService] = useViewportGrid();
const [toolbarButtons, setToolbarButtons] = useState([]);
useEffect(() => {
const { unsubscribe } = toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_MODIFIED, () =>
setToolbarButtons(toolbarService.getButtonSection('primary'))
const updateToolbar = () => {
const toolGroupId =
viewportGridService.getActiveViewportOptionByKey('toolGroupId') ?? 'default';
setToolbarButtons(toolbarService.getButtonSection(toolGroupId));
};
const { unsubscribe } = toolbarService.subscribe(
toolbarService.EVENTS.TOOL_BAR_MODIFIED,
updateToolbar
);
updateToolbar();
return () => {
unsubscribe();
};
}, [toolbarService]);
}, [toolbarService, viewportGrid]);
const onInteraction = useCallback(
args => toolbarService.recordInteraction(args),
@@ -65,7 +65,7 @@ ToolbarButtonWithServices.propTypes = {
state: PropTypes.shape({
primaryToolId: PropTypes.string,
toggles: PropTypes.objectOf(PropTypes.bool),
groups: PropTypes.objectOf(PropTypes.object),
groups: PropTypes.objectOf(PropTypes.any),
}).isRequired,
}).isRequired,
}).isRequired,
@@ -53,7 +53,7 @@ function ViewerHeader({ hotkeysManager, extensionManager, servicesManager }) {
onClick: () =>
show({
content: AboutModal,
title: 'About OHIF Viewer',
title: t('AboutModal:About OHIF Viewer'),
contentProps: { versionNumber, commitHash },
}),
},
@@ -62,7 +62,7 @@ function ViewerHeader({ hotkeysManager, extensionManager, servicesManager }) {
icon: 'settings',
onClick: () =>
show({
title: t('UserPreferencesModal:User Preferences'),
title: t('UserPreferencesModal:User preferences'),
content: UserPreferences,
contentProps: {
hotkeyDefaults: hotkeysManager.getValidHotkeyDefinitions(hotkeyDefaults),
@@ -1,7 +1,12 @@
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { SidePanel, ErrorBoundary, LoadingIndicatorProgress } from '@ohif/ui';
import {
SidePanel,
ErrorBoundary,
LoadingIndicatorProgress,
InvestigationalUseDialog,
} from '@ohif/ui';
import { ServicesManager, HangingProtocolService, CommandsManager } from '@ohif/core';
import { useAppConfig } from '@state';
import ViewerHeader from './ViewerHeader';
@@ -152,6 +157,8 @@ function ViewerLayout({
) : null}
</React.Fragment>
</div>
<InvestigationalUseDialog dialogConfiguration={appConfig?.investigationalUseDialog} />
</div>
);
}
+4 -12
View File
@@ -121,7 +121,10 @@ const commandsModule = ({
if (!button.id) {
return;
}
const { commands, items } = button.props || button;
const { commands, items, primary } = button.props || button;
if (primary) {
enableListener(primary);
}
if (items) {
items.forEach(enableListener);
}
@@ -241,7 +244,6 @@ const commandsModule = ({
];
stateSyncService.store(stateSyncReduce);
// This is a default action applied
const { protocol } = hangingProtocolService.getActiveProtocol();
actions.toggleHpTools();
// try to use the same tool in the new hanging protocol stage
@@ -264,16 +266,6 @@ const commandsModule = ({
});
}
}
// Send the notification about updating the state
if (protocolId !== hpInfo.protocolId) {
// The old protocol callbacks are used for turning off things
// like crosshairs when moving to the new HP
commandsManager.run(oldProtocol.callbacks?.onProtocolExit);
// The new protocol callback is used for things like
// activating modes etc.
}
commandsManager.run(protocol.callbacks?.onProtocolEnter);
return true;
} catch (e) {
console.error(e);
@@ -6,6 +6,7 @@ import { createDicomWebApi } from './DicomWebDataSource/index.js';
import { createDicomJSONApi } from './DicomJSONDataSource/index.js';
import { createDicomLocalApi } from './DicomLocalDataSource/index.js';
import { createDicomWebProxyApi } from './DicomWebProxyDataSource/index.js';
import { createMergeDataSourceApi } from './MergeDataSource/index';
/**
*
@@ -32,6 +33,11 @@ function getDataSourcesModule() {
type: 'localApi',
createDataSource: createDicomLocalApi,
},
{
name: 'merge',
type: 'mergeApi',
createDataSource: createMergeDataSourceApi,
},
];
}
@@ -13,12 +13,12 @@ export default function getDisplaySetMessages(
isReconstructable: boolean
): DisplaySetMessageList {
const messages = new DisplaySetMessageList();
const firstInstance = instances[0];
if (!instances.length || firstInstance) {
if (!instances.length) {
messages.addMessage(DisplaySetMessage.CODES.NO_VALID_INSTANCES);
return;
}
const firstInstance = instances[0];
const { Modality, ImageType, NumberOfFrames } = firstInstance;
// Due to current requirements, LOCALIZER series doesn't have any messages
if (ImageType?.includes('LOCALIZER')) {
@@ -14,6 +14,7 @@ const defaultProtocol = {
editableBy: {},
protocolMatchingRules: [],
toolGroupIds: ['default'],
hpInitiationCriteria: { minSeriesLoaded: 1 },
// -1 would be used to indicate active only, whereas other values are
// the number of required priors referenced - so 0 means active with
// 0 or more priors.
+4 -3
View File
@@ -1,5 +1,6 @@
import React from 'react';
import { WrappedPanelStudyBrowser, PanelMeasurementTable } from './Panels';
import i18n from 'i18next';
// TODO:
// - No loading UI exists yet
@@ -22,7 +23,7 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager })
name: 'seriesList',
iconName: 'tab-studies',
iconLabel: 'Studies',
label: 'Studies',
label: i18n.t('SidePanel:Studies'),
component: WrappedPanelStudyBrowser.bind(null, {
commandsManager,
extensionManager,
@@ -33,8 +34,8 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager })
name: 'measure',
iconName: 'tab-linear',
iconLabel: 'Measure',
label: 'Measurements',
secondaryLabel: 'Measurements',
label: i18n.t('SidePanel:Measurements'),
secondaryLabel: i18n.t('SidePanel:Measurements'),
component: wrappedMeasurementPanel,
},
];
+27 -22
View File
@@ -51,36 +51,41 @@ export default function init({ servicesManager, configuration = {} }): void {
const handlePETImageMetadata = ({ SeriesInstanceUID, StudyInstanceUID }) => {
const { instances } = DicomMetadataStore.getSeries(StudyInstanceUID, SeriesInstanceUID);
const modality = instances[0].Modality;
if (modality !== 'PT') {
if (!instances?.length) {
return;
}
const modality = instances[0].Modality;
if (!modality || modality !== 'PT') {
return;
}
const imageIds = instances.map(instance => instance.imageId);
const instanceMetadataArray = [];
imageIds.forEach(imageId => {
const instanceMetadata = getPTImageIdInstanceMetadata(imageId);
if (instanceMetadata) {
instanceMetadataArray.push(instanceMetadata);
}
});
if (!instanceMetadataArray.length) {
return;
}
// try except block to prevent errors when the metadata is not correct
let suvScalingFactors;
try {
suvScalingFactors = calculateSUVScalingFactors(instanceMetadataArray);
imageIds.forEach(imageId => {
const instanceMetadata = getPTImageIdInstanceMetadata(imageId);
if (instanceMetadata) {
instanceMetadataArray.push(instanceMetadata);
}
});
if (!instanceMetadataArray.length) {
return;
}
const suvScalingFactors = calculateSUVScalingFactors(instanceMetadataArray);
instanceMetadataArray.forEach((instanceMetadata, index) => {
metadataProvider.addCustomMetadata(
imageIds[index],
'scalingModule',
suvScalingFactors[index]
);
});
} catch (error) {
console.log(error);
}
if (!suvScalingFactors) {
return;
}
instanceMetadataArray.forEach((instanceMetadata, index) => {
metadataProvider.addCustomMetadata(imageIds[index], 'scalingModule', suvScalingFactors[index]);
});
};
+5 -1
View File
@@ -37,7 +37,11 @@ const getDirectURL = (config, params) => {
}
if (!singlepart || (singlepart !== true && singlepart.indexOf(fetchPart) === -1)) {
if (value.retrieveBulkData) {
return value.retrieveBulkData().then(arr => {
// Try the specified retrieve type.
const options = {
mediaType: defaultType,
};
return value.retrieveBulkData(options).then(arr => {
value.DirectRetrieveURL = URL.createObjectURL(new Blob([arr], { type: defaultType }));
return value.DirectRetrieveURL;
});
Loaded 100 of 373 files, more files were not shown because too many files have changed in this diff. Show more