Compare commits

..
Author SHA1 Message Date
ohif-bot 7a69c46dc0 chore(release): publish [skip ci]
- @ohif/extension-dicom-tag-browser@0.2.26
 - @ohif/extension-vtk@1.12.42
 - @ohif/ui@1.10.11
 - @ohif/viewer@4.12.51
2023-03-19 22:18:48 +00:00
Igor Octaviano 70367bad0b Merge pull request #3257 from OHIF/dependabot/npm_and_yarn/moment-2.29.4
chore(deps): bump moment from 2.24.0 to 2.29.4
2023-03-19 19:16:56 -03:00
Igor Octaviano cd347812bf Merge branch 'master' into dependabot/npm_and_yarn/moment-2.29.4 2023-03-19 19:01:02 -03:00
Igor Octaviano befd7d1b08 Merge pull request #3255 from OHIF/dependabot/npm_and_yarn/hapi/hoek-8.5.1
chore(deps): bump @hapi/hoek from 8.3.2 to 8.5.1
2023-03-19 19:00:54 -03:00
Igor Octaviano 618b0fc516 Merge branch 'master' into dependabot/npm_and_yarn/hapi/hoek-8.5.1 2023-03-19 18:48:52 -03:00
Igor Octaviano 693bfc5ac3 Merge branch 'master' into dependabot/npm_and_yarn/moment-2.29.4 2023-03-19 18:48:49 -03:00
Igor Octaviano c14daf6735 Merge pull request #3253 from OHIF/dependabot/npm_and_yarn/docs/latest/qs-6.2.4
chore(deps): bump qs from 6.2.3 to 6.2.4 in /docs/latest
2023-03-19 18:48:33 -03:00
Igor Octaviano 5e35fbb21d Merge branch 'master' into dependabot/npm_and_yarn/moment-2.29.4 2023-03-19 18:43:49 -03:00
Igor Octaviano efd02088f1 Merge branch 'master' into dependabot/npm_and_yarn/hapi/hoek-8.5.1 2023-03-19 18:41:28 -03:00
Igor Octaviano d7f2b3acaf Merge branch 'master' into dependabot/npm_and_yarn/docs/latest/qs-6.2.4 2023-03-19 18:35:48 -03:00
Igor Octaviano c609acaaad Merge pull request #2692 from OHIF/dependabot/npm_and_yarn/tar-4.4.19
chore(deps): bump tar from 4.4.13 to 4.4.19
2023-03-19 18:35:36 -03:00
Igor Octaviano 4db092f4bf Merge branch 'master' into dependabot/npm_and_yarn/tar-4.4.19 2023-03-19 18:23:22 -03:00
Igor Octaviano 994abf2a6a Merge branch 'master' into dependabot/npm_and_yarn/docs/latest/qs-6.2.4 2023-03-19 18:23:15 -03:00
Igor Octaviano c7db3fca24 Merge branch 'master' into dependabot/npm_and_yarn/hapi/hoek-8.5.1 2023-03-19 18:23:12 -03:00
Igor Octaviano ce8e00ea73 Merge branch 'master' into dependabot/npm_and_yarn/moment-2.29.4 2023-03-19 18:23:10 -03:00
Igor Octaviano 4d4356338c Merge pull request #3254 from OHIF/dependabot/npm_and_yarn/docs/latest/minimatch-3.0.8
chore(deps): bump minimatch from 3.0.4 to 3.0.8 in /docs/latest
2023-03-19 18:22:54 -03:00
dependabot[bot] 9d9e1aa4fe chore(deps): bump tar from 4.4.13 to 4.4.19
Bumps [tar](https://github.com/npm/node-tar) from 4.4.13 to 4.4.19.
- [Release notes](https://github.com/npm/node-tar/releases)
- [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-tar/compare/v4.4.13...v4.4.19)

---
updated-dependencies:
- dependency-name: tar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-19 21:13:11 +00:00
dependabot[bot] 884224541b chore(deps): bump moment from 2.24.0 to 2.29.4
Bumps [moment](https://github.com/moment/moment) from 2.24.0 to 2.29.4.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.24.0...2.29.4)

---
updated-dependencies:
- dependency-name: moment
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-19 21:09:42 +00:00
dependabot[bot] 69a61698ae chore(deps): bump @hapi/hoek from 8.3.2 to 8.5.1
Bumps [@hapi/hoek](https://github.com/hapijs/hoek) from 8.3.2 to 8.5.1.
- [Release notes](https://github.com/hapijs/hoek/releases)
- [Commits](https://github.com/hapijs/hoek/compare/v8.3.2...v8.5.1)

---
updated-dependencies:
- dependency-name: "@hapi/hoek"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-19 21:09:28 +00:00
dependabot[bot] 82b4f72408 chore(deps): bump minimatch from 3.0.4 to 3.0.8 in /docs/latest
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.0.4 to 3.0.8.
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.0.8)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-19 21:08:49 +00:00
dependabot[bot] c87d933bbc chore(deps): bump qs from 6.2.3 to 6.2.4 in /docs/latest
Bumps [qs](https://github.com/ljharb/qs) from 6.2.3 to 6.2.4.
- [Release notes](https://github.com/ljharb/qs/releases)
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.2.3...v6.2.4)

---
updated-dependencies:
- dependency-name: qs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-19 21:08:33 +00:00
Igor Octaviano b1745c5157 Merge pull request #3251 from OHIF/fix/dependabot-critical-items
Bump libs version to address dependabot [critical] security alerts
2023-03-19 18:06:18 -03:00
Igor Octaviano 096590a7e9 Bump libs version to address dependabot [critical] security alerts 2023-03-19 14:51:21 -03:00
Igor Octaviano 106b67d436 Merge pull request #3249 from OHIF/dependabot/npm_and_yarn/thenify-3.3.1
chore(deps): bump thenify from 3.3.0 to 3.3.1
2023-03-19 14:41:01 -03:00
dependabot[bot] cefe3c3cfb chore(deps): bump thenify from 3.3.0 to 3.3.1
Bumps [thenify](https://github.com/thenables/thenify) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/thenables/thenify/releases)
- [Changelog](https://github.com/thenables/thenify/blob/master/History.md)
- [Commits](https://github.com/thenables/thenify/compare/3.3.0...3.3.1)

---
updated-dependencies:
- dependency-name: thenify
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-19 17:23:49 +00:00
Igor Octaviano 2a2d5eefcb Merge pull request #3248 from OHIF/fix/dependabot-high-critical-items
dependabot security updates
2023-03-19 14:22:54 -03:00
Igor Octaviano 3f55e57056 Bump minimist version to fix prototype pollution reported by dependabot 2023-03-19 14:05:35 -03:00
ohif-bot 30515b8ab5 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.21
 - @ohif/viewer@4.12.50
2023-01-17 17:52:04 +00:00
Gitanjali 24bbf2b190 Re IDC #3077: Seg series thumbnail selection (#3078)
* fix: #3077 update seg tolerance popup and update seg thumbnail warning

* jump to first segment item image

* Shows warning message only once on onChange
2023-01-17 09:50:25 -08:00
Alireza cb9aa6a765 chore: update issue and PR templates (#3113)
* chore: update issue templates

* add template to PRs

* update for pr titles

* update

* update

* update description
2023-01-11 16:53:35 -05:00
ohif-bot 5d9e4c9b02 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.20
 - @ohif/viewer@4.12.49
2023-01-10 16:33:09 +00:00
Gitanjali dab095b6b5 Re IDC #3088: Fix seg toggle visibility logic (#3101) 2023-01-10 08:30:52 -08:00
ohif-bot cfa697aabc chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.16
 - @ohif/extension-dicom-html@1.3.24
 - @ohif/extension-dicom-rt@0.7.14
 - @ohif/extension-dicom-segmentation@0.7.19
 - @ohif/extension-dicom-tag-browser@0.2.25
 - @ohif/extension-vtk@1.12.41
 - @ohif/core@2.16.35
 - @ohif/viewer@4.12.48
2022-12-21 13:40:36 +00:00
Gitanjali 3350b1faa6 Re IDC #3047: update variable name for frame index (#3085) 2022-12-21 19:23:47 +05:45
ohif-bot 4ffb50c7e9 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.18
 - @ohif/viewer@4.12.47
2022-12-21 04:56:46 +00:00
Gitanjali 1d29554a91 Re IDC #3067: Show eye-icon when segment label name is long (#3073)
* fix: #2964 Reword message for segmentation error loading due to orientation tolerance

* fix: Show eye-icon when segment name is long

* update python version
2022-12-21 10:40:04 +05:45
ohif-bot b9d484fb2e chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.17
 - @ohif/extension-vtk@1.12.40
 - @ohif/core@2.16.34
 - @ohif/viewer@4.12.46
2022-12-12 12:05:13 +00:00
Gitanjali 597ac11c4d fix: #2964 Reword message for segmentation error loading due to orientation tolerance (#3017) 2022-12-12 17:47:58 +05:45
ohif-bot 6007f340bf chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.39
 - @ohif/core@2.16.33
 - @ohif/viewer@4.12.45
2022-11-12 16:03:12 +00:00
Pauline Ribeyre 44738078db fix: handle missing ReferencedInstanceSequence attribute (#2786) 2022-11-12 11:01:21 -05:00
ohif-bot 686fe7d931 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.38
 - @ohif/core@2.16.32
 - @ohif/viewer@4.12.44
2022-11-02 21:22:01 +00:00
Gitanjali 0b8facbea6 remove-unsed-code-from-SR-parsing (#2997) 2022-11-02 15:20:20 -06:00
ohif-bot 0f89aa32f9 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.16
 - @ohif/extension-vtk@1.12.37
 - @ohif/core@2.16.31
 - @ohif/viewer@4.12.43
2022-10-28 17:55:54 +00:00
Gitanjali 545161d5e8 fix: #2964 Update message for segmentation error loading due to orientation tolerance (#2982) 2022-10-28 11:54:19 -06:00
ohif-bot eaa423c64e chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.36
 - @ohif/core@2.16.30
 - @ohif/viewer@4.12.42
2022-10-25 14:09:04 +00:00
Gitanjali f7db74a843 fix: 2965 Correct Parsing Logic for Qualitative Instance Level SR (#2972)
* fix: 2965 Correct Parsing Logic for Qualitative Instance Level SR

* fix: 2965 Correct Parsing Logic for Qualitative Instance Level SR

* fix: 2965 Correct Parsing Logic for Qualitative Instance Level SR
2022-10-25 10:06:59 -04:00
ohif-bot 7aba01f534 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.35
 - @ohif/viewer@4.12.41
2022-09-26 14:42:01 +00:00
GitanjaliChhetri c5ebeaa127 Re IDC #2847: Fix 2d MPR rendering issue for the sagittal view (#2960) 2022-09-26 08:39:55 -06:00
ohif-bot d7e1d2c975 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.15
 - @ohif/extension-vtk@1.12.34
 - @ohif/core@2.16.29
 - @ohif/viewer@4.12.40
2022-09-20 11:26:05 +00:00
Davide Punzo eb7eb56d7e Re IDC #2934: update cornerstoneWADOImageLoader to v 4.2.1 (#2944) 2022-09-20 13:24:17 +02:00
ohif-bot c5ee092bf2 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.15
 - @ohif/extension-vtk@1.12.33
 - @ohif/core@2.16.28
 - @ohif/viewer@4.12.39
2022-09-19 10:32:07 +00:00
Davide Punzo e2f4f95222 Re IDC #2935: fix parsing of Instance-level qualitative annotations (#2940) 2022-09-19 12:29:28 +02:00
ohif-bot 4546ede9bb chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.14
 - @ohif/viewer@4.12.38
2022-09-12 12:24:25 +00:00
Davide Punzo e0fb439e98 Fix IDC Re #2918: Runtime tolerance for SEGs loading (#2924) 2022-09-12 14:22:32 +02:00
ohif-bot ebbc9e0d6d chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.32
 - @ohif/core@2.16.27
 - @ohif/viewer@4.12.37
2022-09-12 08:27:33 +00:00
Davide Punzo 47a6130fd5 Re IDC #2919: fix popup notifications behavior (#2923) 2022-09-12 10:25:19 +02:00
ohif-bot 80dfdcc37c chore(release): publish [skip ci]
- @ohif/viewer@4.12.36
2022-09-08 14:48:41 +00:00
Doug Horner d74ad370e0 fix: hotkey page up/down did not work (#2910) 2022-09-08 10:46:26 -04:00
ohif-bot ddfde9279e chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.31
 - @ohif/core@2.16.26
 - @ohif/viewer@4.12.35
2022-09-02 13:49:07 +00:00
Davide Punzo aaab6d2622 Re IDC #2849: raise error if dicom request is not conforming with the UID (DICOM UI VR) character repertoire. (#2908) 2022-09-02 15:47:28 +02:00
ohif-bot d2921083e7 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.14
 - @ohif/extension-dicom-html@1.3.23
 - @ohif/extension-dicom-rt@0.7.13
 - @ohif/extension-dicom-segmentation@0.7.13
 - @ohif/extension-dicom-tag-browser@0.2.24
 - @ohif/extension-vtk@1.12.30
 - @ohif/core@2.16.25
 - @ohif/viewer@4.12.34
2022-09-01 18:14:46 +00:00
Davide Punzo a6338ea266 Re IDC #2869: update dcmjs for fixing eps in nearly equal condition (#2906) 2022-09-01 20:12:30 +02:00
ohif-bot fe9551b9b1 chore(release): publish [skip ci]
- @ohif/extension-dicom-rt@0.7.12
 - @ohif/extension-dicom-segmentation@0.7.12
 - @ohif/extension-vtk@1.12.29
 - @ohif/core@2.16.24
 - @ohif/viewer@4.12.33
2022-08-31 12:59:14 +00:00
Davide Punzo ef60156a47 Fix minor issues IDC (#2903) 2022-08-31 14:57:14 +02:00
ohif-bot 850de2903a chore(release): publish [skip ci]
- @ohif/viewer@4.12.32
2022-08-25 09:50:05 +00:00
Davide Punzo f26ed5539b IDC2859 (#2891)
* Re #2859 IDC: disable jump to for measurements in MPR mode
2022-08-25 11:48:20 +02:00
ohif-bot 21aeaa63c7 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.28
 - @ohif/core@2.16.23
 - @ohif/ui@1.10.10
 - @ohif/viewer@4.12.31
2022-08-24 10:38:46 +00:00
Davide Punzo 2ac0d3f017 Re #2852 IDC: fix parsing of qualitative slice annotation (#2888) 2022-08-24 12:37:21 +02:00
ohif-bot efdbe8e7b4 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.13
 - @ohif/extension-debugging@0.3.3
 - @ohif/extension-dicom-html@1.3.22
 - @ohif/extension-vtk@1.12.27
 - @ohif/core@2.16.22
 - @ohif/viewer@4.12.30
2022-06-30 10:07:05 +00:00
Davide Punzo 67b70eaa98 IDC2797: add linking and report UI for SR displaySets (#2834) 2022-06-30 12:05:47 +02:00
ohif-bot 5150ed9427 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.12
 - @ohif/extension-lesion-tracker@0.2.2
 - @ohif/extension-vtk@1.12.26
 - @ohif/core@2.16.21
 - @ohif/ui@1.10.9
 - @ohif/viewer@4.12.29
2022-06-29 02:26:24 +00:00
Davide Punzo 1bcb0acf9f IDC2797: improving UI for SR qualitative measurements and bug fixes (#2832) 2022-06-29 04:24:35 +02:00
ohif-bot 5d6cf2a609 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.25
 - @ohif/core@2.16.20
 - @ohif/viewer@4.12.28
2022-06-28 11:18:54 +00:00
Davide Punzo 9f813e0ea0 fix: Re IDC2797, fix double parsing of SR qualitative annotations (#2830) 2022-06-28 13:17:16 +02:00
ohif-bot 49de44ba34 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.11
 - @ohif/extension-vtk@1.12.24
 - @ohif/core@2.16.19
 - @ohif/viewer@4.12.27
2022-06-14 12:14:35 +00:00
Davide Punzo b04e186274 feat IDC #2797: add support for SR qualitative annotation per instance (#2822) 2022-06-14 14:12:27 +02:00
ohif-bot c59d66412f chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.23
 - @ohif/core@2.16.18
 - @ohif/viewer@4.12.26
2022-04-22 08:54:26 +00:00
Davide Punzo f8b4ccbb59 IDC: Fix undefined return in getDerivedDatasets (#2784) 2022-04-22 10:53:01 +02:00
ohif-bot 5426773ffc chore(release): publish [skip ci]
- @ohif/extension-dicom-tag-browser@0.2.23
 - @ohif/extension-vtk@1.12.22
 - @ohif/core@2.16.17
 - @ohif/ui@1.10.8
 - @ohif/viewer@4.12.25
2022-04-06 16:24:23 +00:00
Davide Punzo a507a00f59 Fix thumbnail loading bar (#2772) 2022-04-06 18:23:02 +02:00
Davide Punzo cedeb756c0 Re IDC #2762: fix thumbnail series type for unsupported SOPClassUID (#2770) 2022-04-06 17:10:00 +02:00
ohif-bot 64385485b6 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.10
 - @ohif/extension-dicom-html@1.3.21
 - @ohif/extension-dicom-rt@0.7.11
 - @ohif/extension-dicom-segmentation@0.7.11
 - @ohif/extension-dicom-tag-browser@0.2.22
 - @ohif/extension-vtk@1.12.21
 - @ohif/core@2.16.16
 - @ohif/viewer@4.12.24
2022-04-05 07:40:48 +00:00
Davide Punzo 32828d9a6e Re IDC #2765: fix loading of segmentations at first startup (#2768)
Re IDC #2761: fix loading of segmentations

update dcmjs to 0.19.9
2022-04-05 09:39:22 +02:00
ohif-bot b94d4782d1 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.9
 - @ohif/extension-dicom-html@1.3.20
 - @ohif/extension-dicom-rt@0.7.10
 - @ohif/extension-dicom-segmentation@0.7.10
 - @ohif/extension-dicom-tag-browser@0.2.21
 - @ohif/extension-vtk@1.12.20
 - @ohif/core@2.16.15
 - @ohif/viewer@4.12.23
2022-03-25 11:17:54 +00:00
Igor Octaviano 36b47ce3a3 Merge pull request #2750 from OHIF/igoroctaviano/dcmjs-0.19.8
Update dependency: dcmjs@0.19.8
2022-03-25 08:16:36 -03:00
igoroctaviano fe57c00577 Update dependency: dcmjs@0.19.8
dcmjs
  * @ohif/core: 0.19.7 → 0.19.8
  * @ohif/extension-cornerstone: 0.19.7 → 0.19.8
  * @ohif/extension-dicom-html: 0.19.7 → 0.19.8
  * @ohif/extension-dicom-rt: 0.19.7 → 0.19.8
  * @ohif/extension-dicom-segmentation: 0.19.7 → 0.19.8
  * @ohif/extension-dicom-tag-browser: 0.19.7 → 0.19.8
  * @ohif/extension-vtk: 0.19.7 → 0.19.8
  * @ohif/viewer: 0.19.7 → 0.19.8
2022-03-25 07:45:50 -03:00
84 changed files with 2834 additions and 738 deletions

No files matched your search

+16 -9
View File
@@ -2,23 +2,21 @@
name: "\U0001F41B Bug report" name: "\U0001F41B Bug report"
about: Create a report to help us improve about: Create a report to help us improve
title: '' title: ''
labels: 'Community: Report :bug:, Awaiting Reproduction, Triage :white_flag:' labels: 'Community: Report :bug:, Awaiting Reproduction'
assignees: '' assignees: ''
--- ---
> **Before Creating an issue** <!-- ⚠️⚠️ Do Not Delete This! bug_report_template ⚠️⚠️ -->
> <!-- Please read our Rules of Conduct: https://github.com/OHIF/Viewers/blob/master/CODE_OF_CONDUCT.md -->
> - Are you running the latest version? <!-- 🕮 Read our guide about our process: https://v3-docs.ohif.org/development/our-process -->
> - Are you reporting to the correct repository? <!-- 🔎 Search existing issues to avoid creating duplicates. -->
> - Did you search existing issues? <!-- 🧪 Test using the latest version -->
## Bug Report
### Describe the Bug ### Describe the Bug
_A clear and concise description of what the bug is._ _A clear and concise description of what the bug is._
### What steps can we follow to reproduce the bug? ### Steps to Reproduce:
1. First step 1. First step
2. Second step 2. Second step
@@ -28,6 +26,15 @@ _A clear and concise description of what the bug is._
Please use code blocks to show formatted errors or code snippets Please use code blocks to show formatted errors or code snippets
``` ```
### The current behavior
_A clear and concise description of what happens instead of the expected
behavior._
### The expected behavior
_A clear and concise description of what you expected to happen._
> :warning: Reports we cannot reproduce are at risk of being marked stale and > :warning: Reports we cannot reproduce are at risk of being marked stale and
> closed. The more information you can provide, the more likely we are to look > closed. The more information you can provide, the more likely we are to look
> into and address your issue. > into and address your issue.
+14 -5
View File
@@ -2,19 +2,28 @@
name: "\U0001F680 Feature request" name: "\U0001F680 Feature request"
about: Suggest an idea for this project about: Suggest an idea for this project
title: '' title: ''
labels: 'Community: Request :hand:, Triage :white_flag:' labels: 'Community: Request :hand:'
assignees: '' assignees: ''
--- ---
> :hand: Many people requests features. Tell us why yours is important to the <!-- ⚠️⚠️ Do Not Delete This! feature_request_template ⚠️⚠️ -->
<!-- Please read our Rules of Conduct: https://github.com/OHIF/Viewers/blob/master/CODE_OF_CONDUCT.md -->
<!-- :hand: Many people requests features. Tell us why yours is important to the
> community. How does it add value? Why _this feature_? > community. How does it add value? Why _this feature_?
> >
> Is your request very specific to your needs? Consider > Is your request very specific to your needs? Consider
> [contributing it](https://docs.ohif.org/contributing.html) yourself! Or reach > [contributing it](https://v3-docs.ohif.org/development/contributing) yourself!
> out to a community member that offers > Or reach out to a community member that offers
> [consulting services](https://docs.ohif.org/help.html#paid--commercial). > [consulting services](https://docs.ohif.org/help.html#paid--commercial).
-->
## Request ### Request
<!--
Please include as much detail as possible including possibly mock up screen shots, workflow or logic flow diagrams etc.
Discuss if and how the requested feature interacts with existing features
-->
**What feature or change would you like to see made?** **What feature or change would you like to see made?**
+86 -9
View File
@@ -1,14 +1,91 @@
### PR Checklist <!-- Do Not Delete This! pr_template -->
<!-- Please read our Rules of Conduct: https://github.com/OHIF/Viewers/blob/master/CODE_OF_CONDUCT.md -->
- [ ] Brief description of changes <!-- 🕮 Read our guide about our Contributing Guide here https://v3-docs.ohif.org/development/contributing -->
- [ ] Links to any relevant issues <!-- :hand: Thank you for starting this amazing contribution! -->
- [ ] Required status checks are passing
- [ ] User cases if changes impact the user's experience
- [ ] `@mention` a maintainer to request a review
<!-- <!--
Links ⚠️⚠️ Please make sure the checklist section below is complete before submitting your PR.
--> To complete the checklist, add an 'x' to each item: [] -> [x]
(PRs that do not have all the checkboxes marked will not be approved)
-->
### Context
<!--
Provide a clear explanation of the reasoning behind this change, such as:
- A link to the issue being addressed, using the format "Fixes #ISSUE_NUMBER"
- An image showing the issue or problem being addressed (if not already in the issue)
- Error logs or callStacks to help with the understanding of the problem (if not already in the issue)
-->
### Changes & Results
<!--
List all the changes that have been done, such as:
- Add new components
- Remove old components
- Update dependencies
What are the effects of this change?
- Before vs After
- Screenshots / GIFs / Videos
-->
### Testing
<!--
Describe how we can test your changes.
- open a URL
- visit a page
- click on a button
- etc.
-->
### Checklist
#### PR
<!--
https://semantic-release.gitbook.io/semantic-release/#how-does-it-work
Examples:
Please note the letter casing in the provided examples (upper or lower).
- feat(MeasurementService): add ...
- fix(Toolbar): fix ...
- docs(Readme): update ...
- style(Whitespace): fix ...
- refactor(ExtensionManager): ...
- test(HangingProtocol): Add test ...
- chore(git): update ...
- perf(VolumeLoader): ...
You don't need to have each commit within the Pull Request follow the rule,
but the PR title must comply with it, as it will be used as the commit message
after the commits are squashed.
-->
- [] My Pull Request title is descriptive, accurate and follows the
semantic-release format and guidelines.
#### Code
- [] My code has been well-documented (function documentation, inline comments,
etc.)
#### Public Documentation Updates
<!-- https://v3-docs.ohif.org/ -->
- [] The documentation page has been updated as necessary for any public API
additions or removals.
#### Tested Environment
- [] "OS: <!--[e.g. Windows 10, macOS 10.15.4]"-->
- [] "Node version: <!--[e.g. 16.14.0]"-->
- [] "Browser:
<!--[e.g. Chrome 83.0.4103.116, Firefox 77.0.1, Safari 13.1.1]"-->
<!-- prettier-ignore-start --> <!-- prettier-ignore-start -->
[blog]: https://circleci.com/blog/triggering-trusted-ci-jobs-on-untrusted-forks/ [blog]: https://circleci.com/blog/triggering-trusted-ci-jobs-on-untrusted-forks/
+3 -9
View File
@@ -4,23 +4,17 @@
# Number of days of inactivity before an issue becomes stale # Number of days of inactivity before an issue becomes stale
daysUntilStale: 180 daysUntilStale: 180
# Number of days of inactivity before a stale issue is closed # Number of days of inactivity before a stale issue is closed
daysUntilClose: 9000 daysUntilClose: 60
# Issues with these labels will never be considered stale # Issues with these labels will never be considered stale
exemptLabels: exemptLabels:
- 'Story :raised_hands:'
- 'Bug: Verified :bug:' - 'Bug: Verified :bug:'
- 'Task: CI/Tooling :robot:'
- 'Task: Docs 📖'
- 'Task: Docs :book:'
- 'Task: Refactor :hammer_and_wrench:'
- 'Task: Tests :microscope:'
- 'PR: Awaiting Review 👀' - 'PR: Awaiting Review 👀'
- 'Triage :white_flag:'
- 'Extension: Discussion'
- 'Announcement 🎉' - 'Announcement 🎉'
- 'IDC:priority' - 'IDC:priority'
- 'IDC:candidate' - 'IDC:candidate'
- 'IDC:collaboration' - 'IDC:collaboration'
- 'Community: Request :hand:'
- 'Community: Report :bug:'
# Label to use when marking an issue as stale # Label to use when marking an issue as stale
staleLabel: 'Stale :baguette_bread:' staleLabel: 'Stale :baguette_bread:'
# Comment to post when marking an issue as stale. Set to `false` to disable # Comment to post when marking an issue as stale. Set to `false` to disable
+5
View File
@@ -40,5 +40,10 @@
}, },
"devDependencies": { "devDependencies": {
"gitbook-cli": "^2.3.2" "gitbook-cli": "^2.3.2"
},
"resolutions": {
"underscore": "1.12.1",
"json-schema": "0.4.0",
"minimist": "1.2.8"
} }
} }
+31 -34
View File
@@ -1481,10 +1481,10 @@ json-schema-traverse@^0.4.1:
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-schema@0.2.3: json-schema@0.2.3, json-schema@0.4.0:
version "0.2.3" version "0.4.0"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
json-stable-stringify@^1.0.1: json-stable-stringify@^1.0.1:
version "1.0.1" version "1.0.1"
@@ -1729,27 +1729,24 @@ mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.7:
dependencies: dependencies:
mime-db "~1.38.0" mime-db "~1.38.0"
minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.3: minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4:
version "3.0.4" version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
dependencies: dependencies:
brace-expansion "^1.1.7" brace-expansion "^1.1.7"
minimist@0.0.8: minimatch@~3.0.3:
version "0.0.8" version "3.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==
dependencies:
brace-expansion "^1.1.7"
minimist@^1.2.0: minimist@0.0.8, minimist@1.2.8, minimist@^1.2.0, minimist@~0.0.1:
version "1.2.0" version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
minimist@~0.0.1:
version "0.0.10"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
mississippi@^1.2.0, mississippi@^1.3.0, mississippi@~1.3.0: mississippi@^1.2.0, mississippi@^1.3.0, mississippi@~1.3.0:
version "1.3.1" version "1.3.1"
@@ -2491,19 +2488,19 @@ q@1.5.0:
integrity sha1-3QG6ydBtMObyGa7LglPunr3DCPE= integrity sha1-3QG6ydBtMObyGa7LglPunr3DCPE=
qs@~6.2.0: qs@~6.2.0:
version "6.2.3" version "6.2.4"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.4.tgz#d90821bb8537cecc140e6c34f54ec76e54b39b22"
integrity sha1-HPyyXBCpsrSDBT/zn138kjOQjP4= integrity sha512-E57gmgKXqDda+qWTkUJgIwgJICK7zgMfqZZopTRKZ6mY9gzLlmJN9EpXNnDrTxXFlOM/a+I28kJkF/60rqgnYw==
qs@~6.4.0: qs@~6.4.0:
version "6.4.0" version "6.4.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.1.tgz#2bad97710a5b661c366b378b1e3a44a592ff45e6"
integrity sha1-E+JtKK1rD/qpExLNO/cI7TUecjM= integrity sha512-LQy1Q1fcva/UsnP/6Iaa4lVeM49WiOitu2T4hZCyA/elLKu37L99qcBJk4VCCk+rdLvnMzfKyiN3SZTqdAZGSQ==
qs@~6.5.2: qs@~6.5.2:
version "6.5.2" version "6.5.3"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
rc@^1.0.1, rc@^1.1.6: rc@^1.0.1, rc@^1.1.6:
version "1.2.8" version "1.2.8"
@@ -3175,10 +3172,10 @@ umask@~1.1.0:
resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d"
integrity sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0= integrity sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=
underscore@^1.7.0: underscore@1.12.1, underscore@^1.7.0:
version "1.9.1" version "1.12.1"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e"
integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==
unique-filename@^1.1.0, unique-filename@~1.1.0: unique-filename@^1.1.0, unique-filename@~1.1.0:
version "1.1.1" version "1.1.1"
+64
View File
@@ -3,6 +3,70 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.12.16](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.15...@ohif/extension-cornerstone@2.12.16) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.15](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.14...@ohif/extension-cornerstone@2.12.15) (2022-09-20)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.14](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.13...@ohif/extension-cornerstone@2.12.14) (2022-09-01)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.13](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.12...@ohif/extension-cornerstone@2.12.13) (2022-06-30)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.12](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.11...@ohif/extension-cornerstone@2.12.12) (2022-06-29)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.11](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.10...@ohif/extension-cornerstone@2.12.11) (2022-06-14)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.9...@ohif/extension-cornerstone@2.12.10) (2022-04-05)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.8...@ohif/extension-cornerstone@2.12.9) (2022-03-25)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.7...@ohif/extension-cornerstone@2.12.8) (2022-03-14) ## [2.12.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.7...@ohif/extension-cornerstone@2.12.8) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-cornerstone **Note:** Version bump only for package @ohif/extension-cornerstone
+5 -4
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/extension-cornerstone", "name": "@ohif/extension-cornerstone",
"version": "2.12.8", "version": "2.12.16",
"description": "OHIF extension for Cornerstone", "description": "OHIF extension for Cornerstone",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
@@ -35,8 +35,8 @@
"cornerstone-core": "^2.6.1", "cornerstone-core": "^2.6.1",
"cornerstone-math": "^0.1.9", "cornerstone-math": "^0.1.9",
"cornerstone-tools": "^6.0.6", "cornerstone-tools": "^6.0.6",
"cornerstone-wado-image-loader": "^4.1.0", "cornerstone-wado-image-loader": "^4.2.1",
"dcmjs": "0.19.7", "dcmjs": "0.29.3",
"dicom-parser": "^1.8.11", "dicom-parser": "^1.8.11",
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",
"prop-types": "^15.6.2", "prop-types": "^15.6.2",
@@ -44,7 +44,8 @@
"react-dom": "^16.8.6", "react-dom": "^16.8.6",
"react-redux": "^6.0.0", "react-redux": "^6.0.0",
"react-resize-detector": "^3.4.0", "react-resize-detector": "^3.4.0",
"redux": "^4.0.1" "redux": "^4.0.1",
"styled-components": "^5.3.5"
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.5.5", "@babel/runtime": "^7.5.5",
@@ -237,11 +237,21 @@ class OHIFCornerstoneViewport extends Component {
} }
}; };
const warningsOverlay = props => { const overlay = props => {
const displaySet = this.props.viewportData.displaySet;
let filteredSRLabels;
if (displaySet.SRLabels && displaySet.SRLabels.length !== 0) {
filteredSRLabels = displaySet.SRLabels.filter(
SRLabel =>
SRLabel.ReferencedSOPInstanceUID === displaySet.SOPInstanceUID
);
}
return ( return (
<OHIFCornerstoneViewportOverlay <OHIFCornerstoneViewportOverlay
{...props} {...props}
inconsistencyWarnings={inconsistencyWarnings} inconsistencyWarnings={inconsistencyWarnings}
SRLabels={filteredSRLabels}
/> />
); );
}; };
@@ -254,7 +264,7 @@ class OHIFCornerstoneViewport extends Component {
imageIdIndex={currentImageIdIndex} imageIdIndex={currentImageIdIndex}
onNewImageDebounced={newImageHandler} onNewImageDebounced={newImageHandler}
onNewImageDebounceTime={300} onNewImageDebounceTime={300}
viewportOverlayComponent={warningsOverlay} viewportOverlayComponent={overlay}
stackPrefetch={this.props.stackPrefetch} stackPrefetch={this.props.stackPrefetch}
isStackPrefetchEnabled={this.props.isStackPrefetchEnabled} isStackPrefetchEnabled={this.props.isStackPrefetchEnabled}
// ~~ Connected (From REDUX) // ~~ Connected (From REDUX)
@@ -33,6 +33,10 @@
bottom: 140px; bottom: 140px;
left: 20px; left: 20px;
} }
.OHIFCornerstoneViewportOverlay .bottom-left3 {
bottom: 110px;
left: -20px;
}
.OHIFCornerstoneViewportOverlay .bottom-right { .OHIFCornerstoneViewportOverlay .bottom-right {
bottom: 20px; bottom: 20px;
right: 20px; right: 20px;
@@ -1,5 +1,6 @@
import { PureComponent } from 'react'; import { PureComponent } from 'react';
import React from 'react'; import React from 'react';
import styled from 'styled-components';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import cornerstone from 'cornerstone-core'; import cornerstone from 'cornerstone-core';
import './OHIFCornerstoneViewportOverlay.css'; import './OHIFCornerstoneViewportOverlay.css';
@@ -9,13 +10,27 @@ import {
formatDICOMDate, formatDICOMDate,
formatDICOMTime, formatDICOMTime,
formatPN, formatPN,
getCompression getCompression,
} from '../utils/formatStudy'; } from '../utils/formatStudy';
import classNames from 'classnames'; import classNames from 'classnames';
import { Icon } from '@ohif/ui/src/elements/Icon'; import { Icon } from '@ohif/ui/src/elements/Icon';
import { Tooltip } from '@ohif/ui/src/components/tooltip'; import { Tooltip } from '@ohif/ui/src/components/tooltip';
import { OverlayTrigger } from '@ohif/ui/src/components/overlayTrigger'; import { OverlayTrigger } from '@ohif/ui/src/components/overlayTrigger';
const Button = styled.button`
color: white;
padding: 2px 7px;
border-radius: 10px;
outline: 0;
text-transform: none;
margin: 2px 2px;
cursor: pointer;
&:disabled {
cursor: default;
opacity: 0.9;
}
`;
class OHIFCornerstoneViewportOverlay extends PureComponent { class OHIFCornerstoneViewportOverlay extends PureComponent {
static propTypes = { static propTypes = {
scale: PropTypes.number.isRequired, scale: PropTypes.number.isRequired,
@@ -30,11 +45,19 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
imageId: PropTypes.string.isRequired, imageId: PropTypes.string.isRequired,
imageIndex: PropTypes.number.isRequired, imageIndex: PropTypes.number.isRequired,
stackSize: PropTypes.number.isRequired, stackSize: PropTypes.number.isRequired,
inconsistencyWarnings: PropTypes.array.isRequired inconsistencyWarnings: PropTypes.array,
SRLabels: PropTypes.array,
}; };
render() { render() {
const { imageId, scale, windowWidth, windowCenter, inconsistencyWarnings } = this.props; const {
imageId,
scale,
windowWidth,
windowCenter,
inconsistencyWarnings,
SRLabels,
} = this.props;
if (!imageId) { if (!imageId) {
return null; return null;
@@ -72,8 +95,11 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
const { imageIndex, stackSize } = this.props; const { imageIndex, stackSize } = this.props;
const inconsistencyWarningsOn = inconsistencyWarnings && inconsistencyWarnings.length !== 0 ? true : false; const inconsistencyWarningsOn =
const getWarningContent = (warningList) => { inconsistencyWarnings && inconsistencyWarnings.length !== 0
? true
: false;
const getWarningContent = warningList => {
if (Array.isArray(warningList)) { if (Array.isArray(warningList)) {
const listedWarnings = warningList.map((warn, index) => { const listedWarnings = warningList.map((warn, index) => {
return <li key={index}>{warn}</li>; return <li key={index}>{warn}</li>;
@@ -86,7 +112,7 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
}; };
const getWarningInfo = (seriesNumber, inconsistencyWarnings) => { const getWarningInfo = (seriesNumber, inconsistencyWarnings) => {
return( return (
<React.Fragment> <React.Fragment>
{inconsistencyWarnings.length != 0 ? ( {inconsistencyWarnings.length != 0 ? (
<OverlayTrigger <OverlayTrigger
@@ -99,7 +125,9 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
id="tooltip-left" id="tooltip-left"
> >
<div className="warningTitle">Series Inconsistencies</div> <div className="warningTitle">Series Inconsistencies</div>
<div className="warningContent">{getWarningContent(inconsistencyWarnings)}</div> <div className="warningContent">
{getWarningContent(inconsistencyWarnings)}
</div>
</Tooltip> </Tooltip>
} }
> >
@@ -116,6 +144,71 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
); );
}; };
const SRLabelsOn = SRLabels && SRLabels.length !== 0 ? true : false;
/**/
const getSRLabelsContent = SRLabels => {
if (Array.isArray(SRLabels)) {
const listedSRLabels = SRLabels.map((SRLabel, index) => {
const color = SRLabel.labels.color;
return (
SRLabel.labels.visible && (
<OverlayTrigger
key={index}
placement="top"
overlay={
<Tooltip
placement="top"
className="in tooltip-warning"
id="tooltip-top"
>
<div className="warningTitle">
{' '}
Coding scheme designators{' '}
</div>
<div className="warningContent">
{SRLabel.labels.labelCodingSchemeDesignator +
' : ' +
SRLabel.labels.valueCodingSchemeDesignator}
</div>
</Tooltip>
}
>
<div style={{ display: 'inline-block' }}>
<Button
style={{
backgroundColor: color,
}}
disabled={true}
key={index}
>
{SRLabel.labels.label + ' : ' + SRLabel.labels.value}
</Button>
</div>
</OverlayTrigger>
)
);
});
return <ol>{listedSRLabels}</ol>;
} else {
return <React.Fragment></React.Fragment>;
}
};
const getSRLabelsInfo = SRLabels => {
return (
<React.Fragment>
{SRLabels.length != 0 ? (
getSRLabelsContent(SRLabels)
) : (
<React.Fragment></React.Fragment>
)}
</React.Fragment>
);
};
const normal = ( const normal = (
<React.Fragment> <React.Fragment>
<div className="top-left overlay-element"> <div className="top-left overlay-element">
@@ -134,7 +227,14 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
<div className="compressionIndicator">{compression}</div> <div className="compressionIndicator">{compression}</div>
</div> </div>
<div className="bottom-left2 warning"> <div className="bottom-left2 warning">
<div>{inconsistencyWarningsOn ? getWarningInfo(seriesNumber, inconsistencyWarnings) : ''}</div> <div>
{inconsistencyWarningsOn
? getWarningInfo(seriesNumber, inconsistencyWarnings)
: ''}
</div>
</div>
<div className="bottom-left3 warning">
<div>{SRLabelsOn ? getSRLabelsInfo(SRLabels) : ''}</div>
</div> </div>
<div className="bottom-left overlay-element"> <div className="bottom-left overlay-element">
<div>{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}</div> <div>{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}</div>
@@ -97,6 +97,8 @@ export default class DICOMSRDisplayTool extends BaseTool {
const renderableDataForGraphicType = renderableData[GraphicType]; const renderableDataForGraphicType = renderableData[GraphicType];
switch (GraphicType) { switch (GraphicType) {
case SCOORD_TYPES.TEXT:
break;
case SCOORD_TYPES.POINT: case SCOORD_TYPES.POINT:
this.renderPoint(renderableDataForGraphicType, eventData, options); this.renderPoint(renderableDataForGraphicType, eventData, options);
break; break;
@@ -167,6 +169,7 @@ export default class DICOMSRDisplayTool extends BaseTool {
return data.handles.textBox.anchorPoints; return data.handles.textBox.anchorPoints;
} }
if (data.handles.textBox.anchorPoints.length !== 0) {
draw(context, context => { draw(context, context => {
drawLinkedTextBox( drawLinkedTextBox(
context, context,
@@ -182,6 +185,7 @@ export default class DICOMSRDisplayTool extends BaseTool {
); );
}); });
} }
}
// TOOD -> text boxes may overlap with other annotations at the moment. // TOOD -> text boxes may overlap with other annotations at the moment.
// To be fixed after we get requirements. // To be fixed after we get requirements.
@@ -230,7 +234,6 @@ export default class DICOMSRDisplayTool extends BaseTool {
const { element, image } = eventData; const { element, image } = eventData;
const { rows, columns } = image; const { rows, columns } = image;
const context = getNewContext(eventData.canvasContext.canvas); const context = getNewContext(eventData.canvasContext.canvas);
const { color, lineWidth } = options; const { color, lineWidth } = options;
// Find a suitable length for the image size. // Find a suitable length for the image size.
@@ -332,6 +335,8 @@ function _getTextBoxAnchorPointsForRenderableData(renderableData, eventData) {
const renderableDataForGraphicType = renderableData[GraphicType]; const renderableDataForGraphicType = renderableData[GraphicType];
switch (GraphicType) { switch (GraphicType) {
case SCOORD_TYPES.TEXT:
break;
case SCOORD_TYPES.POINT: case SCOORD_TYPES.POINT:
renderableDataForGraphicType.forEach(points => { renderableDataForGraphicType.forEach(points => {
anchorPoints = [...anchorPoints, ...points]; anchorPoints = [...anchorPoints, ...points];
@@ -405,7 +410,7 @@ function _getBoundingBoxFromAnchorPoints(anchorPoints) {
minX = x; minX = x;
} }
if (y > maxX) { if (y > maxY) {
maxY = y; maxY = y;
} else if (y < minY) { } else if (y < minY) {
minY = y; minY = y;
@@ -1,4 +1,5 @@
export default { export default {
TEXT: 'TEXT',
POINT: 'POINT', POINT: 'POINT',
MULTIPOINT: 'MULTIPOINT', MULTIPOINT: 'MULTIPOINT',
POLYLINE: 'POLYLINE', POLYLINE: 'POLYLINE',
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.3.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.3.2...@ohif/extension-debugging@0.3.3) (2022-06-30)
**Note:** Version bump only for package @ohif/extension-debugging
## [0.3.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.3.1...@ohif/extension-debugging@0.3.2) (2022-03-10) ## [0.3.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.3.1...@ohif/extension-debugging@0.3.2) (2022-03-10)
**Note:** Version bump only for package @ohif/extension-debugging **Note:** Version bump only for package @ohif/extension-debugging
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/extension-debugging", "name": "@ohif/extension-debugging",
"version": "0.3.2", "version": "0.3.3",
"description": "OHIF extension for debugging.", "description": "OHIF extension for debugging.",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
+33 -48
View File
@@ -89,10 +89,10 @@ const DubugReportModal = ({
Object.keys(viewportSpecificData).forEach(viewportIndex => { Object.keys(viewportSpecificData).forEach(viewportIndex => {
const displaySet = viewportSpecificData[viewportIndex]; const displaySet = viewportSpecificData[viewportIndex];
const [ const [referencedDisplaySetsRef] = _getReferencedSeriesInstanceUIDsString(
referencedDisplaySetsRef, displaySet,
referencedDisplaySetsCount, 'SEG'
] = _getReferencedSeriesInstanceUIDsString(displaySet, 'SEG'); );
const [row, column] = _viewportIndexToViewportPosition( const [row, column] = _viewportIndexToViewportPosition(
viewportIndex, viewportIndex,
@@ -106,10 +106,27 @@ const DubugReportModal = ({
Object.keys(viewportSpecificData).forEach(viewportIndex => { Object.keys(viewportSpecificData).forEach(viewportIndex => {
const displaySet = viewportSpecificData[viewportIndex]; const displaySet = viewportSpecificData[viewportIndex];
const [ const [referencedDisplaySetsRef] = _getReferencedSeriesInstanceUIDsString(
referencedDisplaySetsRef, displaySet,
referencedDisplaySetsCount, 'RTSTRUCT'
] = _getReferencedSeriesInstanceUIDsString(displaySet, 'RTSTRUCT'); );
const [row, column] = _viewportIndexToViewportPosition(
viewportIndex,
numColumns
);
body += `[${row},${column}]\t${referencedDisplaySetsRef}\n`;
});
body += '== ReferencedSRSeriesInstanceUIDs ==\n';
Object.keys(viewportSpecificData).forEach(viewportIndex => {
const displaySet = viewportSpecificData[viewportIndex];
const [referencedDisplaySetsRef] = _getReferencedSeriesInstanceUIDsString(
displaySet,
'SR'
);
const [row, column] = _viewportIndexToViewportPosition( const [row, column] = _viewportIndexToViewportPosition(
viewportIndex, viewportIndex,
@@ -261,11 +278,15 @@ const getLayout = viewports => {
<tr> <tr>
<th>ReferencedSEGSeriesInstanceUIDs</th> <th>ReferencedSEGSeriesInstanceUIDs</th>
</tr> </tr>
{getReferencedSEGSeriesInstanceUIDsPerRow(viewports)} {getReferencedSeriesInstanceUIDsPerRow(viewports, 'SEG')}
<tr> <tr>
<th>ReferencedRTSTRUCTSeriesInstanceUIDs</th> <th>ReferencedRTSTRUCTSeriesInstanceUIDs</th>
</tr> </tr>
{getReferencedRTSTRUCTSeriesInstanceUIDsPerRow(viewports)} {getReferencedSeriesInstanceUIDsPerRow(viewports, 'RTSTRUCT')}
<tr>
<th>ReferencedSRSeriesInstanceUIDs</th>
</tr>
{getReferencedSeriesInstanceUIDsPerRow(viewports, 'SR')}
</React.Fragment> </React.Fragment>
); );
}; };
@@ -351,7 +372,7 @@ const _getReferencedSeriesInstanceUIDsString = (displaySet, Modality) => {
return [referencedDisplaySetsRef, referencedDisplaySetsCount]; return [referencedDisplaySetsRef, referencedDisplaySetsCount];
}; };
const getReferencedSEGSeriesInstanceUIDsPerRow = viewports => { const getReferencedSeriesInstanceUIDsPerRow = (viewports, Modality) => {
const { viewportSpecificData, numColumns } = viewports; const { viewportSpecificData, numColumns } = viewports;
// NOTE viewportSpecificData is actually an object with numerical keys. // NOTE viewportSpecificData is actually an object with numerical keys.
@@ -360,43 +381,7 @@ const getReferencedSEGSeriesInstanceUIDsPerRow = viewports => {
const [ const [
referencedDisplaySetsRef, referencedDisplaySetsRef,
referencedDisplaySetsCount, referencedDisplaySetsCount,
] = _getReferencedSeriesInstanceUIDsString(displaySet, 'SEG'); ] = _getReferencedSeriesInstanceUIDsString(displaySet, Modality);
const [row, column] = _viewportIndexToViewportPosition(
viewportIndex,
numColumns
);
if (referencedDisplaySetsCount > 1) {
return (
<tr>
<td>{`[${row},${column}]`}</td>
<td className="debug-overflowText-border">
{referencedDisplaySetsRef}
</td>
</tr>
);
} else {
return (
<tr>
<td>{`[${row},${column}]`}</td>
<td className="debug-overflowText">{referencedDisplaySetsRef}</td>
</tr>
);
}
});
};
const getReferencedRTSTRUCTSeriesInstanceUIDsPerRow = viewports => {
const { viewportSpecificData, numColumns } = viewports;
// NOTE viewportSpecificData is actually an object with numerical keys.
return Object.keys(viewportSpecificData).map(viewportIndex => {
const displaySet = viewportSpecificData[viewportIndex];
const [
referencedDisplaySetsRef,
referencedDisplaySetsCount,
] = _getReferencedSeriesInstanceUIDsString(displaySet, 'RTSTRUCT');
const [row, column] = _viewportIndexToViewportPosition( const [row, column] = _viewportIndexToViewportPosition(
viewportIndex, viewportIndex,
+40
View File
@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.3.24](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.23...@ohif/extension-dicom-html@1.3.24) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.23](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.22...@ohif/extension-dicom-html@1.3.23) (2022-09-01)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.22](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.21...@ohif/extension-dicom-html@1.3.22) (2022-06-30)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.20...@ohif/extension-dicom-html@1.3.21) (2022-04-05)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.19...@ohif/extension-dicom-html@1.3.20) (2022-03-25)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.18...@ohif/extension-dicom-html@1.3.19) (2022-03-14) ## [1.3.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.18...@ohif/extension-dicom-html@1.3.19) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-dicom-html **Note:** Version bump only for package @ohif/extension-dicom-html
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/extension-dicom-html", "name": "@ohif/extension-dicom-html",
"version": "1.3.19", "version": "1.3.24",
"description": "OHIF extension for rendering structured reports to HTML", "description": "OHIF extension for rendering structured reports to HTML",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
@@ -29,7 +29,7 @@
}, },
"peerDependencies": { "peerDependencies": {
"@ohif/core": "^0.50.0", "@ohif/core": "^0.50.0",
"dcmjs": "0.19.7", "dcmjs": "0.29.3",
"prop-types": "^15.6.2", "prop-types": "^15.6.2",
"react": "^16.8.6", "react": "^16.8.6",
"react-dom": "^16.8.6" "react-dom": "^16.8.6"
@@ -1,4 +1,4 @@
import { MODULE_TYPES, utils } from '@ohif/core'; import { MODULE_TYPES, utils, metadata } from '@ohif/core';
// TODO: Should probably use dcmjs for this // TODO: Should probably use dcmjs for this
const SOP_CLASS_UIDS = { const SOP_CLASS_UIDS = {
@@ -10,7 +10,7 @@ const SOP_CLASS_UIDS = {
MAMMOGRAPHY_CAD_SR: '1.2.840.10008.5.1.4.1.1.88.50', MAMMOGRAPHY_CAD_SR: '1.2.840.10008.5.1.4.1.1.88.50',
CHEST_CAD_SR: '1.2.840.10008.5.1.4.1.1.88.65', CHEST_CAD_SR: '1.2.840.10008.5.1.4.1.1.88.65',
X_RAY_RADIATION_DOSE_SR: '1.2.840.10008.5.1.4.1.1.88.67', X_RAY_RADIATION_DOSE_SR: '1.2.840.10008.5.1.4.1.1.88.67',
ACQUISITION_CONTEXT_SR_STORAGE: '1.2.840.10008.5.1.4.1.1.88.71' ACQUISITION_CONTEXT_SR_STORAGE: '1.2.840.10008.5.1.4.1.1.88.71',
}; };
const sopClassUIDs = Object.values(SOP_CLASS_UIDS); const sopClassUIDs = Object.values(SOP_CLASS_UIDS);
@@ -32,7 +32,7 @@ const OHIFDicomHtmlSopClassHandler = {
SeriesTime, SeriesTime,
} = metadata; } = metadata;
return { const srDisplaySet = {
plugin: 'html', plugin: 'html',
Modality: 'SR', Modality: 'SR',
displaySetInstanceUID: utils.guid(), displaySetInstanceUID: utils.guid(),
@@ -49,7 +49,15 @@ const OHIFDicomHtmlSopClassHandler = {
authorizationHeaders, authorizationHeaders,
sopClassUids: sopClassUIDs, sopClassUids: sopClassUIDs,
images: series._instances, images: series._instances,
isDerived: true,
referencedDisplaySets: [],
}; };
srDisplaySet.getSourceDisplaySet = function() {
return srDisplaySet.referencedDisplaySets;
};
return srDisplaySet;
}, },
}; };
+40
View File
@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.7.14](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.13...@ohif/extension-dicom-rt@0.7.14) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.7.13](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.12...@ohif/extension-dicom-rt@0.7.13) (2022-09-01)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.7.12](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.11...@ohif/extension-dicom-rt@0.7.12) (2022-08-31)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.7.11](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.10...@ohif/extension-dicom-rt@0.7.11) (2022-04-05)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.7.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.9...@ohif/extension-dicom-rt@0.7.10) (2022-03-25)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.7.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.8...@ohif/extension-dicom-rt@0.7.9) (2022-03-14) ## [0.7.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.8...@ohif/extension-dicom-rt@0.7.9) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-dicom-rt **Note:** Version bump only for package @ohif/extension-dicom-rt
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/extension-dicom-rt", "name": "@ohif/extension-dicom-rt",
"version": "0.7.9", "version": "0.7.14",
"description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.", "description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
@@ -31,7 +31,7 @@
"@ohif/core": "^0.50.0", "@ohif/core": "^0.50.0",
"cornerstone-core": "^2.6.1", "cornerstone-core": "^2.6.1",
"cornerstone-tools": "^6.0.6", "cornerstone-tools": "^6.0.6",
"dcmjs": "0.19.7", "dcmjs": "0.29.3",
"gl-matrix": "^3.3.0", "gl-matrix": "^3.3.0",
"prop-types": "^15.6.2", "prop-types": "^15.6.2",
"react": "^16.8.6", "react": "^16.8.6",
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback } from 'react'; import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import cornerstoneTools from 'cornerstone-tools'; import cornerstoneTools from 'cornerstone-tools';
import cornerstone from 'cornerstone-core'; import cornerstone from 'cornerstone-core';
+102
View File
@@ -3,6 +3,108 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.7.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.20...@ohif/extension-dicom-segmentation@0.7.21) (2023-01-17)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.19...@ohif/extension-dicom-segmentation@0.7.20) (2023-01-10)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.18...@ohif/extension-dicom-segmentation@0.7.19) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.18](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.17...@ohif/extension-dicom-segmentation@0.7.18) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.17](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.16...@ohif/extension-dicom-segmentation@0.7.17) (2022-12-12)
### Bug Fixes
* [#2964](https://github.com/OHIF/Viewers/issues/2964) Reword message for segmentation error loading due to orientation tolerance ([#3017](https://github.com/OHIF/Viewers/issues/3017)) ([597ac11](https://github.com/OHIF/Viewers/commit/597ac11c4daee1b1e14148804551e20611cfef08))
## [0.7.16](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.15...@ohif/extension-dicom-segmentation@0.7.16) (2022-10-28)
### Bug Fixes
* [#2964](https://github.com/OHIF/Viewers/issues/2964) Update message for segmentation error loading due to orientation tolerance ([#2982](https://github.com/OHIF/Viewers/issues/2982)) ([545161d](https://github.com/OHIF/Viewers/commit/545161d5e8d92bb6652f17dc24a36dac8aa7b3a4))
## [0.7.15](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.14...@ohif/extension-dicom-segmentation@0.7.15) (2022-09-19)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.14](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.13...@ohif/extension-dicom-segmentation@0.7.14) (2022-09-12)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.13](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.12...@ohif/extension-dicom-segmentation@0.7.13) (2022-09-01)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.12](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.11...@ohif/extension-dicom-segmentation@0.7.12) (2022-08-31)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.11](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.10...@ohif/extension-dicom-segmentation@0.7.11) (2022-04-05)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.9...@ohif/extension-dicom-segmentation@0.7.10) (2022-03-25)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.8...@ohif/extension-dicom-segmentation@0.7.9) (2022-03-14) ## [0.7.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.8...@ohif/extension-dicom-segmentation@0.7.9) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation **Note:** Version bump only for package @ohif/extension-dicom-segmentation
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/extension-dicom-segmentation", "name": "@ohif/extension-dicom-segmentation",
"version": "0.7.9", "version": "0.7.21",
"description": "OHIF extension for viewing segmentations in the 2D MPR view", "description": "OHIF extension for viewing segmentations in the 2D MPR view",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
@@ -31,7 +31,7 @@
"@ohif/core": "^0.50.0", "@ohif/core": "^0.50.0",
"cornerstone-core": "^2.6.1", "cornerstone-core": "^2.6.1",
"cornerstone-tools": "^6.0.6", "cornerstone-tools": "^6.0.6",
"dcmjs": "0.19.7", "dcmjs": "0.29.3",
"prop-types": "^15.6.2", "prop-types": "^15.6.2",
"react": "^16.8.6", "react": "^16.8.6",
"react-dom": "^16.8.6" "react-dom": "^16.8.6"
@@ -0,0 +1,100 @@
import csTools from 'cornerstone-tools';
import cs from 'cornerstone-core';
import OHIF from '@ohif/core';
import DICOMSegTempCrosshairsTool from './tools/DICOMSegTempCrosshairsTool';
import refreshViewports from './utils/refreshViewports';
const { studyMetadataManager } = OHIF.utils;
const commandsModule = ({ commandsManager }) => {
const actions = {
jumpToFirstSegment: ({ viewports }) => {
try {
const { activeViewportIndex, viewportSpecificData } = viewports;
const viewport = viewportSpecificData[activeViewportIndex];
const { StudyInstanceUID, displaySetInstanceUID } = viewport;
const studyMetadata = studyMetadataManager.get(StudyInstanceUID);
const firstImageId = studyMetadata.getFirstImageId(
displaySetInstanceUID
);
const module = csTools.getModule('segmentation');
const brushStackState = module.state.series[firstImageId];
const { labelmaps3D, activeLabelmapIndex } = brushStackState;
const { labelmaps2D } = labelmaps3D[activeLabelmapIndex];
const firstLabelMap2D = labelmaps2D.find(value => !!value);
const firstSegment = firstLabelMap2D.segmentsOnLabelmap[0];
const segmentNumber = firstSegment;
const validIndexList = [];
labelmaps2D.forEach((labelMap2D, index) => {
if (labelMap2D.segmentsOnLabelmap.includes(segmentNumber)) {
validIndexList.push(index);
}
});
const avg = array => array.reduce((a, b) => a + b) / array.length;
const average = avg(validIndexList);
const closest = validIndexList.reduce((prev, curr) => {
return Math.abs(curr - average) < Math.abs(prev - average)
? curr
: prev;
});
const enabledElements = cs.getEnabledElements();
const element = enabledElements[activeViewportIndex].element;
const toolState = csTools.getToolState(element, 'stack');
if (!toolState) return;
const imageIds = toolState.data[0].imageIds;
const imageId = imageIds[closest];
const frameIndex = imageIds.indexOf(imageId);
const SOPInstanceUID = cs.metaData.get('SOPInstanceUID', imageId);
cs.getEnabledElements().forEach(enabledElement => {
cs.updateImage(enabledElement.element);
});
DICOMSegTempCrosshairsTool.addCrosshair(
element,
imageId,
segmentNumber
);
cs.getEnabledElements().forEach(enabledElement => {
cs.updateImage(enabledElement.element);
});
const refreshViewports = false;
commandsManager.runCommand('jumpToImage', {
StudyInstanceUID,
SOPInstanceUID,
frameIndex,
activeViewportIndex,
refreshViewports,
});
} catch (error) {
console.log('Error in moving to the first segment slice');
}
},
};
const definitions = {
jumpToFirstSegment: {
commandFn: actions.jumpToFirstSegment,
storeContexts: ['viewports'],
options: {},
},
};
return {
definitions,
defaultContext: 'VIEWER',
};
};
export default commandsModule;
@@ -62,8 +62,8 @@
} }
.dcmseg-segment-item .segment-label span { .dcmseg-segment-item .segment-label span {
overflow-wrap: normal; overflow-wrap: break-word;
white-space: nowrap; white-space: normal;
overflow: hidden; overflow: hidden;
max-width: calc(100% - 40px); /* calc(100% - 50px); 20px = eye icon */ max-width: calc(100% - 40px); /* calc(100% - 50px); 20px = eye icon */
text-overflow: ellipsis; text-overflow: ellipsis;
@@ -71,6 +71,7 @@
.dcmseg-segment-item .segment-label .eye-icon { .dcmseg-segment-item .segment-label .eye-icon {
cursor: pointer; cursor: pointer;
min-width: 20px;
color: var(--active-color); color: var(--active-color);
} }
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import cornerstoneTools from 'cornerstone-tools'; import cornerstoneTools from 'cornerstone-tools';
import cornerstone from 'cornerstone-core'; import cornerstone from 'cornerstone-core';
@@ -36,6 +36,7 @@ const { studyMetadataManager } = utils;
* @param {Function} props.onConfigurationChange - Configuration change handler * @param {Function} props.onConfigurationChange - Configuration change handler
* @param {Function} props.activeContexts - List of active application contexts * @param {Function} props.activeContexts - List of active application contexts
* @param {Function} props.contexts - List of available application contexts * @param {Function} props.contexts - List of available application contexts
* @param {Function} props.servicesManager - Services manager
* @returns component * @returns component
*/ */
const SegmentationPanel = ({ const SegmentationPanel = ({
@@ -50,6 +51,7 @@ const SegmentationPanel = ({
onSelectedSegmentationChange, onSelectedSegmentationChange,
activeContexts = [], activeContexts = [],
contexts = {}, contexts = {},
servicesManager,
}) => { }) => {
const isVTK = () => activeContexts.includes(contexts.VTK); const isVTK = () => activeContexts.includes(contexts.VTK);
const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE); const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE);
@@ -59,6 +61,9 @@ const SegmentationPanel = ({
* store with context to make these kind of things less blurry. * store with context to make these kind of things less blurry.
*/ */
const { configuration } = cornerstoneTools.getModule('segmentation'); const { configuration } = cornerstoneTools.getModule('segmentation');
if (configuration.segsTolerance === undefined) {
configuration.segsTolerance = 1e-2;
}
const DEFAULT_BRUSH_RADIUS = configuration.radius || 10; const DEFAULT_BRUSH_RADIUS = configuration.radius || 10;
/* /*
@@ -87,6 +92,25 @@ const SegmentationPanel = ({
return studyMetadata.getFirstImageId(displaySetInstanceUID); return studyMetadata.getFirstImageId(displaySetInstanceUID);
}; };
const getAllSegDisplaySets = () => {
const { StudyInstanceUID } = getActiveViewport();
const studyMetadata = studyMetadataManager.get(StudyInstanceUID);
return studyMetadata.getDerivedDatasets({
Modality: 'SEG',
});
};
const updateSegDisplaySetsTolerance = tolerance => {
const segDisplaySets = getAllSegDisplaySets();
segDisplaySets.forEach(segDisplaySet => {
// update tol value
segDisplaySet.tolerance = tolerance;
// reset load flags for allowing retry for seg parsing.
segDisplaySet.isLoaded = false;
segDisplaySet.loadError = false;
});
};
const getActiveLabelMaps3D = () => { const getActiveLabelMaps3D = () => {
const { labelmaps3D, activeLabelmapIndex } = getBrushStackState(); const { labelmaps3D, activeLabelmapIndex } = getBrushStackState();
return labelmaps3D[activeLabelmapIndex]; return labelmaps3D[activeLabelmapIndex];
@@ -224,33 +248,15 @@ const SegmentationPanel = ({
) )
); );
}; };
}, [ }, [activeIndex, viewports]);
activeIndex,
updateSegmentationComboBox,
viewports,
]);
const updateSegmentationComboBox = e => { const updateSegmentationComboBox = e => {
const index = e.detail.activatedLabelmapIndex; const index = e.detail.activatedLabelmapIndex;
if (index !== -1) { if (index !== -1) {
setState(state => ({ ...state, selectedSegmentation: index })); setState(state => ({ ...state, selectedSegmentation: index }));
} else {
cleanSegmentationComboBox();
} }
}; };
const cleanSegmentationComboBox = () => {
setState(state => ({
...state,
segmentsHidden: [],
segmentNumbers: [],
labelMapList: [],
segmentList: [],
isDisabled: true,
selectedSegmentation: -1,
}));
};
const refreshSegmentations = () => { const refreshSegmentations = () => {
const activeViewport = getActiveViewport(); const activeViewport = getActiveViewport();
const isDisabled = !activeViewport || !activeViewport.StudyInstanceUID; const isDisabled = !activeViewport || !activeViewport.StudyInstanceUID;
@@ -616,32 +622,26 @@ const SegmentationPanel = ({
configuration.outlineWidth = newConfiguration.outlineWidth; configuration.outlineWidth = newConfiguration.outlineWidth;
configuration.fillAlphaInactive = newConfiguration.fillAlphaInactive; configuration.fillAlphaInactive = newConfiguration.fillAlphaInactive;
configuration.outlineAlphaInactive = newConfiguration.outlineAlphaInactive; configuration.outlineAlphaInactive = newConfiguration.outlineAlphaInactive;
configuration.segsTolerance = newConfiguration.segsTolerance;
onConfigurationChange(newConfiguration); onConfigurationChange(newConfiguration);
updateSegDisplaySetsTolerance(configuration.segsTolerance);
refreshViewports(); refreshViewports();
}; };
const onVisibilityChangeHandler = isVisible => { const onVisibilityChangeHandler = isVisible => {
let segmentsHidden = []; let segmentsHidden = [];
const labelmap3D = getActiveLabelMaps3D();
state.segmentNumbers.forEach(segmentNumber => { state.segmentNumbers.forEach(segmentNumber => {
if (isVTK()) { if (isVTK()) {
onSegmentVisibilityChange(segmentNumber, isVisible); onSegmentVisibilityChange(segmentNumber, isVisible);
} }
/** Get all labelmaps with this segmentNumber (overlapping segments) */
const { labelmaps3D } = getBrushStackState();
const possibleLabelMaps3D = labelmaps3D.filter(({ labelmaps2D }) => {
return labelmaps2D.some(({ segmentsOnLabelmap }) =>
segmentsOnLabelmap.includes(segmentNumber)
);
});
possibleLabelMaps3D.forEach(labelmap3D => {
labelmap3D.segmentsHidden[segmentNumber] = !isVisible; labelmap3D.segmentsHidden[segmentNumber] = !isVisible;
segmentsHidden = [ segmentsHidden = [
...new Set([...segmentsHidden, ...labelmap3D.segmentsHidden]), ...new Set([...segmentsHidden, ...labelmap3D.segmentsHidden]),
]; ];
}); });
});
setState(state => ({ ...state, segmentsHidden })); setState(state => ({ ...state, segmentsHidden }));
@@ -665,6 +665,7 @@ const SegmentationPanel = ({
configuration={configuration} configuration={configuration}
onBack={() => setState(state => ({ ...state, showSettings: false }))} onBack={() => setState(state => ({ ...state, showSettings: false }))}
onChange={updateConfiguration} onChange={updateConfiguration}
servicesManager={servicesManager}
/> />
); );
} else { } else {
@@ -709,7 +710,7 @@ const SegmentationPanel = ({
count={state.segmentList.length} count={state.segmentList.length}
isVisible={ isVisible={
state.segmentsHidden.filter(isHidden => isHidden === true).length < state.segmentsHidden.filter(isHidden => isHidden === true).length <
state.segmentNumbers.length state.segmentNumbers.length && state.segmentNumbers.length > 0
} }
onVisibilityChange={onVisibilityChangeHandler} onVisibilityChange={onVisibilityChangeHandler}
> >
@@ -4,7 +4,7 @@ import { Range } from '@ohif/ui';
import './SegmentationSettings.css'; import './SegmentationSettings.css';
const SegmentationSettings = ({ configuration, onBack, onChange, disabledFields = [] }) => { const SegmentationSettings = ({ configuration, onBack, onChange, servicesManager, disabledFields = [] }) => {
const [state, setState] = useState({ const [state, setState] = useState({
renderFill: configuration.renderFill, renderFill: configuration.renderFill,
renderOutline: configuration.renderOutline, renderOutline: configuration.renderOutline,
@@ -13,7 +13,8 @@ const SegmentationSettings = ({ configuration, onBack, onChange, disabledFields
outlineAlpha: configuration.outlineAlpha, outlineAlpha: configuration.outlineAlpha,
outlineWidth: configuration.outlineWidth, outlineWidth: configuration.outlineWidth,
fillAlphaInactive: configuration.fillAlphaInactive, fillAlphaInactive: configuration.fillAlphaInactive,
outlineAlphaInactive: configuration.outlineAlphaInactive outlineAlphaInactive: configuration.outlineAlphaInactive,
segsTolerance: configuration.segsTolerance,
}); });
useEffect(() => { useEffect(() => {
@@ -28,6 +29,32 @@ const SegmentationSettings = ({ configuration, onBack, onChange, disabledFields
setState(state => ({ ...state, [field]: value })); setState(state => ({ ...state, [field]: value }));
}; };
const once = fn => (...args) => {
if (!fn) return;
fn(...args);
fn = null;
};
const segTolValue = document.getElementById('segToleranceValue');
if (segTolValue) {
segTolValue.onchange = once(function() {
const { UINotificationService, LoggerService } = servicesManager.services;
const error = new Error(
'Segmentation loader tolerance changed.\
This operation can potentially generate errors in the Segmentation parsing.'
);
LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: 'Segmentation panel',
message: error.message,
type: 'warning',
autoClose: true,
});
});
}
const toFloat = value => parseFloat(value / 100).toFixed(2); const toFloat = value => parseFloat(value / 100).toFixed(2);
return ( return (
@@ -133,6 +160,31 @@ const SegmentationSettings = ({ configuration, onBack, onChange, disabledFields
)} )}
</div> </div>
)} )}
<div className="settings-group" style={{ marginBottom: 15 }}>
<label style={{ margin: '0 15px' }}>
Tolerance:
<input
id="segToleranceValue"
style={{ margin: '0 15px' }}
label="Tolerance"
onKeyPress={event => {
const validate = string => {
let rgx = /[^-.e0-9]+/g;
return string.match(rgx);
};
if (validate(event.key)) {
event.preventDefault();
}
}
}
onChange={event => {
save('segsTolerance', event.target.value);
}}
value={state.segsTolerance}
/>
</label>
</div>
</div> </div>
); );
}; };
@@ -169,11 +221,12 @@ SegmentationSettings.propTypes = {
renderFill: PropTypes.bool.isRequired, renderFill: PropTypes.bool.isRequired,
renderOutline: PropTypes.bool.isRequired, renderOutline: PropTypes.bool.isRequired,
shouldRenderInactiveLabelmaps: PropTypes.bool.isRequired, shouldRenderInactiveLabelmaps: PropTypes.bool.isRequired,
fillAlpha: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, /* TODO: why fillAlpha is string? */ fillAlpha: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
outlineAlpha: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, /* TODO: why fillAlpha is string? */ outlineAlpha: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
outlineWidth: PropTypes.number.isRequired, outlineWidth: PropTypes.number.isRequired,
fillAlphaInactive: PropTypes.number.isRequired, fillAlphaInactive: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
outlineAlphaInactive: PropTypes.number.isRequired, outlineAlphaInactive: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
segsTolerance: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
}).isRequired, }).isRequired,
onBack: PropTypes.func.isRequired, onBack: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
@@ -62,6 +62,7 @@ export default function getSopClassHandlerModule({ servicesManager }) {
SeriesNumber, SeriesNumber,
SeriesDescription, SeriesDescription,
metadata, metadata,
tolerance: 1e-2,
}; };
segDisplaySet.getSourceDisplaySet = function( segDisplaySet.getSourceDisplaySet = function(
@@ -93,7 +94,7 @@ export default function getSopClassHandlerModule({ servicesManager }) {
referencedDisplaySet.SeriesInstanceUID referencedDisplaySet.SeriesInstanceUID
); );
const results = await _parseSeg(segArrayBuffer, imageIds); const results = await _parseSeg(segArrayBuffer, imageIds, segDisplaySet.tolerance);
if (results === undefined) { if (results === undefined) {
return; return;
} }
@@ -149,10 +150,13 @@ export default function getSopClassHandlerModule({ servicesManager }) {
}; };
} }
function _parseSeg(arrayBuffer, imageIds) { function _parseSeg(
const skipOverlapping = false; arrayBuffer,
const tolerance = 1e-2; imageIds,
const cornerstoneToolsVersion = 4; tolerance = 1e-2,
skipOverlapping = false,
cornerstoneToolsVersion = 4
) {
return dcmjs.adapters.Cornerstone.Segmentation.generateToolState( return dcmjs.adapters.Cornerstone.Segmentation.generateToolState(
imageIds, imageIds,
arrayBuffer, arrayBuffer,
+23 -3
View File
@@ -6,6 +6,7 @@ import toolbarModule from './toolbarModule.js';
import getSopClassHandlerModule from './getOHIFDicomSegSopClassHandler.js'; import getSopClassHandlerModule from './getOHIFDicomSegSopClassHandler.js';
import SegmentationPanel from './components/SegmentationPanel/SegmentationPanel.js'; import SegmentationPanel from './components/SegmentationPanel/SegmentationPanel.js';
import { version } from '../package.json'; import { version } from '../package.json';
import commandsModule from './commandsModule.js';
const { studyMetadataManager } = OHIF.utils; const { studyMetadataManager } = OHIF.utils;
export default { export default {
@@ -32,12 +33,18 @@ export default {
const ExtendedSegmentationPanel = props => { const ExtendedSegmentationPanel = props => {
const { activeContexts } = api.hooks.useAppContext(); const { activeContexts } = api.hooks.useAppContext();
const onDisplaySetLoadFailureHandler = error => { const onDisplaySetLoadFailureHandler = error => {
LoggerService.error({ error, message: error.message }); const message =
error.message.includes('orthogonal') ||
error.message.includes('oblique')
? 'The segmentation has been detected as non coplanar,\
If you really think it is coplanar,\
please adjust the tolerance in the segmentation panel settings (at your own peril!)'
: error.message;
LoggerService.error({ error, message });
UINotificationService.show({ UINotificationService.show({
title: 'DICOM Segmentation Loader', title: 'DICOM Segmentation Loader',
message: error.message, message,
type: 'error', type: 'error',
autoClose: false, autoClose: false,
}); });
@@ -78,6 +85,7 @@ export default {
onConfigurationChange={onConfigurationChangeHandler} onConfigurationChange={onConfigurationChangeHandler}
onSelectedSegmentationChange={onSelectedSegmentationChangeHandler} onSelectedSegmentationChange={onSelectedSegmentationChangeHandler}
onDisplaySetLoadFailure={onDisplaySetLoadFailureHandler} onDisplaySetLoadFailure={onDisplaySetLoadFailureHandler}
servicesManager={servicesManager}
/> />
); );
}; };
@@ -114,6 +122,15 @@ export default {
}); });
}; };
const onSegmentationsCompletelyLoaded = () => {
commandsManager.runCommand('jumpToFirstSegment');
};
document.addEventListener(
'segseriesselected',
onSegmentationsCompletelyLoaded
);
document.addEventListener( document.addEventListener(
'extensiondicomsegmentationsegloaded', 'extensiondicomsegmentationsegloaded',
onSegmentationsLoaded onSegmentationsLoaded
@@ -175,5 +192,8 @@ export default {
defaultContext: ['VIEWER'], defaultContext: ['VIEWER'],
}; };
}, },
getCommandsModule({ commandsManager, servicesManager }) {
return commandsModule({ commandsManager, servicesManager });
},
getSopClassHandlerModule, getSopClassHandlerModule,
}; };
@@ -47,14 +47,23 @@ export default async function setActiveLabelmap(
return labelmapIndex; return labelmapIndex;
} }
if (!displaySet.isLoaded) { if (!displaySet.isLoaded && !displaySet.loadError) {
try { try {
await displaySet.load(referencedDisplaySet, studies); await displaySet.load(referencedDisplaySet, studies);
} catch (error) { } catch (error) {
displaySet.isLoaded = false; displaySet.isLoaded = false;
displaySet.loadError = true; displaySet.loadError = true;
displaySet.segLoadErrorMessagge = error.message;
onDisplaySetLoadFailure(error); onDisplaySetLoadFailure(error);
/*
* TODO: Improve the way we notify parts of the app
* that depends on derived display sets to be loaded.
* (Implement pubsub for better tracking of derived display sets)
*/
const event = new CustomEvent('segmentationLoadingError');
document.dispatchEvent(event);
return -1; return -1;
} }
} }
+48
View File
@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.2.26](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.25...@ohif/extension-dicom-tag-browser@0.2.26) (2023-03-19)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.25](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.24...@ohif/extension-dicom-tag-browser@0.2.25) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.24](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.23...@ohif/extension-dicom-tag-browser@0.2.24) (2022-09-01)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.23](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.22...@ohif/extension-dicom-tag-browser@0.2.23) (2022-04-06)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.22](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.21...@ohif/extension-dicom-tag-browser@0.2.22) (2022-04-05)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.20...@ohif/extension-dicom-tag-browser@0.2.21) (2022-03-25)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.19...@ohif/extension-dicom-tag-browser@0.2.20) (2022-03-14) ## [0.2.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.19...@ohif/extension-dicom-tag-browser@0.2.20) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser **Note:** Version bump only for package @ohif/extension-dicom-tag-browser
+3 -3
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/extension-dicom-tag-browser", "name": "@ohif/extension-dicom-tag-browser",
"version": "0.2.20", "version": "0.2.26",
"description": "OHIF extension for checking DICOM headers.", "description": "OHIF extension for checking DICOM headers.",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
@@ -28,13 +28,13 @@
}, },
"peerDependencies": { "peerDependencies": {
"@ohif/core": "^2.6.0", "@ohif/core": "^2.6.0",
"dcmjs": "0.19.7", "dcmjs": "0.29.3",
"react": "^16.8.6" "react": "^16.8.6"
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.5.5", "@babel/runtime": "^7.5.5",
"dicomweb-client": "^0.8.3", "dicomweb-client": "^0.8.3",
"moment": "2.24.0", "moment": "2.29.4",
"react-select": "^3.0.8" "react-select": "^3.0.8"
} }
} }
@@ -59,7 +59,7 @@ const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
let metadata; let metadata;
const isImageStack = const isImageStack =
activeDisplaySet instanceof ImageSet && activeDisplaySet instanceof ImageSet &&
activeDisplaySet.isModalitySupported === true; activeDisplaySet.isSOPClassUIDSupported === true;
let instanceList; let instanceList;
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.2.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-lesion-tracker@0.2.1...@ohif/extension-lesion-tracker@0.2.2) (2022-06-29)
**Note:** Version bump only for package @ohif/extension-lesion-tracker
## [0.2.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-lesion-tracker@0.2.0...@ohif/extension-lesion-tracker@0.2.1) (2020-09-03) ## [0.2.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-lesion-tracker@0.2.0...@ohif/extension-lesion-tracker@0.2.1) (2020-09-03)
**Note:** Version bump only for package @ohif/extension-lesion-tracker **Note:** Version bump only for package @ohif/extension-lesion-tracker
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/extension-lesion-tracker", "name": "@ohif/extension-lesion-tracker",
"version": "0.2.1", "version": "0.2.2",
"description": "OHIF extension for Lesion Tracker", "description": "OHIF extension for Lesion Tracker",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
@@ -76,13 +76,13 @@ const additionalFindings = [
const currentCollections = [ const currentCollections = [
{ {
selectorAction: () => { }, selectorAction: () => {},
maxMeasurements: 3, maxMeasurements: 3,
groupName: 'Measurements', groupName: 'Measurements',
measurements: measurements, measurements: measurements,
}, },
{ {
selectorAction: () => { }, selectorAction: () => {},
groupName: 'Additional Findings', groupName: 'Additional Findings',
measurements: additionalFindings, measurements: additionalFindings,
}, },
@@ -90,13 +90,13 @@ const currentCollections = [
const comparisonColletions = [ const comparisonColletions = [
{ {
selectorAction: () => { }, selectorAction: () => {},
maxMeasurements: 3, maxMeasurements: 3,
groupName: 'Measurements', groupName: 'Measurements',
measurements: measurements, measurements: measurements,
}, },
{ {
selectorAction: () => { }, selectorAction: () => {},
groupName: 'Additional Findings', groupName: 'Additional Findings',
measurements: additionalFindings, measurements: additionalFindings,
}, },
@@ -128,7 +128,7 @@ const comparisonTimepoints = [
{ {
key: 'Comparison', key: 'Comparison',
date: '15-Jun-18', date: '15-Jun-18',
} },
]; ];
const MeasurementComparisonTable = () => { const MeasurementComparisonTable = () => {
@@ -138,8 +138,8 @@ const MeasurementComparisonTable = () => {
timepoints={comparisonTimepoints} timepoints={comparisonTimepoints}
overallWarnings={overallWarnings} overallWarnings={overallWarnings}
measurementCollection={comparisonCollections} measurementCollection={comparisonCollections}
onRelabelClick={() => { }} onRelabelClick={() => {}}
onEditDescriptionClick={() => { }} onEditDescriptionClick={() => {}}
/> />
<div className="generate-report"> <div className="generate-report">
<button className="btn btn-primary">Generate Report</button> <button className="btn btn-primary">Generate Report</button>
+184
View File
@@ -3,6 +3,190 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.12.42](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.41...@ohif/extension-vtk@1.12.42) (2023-03-19)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.41](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.40...@ohif/extension-vtk@1.12.41) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.40](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.39...@ohif/extension-vtk@1.12.40) (2022-12-12)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.39](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.38...@ohif/extension-vtk@1.12.39) (2022-11-12)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.38](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.37...@ohif/extension-vtk@1.12.38) (2022-11-02)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.37](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.36...@ohif/extension-vtk@1.12.37) (2022-10-28)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.36](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.35...@ohif/extension-vtk@1.12.36) (2022-10-25)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.35](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.34...@ohif/extension-vtk@1.12.35) (2022-09-26)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.34](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.33...@ohif/extension-vtk@1.12.34) (2022-09-20)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.33](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.32...@ohif/extension-vtk@1.12.33) (2022-09-19)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.32](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.31...@ohif/extension-vtk@1.12.32) (2022-09-12)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.31](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.30...@ohif/extension-vtk@1.12.31) (2022-09-02)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.30](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.29...@ohif/extension-vtk@1.12.30) (2022-09-01)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.29](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.28...@ohif/extension-vtk@1.12.29) (2022-08-31)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.28](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.27...@ohif/extension-vtk@1.12.28) (2022-08-24)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.27](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.26...@ohif/extension-vtk@1.12.27) (2022-06-30)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.26](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.25...@ohif/extension-vtk@1.12.26) (2022-06-29)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.25](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.24...@ohif/extension-vtk@1.12.25) (2022-06-28)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.24](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.23...@ohif/extension-vtk@1.12.24) (2022-06-14)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.23](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.22...@ohif/extension-vtk@1.12.23) (2022-04-22)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.22](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.21...@ohif/extension-vtk@1.12.22) (2022-04-06)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.20...@ohif/extension-vtk@1.12.21) (2022-04-05)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.19...@ohif/extension-vtk@1.12.20) (2022-03-25)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.18...@ohif/extension-vtk@1.12.19) (2022-03-14) ## [1.12.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.18...@ohif/extension-vtk@1.12.19) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-vtk **Note:** Version bump only for package @ohif/extension-vtk
+7 -7
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/extension-vtk", "name": "@ohif/extension-vtk",
"version": "1.12.19", "version": "1.12.42",
"description": "OHIF extension for VTK.js", "description": "OHIF extension for VTK.js",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
@@ -34,8 +34,8 @@
"@ohif/ui": "^0.50.0", "@ohif/ui": "^0.50.0",
"cornerstone-core": "^2.6.1", "cornerstone-core": "^2.6.1",
"cornerstone-tools": "^6.0.6", "cornerstone-tools": "^6.0.6",
"cornerstone-wado-image-loader": "^4.1.0", "cornerstone-wado-image-loader": "^4.2.1",
"dcmjs": "0.19.7", "dcmjs": "0.29.3",
"dicom-parser": "^1.8.11", "dicom-parser": "^1.8.11",
"i18next": "^17.0.3", "i18next": "^17.0.3",
"i18next-browser-languagedetector": "^3.0.1", "i18next-browser-languagedetector": "^3.0.1",
@@ -50,13 +50,13 @@
"dependencies": { "dependencies": {
"@babel/runtime": "^7.5.5", "@babel/runtime": "^7.5.5",
"lodash.throttle": "^4.1.1", "lodash.throttle": "^4.1.1",
"react-vtkjs-viewport": "^0.14.4" "react-vtkjs-viewport": "^0.14.5"
}, },
"devDependencies": { "devDependencies": {
"@ohif/core": "^2.16.14", "@ohif/core": "^2.16.35",
"@ohif/ui": "^1.10.7", "@ohif/ui": "^1.10.11",
"cornerstone-tools": "^6.0.6", "cornerstone-tools": "^6.0.6",
"cornerstone-wado-image-loader": "^4.1.0", "cornerstone-wado-image-loader": "^4.2.1",
"dicom-parser": "^1.8.11", "dicom-parser": "^1.8.11",
"gh-pages": "^2.0.1", "gh-pages": "^2.0.1",
"i18next": "^17.0.3", "i18next": "^17.0.3",
+9
View File
@@ -99,6 +99,7 @@
"shader-loader": "^1.3.1", "shader-loader": "^1.3.1",
"start-server-and-test": "^1.10.0", "start-server-and-test": "^1.10.0",
"style-loader": "^1.0.0", "style-loader": "^1.0.0",
"styled-components": "^5.3.5",
"stylelint": "^10.1.0", "stylelint": "^10.1.0",
"stylelint-config-recommended": "^2.2.0", "stylelint-config-recommended": "^2.2.0",
"stylus": "^0.54.5", "stylus": "^0.54.5",
@@ -124,6 +125,14 @@
] ]
}, },
"resolutions": { "resolutions": {
"handlebars": "4.7.7",
"json-schema": "0.4.0",
"ejs": "3.1.7",
"thenify": "3.3.1",
"parse-url": "8.1.0",
"loader-utils": "1.4.1",
"flat": "5.0.1",
"minimist": "1.2.8",
"**/node-gyp": "8.4.1", "**/node-gyp": "8.4.1",
"**/@babel/runtime": "7.5.5" "**/@babel/runtime": "7.5.5"
} }
+183
View File
@@ -3,6 +3,189 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.16.35](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.34...@ohif/core@2.16.35) (2022-12-21)
**Note:** Version bump only for package @ohif/core
## [2.16.34](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.33...@ohif/core@2.16.34) (2022-12-12)
### Bug Fixes
* [#2964](https://github.com/OHIF/Viewers/issues/2964) Reword message for segmentation error loading due to orientation tolerance ([#3017](https://github.com/OHIF/Viewers/issues/3017)) ([597ac11](https://github.com/OHIF/Viewers/commit/597ac11c4daee1b1e14148804551e20611cfef08))
## [2.16.33](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.32...@ohif/core@2.16.33) (2022-11-12)
### Bug Fixes
* handle missing ReferencedInstanceSequence attribute ([#2786](https://github.com/OHIF/Viewers/issues/2786)) ([4473807](https://github.com/OHIF/Viewers/commit/44738078dbd8dc6b27d2d669e25417e37371f48d))
## [2.16.32](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.31...@ohif/core@2.16.32) (2022-11-02)
**Note:** Version bump only for package @ohif/core
## [2.16.31](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.30...@ohif/core@2.16.31) (2022-10-28)
### Bug Fixes
* [#2964](https://github.com/OHIF/Viewers/issues/2964) Update message for segmentation error loading due to orientation tolerance ([#2982](https://github.com/OHIF/Viewers/issues/2982)) ([545161d](https://github.com/OHIF/Viewers/commit/545161d5e8d92bb6652f17dc24a36dac8aa7b3a4))
## [2.16.30](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.29...@ohif/core@2.16.30) (2022-10-25)
### Bug Fixes
* 2965 Correct Parsing Logic for Qualitative Instance Level SR ([#2972](https://github.com/OHIF/Viewers/issues/2972)) ([f7db74a](https://github.com/OHIF/Viewers/commit/f7db74a84376598065b6fa2c00cd5735415ff651))
## [2.16.29](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.28...@ohif/core@2.16.29) (2022-09-20)
**Note:** Version bump only for package @ohif/core
## [2.16.28](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.27...@ohif/core@2.16.28) (2022-09-19)
**Note:** Version bump only for package @ohif/core
## [2.16.27](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.26...@ohif/core@2.16.27) (2022-09-12)
**Note:** Version bump only for package @ohif/core
## [2.16.26](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.25...@ohif/core@2.16.26) (2022-09-02)
**Note:** Version bump only for package @ohif/core
## [2.16.25](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.24...@ohif/core@2.16.25) (2022-09-01)
**Note:** Version bump only for package @ohif/core
## [2.16.24](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.23...@ohif/core@2.16.24) (2022-08-31)
**Note:** Version bump only for package @ohif/core
## [2.16.23](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.22...@ohif/core@2.16.23) (2022-08-24)
**Note:** Version bump only for package @ohif/core
## [2.16.22](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.21...@ohif/core@2.16.22) (2022-06-30)
**Note:** Version bump only for package @ohif/core
## [2.16.21](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.20...@ohif/core@2.16.21) (2022-06-29)
**Note:** Version bump only for package @ohif/core
## [2.16.20](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.19...@ohif/core@2.16.20) (2022-06-28)
### Bug Fixes
* Re IDC2797, fix double parsing of SR qualitative annotations ([#2830](https://github.com/OHIF/Viewers/issues/2830)) ([9f813e0](https://github.com/OHIF/Viewers/commit/9f813e0ea08f0aada8efab9ef6228ad90dd1758d))
## [2.16.19](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.18...@ohif/core@2.16.19) (2022-06-14)
**Note:** Version bump only for package @ohif/core
## [2.16.18](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.17...@ohif/core@2.16.18) (2022-04-22)
**Note:** Version bump only for package @ohif/core
## [2.16.17](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.16...@ohif/core@2.16.17) (2022-04-06)
**Note:** Version bump only for package @ohif/core
## [2.16.16](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.15...@ohif/core@2.16.16) (2022-04-05)
**Note:** Version bump only for package @ohif/core
## [2.16.15](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.14...@ohif/core@2.16.15) (2022-03-25)
**Note:** Version bump only for package @ohif/core
## [2.16.14](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.13...@ohif/core@2.16.14) (2022-03-14) ## [2.16.14](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.13...@ohif/core@2.16.14) (2022-03-14)
**Note:** Version bump only for package @ohif/core **Note:** Version bump only for package @ohif/core
+3 -3
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/core", "name": "@ohif/core",
"version": "2.16.14", "version": "2.16.35",
"description": "Generic business logic for web-based medical imaging applications", "description": "Generic business logic for web-based medical imaging applications",
"author": "OHIF Core Team", "author": "OHIF Core Team",
"license": "MIT", "license": "MIT",
@@ -33,13 +33,13 @@
"peerDependencies": { "peerDependencies": {
"cornerstone-core": "^2.6.1", "cornerstone-core": "^2.6.1",
"cornerstone-tools": "^6.0.6", "cornerstone-tools": "^6.0.6",
"cornerstone-wado-image-loader": "^4.1.0", "cornerstone-wado-image-loader": "^4.2.1",
"dicom-parser": "^1.8.11" "dicom-parser": "^1.8.11"
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.5.5", "@babel/runtime": "^7.5.5",
"ajv": "^6.10.0", "ajv": "^6.10.0",
"dcmjs": "0.19.7", "dcmjs": "0.29.3",
"dicomweb-client": "^0.8.3", "dicomweb-client": "^0.8.3",
"immer": "9.0.12", "immer": "9.0.12",
"isomorphic-base64": "^1.0.2", "isomorphic-base64": "^1.0.2",
@@ -1,4 +1,5 @@
export default { export default {
TEXT: 'TEXT',
POINT: 'POINT', POINT: 'POINT',
MULTIPOINT: 'MULTIPOINT', MULTIPOINT: 'MULTIPOINT',
POLYLINE: 'POLYLINE', POLYLINE: 'POLYLINE',
@@ -1,6 +1,5 @@
import { ImageSet } from '../../classes'; import { ImageSet } from '../../classes';
import getMeasurements from './utils/getMeasurements'; import getMeasurements from './utils/getMeasurements';
import getReferencedImagesList from './utils/getReferencedImagesList';
import isRehydratable from './utils/isRehydratable'; import isRehydratable from './utils/isRehydratable';
import addMeasurement from './utils/addMeasurement'; import addMeasurement from './utils/addMeasurement';
@@ -8,6 +7,16 @@ const parseSCOORD3D = ({ servicesManager, displaySets }) => {
const { MeasurementService } = servicesManager.services; const { MeasurementService } = servicesManager.services;
const srDisplaySets = displaySets.filter(ds => ds.Modality === 'SR'); const srDisplaySets = displaySets.filter(ds => ds.Modality === 'SR');
const imageDisplaySets = displaySets.filter(
ds =>
ds.Modality !== 'SR' &&
ds.Modality !== 'SEG' &&
ds.Modality !== 'RTSTRUCT'
);
imageDisplaySets.forEach(imageDisplaySet => {
imageDisplaySet.SRLabels = [];
});
srDisplaySets.forEach(srDisplaySet => { srDisplaySets.forEach(srDisplaySet => {
const firstInstance = srDisplaySet.metadata; const firstInstance = srDisplaySet.metadata;
@@ -17,8 +26,7 @@ const parseSCOORD3D = ({ servicesManager, displaySets }) => {
const { ContentSequence } = firstInstance; const { ContentSequence } = firstInstance;
srDisplaySet.referencedImages = getReferencedImagesList(ContentSequence); srDisplaySet.measurements = getMeasurements(ContentSequence);
srDisplaySet.measurements = getMeasurements(ContentSequence, srDisplaySet);
const mappings = MeasurementService.getSourceMappings( const mappings = MeasurementService.getSourceMappings(
'CornerstoneTools', 'CornerstoneTools',
'4' '4'
@@ -28,13 +36,6 @@ const parseSCOORD3D = ({ servicesManager, displaySets }) => {
srDisplaySet.isRehydratable = isRehydratable(srDisplaySet, mappings); srDisplaySet.isRehydratable = isRehydratable(srDisplaySet, mappings);
srDisplaySet.isLoaded = true; srDisplaySet.isLoaded = true;
const imageDisplaySets = displaySets.filter(
ds =>
ds.Modality !== 'SR' &&
ds.Modality !== 'SEG' &&
ds.Modality !== 'RTSTRUCT' &&
ds.Modality !== 'RTDOSE'
);
imageDisplaySets.forEach(imageDisplaySet => { imageDisplaySets.forEach(imageDisplaySet => {
// Check currently added displaySets and add measurements if the sources exist. // Check currently added displaySets and add measurements if the sources exist.
checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, imageDisplaySet); checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, imageDisplaySet);
@@ -127,10 +128,10 @@ const checkIfCanAddMeasurementsToDisplaySet = (
const imageIds = images.map(i => i.getImageId()); const imageIds = images.map(i => i.getImageId());
const SOPInstanceUIDs = images.map(i => i.SOPInstanceUID); const SOPInstanceUIDs = images.map(i => i.SOPInstanceUID);
const colors = new Map();
measurements.forEach(measurement => { measurements.forEach(measurement => {
const { coords } = measurement; const { coords } = measurement;
coords.forEach((coord, index) => {
coords.forEach(coord => {
if (coord.ReferencedSOPSequence !== undefined) { if (coord.ReferencedSOPSequence !== undefined) {
const imageIndex = SOPInstanceUIDs.findIndex( const imageIndex = SOPInstanceUIDs.findIndex(
SOPInstanceUID => SOPInstanceUID =>
@@ -138,8 +139,43 @@ const checkIfCanAddMeasurementsToDisplaySet = (
coord.ReferencedSOPSequence.ReferencedSOPInstanceUID coord.ReferencedSOPSequence.ReferencedSOPInstanceUID
); );
if (imageIndex > -1) { if (imageIndex > -1) {
if (!srDisplaySet.referencedDisplaySets.includes(imageDisplaySet)) {
srDisplaySet.referencedDisplaySets.push(imageDisplaySet);
}
const imageId = imageIds[imageIndex]; const imageId = imageIds[imageIndex];
const imageMetadata = images[imageIndex].getData().metadata; const imageMetadata = images[imageIndex].getData().metadata;
if (coord.GraphicType === 'TEXT') {
const key =
measurement.labels[index].label + measurement.labels[index].value;
let color = colors.get(key);
if (!color) {
// random dark color
color =
'hsla(' + Math.floor(Math.random() * 360) + ', 70%, 30%, 1)';
colors.set(key, color);
}
measurement.labels[index].color = color;
measurement.isSRText = true;
measurement.labels[index].visible = true;
imageDisplaySet.SRLabels.push({
ReferencedSOPInstanceUID:
coord.ReferencedSOPSequence.ReferencedSOPInstanceUID,
labels: measurement.labels[index],
});
if (index === 0) {
addMeasurement(
measurement,
imageId,
imageMetadata,
imageDisplaySet.displaySetInstanceUID
);
}
} else {
addMeasurement( addMeasurement(
measurement, measurement,
imageId, imageId,
@@ -148,6 +184,7 @@ const checkIfCanAddMeasurementsToDisplaySet = (
); );
} }
} }
}
}); });
}); });
}; };
@@ -26,8 +26,10 @@ export default function addMeasurement(
const measurementData = { const measurementData = {
TrackingUniqueIdentifier: measurement.TrackingUniqueIdentifier, TrackingUniqueIdentifier: measurement.TrackingUniqueIdentifier,
TrackingIdentifier: measurement.TrackingIdentifier,
renderableData: {}, renderableData: {},
labels: measurement.labels, labels: measurement.labels,
isSRText: measurement.isSRText,
}; };
measurement.coords.forEach(coord => { measurement.coords.forEach(coord => {
@@ -1,22 +1,14 @@
const getCoordsFromSCOORDOrSCOORD3D = (graphicItem, displaySet) => { const getCoordsFromSCOORDOrSCOORD3D = graphicItem => {
const { ValueType, RelationshipType, GraphicType, GraphicData } = graphicItem; const { ValueType, GraphicType, GraphicData } = graphicItem;
// if (RelationshipType !== RELATIONSHIP_TYPE.INFERRED_FROM) {
// console.warn(
// `Relationshiptype === ${RelationshipType}. Cannot deal with NON TID-1400 SCOORD group with RelationshipType !== "INFERRED FROM."`
// );
// return;
// }
const coords = { ValueType, GraphicType, GraphicData }; const coords = { ValueType, GraphicType, GraphicData };
// ContentSequence has length of 1 as RelationshipType === 'INFERRED FROM'
if (ValueType === 'SCOORD') { if (ValueType === 'SCOORD') {
const { ReferencedSOPSequence } = graphicItem.ContentSequence; const { ReferencedSOPSequence } = graphicItem.ContentSequence;
coords.ReferencedSOPSequence = ReferencedSOPSequence; coords.ReferencedSOPSequence = ReferencedSOPSequence;
} else if (ValueType === 'SCOORD3D') { } else if (ValueType === 'SCOORD3D') {
if (graphicItem.ReferencedFrameOfReferenceUID) { if (graphicItem.ReferencedFrameOfReferenceUID) {
coords.ReferencedFrameOfReferenceSequence = graphicItem.ReferencedFrameOfReferenceUID; coords.ReferencedFrameOfReferenceSequence =
graphicItem.ReferencedFrameOfReferenceUID;
} else if (graphicItem.ContentSequence) { } else if (graphicItem.ContentSequence) {
const { const {
ReferencedFrameOfReferenceSequence, ReferencedFrameOfReferenceSequence,
@@ -3,10 +3,7 @@ import getSequenceAsArray from './getSequenceAsArray';
import getMergedContentSequencesByTrackingUniqueIdentifiers from './getMergedContentSequencesByTrackingUniqueIdentifiers'; import getMergedContentSequencesByTrackingUniqueIdentifiers from './getMergedContentSequencesByTrackingUniqueIdentifiers';
import processMeasurement from './processMeasurement'; import processMeasurement from './processMeasurement';
const getMeasurements = ( const getMeasurements = ImagingMeasurementReportContentSequence => {
ImagingMeasurementReportContentSequence,
displaySet
) => {
const ImagingMeasurements = ImagingMeasurementReportContentSequence.find( const ImagingMeasurements = ImagingMeasurementReportContentSequence.find(
item => item =>
item.ConceptNameCodeSequence.CodeValue === item.ConceptNameCodeSequence.CodeValue ===
@@ -21,25 +18,19 @@ const getMeasurements = (
CodeNameCodeSequenceValues.MeasurementGroup CodeNameCodeSequenceValues.MeasurementGroup
); );
const mergedContentSequencesByTrackingUniqueIdentifiers = getMergedContentSequencesByTrackingUniqueIdentifiers( /* const mergedContentSequencesByTrackingUniqueIdentifiers = getMergedContentSequencesByTrackingUniqueIdentifiers(
MeasurementGroups MeasurementGroups
); );*/
let measurements = []; let measurements = [];
Object.keys(mergedContentSequencesByTrackingUniqueIdentifiers).forEach( MeasurementGroups.forEach(MeasurementGroup => {
trackingUniqueIdentifier => { const contentSequence = MeasurementGroup.ContentSequence;
const mergedContentSequence = const measurement = processMeasurement(contentSequence);
mergedContentSequencesByTrackingUniqueIdentifiers[
trackingUniqueIdentifier
];
const measurement = processMeasurement(mergedContentSequence, displaySet);
if (measurement) { if (measurement) {
measurements.push(measurement); measurements.push(measurement);
} }
} });
);
return measurements; return measurements;
}; };
@@ -1,43 +0,0 @@
import getSequenceAsArray from './getSequenceAsArray';
import { CodeNameCodeSequenceValues } from '../enums';
const getReferencedImagesList = ImagingMeasurementReportContentSequence => {
const referencedImages = [];
const ImageLibrary = ImagingMeasurementReportContentSequence.find(
item =>
item.ConceptNameCodeSequence.CodeValue ===
CodeNameCodeSequenceValues.ImageLibrary
);
if (!ImageLibrary.ContentSequence) {
return referencedImages;
}
const ImageLibraryGroup = getSequenceAsArray(
ImageLibrary.ContentSequence
).find(
item =>
item.ConceptNameCodeSequence.CodeValue ===
CodeNameCodeSequenceValues.ImageLibraryGroup
);
getSequenceAsArray(ImageLibraryGroup.ContentSequence).forEach(item => {
const { ReferencedSOPSequence } = item;
if (ReferencedSOPSequence) {
const {
ReferencedSOPClassUID,
ReferencedSOPInstanceUID,
} = ReferencedSOPSequence;
referencedImages.push({
ReferencedSOPClassUID,
ReferencedSOPInstanceUID,
});
}
});
return referencedImages;
};
export default getReferencedImagesList;
@@ -57,6 +57,10 @@ const getRenderableData = (
// https://dicom.innolitics.com/ciods/procedure-log/sr-document-content/00700023 // https://dicom.innolitics.com/ciods/procedure-log/sr-document-content/00700023
switch (GraphicType) { switch (GraphicType) {
case SCOORD_TYPES.TEXT:
renderableData = [{ x: GraphicData[0], y: GraphicData[1] }];
break;
case SCOORD_TYPES.POINT: case SCOORD_TYPES.POINT:
renderableData = []; renderableData = [];
@@ -1,16 +1,16 @@
import processTID1410Measurement from './processTID1410Measurement'; import processTID1410Measurement from './processTID1410Measurement';
import processNonGeometricallyDefinedMeasurement from './processNonGeometricallyDefinedMeasurement'; import processNonGeometricallyDefinedMeasurement from './processNonGeometricallyDefinedMeasurement';
const processMeasurement = (mergedContentSequence, displaySet) => { const processMeasurement = contentSequence => {
if ( if (
mergedContentSequence.some( contentSequence.some(
group => group.ValueType === 'SCOORD' || group.ValueType === 'SCOORD3D' group => group.ValueType === 'SCOORD' || group.ValueType === 'SCOORD3D'
) )
) { ) {
return processTID1410Measurement(mergedContentSequence, displaySet); return processTID1410Measurement(contentSequence);
} }
return processNonGeometricallyDefinedMeasurement(mergedContentSequence); return processNonGeometricallyDefinedMeasurement(contentSequence);
}; };
export default processMeasurement; export default processMeasurement;
@@ -1,31 +1,40 @@
import getLabelFromMeasuredValueSequence from './getLabelFromMeasuredValueSequence'; import getLabelFromMeasuredValueSequence from './getLabelFromMeasuredValueSequence';
import getCoordsFromSCOORDOrSCOORD3D from './getCoordsFromSCOORDOrSCOORD3D'; import getCoordsFromSCOORDOrSCOORD3D from './getCoordsFromSCOORDOrSCOORD3D';
import { CodeNameCodeSequenceValues, CodingSchemeDesignators } from '../enums'; import { CodeNameCodeSequenceValues, CodingSchemeDesignators } from '../enums';
import SCOORD_TYPES from '../constants/scoordTypes';
const CORNERSTONE_FREETEXT_CODE_VALUE = 'CORNERSTONEFREETEXT'; const CORNERSTONE_FREETEXT_CODE_VALUE = 'CORNERSTONEFREETEXT';
const processNonGeometricallyDefinedMeasurement = mergedContentSequence => { const processNonGeometricallyDefinedMeasurement = contentSequence => {
const NUMContentItems = mergedContentSequence.filter( const NUMContentItems = contentSequence.filter(
group => group.ValueType === 'NUM' group => group.ValueType === 'NUM'
); );
const UIDREFContentItem = mergedContentSequence.find( const CODEContentItems = contentSequence.filter(
group => group.ValueType === 'CODE'
);
const UIDREFContentItem = contentSequence.find(
group => group.ValueType === 'UIDREF' group => group.ValueType === 'UIDREF'
); );
const TrackingIdentifierContentItem = mergedContentSequence.find( const IMAGEContentItem = contentSequence.find(
group => group.ValueType === 'IMAGE'
);
const TrackingIdentifierContentItem = contentSequence.find(
item => item =>
item.ConceptNameCodeSequence.CodeValue === item.ConceptNameCodeSequence.CodeValue ===
CodeNameCodeSequenceValues.TrackingIdentifier CodeNameCodeSequenceValues.TrackingIdentifier
); );
const Finding = mergedContentSequence.find( const Finding = contentSequence.find(
item => item =>
item.ConceptNameCodeSequence.CodeValue === item.ConceptNameCodeSequence.CodeValue ===
CodeNameCodeSequenceValues.Finding CodeNameCodeSequenceValues.Finding
); );
const FindingSites = mergedContentSequence.filter( const FindingSites = contentSequence.filter(
item => item =>
item.ConceptNameCodeSequence.CodingSchemeDesignator === item.ConceptNameCodeSequence.CodingSchemeDesignator ===
CodingSchemeDesignators.SRT && CodingSchemeDesignators.SRT &&
@@ -111,6 +120,37 @@ const processNonGeometricallyDefinedMeasurement = mergedContentSequence => {
} }
}); });
if (NUMContentItems.length === 0 && IMAGEContentItem) {
CODEContentItems.forEach(item => {
const { ConceptCodeSequence, ConceptNameCodeSequence } = item;
if (!ConceptCodeSequence || !ConceptNameCodeSequence) {
console.warn(`Graphic missing, skipping annotation.`);
return;
}
const GraphicData = [0, 0];
const GraphicType = SCOORD_TYPES.TEXT;
const { ValueType } = item;
const ReferencedSOPSequence = IMAGEContentItem.ReferencedSOPSequence;
const coord = {
ValueType,
GraphicType,
GraphicData,
ReferencedSOPSequence,
};
measurement.coords.push(coord);
measurement.labels.push({
label: ConceptNameCodeSequence.CodeMeaning,
labelCodingSchemeDesignator:
ConceptNameCodeSequence.CodingSchemeDesignator,
value: ConceptCodeSequence.CodeMeaning,
valueCodingSchemeDesignator: ConceptCodeSequence.CodingSchemeDesignator,
});
});
}
return measurement; return measurement;
}; };
@@ -5,14 +5,14 @@ import { RELATIONSHIP_TYPE, CodeNameCodeSequenceValues } from '../enums';
/** /**
* TID 1410 Planar ROI Measurements and Qualitative Evaluations. * TID 1410 Planar ROI Measurements and Qualitative Evaluations.
* *
* @param {*} mergedContentSequence * @param {*} contentSequence
* @returns * @returns
*/ */
const processTID1410Measurement = (mergedContentSequence, displaySet) => { const processTID1410Measurement = contentSequence => {
// Need to deal with TID 1410 style measurements, which will have a SCOORD or SCOORD3D at the top level, // Need to deal with TID 1410 style measurements, which will have a SCOORD or SCOORD3D at the top level,
// And non-geometric representations where each NUM has "INFERRED FROM" SCOORD/SCOORD3D // And non-geometric representations where each NUM has "INFERRED FROM" SCOORD/SCOORD3D
const graphicItem = mergedContentSequence.find( const graphicItem = contentSequence.find(
group => group.ValueType === 'SCOORD' || group.ValueType === 'SCOORD3D' group => group.ValueType === 'SCOORD' || group.ValueType === 'SCOORD3D'
); );
@@ -23,24 +23,24 @@ const processTID1410Measurement = (mergedContentSequence, displaySet) => {
return; return;
} }
const UIDREFContentItem = mergedContentSequence.find( const UIDREFContentItem = contentSequence.find(
group => group.ValueType === 'UIDREF' group => group.ValueType === 'UIDREF'
); );
const TrackingIdentifierContentItem = mergedContentSequence.find( const TrackingIdentifierContentItem = contentSequence.find(
item => item =>
item.ConceptNameCodeSequence.CodeValue === item.ConceptNameCodeSequence.CodeValue ===
CodeNameCodeSequenceValues.TrackingIdentifier CodeNameCodeSequenceValues.TrackingIdentifier
); );
const NUMContentItems = mergedContentSequence.filter( const NUMContentItems = contentSequence.filter(
group => group.ValueType === 'NUM' group => group.ValueType === 'NUM'
); );
const measurement = { const measurement = {
loaded: false, loaded: false,
labels: [], labels: [],
coords: [getCoordsFromSCOORDOrSCOORD3D(graphicItem, displaySet)], coords: [getCoordsFromSCOORDOrSCOORD3D(graphicItem)],
TrackingUniqueIdentifier: UIDREFContentItem.UID, TrackingUniqueIdentifier: UIDREFContentItem.UID,
TrackingIdentifier: TrackingIdentifierContentItem.TextValue, TrackingIdentifier: TrackingIdentifierContentItem.TextValue,
}; };
@@ -21,16 +21,32 @@ const parseDicomStructuredReport = (
displaySets, displaySets,
external external
) => { ) => {
if (external && external.servicesManager) {
parseSCOORD3D({ servicesManager: external.servicesManager, displaySets });
}
// Get the dicom data as an Object // Get the dicom data as an Object
const dicomData = dcmjs.data.DicomMessage.readFile(part10SRArrayBuffer); const dicomData = dcmjs.data.DicomMessage.readFile(part10SRArrayBuffer);
const dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset( const dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset(
dicomData.dict dicomData.dict
); );
const {
LoggerService,
UINotificationService,
} = external.servicesManager.services;
if (external && external.servicesManager) {
try {
parseSCOORD3D({ servicesManager: external.servicesManager, displaySets });
} catch (error) {
const seriesDescription = dataset.SeriesDescription || '';
LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: `Failed to parse ${seriesDescription} SR display set`,
message: error.message,
type: 'error',
autoClose: false,
});
return;
}
}
const { MeasurementReport } = dcmjs.adapters.Cornerstone; const { MeasurementReport } = dcmjs.adapters.Cornerstone;
let storedMeasurementByToolType; let storedMeasurementByToolType;
@@ -38,11 +54,12 @@ const parseDicomStructuredReport = (
storedMeasurementByToolType = MeasurementReport.generateToolState(dataset); storedMeasurementByToolType = MeasurementReport.generateToolState(dataset);
} catch (error) { } catch (error) {
const seriesDescription = dataset.SeriesDescription || ''; const seriesDescription = dataset.SeriesDescription || '';
LogManager.publish(LogManager.EVENTS.OnLog, { LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: `Failed to parse ${seriesDescription} measurement report`, title: `Failed to parse ${seriesDescription} measurement report`,
type: 'warning', message: error.message,
message: error.message || '', type: 'error',
notify: true, autoClose: false,
}); });
return; return;
} }
+2 -1
View File
@@ -67,12 +67,13 @@ export class HotkeysManager {
UINotificationService, UINotificationService,
LoggerService, LoggerService,
} = this._servicesManager.services; } = this._servicesManager.services;
const message = 'Erro while setting hotkeys'; const message = 'Error while setting hotkeys';
LoggerService.error({ error, message }); LoggerService.error({ error, message });
UINotificationService.show({ UINotificationService.show({
title: 'Hotkeys Manager', title: 'Hotkeys Manager',
message, message,
type: 'error', type: 'error',
autoClose: false,
}); });
} }
} }
@@ -401,7 +401,7 @@ class StackLoadingListener extends BaseLoadingListener {
const totalFramesCount = this.stack.imageIds.length; const totalFramesCount = this.stack.imageIds.length;
const loadedFramesCount = this.loadedCount; const loadedFramesCount = this.loadedCount;
const loadingFramesCount = totalFramesCount - loadedFramesCount; const loadingFramesCount = totalFramesCount - loadedFramesCount;
const percentComplete = Math.round( const percentComplete = Math.ceil(
(loadedFramesCount / totalFramesCount) * 100 (loadedFramesCount / totalFramesCount) * 100
); );
const progressId = this._getProgressId(); const progressId = this._getProgressId();
@@ -469,8 +469,8 @@ class StudyLoadingListener {
// TODO: Make this work for plugins // TODO: Make this work for plugins
if (!stack) { if (!stack) {
console.warn('Skipping adding displaySet to StudyLoadingListener'); //console.warn('Skipping adding displaySet to StudyLoadingListener');
console.warn(displaySet); //console.warn(displaySet);
return; return;
} }
@@ -3,12 +3,12 @@ import DICOMWeb from './../../DICOMWeb';
import ImageSet from './../ImageSet'; import ImageSet from './../ImageSet';
import { InstanceMetadata } from './InstanceMetadata'; import { InstanceMetadata } from './InstanceMetadata';
import { Metadata } from './Metadata'; import { Metadata } from './Metadata';
import OHIFError from '../OHIFError';
import { SeriesMetadata } from './SeriesMetadata'; import { SeriesMetadata } from './SeriesMetadata';
// - createStacks // - createStacks
import { api } from 'dicomweb-client'; import { api } from 'dicomweb-client';
// - createStacks // - createStacks
import { isImage } from '../../utils/isImage'; import { isImage } from '../../utils/isImage';
import { naturalizeSOPClassUID } from '../../utils/naturalizeSOPClassUID';
import { import {
isDisplaySetReconstructable, isDisplaySetReconstructable,
isSpacingUniform, isSpacingUniform,
@@ -169,8 +169,12 @@ class StudyMetadata extends Metadata {
!isImage(instance.getTagValue('SOPClassUID')) && !isImage(instance.getTagValue('SOPClassUID')) &&
!instance.getTagValue('Rows') !instance.getTagValue('Rows')
) { ) {
// we set an empty display and we add a isModalitySupported variable to // we set an empty display and we add a isSOPClassUIDSupported variable to
// print a warning that the modality is not supported in the thumbnail. // print a warning that the series is not supported in the thumbnail.
// SOPClassUIDNaturalized is human readable name, since for non image series,
// we could have a mismatch between the SOPClassUID and the Modality.
// For example, in the Parametric map IOD Modality is expected to match
// the value for the series used to generate Parametric map, and there is no "PM" modality.
const displaySet = new ImageSet([]); const displaySet = new ImageSet([]);
const seriesData = series.getData(); const seriesData = series.getData();
displaySet.setAttributes({ displaySet.setAttributes({
@@ -188,7 +192,10 @@ class StudyMetadata extends Metadata {
InstanceNumber: instance.getTagValue('InstanceNumber'), // Include the instance number InstanceNumber: instance.getTagValue('InstanceNumber'), // Include the instance number
AcquisitionDatetime: instance.getTagValue('AcquisitionDateTime'), // Include the acquisition datetime AcquisitionDatetime: instance.getTagValue('AcquisitionDateTime'), // Include the acquisition datetime
isReconstructable: false, isReconstructable: false,
isModalitySupported: false, isSOPClassUIDSupported: false,
SOPClassUIDNaturalized: naturalizeSOPClassUID(
instance.getTagValue('SOPClassUID')
),
metadata: instance.getData().metadata, metadata: instance.getData().metadata,
}); });
@@ -268,6 +275,8 @@ class StudyMetadata extends Metadata {
const otherDisplaySets = allDisplaySets.filter( const otherDisplaySets = allDisplaySets.filter(
ds => ds =>
ds &&
derivatedDisplaySet &&
ds.displaySetInstanceUID !== derivatedDisplaySet.displaySetInstanceUID ds.displaySetInstanceUID !== derivatedDisplaySet.displaySetInstanceUID
); );
@@ -333,10 +342,38 @@ class StudyMetadata extends Metadata {
if (referencedSeriesInstanceUID) { if (referencedSeriesInstanceUID) {
filteredDerivedDisplaySets = filteredDerivedDisplaySets.filter( filteredDerivedDisplaySets = filteredDerivedDisplaySets.filter(
displaySet => { displaySet => {
return ( const referencedDisplaySet = StudyMetadata.getReferencedDisplaySet(
StudyMetadata.getReferencedDisplaySet(displaySet, [this]) displaySet,
.SeriesInstanceUID === referencedSeriesInstanceUID [this]
); );
if (referencedDisplaySet) {
return (
referencedDisplaySet.SeriesInstanceUID ===
referencedSeriesInstanceUID
);
} else {
if (
!displaySet.referencedDisplaySets ||
displaySet.referencedDisplaySets.length === 0
) {
return false;
}
const filteredReferencedDisplaySets = displaySet.referencedDisplaySets.filter(
referencedDisplaySet =>
referencedDisplaySet.SeriesInstanceUID ===
referencedSeriesInstanceUID
);
if (
filteredReferencedDisplaySets &&
filteredReferencedDisplaySets.length !== 0
) {
return true;
}
return false;
}
} }
); );
} }
@@ -923,7 +960,7 @@ const makeDisplaySet = (series, instances) => {
: displayReconstructableInfo.reconstructionIssues; : displayReconstructableInfo.reconstructionIssues;
} }
imageSet.isModalitySupported = true; imageSet.isSOPClassUIDSupported = true;
return imageSet; return imageSet;
}; };
@@ -6,7 +6,8 @@ export const dicomSRDisplayTool = {
options: { options: {
measurementTable: { measurementTable: {
displayFunction: data => { displayFunction: data => {
return `(SR) ${data.lesionNamingNumber || return `(SR) ${data.TrackingIdentifier ||
data.lesionNamingNumber ||
data.measurementNumber || data.measurementNumber ||
data.text || data.text ||
''}`; ''}`;
@@ -420,6 +420,10 @@ class MeasurementService {
throw new Error('No source definition provided.'); throw new Error('No source definition provided.');
} }
if (definition == 'stack' || definition == 'stackPrefetch') {
return;
}
const sourceInfo = this._getSourceInfo(source); const sourceInfo = this._getSourceInfo(source);
if (!this._sourceHasMappings(source)) { if (!this._sourceHasMappings(source)) {
@@ -19,17 +19,4 @@ describe('retrieveStudyMetadata.js', () => {
expect(callWithNoStudyInstanceUID).toThrow(Error); expect(callWithNoStudyInstanceUID).toThrow(Error);
}); });
it('caches and returns the same promise for identical studyInstanceUIDs', () => {
const firstPromise = retrieveStudyMetadata(
fakeDicomWebServer,
'fake-study-instance-uid'
);
const secondPromise = retrieveStudyMetadata(
fakeDicomWebServer,
'fake-study-instance-uid'
);
expect(firstPromise).toBe(secondPromise);
});
}); });
@@ -21,6 +21,7 @@ const getReferencedSeriesSequence = instance => {
const referencedInstanceSequenceRaw = referencedSeries['0008114A']; const referencedInstanceSequenceRaw = referencedSeries['0008114A'];
const referencedInstanceSequence = []; const referencedInstanceSequence = [];
if (referencedInstanceSequenceRaw) {
referencedInstanceSequenceRaw.Value.forEach(referencedInstance => { referencedInstanceSequenceRaw.Value.forEach(referencedInstance => {
referencedInstanceSequence.push({ referencedInstanceSequence.push({
referencedSOPClassUID: DICOMWeb.getString( referencedSOPClassUID: DICOMWeb.getString(
@@ -31,6 +32,7 @@ const getReferencedSeriesSequence = instance => {
), ),
}); });
}); });
}
referencedSeriesSequence.push({ referencedSeriesSequence.push({
referencedSeriesInstanceUID, referencedSeriesInstanceUID,
@@ -102,6 +102,35 @@ async function makeSOPInstance(server, study, instance) {
SOPInstanceUID, SOPInstanceUID,
} = naturalizedInstance; } = naturalizedInstance;
const validate = string => {
let rgx = /[^.0-9]+/g;
return string.match(rgx);
};
if (StudyInstanceUID === undefined || validate(StudyInstanceUID)) {
const error =
'makeSOPInstance: StudyInstanceUID is not conforming with the UID (DICOM UI VR) character repertoire, skipping SOPInstance.';
console.error(error);
return;
}
if (SeriesInstanceUID === undefined || validate(SeriesInstanceUID)) {
const error =
'makeSOPInstance: SeriesInstanceUID is not conforming with the UID (DICOM UI VR) character repertoire, skipping SOPInstance.';
console.error(error);
return;
}
if (SOPInstanceUID === undefined || validate(SOPInstanceUID)) {
const error =
'makeSOPInstance: SOPInstanceUID is not conforming with the UID (DICOM UI VR) character repertoire, skipping SOPInstance.';
console.error(error);
return;
}
let series = study.seriesMap[SeriesInstanceUID]; let series = study.seriesMap[SeriesInstanceUID];
if (!series) { if (!series) {
+2 -2
View File
@@ -25,7 +25,7 @@ function createAndAddStack(stackMap, study, displaySet, stackUpdatedCallbacks) {
const imageIds = []; const imageIds = [];
let imageId; let imageId;
displaySet.images.forEach((instance, imageIndex) => { images.forEach((instance, imageIndex) => {
const image = instance.getData(); const image = instance.getData();
const metaData = { const metaData = {
instance: image, // in this context, instance will be the data of the InstanceMetadata object... instance: image, // in this context, instance will be the data of the InstanceMetadata object...
@@ -35,7 +35,7 @@ function createAndAddStack(stackMap, study, displaySet, stackUpdatedCallbacks) {
imageIndex: imageIndex + 1, imageIndex: imageIndex + 1,
}; };
const naturalizedInstance = instance.getData().metadata; const naturalizedInstance = image.metadata;
const NumberOfFrames = naturalizedInstance.NumberOfFrames; const NumberOfFrames = naturalizedInstance.NumberOfFrames;
if (NumberOfFrames > 1) { if (NumberOfFrames > 1) {
@@ -49,7 +49,12 @@ import studyMetadataManager from './studyMetadataManager';
* @param {object} snackbar * @param {object} snackbar
* @returns void * @returns void
*/ */
async function loadAndCacheDerivedDisplaySets(referencedDisplaySet, studies, logger, snackbar) { async function loadAndCacheDerivedDisplaySets(
referencedDisplaySet,
studies,
logger,
snackbar
) {
const { StudyInstanceUID, SeriesInstanceUID } = referencedDisplaySet; const { StudyInstanceUID, SeriesInstanceUID } = referencedDisplaySet;
const promises = []; const promises = [];
const studyMetadata = studyMetadataManager.get(StudyInstanceUID); const studyMetadata = studyMetadataManager.get(StudyInstanceUID);
@@ -80,7 +85,8 @@ async function loadAndCacheDerivedDisplaySets(referencedDisplaySet, studies, log
}); });
// For each type, see if any are loaded, if not load the most recent. // For each type, see if any are loaded, if not load the most recent.
await Promise.all(Object.keys(displaySetsPerModality).map(async (key) => { await Promise.all(
Object.keys(displaySetsPerModality).map(async key => {
const displaySets = displaySetsPerModality[key]; const displaySets = displaySetsPerModality[key];
const isLoaded = displaySets.some(displaySet => displaySet.isLoaded); const isLoaded = displaySets.some(displaySet => displaySet.isLoaded);
@@ -107,9 +113,66 @@ async function loadAndCacheDerivedDisplaySets(referencedDisplaySet, studies, log
}); });
try { try {
if (recentDisplaySet.hasOwnProperty('getSourceDisplaySet') && if (
typeof recentDisplaySet.getSourceDisplaySet === 'function') { recentDisplaySet.hasOwnProperty('getSourceDisplaySet') &&
typeof recentDisplaySet.getSourceDisplaySet === 'function'
) {
if (recentDisplaySet.Modality === 'SEG' && logger) {
const onDisplaySetLoadFailureHandler = error => {
const message =
error.message.includes('orthogonal') ||
error.message.includes('oblique')
? 'The segmentation has been detected as non coplanar,\
If you really think it is coplanar,\
please adjust the tolerance in the segmentation panel settings (at your own peril!)'
: error.message;
logger.error({ error, message });
snackbar.show({
title: 'DICOM Segmentation Loader',
message,
type: 'error',
autoClose: false,
});
};
let activatedLabelmapIndex = -1;
while (activatedLabelmapIndex == -1) {
const {
referencedDisplaySet,
activatedLabelmapPromise,
} = await recentDisplaySet.getSourceDisplaySet(
studies,
true,
onDisplaySetLoadFailureHandler
);
activatedLabelmapIndex = await activatedLabelmapPromise;
const selectionFired = new CustomEvent(
'extensiondicomsegmentationsegselected',
{
detail: { activatedLabelmapIndex: activatedLabelmapIndex },
}
);
document.dispatchEvent(selectionFired);
const lastDateTime = Number(
`${recentDisplaySet.SeriesDate}${recentDisplaySet.SeriesTime}`
);
recentDateTime = 0;
displaySets.forEach(displaySet => {
const dateTime = Number(
`${displaySet.SeriesDate}${displaySet.SeriesTime}`
);
if (dateTime > recentDateTime && dateTime < lastDateTime) {
recentDateTime = dateTime;
recentDisplaySet = displaySet;
}
});
}
} else {
await recentDisplaySet.getSourceDisplaySet(studies); await recentDisplaySet.getSourceDisplaySet(studies);
}
} else { } else {
await recentDisplaySet.load(referencedDisplaySet, studies); await recentDisplaySet.load(referencedDisplaySet, studies);
} }
@@ -125,7 +188,8 @@ async function loadAndCacheDerivedDisplaySets(referencedDisplaySet, studies, log
autoClose: false, autoClose: false,
}); });
} }
})); })
);
/* /*
* TODO: Improve the way we notify parts of the app * TODO: Improve the way we notify parts of the app
@@ -134,6 +198,6 @@ async function loadAndCacheDerivedDisplaySets(referencedDisplaySet, studies, log
*/ */
const event = new CustomEvent('deriveddisplaysetsloadedandcached'); const event = new CustomEvent('deriveddisplaysetsloadedandcached');
document.dispatchEvent(event); document.dispatchEvent(event);
}; }
export default loadAndCacheDerivedDisplaySets; export default loadAndCacheDerivedDisplaySets;
@@ -0,0 +1,200 @@
import { sopClassDictionary } from './sopClassDictionary';
import { isImage } from './isImage';
/**
* Naturalize SOP Class UID which do not have image data
* @param {string} SOPClassUID - SOP Class UID to be converted
* @returns {string} - human readable name
*/
export const naturalizeSOPClassUID = SOPClassUID => {
let naturalizedName = '';
if (!SOPClassUID) return naturalizedName;
if (!isImage) return naturalizedName;
if (sopClassDictionary.MRSpectroscopyStorage === SOPClassUID) {
naturalizedName = 'MRSpectroscopy';
} else if (sopClassDictionary.EnhancedUSVolumeStorage === SOPClassUID) {
naturalizedName = 'EnhancedUSVolume';
} else if (sopClassDictionary.Sop12LeadECGWaveformStorage === SOPClassUID) {
naturalizedName = 'Sop12LeadECGWaveform';
} else if (sopClassDictionary.GeneralECGWaveformStorage === SOPClassUID) {
naturalizedName = 'GeneralECGWaveform';
} else if (sopClassDictionary.AmbulatoryECGWaveformStorage === SOPClassUID) {
naturalizedName = 'AECAmbulatoryECGWaveformGW';
} else if (sopClassDictionary.HemodynamicWaveformStorage === SOPClassUID) {
naturalizedName = 'HemodynamicWaveform';
} else if (
sopClassDictionary.CardiacElectrophysiologyWaveformStorage === SOPClassUID
) {
naturalizedName = 'CardiacElectrophysiologyWaveform';
} else if (
sopClassDictionary.BasicVoiceAudioWaveformStorage === SOPClassUID
) {
naturalizedName = 'BasicVoiceAudioWaveform';
} else if (sopClassDictionary.GeneralAudioWaveformStorage === SOPClassUID) {
naturalizedName = 'GGeneralAudioWaveformAW';
} else if (sopClassDictionary.ArterialPulseWaveformStorage === SOPClassUID) {
naturalizedName = 'APArterialPulseWaveformW';
} else if (sopClassDictionary.RespiratoryWaveformStorage === SOPClassUID) {
naturalizedName = 'RespiratoryWaveform';
} else if (
sopClassDictionary.GrayscaleSoftcopyPresentationStateStorage === SOPClassUID
) {
naturalizedName = 'GrayscaleSoftcopyPresentationState';
} else if (
sopClassDictionary.ColorSoftcopyPresentationStateStorage === SOPClassUID
) {
naturalizedName = 'ColorSoftcopyPresentationState';
} else if (
sopClassDictionary.PseudoColorSoftcopyPresentationStateStorage ===
SOPClassUID
) {
naturalizedName = 'PseudoColorSoftcopyPresentationState';
} else if (
sopClassDictionary.BlendingSoftcopyPresentationStateStorage === SOPClassUID
) {
naturalizedName = 'BlendingSoftcopyPresentationState';
} else if (
sopClassDictionary.XAXRFGrayscaleSoftcopyPresentationStateStorage ===
SOPClassUID
) {
naturalizedName = 'XAXRFGrayscaleSoftcopyPresentationState';
} else if (sopClassDictionary.RawDataStorage === SOPClassUID) {
naturalizedName = 'RawData';
} else if (sopClassDictionary.SpatialRegistrationStorage === SOPClassUID) {
naturalizedName = 'SpatialRegistration';
} else if (sopClassDictionary.SpatialFiducialsStorage === SOPClassUID) {
naturalizedName = 'SpatialFiducials';
} else if (
sopClassDictionary.DeformableSpatialRegistrationStorage === SOPClassUID
) {
naturalizedName = 'DeformableSpatialRegistration';
} else if (sopClassDictionary.SegmentationStorage === SOPClassUID) {
naturalizedName = 'SEG';
} else if (sopClassDictionary.SurfaceSegmentationStorage === SOPClassUID) {
naturalizedName = 'SurfaceSEG';
} else if (sopClassDictionary.RealWorldValueMappingStorage === SOPClassUID) {
naturalizedName = 'RealWorldValueMapping';
} else if (sopClassDictionary.SurfaceScanMeshStorage === SOPClassUID) {
naturalizedName = 'SurfaceScanMesh';
} else if (sopClassDictionary.SurfaceScanPointCloudStorage === SOPClassUID) {
naturalizedName = 'SurfaceScanPointCloud';
} else if (
sopClassDictionary.StereometricRelationshipStorage === SOPClassUID
) {
naturalizedName = 'StereometricRelationship';
} else if (sopClassDictionary.LensometryMeasurementsStorage === SOPClassUID) {
naturalizedName = 'LensometryMeasurements';
} else if (
sopClassDictionary.AutorefractionMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'AutorefractionMeasurements';
} else if (
sopClassDictionary.KeratometryMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'KeratometryMeasurements';
} else if (
sopClassDictionary.SubjectiveRefractionMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'SubjectiveRefractionMeasurements';
} else if (
sopClassDictionary.VisualAcuityMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'VisualAcuityMeasurements';
} else if (
sopClassDictionary.SpectaclePrescriptionReportStorage === SOPClassUID
) {
naturalizedName = 'SpectaclePrescriptionReport';
} else if (
sopClassDictionary.OphthalmicAxialMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'OphthalmicAxialMeasurements';
} else if (
sopClassDictionary.IntraocularLensCalculationsStorage === SOPClassUID
) {
naturalizedName = 'IntraocularLensCalculations';
} else if (
sopClassDictionary.MacularGridThicknessandVolumeReport === SOPClassUID
) {
naturalizedName = 'MacularGridThicknessandVolume';
} else if (
sopClassDictionary.OphthalmicVisualFieldStaticPerimetryMeasurementsStorage ===
SOPClassUID
) {
naturalizedName = 'OphthalmicVisualFieldStaticPerimetryMeasurements';
} else if (sopClassDictionary.OphthalmicThicknessMapStorage === SOPClassUID) {
naturalizedName = 'OphthalmicThicknessMap';
} else if (sopClassDictionary.CornealTopographyMapStorage === SOPClassUID) {
naturalizedName = 'CornealTopographyMap';
} else if (sopClassDictionary.BasicTextSR === SOPClassUID) {
naturalizedName = 'BasicTextSR';
} else if (sopClassDictionary.EnhancedSR === SOPClassUID) {
naturalizedName = 'EnhancedSR';
} else if (sopClassDictionary.ComprehensiveSR === SOPClassUID) {
naturalizedName = 'ComprehensiveSR';
} else if (sopClassDictionary.Comprehensive3DSR === SOPClassUID) {
naturalizedName = 'Comprehensive3DSR';
} else if (sopClassDictionary.ProcedureLog === SOPClassUID) {
naturalizedName = 'ProcedureLog';
} else if (sopClassDictionary.MammographyCADSR === SOPClassUID) {
naturalizedName = 'MammographyCADSR';
} else if (sopClassDictionary.KeyObjectSelection === SOPClassUID) {
naturalizedName = 'KeyObject';
} else if (sopClassDictionary.ChestCADSR === SOPClassUID) {
naturalizedName = 'ChestCADSR';
} else if (sopClassDictionary.XRayRadiationDoseSR === SOPClassUID) {
naturalizedName = 'XRayRadiationDoseSR';
} else if (
sopClassDictionary.RadiopharmaceuticalRadiationDoseSR === SOPClassUID
) {
naturalizedName = 'RadiopharmaceuticalRadiationDoseSR';
} else if (sopClassDictionary.ColonCADSR === SOPClassUID) {
naturalizedName = 'ColonCADSR';
} else if (
sopClassDictionary.ImplantationPlanSRDocumentStorage === SOPClassUID
) {
naturalizedName = 'ImplantationPlanSRDocument';
} else if (sopClassDictionary.EncapsulatedPDFStorage === SOPClassUID) {
naturalizedName = 'EncapsulatedPDF';
} else if (sopClassDictionary.EncapsulatedCDAStorage === SOPClassUID) {
naturalizedName = 'EncapsulatedCDA';
} else if (sopClassDictionary.BasicStructuredDisplayStorage === SOPClassUID) {
naturalizedName = 'BasicStructuredDisplay';
} else if (sopClassDictionary.RTDoseStorage === SOPClassUID) {
naturalizedName = 'RTDose';
} else if (sopClassDictionary.RTStructureSetStorage === SOPClassUID) {
naturalizedName = 'RTStructureSet';
} else if (sopClassDictionary.RTBeamsTreatmentRecordStorage === SOPClassUID) {
naturalizedName = 'RTBeamsTreatmentRecord';
} else if (sopClassDictionary.RTPlanStorage === SOPClassUID) {
naturalizedName = 'RTPlan';
} else if (
sopClassDictionary.RTBrachyTreatmentRecordStorage === SOPClassUID
) {
naturalizedName = 'RTBrachyTreatmentRecord';
} else if (
sopClassDictionary.RTTreatmentSummaryRecordStorage === SOPClassUID
) {
naturalizedName = 'RTTreatmentSummaryRecord';
} else if (sopClassDictionary.RTIonPlanStorage === SOPClassUID) {
naturalizedName = 'RTIonPlan';
} else if (
sopClassDictionary.RTIonBeamsTreatmentRecordStorage === SOPClassUID
) {
naturalizedName = 'RTIonBeamsTreatmentRecord';
} else if (
sopClassDictionary.RTBeamsDeliveryInstructionStorage === SOPClassUID
) {
naturalizedName = 'RTBeamsDeliveryInstruction';
} else if (sopClassDictionary.GenericImplantTemplateStorage === SOPClassUID) {
naturalizedName = 'GenericImplantTemplate';
} else if (
sopClassDictionary.ImplantAssemblyTemplateStorage === SOPClassUID
) {
naturalizedName = 'ImplantAssemblyTemplate';
} else if (sopClassDictionary.ImplantTemplateGroupStorage === SOPClassUID) {
naturalizedName = 'ImplantTemplateGroup';
}
return naturalizedName;
};
+32
View File
@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.10.11](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.10...@ohif/ui@1.10.11) (2023-03-19)
**Note:** Version bump only for package @ohif/ui
## [1.10.10](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.9...@ohif/ui@1.10.10) (2022-08-24)
**Note:** Version bump only for package @ohif/ui
## [1.10.9](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.8...@ohif/ui@1.10.9) (2022-06-29)
**Note:** Version bump only for package @ohif/ui
## [1.10.8](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.7...@ohif/ui@1.10.8) (2022-04-06)
**Note:** Version bump only for package @ohif/ui
## [1.10.7](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.6...@ohif/ui@1.10.7) (2022-03-14) ## [1.10.7](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.6...@ohif/ui@1.10.7) (2022-03-14)
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/ui", "name": "@ohif/ui",
"version": "1.10.7", "version": "1.10.11",
"description": "A set of React components for Medical Imaging Viewers", "description": "A set of React components for Medical Imaging Viewers",
"author": "OHIF Contributors", "author": "OHIF Contributors",
"license": "MIT", "license": "MIT",
@@ -45,7 +45,7 @@
"i18next-browser-languagedetector": "^3.0.1", "i18next-browser-languagedetector": "^3.0.1",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"lodash.isequal": "4.5.0", "lodash.isequal": "4.5.0",
"moment": "2.24.0", "moment": "2.29.4",
"prop-types": "15.6.2", "prop-types": "15.6.2",
"prop-types-extra": "^1.1.1", "prop-types-extra": "^1.1.1",
"react-dates": "21.2.1", "react-dates": "21.2.1",
@@ -9,6 +9,14 @@ import { TableListItem } from './../tableList/TableListItem.js';
import './MeasurementTableItem.styl'; import './MeasurementTableItem.styl';
const ColoredCircle = ({ color }) => {
return <div className="item-color" style={{ backgroundColor: color }}></div>;
};
ColoredCircle.propTypes = {
color: PropTypes.string.isRequired,
};
class MeasurementTableItem extends Component { class MeasurementTableItem extends Component {
static propTypes = { static propTypes = {
measurementData: PropTypes.object.isRequired, measurementData: PropTypes.object.isRequired,
@@ -21,6 +29,14 @@ class MeasurementTableItem extends Component {
t: PropTypes.func, t: PropTypes.func,
}; };
constructor(props) {
super(props);
this.state = {
collapsed: true,
visible: true,
};
}
render() { render() {
const { const {
warningTitle = '', warningTitle = '',
@@ -93,8 +109,95 @@ class MeasurementTableItem extends Component {
actionButtons.push(deleteButton); actionButtons.push(deleteButton);
} }
if (
this.props.measurementData.isSRText === true &&
this.props.measurementData.labels &&
this.props.measurementData.labels.length > 0
) {
return (
<React.Fragment>
<TableListItem
key={this.props.measurementData.measurementNumber}
itemKey={this.props.measurementData.measurementNumber}
itemClass={`measurementItem ${this.props.itemClass} ${hasWarningClass}`}
itemIndex={this.props.itemIndex}
onItemClick={this.onItemClick}
>
<div>
<div className="measurementLocation">
{this.props.t(this.props.measurementData.label, {
keySeparator: '>',
nsSeparator: '|',
})}
</div>
</div>
<div className="icons">
<div className="displayTexts">{this.getDataDisplayText()}</div>
<Icon
className={`eye-icon`}
name={this.state.visible ? 'eye' : 'eye-closed'}
width="20px"
height="20px"
onClick={() => {
this.props.measurementData.labels.forEach(label => {
label.visible = !this.state.visible;
});
this.setState({
visible: !this.state.visible,
});
}}
/>
<Icon
className={`angle-double-${
this.state.collapsed ? 'down' : 'up'
}`}
name={`angle-double-${this.state.collapsed ? 'down' : 'up'}`}
width="20px"
height="20px"
onClick={() => {
this.setState({
collapsed: !this.state.collapsed,
});
}}
/>
</div>
</TableListItem>
{this.state.collapsed &&
this.props.measurementData.labels.map((SRLabel, index) => {
return ( return (
<TableListItem <TableListItem
key={index}
itemKey={index}
itemMeta={<ColoredCircle color={SRLabel.color} />}
itemMetaClass="item-color-section"
onItemClick={this.onItemClick}
>
<div>
<div className="icons">
<span style={{ width: '90px' }}>
{SRLabel.label + ' : ' + SRLabel.value}
</span>
<Icon
className={`eye-icon`}
name={SRLabel.visible ? 'eye' : 'eye-closed'}
width="20px"
height="20px"
onClick={() => {
SRLabel.visible = !SRLabel.visible;
}}
/>
</div>
</div>
</TableListItem>
);
})}
</React.Fragment>
);
} else {
return (
<TableListItem
key={this.props.measurementData.measurementNumber}
itemKey={this.props.measurementData.measurementNumber} itemKey={this.props.measurementData.measurementNumber}
itemClass={`measurementItem ${this.props.itemClass} ${hasWarningClass}`} itemClass={`measurementItem ${this.props.itemClass} ${hasWarningClass}`}
itemIndex={this.props.itemIndex} itemIndex={this.props.itemIndex}
@@ -114,6 +217,7 @@ class MeasurementTableItem extends Component {
</div> </div>
</TableListItem> </TableListItem>
); );
}
}; };
onItemClick = event => { onItemClick = event => {
@@ -1,4 +1,16 @@
.measurementItem .measurementItem
.item-color-section
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
.item-color
margin-top: 8px;
border-radius: 100%;
width: 20px;
height: 20px;
.rowActions .rowActions
margin-left: -1px; margin-left: -1px;
background-color: var(--ui-gray-darker) background-color: var(--ui-gray-darker)
@@ -63,3 +75,16 @@
width: 22px; width: 22px;
height: 20px; height: 20px;
pointer-events: inherit; pointer-events: inherit;
.icons
display: flex;
align-items: center;
border-radius: 5px;
.icons .eye-icon
margin-left: 100px;
margin-right: -5px;
.icons .angle-double-down
.icons .angle-double-up
margin-left: 15px;
margin-right: -5px;
@@ -177,8 +177,10 @@ function Thumbnail(props) {
const { progressId, progressData } = detail; const { progressId, progressData } = detail;
if (`StackProgress:${displaySetInstanceUID}` === progressId) { if (`StackProgress:${displaySetInstanceUID}` === progressId) {
const percent = progressData ? progressData.percentComplete : 0; const percent = progressData ? progressData.percentComplete : 0;
if (percent > stackPercentComplete) {
setStackPercentComplete(percent); setStackPercentComplete(percent);
} }
}
}, 100); }, 100);
document.addEventListener( document.addEventListener(
@@ -25,7 +25,8 @@
box-shadow: inset 0 0 0 1px var(--ui-border-color-dark); box-shadow: inset 0 0 0 1px var(--ui-border-color-dark);
border: 2px solid transparent; border: 2px solid transparent;
border-radius: 12px; border-radius: 12px;
height: 135px; min-height: 135px;
max-height: 250px;
margin: 0 auto; margin: 0 auto;
padding: 5px; padding: 5px;
position: relative; position: relative;
@@ -36,6 +37,11 @@
h1 h1
text-align: center text-align: center
color: var(--text-primary-color); color: var(--text-primary-color);
max-width: 200px;
max-height: 250px;
overflow-wrap: break-word;
word-wrap: break-word;
hyphens: auto;
.series-details .series-details
display: flex; display: flex;
@@ -18,6 +18,7 @@ $headerRowHeight = 63px
.tableListHeaderTitle .tableListHeaderTitle
color: var(--text-secondary-color) color: var(--text-secondary-color)
max-width: 230px
font-size: 22px font-size: 22px
font-weight: 300 font-weight: 300
line-height: $headerRowHeight line-height: $headerRowHeight
@@ -12,16 +12,13 @@ export class TableListItem extends Component {
itemIndex: PropTypes.number, itemIndex: PropTypes.number,
itemMeta: PropTypes.node, itemMeta: PropTypes.node,
itemMetaClass: PropTypes.string, itemMetaClass: PropTypes.string,
itemKey: PropTypes.oneOfType([ itemKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
PropTypes.string,
PropTypes.number,
]),
onItemClick: PropTypes.func.isRequired, onItemClick: PropTypes.func.isRequired,
}; };
static defaultProps = { static defaultProps = {
itemMeta: null, itemMeta: null,
itemMetaClass: '' itemMetaClass: '',
}; };
render() { render() {
+241
View File
@@ -3,6 +3,247 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [4.12.51](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.50...@ohif/viewer@4.12.51) (2023-03-19)
**Note:** Version bump only for package @ohif/viewer
## [4.12.50](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.49...@ohif/viewer@4.12.50) (2023-01-17)
**Note:** Version bump only for package @ohif/viewer
## [4.12.49](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.48...@ohif/viewer@4.12.49) (2023-01-10)
**Note:** Version bump only for package @ohif/viewer
## [4.12.48](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.47...@ohif/viewer@4.12.48) (2022-12-21)
**Note:** Version bump only for package @ohif/viewer
## [4.12.47](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.46...@ohif/viewer@4.12.47) (2022-12-21)
**Note:** Version bump only for package @ohif/viewer
## [4.12.46](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.45...@ohif/viewer@4.12.46) (2022-12-12)
### Bug Fixes
* [#2964](https://github.com/OHIF/Viewers/issues/2964) Reword message for segmentation error loading due to orientation tolerance ([#3017](https://github.com/OHIF/Viewers/issues/3017)) ([597ac11](https://github.com/OHIF/Viewers/commit/597ac11c4daee1b1e14148804551e20611cfef08))
## [4.12.45](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.44...@ohif/viewer@4.12.45) (2022-11-12)
**Note:** Version bump only for package @ohif/viewer
## [4.12.44](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.43...@ohif/viewer@4.12.44) (2022-11-02)
**Note:** Version bump only for package @ohif/viewer
## [4.12.43](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.42...@ohif/viewer@4.12.43) (2022-10-28)
### Bug Fixes
* [#2964](https://github.com/OHIF/Viewers/issues/2964) Update message for segmentation error loading due to orientation tolerance ([#2982](https://github.com/OHIF/Viewers/issues/2982)) ([545161d](https://github.com/OHIF/Viewers/commit/545161d5e8d92bb6652f17dc24a36dac8aa7b3a4))
## [4.12.42](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.41...@ohif/viewer@4.12.42) (2022-10-25)
**Note:** Version bump only for package @ohif/viewer
## [4.12.41](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.40...@ohif/viewer@4.12.41) (2022-09-26)
**Note:** Version bump only for package @ohif/viewer
## [4.12.40](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.39...@ohif/viewer@4.12.40) (2022-09-20)
**Note:** Version bump only for package @ohif/viewer
## [4.12.39](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.38...@ohif/viewer@4.12.39) (2022-09-19)
**Note:** Version bump only for package @ohif/viewer
## [4.12.38](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.37...@ohif/viewer@4.12.38) (2022-09-12)
**Note:** Version bump only for package @ohif/viewer
## [4.12.37](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.36...@ohif/viewer@4.12.37) (2022-09-12)
**Note:** Version bump only for package @ohif/viewer
## [4.12.36](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.35...@ohif/viewer@4.12.36) (2022-09-08)
### Bug Fixes
* hotkey page up/down did not work ([#2910](https://github.com/OHIF/Viewers/issues/2910)) ([d74ad37](https://github.com/OHIF/Viewers/commit/d74ad370e091c8af2d93ec35f688c4ef902bab2b))
## [4.12.35](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.34...@ohif/viewer@4.12.35) (2022-09-02)
**Note:** Version bump only for package @ohif/viewer
## [4.12.34](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.33...@ohif/viewer@4.12.34) (2022-09-01)
**Note:** Version bump only for package @ohif/viewer
## [4.12.33](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.32...@ohif/viewer@4.12.33) (2022-08-31)
**Note:** Version bump only for package @ohif/viewer
## [4.12.32](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.31...@ohif/viewer@4.12.32) (2022-08-25)
**Note:** Version bump only for package @ohif/viewer
## [4.12.31](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.30...@ohif/viewer@4.12.31) (2022-08-24)
**Note:** Version bump only for package @ohif/viewer
## [4.12.30](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.29...@ohif/viewer@4.12.30) (2022-06-30)
**Note:** Version bump only for package @ohif/viewer
## [4.12.29](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.28...@ohif/viewer@4.12.29) (2022-06-29)
**Note:** Version bump only for package @ohif/viewer
## [4.12.28](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.27...@ohif/viewer@4.12.28) (2022-06-28)
**Note:** Version bump only for package @ohif/viewer
## [4.12.27](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.26...@ohif/viewer@4.12.27) (2022-06-14)
**Note:** Version bump only for package @ohif/viewer
## [4.12.26](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.25...@ohif/viewer@4.12.26) (2022-04-22)
**Note:** Version bump only for package @ohif/viewer
## [4.12.25](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.24...@ohif/viewer@4.12.25) (2022-04-06)
**Note:** Version bump only for package @ohif/viewer
## [4.12.24](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.23...@ohif/viewer@4.12.24) (2022-04-05)
**Note:** Version bump only for package @ohif/viewer
## [4.12.23](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.22...@ohif/viewer@4.12.23) (2022-03-25)
**Note:** Version bump only for package @ohif/viewer
## [4.12.22](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.21...@ohif/viewer@4.12.22) (2022-03-14) ## [4.12.22](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.12.21...@ohif/viewer@4.12.22) (2022-03-14)
**Note:** Version bump only for package @ohif/viewer **Note:** Version bump only for package @ohif/viewer
+12 -12
View File
@@ -1,6 +1,6 @@
{ {
"name": "@ohif/viewer", "name": "@ohif/viewer",
"version": "4.12.22", "version": "4.12.51",
"description": "OHIF Viewer", "description": "OHIF Viewer",
"author": "OHIF Contributors", "author": "OHIF Contributors",
"license": "MIT", "license": "MIT",
@@ -47,26 +47,26 @@
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.5.5", "@babel/runtime": "^7.5.5",
"@ohif/core": "^2.16.14", "@ohif/core": "^2.16.35",
"@ohif/extension-cornerstone": "^2.12.8", "@ohif/extension-cornerstone": "^2.12.16",
"@ohif/extension-debugging": "^0.3.2", "@ohif/extension-debugging": "^0.3.3",
"@ohif/extension-dicom-html": "^1.3.19", "@ohif/extension-dicom-html": "^1.3.24",
"@ohif/extension-dicom-microscopy": "^0.52.0", "@ohif/extension-dicom-microscopy": "^0.52.0",
"@ohif/extension-dicom-pdf": "^1.1.2", "@ohif/extension-dicom-pdf": "^1.1.2",
"@ohif/extension-dicom-rt": "^0.7.9", "@ohif/extension-dicom-rt": "^0.7.14",
"@ohif/extension-dicom-segmentation": "^0.7.9", "@ohif/extension-dicom-segmentation": "^0.7.21",
"@ohif/extension-lesion-tracker": "^0.2.1", "@ohif/extension-lesion-tracker": "^0.2.2",
"@ohif/extension-vtk": "^1.12.19", "@ohif/extension-vtk": "^1.12.42",
"@ohif/i18n": "^0.53.0", "@ohif/i18n": "^0.53.0",
"@ohif/ui": "^1.10.7", "@ohif/ui": "^1.10.11",
"@tanem/react-nprogress": "^1.1.25", "@tanem/react-nprogress": "^1.1.25",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"core-js": "^3.2.1", "core-js": "^3.2.1",
"cornerstone-core": "^2.6.1", "cornerstone-core": "^2.6.1",
"cornerstone-math": "^0.1.9", "cornerstone-math": "^0.1.9",
"cornerstone-tools": "^6.0.6", "cornerstone-tools": "^6.0.6",
"cornerstone-wado-image-loader": "^4.1.0", "cornerstone-wado-image-loader": "^4.2.1",
"dcmjs": "0.19.7", "dcmjs": "0.29.3",
"dicom-parser": "^1.8.11", "dicom-parser": "^1.8.11",
"dicomweb-client": "^0.8.3", "dicomweb-client": "^0.8.3",
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",
+1
View File
@@ -30,6 +30,7 @@ window.config = {
}, },
], ],
}, },
// Extensions should be able to suggest default values for these? // Extensions should be able to suggest default values for these?
// Or we can require that these be explicitly set // Or we can require that these be explicitly set
hotkeys: [ hotkeys: [
@@ -1,4 +1,4 @@
import { redux } from '@ohif/core'; import { redux, utils } from '@ohif/core';
import store from './../../store'; import store from './../../store';
const commandsModule = ({ commandsManager }) => { const commandsModule = ({ commandsManager }) => {
@@ -122,6 +122,7 @@ function convertMeasurementsToTableData(toolCollections, timepoints) {
Object.keys(toolCollections).forEach(toolId => { Object.keys(toolCollections).forEach(toolId => {
const toolMeasurements = toolCollections[toolId]; const toolMeasurements = toolCollections[toolId];
const tool = tools.find(tool => tool.id === toolId); const tool = tools.find(tool => tool.id === toolId);
const { displayFunction } = tool.options.measurementTable; const { displayFunction } = tool.options.measurementTable;
@@ -131,12 +132,13 @@ function convertMeasurementsToTableData(toolCollections, timepoints) {
Object.keys(groupedMeasurements).forEach(groupedMeasurementsIndex => { Object.keys(groupedMeasurements).forEach(groupedMeasurementsIndex => {
const measurementNumberList = const measurementNumberList =
groupedMeasurements[groupedMeasurementsIndex]; groupedMeasurements[groupedMeasurementsIndex];
const measurementData = measurementNumberList[0]; const measurementData = measurementNumberList[0];
const { const {
measurementNumber, measurementNumber,
lesionNamingNumber, lesionNamingNumber,
toolType, toolType,
isReadOnly isReadOnly,
} = measurementData; } = measurementData;
const measurementId = measurementData._id; const measurementId = measurementData._id;
@@ -150,6 +152,8 @@ function convertMeasurementsToTableData(toolCollections, timepoints) {
const tableMeasurement = { const tableMeasurement = {
itemNumber: lesionNamingNumber, itemNumber: lesionNamingNumber,
label: getMeasurementText(measurementData), label: getMeasurementText(measurementData),
labels: measurementData.labels,
isSRText: measurementData.isSRText,
measurementId, measurementId,
measurementNumber, measurementNumber,
lesionNamingNumber, lesionNamingNumber,
@@ -1,5 +1,5 @@
import { measurements, utils } from '@ohif/core'; import { measurements, utils } from '@ohif/core';
import { servicesManager } from './../../App.js';
const { MeasurementApi } = measurements; const { MeasurementApi } = measurements;
const { studyMetadataManager } = utils; const { studyMetadataManager } = utils;
@@ -19,6 +19,25 @@ export default function jumpToRowItem(
timepointManagerState, timepointManagerState,
options = { invertViewportTimepointsOrder: false, childToolKey: null } options = { invertViewportTimepointsOrder: false, childToolKey: null }
) { ) {
const viewports = viewportsState.layout.viewports;
const activeViewportIndex = viewportsState.activeViewportIndex;
const activeViewport = viewports[activeViewportIndex];
if (activeViewport.vtk) {
const error = new Error('Measurements are not supported by the MPR mode.');
const { UINotificationService, LoggerService } = servicesManager.services;
LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: 'Measurements panel',
message: error.message,
type: 'warning',
autoClose: true,
});
return {
viewportSpecificData: [],
layout: [], // TODO: if we need to change layout, we should return this here
};
}
const numViewports = viewportsState.layout.viewports.length; const numViewports = viewportsState.layout.viewports.length;
const numTimepoints = timepointManagerState.timepoints.length; const numTimepoints = timepointManagerState.timepoints.length;
const { measurements, timepoints } = timepointManagerState; const { measurements, timepoints } = timepointManagerState;
@@ -20,12 +20,20 @@ const mapDispatchToProps = (dispatch, ownProps) => {
const { Modality } = displaySet; const { Modality } = displaySet;
if (Modality === 'SEG' && servicesManager) { if (Modality === 'SEG' && servicesManager) {
const onDisplaySetLoadFailureHandler = error => { const onDisplaySetLoadFailureHandler = error => {
LoggerService.error({ error, message: error.message }); const message =
error.message.includes('orthogonal') ||
error.message.includes('oblique')
? 'The segmentation has been detected as non coplanar,\
If you really think it is coplanar,\
please adjust the tolerance in the segmentation panel settings (at your own peril!)'
: error.message;
LoggerService.error({ error, message });
UINotificationService.show({ UINotificationService.show({
title: 'DICOM Segmentation Loader', title: 'DICOM Segmentation Loader',
message: error.message, message,
type: 'error', type: 'error',
autoClose: true, autoClose: false,
}); });
}; };
@@ -46,9 +54,11 @@ const mapDispatchToProps = (dispatch, ownProps) => {
detail: { activatedLabelmapIndex: activatedLabelmapIndex }, detail: { activatedLabelmapIndex: activatedLabelmapIndex },
} }
); );
const segThumbnailSelected = new CustomEvent('segseriesselected');
document.dispatchEvent(selectionFired); document.dispatchEvent(selectionFired);
document.dispatchEvent(segThumbnailSelected);
}); });
} else { } else if (Modality !== 'SR') {
displaySet = displaySet.getSourceDisplaySet(ownProps.studyMetadata); displaySet = displaySet.getSourceDisplaySet(ownProps.studyMetadata);
} }
@@ -79,7 +89,7 @@ const mapDispatchToProps = (dispatch, ownProps) => {
}); });
} }
if (displaySet.isModalitySupported === false) { if (displaySet.isSOPClassUIDSupported === false) {
const error = new Error('Modality not supported'); const error = new Error('Modality not supported');
const message = 'Modality not supported'; const message = 'Modality not supported';
LoggerService.error({ error, message }); LoggerService.error({ error, message });
+73 -115
View File
@@ -105,6 +105,11 @@ class Viewer extends Component {
if (this.props.dialog) { if (this.props.dialog) {
this.props.dialog.dismissAll(); this.props.dialog.dismissAll();
} }
document.removeEventListener(
'segmentationLoadingError',
this._updateThumbnails
);
} }
retrieveTimepoints = filter => { retrieveTimepoints = filter => {
@@ -212,6 +217,12 @@ class Viewer extends Component {
), ),
}); });
} }
document.addEventListener(
'segmentationLoadingError',
this._updateThumbnails.bind(this),
false
);
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
@@ -251,10 +262,28 @@ class Viewer extends Component {
const { currentTimepointId } = this; const { currentTimepointId } = this;
this.timepointApi.retrieveTimepoints({ PatientID }); this.timepointApi.retrieveTimepoints({ PatientID });
this.measurementApi.retrieveMeasurements(PatientID, [currentTimepointId]); this.measurementApi
.retrieveMeasurements(PatientID, [currentTimepointId])
.then(() => {
this._updateThumbnails();
});
} }
} }
_updateThumbnails() {
const { studies, activeViewportIndex, viewports } = this.props;
const activeViewport = viewports[activeViewportIndex];
const activeDisplaySetInstanceUID = activeViewport
? activeViewport.displaySetInstanceUID
: undefined;
this.setState({
thumbnails: _mapStudiesToThumbnails(studies, activeDisplaySetInstanceUID),
activeDisplaySetInstanceUID,
});
}
_getActiveViewport() { _getActiveViewport() {
return this.props.viewports[this.props.activeViewportIndex]; return this.props.viewports[this.props.activeViewportIndex];
} }
@@ -444,7 +473,7 @@ const _checkForDerivedDisplaySets = async function(displaySet, study) {
let derivedDisplaySetsNumber = 0; let derivedDisplaySetsNumber = 0;
if ( if (
displaySet.Modality && displaySet.Modality &&
!['SEG', 'SR', 'RTSTRUCT', 'RTDOSE'].includes(displaySet.Modality) !['SEG', 'SR', 'RTSTRUCT'].includes(displaySet.Modality)
) { ) {
const studyMetadata = studyMetadataManager.get(study.StudyInstanceUID); const studyMetadata = studyMetadataManager.get(study.StudyInstanceUID);
@@ -461,9 +490,7 @@ const _checkForDerivedDisplaySets = async function(displaySet, study) {
/** /**
* Async function to check if there are any inconsistences in the series. * Async function to check if there are any inconsistences in the series.
* *
* For segmentation checks that the geometry is consistent with the source images: * For segmentation returns any error during loading.
* 1) no frames out of plane;
* 2) have the same width and height.
* *
* For reconstructable 3D volume: * For reconstructable 3D volume:
* 1) Is series multiframe? * 1) Is series multiframe?
@@ -477,18 +504,15 @@ const _checkForDerivedDisplaySets = async function(displaySet, study) {
* @param {*object} displaySet * @param {*object} displaySet
* @returns {[string]} an array of strings containing the warnings * @returns {[string]} an array of strings containing the warnings
*/ */
const _checkForSeriesInconsistencesWarnings = async function( const _checkForSeriesInconsistencesWarnings = async function(displaySet) {
displaySet,
studies
) {
if (displaySet.inconsistencyWarnings) {
// warnings already checked and cached in displaySet
return displaySet.inconsistencyWarnings;
}
const inconsistencyWarnings = []; const inconsistencyWarnings = [];
if (displaySet.Modality !== 'SEG') { if (displaySet.Modality !== 'SEG') {
// warnings already checked and cached in displaySet
if (displaySet.inconsistencyWarnings) {
return displaySet.inconsistencyWarnings;
}
if ( if (
displaySet.reconstructionIssues && displaySet.reconstructionIssues &&
displaySet.reconstructionIssues.length !== 0 displaySet.reconstructionIssues.length !== 0
@@ -543,101 +567,17 @@ const _checkForSeriesInconsistencesWarnings = async function(
); );
} }
if (displaySet.isModalitySupported === false) { if (displaySet.isSOPClassUIDSupported === false) {
inconsistencyWarnings.push('The datasets modality is not supported.'); inconsistencyWarnings.push('The datasets is not supported.');
} }
} else {
const segMetadata = displaySet.metadata;
if (!segMetadata) {
return inconsistencyWarnings;
}
const { referencedDisplaySet } = displaySet.getSourceDisplaySet(
studies,
false
);
if (!referencedDisplaySet) {
return inconsistencyWarnings;
}
const imageIds = referencedDisplaySet.images.map(image =>
image.getImageId()
);
if (!imageIds || imageIds.length === 0) {
return inconsistencyWarnings;
}
for (
let i = 0,
groupsLen = segMetadata.PerFrameFunctionalGroupsSequence.length;
i < groupsLen;
++i
) {
const PerFrameFunctionalGroups =
segMetadata.PerFrameFunctionalGroupsSequence[i];
if (!PerFrameFunctionalGroups) {
continue;
}
let SourceImageSequence = undefined;
if (segMetadata.SourceImageSequence) {
SourceImageSequence = segMetadata.SourceImageSequence[i];
} else if (PerFrameFunctionalGroups.DerivationImageSequence) {
SourceImageSequence =
PerFrameFunctionalGroups.DerivationImageSequence.SourceImageSequence;
}
if (!SourceImageSequence) {
if (inconsistencyWarnings.length === 0) {
const warningMessage =
'The segmentation ' +
'has frames out of plane respect to the source images.';
inconsistencyWarnings.push(warningMessage);
}
continue;
}
const { ReferencedSOPInstanceUID } = SourceImageSequence;
const imageId = imageIds.find(imageId => {
const sopCommonModule = cornerstone.metaData.get(
'sopCommonModule',
imageId
);
if (!sopCommonModule) {
return;
}
return sopCommonModule.sopInstanceUID === ReferencedSOPInstanceUID;
});
if (!imageId) {
continue;
}
const sourceImageMetadata = cornerstone.metaData.get('instance', imageId);
if (
segMetadata.Rows !== sourceImageMetadata.Rows ||
segMetadata.Columns !== sourceImageMetadata.Columns
) {
const warningMessage =
'The segmentation ' +
'has frames with different geometry ' +
'dimensions (Rows and Columns) respect to the source images.';
inconsistencyWarnings.push(warningMessage);
break;
}
}
if (inconsistencyWarnings.length !== 0) {
const warningMessage =
'The segmentation format is not supported yet. ' +
'The segmentation data (segments) could not be loaded.';
inconsistencyWarnings.push(warningMessage);
}
}
// cache the warnings
displaySet.inconsistencyWarnings = inconsistencyWarnings; displaySet.inconsistencyWarnings = inconsistencyWarnings;
} else {
if (displaySet.loadError) {
inconsistencyWarnings.push(displaySet.segLoadErrorMessagge);
displaySet.inconsistencyWarnings = inconsistencyWarnings;
}
}
return inconsistencyWarnings; return inconsistencyWarnings;
}; };
@@ -672,9 +612,29 @@ const _isDisplaySetActive = function(
if ( if (
displaySet.Modality !== 'SEG' && displaySet.Modality !== 'SEG' &&
displaySet.Modality !== 'RTSTRUCT' && displaySet.Modality !== 'RTSTRUCT' &&
displaySet.Modality !== 'RTDOSE' displaySet.Modality !== 'SR'
) { ) {
active = activeDisplaySetInstanceUID === displaySetInstanceUID; active = activeDisplaySetInstanceUID === displaySetInstanceUID;
} else if (displaySet.Modality === 'SR') {
active = activeDisplaySetInstanceUID === displaySetInstanceUID;
if (!active && displaySet.getSourceDisplaySet) {
const referencedDisplaySet = displaySet.getSourceDisplaySet(
studies,
false
);
if (referencedDisplaySet && referencedDisplaySet.length !== 0) {
for (let i = 0; i < referencedDisplaySet.length; i++) {
if (
referencedDisplaySet[i].displaySetInstanceUID ===
activeDisplaySetInstanceUID
) {
active = true;
break;
}
}
}
}
} else if (displaySet.getSourceDisplaySet) { } else if (displaySet.getSourceDisplaySet) {
if (displaySet.Modality === 'SEG') { if (displaySet.Modality === 'SEG') {
const { referencedDisplaySet } = displaySet.getSourceDisplaySet( const { referencedDisplaySet } = displaySet.getSourceDisplaySet(
@@ -725,21 +685,19 @@ const _mapStudiesToThumbnails = function(studies, activeDisplaySetInstanceUID) {
let altImageText; let altImageText;
if (displaySet.Modality && displaySet.Modality === 'SEG') { if (displaySet.Modality && displaySet.Modality === 'SEG') {
// TODO: We want to replace this with a thumbnail showing
// the segmentation map on the image, but this is easier
// and better than what we have right now.
altImageText = 'SEG'; altImageText = 'SEG';
} else if (displaySet.Modality && displaySet.Modality === 'SR') {
altImageText = 'SR';
} else if (displaySet.images && displaySet.images.length) { } else if (displaySet.images && displaySet.images.length) {
const imageIndex = Math.floor(displaySet.images.length / 2); const imageIndex = Math.floor(displaySet.images.length / 2);
imageId = displaySet.images[imageIndex].getImageId(); imageId = displaySet.images[imageIndex].getImageId();
} else if (displaySet.isSOPClassUIDSupported === false) {
altImageText = displaySet.SOPClassUIDNaturalized;
} else { } else {
altImageText = displaySet.Modality ? displaySet.Modality : 'UN'; altImageText = displaySet.Modality ? displaySet.Modality : 'UN';
} }
const hasWarnings = _checkForSeriesInconsistencesWarnings( const hasWarnings = _checkForSeriesInconsistencesWarnings(displaySet);
displaySet,
studies
);
const hasDerivedDisplaySets = _checkForDerivedDisplaySets( const hasDerivedDisplaySets = _checkForDerivedDisplaySets(
displaySet, displaySet,
@@ -145,22 +145,42 @@ class ViewerMain extends Component {
const { Modality } = displaySet; const { Modality } = displaySet;
if (Modality === 'SEG' && servicesManager) { if (Modality === 'SEG' && servicesManager) {
const onDisplaySetLoadFailureHandler = error => { const onDisplaySetLoadFailureHandler = error => {
LoggerService.error({ error, message: error.message }); const message =
error.message.includes('orthogonal') ||
error.message.includes('oblique')
? 'The segmentation has been detected as non coplanar,\
If you really think it is coplanar,\
please adjust the tolerance in the segmentation panel settings (at your own peril!)'
: error.message;
LoggerService.error({ error, message });
UINotificationService.show({ UINotificationService.show({
title: 'DICOM Segmentation Loader', title: 'DICOM Segmentation Loader',
message: error.message, message,
type: 'error', type: 'error',
autoClose: true, autoClose: false,
}); });
}; };
const { referencedDisplaySet } = displaySet.getSourceDisplaySet( const {
referencedDisplaySet,
activatedLabelmapPromise,
} = displaySet.getSourceDisplaySet(
this.props.studies, this.props.studies,
true, true,
onDisplaySetLoadFailureHandler onDisplaySetLoadFailureHandler
); );
displaySet = referencedDisplaySet; displaySet = referencedDisplaySet;
} else {
activatedLabelmapPromise.then(activatedLabelmapIndex => {
const selectionFired = new CustomEvent(
'extensiondicomsegmentationsegselected',
{
detail: { activatedLabelmapIndex: activatedLabelmapIndex },
}
);
document.dispatchEvent(selectionFired);
});
} else if (Modality !== 'SR') {
displaySet = displaySet.getSourceDisplaySet(this.props.studies); displaySet = displaySet.getSourceDisplaySet(this.props.studies);
} }
@@ -177,7 +197,7 @@ class ViewerMain extends Component {
} }
} }
if (displaySet.isModalitySupported === false) { if (displaySet.isSOPClassUIDSupported === false) {
const error = new Error('Modality not supported'); const error = new Error('Modality not supported');
const message = 'Modality not supported'; const message = 'Modality not supported';
LoggerService.error({ error, message }); LoggerService.error({ error, message });
@@ -36,7 +36,7 @@ function DicomStorePickerModal({
user, user,
url, url,
}, },
onClose onClose,
}); });
} }
}; };
+1 -1
View File
@@ -1 +1 @@
3.7 3.8
+467 -234
View File
File diff suppressed because it is too large. Load diff