Compare commits

...
Author SHA1 Message Date
ohif-bot 410ab028c7 chore(release): publish [skip ci]
- @ohif/extension-dicom-html@1.3.8
 - @ohif/extension-dicom-rt@0.6.10
 - @ohif/extension-dicom-segmentation@0.6.7
 - @ohif/extension-dicom-tag-browser@0.2.8
 - @ohif/extension-vtk@1.11.10
 - @ohif/core@2.13.9
 - @ohif/viewer@4.9.14
2021-04-22 03:27:52 +00:00
dannyrb 54dd738f61 Merge branch 'master' of github.com:OHIF/Viewers into ups-master 2021-04-21 23:24:39 -04:00
dannyrb 6f16c7e48d Remove broken plugin? Seems to have broken child dep 2021-04-21 23:24:28 -04:00
ohif-bot 82ddd95cf0 chore(release): publish [skip ci]
- @ohif/extension-dicom-html@1.3.7
 - @ohif/extension-dicom-rt@0.6.9
 - @ohif/extension-dicom-segmentation@0.6.6
 - @ohif/extension-dicom-tag-browser@0.2.7
 - @ohif/extension-vtk@1.11.9
 - @ohif/core@2.13.8
 - @ohif/viewer@4.9.13
2021-04-21 14:14:00 +00:00
Davide Punzo 2b658fae7e IDC2345: update dcmjs to version 0.18.5 (#2378) 2021-04-21 16:10:49 +02:00
ohif-bot a822151e92 chore(release): publish [skip ci]
- @ohif/extension-dicom-html@1.3.6
 - @ohif/extension-vtk@1.11.8
 - @ohif/core@2.13.7
 - @ohif/viewer@4.9.12
2021-04-21 11:17:09 +00:00
Igor Octaviano 0ae49c6fdc IDC-2348: Add acquisition storage sr sopclass to sr html ext (#2352)
* Add acquisition context storage sr sop to html ext
2021-04-21 13:12:54 +02:00
ohif-bot 1d069d2da3 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.6.5
 - @ohif/extension-vtk@1.11.7
 - @ohif/core@2.13.6
 - @ohif/viewer@4.9.11
2021-04-21 10:22:55 +00:00
Igor Octaviano 274342a5e1 Merge pull request #2369 from Punzo/IDC2361
Re #2361: fix seg combobox filling
2021-04-21 07:19:32 -03:00
Davide Punzo 21a5d1bfc4 update 2021-04-21 10:40:02 +02:00
Davide Punzo e421bc7df9 update 2021-04-20 16:39:04 +02:00
Davide Punzo e41ba2bfde IDC2361: fix seg combobox filling 2021-04-19 19:42:30 +02:00
ohif-bot d2e75b0f20 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.6.4
 - @ohif/extension-vtk@1.11.6
 - @ohif/core@2.13.5
 - @ohif/viewer@4.9.10
2021-04-16 18:18:27 +00:00
Davide Punzo 07b272e024 IDC2345: implement thumbnails footnotes UI for segmentation series inconsistencies warning (#2364)
* IDC2345: implement thumbnails footnotes UI for segmentation series inconsistencies warning
2021-04-16 20:14:04 +02:00
ohif-bot a08caa9bdb chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.10.7
 - @ohif/extension-dicom-html@1.3.5
 - @ohif/extension-dicom-rt@0.6.8
 - @ohif/extension-dicom-segmentation@0.6.3
 - @ohif/extension-dicom-tag-browser@0.2.6
 - @ohif/extension-vtk@1.11.5
 - @ohif/core@2.13.4
 - @ohif/viewer@4.9.9
2021-04-15 13:13:50 +00:00
Igor Octaviano 29afddb3a6 Merge pull request #2363 from OHIF/fix/window-level-issues
fix(MetadataProvider): Update metadata provider to resolve issues after dicomweb update/new return value
2021-04-15 10:10:48 -03:00
igoroctaviano f85f856734 Comment cache 2021-04-15 09:40:37 -03:00
igoroctaviano c6bc19c002 Rollback circle ci test 2021-04-15 09:29:50 -03:00
igoroctaviano 538555f000 Merge branch 'master' of github.com:OHIF/Viewers into fix/window-level-issues 2021-04-15 09:17:54 -03:00
igoroctaviano 8681036b21 fix(wl): fix metadata provider window level issues after dicomweb update (string vs number) 2021-04-15 09:15:42 -03:00
Davide Punzo e55b909ca6 IDC2345: Update dcmjs to version 0.18.4 (#2362) 2021-04-15 13:33:13 +02:00
Davide Punzo 4bb36704ee IDC2346: fix images sorting (#2358) 2021-04-14 19:43:58 +02:00
Davide Punzo 9bbdb35d88 IDC2259: do not check uniform spacing in the 4th dimension for 4D datasets (#2356) 2021-04-13 12:57:28 +02:00
qqalexqq 2f443fa2ef fix: Update Dockerfile node version - fix missing dependencies (#2349)
There were some utilities missing: python, make, g++. Also node version was too old - current node builds without problems.
2021-04-05 09:47:57 +02:00
ohif-bot 6d7d7da287 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.6.2
 - @ohif/viewer@4.9.8
2021-03-31 10:24:08 +00:00
Davide Punzo 1f6751f95b IDC2332 (#2341)
1) fix the loading of the segmentations when filtering study with ?seriesInstanceUID= syntax
2) add time in the dates of the items of the segmentation combobox list
3) order segmentation combobox list in reverse time order
2021-03-31 12:20:34 +02:00
ohif-bot 92081a097d chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.10.6
 - @ohif/viewer@4.9.7
2021-03-26 18:38:58 +00:00
Igor Octaviano ba1a33c3ac Merge pull request #2335 from OHIF/idc-2334
IDC-2334: Resolve choppy scrolling in 2D mode
2021-03-26 15:36:07 -03:00
igoroctaviano 193ff12b6e Fix scroll speed 2021-03-26 13:27:51 -03:00
ohif-bot 3296ffaa07 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.11.4
 - @ohif/core@2.13.3
 - @ohif/ui@1.9.1
 - @ohif/viewer@4.9.6
2021-03-26 10:35:50 +00:00
Davide Punzo 0456d92462 IDC 2259: add warning UI for series inconsistencies (#2331)
IDC 2259: add warning UI for series inconsistencies

remove VTKMPRToolbarButton component memoization (it is not anymore necessary)
2021-03-26 11:32:10 +01:00
ohif-bot db3b15e537 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.11.3
 - @ohif/core@2.13.2
 - @ohif/viewer@4.9.5
2021-03-25 16:16:14 +00:00
Igor OctavianoandDavide Punzo 6e723ebced fix: IDC-2288: Update toolbar tabs after derived displayset loaded (#2307)
* Update toolbar tabs after derived displayset loaded

* trigger CI

Co-authored-by: Davide Punzo <punzodavide@hotmail.it>
2021-03-25 17:12:20 +01:00
ohif-bot a6a231c81e chore(release): publish [skip ci]
- @ohif/extension-debugging@0.2.1
 - @ohif/viewer@4.9.4
2021-03-19 18:54:21 +00:00
Igor Octaviano 7c2bd9b76a Merge pull request #2321 from OHIF/bugfix/idc-2006
bug(IDC-2006): Fix bug introduced with new logger service which broke debugger mailto functionality
2021-03-19 15:51:01 -03:00
igoroctaviano 5dfa8d465d Force pipeline 2021-03-19 15:12:37 -03:00
igoroctaviano fc5301e904 bug(debugger):Fix bug that breaks mailto introduced by logger service 2021-03-18 07:40:59 -03:00
ohif-bot 88e5a7e54a chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.10.5
 - @ohif/viewer@4.9.3
2021-03-15 20:12:36 +00:00
Igor Octaviano 5d24bb4b73 Merge pull request #2315 from OHIF/igoroctaviano/react-cornerstone-viewport-4.0.5
Update dependency: react-cornerstone-viewport@4.0.5
2021-03-15 17:09:16 -03:00
igoroctaviano 03a4056179 Update dependency: react-cornerstone-viewport@4.0.5
react-cornerstone-viewport
  * @ohif/extension-cornerstone: 4.0.4 → 4.0.5
2021-03-15 16:42:24 -03:00
ohif-bot ec76bc3b0b chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.10.4
 - @ohif/extension-dicom-html@1.3.4
 - @ohif/extension-dicom-rt@0.6.7
 - @ohif/extension-dicom-segmentation@0.6.1
 - @ohif/extension-dicom-tag-browser@0.2.5
 - @ohif/extension-vtk@1.11.2
 - @ohif/core@2.13.1
 - @ohif/viewer@4.9.2
2021-03-09 19:43:21 +00:00
Davide Punzo b1070acaca Update dependency: dcmjs@0.18.3 (#2302) 2021-03-09 20:38:19 +01:00
ohif-bot 7b5beb8f98 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.11.1
 - @ohif/viewer@4.9.1
2021-03-09 15:55:47 +00:00
97410e12b9 Added memoization on VTKMPRToolbarButton component to avoid unnecesary rebuilds (#2274)
* Added memoization on VTKMPRToolbarButton component to avoid unnecessary rebuilds

* update isDisplaySetReconstructable for float precision

Co-authored-by: Rodrigo Cáceres Vicencio <rcaceres@nursoft.cl>
Co-authored-by: Davide Punzo <punzodavide@hotmail.it>
2021-03-09 16:52:56 +01:00
ohif-bot bdecbfeee3 chore(release): publish [skip ci]
- @ohif/extension-debugging@0.2.0
 - @ohif/extension-dicom-microscopy@0.52.0
 - @ohif/extension-dicom-segmentation@0.6.0
 - @ohif/extension-vtk@1.11.0
 - @ohif/core@2.13.0
 - @ohif/ui@1.9.0
 - @ohif/viewer@4.9.0
2021-03-04 21:44:04 +00:00
Igor Octaviano 5a970056ae Merge pull request #2283 from OHIF/IDC-2223-update
feat(IDC-2223): add new log service to be used by debugger extension
2021-03-04 18:41:04 -03:00
igoroctaviano 8581405352 Add logger to viewport grid 2021-03-04 18:20:57 -03:00
igoroctaviano df8c4db2ed Update broken test 2021-03-03 20:06:58 -03:00
igoroctaviano ea62bdaddf Merge branch 'master' of github.com:OHIF/Viewers into IDC-2223-update 2021-03-03 19:18:36 -03:00
igoroctaviano e983b02677 Add onerror event to cover all other unhandled errors 2021-03-03 19:16:49 -03:00
ohif-bot 1e4b78d78d chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.10.3
 - @ohif/extension-dicom-html@1.3.3
 - @ohif/extension-dicom-rt@0.6.6
 - @ohif/extension-dicom-segmentation@0.5.4
 - @ohif/extension-dicom-tag-browser@0.2.4
 - @ohif/extension-vtk@1.10.6
 - @ohif/core@2.12.5
 - @ohif/viewer@4.8.12
2021-03-03 18:31:51 +00:00
igoroctaviano ee6131f98e Merge branch 'master' of github.com:OHIF/Viewers into IDC-2223-update 2021-03-03 15:28:23 -03:00
Igor Octaviano a56bdd035b Merge pull request #2290 from OHIF/bump-dcmjs
Update dependency: dcmjs@0.18.2
2021-03-03 15:27:54 -03:00
igoroctaviano 04901c296e Update dependency: dcmjs@0.18.2
dcmjs
  * @ohif/core: 0.18.1 → 0.18.2
  * @ohif/extension-cornerstone: 0.18.1 → 0.18.2
  * @ohif/extension-dicom-html: 0.18.1 → 0.18.2
  * @ohif/extension-dicom-rt: 0.18.1 → 0.18.2
  * @ohif/extension-dicom-segmentation: 0.18.1 → 0.18.2
  * @ohif/extension-dicom-tag-browser: 0.18.1 → 0.18.2
  * @ohif/extension-vtk: 0.18.1 → 0.18.2
  * @ohif/viewer: 0.18.1 → 0.18.2
2021-03-03 14:35:06 -03:00
ohif-bot 59cadad98c chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.10.2
 - @ohif/extension-dicom-html@1.3.2
 - @ohif/extension-dicom-rt@0.6.5
 - @ohif/extension-dicom-segmentation@0.5.3
 - @ohif/extension-dicom-tag-browser@0.2.3
 - @ohif/extension-vtk@1.10.5
 - @ohif/core@2.12.4
 - @ohif/viewer@4.8.11
2021-02-25 21:31:47 +00:00
igoroctaviano 14d6454eaf feat(log): add new log service 2021-02-25 18:29:28 -03:00
Igor Octaviano 64f87d2c93 Merge pull request #2281 from OHIF/fix/bump-dcmjs
Update dependency: dcmjs@0.18.1
2021-02-25 18:28:37 -03:00
igoroctaviano cfd66e5ef7 Update dependency: dcmjs@0.18.1
dcmjs
  * @ohif/core: 0.17.2 → 0.18.1
  * @ohif/extension-cornerstone: 0.17.2 → 0.18.1
  * @ohif/extension-dicom-html: 0.17.2 → 0.18.1
  * @ohif/extension-dicom-rt: 0.17.2 → 0.18.1
  * @ohif/extension-dicom-segmentation: 0.17.2 → 0.18.1
  * @ohif/extension-dicom-tag-browser: 0.17.2 → 0.18.1
  * @ohif/extension-vtk: 0.17.2 → 0.18.1
  * @ohif/viewer: 0.17.2 → 0.18.1
2021-02-25 17:05:24 -03:00
Andrey Fedorovandigoroctaviano 6480389778 chore: add acknowledgment of IDC (#2255)
* add acknowldgment of IDC

resolves #1136

* Fix typo + remove IDC ack example

Co-authored-by: igoroctaviano <igoroctaviano@gmail.com>
2021-02-12 12:08:43 +01:00
ohif-bot 0e736e7a56 chore(release): publish [skip ci]
- @ohif/viewer@4.8.10
2021-02-08 11:56:46 +00:00
Igor Octaviano d246cd9842 Merge pull request #2267 from OHIF/IDC-2251
IDC-2251: Add error page and not found pages if failed to retrieve study data
2021-02-08 08:53:35 -03:00
igoroctaviano 4fa1eb683d Merge branch 'master' of github.com:OHIF/Viewers into IDC-2251 2021-02-07 22:29:45 -03:00
igoroctaviano d97270f995 Merge branch 'master' of github.com:OHIF/Viewers into IDC-2251 2021-02-05 17:00:06 -03:00
igoroctaviano 7c5f9c44b6 Add error page and not found pages if failed to retrieve study data 2021-02-03 13:58:46 -03:00
72 changed files with 1961 additions and 445 deletions

No files matched your search

+35 -27
View File
@@ -48,12 +48,12 @@ jobs:
- checkout:
post:
- git fetch --all
- restore_cache:
name: Restore Yarn and Cypress Package Cache
keys:
# when lock file changes, use increasingly general patterns to restore cache
- yarn-packages-{{ checksum "yarn.lock" }}
- yarn-packages-
# - restore_cache:
# name: Restore Yarn and Cypress Package Cache
# keys:
# # when lock file changes, use increasingly general patterns to restore cache
# - yarn-packages-{{ checksum "yarn.lock" }}
# - yarn-packages-
- run:
name: Install Dependencies
command: yarn install --frozen-lockfile
@@ -107,12 +107,12 @@ jobs:
post:
- git fetch --all
- restore_cache:
name: Restore Yarn and Cypress Package Cache
keys:
# when lock file changes, use increasingly general patterns to restore cache
- yarn-packages-{{ checksum "yarn.lock" }}
- yarn-packages-
# - restore_cache:
# name: Restore Yarn and Cypress Package Cache
# keys:
# # when lock file changes, use increasingly general patterns to restore cache
# - yarn-packages-{{ checksum "yarn.lock" }}
# - yarn-packages-
- run:
name: Install Dependencies
@@ -143,12 +143,12 @@ jobs:
- checkout:
post:
- git fetch --all
- restore_cache:
name: Restore Yarn and Cypress Package Cache
keys:
# when lock file changes, use increasingly general patterns to restore cache
- yarn-packages-{{ checksum "yarn.lock" }}
- yarn-packages-
# - restore_cache:
# name: Restore Yarn and Cypress Package Cache
# keys:
# # when lock file changes, use increasingly general patterns to restore cache
# - yarn-packages-{{ checksum "yarn.lock" }}
# - yarn-packages-
- run:
name: Install Dependencies
command: yarn install --frozen-lockfile
@@ -237,11 +237,11 @@ jobs:
post:
- git fetch --all
# Use increasingly general patterns to restore cache
- restore_cache:
name: Restore Yarn and Cypress Package Cache
keys:
- yarn-packages-{{ checksum "yarn.lock" }}
- yarn-packages-
# - restore_cache:
# name: Restore Yarn and Cypress Package Cache
# keys:
# - yarn-packages-{{ checksum "yarn.lock" }}
# - yarn-packages-
- run:
name: Install Dependencies
command: yarn install --frozen-lockfile
@@ -346,7 +346,9 @@ workflows:
record: true
store_artifacts: true
working_directory: platform/viewer
build: npx cross-env QUICK_BUILD=true APP_CONFIG=config/dicomweb-server.js yarn run build
build:
npx cross-env QUICK_BUILD=true APP_CONFIG=config/dicomweb-server.js
yarn run build
start: yarn run test:e2e:serve
spec: 'cypress/integration/common/**/*,cypress/integration/pwa/**/*'
wait-on: 'http://localhost:3000'
@@ -372,7 +374,9 @@ workflows:
record: true
store_artifacts: true
working_directory: platform/viewer
build: npx cross-env QUICK_BUILD=true APP_CONFIG=config/dicomweb-server.js yarn run build:package
build:
npx cross-env QUICK_BUILD=true APP_CONFIG=config/dicomweb-server.js
yarn run build:package
start: yarn run test:e2e:serve
spec: 'cypress/integration/common/**/*,cypress/integration/script-tag/**/*'
wait-on: 'http://localhost:3000'
@@ -403,7 +407,9 @@ workflows:
yarn: true
store_artifacts: false
working_directory: platform/viewer
build: npx cross-env QUICK_BUILD=true APP_CONFIG=config/dicomweb-server.js yarn run build
build:
npx cross-env QUICK_BUILD=true APP_CONFIG=config/dicomweb-server.js
yarn run build
# start server --> verify running --> percy + chrome + cypress
command: yarn run test:e2e:dist
cache-key: 'yarn-packages-{{ checksum "yarn.lock" }}'
@@ -480,7 +486,9 @@ workflows:
yarn: true
store_artifacts: false
working_directory: platform/viewer
build: npx cross-env QUICK_BUILD=true APP_CONFIG=config/dicomweb-server.js yarn run build
build:
npx cross-env QUICK_BUILD=true APP_CONFIG=config/dicomweb-server.js
yarn run build
# start server --> verify running --> percy + chrome + cypress
command: yarn run test:e2e:dist
cache-key: 'yarn-packages-{{ checksum "yarn.lock" }}'
+2 -1
View File
@@ -21,7 +21,7 @@
# Stage 1: Build the application
# docker build -t ohif/viewer:latest .
FROM node:10.16.3-slim as builder
FROM node:15.13.0-slim as builder
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
@@ -39,6 +39,7 @@ COPY package.json /usr/src/app/package.json
COPY postcss.config.js /usr/src/app/postcss.config.js
COPY yarn.lock /usr/src/app/yarn.lock
RUN apt-get update && apt-get install -y python make g++
# Run the install before copying the rest of the files
RUN yarn config set workspaces-experimental true
RUN yarn install
+16 -3
View File
@@ -248,9 +248,6 @@ To acknowledge the OHIF Viewer in an academic publication, please cite
>
> _Cancer Research_, November 1 2017 (77) (21) e119-e122 DOI:
> [10.1158/0008-5472.CAN-17-0334](https://www.doi.org/10.1158/0008-5472.CAN-17-0334)
>
> NCI Imaging Data Commons: contract number 19X037Q from Leidos Biomedical
> Research under Task Order HHSN26100071 from NCI.
**Note:** If you use or find this repository helpful, please take the time to
star this repository on Github. This is an easy way for us to assess adoption
@@ -261,6 +258,22 @@ Cancer Institute, Informatics Technology for Cancer Research (ITCR) program,
under a
[grant to Dr. Gordon Harris at Massachusetts General Hospital (U24 CA199460)](https://projectreporter.nih.gov/project_info_description.cfm?aid=8971104).
## Projects that contributed to OHIF Viewer
The following is a (partial) list of projects that contributed resources towards
development of OHIF Viewer:
- [NCI Imaging Data Commons (IDC) project](https://imaging.datacommons.cancer.gov/)
supported development of new features and bug fixes marked with
["IDC:priority"](https://github.com/OHIF/Viewers/issues?q=is%3Aissue+is%3Aopen+label%3AIDC%3Apriority),
["IDC:candidate"](https://github.com/OHIF/Viewers/issues?q=is%3Aissue+is%3Aopen+label%3AIDC%3Acandidate)
or
["IDC:collaboration"](https://github.com/OHIF/Viewers/issues?q=is%3Aissue+is%3Aopen+label%3AIDC%3Acollaboration).
NCI Imaging Data Commons is supported by the contract number 19X037Q from
Leidos Biomedical Research under Task Order HHSN26100071 from NCI.
[IDC Viewer](https://learn.canceridc.dev/portal/visualization) is a customized
version of the OHIF Viewer.
## License
MIT © [OHIF](https://github.com/OHIF)
+2 -2
View File
@@ -8,7 +8,6 @@
"-fontsettings",
"github",
"ga",
"sitemap",
"anchors",
"versions"
],
@@ -24,7 +23,8 @@
"token": "UA-110573590-2"
},
"sitemap": {
"hostname": "https://docs.ohif.org"
"hostname": "https://docs.ohif.org",
"todo": "sitemap plugin removed; causing build errors"
},
"versions": {
"gitbookConfigURL": "https://raw.githubusercontent.com/OHIF/Viewers/master/docs/book.json",
+48
View File
@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.10.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.6...@ohif/extension-cornerstone@2.10.7) (2021-04-15)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.10.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.5...@ohif/extension-cornerstone@2.10.6) (2021-03-26)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.10.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.4...@ohif/extension-cornerstone@2.10.5) (2021-03-15)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.10.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.3...@ohif/extension-cornerstone@2.10.4) (2021-03-09)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.10.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.2...@ohif/extension-cornerstone@2.10.3) (2021-03-03)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.10.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.1...@ohif/extension-cornerstone@2.10.2) (2021-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.10.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.0...@ohif/extension-cornerstone@2.10.1) (2021-02-05)
**Note:** Version bump only for package @ohif/extension-cornerstone
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone",
"version": "2.10.1",
"version": "2.10.7",
"description": "OHIF extension for Cornerstone",
"author": "OHIF",
"license": "MIT",
@@ -36,7 +36,7 @@
"cornerstone-math": "^0.1.8",
"cornerstone-tools": "^4.20.1",
"cornerstone-wado-image-loader": "^3.1.0",
"dcmjs": "0.17.2",
"dcmjs": "0.18.4",
"dicom-parser": "^1.8.3",
"hammerjs": "^2.0.8",
"prop-types": "^15.6.2",
@@ -51,6 +51,6 @@
"classnames": "^2.2.6",
"lodash.merge": "^4.6.2",
"lodash.throttle": "^4.1.1",
"react-cornerstone-viewport": "4.0.4"
"react-cornerstone-viewport": "4.0.5"
}
}
@@ -179,7 +179,7 @@ class OHIFCornerstoneViewport extends Component {
if (
displaySet.displaySetInstanceUID !==
prevDisplaySet.displaySetInstanceUID ||
prevDisplaySet.displaySetInstanceUID ||
displaySet.SOPInstanceUID !== prevDisplaySet.SOPInstanceUID ||
displaySet.frameIndex !== prevDisplaySet.frameIndex
) {
@@ -235,8 +235,8 @@ class OHIFCornerstoneViewport extends Component {
viewportIndex={viewportIndex}
imageIds={imageIds}
imageIdIndex={currentImageIdIndex}
onNewImage={newImageHandler}
onNewImageDebounceTime={700}
onNewImageDebounced={newImageHandler}
onNewImageDebounceTime={300}
// ~~ Connected (From REDUX)
// frameRate={frameRate}
// isPlaying={false}
+8 -1
View File
@@ -268,6 +268,7 @@ const commandsModule = ({ servicesManager }) => {
SOPInstanceUID,
frameIndex,
activeViewportIndex,
refreshViewports = true,
}) => {
const study = studyMetadataManager.get(StudyInstanceUID);
@@ -278,6 +279,10 @@ const commandsModule = ({ servicesManager }) => {
);
});
if (!displaySet) {
return;
}
displaySet.SOPInstanceUID = SOPInstanceUID;
displaySet.frameIndex = frameIndex;
@@ -285,7 +290,9 @@ const commandsModule = ({ servicesManager }) => {
setViewportSpecificData(activeViewportIndex, displaySet)
);
refreshCornerstoneViewports();
if (refreshViewports) {
refreshCornerstoneViewports();
}
},
};
+7
View File
@@ -38,7 +38,14 @@ export default {
},
getViewportModule({ commandsManager }) {
const ExtendedOHIFCornerstoneViewport = props => {
/**
* TODO: This appears to be used to set the redux parameters for
* the viewport when new images are loaded. It's very ugly
* and we should remove it.
*/
const onNewImageHandler = jumpData => {
/** Do not trigger all viewports to render unnecessarily */
jumpData.refreshViewports = false;
commandsManager.runCommand('jumpToImage', jumpData);
};
return (
+19
View File
@@ -3,6 +3,25 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.2.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.2.0...@ohif/extension-debugging@0.2.1) (2021-03-19)
**Note:** Version bump only for package @ohif/extension-debugging
# [0.2.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.1.6...@ohif/extension-debugging@0.2.0) (2021-03-04)
### Features
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
## [0.1.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.1.5...@ohif/extension-debugging@0.1.6) (2020-10-06)
**Note:** Version bump only for package @ohif/extension-debugging
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-debugging",
"version": "0.1.6",
"version": "0.2.1",
"description": "OHIF extension for debugging.",
"author": "OHIF",
"license": "MIT",
@@ -12,3 +12,15 @@
display: flex;
flex-direction: row;
}
.debug-report-modal-container .errors {
margin-top: 10px;
}
.debug-report-modal-container .errors-container {
border: 1px solid var(--active-color);
border-radius: 5px;
padding: 10px;
overflow: scroll;
max-height: 300px;
}
@@ -10,6 +10,7 @@ const DubugReportModal = ({
extensionManager,
mailTo,
debugModalMessage,
errors = [],
}) => {
const copyDebugDataToClipboard = () => {
const body = getEmailBody();
@@ -131,6 +132,19 @@ const DubugReportModal = ({
{getLayout(viewports)}
</table>
</div>
<div className="errors">
<h3>Errors ({errors.length})</h3>
<div className="errors-container">
{errors.map(error => {
return (
<div>
<pre>Message: {error.message}</pre>
{error.error && <pre>Stack: {error.error.stack}</pre>}
</div>
);
})}
</div>
</div>
</div>
);
};
@@ -1,4 +1,6 @@
import OHIF from '@ohif/core';
import { useLogger } from '@ohif/ui';
import {
save,
upload,
@@ -95,6 +97,7 @@ export function getCommands(context, servicesManager, extensionManager) {
const { UIModalService } = servicesManager.services;
const WrappedDebugReportModal = function() {
const { state: loggerState } = useLogger();
return (
<DebugReportModal
viewports={viewports}
@@ -103,6 +106,7 @@ export function getCommands(context, servicesManager, extensionManager) {
extensionManager={extensionManager}
mailTo={state.mailTo}
debugModalMessage={state.debugModalMessage}
errors={loggerState.errors}
/>
);
};
+1 -1
View File
@@ -1,3 +1,3 @@
const state = { mailTo: undefined, message: undefined };
const state = { mailTo: undefined, debugModalMessage: undefined };
export default state;
+56
View File
@@ -3,6 +3,62 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.3.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.7...@ohif/extension-dicom-html@1.3.8) (2021-04-22)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.6...@ohif/extension-dicom-html@1.3.7) (2021-04-21)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.5...@ohif/extension-dicom-html@1.3.6) (2021-04-21)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.4...@ohif/extension-dicom-html@1.3.5) (2021-04-15)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.3...@ohif/extension-dicom-html@1.3.4) (2021-03-09)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.2...@ohif/extension-dicom-html@1.3.3) (2021-03-03)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.1...@ohif/extension-dicom-html@1.3.2) (2021-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.0...@ohif/extension-dicom-html@1.3.1) (2021-02-05)
**Note:** Version bump only for package @ohif/extension-dicom-html
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-html",
"version": "1.3.1",
"version": "1.3.8",
"description": "OHIF extension for rendering structured reports to HTML",
"author": "OHIF",
"license": "MIT",
@@ -29,7 +29,7 @@
},
"peerDependencies": {
"@ohif/core": "^0.50.0",
"dcmjs": "0.17.2",
"dcmjs": "0.18.5",
"prop-types": "^15.6.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"
@@ -9,6 +9,7 @@ const SOP_CLASS_UIDS = {
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',
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',
};
const sopClassUIDs = Object.values(SOP_CLASS_UIDS);
+11
View File
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [0.52.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.51.4...@ohif/extension-dicom-microscopy@0.52.0) (2021-03-04)
### Features
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
## [0.51.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.51.3...@ohif/extension-dicom-microscopy@0.51.4) (2021-01-21)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-microscopy",
"version": "0.51.4",
"version": "0.52.0",
"description": "OHIF extension for Dicom Microscopy",
"author": "OHIF",
"license": "MIT",
@@ -70,12 +70,18 @@ class DicomMicroscopyViewport extends Component {
});
} catch (error) {
console.error('[Microscopy Viewer] Failed to load:', error);
const { UINotificationService } = this.props.servicesManager.services;
const {
UINotificationService,
LoggerService,
} = this.props.servicesManager.services;
if (UINotificationService) {
const message =
'Failed to load viewport. Please check that you have hardware acceleration enabled.';
LoggerService.error({ error, message });
UINotificationService.show({
autoClose: false,
title: 'Microscopy Viewport',
message:
'Failed to load viewport. Please check that you have hardware acceleration enabled.',
message,
type: 'error',
});
}
+48
View File
@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.6.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.6.9...@ohif/extension-dicom-rt@0.6.10) (2021-04-22)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.6.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.6.8...@ohif/extension-dicom-rt@0.6.9) (2021-04-21)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.6.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.6.7...@ohif/extension-dicom-rt@0.6.8) (2021-04-15)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.6.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.6.6...@ohif/extension-dicom-rt@0.6.7) (2021-03-09)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.6.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.6.5...@ohif/extension-dicom-rt@0.6.6) (2021-03-03)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.6.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.6.4...@ohif/extension-dicom-rt@0.6.5) (2021-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.6.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.6.3...@ohif/extension-dicom-rt@0.6.4) (2021-02-05)
**Note:** Version bump only for package @ohif/extension-dicom-rt
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-rt",
"version": "0.6.4",
"version": "0.6.10",
"description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.",
"author": "OHIF",
"license": "MIT",
@@ -31,7 +31,7 @@
"@ohif/core": "^0.50.0",
"cornerstone-core": "^2.2.8",
"cornerstone-tools": "^4.20.1",
"dcmjs": "0.17.2",
"dcmjs": "0.18.5",
"gl-matrix": "^3.3.0",
"prop-types": "^15.6.2",
"react": "^16.8.6",
@@ -3,6 +3,89 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.6.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.6.6...@ohif/extension-dicom-segmentation@0.6.7) (2021-04-22)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.6.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.6.5...@ohif/extension-dicom-segmentation@0.6.6) (2021-04-21)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.6.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.6.4...@ohif/extension-dicom-segmentation@0.6.5) (2021-04-21)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.6.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.6.3...@ohif/extension-dicom-segmentation@0.6.4) (2021-04-16)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.6.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.6.2...@ohif/extension-dicom-segmentation@0.6.3) (2021-04-15)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.6.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.6.1...@ohif/extension-dicom-segmentation@0.6.2) (2021-03-31)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.6.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.6.0...@ohif/extension-dicom-segmentation@0.6.1) (2021-03-09)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
# [0.6.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.5.4...@ohif/extension-dicom-segmentation@0.6.0) (2021-03-04)
### Features
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
## [0.5.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.5.3...@ohif/extension-dicom-segmentation@0.5.4) (2021-03-03)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.5.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.5.2...@ohif/extension-dicom-segmentation@0.5.3) (2021-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.5.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.5.1...@ohif/extension-dicom-segmentation@0.5.2) (2021-02-05)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-segmentation",
"version": "0.5.2",
"version": "0.6.7",
"description": "OHIF extension for viewing segmentations in the 2D MPR view",
"author": "OHIF",
"license": "MIT",
@@ -31,7 +31,7 @@
"@ohif/core": "^0.50.0",
"cornerstone-core": "^2.2.8",
"cornerstone-tools": "^4.20.1",
"dcmjs": "0.17.2",
"dcmjs": "0.18.5",
"prop-types": "^15.6.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"
@@ -155,7 +155,9 @@ const SegmentationPanel = ({
const brushStackState = getBrushStackState();
brushStackState.activeLabelmapIndex = newLabelmapIndex;
setState(state => ({ ...state, selectedSegmentation }));
if (selectedSegmentation) {
setState(state => ({ ...state, selectedSegmentation }));
}
refreshViewports();
@@ -189,6 +191,10 @@ const SegmentationPanel = ({
'extensiondicomsegmentationsegloaded',
refreshSegmentations
);
document.addEventListener(
'extensiondicomsegmentationsegselected',
updateSegmentationComboBox
);
/*
* These are specific to each element;
@@ -207,6 +213,10 @@ const SegmentationPanel = ({
'extensiondicomsegmentationsegloaded',
refreshSegmentations
);
document.removeEventListener(
'extensiondicomsegmentationsegselected',
updateSegmentationComboBox
);
cornerstoneTools.store.state.enabledElements.forEach(enabledElement =>
enabledElement.removeEventListener(
'cornerstonetoolslabelmapmodified',
@@ -216,6 +226,27 @@ const SegmentationPanel = ({
};
}, [activeIndex, viewports]);
const updateSegmentationComboBox = (e) => {
const index = e.detail.activatedLabelmapIndex;
if (index !== -1) {
setState(state => ({ ...state, selectedSegmentation: index }));
} else {
cleanSegmentationComboBox();
}
}
const cleanSegmentationComboBox = () => {
setState(state => ({
...state,
segmentsHidden: [],
segmentNumbers: [],
labelMapList: [],
segmentList: [],
isDisabled: true,
selectedSegmentation: -1,
}));
}
const refreshSegmentations = () => {
const activeViewport = getActiveViewport();
const isDisabled = !activeViewport || !activeViewport.StudyInstanceUID;
@@ -277,7 +308,10 @@ const SegmentationPanel = ({
activeViewport.SeriesInstanceUID
);
return referencedSegDisplaysets.map((displaySet, index) => {
const filteredReferencedSegDisplaysets = referencedSegDisplaysets.filter(
(segDisplay => segDisplay.loadError !== true));
return filteredReferencedSegDisplaysets.map((displaySet, index) => {
const {
labelmapIndex,
originLabelMapIndex,
@@ -289,7 +323,7 @@ const SegmentationPanel = ({
/* Map to display representation */
const dateStr = `${SeriesDate}:${SeriesTime}`.split('.')[0];
const date = moment(dateStr, 'YYYYMMDD:HHmmss');
const displayDate = date.format('ddd, MMM Do YYYY');
const displayDate = date.format('ddd, MMM Do YYYY, h:mm:ss a');
const displayDescription = displaySet.SeriesDescription;
return {
@@ -709,7 +743,7 @@ const _getReferencedSegDisplaysets = (StudyInstanceUID, SeriesInstanceUID) => {
referencedDisplaysets.sort((a, b) => {
const aNumber = Number(`${a.SeriesDate}${a.SeriesTime}`);
const bNumber = Number(`${b.SeriesDate}${b.SeriesTime}`);
return aNumber - bNumber;
return bNumber - aNumber;
});
return referencedDisplaysets;
@@ -3,7 +3,7 @@ import Select from 'react-select';
const SegmentationSelect = ({ value, formatOptionLabel, options }) => (
<Select
value={value}
value={value === undefined ? null : value}
formatOptionLabel={formatOptionLabel}
styles={segmentationSelectStyles}
options={options}
@@ -55,6 +55,7 @@ export default function getSopClassHandlerModule({ servicesManager }) {
referencedDisplaySetUID: null, // Assigned when loaded.
labelmapIndex: null, // Assigned when loaded.
isLoaded: false,
loadError: false,
hasOverlapping: false,
SeriesDate,
SeriesTime,
@@ -63,8 +64,8 @@ export default function getSopClassHandlerModule({ servicesManager }) {
metadata,
};
segDisplaySet.getSourceDisplaySet = function(studies) {
return getSourceDisplaySet(studies, segDisplaySet);
segDisplaySet.getSourceDisplaySet = function(studies, activateLabelMap = true, onDisplaySetLoadFailureHandler) {
return getSourceDisplaySet(studies, segDisplaySet, activateLabelMap, onDisplaySetLoadFailureHandler);
};
segDisplaySet.load = async function(referencedDisplaySet, studies) {
@@ -82,57 +83,50 @@ export default function getSopClassHandlerModule({ servicesManager }) {
StudyInstanceUID,
referencedDisplaySet.SeriesInstanceUID
);
return new Promise(async (resolve, reject) => {
let results;
try {
results = _parseSeg(segArrayBuffer, imageIds);
} catch (error) {
segDisplaySet.isLoaded = false;
segDisplaySet.loadError = true;
reject(error);
}
const {
labelmapBufferArray,
segMetadata,
segmentsOnFrame,
segmentsOnFrameArray,
} = results;
let labelmapIndex;
if (labelmapBufferArray.length > 1) {
let labelmapIndexes = [];
for (let i = 0; i < labelmapBufferArray.length; ++i) {
labelmapIndexes.push(
await loadSegmentation(
imageIds,
segDisplaySet,
labelmapBufferArray[i],
segMetadata,
segmentsOnFrame,
segmentsOnFrameArray[i]
)
);
}
/**
* Since overlapping segmentations have virtual labelmaps,
* originLabelMapIndex is used in the panel to select the correct dropdown value.
*/
segDisplaySet.hasOverlapping = true;
segDisplaySet.originLabelMapIndex = labelmapIndexes[0];
labelmapIndex = labelmapIndexes[0];
console.warn('Overlapping segmentations!');
} else {
labelmapIndex = await loadSegmentation(
imageIds,
segDisplaySet,
labelmapBufferArray[0],
segMetadata,
segmentsOnFrame,
[]
const results = await _parseSeg(segArrayBuffer, imageIds);
if (results === undefined) {
return;
}
const {
labelmapBufferArray,
segMetadata,
segmentsOnFrame,
segmentsOnFrameArray,
} = results;
let labelmapIndex;
if (labelmapBufferArray.length > 1) {
let labelmapIndexes = [];
for (let i = 0; i < labelmapBufferArray.length; ++i) {
labelmapIndexes.push(
await loadSegmentation(
imageIds,
segDisplaySet,
labelmapBufferArray[i],
segMetadata,
segmentsOnFrame,
segmentsOnFrameArray[i]
)
);
}
resolve(labelmapIndex);
});
/**
* Since overlapping segments have virtual labelmaps,
* originLabelMapIndex is used in the panel to select the correct dropdown value.
*/
segDisplaySet.hasOverlapping = true;
segDisplaySet.originLabelMapIndex = labelmapIndexes[0];
labelmapIndex = labelmapIndexes[0];
console.warn('Overlapping segments!');
} else {
labelmapIndex = await loadSegmentation(
imageIds,
segDisplaySet,
labelmapBufferArray[0],
segMetadata,
segmentsOnFrame,
[]
);
}
};
return segDisplaySet;
@@ -1,88 +1,16 @@
import setActiveLabelmap from './utils/setActiveLabelMap';
import { classes } from '@ohif/core';
import { getReferencedDisplaySet } from '../../../platform/core/src/classes/metadata/StudyMetadata.js';
const { ImageSet } = classes;
export default function getSourceDisplaySet(studies, segDisplaySet, activateLabelMap = true, onDisplaySetLoadFailureHandler) {
const referencedDisplaySet = getReferencedDisplaySet(segDisplaySet, studies);
export default function getSourceDisplaySet(studies, segDisplaySet) {
const referencedDisplaySet = _getReferencedDisplaySet(segDisplaySet, studies);
setActiveLabelmap(referencedDisplaySet, studies, segDisplaySet);
return referencedDisplaySet;
}
const _getReferencedDisplaySet = (segDisplaySet, studies) => {
let allDisplaySets = [];
studies.forEach(study => {
allDisplaySets = allDisplaySets.concat(study.displaySets);
});
const otherDisplaySets = allDisplaySets.filter(
ds => ds.displaySetInstanceUID !== segDisplaySet.displaySetInstanceUID
);
const { metadata } = segDisplaySet;
let referencedSeriesInstanceUIDs;
if (metadata.ReferencedSeriesSequence) {
const ReferencedSeriesSequence = _toArray(
metadata.ReferencedSeriesSequence
);
referencedSeriesInstanceUIDs = ReferencedSeriesSequence.map(
ReferencedSeries => ReferencedSeries.SeriesInstanceUID
);
} else {
const { PerFrameFunctionalGroupsSequence } = metadata;
let SourceImageSequence;
if (metadata.SourceImageSequence) {
SourceImageSequence = metadata.SourceImageSequence;
} else {
const firstFunctionalGroups = _toArray(
PerFrameFunctionalGroupsSequence
)[0];
const { DerivationImageSequence } = firstFunctionalGroups;
SourceImageSequence = DerivationImageSequence;
}
const firstSourceImage = _toArray(SourceImageSequence)[0];
const { ReferencedSOPInstanceUID } = firstSourceImage;
referencedSeriesInstanceUIDs = _findReferencedSeriesInstanceUIDsFromSOPInstanceUID(
otherDisplaySets,
ReferencedSOPInstanceUID
);
let activatedLabelmapPromise;
if (activateLabelMap) {
activatedLabelmapPromise = setActiveLabelmap(referencedDisplaySet, studies, segDisplaySet, undefined, onDisplaySetLoadFailureHandler);
}
const referencedDisplaySet = otherDisplaySets.find(ds =>
referencedSeriesInstanceUIDs.includes(ds.SeriesInstanceUID)
);
return referencedDisplaySet;
};
const _findReferencedSeriesInstanceUIDsFromSOPInstanceUID = (
displaySets,
SOPInstanceUID
) => {
const imageSets = displaySets.filter(ds => ds instanceof ImageSet);
for (let i = 0; i < imageSets.length; i++) {
const { images } = imageSets[i];
for (let j = 0; j < images.length; j++) {
if (images[j].SOPInstanceUID === SOPInstanceUID) {
return [images[j].getData().metadata.SeriesInstanceUID];
}
}
return {
referencedDisplaySet : referencedDisplaySet,
activatedLabelmapPromise : activatedLabelmapPromise
}
};
function _toArray(arrayOrObject) {
return Array.isArray(arrayOrObject) ? arrayOrObject : [arrayOrObject];
}
+2 -1
View File
@@ -25,12 +25,13 @@ export default {
return toolbarModule;
},
getPanelModule({ commandsManager, api, servicesManager }) {
const { UINotificationService } = servicesManager.services;
const { UINotificationService, LoggerService } = servicesManager.services;
const ExtendedSegmentationPanel = props => {
const { activeContexts } = api.hooks.useAppContext();
const onDisplaySetLoadFailureHandler = error => {
LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: 'DICOM Segmentation Loader',
message: error.message,
@@ -20,7 +20,7 @@ export default async function setActiveLabelmap(
displaySet,
callback = () => {},
onDisplaySetLoadFailure = err => {
throw new Error(err.message);
console.error(err.message);
}
) {
const studyMetadata = studyMetadataManager.get(
@@ -48,16 +48,15 @@ export default async function setActiveLabelmap(
}
if (!displaySet.isLoaded) {
const loadPromise = displaySet.load(referencedDisplaySet, studies);
loadPromise.catch(error => {
try {
await displaySet.load(referencedDisplaySet, studies);
} catch (error) {
displaySet.isLoaded = false;
displaySet.loadError = true;
onDisplaySetLoadFailure(error);
// Return old index.
return activeLabelmapIndex;
});
await loadPromise;
return -1;
}
}
labelmapIndex =
@@ -67,8 +66,11 @@ export default async function setActiveLabelmap(
// This might have just been created, so need to use the non-cached value.
state = cornerstoneTools.getModule('segmentation').state;
brushStackState = state.series[firstImageId];
brushStackState.activeLabelmapIndex = labelmapIndex;
if (brushStackState) {
brushStackState.activeLabelmapIndex = labelmapIndex;
}
refreshViewports();
callback();
+48
View File
@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.2.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.7...@ohif/extension-dicom-tag-browser@0.2.8) (2021-04-22)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.6...@ohif/extension-dicom-tag-browser@0.2.7) (2021-04-21)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.5...@ohif/extension-dicom-tag-browser@0.2.6) (2021-04-15)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.4...@ohif/extension-dicom-tag-browser@0.2.5) (2021-03-09)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.3...@ohif/extension-dicom-tag-browser@0.2.4) (2021-03-03)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.2...@ohif/extension-dicom-tag-browser@0.2.3) (2021-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.1...@ohif/extension-dicom-tag-browser@0.2.2) (2021-02-05)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-tag-browser",
"version": "0.2.2",
"version": "0.2.8",
"description": "OHIF extension for checking DICOM headers.",
"author": "OHIF",
"license": "MIT",
@@ -28,7 +28,7 @@
},
"peerDependencies": {
"@ohif/core": "^2.6.0",
"dcmjs": "0.17.2",
"dcmjs": "0.18.5",
"react": "^16.8.6"
},
"dependencies": {
+107
View File
@@ -3,6 +3,113 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.11.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.9...@ohif/extension-vtk@1.11.10) (2021-04-22)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.11.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.8...@ohif/extension-vtk@1.11.9) (2021-04-21)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.11.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.7...@ohif/extension-vtk@1.11.8) (2021-04-21)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.11.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.6...@ohif/extension-vtk@1.11.7) (2021-04-21)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.11.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.5...@ohif/extension-vtk@1.11.6) (2021-04-16)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.11.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.4...@ohif/extension-vtk@1.11.5) (2021-04-15)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.11.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.3...@ohif/extension-vtk@1.11.4) (2021-03-26)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.11.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.2...@ohif/extension-vtk@1.11.3) (2021-03-25)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.11.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.1...@ohif/extension-vtk@1.11.2) (2021-03-09)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.11.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.0...@ohif/extension-vtk@1.11.1) (2021-03-09)
**Note:** Version bump only for package @ohif/extension-vtk
# [1.11.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.10.6...@ohif/extension-vtk@1.11.0) (2021-03-04)
### Features
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
## [1.10.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.10.5...@ohif/extension-vtk@1.10.6) (2021-03-03)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.10.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.10.4...@ohif/extension-vtk@1.10.5) (2021-02-25)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.10.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.10.3...@ohif/extension-vtk@1.10.4) (2021-02-05)
**Note:** Version bump only for package @ohif/extension-vtk
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-vtk",
"version": "1.10.4",
"version": "1.11.10",
"description": "OHIF extension for VTK.js",
"author": "OHIF",
"license": "MIT",
@@ -35,7 +35,7 @@
"cornerstone-core": "^2.2.8",
"cornerstone-tools": "^4.20.1",
"cornerstone-wado-image-loader": "^3.1.0",
"dcmjs": "0.17.2",
"dcmjs": "0.18.5",
"dicom-parser": "^1.8.3",
"i18next": "^17.0.3",
"i18next-browser-languagedetector": "^3.0.1",
@@ -53,8 +53,8 @@
"react-vtkjs-viewport": "^0.14.2"
},
"devDependencies": {
"@ohif/core": "^2.12.3",
"@ohif/ui": "^1.8.2",
"@ohif/core": "^2.13.9",
"@ohif/ui": "^1.9.1",
"cornerstone-tools": "^4.20.1",
"cornerstone-wado-image-loader": "^3.1.0",
"dicom-parser": "^1.8.3",
+10 -3
View File
@@ -360,12 +360,15 @@ class OHIFVTKViewport extends Component {
} catch (error) {
const errorTitle = 'Failed to load 2D MPR';
console.error(errorTitle, error);
const { UINotificationService } = this.props.servicesManager.services;
const {
UINotificationService,
LoggerService,
} = this.props.servicesManager.services;
if (this.props.viewportIndex === 0) {
const message = error.message.includes('buffer')
? 'Dataset is too big to display in MPR'
: error.message;
console.error(errorTitle, error);
LoggerService.error({ error, message });
UINotificationService.show({
title: errorTitle,
message,
@@ -428,11 +431,15 @@ class OHIFVTKViewport extends Component {
};
const onPixelDataInsertedErrorCallback = error => {
const { UINotificationService } = this.props.servicesManager.services;
const {
UINotificationService,
LoggerService,
} = this.props.servicesManager.services;
if (!this.hasError) {
if (this.props.viewportIndex === 0) {
// Only show the notification from one viewport 1 in MPR2D.
LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: 'MPR Load Error',
message: error.message,
+8 -4
View File
@@ -14,7 +14,9 @@ import OHIFVTKViewport from './OHIFVTKViewport';
const { BlendMode } = Constants;
const commandsModule = ({ commandsManager, UINotificationService }) => {
const commandsModule = ({ commandsManager, servicesManager }) => {
const { UINotificationService, LoggerService } = servicesManager.services;
// TODO: Put this somewhere else
let apis = {};
let defaultVOI;
@@ -175,7 +177,7 @@ const commandsModule = ({ commandsManager, UINotificationService }) => {
segmentNumber,
frameIndex,
frame,
done = () => { },
done = () => {},
}) => {
let api = apis[viewports.activeViewportIndex];
@@ -473,10 +475,12 @@ const commandsModule = ({ commandsManager, UINotificationService }) => {
const volumeLength = dimensions[0] * dimensions[1] * dimensions[2];
if (volumeLength > maxBufferLengthFloat32) {
const message =
'This volume is too large to fit in WebGL 1 textures and will display incorrectly. Please use a different browser to view this data';
LoggerService.error({ message });
UINotificationService.show({
title: 'Browser does not support WebGL 2',
message:
'This volume is too large to fit in WebGL 1 textures and will display incorrectly. Please use a different browser to view this data',
message,
type: 'error',
autoClose: false,
});
+1 -2
View File
@@ -35,8 +35,7 @@ const vtkExtension = {
return toolbarModule;
},
getCommandsModule({ commandsManager, servicesManager }) {
const { UINotificationService } = servicesManager.services;
return commandsModule({ commandsManager, UINotificationService });
return commandsModule({ commandsManager, servicesManager });
},
};
@@ -31,63 +31,7 @@ const _isDisplaySetReconstructable = (viewportSpecificData = {}, activeViewportI
if (!displaySet) {
return false;
}
// 2D MPR is not currently available for 4D datasets.
// Assuming that slices at different time have the same position, here we just check if
// there are multiple slices for the same ImagePositionPatient and disable MPR.
// A better heuristic would be checking 4D tags, e.g. the presence of multiple TemporalPositionIdentifier values.
// However, some studies (e.g. https://github.com/OHIF/Viewers/issues/2113) do not have such tags.
for (let ii = 0; ii < displaySet.numImageFrames; ++ii) {
const image = displaySet.images[ii];
if (!image) continue;
const imageIdControl = image.getImageId()
const instanceMetadataControl = cornerstone.metaData.get('instance', imageIdControl)
if (!instanceMetadataControl ||
instanceMetadataControl === undefined ||
!instanceMetadataControl.ImagePositionPatient ||
instanceMetadataControl.ImagePositionPatient === undefined) {
// if ImagePositionPatient is missing, skip the 4D datasets check.
// do not return false, because it could be a 3D dataset.
continue;
}
let xImagePositionPatientControl = instanceMetadataControl.ImagePositionPatient[0];
let yImagePositionPatientControl = instanceMetadataControl.ImagePositionPatient[1];
let zImagePositionPatientControl = instanceMetadataControl.ImagePositionPatient[2];
for (let jj = ii + 1; jj < displaySet.numImageFrames; ++jj) {
const image = displaySet.images[jj];
if (!image) continue;
const imageId = image.getImageId()
const instanceMetadata = cornerstone.metaData.get('instance', imageId)
if (!instanceMetadata ||
instanceMetadata === undefined ||
!instanceMetadata.ImagePositionPatient ||
instanceMetadata.ImagePositionPatient === undefined) {
// if ImagePositionPatient is missing, skip the 4D datasets check.
// do not return false, because it could be a 3D dataset.
continue;
}
let xImagePositionPatient = instanceMetadata.ImagePositionPatient[0];
let yImagePositionPatient = instanceMetadata.ImagePositionPatient[1];
let zImagePositionPatient = instanceMetadata.ImagePositionPatient[2];
if (xImagePositionPatientControl === xImagePositionPatient &&
yImagePositionPatientControl === yImagePositionPatient &&
zImagePositionPatientControl === zImagePositionPatient) {
return false;
}
}
}
};
return displaySet.isReconstructable;
};
+105
View File
@@ -3,6 +3,111 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.13.9](https://github.com/OHIF/Viewers/compare/@ohif/core@2.13.8...@ohif/core@2.13.9) (2021-04-22)
**Note:** Version bump only for package @ohif/core
## [2.13.8](https://github.com/OHIF/Viewers/compare/@ohif/core@2.13.7...@ohif/core@2.13.8) (2021-04-21)
**Note:** Version bump only for package @ohif/core
## [2.13.7](https://github.com/OHIF/Viewers/compare/@ohif/core@2.13.6...@ohif/core@2.13.7) (2021-04-21)
**Note:** Version bump only for package @ohif/core
## [2.13.6](https://github.com/OHIF/Viewers/compare/@ohif/core@2.13.5...@ohif/core@2.13.6) (2021-04-21)
**Note:** Version bump only for package @ohif/core
## [2.13.5](https://github.com/OHIF/Viewers/compare/@ohif/core@2.13.4...@ohif/core@2.13.5) (2021-04-16)
**Note:** Version bump only for package @ohif/core
## [2.13.4](https://github.com/OHIF/Viewers/compare/@ohif/core@2.13.3...@ohif/core@2.13.4) (2021-04-15)
### Bug Fixes
* **wl:** fix metadata provider window level issues after dicomweb update (string vs number) ([8681036](https://github.com/OHIF/Viewers/commit/8681036b2133cfc325658691a256a86b5e36705f))
## [2.13.3](https://github.com/OHIF/Viewers/compare/@ohif/core@2.13.2...@ohif/core@2.13.3) (2021-03-26)
**Note:** Version bump only for package @ohif/core
## [2.13.2](https://github.com/OHIF/Viewers/compare/@ohif/core@2.13.1...@ohif/core@2.13.2) (2021-03-25)
### Bug Fixes
* IDC-2288: Update toolbar tabs after derived displayset loaded ([#2307](https://github.com/OHIF/Viewers/issues/2307)) ([6e723eb](https://github.com/OHIF/Viewers/commit/6e723ebced58852007ca553792c740976cfc4201))
## [2.13.1](https://github.com/OHIF/Viewers/compare/@ohif/core@2.13.0...@ohif/core@2.13.1) (2021-03-09)
**Note:** Version bump only for package @ohif/core
# [2.13.0](https://github.com/OHIF/Viewers/compare/@ohif/core@2.12.5...@ohif/core@2.13.0) (2021-03-04)
### Features
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
## [2.12.5](https://github.com/OHIF/Viewers/compare/@ohif/core@2.12.4...@ohif/core@2.12.5) (2021-03-03)
**Note:** Version bump only for package @ohif/core
## [2.12.4](https://github.com/OHIF/Viewers/compare/@ohif/core@2.12.3...@ohif/core@2.12.4) (2021-02-25)
**Note:** Version bump only for package @ohif/core
## [2.12.3](https://github.com/OHIF/Viewers/compare/@ohif/core@2.12.2...@ohif/core@2.12.3) (2021-02-05)
**Note:** Version bump only for package @ohif/core
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/core",
"version": "2.12.3",
"version": "2.13.9",
"description": "Generic business logic for web-based medical imaging applications",
"author": "OHIF Core Team",
"license": "MIT",
@@ -39,7 +39,7 @@
"dependencies": {
"@babel/runtime": "^7.5.5",
"ajv": "^6.10.0",
"dcmjs": "0.17.2",
"dcmjs": "0.18.5",
"dicomweb-client": "^0.6.0",
"immer": "6.0.2",
"isomorphic-base64": "^1.0.2",
@@ -77,7 +77,6 @@ const parseDicomStructuredReport = (part10SRArrayBuffer, displaySets) => {
/**
* Function to create imagePath with all imageData related
*
* @param {string} StudyInstanceUID
* @param {string} SeriesInstanceUID
* @param {string} SOPInstanceUID
+7 -2
View File
@@ -63,10 +63,15 @@ export class HotkeysManager {
definitions.forEach(definition => this.registerHotkeys(definition));
} catch (error) {
const { UINotificationService } = this._servicesManager.services;
const {
UINotificationService,
LoggerService,
} = this._servicesManager.services;
const message = 'Erro while setting hotkeys';
LoggerService.error({ error, message });
UINotificationService.show({
title: 'Hotkeys Manager',
message: 'Erro while setting hotkeys',
message,
type: 'error',
});
}
@@ -4,6 +4,7 @@ import dicomParser from 'dicom-parser';
import getPixelSpacingInformation from '../utils/metadataProvider/getPixelSpacingInformation';
import fetchPaletteColorLookupTableData from '../utils/metadataProvider/fetchPaletteColorLookupTableData';
import fetchOverlayData from '../utils/metadataProvider/fetchOverlayData';
import validNumber from '../utils/metadataProvider/validNumber';
class MetadataProvider {
constructor() {
@@ -284,7 +285,7 @@ class MetadataProvider {
break;
case WADO_IMAGE_LOADER_TAGS.VOI_LUT_MODULE:
const { WindowCenter, WindowWidth } = instance;
let { WindowCenter, WindowWidth } = instance;
const windowCenter = Array.isArray(WindowCenter)
? WindowCenter
@@ -294,15 +295,17 @@ class MetadataProvider {
: [WindowWidth];
metadata = {
windowCenter,
windowWidth,
windowCenter: validNumber(windowCenter),
windowWidth: validNumber(windowWidth),
};
break;
case WADO_IMAGE_LOADER_TAGS.MODALITY_LUT_MODULE:
const rescaleSlope = validNumber(instance.RescaleSlope);
const rescaleIntercept = validNumber(instance.RescaleIntercept);
metadata = {
rescaleIntercept: instance.RescaleIntercept,
rescaleSlope: instance.RescaleSlope,
rescaleIntercept,
rescaleSlope,
rescaleType: instance.RescaleType,
};
break;
@@ -9,11 +9,11 @@ import { SeriesMetadata } from './SeriesMetadata';
import { api } from 'dicomweb-client';
// - createStacks
import { isImage } from '../../utils/isImage';
import isDisplaySetReconstructable from '../../utils/isDisplaySetReconstructable';
import { isDisplaySetReconstructable, isSpacingUniform } from '../../utils/isDisplaySetReconstructable';
import errorHandler from '../../errorHandler';
import isLowPriorityModality from '../../utils/isLowPriorityModality';
export class StudyMetadata extends Metadata {
class StudyMetadata extends Metadata {
constructor(data, uid) {
super(data, uid);
// Initialize Private Properties
@@ -252,20 +252,7 @@ export class StudyMetadata extends Metadata {
if (referencedSeriesInstanceUID) {
filteredDerivedDisplaySets = filteredDerivedDisplaySets.filter(
displaySet => {
if (!displaySet.metadata.ReferencedSeriesSequence) {
return false;
}
const ReferencedSeriesSequence = Array.isArray(
displaySet.metadata.ReferencedSeriesSequence
)
? displaySet.metadata.ReferencedSeriesSequence
: [displaySet.metadata.ReferencedSeriesSequence];
return ReferencedSeriesSequence.some(
ReferencedSeries =>
ReferencedSeries.SeriesInstanceUID === referencedSeriesInstanceUID
);
return getReferencedDisplaySet(displaySet, [this]).SeriesInstanceUID === referencedSeriesInstanceUID;
}
);
}
@@ -273,7 +260,7 @@ export class StudyMetadata extends Metadata {
if (referencedFrameOfReferenceUID) {
filteredDerivedDisplaySets = filteredDerivedDisplaySets.filter(
displaySet =>
displaySet.ReferencedFrameOfReferenceUID ===
displaySet.FrameOfReferenceUID ===
referencedFrameOfReferenceUID
);
}
@@ -767,6 +754,16 @@ const isMultiFrame = instance => {
return instance.getTagValue('NumberOfFrames') > 1;
};
/**
* Creates a display set for a series.
* Checks if a series is reconstructable to a 3D volume.
* If reconstructable, the frames are sorted.
*
* @param {SeriesMetadata} series The series metadata object from which the display sets will be created
* @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.
*
* @returns {Object} imageSet.
*/
const makeDisplaySet = (series, instances) => {
const instance = instances[0];
const imageSet = new ImageSet(instances);
@@ -786,7 +783,7 @@ const makeDisplaySet = (series, instances) => {
isMultiFrame: isMultiFrame(instance),
});
// Sort the images in this series if needed
// Sort the images in this series by instanceNumber
const shallSort = true; //!OHIF.utils.ObjectPath.get(Meteor, 'settings.public.ui.sortSeriesByIncomingOrder');
if (shallSort) {
imageSet.sortBy((a, b) => {
@@ -804,18 +801,32 @@ const makeDisplaySet = (series, instances) => {
imageSet.getImage(0).getTagValue('InstanceNumber')
);
const isReconstructable = isDisplaySetReconstructable(instances);
imageSet.isReconstructable = isReconstructable.value;
const displayReconstructableInfo = isDisplaySetReconstructable(instances);
imageSet.isReconstructable = displayReconstructableInfo.value;
let displaySpacingInfo = undefined;
if (shallSort && imageSet.isReconstructable) {
// sort images by image position
imageSet.sortByImagePositionPatient();
// check if the spacing is uniform and update isReconstructable
const datasetIs4D = displayReconstructableInfo.warningIssues.find
(issue => issue === ReconstructionIssues.DATASET_4D);
displaySpacingInfo = isSpacingUniform(imageSet.images, datasetIs4D);
imageSet.isReconstructable = displaySpacingInfo.isUniform;
if (displaySpacingInfo.missingFrames) {
// TODO -> This is currently unused, but may be used for reconstructing
// Volumes with gaps later on.
imageSet.missingFrames = displaySpacingInfo.missingFrames;
}
}
if (isReconstructable.missingFrames) {
// TODO -> This is currently unused, but may be used for reconstructing
// Volumes with gaps later on.
imageSet.missingFrames = isReconstructable.missingFrames;
if (!imageSet.displayReconstructableInfo) {
// It is not reconstrabale Save type of warning
imageSet.warningIssues = displaySpacingInfo ?
displayReconstructableInfo.warningIssues.concat(displaySpacingInfo.warningIssues) :
displayReconstructableInfo.warningIssues;
}
return imageSet;
@@ -892,3 +903,184 @@ function _getDisplaySetFromSopClassModule(
}
return displaySet;
}
/**
* Returns the source display set of the derivated display set.
* @param {object} derivatedDisplaySet
* @param {array[StudyMetadata]} studies
* @return {object} source display set.
*/
function getReferencedDisplaySet(derivatedDisplaySet, studies) {
let allDisplaySets = [];
studies.forEach(study => {
allDisplaySets = allDisplaySets.concat(study.displaySets);
});
const otherDisplaySets = allDisplaySets.filter(
ds => ds.displaySetInstanceUID !== derivatedDisplaySet.displaySetInstanceUID
);
const { metadata } = derivatedDisplaySet;
let referencedSeriesInstanceUIDs = _findReferencedSeriesInstanceUIDsFromSourceImageSequence
(metadata, otherDisplaySets);
let noReferencedSeriesAvailable = !referencedSeriesInstanceUIDs ||
referencedSeriesInstanceUIDs.length === 0;
if (noReferencedSeriesAvailable) {
referencedSeriesInstanceUIDs =
_findReferencedSeriesInstanceUIDsFromReferencedSeriesSequence
(metadata);
}
noReferencedSeriesAvailable = !referencedSeriesInstanceUIDs ||
referencedSeriesInstanceUIDs.length === 0;
if (noReferencedSeriesAvailable) {
referencedSeriesInstanceUIDs =
_findReferencedSeriesInstanceUIDsFromReferencedImageSequence
(metadata, otherDisplaySets);
}
const referencedSeriesAvailable = referencedSeriesInstanceUIDs &&
referencedSeriesInstanceUIDs.length !== 0;
if (referencedSeriesAvailable) {
const referencedDisplaySet = otherDisplaySets.find(ds =>
referencedSeriesInstanceUIDs.includes(ds.SeriesInstanceUID)
);
;
return referencedDisplaySet;
}
};
/**
* Returns the referenced series instance UIDs by searching the information in the
* ReferencedSeriesSequence.
* @param {object} derivatedDisplaySet.metadata
* @return {array[string]} referenced series instance UIDs.
*/
function _findReferencedSeriesInstanceUIDsFromReferencedSeriesSequence (
metadata,
) {
if (!metadata.ReferencedSeriesSequence) {
return;
}
let referencedSeriesInstanceUIDs;
const ReferencedSeriesSequence = _toArray(
metadata.ReferencedSeriesSequence
);
referencedSeriesInstanceUIDs = ReferencedSeriesSequence.map(
ReferencedSeries => ReferencedSeries.SeriesInstanceUID
);
return referencedSeriesInstanceUIDs;
};
/**
* Returns the referenced series instance UIDs by searching the information in the
* ReferencedImageSequence.
* @param {object} derivatedDisplaySet.metadata
* @param {array[object]} displaysets
* @return {array[string]} referenced series instance UIDs.
*/
function _findReferencedSeriesInstanceUIDsFromReferencedImageSequence (
metadata,
displaySets
) {
if (!metadata.ReferencedImageSequence) {
return;
}
let referencedSeriesInstanceUIDs;
const referencedImageArray = _toArray(metadata.ReferencedImageSequence);
for (let i = 0; i < referencedImageArray.length; i++) {
const { ReferencedSOPInstanceUID } = referencedImageArray[i];
referencedSeriesInstanceUIDs = _findReferencedSeriesInstanceUIDsFromSOPInstanceUID(
displaySets,
ReferencedSOPInstanceUID
);
if (referencedSeriesInstanceUIDs && referencedSeriesInstanceUIDs.length !== 0) {
break;
}
}
return referencedSeriesInstanceUIDs;
};
/**
* Returns the referenced series instance UIDs by searching the information in the
* SourceImageSequence.
* @param {object} derivatedDisplaySet.metadata
* @param {array[object]} displaysets
* @return {array[string]} referenced series instance UIDs.
*/
function _findReferencedSeriesInstanceUIDsFromSourceImageSequence (
metadata,
displaySets
) {
let SourceImageSequence;
if (metadata.SourceImageSequence) {
SourceImageSequence = metadata.SourceImageSequence;
} else {
const { PerFrameFunctionalGroupsSequence } = metadata;
const firstFunctionalGroups = _toArray(
PerFrameFunctionalGroupsSequence
)[0];
const { DerivationImageSequence } = firstFunctionalGroups;
SourceImageSequence = DerivationImageSequence;
}
if (!SourceImageSequence) {
return;
}
const sourceImageArray = _toArray(SourceImageSequence);
let referencedSeriesInstanceUIDs;
for (let i = 0; i < sourceImageArray.length; i++) {
const { ReferencedSOPInstanceUID } = sourceImageArray[i];
referencedSeriesInstanceUIDs = _findReferencedSeriesInstanceUIDsFromSOPInstanceUID(
displaySets,
ReferencedSOPInstanceUID
);
if (referencedSeriesInstanceUIDs && referencedSeriesInstanceUIDs.length !== 0) {
break;
}
}
return referencedSeriesInstanceUIDs;
};
/**
* Returns the referenced series instance UIDs by searching the information in the
* SOPInstanceUID of the displaySets.
* @param {array[object]} displaysets
* @param {string} SOPInstanceUID
* @return {array[string]} referenced series instance UIDs.
*/
function _findReferencedSeriesInstanceUIDsFromSOPInstanceUID (
displaySets,
SOPInstanceUID
) {
const imageSets = displaySets.filter(ds => ds instanceof ImageSet);
for (let i = 0; i < imageSets.length; i++) {
const { images } = imageSets[i];
for (let j = 0; j < images.length; j++) {
if (images[j].SOPInstanceUID === SOPInstanceUID) {
return [images[j].getData().metadata.SeriesInstanceUID];
}
}
}
};
function _toArray(arrayOrObject) {
return Array.isArray(arrayOrObject) ? arrayOrObject : [arrayOrObject];
}
export {StudyMetadata, getReferencedDisplaySet};
+11
View File
@@ -0,0 +1,11 @@
const ReconstructionIssues = {
DATASET_4D: 'datasetis4D',
VARYING_IMAGESDIMENSIONS: 'imagesdimensionsvarying',
VARYING_IMAGESCOMPONENTS: 'imagescomponentsvarying',
VARYING_IMAGESORIENTATION: 'imagesorientationvarying',
MISSING_FRAMES: 'missingframes',
IRREGULAR_SPACING: 'irregularspacing',
MULTIFFRAMES: 'multiframe',
};
export {ReconstructionIssues};
+3
View File
@@ -26,6 +26,7 @@ import {
UIModalService,
UIDialogService,
MeasurementService,
LoggerService,
} from './services';
const OHIF = {
@@ -60,6 +61,7 @@ const OHIF = {
UIModalService,
UIDialogService,
MeasurementService,
LoggerService,
};
export {
@@ -93,6 +95,7 @@ export {
UIModalService,
UIDialogService,
MeasurementService,
LoggerService,
};
export { OHIF };
+1
View File
@@ -14,6 +14,7 @@ describe('Top level exports', () => {
'UIModalService',
'UIDialogService',
'MeasurementService',
'LoggerService',
//
'utils',
'hotkeys',
@@ -0,0 +1,67 @@
const name = 'LoggerService';
const publicAPI = {
name,
info: _info,
error: _error,
setServiceImplementation,
};
const serviceImplementation = {
_info: () => console.warn('info() NOT IMPLEMENTED'),
_error: () => console.warn('error() NOT IMPLEMENTED'),
};
/**
* Logs an info
*
* @param {object} props { message, displayOnConsole }
*/
function _info({ message, displayOnConsole }) {
return serviceImplementation._info({
message,
displayOnConsole,
});
}
/**
* Logs an error
*
* @param {object} props { error, stack, message, displayOnConsole }
* @returns void
*/
function _error({ error, stack, message, displayOnConsole }) {
return serviceImplementation._error({
error,
stack,
message,
displayOnConsole,
});
}
/**
*
*
* @param {*} {
* info: infoImplementation,
* error: errorImplementation,
* }
*/
function setServiceImplementation({
info: infoImplementation,
error: errorImplementation,
}) {
if (infoImplementation) {
serviceImplementation._info = infoImplementation;
}
if (errorImplementation) {
serviceImplementation._error = errorImplementation;
}
}
export default {
name,
create: ({ configuration = {} }) => {
return publicAPI;
},
};
+2
View File
@@ -3,6 +3,7 @@ import UINotificationService from './UINotificationService';
import UIModalService from './UIModalService';
import UIDialogService from './UIDialogService';
import MeasurementService from './MeasurementService';
import LoggerService from './LoggerService';
export {
UINotificationService,
@@ -10,4 +11,5 @@ export {
UIDialogService,
ServicesManager,
MeasurementService,
LoggerService,
};
@@ -1,9 +1,14 @@
import { ReconstructionIssues } from './../enums.js';
/**
* Checks if a series is reconstructable to a 3D volume.
*
* @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.
* @param {Object[]} An array of `OHIFInstanceMetadata` objects.
*
* @returns {Object} value, warningIssues.
*/
export default function isDisplaySetReconstructable(instances) {
function isDisplaySetReconstructable(instances) {
if (!instances.length) {
return { value: false };
}
@@ -23,31 +28,45 @@ export default function isDisplaySetReconstructable(instances) {
}
if (isMultiframe) {
return processMultiframe(instances[0]);
return processMultiframe();
} else {
return processSingleframe(instances);
}
}
function processMultiframe(instance) {
//TODO: deal with multriframe checks! return false for now as can't reconstruct.
return { value: false };
/**
* Process reconstructable multiframes checks
* TODO: deal with multriframe checks! return false for now as can't reconstruct.
* *
* @returns {Object} value and warningIssues.
*/
function processMultiframe() {
const warningIssues = [ReconstructionIssues.MULTIFRAMES];
return { value: false, warningIssues };
}
/**
* Process reconstructable single frame checks
*
* @param {Object[]} An array of `OHIFInstanceMetadata` objects.
*
* @returns {Object} value and warningIssues.
*/
function processSingleframe(instances) {
const n = instances.length;
const firstImage = instances[0].getData().metadata;
const firstImageRows = firstImage.Rows;
const firstImageColumns = firstImage.Columns;
const firstImageSamplesPerPixel = firstImage.SamplesPerPixel;
const firstImageOrientationPatient = firstImage.ImageOrientationPatient;
const firstImagePositionPatient = firstImage.ImagePositionPatient;
const warningIssues = [];
// Can't reconstruct if we:
// -- Have a different dimensions within a displaySet.
// -- Have a different number of components within a displaySet.
// -- Have different orientations within a displaySet.
for (let i = 1; i < instances.length; i++) {
const instance = instances[i].getData().metadata;
for (let ii = 1; ii < n; ++ii) {
const instance = instances[ii].getData().metadata;
const {
Rows,
Columns,
@@ -55,67 +74,146 @@ function processSingleframe(instances) {
ImageOrientationPatient,
} = instance;
if (
Rows !== firstImageRows ||
Columns !== firstImageColumns ||
SamplesPerPixel !== firstImageSamplesPerPixel ||
!_isSameOrientation(ImageOrientationPatient, firstImageOrientationPatient)
) {
return { value: false };
if (Rows !== firstImageRows || Columns !== firstImageColumns) {
warningIssues.push(ReconstructionIssues.VARYING_IMAGESDIMENSIONS);
} else if (SamplesPerPixel !== firstImageSamplesPerPixel) {
warningIssues.push(ReconstructionIssues.VARYING_IMAGESCOMPONENTS);
} else if (!_isSameArray(ImageOrientationPatient, firstImageOrientationPatient)) {
warningIssues.push(ReconstructionIssues.VARYING_IMAGESORIENTATION);
}
if (warningIssues.length !== 0) {
break;
}
}
// check if dataset is 4D
if (_isDataset4D(instances)) {
warningIssues.push(ReconstructionIssues.DATASET_4D);
}
return { value: warningIssues.length === 0 ? true : false, warningIssues };
}
/**
* Check is the spacing is uniform.
* The input metadata array has to be ordered by image position.
*
* @param {Object[]} An array of `OHIFInstanceMetadata` objects.
* @param {boolean} is the dataset 4D.
*
* @returns {Object} isUniform, warningIssues and missingFrames
*/
function isSpacingUniform(instances, datasetIs4D) {
const n = instances.length;
const firstImage = instances[0].getData().metadata;
const firstImagePositionPatient = firstImage.ImagePositionPatient;
const warningIssues = [];
let missingFrames = 0;
// Check if frame spacing is approximately equal within a spacingTolerance.
// If spacing is on a uniform grid but we are missing frames,
// Allow reconstruction, but pass back the number of missing frames.
if (instances.length > 2) {
const lastIpp = instances[instances.length - 1].getData().metadata
if (n > 2) {
const lastIpp = instances[n - 1].getData().metadata
.ImagePositionPatient;
// We can't reconstruct if we are missing ImagePositionPatient values
if (!firstImagePositionPatient || !lastIpp) {
return { value: false };
}
if (firstImagePositionPatient && lastIpp) {
const averageSpacingBetweenFrames =
_getPerpendicularDistance(firstImagePositionPatient, lastIpp) /
(n - 1);
const averageSpacingBetweenFrames =
_getPerpendicularDistance(firstImagePositionPatient, lastIpp) /
(instances.length - 1);
let previousImagePositionPatient = firstImagePositionPatient;
let previousImagePositionPatient = firstImagePositionPatient;
for (let ii = 1; ii < n; ++ii) {
const instance = instances[ii].getData().metadata;
const { ImagePositionPatient } = instance;
for (let i = 1; i < instances.length; i++) {
const instance = instances[i].getData().metadata;
const { ImagePositionPatient } = instance;
const spacingBetweenFrames = _getPerpendicularDistance(
ImagePositionPatient,
previousImagePositionPatient
);
const spacingBetweenFrames = _getPerpendicularDistance(
ImagePositionPatient,
previousImagePositionPatient
);
const spacingIssue = _getSpacingIssue(
spacingBetweenFrames,
averageSpacingBetweenFrames
);
if (spacingIssue) {
const issue = spacingIssue.issue;
if (issue === reconstructionIssues.MISSING_FRAMES) {
missingFrames += spacingIssue.missingFrames;
} else if (issue === reconstructionIssues.IRREGULAR_SPACING) {
return { value: false };
if (datasetIs4D && spacingBetweenFrames < 1.e-3) {
// the dataset is 4D, if the distance is zero, means that we are
// checking the 4th dimension. Do not return, since we want still to
// check the 3rd dimension spacing.
continue;
}
}
previousImagePositionPatient = ImagePositionPatient;
const spacingIssue = _getSpacingIssue(
spacingBetweenFrames,
averageSpacingBetweenFrames
);
if (spacingIssue) {
const issue = spacingIssue.issue;
if (issue === ReconstructionIssues.MISSING_FRAMES) {
missingFrames += spacingIssue.missingFrames;
} else if (issue === ReconstructionIssues.IRREGULAR_SPACING) {
warningIssues.push(issue);
break;
}
}
previousImagePositionPatient = ImagePositionPatient;
}
}
}
return { value: true, missingFrames };
return { isUniform: warningIssues.length === 0 ? true : false, missingFrames, warningIssues };
}
function _isSameOrientation(iop1, iop2) {
/**
* Check if 4D dataset.
*
* Assuming that slices at different time have the same position, here we just check if
* there are multiple slices for the same ImagePositionPatient and disable MPR.
*
* A better heuristic would be checking 4D tags, e.g. the presence of multiple TemporalPositionIdentifier values.
* However, some studies (e.g. https://github.com/OHIF/Viewers/issues/2113) do not have such tags.
*
* @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.
*
* @returns {boolean} dataset4D value.
*/
function _isDataset4D(instances) {
const n = instances.length;
for (let ii = 0; ii < n; ++ii) {
const instanceMetadataControl = instances[ii].getData().metadata;
if (
!instanceMetadataControl ||
instanceMetadataControl === undefined ||
!instanceMetadataControl.ImagePositionPatient ||
instanceMetadataControl.ImagePositionPatient === undefined
) {
continue;
}
for (let jj = ii + 1; jj < n; ++jj) {
const instanceMetadata = instances[jj].getData().metadata;
if (
!instanceMetadata ||
instanceMetadata === undefined ||
!instanceMetadata.ImagePositionPatient ||
instanceMetadata.ImagePositionPatient === undefined
) {
continue;
}
if (_isSameArray(instanceMetadataControl.ImagePositionPatient, instanceMetadata.ImagePositionPatient)) {
return true;
}
}
}
return false;
}
function _isSameArray(iop1, iop2) {
if (iop1 === undefined || !iop2 === undefined) {
return;
}
@@ -156,12 +254,12 @@ function _getSpacingIssue(spacing, averageSpacing) {
if (errorForEachSpacing < spacingTolerance * averageSpacing) {
return {
issue: reconstructionIssues.MISSING_FRAMES,
issue: ReconstructionIssues.MISSING_FRAMES,
missingFrames: numberOfSpacings - 1,
};
}
return { issue: reconstructionIssues.IRREGULAR_SPACING };
return { issue: ReconstructionIssues.IRREGULAR_SPACING };
}
function _getPerpendicularDistance(a, b) {
@@ -173,7 +271,5 @@ function _getPerpendicularDistance(a, b) {
}
const constructableModalities = ['MR', 'CT', 'PT', 'NM'];
const reconstructionIssues = {
MISSING_FRAMES: 'missingframes',
IRREGULAR_SPACING: 'irregularspacing',
};
export {isDisplaySetReconstructable, isSpacingUniform};
@@ -45,13 +45,13 @@ import studyMetadataManager from './studyMetadataManager';
* @param {string} referencedDisplaySet.studyInstanceUid
* @param {Array} referencedDisplaySet.sopClassUids
* @param {Study[]} studies Collection of studies
* @param {object} logger
* @param {object} snackbar
* @returns void
*/
const loadAndCacheDerivedDisplaySets = (referencedDisplaySet, studies) => {
async function loadAndCacheDerivedDisplaySets(referencedDisplaySet, studies, logger, snackbar) {
const { StudyInstanceUID, SeriesInstanceUID } = referencedDisplaySet;
const promises = [];
const studyMetadata = studyMetadataManager.get(StudyInstanceUID);
if (!studyMetadata) {
@@ -80,11 +80,10 @@ const loadAndCacheDerivedDisplaySets = (referencedDisplaySet, studies) => {
});
// For each type, see if any are loaded, if not load the most recent.
Object.keys(displaySetsPerModality).forEach(key => {
await Promise.all(Object.keys(displaySetsPerModality).map(async (key) => {
const displaySets = displaySetsPerModality[key];
const isLoaded = displaySets.some(displaySet => displaySet.isLoaded);
if (isLoaded) {
return;
}
@@ -107,12 +106,29 @@ const loadAndCacheDerivedDisplaySets = (referencedDisplaySet, studies) => {
}
});
recentDisplaySet.isLoading = true;
try {
await recentDisplaySet.load(referencedDisplaySet, studies);
} catch (error) {
recentDisplaySet.isLoaded = false;
recentDisplaySet.loadError = true;
logger.error({ error, message: error.message });
snackbar.show({
title: 'Error loading derived display set:',
message: error.message,
type: 'error',
error,
autoClose: false,
});
}
}));
promises.push(recentDisplaySet.load(referencedDisplaySet, studies));
});
return promises;
/*
* 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('deriveddisplaysetsloadedandcached');
document.dispatchEvent(event);
};
export default loadAndCacheDerivedDisplaySets;
@@ -0,0 +1,9 @@
const validNumber = val => {
if (Array.isArray(val)) {
return val.map(v => (v !== undefined ? Number(v) : v));
} else {
return val !== undefined ? Number(val) : val;
}
};
export default validNumber;
+19
View File
@@ -3,6 +3,25 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.9.1](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.9.0...@ohif/ui@1.9.1) (2021-03-26)
**Note:** Version bump only for package @ohif/ui
# [1.9.0](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.8.2...@ohif/ui@1.9.0) (2021-03-04)
### Features
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
## [1.8.2](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.8.1...@ohif/ui@1.8.2) (2021-02-05)
**Note:** Version bump only for package @ohif/ui
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/ui",
"version": "1.8.2",
"version": "1.9.1",
"description": "A set of React components for Medical Imaging Viewers",
"author": "OHIF Contributors",
"license": "MIT",
@@ -28,6 +28,7 @@ function StudyBrowser(props) {
SeriesDescription,
SeriesNumber,
stackPercentComplete,
hasWarnings,
} = thumb;
return (
@@ -50,6 +51,7 @@ function StudyBrowser(props) {
numImageFrames={numImageFrames}
SeriesDescription={SeriesDescription}
SeriesNumber={SeriesNumber}
hasWarnings={hasWarnings}
stackPercentComplete={stackPercentComplete}
// Events
onClick={onThumbnailClick.bind(
@@ -1,8 +1,11 @@
import React from 'react';
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { useDrag } from 'react-dnd';
import ImageThumbnail from './ImageThumbnail';
import classNames from 'classnames';
import { Icon } from './../../elements/Icon';
import { Tooltip } from './../tooltip';
import { OverlayTrigger } from './../overlayTrigger';
import './Thumbnail.styl';
@@ -11,7 +14,22 @@ function ThumbnailFooter({
SeriesNumber,
InstanceNumber,
numImageFrames,
hasWarnings
}) {
const [warningList, warningListSet] = useState([]);
useEffect(() => {
let unmounted = false
hasWarnings.then(response => {
if (!unmounted) {
warningListSet(response)
}
})
return () => {
unmounted = true
}
}, [])
const infoOnly = !SeriesDescription;
const getInfo = (value, icon, className = '') => {
@@ -22,28 +40,73 @@ function ThumbnailFooter({
</div>
);
};
const getWarningContent = (warningList) => {
if (Array.isArray(warningList)) {
const listedWarnings = warningList.map((warn, index) => {
return <li key={index}>{warn}</li>;
});
return <ol>{listedWarnings}</ol>;
} else {
return <React.Fragment>{warningList}</React.Fragment>;
}
};
const getWarningInfo = (SeriesNumber, warningList) => {
return(
<React.Fragment>
{warningList.length != 0 ? (
<OverlayTrigger
key={SeriesNumber}
placement="left"
overlay={
<Tooltip
placement="left"
className="in tooltip-warning"
id="tooltip-left"
>
<div className="warningTitle">Series Inconsistencies</div>
<div className="warningContent">{getWarningContent(warningList)}</div>
</Tooltip>
}
>
<div className={classNames('warning')}>
<span className="warning-icon">
<Icon name="exclamation-triangle" />
</span>
</div>
</OverlayTrigger>
) : (
<React.Fragment></React.Fragment>
)}
</React.Fragment>
);
};
const getSeriesInformation = (
SeriesNumber,
InstanceNumber,
numImageFrames
numImageFrames,
warningList
) => {
if (!SeriesNumber && !InstanceNumber && !numImageFrames) {
return;
}
return (
const seriesInformation =
<div className="series-information">
{getInfo(SeriesNumber, 'S:')}
{getInfo(InstanceNumber, 'I:')}
{getInfo(numImageFrames, '', 'image-frames')}
{getWarningInfo(SeriesNumber, warningList)}
</div>
);
return (seriesInformation);
};
return (
<div className={classNames('series-details', { 'info-only': infoOnly })}>
<div className="series-description">{SeriesDescription}</div>
{getSeriesInformation(SeriesNumber, InstanceNumber, numImageFrames)}
{getSeriesInformation(SeriesNumber, InstanceNumber, numImageFrames, warningList)}
</div>
);
}
@@ -60,6 +123,7 @@ function Thumbnail(props) {
numImageFrames,
SeriesDescription,
SeriesNumber,
hasWarnings,
stackPercentComplete,
StudyInstanceUID,
onClick,
@@ -126,13 +190,14 @@ Thumbnail.propTypes = {
stackPercentComplete: PropTypes.number,
/**
altImageText will be used when no imageId or imageSrc is provided.
It will be displayed inside the <div>. This is useful when it is difficult
It will be displayed inside the <div>. This is useful when it is difficult
to make a preview for a type of DICOM series (e.g. DICOM-SR)
*/
altImageText: PropTypes.string,
SeriesDescription: PropTypes.string,
SeriesNumber: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
InstanceNumber: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
hasWarnings: PropTypes.instanceOf(Promise),
numImageFrames: PropTypes.number,
onDoubleClick: PropTypes.func,
onClick: PropTypes.func,
@@ -78,6 +78,17 @@
height: 11px
width: 11px
.warning
margin: auto 0;
opacity: 1
color: #e29e4a;
svg
width: 16px;
height: 14px;
pointer-events: inherit;
.value
color: var(--text-secondary-color);
display: inline-block
@@ -0,0 +1,104 @@
import React, { useState, createContext, useContext, useEffect } from 'react';
import PropTypes from 'prop-types';
const LoggerContext = createContext(null);
const { Provider } = LoggerContext;
export const useLogger = () => useContext(LoggerContext);
const LoggerProvider = ({ children, service }) => {
const [state, setState] = useState({
errors: [],
infos: [],
});
useEffect(() => {
const onErrorHandler = ({ error: errorObject, message }) => {
error({ error: errorObject, message });
};
window.addEventListener('error', onErrorHandler);
return () => {
window.removeEventListener('error', onErrorHandler);
};
}, []);
/**
* Logs an error
*
* @param {object} props { error, stack, message, displayOnConsole }
* @returns void
*/
const error = ({
error = {},
stack = '',
message = '',
displayOnConsole = true,
}) => {
const errorObject = { error, stack, message, displayOnConsole };
setState(state => ({ ...state, errors: [...state.errors, errorObject] }));
if (displayOnConsole) {
console.error(error);
}
};
/**
* Logs an info
*
* @param {object} props { message, displayOnConsole }
* @returns void
*/
const info = ({ message = '', displayOnConsole = true }) => {
setState(state => ({
...state,
infos: state.infos.push({ message, displayOnConsole }),
}));
if (displayOnConsole) {
console.info(message);
}
};
/**
* Sets the implementation of a log service that can be used by extensions
*
* @returns void
*/
useEffect(() => {
if (service) {
service.setServiceImplementation({ error, info });
}
}, [error, service, info]);
return <Provider value={{ info, error, state }}>{children}</Provider>;
};
/**
* Higher Order Component to use the log methods through a Class Component
*
* @returns
*/
export const withLogger = Component => {
return function WrappedComponent(props) {
const { error, info, state } = useLogger();
return <Component {...props} logger={{ error, info, state }} />;
};
};
LoggerProvider.defaultProps = {
service: null,
};
LoggerProvider.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
]).isRequired,
service: PropTypes.shape({
setServiceImplementation: PropTypes.func,
}),
};
export default LoggerProvider;
export const LogConsumer = LoggerContext.Consumer;
@@ -18,3 +18,8 @@ export {
withDialog,
useDialog,
} from './DialogProvider.js';
export {
default as LoggerProvider,
withLogger,
useLogger,
} from './LoggerProvider.js';
+8 -2
View File
@@ -30,7 +30,7 @@ import {
AboutContent,
OHIFModal,
ErrorBoundary,
ErrorPage
ErrorPage,
} from './components';
import { useDebounce, useMedia } from './hooks';
@@ -66,6 +66,9 @@ import {
ModalConsumer,
useModal,
withModal,
LoggerProvider,
withLogger,
useLogger,
} from './contextProviders';
export {
@@ -127,11 +130,14 @@ export {
useDialog,
ErrorBoundary,
ErrorPage,
LoggerProvider,
withLogger,
useLogger,
// Hooks
useDebounce,
useMedia,
// Utils
ViewerbaseDragDropContext,
asyncComponent,
retryImport
retryImport,
};
+150
View File
@@ -3,6 +3,156 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [4.9.14](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.13...@ohif/viewer@4.9.14) (2021-04-22)
**Note:** Version bump only for package @ohif/viewer
## [4.9.13](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.12...@ohif/viewer@4.9.13) (2021-04-21)
**Note:** Version bump only for package @ohif/viewer
## [4.9.12](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.11...@ohif/viewer@4.9.12) (2021-04-21)
**Note:** Version bump only for package @ohif/viewer
## [4.9.11](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.10...@ohif/viewer@4.9.11) (2021-04-21)
**Note:** Version bump only for package @ohif/viewer
## [4.9.10](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.9...@ohif/viewer@4.9.10) (2021-04-16)
**Note:** Version bump only for package @ohif/viewer
## [4.9.9](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.8...@ohif/viewer@4.9.9) (2021-04-15)
**Note:** Version bump only for package @ohif/viewer
## [4.9.8](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.7...@ohif/viewer@4.9.8) (2021-03-31)
**Note:** Version bump only for package @ohif/viewer
## [4.9.7](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.6...@ohif/viewer@4.9.7) (2021-03-26)
**Note:** Version bump only for package @ohif/viewer
## [4.9.6](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.5...@ohif/viewer@4.9.6) (2021-03-26)
**Note:** Version bump only for package @ohif/viewer
## [4.9.5](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.4...@ohif/viewer@4.9.5) (2021-03-25)
### Bug Fixes
* IDC-2288: Update toolbar tabs after derived displayset loaded ([#2307](https://github.com/OHIF/Viewers/issues/2307)) ([6e723eb](https://github.com/OHIF/Viewers/commit/6e723ebced58852007ca553792c740976cfc4201))
## [4.9.4](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.3...@ohif/viewer@4.9.4) (2021-03-19)
**Note:** Version bump only for package @ohif/viewer
## [4.9.3](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.2...@ohif/viewer@4.9.3) (2021-03-15)
**Note:** Version bump only for package @ohif/viewer
## [4.9.2](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.1...@ohif/viewer@4.9.2) (2021-03-09)
**Note:** Version bump only for package @ohif/viewer
## [4.9.1](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.0...@ohif/viewer@4.9.1) (2021-03-09)
**Note:** Version bump only for package @ohif/viewer
# [4.9.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.8.12...@ohif/viewer@4.9.0) (2021-03-04)
### Features
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
## [4.8.12](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.8.11...@ohif/viewer@4.8.12) (2021-03-03)
**Note:** Version bump only for package @ohif/viewer
## [4.8.11](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.8.10...@ohif/viewer@4.8.11) (2021-02-25)
**Note:** Version bump only for package @ohif/viewer
## [4.8.10](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.8.9...@ohif/viewer@4.8.10) (2021-02-08)
**Note:** Version bump only for package @ohif/viewer
## [4.8.9](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.8.8...@ohif/viewer@4.8.9) (2021-02-05)
**Note:** Version bump only for package @ohif/viewer
+11 -11
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/viewer",
"version": "4.8.9",
"version": "4.9.14",
"description": "OHIF Viewer",
"author": "OHIF Contributors",
"license": "MIT",
@@ -49,18 +49,18 @@
},
"dependencies": {
"@babel/runtime": "^7.5.5",
"@ohif/core": "^2.12.3",
"@ohif/extension-cornerstone": "^2.10.1",
"@ohif/extension-debugging": "^0.1.6",
"@ohif/extension-dicom-html": "^1.3.1",
"@ohif/extension-dicom-microscopy": "^0.51.4",
"@ohif/core": "^2.13.9",
"@ohif/extension-cornerstone": "^2.10.7",
"@ohif/extension-debugging": "^0.2.1",
"@ohif/extension-dicom-html": "^1.3.8",
"@ohif/extension-dicom-microscopy": "^0.52.0",
"@ohif/extension-dicom-pdf": "^1.0.6",
"@ohif/extension-dicom-rt": "^0.6.4",
"@ohif/extension-dicom-segmentation": "^0.5.2",
"@ohif/extension-dicom-rt": "^0.6.10",
"@ohif/extension-dicom-segmentation": "^0.6.7",
"@ohif/extension-lesion-tracker": "^0.2.1",
"@ohif/extension-vtk": "^1.10.4",
"@ohif/extension-vtk": "^1.11.10",
"@ohif/i18n": "^0.53.0",
"@ohif/ui": "^1.8.2",
"@ohif/ui": "^1.9.1",
"@tanem/react-nprogress": "^1.1.25",
"classnames": "^2.2.6",
"core-js": "^3.2.1",
@@ -68,7 +68,7 @@
"cornerstone-math": "^0.1.8",
"cornerstone-tools": "^4.20.1",
"cornerstone-wado-image-loader": "^3.1.0",
"dcmjs": "0.17.2",
"dcmjs": "0.18.5",
"dicom-parser": "^1.8.3",
"dicomweb-client": "^0.4.4",
"hammerjs": "^2.0.8",
+30 -19
View File
@@ -13,6 +13,7 @@ import {
ModalProvider,
DialogProvider,
OHIFModal,
LoggerProvider,
ErrorBoundary,
} from '@ohif/ui';
@@ -24,6 +25,7 @@ import {
UINotificationService,
UIModalService,
UIDialogService,
LoggerService,
MeasurementService,
utils,
redux as reduxOHIF,
@@ -141,6 +143,7 @@ class App extends Component {
UIModalService,
UIDialogService,
MeasurementService,
LoggerService,
]);
_initExtensions(
[...defaultExtensions, ...extensions],
@@ -164,6 +167,7 @@ class App extends Component {
UIDialogService,
UIModalService,
MeasurementService,
LoggerService,
} = servicesManager.services;
if (this._userManager) {
@@ -176,18 +180,20 @@ class App extends Component {
<UserManagerContext.Provider value={this._userManager}>
<Router basename={routerBasename}>
<WhiteLabelingContext.Provider value={whiteLabeling}>
<SnackbarProvider service={UINotificationService}>
<DialogProvider service={UIDialogService}>
<ModalProvider
modal={OHIFModal}
service={UIModalService}
>
<OHIFStandaloneViewer
userManager={this._userManager}
/>
</ModalProvider>
</DialogProvider>
</SnackbarProvider>
<LoggerProvider service={LoggerService}>
<SnackbarProvider service={UINotificationService}>
<DialogProvider service={UIDialogService}>
<ModalProvider
modal={OHIFModal}
service={UIModalService}
>
<OHIFStandaloneViewer
userManager={this._userManager}
/>
</ModalProvider>
</DialogProvider>
</SnackbarProvider>
</LoggerProvider>
</WhiteLabelingContext.Provider>
</Router>
</UserManagerContext.Provider>
@@ -206,13 +212,18 @@ class App extends Component {
<I18nextProvider i18n={i18n}>
<Router basename={routerBasename}>
<WhiteLabelingContext.Provider value={whiteLabeling}>
<SnackbarProvider service={UINotificationService}>
<DialogProvider service={UIDialogService}>
<ModalProvider modal={OHIFModal} service={UIModalService}>
<OHIFStandaloneViewer />
</ModalProvider>
</DialogProvider>
</SnackbarProvider>
<LoggerProvider service={LoggerService}>
<SnackbarProvider service={UINotificationService}>
<DialogProvider service={UIDialogService}>
<ModalProvider
modal={OHIFModal}
service={UIModalService}
>
<OHIFStandaloneViewer />
</ModalProvider>
</DialogProvider>
</SnackbarProvider>
</LoggerProvider>
</WhiteLabelingContext.Provider>
</Router>
</I18nextProvider>
@@ -4,7 +4,7 @@ import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { utils } from '@ohif/core';
import { useSnackbarContext } from '@ohif/ui';
import { useSnackbarContext, useLogger } from '@ohif/ui';
//
import ViewportPane from './ViewportPane.js';
import DefaultViewport from './DefaultViewport.js';
@@ -12,7 +12,7 @@ import EmptyViewport from './EmptyViewport.js';
const { loadAndCacheDerivedDisplaySets } = utils;
const ViewportGrid = function (props) {
const ViewportGrid = function(props) {
const {
activeViewportIndex,
availablePlugins,
@@ -36,23 +36,12 @@ const ViewportGrid = function (props) {
}
const snackbar = useSnackbarContext();
const logger = useLogger();
useEffect(() => {
if (isStudyLoaded) {
viewportData.forEach(displaySet => {
const promises = loadAndCacheDerivedDisplaySets(displaySet, studies);
promises.forEach(promise => {
promise.catch(error => {
snackbar.show({
title: 'Error loading derived display set:',
message: error.message,
type: 'error',
error,
autoClose: false,
});
});
});
loadAndCacheDerivedDisplaySets(displaySet, studies, logger, snackbar);
});
}
}, [studies, viewportData, isStudyLoaded, snackbar]);
@@ -3,6 +3,7 @@ import { connect } from 'react-redux';
import { StudyBrowser } from '@ohif/ui';
import cloneDeep from 'lodash.clonedeep';
import findDisplaySetByUID from './findDisplaySetByUID';
import { servicesManager } from './../App.js';
const { studyMetadataManager } = OHIF.utils;
@@ -48,8 +49,35 @@ const mapDispatchToProps = (dispatch, ownProps) => {
if (displaySet.isDerived) {
const { Modality } = displaySet;
if (Modality === 'SEG' && servicesManager) {
const {LoggerService, UINotificationService} = servicesManager.services;
const onDisplaySetLoadFailureHandler = error => {
LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: 'DICOM Segmentation Loader',
message: error.message,
type: 'error',
autoClose: true,
});
};
displaySet = displaySet.getSourceDisplaySet(ownProps.studyMetadata);
const {referencedDisplaySet, activatedLabelmapPromise} = displaySet.getSourceDisplaySet(
ownProps.studyMetadata,
true,
onDisplaySetLoadFailureHandler
);
displaySet = referencedDisplaySet;
activatedLabelmapPromise.then((activatedLabelmapIndex) => {
const selectionFired = new CustomEvent("extensiondicomsegmentationsegselected", {
"detail": {"activatedLabelmapIndex":activatedLabelmapIndex}
});
document.dispatchEvent(selectionFired);
});
} else {
displaySet = displaySet.getSourceDisplaySet(ownProps.studyMetadata);
}
if (!displaySet) {
throw new Error(
@@ -59,6 +59,9 @@ class ToolbarRow extends Component {
this.seriesPerStudyCount = [];
this._handleBuiltIn = _handleBuiltIn.bind(this);
this._onDerivedDisplaySetsLoadedAndCached = this._onDerivedDisplaySetsLoadedAndCached.bind(
this
);
this.updateButtonGroups();
}
@@ -109,6 +112,32 @@ class ToolbarRow extends Component {
});
}
componentDidMount() {
/*
* 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)
*/
document.addEventListener(
'deriveddisplaysetsloadedandcached',
this._onDerivedDisplaySetsLoadedAndCached
);
}
componentWillUnmount() {
document.removeEventListener(
'deriveddisplaysetsloadedandcached',
this._onDerivedDisplaySetsLoadedAndCached
);
}
_onDerivedDisplaySetsLoadedAndCached() {
this.updateButtonGroups();
this.setState({
toolbarButtons: _getVisibleToolbarButtons.call(this),
});
}
componentDidUpdate(prevProps) {
const activeContextsChanged =
prevProps.activeContexts !== this.props.activeContexts;
@@ -1,6 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { useLogger } from '@ohif/ui';
import OHIF, { MODULE_TYPES, DICOMSR } from '@ohif/core';
import { withDialog } from '@ohif/ui';
@@ -12,6 +13,8 @@ import ConnectedViewerMain from './ConnectedViewerMain.js';
import SidePanel from './../components/SidePanel.js';
import ErrorBoundaryDialog from './../components/ErrorBoundaryDialog';
import { extensionManager } from './../App.js';
import { ReconstructionIssues } from './../../../core/src/enums.js';
import dcmjs from 'dcmjs';
// Contexts
import WhiteLabelingContext from '../context/WhiteLabelingContext.js';
@@ -20,6 +23,7 @@ import AppContext from '../context/AppContext';
import './Viewer.css';
import { finished } from 'stream';
import { cornerstoneWADOImageLoader } from 'cornerstone-wado-image-loader';
class Viewer extends Component {
static propTypes = {
@@ -271,6 +275,7 @@ class Viewer extends Component {
activeViewport={
this.props.viewports[this.props.activeViewportIndex]
}
isDerivedDisplaySetsLoaded={this.props.isDerivedDisplaySetsLoaded}
isLeftSidePanelOpen={this.state.isLeftSidePanelOpen}
isRightSidePanelOpen={this.state.isRightSidePanelOpen}
selectedLeftSidePanel={
@@ -366,6 +371,151 @@ class Viewer extends Component {
export default withDialog(Viewer);
/**
* Async function to check if there are any inconsistences in the series.
*
* For segmentation checks that the geometry is consistent with the source images:
* 1) no frames out of plane;
* 2) have the same width and height.
*
* For reconstructable 3D volume:
* 1) Is series multiframe?
* 2) Do the frames have different dimensions/number of components/orientations?
* 3) Has the series any missing frames or irregular spacing?
* 4) Is the series 4D?
*
* If not reconstructable, MPR is disabled.
* The actual computations are done in isDisplaySetReconstructable.
*
* @param {*object} displaySet
* @returns {[string]} an array of strings containing the warnings
*/
const _checkForSeriesInconsistencesWarnings = async function (displaySet, studies) {
const warningsList = [];
if (displaySet.Modality !== 'SEG') {
if (displaySet.warningIssues && displaySet.warningIssues.length !== 0) {
displaySet.warningIssues.forEach(warning => {
switch (warning) {
case ReconstructionIssues.DATASET_4D:
warningsList.push('The dataset is 4D.');
break;
case ReconstructionIssues.VARYING_IMAGESDIMENSIONS:
warningsList.push('The dataset frames have different dimensions (rows, columns).');
break;
case ReconstructionIssues.VARYING_IMAGESCOMPONENTS:
warningsList.push('The dataset frames have different components (Sample per pixel).');
break;
case ReconstructionIssues.VARYING_IMAGESORIENTATION:
warningsList.push('The dataset frames have different orientation.');
break;
case ReconstructionIssues.IRREGULAR_SPACING:
warningsList.push('The dataset frames have different pixel spacing.');
break;
case ReconstructionIssues.MULTIFFRAMES:
warningsList.push('The dataset is a multiframes.');
break;
default:
break;
}
});
warningsList.push('The datasets is not a reconstructable 3D volume. MPR mode is not available.');
}
if (displaySet.missingFrames &&
(!displaySet.warningIssues ||
(displaySet.warningIssues && !displaySet.warningIssues.find(warn => warn === ReconstructionIssues.DATASET_4D)))) {
warningsList.push('The datasets is missing frames: ' + displaySet.missingFrames + '.');
}
} else {
const segMetadata = displaySet.metadata;
if (!segMetadata) {
return warningsList;
}
const { referencedDisplaySet } = displaySet.getSourceDisplaySet(studies, false);
if (!referencedDisplaySet) {
return warningsList;
}
const imageIds = referencedDisplaySet.images.map(image => image.getImageId());
if (!imageIds || imageIds.length === 0) {
return warningsList;
}
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 (warningsList.length === 0) {
const warningMessage = 'The segmentation ' +
'has frames out of plane respect to the source images.';
warningsList.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.';
warningsList.push(warningMessage);
break;
}
}
if (warningsList.length !== 0) {
const warningMessage = 'The segmentation format is not supported yet. ' +
'The segmentation data (segments) could not be loaded.';
warningsList.push(warningMessage);
}
}
return warningsList;
}
/**
* What types are these? Why do we have "mapping" dropped in here instead of in
* a mapping layer?
@@ -405,6 +555,8 @@ const _mapStudiesToThumbnails = function(studies) {
altImageText = displaySet.Modality ? displaySet.Modality : 'UN';
}
const hasWarnings = _checkForSeriesInconsistencesWarnings(displaySet, studies);
return {
imageId,
altImageText,
@@ -413,6 +565,7 @@ const _mapStudiesToThumbnails = function(studies) {
InstanceNumber,
numImageFrames,
SeriesNumber,
hasWarnings,
};
});
@@ -1,5 +1,5 @@
import './ViewerMain.css';
import { servicesManager } from './../App.js';
import { Component } from 'react';
import { ConnectedViewportGrid } from './../components/ViewportGrid/index.js';
import PropTypes from 'prop-types';
@@ -141,7 +141,28 @@ class ViewerMain extends Component {
if (displaySet.isDerived) {
const { Modality } = displaySet;
displaySet = displaySet.getSourceDisplaySet(this.props.studies);
if (Modality === 'SEG' && servicesManager) {
const {LoggerService, UINotificationService} = servicesManager.services;
const onDisplaySetLoadFailureHandler = error => {
LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: 'DICOM Segmentation Loader',
message: error.message,
type: 'error',
autoClose: true,
});
};
const {referencedDisplaySet} = displaySet.getSourceDisplaySet(
this.props.studies,
true,
onDisplaySetLoadFailureHandler
);
displaySet = referencedDisplaySet;
} else {
displaySet = displaySet.getSourceDisplaySet(this.props.studies);
}
if (!displaySet) {
throw new Error(
@@ -5,10 +5,11 @@ import usePrevious from '../customHooks/usePrevious';
import ConnectedViewer from './ConnectedViewer.js';
import PropTypes from 'prop-types';
import { extensionManager } from './../App.js';
import { useSnackbarContext } from '@ohif/ui';
import { useSnackbarContext, ErrorPage } from '@ohif/ui';
// Contexts
import AppContext from '../context/AppContext';
import NotFound from '../routes/NotFound';
const { OHIFStudyMetadata, OHIFSeriesMetadata } = metadata;
const { retrieveStudiesMetadata, deleteStudyMetadataPromise } = studies;
@@ -258,7 +259,6 @@ function ViewerRetrieveStudyData({
);
setStudies([...studies, study]);
setIsStudyLoaded(true);
};
/**
@@ -291,9 +291,12 @@ function ViewerRetrieveStudyData({
})
.catch(error => {
if (error && !error.isCanceled) {
setError(true);
setError(error);
log.error(error);
}
})
.finally(() => {
setIsStudyLoaded(true);
});
return study;
@@ -322,8 +325,9 @@ function ViewerRetrieveStudyData({
const promises = Array(concurrentRequestsAllowed)
.fill(null)
.map(loadNextSeries);
return await Promise.all(promises);
const remainingPromises = await Promise.all(promises);
setIsStudyLoaded(true);
return remainingPromises;
};
const loadStudies = async () => {
@@ -358,13 +362,13 @@ function ViewerRetrieveStudyData({
})
.catch(error => {
if (error && !error.isCanceled) {
setError(true);
setError(error);
log.error(error);
}
});
} catch (error) {
if (error) {
setError(true);
setError(error);
log.error(error);
}
}
@@ -411,7 +415,12 @@ function ViewerRetrieveStudyData({
}, []);
if (error) {
return <div>Error: {JSON.stringify(error)}</div>;
const content = JSON.stringify(error);
if (content.includes('404') || content.includes('NOT_FOUND')) {
return <NotFound />;
}
return <NotFound message="Failed to retrieve study data" />;
}
return (
-1
View File
@@ -41,7 +41,6 @@ let config = {};
if (window) {
config = window.config || {};
window.version = version;
}
+8 -8
View File
@@ -6619,10 +6619,10 @@ dateformat@^3.0.0:
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
dcmjs@0.17.2:
version "0.17.2"
resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.17.2.tgz#81d6e696119c25afbd26967a6250a32c25f06535"
integrity sha512-wM9AUWt9vM2S+owI/4UjoBCSV9Mfi/m5rykHH5WTDZVxQZUrL/ehOC/l7d7gkcMaOSD0C0r9X56Nn/562Jt1/Q==
dcmjs@0.18.5:
version "0.18.5"
resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.18.5.tgz#06edd5562a91fa1e6be3a9fd2fc919e103f44e6f"
integrity sha512-AWGFMwCdQg4C/hJIhnnWS4ieClnWMkVmV9sX29jpLYYMEb7QGBe1t9UsWvgBh1QiXePUh4u+zGFQk27duHB6rw==
dependencies:
"@babel/polyfill" "^7.8.3"
"@babel/runtime" "^7.8.4"
@@ -15698,10 +15698,10 @@ react-codemirror2@^6.0.0:
resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-6.0.0.tgz#180065df57a64026026cde569a9708fdf7656525"
integrity sha512-D7y9qZ05FbUh9blqECaJMdDwKluQiO3A9xB+fssd5jKM7YAXucRuEOlX32mJQumUvHUkHRHqXIPBjm6g0FW0Ag==
react-cornerstone-viewport@4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-4.0.4.tgz#0e4291d9b0fe55c003e275175b0902ced61b0c80"
integrity sha512-RjCqOtQep04dRoHtsju0USlxN/vGUI2WnEt1aN84iYU7eZ+AXnwJo1nAd0RMX2obcXaGCIqMDtMRkE/zm3oZHw==
react-cornerstone-viewport@4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-4.0.5.tgz#3de83cdd3643980e0330f3743f631dbbb24d98a7"
integrity sha512-uamDtFljWWEHe26kOBJJ1Bu//6hAgEra7BDVykOvtMC/W7kW34Q2fFX3ZwkL6TDdCQ94O6K98IXPS9HbrEJWYg==
dependencies:
classnames "^2.2.6"
date-fns "^2.2.1"