Compare commits
300
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37231a5ffe | ||
|
|
c53ee335ee | ||
|
|
fbd9371884 | ||
|
|
5d57c05217 | ||
|
|
ec38af8c06 | ||
|
|
c7d2017f08 | ||
|
|
3d393df45d | ||
|
|
2f94e27d3b | ||
|
|
e9b57d5731 | ||
|
|
ff4ffbe975 | ||
|
|
458311252b | ||
|
|
3fe67d5c98 | ||
|
|
87f78069e7 | ||
|
|
f8f7a175c4 | ||
|
|
41c028781b | ||
|
|
f6cf4d127d | ||
|
|
131fb57cc9 | ||
|
|
efe97cd01d | ||
|
|
17e1641226 | ||
|
|
be1b44a4ba | ||
|
|
84f27593a0 | ||
|
|
2af95988df | ||
|
|
e2901eb30f | ||
|
|
377d5e2fb6 | ||
|
|
d3adeec109 | ||
|
|
fc3aec7a79 | ||
|
|
78df8ff03a | ||
|
|
c4902f2b9e | ||
|
|
1423ecc9d8 | ||
|
|
5040c947d2 | ||
|
|
c05698c5ec | ||
|
|
3dd18a453a | ||
|
|
2c6ce21c8f | ||
|
|
0803dce328 | ||
|
|
990ae853b0 | ||
|
|
3c421f124e | ||
|
|
44beac799f | ||
|
|
3b4b59c32b | ||
|
|
7f12f398fb | ||
|
|
891b752e69 | ||
|
|
42bf9c1484 | ||
|
|
4d04dd5651 | ||
|
|
9e79e76bab | ||
|
|
a58371e83b | ||
|
|
d2ae13b03f | ||
|
|
c9b687900e | ||
|
|
282633f907 | ||
|
|
e2964bf669 | ||
|
|
fae3b25b7b | ||
|
|
64ee6d529f | ||
|
|
792db26ff1 | ||
|
|
60633a8f3f | ||
|
|
07eeb8e5fe | ||
|
|
851e74d7b8 | ||
|
|
639863a8ef | ||
|
|
a00f610b2d | ||
|
|
9e951e8800 | ||
|
|
71c16615d1 | ||
|
|
b1fc82315c | ||
|
|
6a1df9de4a | ||
|
|
06445dcaa2 | ||
|
|
a344183355 | ||
|
|
2f28a0deab | ||
|
|
e04310a02d | ||
|
|
4efb7efd0e | ||
|
|
9ad0d7fc8c | ||
|
|
71d21ee184 | ||
|
|
9677dfdb90 | ||
|
|
5b361fb289 | ||
|
|
d9c5b840a5 | ||
|
|
ec3a70b5a7 | ||
|
|
a46b00f76b | ||
|
|
f0e9865ca1 | ||
|
|
0d37705435 | ||
|
|
12ac509c40 | ||
|
|
9353a840ee | ||
|
|
8030577fb2 | ||
|
|
dd86a8eabd | ||
|
|
47164463cc | ||
|
|
00b74664f9 | ||
|
|
c91752d575 | ||
|
|
41d4398342 | ||
|
|
f0a5795b68 | ||
|
|
80f314a422 | ||
|
|
a6408d6033 | ||
|
|
5332d3e5f5 | ||
|
|
d41eca4ed5 | ||
|
|
a5ddcf43de | ||
|
|
bd19ab983d | ||
|
|
d88a341884 | ||
|
|
6db50d26b2 | ||
|
|
3906c754f1 | ||
|
|
7783d0f558 | ||
|
|
add69e5e4f | ||
|
|
d32edcca45 | ||
|
|
69dbe27784 | ||
|
|
de201d567f | ||
|
|
26a042d8b9 | ||
|
|
74b82bd934 | ||
|
|
a7576e07a7 | ||
|
|
66b2f16c9e | ||
|
|
cf10e3cf67 | ||
|
|
3ea981b40c | ||
|
|
e1ce9c63ee | ||
|
|
06073af035 | ||
|
|
19f7bba5d8 | ||
|
|
5f7045eb09 | ||
|
|
8610c862a9 | ||
|
|
8c8a4c2222 | ||
|
|
57cc0b0ae3 | ||
|
|
56c5828b02 | ||
|
|
f6d05bc21c | ||
|
|
a5d72a130a | ||
|
|
d6ea179ac4 | ||
|
|
7de1c78fc4 | ||
|
|
5f8f559426 | ||
|
|
79473c2ea4 | ||
|
|
ecf91bdcd4 | ||
|
|
2df818c8cd | ||
|
|
0f6f2bb432 | ||
|
|
9f2835be2d | ||
|
|
01a1265291 | ||
|
|
83ee20d249 | ||
|
|
a0a571cb4b | ||
|
|
d45fd931b3 | ||
|
|
fc0e7f8572 | ||
|
|
cb9c099f36 | ||
|
|
ccb8a0dcc3 | ||
|
|
6a1838bf0d | ||
|
|
df0593aac9 | ||
|
|
aa9b881c54 | ||
|
|
d91cc230e5 | ||
|
|
e0f7b5b5db | ||
|
|
ada7fb45e1 | ||
|
|
368a176c09 | ||
|
|
25d411ecf9 | ||
|
|
6f839142de | ||
|
|
bedb1854f9 | ||
|
|
7f8cc666a5 | ||
|
|
132db911c6 | ||
|
|
d2694048a4 | ||
|
|
722efe9587 | ||
|
|
7e8f702eb3 | ||
|
|
21d6ba2bb3 | ||
|
|
9b39719149 | ||
|
|
2f66c7746c | ||
|
|
b9d6f558cb | ||
|
|
e071ed740f | ||
|
|
0b4020a7e0 | ||
|
|
840b5d37d1 | ||
|
|
49dddc50d3 | ||
|
|
396f75b906 | ||
|
|
6fe9df6ec9 | ||
|
|
16759506e5 | ||
|
|
0688fac419 | ||
|
|
e1112b7abe | ||
|
|
a2133ef6cb | ||
|
|
824816154b | ||
|
|
2fe9866b28 | ||
|
|
2ed6818171 | ||
|
|
0164ad5519 | ||
|
|
244a91fda5 | ||
|
|
becba7861f | ||
|
|
730de56a5f | ||
|
|
72372c022f | ||
|
|
266b1f58f0 | ||
|
|
ede7c4e3ee | ||
|
|
a055cfe924 | ||
|
|
0e83f4515c | ||
|
|
51b2303b0a | ||
|
|
078cac76bf | ||
|
|
07b310d6e6 | ||
|
|
f36eeb182c | ||
|
|
6242f28bc5 | ||
|
|
2553b54432 | ||
|
|
6a54eee330 | ||
|
|
6b676750c0 | ||
|
|
f1d158bbe8 | ||
|
|
96862d64fc | ||
|
|
0f201ecf16 | ||
|
|
479d26f7c7 | ||
|
|
481c2ff781 | ||
|
|
0687120542 | ||
|
|
1bfb680b6b | ||
|
|
974ef29aa1 | ||
|
|
a4d1f56c01 | ||
|
|
35bc074a53 | ||
|
|
4d74611eb1 | ||
|
|
79cfc58533 | ||
|
|
735405a855 | ||
|
|
af40f06524 | ||
|
|
568cd0b39d | ||
|
|
8643c868fd | ||
|
|
eede2945ae | ||
|
|
1fc38c7379 | ||
|
|
271b84f78f | ||
|
|
dd896fea25 | ||
|
|
1e3f69d977 | ||
|
|
341f1c4ce7 | ||
|
|
b8ff0a80f0 | ||
|
|
760194ac80 | ||
|
|
d24fe54d2b | ||
|
|
1cc78112e5 | ||
|
|
0f816e4733 | ||
|
|
04dcacd3a5 | ||
|
|
47e231f061 | ||
|
|
4b7c26e273 | ||
|
|
d45dc473ad | ||
|
|
c766f3c054 | ||
|
|
03941dca8e | ||
|
|
be6e228c36 | ||
|
|
570e087007 | ||
|
|
afac23a79a | ||
|
|
3322f652fe | ||
|
|
d0cf9e02f4 | ||
|
|
84e3e43ae3 | ||
|
|
71b685364f | ||
|
|
3c8446a5e5 | ||
|
|
4e6530d1d8 | ||
|
|
0b87691d50 | ||
|
|
730046f83c | ||
|
|
763002f2fe | ||
|
|
76e630cf61 | ||
|
|
428b6ffbe7 | ||
|
|
78597aacac | ||
|
|
eacebad315 | ||
|
|
c8261d9883 | ||
|
|
eedaa9a2e2 | ||
|
|
fa37acc2fb | ||
|
|
05526e5cdc | ||
|
|
cf2e58bdb9 | ||
|
|
9b953f0942 | ||
|
|
75cc6eff32 | ||
|
|
c271e869c2 | ||
|
|
b71b14efdd | ||
|
|
7ffe17deea | ||
|
|
dd2e89bfdb | ||
|
|
18f8c88a89 | ||
|
|
bd3ff5f57c | ||
|
|
04a599962d | ||
|
|
3be5d84fc4 | ||
|
|
83d4bc4a5a | ||
|
|
83ea0ad93e | ||
|
|
b77b2f3fa0 | ||
|
|
111c3b3d0d | ||
|
|
76a2b90c17 | ||
|
|
aa83cda49c | ||
|
|
1ae4967fe5 | ||
|
|
12de7a85c9 | ||
|
|
91d0ae7da6 | ||
|
|
f7fab0c461 | ||
|
|
bde0eb1f07 | ||
|
|
73ee3140ea | ||
|
|
2a738dec09 | ||
|
|
3d5ee687cb | ||
|
|
7060aeca4b | ||
|
|
5ecb8e9821 | ||
|
|
ed3de96e4c | ||
|
|
db8a54d965 | ||
|
|
3980150aef | ||
|
|
3d4ec3181d | ||
|
|
779907e526 | ||
|
|
1841d6202f | ||
|
|
6a4ca70836 | ||
|
|
8dda7d5f81 | ||
|
|
e207f58031 | ||
|
|
faef74ab21 | ||
|
|
3ff9a65ef3 | ||
|
|
26d77fb149 | ||
|
|
5977326665 | ||
|
|
27e4f0440c | ||
|
|
f38805e6f1 | ||
|
|
a7892c0d59 | ||
|
|
991f17e0ca | ||
|
|
522d2aa764 | ||
|
|
fceb515a68 | ||
|
|
e1fb97f862 | ||
|
|
e0289dc49f | ||
|
|
302705ea4d | ||
|
|
ff0568f2ab | ||
|
|
545411137c | ||
|
|
1f33b291b9 | ||
|
|
768e5ba928 | ||
|
|
c175837273 | ||
|
|
529806c0d9 | ||
|
|
658d824505 | ||
|
|
94bdcf414d | ||
|
|
a24ec13239 | ||
|
|
2c7c62443c | ||
|
|
540923ad8b | ||
|
|
df926e2513 | ||
|
|
86ad50d886 | ||
|
|
0ed9ef06c1 | ||
|
|
4a59126dd9 | ||
|
|
277cef2168 | ||
|
|
168d5b27f3 | ||
|
|
fd5bcee909 | ||
|
|
8bbf83fb84 | ||
|
|
4253982050 | ||
|
|
10d93161b4 |
No files matched your search
+34
-10
@@ -15,22 +15,13 @@ defaults: &defaults
|
||||
commands:
|
||||
install_bun:
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- bun-cache-v2-{{ arch }}-latest
|
||||
- run:
|
||||
name: Install Bun
|
||||
command: |
|
||||
if [ ! -d "$HOME/.bun" ]; then
|
||||
curl -fsSL https://bun.sh/install | bash
|
||||
fi
|
||||
curl -fsSL https://bun.sh/install | bash -s "bun-v1.2.23"
|
||||
echo 'export BUN_INSTALL="$HOME/.bun"' >> $BASH_ENV
|
||||
echo 'export PATH="$BUN_INSTALL/bin:$PATH"' >> $BASH_ENV
|
||||
source $BASH_ENV
|
||||
- save_cache:
|
||||
key: bun-cache-v2-{{ arch }}-latest
|
||||
paths:
|
||||
- ~/.bun
|
||||
|
||||
jobs:
|
||||
UNIT_TESTS:
|
||||
@@ -121,6 +112,34 @@ jobs:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: ~/repo
|
||||
# SECURITY AUDIT
|
||||
- run:
|
||||
name: 'Security Audit - High Risk Vulnerabilities'
|
||||
command: |
|
||||
echo "🔍 Running bun audit for security vulnerabilities..."
|
||||
echo "Checking for HIGH-RISK vulnerabilities..."
|
||||
|
||||
if bun audit --audit-level high; then
|
||||
echo "✅ No high-risk vulnerabilities found"
|
||||
echo "🎉 Security audit passed!"
|
||||
else
|
||||
echo ""
|
||||
echo "❌ HIGH-RISK VULNERABILITIES DETECTED!"
|
||||
echo "======================================"
|
||||
echo ""
|
||||
echo "🔧 To fix these issues:"
|
||||
echo " 1. Run: bun audit"
|
||||
echo " 2. Review the vulnerability details"
|
||||
echo " 3. Update affected packages to secure versions"
|
||||
echo " 4. Test your changes"
|
||||
echo " 5. Re-run: bun audit --audit-level high"
|
||||
echo ""
|
||||
echo "📋 Full audit report:"
|
||||
bun audit --audit-level low || true
|
||||
echo ""
|
||||
echo "❌ This build cannot proceed until high-risk vulnerabilities are resolved."
|
||||
exit 1
|
||||
fi
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: bun install --frozen-lockfile
|
||||
@@ -455,8 +474,13 @@ workflows:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
# - HOLD_FOR_APPROVAL:
|
||||
# type: approval
|
||||
# requires:
|
||||
# - BUILD
|
||||
- NPM_PUBLISH:
|
||||
requires:
|
||||
# - HOLD_FOR_APPROVAL
|
||||
- BUILD
|
||||
- DOCKER_BETA_PUBLISH:
|
||||
requires:
|
||||
|
||||
@@ -51,28 +51,29 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: os
|
||||
- type: textarea
|
||||
id: system_info
|
||||
attributes:
|
||||
label: 'OS'
|
||||
description: 'Your operating system.'
|
||||
placeholder: 'e.g., Windows 10, macOS 10.15.4'
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: node-version
|
||||
attributes:
|
||||
label: 'Node version'
|
||||
description: 'Your Node.js version.'
|
||||
placeholder: 'e.g., 20.18.1'
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: browser
|
||||
attributes:
|
||||
label: 'Browser'
|
||||
description: 'Your browser.'
|
||||
placeholder: 'e.g., Chrome 83.0.4103.116, Firefox 77.0.1, Safari 13.1.1'
|
||||
label: 'System Information'
|
||||
description: 'Please run the following command in your terminal and paste the output:'
|
||||
placeholder: |
|
||||
Run: npx envinfo --system --binaries --browsers
|
||||
|
||||
Then paste the output here. It should look something like:
|
||||
|
||||
System:
|
||||
OS: Windows 10 10.0.19042
|
||||
CPU: (8) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
|
||||
Memory: 15.89 GB / 31.74 GB
|
||||
Shell: 1.0.0 - C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe
|
||||
Binaries:
|
||||
Node: 20.18.1 - C:\Program Files\nodejs\node.EXE
|
||||
Yarn: 1.22.22 - C:\Users\user\AppData\Roaming\npm\yarn.CMD
|
||||
npm: 10.8.2 - C:\Program Files\nodejs\npm.CMD
|
||||
Browsers:
|
||||
Chrome: 83.0.4103.116
|
||||
Edge: Spartan (44.19041.1266.0), Chromium (83.0.478.58)
|
||||
Firefox: 77.0.1
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: 1.2.23
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20 # Or your desired Node version
|
||||
|
||||
@@ -18,6 +18,8 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: 1.2.23
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
@@ -60,3 +60,6 @@ tests/playwright-report/
|
||||
/playwright/.cache/
|
||||
|
||||
**/.claude/settings.local.json
|
||||
|
||||
# Backup files
|
||||
*~
|
||||
@@ -10,6 +10,6 @@
|
||||
"deploy": "netlify deploy --prod --dir ./../platform/app/dist"
|
||||
},
|
||||
"devDependencies": {
|
||||
"netlify-cli": "^2.21.0"
|
||||
"netlify-cli": "2.21.0"
|
||||
}
|
||||
}
|
||||
@@ -201,8 +201,6 @@ module.exports = (env, argv, { SRC_DIR, ENTRY }) => {
|
||||
'@hooks': path.resolve(__dirname, '../platform/app/src/hooks'),
|
||||
'@routes': path.resolve(__dirname, '../platform/app/src/routes'),
|
||||
'@state': path.resolve(__dirname, '../platform/app/src/state'),
|
||||
'dicom-microscopy-viewer':
|
||||
'dicom-microscopy-viewer/dist/dynamic-import/dicomMicroscopyViewer.min.js',
|
||||
},
|
||||
// Which directories to search when resolving modules
|
||||
modules: [
|
||||
|
||||
+1004
File diff suppressed because it is too large.
Load diff
+3
-2
@@ -50,7 +50,7 @@ RUN apt-get update && apt-get install -y build-essential python3
|
||||
RUN mkdir /usr/src/app
|
||||
WORKDIR /usr/src/app
|
||||
RUN npm install -g bun
|
||||
# RUN npm install -g lerna@7.4.2
|
||||
RUN npm install -g lerna@7.4.2
|
||||
ENV PATH=/usr/src/app/node_modules/.bin:$PATH
|
||||
|
||||
# Do an initial install and then a final install
|
||||
@@ -60,6 +60,7 @@ COPY --parents ./addOns/package.json ./addOns/*/*/package.json ./extensions/*/pa
|
||||
|
||||
RUN bun pm cache rm
|
||||
RUN bun install
|
||||
RUN bun add ajv@8.12.0
|
||||
# Copy the local directory
|
||||
COPY --link --exclude=yarn.lock --exclude=package.json --exclude=Dockerfile . .
|
||||
|
||||
@@ -98,7 +99,7 @@ COPY --from=builder /usr/src/app/platform/app/dist/dicom-microscopy-viewer /usr/
|
||||
# In entrypoint.sh, app-config.js might be overwritten, so chmod it to be writeable.
|
||||
# The nginx user cannot chmod it, so change to root.
|
||||
USER root
|
||||
RUN chown -R nginx:nginx /usr/share/nginx/html
|
||||
RUN chown -R nginx:nginx /usr/share/nginx/html && chmod -R 777 /usr/share/nginx/html
|
||||
USER nginx
|
||||
ENTRYPOINT ["/usr/src/entrypoint.sh"]
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -76,7 +76,7 @@ contributions of individuals, research groups, and commercial organizations.
|
||||
After more than 8-years of integrating with many companies and organizations,
|
||||
The OHIF Viewer has been rebuilt from the ground up to better address the
|
||||
varying workflow and configuration needs of its many users. All of the Viewer's
|
||||
core features are built using it's own extension system. The same extensibility
|
||||
core features are built using its own extension system. The same extensibility
|
||||
that allows us to offer:
|
||||
|
||||
- 2D and 3D medical image viewing
|
||||
|
||||
+796
@@ -3,6 +3,802 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.12.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.59...v3.12.0-beta.60) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.58...v3.12.0-beta.59) (2025-10-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Use exact versioning for dependencies in package.json files. ([#5494](https://github.com/OHIF/Viewers/issues/5494)) ([c7d2017](https://github.com/OHIF/Viewers/commit/c7d2017f081c5803a70bab6c75bba0c975028125))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.57...v3.12.0-beta.58) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.56...v3.12.0-beta.57) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.55...v3.12.0-beta.56) (2025-10-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.54...v3.12.0-beta.55) (2025-10-09)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.53...v3.12.0-beta.54) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.52...v3.12.0-beta.53) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.51...v3.12.0-beta.52) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.50...v3.12.0-beta.51) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.49...v3.12.0-beta.50) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.48...v3.12.0-beta.49) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.47...v3.12.0-beta.48) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.46...v3.12.0-beta.47) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.45...v3.12.0-beta.46) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.44...v3.12.0-beta.45) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.43...v3.12.0-beta.44) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.42...v3.12.0-beta.43) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.41...v3.12.0-beta.42) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.40...v3.12.0-beta.41) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.39...v3.12.0-beta.40) (2025-10-02)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.38...v3.12.0-beta.39) (2025-10-01)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.37...v3.12.0-beta.38) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.36...v3.12.0-beta.37) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.35...v3.12.0-beta.36) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.34...v3.12.0-beta.35) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.33...v3.12.0-beta.34) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.32...v3.12.0-beta.33) (2025-09-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Removed dependency on tar-fs by removing dependencies on storybook and sharp. ([#5438](https://github.com/OHIF/Viewers/issues/5438)) ([80f314a](https://github.com/OHIF/Viewers/commit/80f314a422ec45fff6cdd5869f4293a110d00125))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.31...v3.12.0-beta.32) (2025-09-26)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.30...v3.12.0-beta.31) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.29...v3.12.0-beta.30) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.28...v3.12.0-beta.29) (2025-09-22)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.27...v3.12.0-beta.28) (2025-09-19)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.26...v3.12.0-beta.27) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.25...v3.12.0-beta.26) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.24...v3.12.0-beta.25) (2025-09-16)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.23...v3.12.0-beta.24) (2025-09-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.22...v3.12.0-beta.23) (2025-09-05)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.21...v3.12.0-beta.22) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.20...v3.12.0-beta.21) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.19...v3.12.0-beta.20) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.18...v3.12.0-beta.19) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.17...v3.12.0-beta.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.16...v3.12.0-beta.17) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.15...v3.12.0-beta.16) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.14...v3.12.0-beta.15) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.13...v3.12.0-beta.14) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.12...v3.12.0-beta.13) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.11...v3.12.0-beta.12) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.10...v3.12.0-beta.11) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.9...v3.12.0-beta.10) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.8...v3.12.0-beta.9) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.7...v3.12.0-beta.8) (2025-08-20)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.6...v3.12.0-beta.7) (2025-08-15)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.5...v3.12.0-beta.6) (2025-08-13)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.4...v3.12.0-beta.5) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.3...v3.12.0-beta.4) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.2...v3.12.0-beta.3) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.1...v3.12.0-beta.2) (2025-08-08)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.0...v3.12.0-beta.1) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.116...v3.12.0-beta.0) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.116](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.115...v3.11.0-beta.116) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.115](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.114...v3.11.0-beta.115) (2025-07-31)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.114](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.113...v3.11.0-beta.114) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.113](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.112...v3.11.0-beta.113) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.111...v3.11.0-beta.112) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.110...v3.11.0-beta.111) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.109...v3.11.0-beta.110) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.108...v3.11.0-beta.109) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.107...v3.11.0-beta.108) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.106...v3.11.0-beta.107) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.105...v3.11.0-beta.106) (2025-07-24)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.104...v3.11.0-beta.105) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.103...v3.11.0-beta.104) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.102...v3.11.0-beta.103) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.101...v3.11.0-beta.102) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.100...v3.11.0-beta.101) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.99...v3.11.0-beta.100) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.98...v3.11.0-beta.99) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.97...v3.11.0-beta.98) (2025-07-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Removed stylus package due to potential security vulnerability and we don't use it. ([#5250](https://github.com/OHIF/Viewers/issues/5250)) ([83d4bc4](https://github.com/OHIF/Viewers/commit/83d4bc4a5a470bc09ede78c92ef89611dbce1d00))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.96...v3.11.0-beta.97) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.95...v3.11.0-beta.96) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.94...v3.11.0-beta.95) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.93...v3.11.0-beta.94) (2025-07-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Pin eslint-config-prettier and eslint-plugin-prettier versions. ([#5234](https://github.com/OHIF/Viewers/issues/5234)) ([3d5ee68](https://github.com/OHIF/Viewers/commit/3d5ee687cb105acfbcfb045a95ca32047e8dd78a))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.92...v3.11.0-beta.93) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.91...v3.11.0-beta.92) (2025-07-18)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.90...v3.11.0-beta.91) (2025-07-17)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.89...v3.11.0-beta.90) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.88...v3.11.0-beta.89) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.87...v3.11.0-beta.88) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.86...v3.11.0-beta.87) (2025-07-15)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.85...v3.11.0-beta.86) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.84...v3.11.0-beta.85) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.83...v3.11.0-beta.84) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.82...v3.11.0-beta.83) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.81...v3.11.0-beta.82) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.80...v3.11.0-beta.81) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.79...v3.11.0-beta.80) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.78...v3.11.0-beta.79) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
+71
-73
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@externals/devDependencies",
|
||||
"description": "External dev dependencies - put dev build dependencies here",
|
||||
"version": "3.11.0-beta.79",
|
||||
"version": "3.12.0-beta.60",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"engines": {
|
||||
@@ -9,87 +9,85 @@
|
||||
"yarn": ">=1.19.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@kitware/vtk.js": "32.12.0",
|
||||
"clsx": "^2.1.1",
|
||||
"core-js": "^3.2.1",
|
||||
"moment": "^2.30.1"
|
||||
"clsx": "2.1.1",
|
||||
"core-js": "3.45.1",
|
||||
"moment": "2.30.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "7.28.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
|
||||
"@rsbuild/core": "^1.3.16",
|
||||
"@rsbuild/plugin-node-polyfill": "^1.3.0",
|
||||
"@rsbuild/plugin-react": "^1.3.1",
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@swc/helpers": "^0.5.15",
|
||||
"@types/jest": "^27.5.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.3.0",
|
||||
"@typescript-eslint/parser": "^6.3.0",
|
||||
"autoprefixer": "^10.4.4",
|
||||
"babel-loader": "^8.2.4",
|
||||
"babel-plugin-module-resolver": "^5.0.0",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"copy-webpack-plugin": "^9.0.1",
|
||||
"cross-env": "^5.2.0",
|
||||
"css-loader": "^6.8.1",
|
||||
"dotenv": "^8.1.0",
|
||||
"eslint": "^8.39.0",
|
||||
"eslint-config-prettier": "^7.2.0",
|
||||
"eslint-config-react-app": "^6.0.0",
|
||||
"eslint-plugin-cypress": "^2.12.1",
|
||||
"eslint-plugin-flowtype": "^7.0.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.5.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"eslint-plugin-promise": "^5.2.0",
|
||||
"eslint-plugin-react": "^7.29.4",
|
||||
"eslint-plugin-react-hooks": "^4.4.0",
|
||||
"eslint-plugin-tsdoc": "^0.2.11",
|
||||
"eslint-webpack-plugin": "^2.5.3",
|
||||
"execa": "^8.0.1",
|
||||
"extract-css-chunks-webpack-plugin": "^4.5.4",
|
||||
"html-webpack-plugin": "^5.3.2",
|
||||
"husky": "^3.0.0",
|
||||
"jest": "^29.5.0",
|
||||
"jest-canvas-mock": "^2.1.0",
|
||||
"jest-environment-jsdom": "^29.5.0",
|
||||
"jest-junit": "^6.4.0",
|
||||
"lerna": "^7.2.0",
|
||||
"lint-staged": "^9.0.2",
|
||||
"mini-css-extract-plugin": "^2.1.0",
|
||||
"optimize-css-assets-webpack-plugin": "^6.0.1",
|
||||
"postcss": "^8.3.5",
|
||||
"postcss-import": "^14.0.2",
|
||||
"postcss-loader": "^6.1.1",
|
||||
"postcss-preset-env": "^7.4.3",
|
||||
"prettier": "^3.0.3",
|
||||
"prettier-plugin-tailwindcss": "^0.5.4",
|
||||
"react-refresh": "^0.14.2",
|
||||
"semver": "^7.5.1",
|
||||
"serve": "^14.2.4",
|
||||
"shader-loader": "^1.3.1",
|
||||
"shx": "^0.3.3",
|
||||
"source-map-loader": "^4.0.1",
|
||||
"style-loader": "^1.0.0",
|
||||
"stylus": "^0.59.0",
|
||||
"stylus-loader": "^7.1.3",
|
||||
"terser-webpack-plugin": "^5.1.4",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "0.5.17",
|
||||
"@rsbuild/core": "1.5.1",
|
||||
"@rsbuild/plugin-node-polyfill": "1.4.2",
|
||||
"@rsbuild/plugin-react": "1.4.0",
|
||||
"@svgr/webpack": "8.1.0",
|
||||
"@swc/helpers": "0.5.17",
|
||||
"@types/jest": "27.5.2",
|
||||
"@typescript-eslint/eslint-plugin": "6.21.0",
|
||||
"@typescript-eslint/parser": "6.21.0",
|
||||
"autoprefixer": "10.4.21",
|
||||
"babel-loader": "8.4.1",
|
||||
"babel-plugin-module-resolver": "5.0.2",
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"copy-webpack-plugin": "9.1.0",
|
||||
"cross-env": "7.0.3",
|
||||
"css-loader": "6.11.0",
|
||||
"dotenv": "8.6.0",
|
||||
"eslint": "8.57.1",
|
||||
"eslint-config-prettier": "7.2.0",
|
||||
"eslint-config-react-app": "6.0.0",
|
||||
"eslint-plugin-cypress": "2.15.2",
|
||||
"eslint-plugin-flowtype": "7.0.0",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"eslint-plugin-jsx-a11y": "6.10.2",
|
||||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-prettier": "5.5.1",
|
||||
"eslint-plugin-promise": "5.2.0",
|
||||
"eslint-plugin-react": "7.37.5",
|
||||
"eslint-plugin-react-hooks": "4.6.2",
|
||||
"eslint-plugin-tsdoc": "0.2.17",
|
||||
"eslint-webpack-plugin": "2.7.0",
|
||||
"execa": "8.0.1",
|
||||
"extract-css-chunks-webpack-plugin": "4.10.0",
|
||||
"html-webpack-plugin": "5.6.3",
|
||||
"husky": "3.1.0",
|
||||
"jest": "29.7.0",
|
||||
"jest-canvas-mock": "2.5.2",
|
||||
"jest-environment-jsdom": "29.7.0",
|
||||
"jest-junit": "6.4.0",
|
||||
"lerna": "7.4.2",
|
||||
"lint-staged": "9.5.0",
|
||||
"mini-css-extract-plugin": "2.9.2",
|
||||
"optimize-css-assets-webpack-plugin": "6.0.1",
|
||||
"postcss": "8.5.6",
|
||||
"postcss-import": "14.1.0",
|
||||
"postcss-loader": "6.2.1",
|
||||
"postcss-preset-env": "7.8.3",
|
||||
"prettier": "3.6.2",
|
||||
"prettier-plugin-tailwindcss": "0.6.9",
|
||||
"react-refresh": "0.14.2",
|
||||
"semver": "7.7.2",
|
||||
"serve": "14.2.4",
|
||||
"shader-loader": "1.3.1",
|
||||
"shx": "0.3.4",
|
||||
"source-map-loader": "4.0.2",
|
||||
"style-loader": "1.3.0",
|
||||
"terser-webpack-plugin": "5.3.14",
|
||||
"typescript": "5.5.4",
|
||||
"unused-webpack-plugin": "2.4.0",
|
||||
"webpack": "^5.94.0",
|
||||
"webpack-bundle-analyzer": "^4.8.0",
|
||||
"webpack-cli": "^5.0.1",
|
||||
"webpack": "5.95.0",
|
||||
"webpack-bundle-analyzer": "4.10.2",
|
||||
"webpack-cli": "5.1.4",
|
||||
"webpack-dev-server": "5.2.2",
|
||||
"webpack-hot-middleware": "^2.25.0",
|
||||
"webpack-merge": "^5.7.3",
|
||||
"workbox-webpack-plugin": "^6.1.5",
|
||||
"worker-loader": "^3.0.8"
|
||||
"webpack-hot-middleware": "2.26.1",
|
||||
"webpack-merge": "5.10.0",
|
||||
"workbox-webpack-plugin": "6.6.1",
|
||||
"worker-loader": "3.0.8"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "Included as direct dependency"
|
||||
|
||||
@@ -3,6 +3,796 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.12.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.59...v3.12.0-beta.60) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.58...v3.12.0-beta.59) (2025-10-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Use exact versioning for dependencies in package.json files. ([#5494](https://github.com/OHIF/Viewers/issues/5494)) ([c7d2017](https://github.com/OHIF/Viewers/commit/c7d2017f081c5803a70bab6c75bba0c975028125))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.57...v3.12.0-beta.58) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.56...v3.12.0-beta.57) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.55...v3.12.0-beta.56) (2025-10-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.54...v3.12.0-beta.55) (2025-10-09)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.53...v3.12.0-beta.54) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.52...v3.12.0-beta.53) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.51...v3.12.0-beta.52) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.50...v3.12.0-beta.51) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.49...v3.12.0-beta.50) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.48...v3.12.0-beta.49) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.47...v3.12.0-beta.48) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.46...v3.12.0-beta.47) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.45...v3.12.0-beta.46) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.44...v3.12.0-beta.45) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.43...v3.12.0-beta.44) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.42...v3.12.0-beta.43) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.41...v3.12.0-beta.42) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.40...v3.12.0-beta.41) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.39...v3.12.0-beta.40) (2025-10-02)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.38...v3.12.0-beta.39) (2025-10-01)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.37...v3.12.0-beta.38) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.36...v3.12.0-beta.37) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.35...v3.12.0-beta.36) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.34...v3.12.0-beta.35) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.33...v3.12.0-beta.34) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.32...v3.12.0-beta.33) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.31...v3.12.0-beta.32) (2025-09-26)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.30...v3.12.0-beta.31) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.29...v3.12.0-beta.30) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.28...v3.12.0-beta.29) (2025-09-22)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.27...v3.12.0-beta.28) (2025-09-19)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.26...v3.12.0-beta.27) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.25...v3.12.0-beta.26) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.24...v3.12.0-beta.25) (2025-09-16)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.23...v3.12.0-beta.24) (2025-09-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.22...v3.12.0-beta.23) (2025-09-05)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.21...v3.12.0-beta.22) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.20...v3.12.0-beta.21) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.19...v3.12.0-beta.20) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.18...v3.12.0-beta.19) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.17...v3.12.0-beta.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.16...v3.12.0-beta.17) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.15...v3.12.0-beta.16) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.14...v3.12.0-beta.15) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.13...v3.12.0-beta.14) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.12...v3.12.0-beta.13) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.11...v3.12.0-beta.12) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.10...v3.12.0-beta.11) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.9...v3.12.0-beta.10) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.8...v3.12.0-beta.9) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.7...v3.12.0-beta.8) (2025-08-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add WSI bulk data annotations support (ANN) ([#4972](https://github.com/OHIF/Viewers/issues/4972)) ([2ed6818](https://github.com/OHIF/Viewers/commit/2ed681817142b13971bb17b3058be26bbab6b90b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.6...v3.12.0-beta.7) (2025-08-15)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.5...v3.12.0-beta.6) (2025-08-13)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.4...v3.12.0-beta.5) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.3...v3.12.0-beta.4) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.2...v3.12.0-beta.3) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.1...v3.12.0-beta.2) (2025-08-08)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.0...v3.12.0-beta.1) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.116...v3.12.0-beta.0) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.116](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.115...v3.11.0-beta.116) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.115](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.114...v3.11.0-beta.115) (2025-07-31)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.114](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.113...v3.11.0-beta.114) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.113](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.112...v3.11.0-beta.113) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.111...v3.11.0-beta.112) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.110...v3.11.0-beta.111) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.109...v3.11.0-beta.110) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.108...v3.11.0-beta.109) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.107...v3.11.0-beta.108) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.106...v3.11.0-beta.107) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.105...v3.11.0-beta.106) (2025-07-24)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.104...v3.11.0-beta.105) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.103...v3.11.0-beta.104) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.102...v3.11.0-beta.103) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.101...v3.11.0-beta.102) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.100...v3.11.0-beta.101) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.99...v3.11.0-beta.100) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.98...v3.11.0-beta.99) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.97...v3.11.0-beta.98) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.96...v3.11.0-beta.97) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.95...v3.11.0-beta.96) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.94...v3.11.0-beta.95) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.93...v3.11.0-beta.94) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.92...v3.11.0-beta.93) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.91...v3.11.0-beta.92) (2025-07-18)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.90...v3.11.0-beta.91) (2025-07-17)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.89...v3.11.0-beta.90) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.88...v3.11.0-beta.89) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.87...v3.11.0-beta.88) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.86...v3.11.0-beta.87) (2025-07-15)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.85...v3.11.0-beta.86) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.84...v3.11.0-beta.85) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.83...v3.11.0-beta.84) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.82...v3.11.0-beta.83) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.81...v3.11.0-beta.82) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.80...v3.11.0-beta.81) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.79...v3.11.0-beta.80) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.78...v3.11.0-beta.79) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "@externals/dicom-microscopy-viewer",
|
||||
"description": "External reference to dicom-microscopy-viewer",
|
||||
"version": "3.11.0-beta.79",
|
||||
"version": "3.12.0-beta.60",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dicom-microscopy-viewer": "^0.46.1"
|
||||
"dicom-microscopy-viewer": "0.48.6"
|
||||
}
|
||||
}
|
||||
+18
-19
@@ -22,30 +22,29 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.28.0",
|
||||
"@babel/plugin-transform-class-properties": "^7.27.1",
|
||||
"@babel/plugin-transform-object-rest-spread": "^7.28.0",
|
||||
"@babel/plugin-transform-private-methods": "^7.27.1",
|
||||
"@babel/plugin-transform-private-property-in-object": "^7.27.1",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-arrow-functions": "^7.16.7",
|
||||
"@babel/plugin-transform-regenerator": "^7.16.7",
|
||||
"@babel/plugin-transform-class-properties": "7.27.1",
|
||||
"@babel/plugin-transform-object-rest-spread": "7.28.0",
|
||||
"@babel/plugin-transform-private-methods": "7.27.1",
|
||||
"@babel/plugin-transform-private-property-in-object": "7.27.1",
|
||||
"@babel/plugin-syntax-dynamic-import": "7.8.3",
|
||||
"@babel/plugin-transform-arrow-functions": "7.27.1",
|
||||
"@babel/plugin-transform-regenerator": "7.28.1",
|
||||
"@babel/plugin-transform-runtime": "7.28.0",
|
||||
"@babel/plugin-transform-typescript": "^7.28.0",
|
||||
"@babel/plugin-transform-typescript": "7.28.0",
|
||||
"@babel/preset-env": "7.28.0",
|
||||
"@babel/preset-react": "^7.27.1",
|
||||
"@babel/preset-typescript": "^7.27.1"
|
||||
"@babel/preset-react": "7.27.1",
|
||||
"@babel/preset-typescript": "7.27.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"**/@babel/runtime": "^7.20.13",
|
||||
"**/@babel/runtime": "7.28.2",
|
||||
"commander": "8.3.0",
|
||||
"dcmjs": "^0.42.0",
|
||||
"dcmjs": "0.43.1",
|
||||
"dicomweb-client": ">=0.10.4",
|
||||
"nth-check": "^2.1.1",
|
||||
"trim-newlines": "^5.0.0",
|
||||
"glob-parent": "^6.0.2",
|
||||
"trim": "^1.0.0",
|
||||
"package-json": "^8.1.0",
|
||||
"typescript": "5.5.4",
|
||||
"sharp": "^0.32.6"
|
||||
"nth-check": "2.1.1",
|
||||
"trim-newlines": "5.0.0",
|
||||
"glob-parent": "6.0.2",
|
||||
"trim": "1.0.1",
|
||||
"package-json": "8.1.1",
|
||||
"typescript": "5.5.4"
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,8 @@ module.exports = {
|
||||
{
|
||||
modules: 'commonjs',
|
||||
debug: false,
|
||||
targets: { node: 'current' },
|
||||
bugfixes: true,
|
||||
},
|
||||
],
|
||||
'@babel/preset-react',
|
||||
@@ -32,6 +34,8 @@ module.exports = {
|
||||
'@babel/plugin-transform-runtime',
|
||||
'@babel/plugin-transform-typescript',
|
||||
'@babel/plugin-transform-class-static-block',
|
||||
'@babel/plugin-transform-for-of',
|
||||
['babel-plugin-transform-import-meta', { module: 'ES6' }],
|
||||
],
|
||||
},
|
||||
production: {
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
4d3ff5a6cc720431f774a179e24205bfaec1d539
|
||||
fbd9371884d0e87376d67eb98c17a4d62e4e6dd1
|
||||
@@ -0,0 +1,118 @@
|
||||
diff --git a/extensions/cornerstone/src/components/ViewportOrientationMenu/ViewportOrientationMenu.tsx b/extensions/cornerstone/src/components/ViewportOrientationMenu/ViewportOrientationMenu.tsx
|
||||
index 6c1e4f8f6..56dac15b5 100644
|
||||
--- a/extensions/cornerstone/src/components/ViewportOrientationMenu/ViewportOrientationMenu.tsx
|
||||
+++ b/extensions/cornerstone/src/components/ViewportOrientationMenu/ViewportOrientationMenu.tsx
|
||||
@@ -156,65 +156,65 @@ function ViewportOrientationMenu({
|
||||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
- className="flex h-[28px] flex-shrink-0 items-center justify-start self-stretch"
|
||||
+ className="flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0"
|
||||
onClick={() => handleOrientationChange('axial')}
|
||||
>
|
||||
- <span className="mr-0 flex w-4 items-center justify-center">
|
||||
+ <div className="mr-1 flex w-6 items-center justify-start">
|
||||
{currentOrientation === 'axial' ? (
|
||||
- <Icons.Checked className="text-primary h-5 w-5" />
|
||||
+ <Icons.Checked className="text-primary h-6 w-6" />
|
||||
) : null}
|
||||
- </span>
|
||||
- <span className="flex-1 text-left">Axial</span>
|
||||
+ </div>
|
||||
+ <div className="flex-1 text-left">Axial</div>
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
- className="flex h-[28px] flex-shrink-0 items-center justify-start self-stretch"
|
||||
+ className="flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0"
|
||||
onClick={() => handleOrientationChange('sagittal')}
|
||||
>
|
||||
- <span className="mr-0 flex w-4 items-center justify-center">
|
||||
+ <div className="mr-1 flex w-6 items-center justify-start">
|
||||
{currentOrientation === 'sagittal' ? (
|
||||
- <Icons.Checked className="text-primary h-5 w-5" />
|
||||
+ <Icons.Checked className="text-primary h-6 w-6" />
|
||||
) : null}
|
||||
- </span>
|
||||
- <span className="flex-1 text-left">Sagittal</span>
|
||||
+ </div>
|
||||
+ <div className="flex-1 text-left">Sagittal</div>
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
- className="flex h-[28px] flex-shrink-0 items-center justify-start self-stretch"
|
||||
+ className="flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0"
|
||||
onClick={() => handleOrientationChange('coronal')}
|
||||
>
|
||||
- <span className="mr-0 flex w-4 items-center justify-center">
|
||||
+ <div className="mr-1 flex w-6 items-center justify-start">
|
||||
{currentOrientation === 'coronal' ? (
|
||||
- <Icons.Checked className="text-primary h-5 w-5" />
|
||||
+ <Icons.Checked className="text-primary h-6 w-6" />
|
||||
) : null}
|
||||
- </span>
|
||||
- <span className="flex-1 text-left">Coronal</span>
|
||||
+ </div>
|
||||
+ <div className="flex-1 text-left">Coronal</div>
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
- className="flex h-[28px] flex-shrink-0 items-center justify-start self-stretch"
|
||||
+ className="flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0"
|
||||
onClick={() => handleOrientationChange('acquisition')}
|
||||
>
|
||||
- <span className="mr-0 flex w-4 items-center justify-center">
|
||||
+ <div className="mr-1 flex w-6 items-center justify-start">
|
||||
{currentOrientation === 'acquisition' ? (
|
||||
- <Icons.Checked className="text-primary h-5 w-5" />
|
||||
+ <Icons.Checked className="text-primary h-6 w-6" />
|
||||
) : null}
|
||||
- </span>
|
||||
- <span className="flex-1 text-left">Acquisition</span>
|
||||
+ </div>
|
||||
+ <div className="flex-1 text-left">Acquisition</div>
|
||||
</Button>
|
||||
{/* Divider */}
|
||||
- <div className="my-2 border-t border-white/20" />
|
||||
+ <div className="mx-1 my-2 border-t border-white/20" />
|
||||
<Button
|
||||
variant="ghost"
|
||||
- className="flex h-[28px] flex-shrink-0 items-center justify-start self-stretch"
|
||||
+ className="flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0"
|
||||
onClick={() => handleOrientationChange('reformat')}
|
||||
>
|
||||
- <span className="mr-0 flex w-4 items-center justify-center">
|
||||
+ <div className="mr-1 flex w-6 items-center justify-start">
|
||||
{currentOrientation === 'reformat' ? (
|
||||
- <Icons.Checked className="text-primary h-5 w-5" />
|
||||
+ <Icons.Checked className="text-primary h-6 w-6" />
|
||||
) : null}
|
||||
- </span>
|
||||
- <span className="flex-1 text-left">Reformat</span>
|
||||
+ </div>
|
||||
+ <div className="flex-1 text-left">Reformat</div>
|
||||
</Button>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
diff --git a/platform/ui-next/src/components/Icons/Sources/Checked.tsx b/platform/ui-next/src/components/Icons/Sources/Checked.tsx
|
||||
index 83c8fc57e..c88b75e0d 100644
|
||||
--- a/platform/ui-next/src/components/Icons/Sources/Checked.tsx
|
||||
+++ b/platform/ui-next/src/components/Icons/Sources/Checked.tsx
|
||||
@@ -4,14 +4,14 @@ import type { IconProps } from '../types';
|
||||
export const Checked = (props: IconProps) => (
|
||||
<svg
|
||||
{...props}
|
||||
- width="24"
|
||||
+ width="20"
|
||||
height="24"
|
||||
- viewBox="0 0 24 24"
|
||||
+ viewBox="0 0 20 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
- d="M16 9L11.3333 15L8 12.4737"
|
||||
+ d="M14 9L9.3333 15L6 12.4737"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
@@ -3,6 +3,805 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.12.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.59...v3.12.0-beta.60) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.58...v3.12.0-beta.59) (2025-10-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Use exact versioning for dependencies in package.json files. ([#5494](https://github.com/OHIF/Viewers/issues/5494)) ([c7d2017](https://github.com/OHIF/Viewers/commit/c7d2017f081c5803a70bab6c75bba0c975028125))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.57...v3.12.0-beta.58) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.56...v3.12.0-beta.57) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.55...v3.12.0-beta.56) (2025-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.54...v3.12.0-beta.55) (2025-10-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.53...v3.12.0-beta.54) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.52...v3.12.0-beta.53) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.51...v3.12.0-beta.52) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.50...v3.12.0-beta.51) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.49...v3.12.0-beta.50) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.48...v3.12.0-beta.49) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.47...v3.12.0-beta.48) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.46...v3.12.0-beta.47) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.45...v3.12.0-beta.46) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.44...v3.12.0-beta.45) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.43...v3.12.0-beta.44) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.42...v3.12.0-beta.43) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.41...v3.12.0-beta.42) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.40...v3.12.0-beta.41) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.39...v3.12.0-beta.40) (2025-10-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.38...v3.12.0-beta.39) (2025-10-01)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.37...v3.12.0-beta.38) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.36...v3.12.0-beta.37) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.35...v3.12.0-beta.36) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.34...v3.12.0-beta.35) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.33...v3.12.0-beta.34) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.32...v3.12.0-beta.33) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.31...v3.12.0-beta.32) (2025-09-26)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.30...v3.12.0-beta.31) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.29...v3.12.0-beta.30) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.28...v3.12.0-beta.29) (2025-09-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.27...v3.12.0-beta.28) (2025-09-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.26...v3.12.0-beta.27) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.25...v3.12.0-beta.26) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.24...v3.12.0-beta.25) (2025-09-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.23...v3.12.0-beta.24) (2025-09-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.22...v3.12.0-beta.23) (2025-09-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.21...v3.12.0-beta.22) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.20...v3.12.0-beta.21) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.19...v3.12.0-beta.20) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.18...v3.12.0-beta.19) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.17...v3.12.0-beta.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.16...v3.12.0-beta.17) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.15...v3.12.0-beta.16) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.14...v3.12.0-beta.15) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.13...v3.12.0-beta.14) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.12...v3.12.0-beta.13) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.11...v3.12.0-beta.12) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.10...v3.12.0-beta.11) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.9...v3.12.0-beta.10) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.8...v3.12.0-beta.9) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.7...v3.12.0-beta.8) (2025-08-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add WSI bulk data annotations support (ANN) ([#4972](https://github.com/OHIF/Viewers/issues/4972)) ([2ed6818](https://github.com/OHIF/Viewers/commit/2ed681817142b13971bb17b3058be26bbab6b90b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.6...v3.12.0-beta.7) (2025-08-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.5...v3.12.0-beta.6) (2025-08-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.4...v3.12.0-beta.5) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.3...v3.12.0-beta.4) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.2...v3.12.0-beta.3) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.1...v3.12.0-beta.2) (2025-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.0...v3.12.0-beta.1) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.116...v3.12.0-beta.0) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.116](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.115...v3.11.0-beta.116) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.115](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.114...v3.11.0-beta.115) (2025-07-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add support to scoord3d ([#5016](https://github.com/OHIF/Viewers/issues/5016)) ([735405a](https://github.com/OHIF/Viewers/commit/735405a8554c7ee6283faa83fc42ff8bb9ac34ff))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.114](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.113...v3.11.0-beta.114) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.113](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.112...v3.11.0-beta.113) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.111...v3.11.0-beta.112) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.110...v3.11.0-beta.111) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.109...v3.11.0-beta.110) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.108...v3.11.0-beta.109) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.107...v3.11.0-beta.108) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.106...v3.11.0-beta.107) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.105...v3.11.0-beta.106) (2025-07-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.104...v3.11.0-beta.105) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.103...v3.11.0-beta.104) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.102...v3.11.0-beta.103) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.101...v3.11.0-beta.102) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.100...v3.11.0-beta.101) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.99...v3.11.0-beta.100) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.98...v3.11.0-beta.99) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.97...v3.11.0-beta.98) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.96...v3.11.0-beta.97) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.95...v3.11.0-beta.96) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.94...v3.11.0-beta.95) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.93...v3.11.0-beta.94) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.92...v3.11.0-beta.93) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.91...v3.11.0-beta.92) (2025-07-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.90...v3.11.0-beta.91) (2025-07-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.89...v3.11.0-beta.90) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.88...v3.11.0-beta.89) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.87...v3.11.0-beta.88) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.86...v3.11.0-beta.87) (2025-07-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.85...v3.11.0-beta.86) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.84...v3.11.0-beta.85) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.83...v3.11.0-beta.84) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.82...v3.11.0-beta.83) (2025-07-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* enhance preview accept method ([#5199](https://github.com/OHIF/Viewers/issues/5199)) ([540923a](https://github.com/OHIF/Viewers/commit/540923ad8b2f768bd0f766c4f106cf6785a06afc))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.81...v3.11.0-beta.82) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.80...v3.11.0-beta.81) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.79...v3.11.0-beta.80) (2025-07-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **rendering:** Introduce WebGLContextPool for parallel rendering in ContextPoolRenderingEngine ([#5196](https://github.com/OHIF/Viewers/issues/5196)) ([10d9316](https://github.com/OHIF/Viewers/commit/10d93161b4a1bea18ec1b9de9ae3e094e6bb47d0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.78...v3.11.0-beta.79) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-pmap",
|
||||
"version": "3.11.0-beta.79",
|
||||
"version": "3.12.0-beta.60",
|
||||
"description": "DICOM Parametric Map read workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -33,22 +33,22 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.11.0-beta.79",
|
||||
"@ohif/extension-cornerstone": "3.11.0-beta.79",
|
||||
"@ohif/extension-default": "3.11.0-beta.79",
|
||||
"@ohif/i18n": "3.11.0-beta.79",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-i18next": "^12.2.2",
|
||||
"react-router": "^6.8.1",
|
||||
"react-router-dom": "^6.8.1"
|
||||
"@ohif/core": "3.12.0-beta.60",
|
||||
"@ohif/extension-cornerstone": "3.12.0-beta.60",
|
||||
"@ohif/extension-default": "3.12.0-beta.60",
|
||||
"@ohif/i18n": "3.12.0-beta.60",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-i18next": "12.3.1",
|
||||
"react-router": "6.30.1",
|
||||
"react-router-dom": "6.30.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^3.29.2",
|
||||
"@cornerstonejs/core": "^3.29.2",
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.5.5",
|
||||
"@cornerstonejs/core": "4.5.5",
|
||||
"@kitware/vtk.js": "32.12.0",
|
||||
"react-color": "^2.19.3"
|
||||
"react-color": "2.19.3"
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,805 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.12.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.59...v3.12.0-beta.60) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.58...v3.12.0-beta.59) (2025-10-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Use exact versioning for dependencies in package.json files. ([#5494](https://github.com/OHIF/Viewers/issues/5494)) ([c7d2017](https://github.com/OHIF/Viewers/commit/c7d2017f081c5803a70bab6c75bba0c975028125))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.57...v3.12.0-beta.58) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.56...v3.12.0-beta.57) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.55...v3.12.0-beta.56) (2025-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.54...v3.12.0-beta.55) (2025-10-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.53...v3.12.0-beta.54) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.52...v3.12.0-beta.53) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.51...v3.12.0-beta.52) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.50...v3.12.0-beta.51) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.49...v3.12.0-beta.50) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.48...v3.12.0-beta.49) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.47...v3.12.0-beta.48) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.46...v3.12.0-beta.47) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.45...v3.12.0-beta.46) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.44...v3.12.0-beta.45) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.43...v3.12.0-beta.44) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.42...v3.12.0-beta.43) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.41...v3.12.0-beta.42) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.40...v3.12.0-beta.41) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.39...v3.12.0-beta.40) (2025-10-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.38...v3.12.0-beta.39) (2025-10-01)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.37...v3.12.0-beta.38) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.36...v3.12.0-beta.37) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.35...v3.12.0-beta.36) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.34...v3.12.0-beta.35) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.33...v3.12.0-beta.34) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.32...v3.12.0-beta.33) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.31...v3.12.0-beta.32) (2025-09-26)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.30...v3.12.0-beta.31) (2025-09-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Improve rt handling for bulkdata ([#5415](https://github.com/OHIF/Viewers/issues/5415)) ([d88a341](https://github.com/OHIF/Viewers/commit/d88a341884f7361865bc10159c1a82633667ab5b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.29...v3.12.0-beta.30) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.28...v3.12.0-beta.29) (2025-09-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.27...v3.12.0-beta.28) (2025-09-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.26...v3.12.0-beta.27) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.25...v3.12.0-beta.26) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.24...v3.12.0-beta.25) (2025-09-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.23...v3.12.0-beta.24) (2025-09-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.22...v3.12.0-beta.23) (2025-09-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cornerstone-dicom-rt:** adding caching usage to cornerstone-dicom-rt SOP Class Handler ([#5387](https://github.com/OHIF/Viewers/issues/5387)) ([d6ea179](https://github.com/OHIF/Viewers/commit/d6ea179ac43a47d4011b8dcaf59d79d99382d6c8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.21...v3.12.0-beta.22) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.20...v3.12.0-beta.21) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.19...v3.12.0-beta.20) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.18...v3.12.0-beta.19) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.17...v3.12.0-beta.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.16...v3.12.0-beta.17) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.15...v3.12.0-beta.16) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.14...v3.12.0-beta.15) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.13...v3.12.0-beta.14) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.12...v3.12.0-beta.13) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.11...v3.12.0-beta.12) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.10...v3.12.0-beta.11) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.9...v3.12.0-beta.10) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.8...v3.12.0-beta.9) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.7...v3.12.0-beta.8) (2025-08-20)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.6...v3.12.0-beta.7) (2025-08-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.5...v3.12.0-beta.6) (2025-08-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.4...v3.12.0-beta.5) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.3...v3.12.0-beta.4) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.2...v3.12.0-beta.3) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.1...v3.12.0-beta.2) (2025-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.0...v3.12.0-beta.1) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.116...v3.12.0-beta.0) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.116](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.115...v3.11.0-beta.116) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.115](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.114...v3.11.0-beta.115) (2025-07-31)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.114](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.113...v3.11.0-beta.114) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.113](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.112...v3.11.0-beta.113) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.111...v3.11.0-beta.112) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.110...v3.11.0-beta.111) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.109...v3.11.0-beta.110) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.108...v3.11.0-beta.109) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.107...v3.11.0-beta.108) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.106...v3.11.0-beta.107) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.105...v3.11.0-beta.106) (2025-07-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.104...v3.11.0-beta.105) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.103...v3.11.0-beta.104) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.102...v3.11.0-beta.103) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.101...v3.11.0-beta.102) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.100...v3.11.0-beta.101) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.99...v3.11.0-beta.100) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.98...v3.11.0-beta.99) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.97...v3.11.0-beta.98) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.96...v3.11.0-beta.97) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.95...v3.11.0-beta.96) (2025-07-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **segmentation:** Add customization for handling missing referencedDisplaySetInstanceUID for the SEG/RTSTRUCT. ([#4983](https://github.com/OHIF/Viewers/issues/4983)) ([12de7a8](https://github.com/OHIF/Viewers/commit/12de7a85c9330471d81f481de7bc65e60c1c4ab3))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.94...v3.11.0-beta.95) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.93...v3.11.0-beta.94) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.92...v3.11.0-beta.93) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.91...v3.11.0-beta.92) (2025-07-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.90...v3.11.0-beta.91) (2025-07-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.89...v3.11.0-beta.90) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.88...v3.11.0-beta.89) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.87...v3.11.0-beta.88) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.86...v3.11.0-beta.87) (2025-07-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Removed LOAD/hydrate button for segmentation overlays ([#5214](https://github.com/OHIF/Viewers/issues/5214)) ([e0289dc](https://github.com/OHIF/Viewers/commit/e0289dc49f52e7ee6f0642f01de3ae31cddf71e0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.85...v3.11.0-beta.86) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.84...v3.11.0-beta.85) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.83...v3.11.0-beta.84) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.82...v3.11.0-beta.83) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.81...v3.11.0-beta.82) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.80...v3.11.0-beta.81) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.79...v3.11.0-beta.80) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.78...v3.11.0-beta.79) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-rt",
|
||||
"version": "3.11.0-beta.79",
|
||||
"version": "3.12.0-beta.60",
|
||||
"description": "DICOM RT read workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -33,19 +33,19 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.11.0-beta.79",
|
||||
"@ohif/extension-cornerstone": "3.11.0-beta.79",
|
||||
"@ohif/extension-default": "3.11.0-beta.79",
|
||||
"@ohif/i18n": "3.11.0-beta.79",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-i18next": "^10.11.0",
|
||||
"react-router": "^6.23.1",
|
||||
"react-router-dom": "^6.23.1"
|
||||
"@ohif/core": "3.12.0-beta.60",
|
||||
"@ohif/extension-cornerstone": "3.12.0-beta.60",
|
||||
"@ohif/extension-default": "3.12.0-beta.60",
|
||||
"@ohif/i18n": "3.12.0-beta.60",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-i18next": "12.3.1",
|
||||
"react-router": "6.30.1",
|
||||
"react-router-dom": "6.30.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"react-color": "^2.19.3"
|
||||
"@babel/runtime": "7.28.2",
|
||||
"react-color": "2.19.3"
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,11 @@ import i18n from '@ohif/i18n';
|
||||
import { SOPClassHandlerId } from './id';
|
||||
import loadRTStruct from './loadRTStruct';
|
||||
|
||||
const sopClassUids = ['1.2.840.10008.5.1.4.1.1.481.3'];
|
||||
const { sopClassDictionary } = utils;
|
||||
|
||||
const sopClassUids = [sopClassDictionary.RTStructureSetStorage];
|
||||
|
||||
const cachedRTStructsSEG = new Set<string>();
|
||||
|
||||
const loadPromises = {};
|
||||
|
||||
@@ -113,39 +117,45 @@ function _load(
|
||||
) {
|
||||
const { SOPInstanceUID } = rtDisplaySet;
|
||||
const { segmentationService } = servicesManager.services;
|
||||
|
||||
if (
|
||||
(rtDisplaySet.loading || rtDisplaySet.isLoaded) &&
|
||||
loadPromises[SOPInstanceUID] &&
|
||||
_segmentationExistsInCache(rtDisplaySet, segmentationService)
|
||||
cachedRTStructsSEG.has(rtDisplaySet.displaySetInstanceUID)
|
||||
) {
|
||||
return loadPromises[SOPInstanceUID];
|
||||
}
|
||||
|
||||
rtDisplaySet.loading = true;
|
||||
|
||||
const { unsubscribe } = segmentationService.subscribe(
|
||||
segmentationService.EVENTS.SEGMENTATION_LOADING_COMPLETE,
|
||||
(evt: { rtDisplaySet: { displaySetInstanceUID: string } }) => {
|
||||
if (evt.rtDisplaySet?.displaySetInstanceUID === rtDisplaySet.displaySetInstanceUID) {
|
||||
cachedRTStructsSEG.add(rtDisplaySet.displaySetInstanceUID);
|
||||
unsubscribe();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// We don't want to fire multiple loads, so we'll wait for the first to finish
|
||||
// and also return the same promise to any other callers.
|
||||
loadPromises[SOPInstanceUID] = new Promise(async (resolve, reject) => {
|
||||
if (!rtDisplaySet.structureSet) {
|
||||
const structureSet = await loadRTStruct(extensionManager, rtDisplaySet, headers);
|
||||
loadPromises[SOPInstanceUID] = new Promise<void>(async (resolve, reject) => {
|
||||
try {
|
||||
if (!rtDisplaySet.structureSet) {
|
||||
const structureSet = await loadRTStruct(extensionManager, rtDisplaySet, headers);
|
||||
rtDisplaySet.structureSet = structureSet;
|
||||
}
|
||||
|
||||
rtDisplaySet.structureSet = structureSet;
|
||||
}
|
||||
if (createSegmentation) {
|
||||
await segmentationService.createSegmentationForRTDisplaySet(rtDisplaySet);
|
||||
}
|
||||
|
||||
if (createSegmentation) {
|
||||
segmentationService
|
||||
.createSegmentationForRTDisplaySet(rtDisplaySet)
|
||||
.then(() => {
|
||||
rtDisplaySet.loading = false;
|
||||
resolve();
|
||||
})
|
||||
.catch(error => {
|
||||
rtDisplaySet.loading = false;
|
||||
reject(error);
|
||||
});
|
||||
} else {
|
||||
rtDisplaySet.loading = false;
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
} finally {
|
||||
rtDisplaySet.loading = false;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -187,11 +197,6 @@ function _deriveReferencedSeriesSequenceFromFrameOfReferenceSequence(
|
||||
return ReferencedSeriesSequence;
|
||||
}
|
||||
|
||||
function _segmentationExistsInCache() {
|
||||
// Todo: fix this
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSopClassHandlerModule(params: OhifTypes.Extensions.ExtensionParams) {
|
||||
const { servicesManager, extensionManager } = params;
|
||||
|
||||
|
||||
@@ -2,9 +2,34 @@ import dcmjs from 'dcmjs';
|
||||
const { DicomMessage, DicomMetaDictionary } = dcmjs.data;
|
||||
const dicomlab2RGB = dcmjs.data.Colors.dicomlab2RGB;
|
||||
|
||||
async function checkAndLoadContourData(instance, datasource) {
|
||||
/**
|
||||
* Checks and loads contour data for RT Structure Set, handling both inline and bulk data URIs.
|
||||
* Processes ROIContourSequence to extract contour data and resolve any bulk data references.
|
||||
*
|
||||
* @async
|
||||
* @function checkAndLoadContourData
|
||||
* @param {Object} params - Parameters object
|
||||
* @param {Object} params.instance - Initial RT Structure instance
|
||||
* @param {Object} params.dataSource - Data source for retrieving bulk data
|
||||
* @param {Object} params.extensionManager - OHIF extension manager
|
||||
* @param {Object} params.rtStructDisplaySet - RT Structure display set
|
||||
* @param {Object} params.headers - HTTP headers for requests
|
||||
* @returns {Promise<Object>} Promise that resolves to the processed RT Structure instance with loaded contour data
|
||||
* @throws {Promise<string>} Rejects with error message if instance is invalid or data retrieval fails
|
||||
*/
|
||||
async function checkAndLoadContourData({
|
||||
instance: initialInstance,
|
||||
dataSource,
|
||||
extensionManager,
|
||||
rtStructDisplaySet,
|
||||
headers,
|
||||
}) {
|
||||
let instance = initialInstance;
|
||||
if (!instance || !instance.ROIContourSequence) {
|
||||
return Promise.reject('Invalid instance object or ROIContourSequence');
|
||||
instance = await getRTStructInstance({ extensionManager, rtStructDisplaySet, headers });
|
||||
if (!instance || !instance.ROIContourSequence) {
|
||||
return Promise.reject('Invalid instance object or ROIContourSequence');
|
||||
}
|
||||
}
|
||||
|
||||
const promisesMap = new Map();
|
||||
@@ -30,11 +55,11 @@ async function checkAndLoadContourData(instance, datasource) {
|
||||
} else if (contourData && contourData.BulkDataURI) {
|
||||
const bulkDataURI = contourData.BulkDataURI;
|
||||
|
||||
if (!datasource || !datasource.retrieve || !datasource.retrieve.bulkDataURI) {
|
||||
return Promise.reject('Invalid datasource object or retrieve function');
|
||||
if (!dataSource || !dataSource.retrieve || !dataSource.retrieve.bulkDataURI) {
|
||||
return Promise.reject('Invalid dataSource object or retrieve function');
|
||||
}
|
||||
|
||||
const bulkDataPromise = datasource.retrieve.bulkDataURI({
|
||||
const bulkDataPromise = dataSource.retrieve.bulkDataURI({
|
||||
BulkDataURI: bulkDataURI,
|
||||
StudyInstanceUID: instance.StudyInstanceUID,
|
||||
SeriesInstanceUID: instance.SeriesInstanceUID,
|
||||
@@ -87,35 +112,74 @@ async function checkAndLoadContourData(instance, datasource) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
export default async function loadRTStruct(extensionManager, rtStructDisplaySet, headers) {
|
||||
/**
|
||||
* Retrieves and parses RT Structure Set instance from DICOM data.
|
||||
* Uses the cornerstone utility module to load DICOM data and converts it to a naturalized dataset.
|
||||
*
|
||||
* @async
|
||||
* @function getRTStructInstance
|
||||
* @param {Object} params - Parameters object
|
||||
* @param {Object} params.extensionManager - OHIF extension manager
|
||||
* @param {Object} params.rtStructDisplaySet - RT Structure display set
|
||||
* @param {Object} params.headers - HTTP headers for requests
|
||||
* @returns {Promise<Object>} Promise that resolves to the parsed RT Structure dataset
|
||||
*/
|
||||
const getRTStructInstance = async ({ extensionManager, rtStructDisplaySet, headers }) => {
|
||||
const utilityModule = extensionManager.getModuleEntry(
|
||||
'@ohif/extension-cornerstone.utilityModule.common'
|
||||
);
|
||||
const { dicomLoaderService } = utilityModule.exports;
|
||||
const segArrayBuffer = await dicomLoaderService.findDicomDataPromise(
|
||||
rtStructDisplaySet,
|
||||
null,
|
||||
headers
|
||||
);
|
||||
const dicomData = DicomMessage.readFile(segArrayBuffer);
|
||||
const rtStructDataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
|
||||
rtStructDataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
|
||||
return rtStructDataset;
|
||||
};
|
||||
|
||||
/**
|
||||
* Main function to load and process RT Structure Set data.
|
||||
* Creates a structure set object with ROI contours, metadata, and visualization properties.
|
||||
* Handles both bulk data URI and inline contour data scenarios.
|
||||
*
|
||||
* @async
|
||||
* @function loadRTStruct
|
||||
* @param {Object} extensionManager - OHIF extension manager
|
||||
* @param {Object} rtStructDisplaySet - RT Structure display set to process
|
||||
* @param {Object} headers - HTTP headers for data requests
|
||||
* @returns {Promise<Object>} Promise that resolves to a structure set object containing:
|
||||
* - StructureSetLabel: Label of the structure set
|
||||
* - SeriesInstanceUID: Series instance UID
|
||||
* - ROIContours: Array of ROI contour data with points and metadata
|
||||
* - visible: Visibility state
|
||||
* - ReferencedSOPInstanceUIDsSet: Set of referenced SOP instance UIDs
|
||||
*/
|
||||
export default async function loadRTStruct(extensionManager, rtStructDisplaySet, headers) {
|
||||
const dataSource = extensionManager.getActiveDataSource()[0];
|
||||
const { bulkDataURI } = dataSource.getConfig?.() || {};
|
||||
|
||||
const { dicomLoaderService } = utilityModule.exports;
|
||||
|
||||
// Set here is loading is asynchronous.
|
||||
// If this function throws its set back to false.
|
||||
rtStructDisplaySet.isLoaded = true;
|
||||
let instance = rtStructDisplaySet.instance;
|
||||
|
||||
if (!bulkDataURI || !bulkDataURI.enabled) {
|
||||
const segArrayBuffer = await dicomLoaderService.findDicomDataPromise(
|
||||
rtStructDisplaySet,
|
||||
null,
|
||||
headers
|
||||
);
|
||||
|
||||
const dicomData = DicomMessage.readFile(segArrayBuffer);
|
||||
const rtStructDataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
|
||||
rtStructDataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
|
||||
instance = rtStructDataset;
|
||||
instance = await getRTStructInstance({ extensionManager, rtStructDisplaySet, headers });
|
||||
} else {
|
||||
await checkAndLoadContourData(instance, dataSource);
|
||||
instance = await checkAndLoadContourData({
|
||||
instance,
|
||||
dataSource,
|
||||
extensionManager,
|
||||
rtStructDisplaySet,
|
||||
headers,
|
||||
});
|
||||
}
|
||||
|
||||
const { StructureSetROISequence, ROIContourSequence, RTROIObservationsSequence } = instance;
|
||||
@@ -132,21 +196,16 @@ export default async function loadRTStruct(extensionManager, rtStructDisplaySet,
|
||||
for (let i = 0; i < ROIContourSequence.length; i++) {
|
||||
const ROIContour = ROIContourSequence[i];
|
||||
const { ContourSequence } = ROIContour;
|
||||
|
||||
if (!ContourSequence) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const isSupported = false;
|
||||
|
||||
const ContourSequenceArray = _toArray(ContourSequence);
|
||||
|
||||
const contourPoints = [];
|
||||
for (let c = 0; c < ContourSequenceArray.length; c++) {
|
||||
for (const ContourSequenceItem of ContourSequenceArray) {
|
||||
const { ContourData, NumberOfContourPoints, ContourGeometricType, ContourImageSequence } =
|
||||
ContourSequenceArray[c];
|
||||
|
||||
let isSupported = false;
|
||||
ContourSequenceItem;
|
||||
|
||||
const points = [];
|
||||
for (let p = 0; p < NumberOfContourPoints * 3; p += 3) {
|
||||
@@ -157,22 +216,18 @@ export default async function loadRTStruct(extensionManager, rtStructDisplaySet,
|
||||
});
|
||||
}
|
||||
|
||||
switch (ContourGeometricType) {
|
||||
case 'CLOSED_PLANAR':
|
||||
case 'OPEN_PLANAR':
|
||||
case 'POINT':
|
||||
isSupported = true;
|
||||
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
const supportedContourTypesMap = new Map([
|
||||
['CLOSED_PLANAR', false],
|
||||
['OPEN_NONPLANAR', false],
|
||||
['OPEN_PLANAR', false],
|
||||
['POINT', true],
|
||||
]);
|
||||
|
||||
contourPoints.push({
|
||||
numberOfPoints: NumberOfContourPoints,
|
||||
points,
|
||||
type: ContourGeometricType,
|
||||
isSupported,
|
||||
isSupported: supportedContourTypesMap.get(ContourGeometricType) ?? false,
|
||||
});
|
||||
|
||||
if (ContourImageSequence?.ReferencedSOPInstanceUID) {
|
||||
@@ -187,20 +242,30 @@ export default async function loadRTStruct(extensionManager, rtStructDisplaySet,
|
||||
StructureSetROISequence,
|
||||
RTROIObservationsSequence,
|
||||
ROIContour,
|
||||
contourPoints,
|
||||
isSupported
|
||||
contourPoints
|
||||
);
|
||||
}
|
||||
return structureSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets metadata for ROI contour data and adds it to the structure set.
|
||||
* Extracts ROI information from StructureSetROISequence and RTROIObservationsSequence,
|
||||
* then creates a complete ROI contour data object with visualization properties.
|
||||
*
|
||||
* @function _setROIContourMetadata
|
||||
* @param {Object} structureSet - The structure set object to add ROI contour to
|
||||
* @param {Array} StructureSetROISequence - Array of structure set ROI definitions
|
||||
* @param {Array} RTROIObservationsSequence - Array of RT ROI observations
|
||||
* @param {Object} ROIContour - ROI contour object containing contour data
|
||||
* @param {Array} contourPoints - Array of processed contour points
|
||||
*/
|
||||
function _setROIContourMetadata(
|
||||
structureSet,
|
||||
StructureSetROISequence,
|
||||
RTROIObservationsSequence,
|
||||
ROIContour,
|
||||
contourPoints,
|
||||
isSupported
|
||||
contourPoints
|
||||
) {
|
||||
const StructureSetROI = StructureSetROISequence.find(
|
||||
structureSetROI => structureSetROI.ROINumber === ROIContour.ReferencedROINumber
|
||||
@@ -211,9 +276,9 @@ function _setROIContourMetadata(
|
||||
ROIName: StructureSetROI.ROIName,
|
||||
ROIGenerationAlgorithm: StructureSetROI.ROIGenerationAlgorithm,
|
||||
ROIDescription: StructureSetROI.ROIDescription,
|
||||
isSupported,
|
||||
contourPoints,
|
||||
visible: true,
|
||||
colorArray: [],
|
||||
};
|
||||
|
||||
_setROIContourDataColor(ROIContour, ROIContourData);
|
||||
@@ -230,6 +295,14 @@ function _setROIContourMetadata(
|
||||
structureSet.ROIContours.push(ROIContourData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the display color for ROI contour data.
|
||||
* Uses ROIDisplayColor if available, otherwise converts RecommendedDisplayCIELabValue to RGB.
|
||||
*
|
||||
* @function _setROIContourDataColor
|
||||
* @param {Object} ROIContour - ROI contour object containing color information
|
||||
* @param {Object} ROIContourData - ROI contour data object to set color on
|
||||
*/
|
||||
function _setROIContourDataColor(ROIContour, ROIContourData) {
|
||||
let { ROIDisplayColor, RecommendedDisplayCIELabValue } = ROIContour;
|
||||
|
||||
@@ -243,6 +316,15 @@ function _setROIContourDataColor(ROIContour, ROIContourData) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets RT ROI observations metadata for ROI contour data.
|
||||
* Finds matching RTROIObservations by ROINumber and adds observation details to contour data.
|
||||
*
|
||||
* @function _setROIContourRTROIObservations
|
||||
* @param {Object} ROIContourData - ROI contour data object to add observations to
|
||||
* @param {Array} RTROIObservationsSequence - Array of RT ROI observations
|
||||
* @param {number} ROINumber - ROI number to match observations
|
||||
*/
|
||||
function _setROIContourRTROIObservations(ROIContourData, RTROIObservationsSequence, ROINumber) {
|
||||
const RTROIObservations = RTROIObservationsSequence.find(
|
||||
RTROIObservations => RTROIObservations.ReferencedROINumber === ROINumber
|
||||
@@ -262,6 +344,14 @@ function _setROIContourRTROIObservations(ROIContourData, RTROIObservationsSequen
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a single object or array to an array.
|
||||
* Utility function to ensure consistent array handling for DICOM sequences.
|
||||
*
|
||||
* @function _toArray
|
||||
* @param {*} objOrArray - Object or array to convert
|
||||
* @returns {Array} Array containing the input (if already array) or wrapped in array
|
||||
*/
|
||||
function _toArray(objOrArray) {
|
||||
return Array.isArray(objOrArray) ? objOrArray : [objOrArray];
|
||||
}
|
||||
@@ -41,7 +41,6 @@ function OHIFCornerstoneRTViewport(props: withAppTypes) {
|
||||
const [{ viewports, activeViewportId }, viewportGridService] = useViewportGrid();
|
||||
|
||||
// States
|
||||
const selectedSegmentObjectIndex: number = 0;
|
||||
const { setPositionPresentation } = usePositionPresentationStore();
|
||||
const [rtIsLoading, setRtIsLoading] = useState(!rtDisplaySet.isLoaded);
|
||||
const [processingProgress, setProcessingProgress] = useState({
|
||||
@@ -52,6 +51,21 @@ function OHIFCornerstoneRTViewport(props: withAppTypes) {
|
||||
const referencedDisplaySetRef = useRef(null);
|
||||
|
||||
const referencedDisplaySetInstanceUID = rtDisplaySet.referencedDisplaySetInstanceUID;
|
||||
// If the referencedDisplaySetInstanceUID is not found, it means the RTStruct series is being
|
||||
// launched without its corresponding referenced display set (e.g., the RTStruct series is launched using
|
||||
// series launch /mode?StudyInstanceUIDs=&SeriesInstanceUID).
|
||||
// In such cases, we attempt to handle this scenario gracefully by
|
||||
// invoking a custom handler. Ideally, if a user tries to launch a series that isn't viewable,
|
||||
// (eg.: we can prompt them with an explanation and provide a link to the full study).
|
||||
if (!referencedDisplaySetInstanceUID) {
|
||||
const missingReferenceDisplaySetHandler = customizationService.getCustomization(
|
||||
'missingReferenceDisplaySetHandler'
|
||||
);
|
||||
const { handled } = missingReferenceDisplaySetHandler();
|
||||
if (handled) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const referencedDisplaySet = displaySetService.getDisplaySetByUID(
|
||||
referencedDisplaySetInstanceUID
|
||||
);
|
||||
|
||||
@@ -3,6 +3,811 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.12.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.59...v3.12.0-beta.60) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.58...v3.12.0-beta.59) (2025-10-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Use exact versioning for dependencies in package.json files. ([#5494](https://github.com/OHIF/Viewers/issues/5494)) ([c7d2017](https://github.com/OHIF/Viewers/commit/c7d2017f081c5803a70bab6c75bba0c975028125))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.57...v3.12.0-beta.58) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.56...v3.12.0-beta.57) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.55...v3.12.0-beta.56) (2025-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.54...v3.12.0-beta.55) (2025-10-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.53...v3.12.0-beta.54) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.52...v3.12.0-beta.53) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.51...v3.12.0-beta.52) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.50...v3.12.0-beta.51) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.49...v3.12.0-beta.50) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.48...v3.12.0-beta.49) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.47...v3.12.0-beta.48) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.46...v3.12.0-beta.47) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.45...v3.12.0-beta.46) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.44...v3.12.0-beta.45) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.43...v3.12.0-beta.44) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.42...v3.12.0-beta.43) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.41...v3.12.0-beta.42) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.40...v3.12.0-beta.41) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.39...v3.12.0-beta.40) (2025-10-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.38...v3.12.0-beta.39) (2025-10-01)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.37...v3.12.0-beta.38) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.36...v3.12.0-beta.37) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.35...v3.12.0-beta.36) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.34...v3.12.0-beta.35) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.33...v3.12.0-beta.34) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.32...v3.12.0-beta.33) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.31...v3.12.0-beta.32) (2025-09-26)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.30...v3.12.0-beta.31) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.29...v3.12.0-beta.30) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.28...v3.12.0-beta.29) (2025-09-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.27...v3.12.0-beta.28) (2025-09-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.26...v3.12.0-beta.27) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.25...v3.12.0-beta.26) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.24...v3.12.0-beta.25) (2025-09-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.23...v3.12.0-beta.24) (2025-09-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.22...v3.12.0-beta.23) (2025-09-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.21...v3.12.0-beta.22) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.20...v3.12.0-beta.21) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.19...v3.12.0-beta.20) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.18...v3.12.0-beta.19) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.17...v3.12.0-beta.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.16...v3.12.0-beta.17) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.15...v3.12.0-beta.16) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.14...v3.12.0-beta.15) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.13...v3.12.0-beta.14) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.12...v3.12.0-beta.13) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.11...v3.12.0-beta.12) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.10...v3.12.0-beta.11) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.9...v3.12.0-beta.10) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.8...v3.12.0-beta.9) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.7...v3.12.0-beta.8) (2025-08-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add WSI bulk data annotations support (ANN) ([#4972](https://github.com/OHIF/Viewers/issues/4972)) ([2ed6818](https://github.com/OHIF/Viewers/commit/2ed681817142b13971bb17b3058be26bbab6b90b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.6...v3.12.0-beta.7) (2025-08-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.5...v3.12.0-beta.6) (2025-08-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.4...v3.12.0-beta.5) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.3...v3.12.0-beta.4) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.2...v3.12.0-beta.3) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.1...v3.12.0-beta.2) (2025-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.0...v3.12.0-beta.1) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.116...v3.12.0-beta.0) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.116](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.115...v3.11.0-beta.116) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.115](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.114...v3.11.0-beta.115) (2025-07-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add support to scoord3d ([#5016](https://github.com/OHIF/Viewers/issues/5016)) ([735405a](https://github.com/OHIF/Viewers/commit/735405a8554c7ee6283faa83fc42ff8bb9ac34ff))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.114](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.113...v3.11.0-beta.114) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.113](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.112...v3.11.0-beta.113) (2025-07-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* improve segment label ([#5217](https://github.com/OHIF/Viewers/issues/5217)) ([271b84f](https://github.com/OHIF/Viewers/commit/271b84f78fcc3974006c7e1a4dbb2ef322fdb9ec))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.111...v3.11.0-beta.112) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.110...v3.11.0-beta.111) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.109...v3.11.0-beta.110) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.108...v3.11.0-beta.109) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.107...v3.11.0-beta.108) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.106...v3.11.0-beta.107) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.105...v3.11.0-beta.106) (2025-07-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.104...v3.11.0-beta.105) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.103...v3.11.0-beta.104) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.102...v3.11.0-beta.103) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.101...v3.11.0-beta.102) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.100...v3.11.0-beta.101) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.99...v3.11.0-beta.100) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.98...v3.11.0-beta.99) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.97...v3.11.0-beta.98) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.96...v3.11.0-beta.97) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.95...v3.11.0-beta.96) (2025-07-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **segmentation:** Add customization for handling missing referencedDisplaySetInstanceUID for the SEG/RTSTRUCT. ([#4983](https://github.com/OHIF/Viewers/issues/4983)) ([12de7a8](https://github.com/OHIF/Viewers/commit/12de7a85c9330471d81f481de7bc65e60c1c4ab3))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.94...v3.11.0-beta.95) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.93...v3.11.0-beta.94) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.92...v3.11.0-beta.93) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.91...v3.11.0-beta.92) (2025-07-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.90...v3.11.0-beta.91) (2025-07-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.89...v3.11.0-beta.90) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.88...v3.11.0-beta.89) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.87...v3.11.0-beta.88) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.86...v3.11.0-beta.87) (2025-07-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.85...v3.11.0-beta.86) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.84...v3.11.0-beta.85) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.83...v3.11.0-beta.84) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.82...v3.11.0-beta.83) (2025-07-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* enhance preview accept method ([#5199](https://github.com/OHIF/Viewers/issues/5199)) ([540923a](https://github.com/OHIF/Viewers/commit/540923ad8b2f768bd0f766c4f106cf6785a06afc))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.81...v3.11.0-beta.82) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.80...v3.11.0-beta.81) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.79...v3.11.0-beta.80) (2025-07-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **rendering:** Introduce WebGLContextPool for parallel rendering in ContextPoolRenderingEngine ([#5196](https://github.com/OHIF/Viewers/issues/5196)) ([10d9316](https://github.com/OHIF/Viewers/commit/10d93161b4a1bea18ec1b9de9ae3e094e6bb47d0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.78...v3.11.0-beta.79) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-seg",
|
||||
"version": "3.11.0-beta.79",
|
||||
"version": "3.12.0-beta.60",
|
||||
"description": "DICOM SEG read workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -33,22 +33,22 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.11.0-beta.79",
|
||||
"@ohif/extension-cornerstone": "3.11.0-beta.79",
|
||||
"@ohif/extension-default": "3.11.0-beta.79",
|
||||
"@ohif/i18n": "3.11.0-beta.79",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-i18next": "^12.2.2",
|
||||
"react-router": "^6.23.1",
|
||||
"react-router-dom": "^6.23.1"
|
||||
"@ohif/core": "3.12.0-beta.60",
|
||||
"@ohif/extension-cornerstone": "3.12.0-beta.60",
|
||||
"@ohif/extension-default": "3.12.0-beta.60",
|
||||
"@ohif/i18n": "3.12.0-beta.60",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-i18next": "12.3.1",
|
||||
"react-router": "6.30.1",
|
||||
"react-router-dom": "6.30.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^3.29.2",
|
||||
"@cornerstonejs/core": "^3.29.2",
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.5.5",
|
||||
"@cornerstonejs/core": "4.5.5",
|
||||
"@kitware/vtk.js": "32.12.0",
|
||||
"react-color": "^2.19.3"
|
||||
"react-color": "2.19.3"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,14 @@
|
||||
function createSEGToolGroupAndAddTools(ToolGroupService, customizationService, toolGroupId) {
|
||||
function createSEGToolGroupAndAddTools({
|
||||
commandsManager,
|
||||
toolGroupService,
|
||||
customizationService,
|
||||
toolGroupId,
|
||||
}) {
|
||||
const tools = customizationService.getCustomization('cornerstone.overlayViewportTools');
|
||||
|
||||
return ToolGroupService.createToolGroupAndAddTools(toolGroupId, tools);
|
||||
const updatedTools = commandsManager.run('initializeSegmentLabelTool', { tools });
|
||||
|
||||
return toolGroupService.createToolGroupAndAddTools(toolGroupId, updatedTools);
|
||||
}
|
||||
|
||||
export default createSEGToolGroupAndAddTools;
|
||||
@@ -54,6 +54,21 @@ function OHIFCornerstoneSEGViewport(props: withAppTypes) {
|
||||
const { viewports, activeViewportId } = viewportGrid;
|
||||
|
||||
const referencedDisplaySetInstanceUID = segDisplaySet.referencedDisplaySetInstanceUID;
|
||||
// If the referencedDisplaySetInstanceUID is not found, it means the SEG series is being
|
||||
// launched without its corresponding referenced display set (e.g., the SEG series is launched using
|
||||
// series launch /mode?StudyInstanceUIDs=&SeriesInstanceUID).
|
||||
// In such cases, we attempt to handle this scenario gracefully by
|
||||
// invoking a custom handler. Ideally, if a user tries to launch a series that isn't viewable,
|
||||
// (eg.: we can prompt them with an explanation and provide a link to the full study).
|
||||
if (!referencedDisplaySetInstanceUID) {
|
||||
const missingReferenceDisplaySetHandler = customizationService.getCustomization(
|
||||
'missingReferenceDisplaySetHandler'
|
||||
);
|
||||
const { handled } = missingReferenceDisplaySetHandler();
|
||||
if (handled) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const referencedDisplaySet = displaySetService.getDisplaySetByUID(
|
||||
referencedDisplaySetInstanceUID
|
||||
);
|
||||
@@ -199,7 +214,12 @@ function OHIFCornerstoneSEGViewport(props: withAppTypes) {
|
||||
|
||||
// This creates a custom tool group which has the lifetime of this view
|
||||
// only, and does NOT interfere with currently displayed segmentations.
|
||||
toolGroup = createSEGToolGroupAndAddTools(toolGroupService, customizationService, toolGroupId);
|
||||
toolGroup = createSEGToolGroupAndAddTools({
|
||||
commandsManager,
|
||||
toolGroupService,
|
||||
customizationService,
|
||||
toolGroupId,
|
||||
});
|
||||
|
||||
return () => {
|
||||
// remove the segmentation representations if seg displayset changed
|
||||
|
||||
@@ -3,6 +3,811 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.12.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.59...v3.12.0-beta.60) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.58...v3.12.0-beta.59) (2025-10-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Use exact versioning for dependencies in package.json files. ([#5494](https://github.com/OHIF/Viewers/issues/5494)) ([c7d2017](https://github.com/OHIF/Viewers/commit/c7d2017f081c5803a70bab6c75bba0c975028125))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.57...v3.12.0-beta.58) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.56...v3.12.0-beta.57) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.55...v3.12.0-beta.56) (2025-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.54...v3.12.0-beta.55) (2025-10-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.53...v3.12.0-beta.54) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.52...v3.12.0-beta.53) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.51...v3.12.0-beta.52) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.50...v3.12.0-beta.51) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.49...v3.12.0-beta.50) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.48...v3.12.0-beta.49) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.47...v3.12.0-beta.48) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.46...v3.12.0-beta.47) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.45...v3.12.0-beta.46) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.44...v3.12.0-beta.45) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.43...v3.12.0-beta.44) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.42...v3.12.0-beta.43) (2025-10-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **MeasurementService:** add rendering of unmapped measurements ([#5416](https://github.com/OHIF/Viewers/issues/5416)) ([851e74d](https://github.com/OHIF/Viewers/commit/851e74d7b867a806befb5d85fd71ff9a75e9f2d2))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.41...v3.12.0-beta.42) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.40...v3.12.0-beta.41) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.39...v3.12.0-beta.40) (2025-10-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.38...v3.12.0-beta.39) (2025-10-01)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.37...v3.12.0-beta.38) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.36...v3.12.0-beta.37) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.35...v3.12.0-beta.36) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.34...v3.12.0-beta.35) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.33...v3.12.0-beta.34) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.32...v3.12.0-beta.33) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.31...v3.12.0-beta.32) (2025-09-26)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.30...v3.12.0-beta.31) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.29...v3.12.0-beta.30) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.28...v3.12.0-beta.29) (2025-09-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.27...v3.12.0-beta.28) (2025-09-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.26...v3.12.0-beta.27) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.25...v3.12.0-beta.26) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.24...v3.12.0-beta.25) (2025-09-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.23...v3.12.0-beta.24) (2025-09-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.22...v3.12.0-beta.23) (2025-09-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.21...v3.12.0-beta.22) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.20...v3.12.0-beta.21) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.19...v3.12.0-beta.20) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.18...v3.12.0-beta.19) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.17...v3.12.0-beta.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.16...v3.12.0-beta.17) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.15...v3.12.0-beta.16) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.14...v3.12.0-beta.15) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.13...v3.12.0-beta.14) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.12...v3.12.0-beta.13) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.11...v3.12.0-beta.12) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.10...v3.12.0-beta.11) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.9...v3.12.0-beta.10) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.8...v3.12.0-beta.9) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.7...v3.12.0-beta.8) (2025-08-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add WSI bulk data annotations support (ANN) ([#4972](https://github.com/OHIF/Viewers/issues/4972)) ([2ed6818](https://github.com/OHIF/Viewers/commit/2ed681817142b13971bb17b3058be26bbab6b90b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.6...v3.12.0-beta.7) (2025-08-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* load 3dsr ([#5335](https://github.com/OHIF/Viewers/issues/5335)) ([becba78](https://github.com/OHIF/Viewers/commit/becba7861f99ae4e190caddea8b663e60a9883f5))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.5...v3.12.0-beta.6) (2025-08-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.4...v3.12.0-beta.5) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.3...v3.12.0-beta.4) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.2...v3.12.0-beta.3) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.1...v3.12.0-beta.2) (2025-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.0...v3.12.0-beta.1) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.116...v3.12.0-beta.0) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.116](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.115...v3.11.0-beta.116) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.115](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.114...v3.11.0-beta.115) (2025-07-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add support to scoord3d ([#5016](https://github.com/OHIF/Viewers/issues/5016)) ([735405a](https://github.com/OHIF/Viewers/commit/735405a8554c7ee6283faa83fc42ff8bb9ac34ff))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.114](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.113...v3.11.0-beta.114) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.113](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.112...v3.11.0-beta.113) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.111...v3.11.0-beta.112) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.110...v3.11.0-beta.111) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.109...v3.11.0-beta.110) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.108...v3.11.0-beta.109) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.107...v3.11.0-beta.108) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.106...v3.11.0-beta.107) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.105...v3.11.0-beta.106) (2025-07-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.104...v3.11.0-beta.105) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.103...v3.11.0-beta.104) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.102...v3.11.0-beta.103) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.101...v3.11.0-beta.102) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.100...v3.11.0-beta.101) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.99...v3.11.0-beta.100) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.98...v3.11.0-beta.99) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.97...v3.11.0-beta.98) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.96...v3.11.0-beta.97) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.95...v3.11.0-beta.96) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.94...v3.11.0-beta.95) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.93...v3.11.0-beta.94) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.92...v3.11.0-beta.93) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.91...v3.11.0-beta.92) (2025-07-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.90...v3.11.0-beta.91) (2025-07-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.89...v3.11.0-beta.90) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.88...v3.11.0-beta.89) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.87...v3.11.0-beta.88) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.86...v3.11.0-beta.87) (2025-07-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.85...v3.11.0-beta.86) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.84...v3.11.0-beta.85) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.83...v3.11.0-beta.84) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.82...v3.11.0-beta.83) (2025-07-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* enhance preview accept method ([#5199](https://github.com/OHIF/Viewers/issues/5199)) ([540923a](https://github.com/OHIF/Viewers/commit/540923ad8b2f768bd0f766c4f106cf6785a06afc))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.81...v3.11.0-beta.82) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.80...v3.11.0-beta.81) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.79...v3.11.0-beta.80) (2025-07-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **rendering:** Introduce WebGLContextPool for parallel rendering in ContextPoolRenderingEngine ([#5196](https://github.com/OHIF/Viewers/issues/5196)) ([10d9316](https://github.com/OHIF/Viewers/commit/10d93161b4a1bea18ec1b9de9ae3e094e6bb47d0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.78...v3.11.0-beta.79) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-sr",
|
||||
"version": "3.11.0-beta.79",
|
||||
"version": "3.12.0-beta.60",
|
||||
"description": "OHIF extension for an SR Cornerstone Viewport",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -34,21 +34,21 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.11.0-beta.79",
|
||||
"@ohif/extension-cornerstone": "3.11.0-beta.79",
|
||||
"@ohif/extension-measurement-tracking": "3.11.0-beta.79",
|
||||
"@ohif/ui": "3.11.0-beta.79",
|
||||
"dcmjs": "^0.42.0",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^18.3.1"
|
||||
"@ohif/core": "3.12.0-beta.60",
|
||||
"@ohif/extension-cornerstone": "3.12.0-beta.60",
|
||||
"@ohif/extension-measurement-tracking": "3.12.0-beta.60",
|
||||
"@ohif/ui": "3.12.0-beta.60",
|
||||
"dcmjs": "0.43.1",
|
||||
"dicom-parser": "1.8.21",
|
||||
"hammerjs": "2.0.8",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^3.29.2",
|
||||
"@cornerstonejs/core": "^3.29.2",
|
||||
"@cornerstonejs/tools": "^3.29.2",
|
||||
"classnames": "^2.3.2"
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.5.5",
|
||||
"@cornerstonejs/core": "4.5.5",
|
||||
"@cornerstonejs/tools": "4.5.5",
|
||||
"classnames": "2.5.1"
|
||||
}
|
||||
}
|
||||
@@ -32,12 +32,7 @@ const _generateReport = (measurementData, additionalFindingTypes, options: Optio
|
||||
additionalFindingTypes
|
||||
);
|
||||
|
||||
const report = MeasurementReport.generateReport(
|
||||
filteredToolState,
|
||||
metaData,
|
||||
utilities.worldToImageCoords,
|
||||
options
|
||||
);
|
||||
const report = MeasurementReport.generateReport(filteredToolState, metaData, options);
|
||||
|
||||
const { dataset } = report;
|
||||
|
||||
@@ -54,7 +49,7 @@ const _generateReport = (measurementData, additionalFindingTypes, options: Optio
|
||||
|
||||
const commandsModule = (props: withAppTypes) => {
|
||||
const { servicesManager, extensionManager, commandsManager } = props;
|
||||
const { customizationService, viewportGridService, displaySetService } = servicesManager.services;
|
||||
const { customizationService } = servicesManager.services;
|
||||
|
||||
const actions = {
|
||||
changeColorMeasurement: ({ uid }) => {
|
||||
@@ -129,6 +124,9 @@ const commandsModule = (props: withAppTypes) => {
|
||||
console.log('naturalizedReport missing imaging content', naturalizedReport);
|
||||
throw new Error('Invalid report, no content');
|
||||
}
|
||||
if (!naturalizedReport.SOPClassUID) {
|
||||
throw new Error('No sop class uid');
|
||||
}
|
||||
|
||||
const onBeforeDicomStore = customizationService.getCustomization('onBeforeDicomStore');
|
||||
|
||||
|
||||
+5
-8
@@ -63,18 +63,12 @@ function OHIFCornerstoneSRMeasurementViewport(props) {
|
||||
|
||||
const updateViewport = useCallback(
|
||||
newMeasurementSelected => {
|
||||
const { StudyInstanceUID, displaySetInstanceUID, sopClassUids } = srDisplaySet;
|
||||
const { StudyInstanceUID, displaySetInstanceUID } = srDisplaySet;
|
||||
|
||||
if (!StudyInstanceUID || !displaySetInstanceUID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sopClassUids && sopClassUids.length > 1) {
|
||||
// Todo: what happens if there are multiple SOP Classes? Why we are
|
||||
// not throwing an error?
|
||||
console.warn('More than one SOPClassUID in the same series is not yet supported.');
|
||||
}
|
||||
|
||||
_getViewportReferencedDisplaySetData(
|
||||
srDisplaySet,
|
||||
newMeasurementSelected,
|
||||
@@ -92,7 +86,7 @@ function OHIFCornerstoneSRMeasurementViewport(props) {
|
||||
const { presentationIds } = viewportOptions;
|
||||
const measurement = srDisplaySet.measurements[newMeasurementSelected];
|
||||
setPositionPresentation(presentationIds.positionPresentationId, {
|
||||
viewReference: {
|
||||
viewReference: measurement.viewReference || {
|
||||
referencedImageId: measurement.imageId,
|
||||
},
|
||||
});
|
||||
@@ -258,6 +252,9 @@ async function _getViewportReferencedDisplaySetData(
|
||||
}
|
||||
|
||||
const referencedDisplaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||
if (!referencedDisplaySet?.images) {
|
||||
return { referencedDisplaySetMetadata: null, referencedDisplaySet: null };
|
||||
}
|
||||
|
||||
const image0 = referencedDisplaySet.images[0];
|
||||
const referencedDisplaySetMetadata = {
|
||||
|
||||
@@ -15,10 +15,14 @@ import { CodeNameCodeSequenceValues, CodingSchemeDesignators } from './enums';
|
||||
|
||||
const { sopClassDictionary } = utils;
|
||||
const { CORNERSTONE_3D_TOOLS_SOURCE_NAME, CORNERSTONE_3D_TOOLS_SOURCE_VERSION } = CSExtensionEnums;
|
||||
const { ImageSet, MetadataProvider: metadataProvider } = classes;
|
||||
const { CodeScheme: Cornerstone3DCodeScheme } = adaptersSR.Cornerstone3D;
|
||||
const { MetadataProvider: metadataProvider } = classes;
|
||||
const {
|
||||
TEXT_ANNOTATION_POSITION,
|
||||
COMMENT_CODE,
|
||||
CodeScheme: Cornerstone3DCodeScheme,
|
||||
} = adaptersSR.Cornerstone3D;
|
||||
|
||||
type InstanceMetadata = Types.InstanceMetadata;
|
||||
type InstanceMetadata = OhifTypes.InstanceMetadata;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
@@ -31,6 +35,7 @@ const sopClassUids = [
|
||||
sopClassDictionary.BasicTextSR,
|
||||
sopClassDictionary.EnhancedSR,
|
||||
sopClassDictionary.ComprehensiveSR,
|
||||
sopClassDictionary.Comprehensive3DSR,
|
||||
];
|
||||
|
||||
const validateSameStudyUID = (uid: string, instances): void => {
|
||||
@@ -49,7 +54,7 @@ const validateSameStudyUID = (uid: string, instances): void => {
|
||||
* @param instances is a list of instances from THIS series that are not
|
||||
* in this DICOM SR Display Set already.
|
||||
*/
|
||||
function addInstances(instances: InstanceMetadata[], displaySetService: DisplaySetService) {
|
||||
function addInstances(instances: InstanceMetadata[], _displaySetService: DisplaySetService) {
|
||||
this.instances.push(...instances);
|
||||
utils.sortStudyInstances(this.instances);
|
||||
// The last instance is the newest one, so is the one most interesting.
|
||||
@@ -64,9 +69,10 @@ function addInstances(instances: InstanceMetadata[], displaySetService: DisplayS
|
||||
* DICOM SR SOP Class Handler
|
||||
* For all referenced images in the TID 1500/300 sections, add an image to the
|
||||
* display.
|
||||
* @param instances is a set of instances all from the same series
|
||||
* @param servicesManager is the services that can be used for creating
|
||||
* @returns The list of display sets created for the given instances object
|
||||
* @param {InstanceMetadata[]} instances - A set of instances all from the same series
|
||||
* @param {AppTypes.ServicesManager} servicesManager - The services that can be used for creating
|
||||
* @param {AppTypes.ExtensionManager} extensionManager - The extension manager
|
||||
* @returns {Types.DisplaySet[]} The list of display sets created for the given instances object
|
||||
*/
|
||||
function _getDisplaySetsFromSeries(
|
||||
instances,
|
||||
@@ -138,7 +144,7 @@ function _getDisplaySetsFromSeries(
|
||||
* @param extensionManager - The extension manager containing data sources.
|
||||
*/
|
||||
async function _load(
|
||||
srDisplaySet: Types.DisplaySet,
|
||||
srDisplaySet: OhifTypes.DisplaySet,
|
||||
servicesManager: AppTypes.ServicesManager,
|
||||
extensionManager: AppTypes.ExtensionManager
|
||||
) {
|
||||
@@ -216,17 +222,15 @@ async function _load(
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if measurements can be added to a display set.
|
||||
*
|
||||
* @param srDisplaySet - The source display set containing measurements.
|
||||
* @param newDisplaySet - The new display set to check if measurements can be added.
|
||||
* @param dataSource - The data source used to retrieve image IDs.
|
||||
* @param servicesManager - The services manager.
|
||||
*/
|
||||
function _measurementBelongsToDisplaySet({ measurement, displaySet }) {
|
||||
return (
|
||||
measurement.coords[0].ReferencedFrameOfReferenceSequence === displaySet.FrameOfReferenceUID
|
||||
);
|
||||
}
|
||||
|
||||
function _checkIfCanAddMeasurementsToDisplaySet(
|
||||
srDisplaySet,
|
||||
newDisplaySet,
|
||||
srDisplaySet: OhifTypes.DisplaySet,
|
||||
newDisplaySet: OhifTypes.DisplaySet,
|
||||
dataSource,
|
||||
servicesManager: AppTypes.ServicesManager
|
||||
) {
|
||||
@@ -236,18 +240,10 @@ function _checkIfCanAddMeasurementsToDisplaySet(
|
||||
measurement => measurement.loaded === false
|
||||
);
|
||||
|
||||
if (
|
||||
unloadedMeasurements.length === 0 ||
|
||||
!(newDisplaySet instanceof ImageSet) ||
|
||||
newDisplaySet.unsupported
|
||||
) {
|
||||
if (!unloadedMeasurements.length || newDisplaySet.unsupported) {
|
||||
return;
|
||||
}
|
||||
|
||||
// const { sopClassUids } = newDisplaySet;
|
||||
// Create a Set for faster lookups
|
||||
// const sopClassUidSet = new Set(sopClassUids);
|
||||
|
||||
// Create a Map to efficiently look up ImageIds by SOPInstanceUID and frame number
|
||||
const imageIdMap = new Map<string, string>();
|
||||
const imageIds = dataSource.getImageIdsForDisplaySet(newDisplaySet);
|
||||
@@ -266,6 +262,7 @@ function _checkIfCanAddMeasurementsToDisplaySet(
|
||||
|
||||
for (let j = unloadedMeasurements.length - 1; j >= 0; j--) {
|
||||
let measurement = unloadedMeasurements[j];
|
||||
const is3DMeasurement = measurement.coords?.[0]?.ValueType === 'SCOORD3D';
|
||||
|
||||
const onBeforeSRAddMeasurement = customizationService.getCustomization(
|
||||
'onBeforeSRAddMeasurement'
|
||||
@@ -280,9 +277,15 @@ function _checkIfCanAddMeasurementsToDisplaySet(
|
||||
}
|
||||
|
||||
// if it is 3d SR we can just add the SR annotation
|
||||
if (is3DSR) {
|
||||
addSRAnnotation(measurement, null, null);
|
||||
if (
|
||||
is3DSR &&
|
||||
is3DMeasurement &&
|
||||
_measurementBelongsToDisplaySet({ measurement, displaySet: newDisplaySet })
|
||||
) {
|
||||
addSRAnnotation({ measurement, displaySet: newDisplaySet });
|
||||
measurement.loaded = true;
|
||||
measurement.displaySetInstanceUID = newDisplaySet.displaySetInstanceUID;
|
||||
unloadedMeasurements.splice(j, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -300,15 +303,12 @@ function _checkIfCanAddMeasurementsToDisplaySet(
|
||||
imageId &&
|
||||
_measurementReferencesSOPInstanceUID(measurement, ReferencedSOPInstanceUID, frame)
|
||||
) {
|
||||
addSRAnnotation(measurement, imageId, frame);
|
||||
|
||||
// Update measurement properties
|
||||
addSRAnnotation({ measurement, imageId, frameNumber: frame, displaySet: newDisplaySet });
|
||||
measurement.loaded = true;
|
||||
measurement.imageId = imageId;
|
||||
measurement.displaySetInstanceUID = newDisplaySet.displaySetInstanceUID;
|
||||
measurement.ReferencedSOPInstanceUID = ReferencedSOPInstanceUID;
|
||||
measurement.frameNumber = frame;
|
||||
|
||||
unloadedMeasurements.splice(j, 1);
|
||||
}
|
||||
}
|
||||
@@ -316,10 +316,10 @@ function _checkIfCanAddMeasurementsToDisplaySet(
|
||||
|
||||
/**
|
||||
* Checks if a measurement references a specific SOP Instance UID.
|
||||
* @param measurement - The measurement object.
|
||||
* @param SOPInstanceUID - The SOP Instance UID to check against.
|
||||
* @param frameNumber - The frame number to check against (optional).
|
||||
* @returns True if the measurement references the specified SOP Instance UID, false otherwise.
|
||||
* @param {any} measurement - The measurement object.
|
||||
* @param {string} sopInstanceUID - The SOP Instance UID to check against.
|
||||
* @param {number} frameNumber - The frame number to check against (optional).
|
||||
* @returns {boolean} True if the measurement references the specified SOP Instance UID, false otherwise.
|
||||
*/
|
||||
function _measurementReferencesSOPInstanceUID(measurement, SOPInstanceUID, frameNumber) {
|
||||
const { coords } = measurement;
|
||||
@@ -351,10 +351,8 @@ function _measurementReferencesSOPInstanceUID(measurement, SOPInstanceUID, frame
|
||||
/**
|
||||
* Retrieves the SOP class handler module.
|
||||
*
|
||||
* @param {Object} options - The options for retrieving the SOP class handler module.
|
||||
* @param {Object} options.servicesManager - The services manager.
|
||||
* @param {Object} options.extensionManager - The extension manager.
|
||||
* @returns {Array} An array containing the SOP class handler module.
|
||||
* @param {OhifTypes.Extensions.ExtensionParams} params - The extension parameters.
|
||||
* @returns {Array} An array containing the SOP class handler modules.
|
||||
*/
|
||||
function getSopClassHandlerModule(params: OhifTypes.Extensions.ExtensionParams) {
|
||||
const { servicesManager, extensionManager } = params;
|
||||
@@ -378,8 +376,8 @@ function getSopClassHandlerModule(params: OhifTypes.Extensions.ExtensionParams)
|
||||
/**
|
||||
* Retrieves the measurements from the ImagingMeasurementReportContentSequence.
|
||||
*
|
||||
* @param {Array} ImagingMeasurementReportContentSequence - The ImagingMeasurementReportContentSequence array.
|
||||
* @returns {Array} - The array of measurements.
|
||||
* @param {any[]} imagingMeasurementReportContentSequence - The ImagingMeasurementReportContentSequence array.
|
||||
* @returns {any[]} The array of measurements.
|
||||
*/
|
||||
function _getMeasurements(ImagingMeasurementReportContentSequence) {
|
||||
const ImagingMeasurements = ImagingMeasurementReportContentSequence.find(
|
||||
@@ -417,8 +415,8 @@ function _getMeasurements(ImagingMeasurementReportContentSequence) {
|
||||
/**
|
||||
* Retrieves merged content sequences by tracking unique identifiers.
|
||||
*
|
||||
* @param {Array} MeasurementGroups - The measurement groups.
|
||||
* @returns {Object} - The merged content sequences by tracking unique identifiers.
|
||||
* @param {any[]} measurementGroups - The measurement groups.
|
||||
* @returns {Object} The merged content sequences by tracking unique identifiers.
|
||||
*/
|
||||
function _getMergedContentSequencesByTrackingUniqueIdentifiers(MeasurementGroups) {
|
||||
const mergedContentSequencesByTrackingUniqueIdentifiers = {};
|
||||
@@ -465,15 +463,11 @@ function _getMergedContentSequencesByTrackingUniqueIdentifiers(MeasurementGroups
|
||||
* it calls the _processTID1410Measurement function.
|
||||
* Otherwise, it calls the _processNonGeometricallyDefinedMeasurement function.
|
||||
*
|
||||
* @param {Array<Object>} mergedContentSequence - The merged content sequence to process.
|
||||
* @returns {any} - The processed measurement result.
|
||||
* @param {any[]} mergedContentSequence - The merged content sequence to process.
|
||||
* @returns {any} The processed measurement result.
|
||||
*/
|
||||
function _processMeasurement(mergedContentSequence) {
|
||||
if (
|
||||
mergedContentSequence.some(
|
||||
group => group.ValueType === 'SCOORD' || group.ValueType === 'SCOORD3D'
|
||||
)
|
||||
) {
|
||||
if (mergedContentSequence.some(group => isScoordOr3d(group) && !isTextPosition(group))) {
|
||||
return _processTID1410Measurement(mergedContentSequence);
|
||||
}
|
||||
|
||||
@@ -485,8 +479,8 @@ function _processMeasurement(mergedContentSequence) {
|
||||
* TID 1410 style measurements have a SCOORD or SCOORD3D at the top level,
|
||||
* and non-geometric representations where each NUM has "INFERRED FROM" SCOORD/SCOORD3D.
|
||||
*
|
||||
* @param mergedContentSequence - The merged content sequence containing the measurements.
|
||||
* @returns The measurement object containing the loaded status, labels, coordinates, tracking unique identifier, and tracking identifier.
|
||||
* @param {any[]} mergedContentSequence - The merged content sequence containing the measurements.
|
||||
* @returns {any} The measurement object containing the loaded status, labels, coordinates, tracking unique identifier, and tracking identifier.
|
||||
*/
|
||||
function _processTID1410Measurement(mergedContentSequence) {
|
||||
// Need to deal with TID 1410 style measurements, which will have a SCOORD or SCOORD3D at the top level,
|
||||
@@ -511,12 +505,25 @@ function _processTID1410Measurement(mergedContentSequence) {
|
||||
|
||||
const NUMContentItems = mergedContentSequence.filter(group => group.ValueType === 'NUM');
|
||||
|
||||
const { ConceptNameCodeSequence: conceptNameItem } = graphicItem;
|
||||
const { CodeValue: graphicValue, CodingSchemeDesignator: graphicDesignator } = conceptNameItem;
|
||||
const graphicCode = `${graphicDesignator}:${graphicValue}`;
|
||||
|
||||
const pointDataItem = _getCoordsFromSCOORDOrSCOORD3D(graphicItem);
|
||||
const is3DMeasurement = pointDataItem.ValueType === 'SCOORD3D';
|
||||
const pointLength = is3DMeasurement ? 3 : 2;
|
||||
const pointsLength = pointDataItem.GraphicData.length / pointLength;
|
||||
|
||||
const measurement = {
|
||||
loaded: false,
|
||||
labels: [],
|
||||
coords: [_getCoordsFromSCOORDOrSCOORD3D(graphicItem)],
|
||||
coords: [pointDataItem],
|
||||
TrackingUniqueIdentifier: UIDREFContentItem.UID,
|
||||
TrackingIdentifier: TrackingIdentifierContentItem.TextValue,
|
||||
graphicCode,
|
||||
is3DMeasurement,
|
||||
pointsLength,
|
||||
graphicType: pointDataItem.GraphicType,
|
||||
};
|
||||
|
||||
NUMContentItems.forEach(item => {
|
||||
@@ -546,8 +553,8 @@ function _processTID1410Measurement(mergedContentSequence) {
|
||||
/**
|
||||
* Processes the non-geometrically defined measurement from the merged content sequence.
|
||||
*
|
||||
* @param mergedContentSequence The merged content sequence containing the measurement data.
|
||||
* @returns The processed measurement object.
|
||||
* @param {any[]} mergedContentSequence The merged content sequence containing the measurement data.
|
||||
* @returns {any} The processed measurement object.
|
||||
*/
|
||||
function _processNonGeometricallyDefinedMeasurement(mergedContentSequence) {
|
||||
const NUMContentItems = mergedContentSequence.filter(group => group.ValueType === 'NUM');
|
||||
@@ -567,6 +574,12 @@ function _processNonGeometricallyDefinedMeasurement(mergedContentSequence) {
|
||||
item.ConceptNameCodeSequence.CodeValue === CodeNameCodeSequenceValues.FindingSite
|
||||
);
|
||||
|
||||
const commentSites = mergedContentSequence.filter(
|
||||
item =>
|
||||
item.ConceptNameCodeSequence.CodingSchemeDesignator === COMMENT_CODE.schemeDesignator &&
|
||||
item.ConceptNameCodeSequence.CodeValue === COMMENT_CODE.value
|
||||
);
|
||||
|
||||
const measurement = {
|
||||
loaded: false,
|
||||
labels: [],
|
||||
@@ -575,6 +588,14 @@ function _processNonGeometricallyDefinedMeasurement(mergedContentSequence) {
|
||||
TrackingIdentifier: TrackingIdentifierContentItem.TextValue,
|
||||
};
|
||||
|
||||
if (commentSites) {
|
||||
for (const group of commentSites) {
|
||||
if (group.TextValue) {
|
||||
measurement.labels.push({ label: group.TextValue, value: '' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
finding &&
|
||||
CodingSchemeDesignators.CornerstoneCodeSchemes.includes(
|
||||
@@ -633,8 +654,8 @@ function _processNonGeometricallyDefinedMeasurement(mergedContentSequence) {
|
||||
|
||||
/**
|
||||
* Extracts coordinates from a graphic item of type SCOORD or SCOORD3D.
|
||||
* @param {object} graphicItem - The graphic item containing the coordinates.
|
||||
* @returns {object} - The extracted coordinates.
|
||||
* @param {any} graphicItem - The graphic item containing the coordinates.
|
||||
* @returns {any} The extracted coordinates.
|
||||
*/
|
||||
const _getCoordsFromSCOORDOrSCOORD3D = graphicItem => {
|
||||
const { ValueType, GraphicType, GraphicData } = graphicItem;
|
||||
@@ -648,9 +669,9 @@ const _getCoordsFromSCOORDOrSCOORD3D = graphicItem => {
|
||||
|
||||
/**
|
||||
* Retrieves the label and value from the provided ConceptNameCodeSequence and MeasuredValueSequence.
|
||||
* @param {Object} ConceptNameCodeSequence - The ConceptNameCodeSequence object.
|
||||
* @param {Object} MeasuredValueSequence - The MeasuredValueSequence object.
|
||||
* @returns {Object} - An object containing the label and value.
|
||||
* @param {any} conceptNameCodeSequence - The ConceptNameCodeSequence object.
|
||||
* @param {any} measuredValueSequence - The MeasuredValueSequence object.
|
||||
* @returns {Object} An object containing the label and value.
|
||||
* The label represents the CodeMeaning from the ConceptNameCodeSequence.
|
||||
* The value represents the formatted NumericValue and CodeValue from the MeasuredValueSequence.
|
||||
* Example: { label: 'Long Axis', value: '31.00 mm' }
|
||||
@@ -669,8 +690,8 @@ function _getLabelFromMeasuredValueSequence(ConceptNameCodeSequence, MeasuredVal
|
||||
/**
|
||||
* Retrieves a list of referenced images from the Imaging Measurement Report Content Sequence.
|
||||
*
|
||||
* @param {Array} ImagingMeasurementReportContentSequence - The Imaging Measurement Report Content Sequence.
|
||||
* @returns {Array} - The list of referenced images.
|
||||
* @param {any[]} imagingMeasurementReportContentSequence - The Imaging Measurement Report Content Sequence.
|
||||
* @returns {any[]} The list of referenced images.
|
||||
*/
|
||||
function _getReferencedImagesList(ImagingMeasurementReportContentSequence) {
|
||||
const ImageLibrary = ImagingMeasurementReportContentSequence.find(
|
||||
@@ -717,7 +738,7 @@ function _getReferencedImagesList(ImagingMeasurementReportContentSequence) {
|
||||
* Otherwise, the sequence is wrapped in an array and returned.
|
||||
*
|
||||
* @param {any} sequence - The DICOM sequence to convert.
|
||||
* @returns {any[]} - The converted array.
|
||||
* @returns {any[]} The converted array.
|
||||
*/
|
||||
function _getSequenceAsArray(sequence) {
|
||||
if (!sequence) {
|
||||
@@ -726,4 +747,17 @@ function _getSequenceAsArray(sequence) {
|
||||
return Array.isArray(sequence) ? sequence : [sequence];
|
||||
}
|
||||
|
||||
function isScoordOr3d(group) {
|
||||
return group.ValueType === 'SCOORD' || group.ValueType === 'SCOORD3D';
|
||||
}
|
||||
|
||||
function isTextPosition(group) {
|
||||
const concept = group.ConceptNameCodeSequence[0];
|
||||
return (
|
||||
concept &&
|
||||
concept.CodeValue === TEXT_ANNOTATION_POSITION.value &&
|
||||
concept.CodingSchemeDesignator === TEXT_ANNOTATION_POSITION.schemeDesignator
|
||||
);
|
||||
}
|
||||
|
||||
export default getSopClassHandlerModule;
|
||||
@@ -9,11 +9,10 @@ import {
|
||||
LengthTool,
|
||||
PlanarFreehandROITool,
|
||||
RectangleROITool,
|
||||
utilities as csToolsUtils,
|
||||
} from '@cornerstonejs/tools';
|
||||
import { Types, MeasurementService } from '@ohif/core';
|
||||
import { StackViewport, utilities as csUtils } from '@cornerstonejs/core';
|
||||
import { Types } from '@ohif/core';
|
||||
import { Enums as CSExtensionEnums } from '@ohif/extension-cornerstone';
|
||||
|
||||
import DICOMSRDisplayTool from './tools/DICOMSRDisplayTool';
|
||||
import SCOORD3DPointTool from './tools/SCOORD3DPointTool';
|
||||
import SRSCOOR3DProbeMapper from './utils/SRSCOOR3DProbeMapper';
|
||||
@@ -29,7 +28,7 @@ export default function init({
|
||||
configuration = {},
|
||||
servicesManager,
|
||||
}: Types.Extensions.ExtensionParams): void {
|
||||
const { measurementService, cornerstoneViewportService } = servicesManager.services;
|
||||
const { measurementService } = servicesManager.services;
|
||||
|
||||
addToolInstance(toolNames.DICOMSRDisplay, DICOMSRDisplayTool);
|
||||
addToolInstance(toolNames.SRLength, LengthTool);
|
||||
@@ -57,7 +56,7 @@ export default function init({
|
||||
'SRSCOORD3DPoint',
|
||||
POINT,
|
||||
SRSCOOR3DProbeMapper.toAnnotation,
|
||||
SRSCOOR3DProbeMapper.toMeasurement
|
||||
SRSCOOR3DProbeMapper.toMeasurement.bind(null, { servicesManager })
|
||||
);
|
||||
|
||||
// Modify annotation tools to use dashed lines on SR
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Types, metaData, utilities as csUtils } from '@cornerstonejs/core';
|
||||
import { type Types } from '@cornerstonejs/core';
|
||||
import {
|
||||
annotation,
|
||||
drawing,
|
||||
|
||||
@@ -7,13 +7,8 @@ const SRSCOOR3DProbe = {
|
||||
* @param {Object} cornerstone Cornerstone event data
|
||||
* @return {Measurement} Measurement instance
|
||||
*/
|
||||
toMeasurement: (
|
||||
csToolsEventDetail,
|
||||
displaySetService,
|
||||
CornerstoneViewportService,
|
||||
getValueTypeFromToolType,
|
||||
customizationService
|
||||
) => {
|
||||
toMeasurement: ({ servicesManager, getValueTypeFromToolType }, csToolsEventDetail) => {
|
||||
const { displaySetService } = servicesManager.services;
|
||||
const { annotation } = csToolsEventDetail;
|
||||
const { metadata, data, annotationUID } = annotation;
|
||||
|
||||
@@ -22,14 +17,25 @@ const SRSCOOR3DProbe = {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { toolName } = metadata;
|
||||
const { toolName, FrameOfReferenceUID } = metadata;
|
||||
const { points } = data.handles;
|
||||
|
||||
const displaySets = displaySetService
|
||||
.getActiveDisplaySets()
|
||||
.filter(ds => ds.FrameOfReferenceUID === FrameOfReferenceUID);
|
||||
const displaySet = displaySets.filter(ds => ds.isReconstructable)[0] || displaySets[0];
|
||||
|
||||
const { StudyInstanceUID: referenceStudyUID, SeriesInstanceUID: referenceSeriesUID } =
|
||||
displaySets[0] || {};
|
||||
|
||||
const displayText = getDisplayText(annotation);
|
||||
return {
|
||||
uid: annotationUID,
|
||||
points,
|
||||
metadata,
|
||||
referenceStudyUID,
|
||||
referenceSeriesUID,
|
||||
displaySetInstanceUID: displaySet?.displaySetInstanceUID,
|
||||
toolName: metadata.toolName,
|
||||
label: data.label,
|
||||
displayText: displayText,
|
||||
@@ -56,7 +62,10 @@ function getDisplayText(annotation) {
|
||||
}
|
||||
}
|
||||
|
||||
return displayText;
|
||||
return {
|
||||
primary: displayText,
|
||||
secondary: [],
|
||||
};
|
||||
}
|
||||
|
||||
export default SRSCOOR3DProbe;
|
||||
@@ -1,11 +1,59 @@
|
||||
import { Types, annotation } from '@cornerstonejs/tools';
|
||||
import { metaData } from '@cornerstonejs/core';
|
||||
import { adaptersSR } from '@cornerstonejs/adapters';
|
||||
|
||||
import getRenderableData from './getRenderableData';
|
||||
import toolNames from '../tools/toolNames';
|
||||
|
||||
export default function addSRAnnotation(measurement, imageId, frameNumber) {
|
||||
const { MeasurementReport } = adaptersSR.Cornerstone3D;
|
||||
|
||||
/**
|
||||
* Adds a DICOM SR (Structured Report) annotation to the annotation manager.
|
||||
* This function processes measurement data from DICOM SR and converts it into
|
||||
* a format suitable for display in the Cornerstone3D viewer.
|
||||
*
|
||||
* @param {Object} params - The parameters object
|
||||
* @param {Object} params.measurement - The DICOM SR measurement data containing coordinates, labels, and metadata
|
||||
* @param {Array} params.measurement.coords - Array of coordinate objects with GraphicType, ValueType, and other properties
|
||||
* @param {string} params.measurement.TrackingUniqueIdentifier - Unique identifier for the measurement
|
||||
* @param {string} params.measurement.TrackingIdentifier - Tracking identifier for adapter lookup
|
||||
* @param {Array} [params.measurement.labels] - Optional array of label objects
|
||||
* @param {string} [params.measurement.displayText] - Optional display text for the annotation
|
||||
* @param {Object} [params.measurement.textBox] - Optional text box configuration
|
||||
* @param {string|null} [params.imageId] - Optional image ID for the referenced image (defaults to null)
|
||||
* @param {number|null} [params.frameNumber] - Optional frame number for multi-frame images (defaults to null)
|
||||
* @param {Object} params.displaySet - The display set containing the image
|
||||
* @param {string} params.displaySet.displaySetInstanceUID - Unique identifier for the display set
|
||||
* @returns {void}
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* addSRAnnotation({
|
||||
* measurement: {
|
||||
* TrackingUniqueIdentifier: '1.2.3.4.5',
|
||||
* TrackingIdentifier: 'POINT',
|
||||
* coords: [{
|
||||
* GraphicType: 'POINT',
|
||||
* ValueType: 'SCOORD',
|
||||
* // ... other coordinate properties
|
||||
* }],
|
||||
* labels: [{ value: 'Measurement Point' }],
|
||||
* displayText: 'Point measurement'
|
||||
* },
|
||||
* imageId: 'wadouri:file://path/to/image.dcm', // Optional
|
||||
* frameNumber: 0, // Optional
|
||||
* displaySet: { displaySetInstanceUID: '1.2.3.4' }
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export default function addSRAnnotation({ measurement, imageId = null, frameNumber = null, displaySet }) {
|
||||
/** @type {string} The tool name to use for the annotation, defaults to DICOMSRDisplay */
|
||||
let toolName = toolNames.DICOMSRDisplay;
|
||||
|
||||
/**
|
||||
* @type {Object} Renderable data organized by graphic type
|
||||
* Groups coordinate data by GraphicType for efficient rendering
|
||||
*/
|
||||
const renderableData = measurement.coords.reduce((acc, coordProps) => {
|
||||
acc[coordProps.GraphicType] = acc[coordProps.GraphicType] || [];
|
||||
acc[coordProps.GraphicType].push(getRenderableData({ ...coordProps, imageId }));
|
||||
@@ -18,6 +66,7 @@ export default function addSRAnnotation(measurement, imageId, frameNumber) {
|
||||
|
||||
/** TODO: Read the tool name from the DICOM SR identification type in the future. */
|
||||
let frameOfReferenceUID = null;
|
||||
let planeRestriction = null;
|
||||
|
||||
if (imageId) {
|
||||
const imagePlaneModule = metaData.get('imagePlaneModule', imageId);
|
||||
@@ -25,23 +74,47 @@ export default function addSRAnnotation(measurement, imageId, frameNumber) {
|
||||
}
|
||||
|
||||
if (valueType === 'SCOORD3D') {
|
||||
toolName = toolNames.SRSCOORD3DPoint;
|
||||
const adapter = MeasurementReport.getAdapterForTrackingIdentifier(
|
||||
measurement.TrackingIdentifier
|
||||
);
|
||||
if (!adapter) {
|
||||
toolName = toolNames.SRSCOORD3DPoint;
|
||||
}
|
||||
|
||||
// get the ReferencedFrameOfReferenceUID from the measurement
|
||||
frameOfReferenceUID = measurement.coords[0].ReferencedFrameOfReferenceSequence;
|
||||
|
||||
planeRestriction = {
|
||||
FrameOfReferenceUID: frameOfReferenceUID,
|
||||
point: graphicTypePoints[0][0],
|
||||
};
|
||||
}
|
||||
|
||||
// Store the view reference for use in initial navigation
|
||||
measurement.viewReference = {
|
||||
planeRestriction,
|
||||
FrameOfReferenceUID: frameOfReferenceUID,
|
||||
referencedImageId: imageId,
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Types.Annotation} The annotation object to be added to the annotation manager
|
||||
* Contains all necessary metadata and data for rendering the DICOM SR measurement
|
||||
*/
|
||||
const SRAnnotation: Types.Annotation = {
|
||||
annotationUID: TrackingUniqueIdentifier,
|
||||
highlighted: false,
|
||||
isLocked: false,
|
||||
isPreview: toolName === toolNames.DICOMSRDisplay,
|
||||
invalidated: false,
|
||||
metadata: {
|
||||
toolName,
|
||||
planeRestriction,
|
||||
valueType,
|
||||
graphicType,
|
||||
FrameOfReferenceUID: frameOfReferenceUID,
|
||||
referencedImageId: imageId,
|
||||
displaySetInstanceUID: displaySet.displaySetInstanceUID,
|
||||
},
|
||||
data: {
|
||||
label: measurement.labels?.[0]?.value || undefined,
|
||||
@@ -59,8 +132,11 @@ export default function addSRAnnotation(measurement, imageId, frameNumber) {
|
||||
};
|
||||
|
||||
/**
|
||||
* const annotationManager = annotation.annotationState.getAnnotationManager();
|
||||
* was not triggering annotation_added events.
|
||||
* Add the annotation to the annotation state manager.
|
||||
* Note: Using annotation.state.addAnnotation() instead of annotationManager.addAnnotation()
|
||||
* because the latter was not triggering annotation_added events properly.
|
||||
*
|
||||
* @param {Types.Annotation} SRAnnotation - The annotation to add
|
||||
*/
|
||||
annotation.state.addAnnotation(SRAnnotation);
|
||||
}
|
||||
@@ -1,17 +1,11 @@
|
||||
import OHIF from '@ohif/core';
|
||||
import { annotation } from '@cornerstonejs/tools';
|
||||
const { log } = OHIF;
|
||||
import { NO_IMAGE_ID } from '@cornerstonejs/adapters';
|
||||
|
||||
function getFilteredCornerstoneToolState(measurementData, additionalFindingTypes) {
|
||||
const filteredToolState = {};
|
||||
|
||||
function addToFilteredToolState(annotation, toolType) {
|
||||
if (!annotation.metadata?.referencedImageId) {
|
||||
log.warn(`[DICOMSR] No referencedImageId found for ${toolType} ${annotation.id}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const imageId = annotation.metadata.referencedImageId;
|
||||
const imageId = annotation.metadata?.referencedImageId ?? NO_IMAGE_ID;
|
||||
|
||||
if (!filteredToolState[imageId]) {
|
||||
filteredToolState[imageId] = {};
|
||||
|
||||
@@ -11,7 +11,11 @@ const { CodeScheme: Cornerstone3DCodeScheme } = adaptersSR.Cornerstone3D;
|
||||
* @returns {string} The extracted label.
|
||||
*/
|
||||
export default function getLabelFromDCMJSImportedToolData(toolData) {
|
||||
const { findingSites = [], finding } = toolData;
|
||||
const { findingSites = [], finding, annotation } = toolData;
|
||||
|
||||
if (annotation.data.label) {
|
||||
return annotation.data.label;
|
||||
}
|
||||
|
||||
let freeTextLabel = findingSites.find(
|
||||
fs => fs.CodeValue === Cornerstone3DCodeScheme.codeValues.CORNERSTONEFREETEXT
|
||||
|
||||
@@ -36,6 +36,14 @@ function getRenderableData({ GraphicType, GraphicData, ValueType, imageId }) {
|
||||
ValueType,
|
||||
imageId,
|
||||
});
|
||||
|
||||
if (!imageId) {
|
||||
// without the image id it's not possible to perform the calculations below
|
||||
// these calculations also do not seem to be needed, since everything works
|
||||
// just fine when we skip them. At least for SCOORD3D annotations.
|
||||
return pointsWorld;
|
||||
}
|
||||
|
||||
// We do not have an explicit draw circle svg helper in Cornerstone3D at
|
||||
// this time, but we can use the ellipse svg helper to draw a circle, so
|
||||
// here we reshape the data for that purpose.
|
||||
@@ -90,6 +98,13 @@ function getRenderableData({ GraphicType, GraphicData, ValueType, imageId }) {
|
||||
imageId,
|
||||
});
|
||||
|
||||
if (!imageId) {
|
||||
// without the image id it's not possible to perform the calculations below
|
||||
// these calculations also do not seem to be needed, since everything works
|
||||
// just fine when we skip them. At least for SCOORD3D annotations.
|
||||
return pointsWorld;
|
||||
}
|
||||
|
||||
const majorAxisStart = vec3.fromValues(...pointsWorld[0]);
|
||||
const majorAxisEnd = vec3.fromValues(...pointsWorld[1]);
|
||||
const minorAxisStart = vec3.fromValues(...pointsWorld[2]);
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { utilities, metaData } from '@cornerstonejs/core';
|
||||
import { utilities, metaData, type Types } from '@cornerstonejs/core';
|
||||
import OHIF, { DicomMetadataStore } from '@ohif/core';
|
||||
import { vec3 } from 'gl-matrix';
|
||||
|
||||
import getLabelFromDCMJSImportedToolData from './getLabelFromDCMJSImportedToolData';
|
||||
import { adaptersSR } from '@cornerstonejs/adapters';
|
||||
import { annotation as CsAnnotation } from '@cornerstonejs/tools';
|
||||
import { annotation as CsAnnotation, type Types as ToolTypes } from '@cornerstonejs/tools';
|
||||
import { Enums as CSExtensionEnums } from '@ohif/extension-cornerstone';
|
||||
|
||||
const { locking } = CsAnnotation;
|
||||
const { guid } = OHIF.utils;
|
||||
const { MeasurementReport, CORNERSTONE_3D_TAG } = adaptersSR.Cornerstone3D;
|
||||
const { MeasurementReport } = adaptersSR.Cornerstone3D;
|
||||
const { CORNERSTONE_3D_TOOLS_SOURCE_NAME, CORNERSTONE_3D_TOOLS_SOURCE_VERSION } = CSExtensionEnums;
|
||||
const supportedLegacyCornerstoneTags = ['cornerstoneTools@^4.0.0'];
|
||||
|
||||
const convertCode = (codingValues, code) => {
|
||||
if (!code || code.CodingSchemeDesignator === 'CORNERSTONEJS') {
|
||||
@@ -37,8 +38,10 @@ const convertSites = (codingValues, sites) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Hydrates a structured report, for default viewports.
|
||||
*
|
||||
* Hydrates a structured report
|
||||
* Handles 2d and 3d hydration from SCOORD and SCOORD3D points
|
||||
* For 3D hydration, chooses a volume display set to display with
|
||||
* FOr 2D hydration, chooses the (first) display set containing the referenced image.
|
||||
*/
|
||||
export default function hydrateStructuredReport(
|
||||
{ servicesManager, extensionManager, commandsManager }: withAppTypes,
|
||||
@@ -88,7 +91,7 @@ export default function hydrateStructuredReport(
|
||||
// Mapping of legacy datasets is now directly handled by adapters module
|
||||
const datasetToUse = instance;
|
||||
|
||||
// Use dcmjs to generate toolState.
|
||||
// Use CS3D adapters to generate toolState.
|
||||
let storedMeasurementByAnnotationType = MeasurementReport.generateToolState(
|
||||
datasetToUse,
|
||||
// NOTE: we need to pass in the imageIds to dcmjs since the we use them
|
||||
@@ -96,7 +99,6 @@ export default function hydrateStructuredReport(
|
||||
// that measurements were added to the display set are the same order as
|
||||
// the measurementGroups in the instance.
|
||||
sopInstanceUIDToImageId,
|
||||
utilities.imageToWorldCoords,
|
||||
metaData
|
||||
);
|
||||
|
||||
@@ -147,6 +149,9 @@ export default function hydrateStructuredReport(
|
||||
|
||||
for (let i = 0; i < imageIds.length; i++) {
|
||||
const imageId = imageIds[i];
|
||||
if (!imageId) {
|
||||
continue;
|
||||
}
|
||||
const { SeriesInstanceUID, StudyInstanceUID } = metaData.get('instance', imageId);
|
||||
|
||||
if (!SeriesInstanceUIDs.includes(SeriesInstanceUID)) {
|
||||
@@ -160,38 +165,55 @@ export default function hydrateStructuredReport(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets reference data for what frame of reference and the referenced
|
||||
* image id, or for 3d measurements, the volumeId to apply this annotation to.
|
||||
*/
|
||||
function getReferenceData(toolData): ToolTypes.AnnotationMetadata {
|
||||
// Add the measurement to toolState
|
||||
// dcmjs and Cornerstone3D has structural defect in supporting multi-frame
|
||||
// files, and looking up the imageId from sopInstanceUIDToImageId results
|
||||
// in the wrong value.
|
||||
const frameNumber = (toolData.annotation.data && toolData.annotation.data.frameNumber) || 1;
|
||||
const imageId =
|
||||
imageIdsForToolState[toolData.sopInstanceUid][frameNumber] ||
|
||||
sopInstanceUIDToImageId[toolData.sopInstanceUid];
|
||||
|
||||
if (!imageId) {
|
||||
return getReferenceData3D(toolData, servicesManager);
|
||||
}
|
||||
|
||||
const instance = metaData.get('instance', imageId);
|
||||
const {
|
||||
FrameOfReferenceUID,
|
||||
// SOPInstanceUID,
|
||||
// SeriesInstanceUID,
|
||||
// StudyInstanceUID,
|
||||
} = instance;
|
||||
|
||||
return {
|
||||
referencedImageId: imageId,
|
||||
FrameOfReferenceUID,
|
||||
};
|
||||
}
|
||||
|
||||
Object.keys(hydratableMeasurementsInSR).forEach(annotationType => {
|
||||
const toolDataForAnnotationType = hydratableMeasurementsInSR[annotationType];
|
||||
|
||||
toolDataForAnnotationType.forEach(toolData => {
|
||||
// Add the measurement to toolState
|
||||
// dcmjs and Cornerstone3D has structural defect in supporting multi-frame
|
||||
// files, and looking up the imageId from sopInstanceUIDToImageId results
|
||||
// in the wrong value.
|
||||
const frameNumber = (toolData.annotation.data && toolData.annotation.data.frameNumber) || 1;
|
||||
const imageId =
|
||||
imageIdsForToolState[toolData.sopInstanceUid][frameNumber] ||
|
||||
sopInstanceUIDToImageId[toolData.sopInstanceUid];
|
||||
|
||||
toolData.uid = guid();
|
||||
|
||||
const instance = metaData.get('instance', imageId);
|
||||
const {
|
||||
FrameOfReferenceUID,
|
||||
// SOPInstanceUID,
|
||||
// SeriesInstanceUID,
|
||||
// StudyInstanceUID,
|
||||
} = instance;
|
||||
const referenceData = getReferenceData(toolData);
|
||||
const { imageId } = referenceData;
|
||||
|
||||
const annotation = {
|
||||
annotationUID: toolData.annotation.annotationUID,
|
||||
data: toolData.annotation.data,
|
||||
metadata: {
|
||||
...referenceData,
|
||||
toolName: annotationType,
|
||||
referencedImageId: imageId,
|
||||
FrameOfReferenceUID,
|
||||
},
|
||||
};
|
||||
utilities.updatePlaneRestriction(annotation.data.handles.points, annotation.metadata);
|
||||
|
||||
const source = measurementService.getSource(
|
||||
CORNERSTONE_3D_TOOLS_SOURCE_NAME,
|
||||
@@ -225,7 +247,7 @@ export default function hydrateStructuredReport(
|
||||
locking.setAnnotationLocked(newAnnotationUID, true);
|
||||
}
|
||||
|
||||
if (!imageIds.includes(imageId)) {
|
||||
if (imageId && !imageIds.includes(imageId)) {
|
||||
imageIds.push(imageId);
|
||||
}
|
||||
});
|
||||
@@ -238,3 +260,92 @@ export default function hydrateStructuredReport(
|
||||
SeriesInstanceUIDs,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* For 3d annotations, there are often several display sets which could
|
||||
* be used to display the annotation. Choose the first annotation with the
|
||||
* same frame of reference that is reconstructable, or the first display set
|
||||
* otherwise.
|
||||
*/
|
||||
function chooseDisplaySet(displaySets, annotation) {
|
||||
if (!displaySets?.length) {
|
||||
console.warn('No display set found for', annotation);
|
||||
return;
|
||||
}
|
||||
if (displaySets.length === 1) {
|
||||
return displaySets[0];
|
||||
}
|
||||
const volumeDs = displaySets.find(ds => ds.isReconstructable);
|
||||
if (volumeDs) {
|
||||
return volumeDs;
|
||||
}
|
||||
return displaySets[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the additional reference data appropriate for a 3d reference.
|
||||
* This will choose a volume id, frame of reference and a plane restriction.
|
||||
*/
|
||||
function getReferenceData3D(toolData, servicesManager: Types.ServicesManager) {
|
||||
const { FrameOfReferenceUID } = toolData.annotation.metadata;
|
||||
const { points } = toolData.annotation.data.handles;
|
||||
const { displaySetService } = servicesManager.services;
|
||||
const displaySetsFOR = displaySetService.getDisplaySetsBy(
|
||||
ds => ds.FrameOfReferenceUID === FrameOfReferenceUID
|
||||
);
|
||||
if (!displaySetsFOR.length || !points?.length) {
|
||||
return {
|
||||
FrameOfReferenceUID,
|
||||
};
|
||||
}
|
||||
const ds = chooseDisplaySet(displaySetsFOR, toolData.annotation);
|
||||
const cameraView = chooseCameraView(ds, points);
|
||||
|
||||
const viewReference = {
|
||||
...cameraView,
|
||||
volumeId: ds.displaySetInstanceUID,
|
||||
FrameOfReferenceUID,
|
||||
};
|
||||
utilities.updatePlaneRestriction(points, viewReference);
|
||||
return viewReference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chooses a possible camera view - right now this is fairly basic,
|
||||
* just setting the unknowns to null.
|
||||
*/
|
||||
function chooseCameraView(_ds, points) {
|
||||
const selectedPoints = choosePoints(points);
|
||||
const cameraFocalPoint = <Point3>centerOf(selectedPoints);
|
||||
// These are sufficient to be null for now and can be set on first view
|
||||
let viewPlaneNormal: Types.Point3 = null;
|
||||
let viewUp: Types.Point3 = null;
|
||||
|
||||
return {
|
||||
cameraFocalPoint,
|
||||
viewPlaneNormal,
|
||||
viewUp,
|
||||
};
|
||||
}
|
||||
|
||||
function centerOf(points) {
|
||||
const scale = 1 / points.length;
|
||||
const center = vec3.create();
|
||||
for (const point of points) {
|
||||
vec3.scaleAndAdd(center, center, point, scale);
|
||||
}
|
||||
return center;
|
||||
}
|
||||
|
||||
function choosePoints(points) {
|
||||
if (points.length === 1 || points.length === 2) {
|
||||
return points;
|
||||
}
|
||||
const firstIndex = 0;
|
||||
const secondIndex = Math.ceil(points.length / 4);
|
||||
const thirdIndex = Math.ceil(points.length / 2);
|
||||
// TODO - check if colinear, if so try to find another 3 points.
|
||||
|
||||
const newPoints = [points[firstIndex], points[secondIndex], points[thirdIndex]];
|
||||
return newPoints;
|
||||
}
|
||||
@@ -22,13 +22,20 @@ export default function isRehydratable(displaySet, mappings) {
|
||||
const { measurements } = displaySet;
|
||||
|
||||
for (let i = 0; i < measurements.length; i++) {
|
||||
const { TrackingIdentifier } = measurements[i] || {};
|
||||
if (!TrackingIdentifier) {
|
||||
console.warn('No tracking identifier for measurement ', measurements[i]);
|
||||
const measurement = measurements[i];
|
||||
if (!measurement) {
|
||||
continue;
|
||||
}
|
||||
const { TrackingIdentifier = '', graphicType, graphicCode, pointsLength } = measurement;
|
||||
if (!TrackingIdentifier && !graphicType) {
|
||||
console.warn('No tracking identifier or graphicType for measurement ', measurement);
|
||||
continue;
|
||||
}
|
||||
const adapter = MeasurementReport.getAdapterForTrackingIdentifier(TrackingIdentifier);
|
||||
const hydratable = adapter && mappingDefinitions.has(adapter.toolType);
|
||||
const adapters = MeasurementReport.getAdaptersForTypes(graphicCode, graphicType, pointsLength);
|
||||
const hydratable =
|
||||
(adapter && mappingDefinitions.has(adapter.toolType)) ||
|
||||
(adapters && adapters.some(adapter => mappingDefinitions.has(adapter.toolType)));
|
||||
|
||||
if (hydratable) {
|
||||
return true;
|
||||
|
||||
@@ -3,6 +3,805 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.12.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.59...v3.12.0-beta.60) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.58...v3.12.0-beta.59) (2025-10-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Use exact versioning for dependencies in package.json files. ([#5494](https://github.com/OHIF/Viewers/issues/5494)) ([c7d2017](https://github.com/OHIF/Viewers/commit/c7d2017f081c5803a70bab6c75bba0c975028125))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.57...v3.12.0-beta.58) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.56...v3.12.0-beta.57) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.55...v3.12.0-beta.56) (2025-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.54...v3.12.0-beta.55) (2025-10-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.53...v3.12.0-beta.54) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.52...v3.12.0-beta.53) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.51...v3.12.0-beta.52) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.50...v3.12.0-beta.51) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.49...v3.12.0-beta.50) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.48...v3.12.0-beta.49) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.47...v3.12.0-beta.48) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.46...v3.12.0-beta.47) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.45...v3.12.0-beta.46) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.44...v3.12.0-beta.45) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.43...v3.12.0-beta.44) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.42...v3.12.0-beta.43) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.41...v3.12.0-beta.42) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.40...v3.12.0-beta.41) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.39...v3.12.0-beta.40) (2025-10-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.38...v3.12.0-beta.39) (2025-10-01)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.37...v3.12.0-beta.38) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.36...v3.12.0-beta.37) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.35...v3.12.0-beta.36) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.34...v3.12.0-beta.35) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.33...v3.12.0-beta.34) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.32...v3.12.0-beta.33) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.31...v3.12.0-beta.32) (2025-09-26)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.30...v3.12.0-beta.31) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.29...v3.12.0-beta.30) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.28...v3.12.0-beta.29) (2025-09-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.27...v3.12.0-beta.28) (2025-09-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.26...v3.12.0-beta.27) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.25...v3.12.0-beta.26) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.24...v3.12.0-beta.25) (2025-09-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.23...v3.12.0-beta.24) (2025-09-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.22...v3.12.0-beta.23) (2025-09-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.21...v3.12.0-beta.22) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.20...v3.12.0-beta.21) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.19...v3.12.0-beta.20) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.18...v3.12.0-beta.19) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.17...v3.12.0-beta.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.16...v3.12.0-beta.17) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.15...v3.12.0-beta.16) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.14...v3.12.0-beta.15) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.13...v3.12.0-beta.14) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.12...v3.12.0-beta.13) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.11...v3.12.0-beta.12) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.10...v3.12.0-beta.11) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.9...v3.12.0-beta.10) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.8...v3.12.0-beta.9) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.7...v3.12.0-beta.8) (2025-08-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add WSI bulk data annotations support (ANN) ([#4972](https://github.com/OHIF/Viewers/issues/4972)) ([2ed6818](https://github.com/OHIF/Viewers/commit/2ed681817142b13971bb17b3058be26bbab6b90b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.6...v3.12.0-beta.7) (2025-08-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.5...v3.12.0-beta.6) (2025-08-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.4...v3.12.0-beta.5) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.3...v3.12.0-beta.4) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.2...v3.12.0-beta.3) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.1...v3.12.0-beta.2) (2025-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.0...v3.12.0-beta.1) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.116...v3.12.0-beta.0) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.116](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.115...v3.11.0-beta.116) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.115](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.114...v3.11.0-beta.115) (2025-07-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add support to scoord3d ([#5016](https://github.com/OHIF/Viewers/issues/5016)) ([735405a](https://github.com/OHIF/Viewers/commit/735405a8554c7ee6283faa83fc42ff8bb9ac34ff))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.114](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.113...v3.11.0-beta.114) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.113](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.112...v3.11.0-beta.113) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.111...v3.11.0-beta.112) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.110...v3.11.0-beta.111) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.109...v3.11.0-beta.110) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.108...v3.11.0-beta.109) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.107...v3.11.0-beta.108) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.106...v3.11.0-beta.107) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.105...v3.11.0-beta.106) (2025-07-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.104...v3.11.0-beta.105) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.103...v3.11.0-beta.104) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.102...v3.11.0-beta.103) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.101...v3.11.0-beta.102) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.100...v3.11.0-beta.101) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.99...v3.11.0-beta.100) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.98...v3.11.0-beta.99) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.97...v3.11.0-beta.98) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.96...v3.11.0-beta.97) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.95...v3.11.0-beta.96) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.94...v3.11.0-beta.95) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.93...v3.11.0-beta.94) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.92...v3.11.0-beta.93) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.91...v3.11.0-beta.92) (2025-07-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.90...v3.11.0-beta.91) (2025-07-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.89...v3.11.0-beta.90) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.88...v3.11.0-beta.89) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.87...v3.11.0-beta.88) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.86...v3.11.0-beta.87) (2025-07-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.85...v3.11.0-beta.86) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.84...v3.11.0-beta.85) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.83...v3.11.0-beta.84) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.82...v3.11.0-beta.83) (2025-07-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* enhance preview accept method ([#5199](https://github.com/OHIF/Viewers/issues/5199)) ([540923a](https://github.com/OHIF/Viewers/commit/540923ad8b2f768bd0f766c4f106cf6785a06afc))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.81...v3.11.0-beta.82) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.80...v3.11.0-beta.81) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.79...v3.11.0-beta.80) (2025-07-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **rendering:** Introduce WebGLContextPool for parallel rendering in ContextPoolRenderingEngine ([#5196](https://github.com/OHIF/Viewers/issues/5196)) ([10d9316](https://github.com/OHIF/Viewers/commit/10d93161b4a1bea18ec1b9de9ae3e094e6bb47d0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.78...v3.11.0-beta.79) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dynamic-volume",
|
||||
"version": "3.11.0-beta.79",
|
||||
"version": "3.12.0-beta.60",
|
||||
"description": "OHIF extension for 4D volumes data",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -29,21 +29,21 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.11.0-beta.79",
|
||||
"@ohif/extension-cornerstone": "3.11.0-beta.79",
|
||||
"@ohif/extension-default": "3.11.0-beta.79",
|
||||
"@ohif/i18n": "3.11.0-beta.79",
|
||||
"@ohif/ui": "3.11.0-beta.79",
|
||||
"dcmjs": "^0.42.0",
|
||||
"dicom-parser": "^1.8.21",
|
||||
"hammerjs": "^2.0.8",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^18.3.1"
|
||||
"@ohif/core": "3.12.0-beta.60",
|
||||
"@ohif/extension-cornerstone": "3.12.0-beta.60",
|
||||
"@ohif/extension-default": "3.12.0-beta.60",
|
||||
"@ohif/i18n": "3.12.0-beta.60",
|
||||
"@ohif/ui": "3.12.0-beta.60",
|
||||
"dcmjs": "0.43.1",
|
||||
"dicom-parser": "1.8.21",
|
||||
"hammerjs": "2.0.8",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/core": "^3.29.2",
|
||||
"@cornerstonejs/tools": "^3.29.2",
|
||||
"classnames": "^2.3.2"
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/core": "4.5.5",
|
||||
"@cornerstonejs/tools": "4.5.5",
|
||||
"classnames": "2.5.1"
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,887 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.12.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.59...v3.12.0-beta.60) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.58...v3.12.0-beta.59) (2025-10-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Use exact versioning for dependencies in package.json files. ([#5494](https://github.com/OHIF/Viewers/issues/5494)) ([c7d2017](https://github.com/OHIF/Viewers/commit/c7d2017f081c5803a70bab6c75bba0c975028125))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.57...v3.12.0-beta.58) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.56...v3.12.0-beta.57) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.55...v3.12.0-beta.56) (2025-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.54...v3.12.0-beta.55) (2025-10-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.53...v3.12.0-beta.54) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.52...v3.12.0-beta.53) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.51...v3.12.0-beta.52) (2025-10-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Segmentation not displayed and unable to draw segments when switching back to volume/stack viewport from 3D viewport ([#5430](https://github.com/OHIF/Viewers/issues/5430)) ([78df8ff](https://github.com/OHIF/Viewers/commit/78df8ff03a371904a390c63a95628d5511dad136))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.50...v3.12.0-beta.51) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.49...v3.12.0-beta.50) (2025-10-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Segmentation:** [Bug [#5420](https://github.com/OHIF/Viewers/issues/5420)] Segmentation color resets after using toggleOneUp ([#5465](https://github.com/OHIF/Viewers/issues/5465)) ([2c6ce21](https://github.com/OHIF/Viewers/commit/2c6ce21c8f79f8b3e6dc47b5aa6f717b6b5cbd2a))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.48...v3.12.0-beta.49) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.47...v3.12.0-beta.48) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.46...v3.12.0-beta.47) (2025-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.45...v3.12.0-beta.46) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.44...v3.12.0-beta.45) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.43...v3.12.0-beta.44) (2025-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.42...v3.12.0-beta.43) (2025-10-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **MeasurementService:** add rendering of unmapped measurements ([#5416](https://github.com/OHIF/Viewers/issues/5416)) ([851e74d](https://github.com/OHIF/Viewers/commit/851e74d7b867a806befb5d85fd71ff9a75e9f2d2))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.41...v3.12.0-beta.42) (2025-10-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* duplicate segmentation entries on layout switch ([#5458](https://github.com/OHIF/Viewers/issues/5458)) ([9e951e8](https://github.com/OHIF/Viewers/commit/9e951e88005af505ae0c07fbcd3366de12b773dd))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.40...v3.12.0-beta.41) (2025-10-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.39...v3.12.0-beta.40) (2025-10-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.38...v3.12.0-beta.39) (2025-10-01)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.37...v3.12.0-beta.38) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.36...v3.12.0-beta.37) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.35...v3.12.0-beta.36) (2025-09-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.34...v3.12.0-beta.35) (2025-09-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Restored segment label tool in longitudinal mode. ([#5443](https://github.com/OHIF/Viewers/issues/5443)) ([dd86a8e](https://github.com/OHIF/Viewers/commit/dd86a8eabd0712d25e7652a242377fe09597e8d5))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.33...v3.12.0-beta.34) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.32...v3.12.0-beta.33) (2025-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.31...v3.12.0-beta.32) (2025-09-26)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.30...v3.12.0-beta.31) (2025-09-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.29...v3.12.0-beta.30) (2025-09-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **i18n:** Add and update i18n Translation for Toolbar Tool Names ([#5392](https://github.com/OHIF/Viewers/issues/5392)) ([7783d0f](https://github.com/OHIF/Viewers/commit/7783d0f558bbb7016c29513b6fe76ed069dbd75c))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.28...v3.12.0-beta.29) (2025-09-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Segmentation:** Segmentation highlight animation function selection ([#5401](https://github.com/OHIF/Viewers/issues/5401)) ([69dbe27](https://github.com/OHIF/Viewers/commit/69dbe2778493cdfc7a8da5e757c95217bb31edc2))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.27...v3.12.0-beta.28) (2025-09-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SegmentationService:** _getSegmentCenter wrongly handling seg center availability ([#5396](https://github.com/OHIF/Viewers/issues/5396)) ([74b82bd](https://github.com/OHIF/Viewers/commit/74b82bd93442411ad68f4872992126c40321eb9e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.26...v3.12.0-beta.27) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.25...v3.12.0-beta.26) (2025-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.24...v3.12.0-beta.25) (2025-09-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.23...v3.12.0-beta.24) (2025-09-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.22...v3.12.0-beta.23) (2025-09-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cornerstone-dicom-rt:** adding caching usage to cornerstone-dicom-rt SOP Class Handler ([#5387](https://github.com/OHIF/Viewers/issues/5387)) ([d6ea179](https://github.com/OHIF/Viewers/commit/d6ea179ac43a47d4011b8dcaf59d79d99382d6c8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.21...v3.12.0-beta.22) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.20...v3.12.0-beta.21) (2025-08-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.19...v3.12.0-beta.20) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.18...v3.12.0-beta.19) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.17...v3.12.0-beta.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.16...v3.12.0-beta.17) (2025-08-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* seg preview ([#5338](https://github.com/OHIF/Viewers/issues/5338)) ([d91cc23](https://github.com/OHIF/Viewers/commit/d91cc230e5231ca32ee28736f661a1497f7834c5))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.15...v3.12.0-beta.16) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.14...v3.12.0-beta.15) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.13...v3.12.0-beta.14) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.12...v3.12.0-beta.13) (2025-08-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add back clear segmentation representations ([#5336](https://github.com/OHIF/Viewers/issues/5336)) ([21d6ba2](https://github.com/OHIF/Viewers/commit/21d6ba2bb30df5b99bf5728163caff514aaa5dcd))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.11...v3.12.0-beta.12) (2025-08-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Segmentation stats customization module ([#5324](https://github.com/OHIF/Viewers/issues/5324)) ([b9d6f55](https://github.com/OHIF/Viewers/commit/b9d6f558cbe5957f83e6d92305a78662a0b186ed))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.10...v3.12.0-beta.11) (2025-08-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.9...v3.12.0-beta.10) (2025-08-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Jump to measurement moves the camera if it is not in the viewport ([#5023](https://github.com/OHIF/Viewers/issues/5023)) ([6fe9df6](https://github.com/OHIF/Viewers/commit/6fe9df6ec93c0f37e3bb9f8bf6425bae025e75c8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.8...v3.12.0-beta.9) (2025-08-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.7...v3.12.0-beta.8) (2025-08-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add WSI bulk data annotations support (ANN) ([#4972](https://github.com/OHIF/Viewers/issues/4972)) ([2ed6818](https://github.com/OHIF/Viewers/commit/2ed681817142b13971bb17b3058be26bbab6b90b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.6...v3.12.0-beta.7) (2025-08-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.5...v3.12.0-beta.6) (2025-08-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **orientationMarkers:** improved the orientation markers with a simplified version ([#5328](https://github.com/OHIF/Viewers/issues/5328)) ([266b1f5](https://github.com/OHIF/Viewers/commit/266b1f58f01ac6742a9bb40dda28459e7cddc683))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.4...v3.12.0-beta.5) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.3...v3.12.0-beta.4) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.2...v3.12.0-beta.3) (2025-08-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.1...v3.12.0-beta.2) (2025-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.0...v3.12.0-beta.1) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.12.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.116...v3.12.0-beta.0) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.116](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.115...v3.11.0-beta.116) (2025-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.115](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.114...v3.11.0-beta.115) (2025-07-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add support to scoord3d ([#5016](https://github.com/OHIF/Viewers/issues/5016)) ([735405a](https://github.com/OHIF/Viewers/commit/735405a8554c7ee6283faa83fc42ff8bb9ac34ff))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.114](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.113...v3.11.0-beta.114) (2025-07-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.113](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.112...v3.11.0-beta.113) (2025-07-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* improve segment label ([#5217](https://github.com/OHIF/Viewers/issues/5217)) ([271b84f](https://github.com/OHIF/Viewers/commit/271b84f78fcc3974006c7e1a4dbb2ef322fdb9ec))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.111...v3.11.0-beta.112) (2025-07-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **colorbar:** Allow for AdvancedRenderingControls to be placed at the left or right of the viewport. ([#5273](https://github.com/OHIF/Viewers/issues/5273)) ([341f1c4](https://github.com/OHIF/Viewers/commit/341f1c4ce799d1bcef3632e0d135be0cfcb333a9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.110...v3.11.0-beta.111) (2025-07-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **colorbar:** Allow for `AdvancedRenderingControls` to be placed at the top or bottom of the viewport. ([#5270](https://github.com/OHIF/Viewers/issues/5270)) ([d24fe54](https://github.com/OHIF/Viewers/commit/d24fe54d2b5598c8356afa9ce91939018940ee19))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.109...v3.11.0-beta.110) (2025-07-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* null save voi range properties ([#5268](https://github.com/OHIF/Viewers/issues/5268)) ([04dcacd](https://github.com/OHIF/Viewers/commit/04dcacd3a5d0d565b163c96222c8c7f948a05abd))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.108...v3.11.0-beta.109) (2025-07-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.107...v3.11.0-beta.108) (2025-07-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.106...v3.11.0-beta.107) (2025-07-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* prevent failure in DICOM loader for wadouri type ([#5260](https://github.com/OHIF/Viewers/issues/5260)) ([d0cf9e0](https://github.com/OHIF/Viewers/commit/d0cf9e02f438cd8d26ed5bca5fb528549f4c8b98))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.105...v3.11.0-beta.106) (2025-07-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ArrowAnnotate:** Allow free-form text for arrow annotations ([#5259](https://github.com/OHIF/Viewers/issues/5259)) ([3c8446a](https://github.com/OHIF/Viewers/commit/3c8446a5e5caf8c050275bd4c193defa9e370b32))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.104...v3.11.0-beta.105) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.103...v3.11.0-beta.104) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.102...v3.11.0-beta.103) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.101...v3.11.0-beta.102) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.100...v3.11.0-beta.101) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.99...v3.11.0-beta.100) (2025-07-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* disable seg download/export buttons until a user has drawn something ([#4953](https://github.com/OHIF/Viewers/issues/4953)) ([7ffe17d](https://github.com/OHIF/Viewers/commit/7ffe17deea8d5642ad69d11943cff3298c227be2))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.98...v3.11.0-beta.99) (2025-07-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ViewportOrientationMarkers:** round rotation to fix floating point issue ([#5135](https://github.com/OHIF/Viewers/issues/5135)) ([bd3ff5f](https://github.com/OHIF/Viewers/commit/bd3ff5f57c2fee35e92be4571048cc057eeaf29d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.97...v3.11.0-beta.98) (2025-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.96...v3.11.0-beta.97) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.95...v3.11.0-beta.96) (2025-07-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.94...v3.11.0-beta.95) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.93...v3.11.0-beta.94) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.92...v3.11.0-beta.93) (2025-07-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.91...v3.11.0-beta.92) (2025-07-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.90...v3.11.0-beta.91) (2025-07-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.89...v3.11.0-beta.90) (2025-07-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **black-viewports:** MPR viewports were turning black if their parent stack had it's properties reset ([#5219](https://github.com/OHIF/Viewers/issues/5219)) ([3ff9a65](https://github.com/OHIF/Viewers/commit/3ff9a65ef3c3f1735d8730868a8b7dc984fc76fc))
|
||||
* **DicomUpload:** Fix upload form and some scrollbars styles ([#5125](https://github.com/OHIF/Viewers/issues/5125)) ([26d77fb](https://github.com/OHIF/Viewers/commit/26d77fb149bd126cdd0571fa0e202e136c6d0d83))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.88...v3.11.0-beta.89) (2025-07-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Fix segmentationid undefined 5106 ([#5107](https://github.com/OHIF/Viewers/issues/5107)) ([f38805e](https://github.com/OHIF/Viewers/commit/f38805e6f1c98138db1617c2fa56f9007207d456))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.87...v3.11.0-beta.88) (2025-07-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.86...v3.11.0-beta.87) (2025-07-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Removed LOAD/hydrate button for segmentation overlays ([#5214](https://github.com/OHIF/Viewers/issues/5214)) ([e0289dc](https://github.com/OHIF/Viewers/commit/e0289dc49f52e7ee6f0642f01de3ae31cddf71e0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.85...v3.11.0-beta.86) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.84...v3.11.0-beta.85) (2025-07-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **viewport:** Enhance Orientation Menu with Reformat Option and UI Improvements ([#5184](https://github.com/OHIF/Viewers/issues/5184)) ([c175837](https://github.com/OHIF/Viewers/commit/c175837273e664318fe51c426d98e4989f55b050))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.83...v3.11.0-beta.84) (2025-07-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.82...v3.11.0-beta.83) (2025-07-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* enhance preview accept method ([#5199](https://github.com/OHIF/Viewers/issues/5199)) ([540923a](https://github.com/OHIF/Viewers/commit/540923ad8b2f768bd0f766c4f106cf6785a06afc))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.81...v3.11.0-beta.82) (2025-07-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.80...v3.11.0-beta.81) (2025-07-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* exception in newly added segmentations ([#5198](https://github.com/OHIF/Viewers/issues/5198)) ([fd5bcee](https://github.com/OHIF/Viewers/commit/fd5bcee909223f92c0833bf63f9aee08eb533be2))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.79...v3.11.0-beta.80) (2025-07-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **rendering:** Introduce WebGLContextPool for parallel rendering in ContextPoolRenderingEngine ([#5196](https://github.com/OHIF/Viewers/issues/5196)) ([10d9316](https://github.com/OHIF/Viewers/commit/10d93161b4a1bea18ec1b9de9ae3e094e6bb47d0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.11.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.11.0-beta.78...v3.11.0-beta.79) (2025-07-11)
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
const base = require('../../jest.config.base.js');
|
||||
const pkg = require('./package');
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
displayName: pkg.name,
|
||||
moduleNameMapper: {
|
||||
...base.moduleNameMapper,
|
||||
'@ohif/(.*)': '<rootDir>/../../platform/$1/src',
|
||||
'^@cornerstonejs/([^/]+)/(.*)$': '<rootDir>/../../node_modules/@cornerstonejs/$1/dist/esm/$2',
|
||||
'^@cornerstonejs/([^/]+)$': '<rootDir>/../../node_modules/@cornerstonejs/$1/dist/esm',
|
||||
},
|
||||
// rootDir: "../.."
|
||||
// testMatch: [
|
||||
// //`<rootDir>/platform/${pack.name}/**/*.spec.js`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "3.11.0-beta.79",
|
||||
"version": "3.12.0-beta.60",
|
||||
"description": "OHIF extension for Cornerstone",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -31,41 +31,43 @@
|
||||
"dev:cornerstone": "yarn run dev",
|
||||
"build": "cross-env NODE_ENV=production webpack --progress --config .webpack/webpack.prod.js",
|
||||
"build:package-1": "yarn run build",
|
||||
"start": "yarn run dev"
|
||||
"start": "yarn run dev",
|
||||
"test:unit": "jest --watchAll",
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@cornerstonejs/codec-charls": "^1.2.3",
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||
"@cornerstonejs/dicom-image-loader": "^3.29.2",
|
||||
"@ohif/core": "3.11.0-beta.79",
|
||||
"@ohif/ui": "3.11.0-beta.79",
|
||||
"dcmjs": "^0.42.0",
|
||||
"dicom-parser": "^1.8.21",
|
||||
"hammerjs": "^2.0.8",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-resize-detector": "^10.0.1"
|
||||
"@cornerstonejs/codec-charls": "1.2.3",
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "1.2.4",
|
||||
"@cornerstonejs/codec-openjph": "2.4.7",
|
||||
"@cornerstonejs/dicom-image-loader": "4.5.5",
|
||||
"@ohif/core": "3.12.0-beta.60",
|
||||
"@ohif/ui": "3.12.0-beta.60",
|
||||
"dcmjs": "0.43.1",
|
||||
"dicom-parser": "1.8.21",
|
||||
"hammerjs": "2.0.8",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-resize-detector": "10.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^3.29.2",
|
||||
"@cornerstonejs/ai": "^3.29.2",
|
||||
"@cornerstonejs/core": "^3.29.2",
|
||||
"@cornerstonejs/labelmap-interpolation": "^3.29.2",
|
||||
"@cornerstonejs/polymorphic-segmentation": "^3.29.2",
|
||||
"@cornerstonejs/tools": "^3.29.2",
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.5.5",
|
||||
"@cornerstonejs/ai": "4.5.5",
|
||||
"@cornerstonejs/core": "4.5.5",
|
||||
"@cornerstonejs/labelmap-interpolation": "4.5.5",
|
||||
"@cornerstonejs/polymorphic-segmentation": "4.5.5",
|
||||
"@cornerstonejs/tools": "4.5.5",
|
||||
"@itk-wasm/morphological-contour-interpolation": "1.1.0",
|
||||
"@kitware/vtk.js": "32.12.0",
|
||||
"html2canvas": "^1.4.1",
|
||||
"lodash.compact": "^3.0.1",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.flatten": "^4.4.0",
|
||||
"lodash.merge": "^4.6.2",
|
||||
"lodash.zip": "^4.2.0",
|
||||
"shader-loader": "^1.3.1",
|
||||
"worker-loader": "^3.0.8"
|
||||
"html2canvas": "1.4.1",
|
||||
"lodash.compact": "3.0.1",
|
||||
"lodash.debounce": "4.0.8",
|
||||
"lodash.flatten": "4.4.0",
|
||||
"lodash.merge": "4.6.2",
|
||||
"lodash.zip": "4.2.0",
|
||||
"shader-loader": "1.3.1",
|
||||
"worker-loader": "3.0.8"
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import CinePlayer from '../components/CinePlayer';
|
||||
import type { Types } from '@ohif/core';
|
||||
|
||||
import OHIFViewportActionCorners from '../components/OHIFViewportActionCorners';
|
||||
import ViewportColorbarsContainer from '../components/ViewportColorbar';
|
||||
import { getViewportPresentations } from '../utils/presentations/getViewportPresentations';
|
||||
import { useSynchronizersStore } from '../stores/useSynchronizersStore';
|
||||
import ActiveViewportBehavior from '../utils/ActiveViewportBehavior';
|
||||
@@ -305,31 +304,6 @@ const OHIFCornerstoneViewport = React.memo(
|
||||
loadViewportData();
|
||||
}, [viewportOptions, displaySets, dataSource]);
|
||||
|
||||
/**
|
||||
* There are two scenarios for jump to click
|
||||
* 1. Current viewports contain the displaySet that the annotation was drawn on
|
||||
* 2. Current viewports don't contain the displaySet that the annotation was drawn on
|
||||
* and we need to change the viewports displaySet for jumping.
|
||||
* Since measurement_jump happens via events and listeners, the former case is handled
|
||||
* by the measurement_jump direct callback, but the latter case is handled first by
|
||||
* the viewportGrid to set the correct displaySet on the viewport, AND THEN we check
|
||||
* the cache for jumping to see if there is any jump queued, then we jump to the correct slice.
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (isJumpToMeasurementDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { unsubscribe } = measurementService.subscribe(
|
||||
MeasurementService.EVENTS.JUMP_TO_MEASUREMENT_VIEWPORT,
|
||||
event => handleJumpToMeasurement(event, elementRef, viewportId, cornerstoneViewportService)
|
||||
);
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
}, [displaySets, elementRef, viewportId, isJumpToMeasurementDisabled, servicesManager]);
|
||||
|
||||
const Notification = customizationService.getCustomization('ui.notificationComponent');
|
||||
|
||||
return (
|
||||
@@ -387,54 +361,6 @@ const OHIFCornerstoneViewport = React.memo(
|
||||
areEqual
|
||||
);
|
||||
|
||||
// Helper function to handle jumping to measurements
|
||||
function handleJumpToMeasurement(event, elementRef, viewportId, cornerstoneViewportService) {
|
||||
const { measurement, isConsumed } = event;
|
||||
if (!measurement || isConsumed) {
|
||||
return;
|
||||
}
|
||||
|
||||
const enabledElement = getEnabledElement(elementRef.current);
|
||||
|
||||
if (!enabledElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const viewport = enabledElement.viewport as csTypes.IStackViewport | csTypes.IVolumeViewport;
|
||||
|
||||
const { metadata, displaySetInstanceUID } = measurement;
|
||||
|
||||
const viewportDisplaySets = cornerstoneViewportService.getViewportDisplaySets(viewportId);
|
||||
|
||||
const showingDisplaySet = viewportDisplaySets.find(
|
||||
ds => ds.displaySetInstanceUID === displaySetInstanceUID
|
||||
);
|
||||
|
||||
let metadataToUse = metadata;
|
||||
// if it is not showing the displaySet we need to remove the FOR from the metadata
|
||||
if (!showingDisplaySet) {
|
||||
metadataToUse = {
|
||||
...metadata,
|
||||
FrameOfReferenceUID: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
// Todo: make it work with cases where we want to define FOR based measurements too
|
||||
if (!viewport.isReferenceViewable(metadataToUse, WITH_NAVIGATION)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
viewport.setViewReference(metadata);
|
||||
viewport.render();
|
||||
} catch (e) {
|
||||
console.warn('Unable to apply', metadata, e);
|
||||
}
|
||||
|
||||
cs3DTools.annotation.selection.setAnnotationSelected(measurement.uid);
|
||||
event?.consume?.();
|
||||
}
|
||||
|
||||
function _rehydrateSynchronizers(viewportId: string, syncGroupService: any) {
|
||||
const { synchronizersStore } = useSynchronizersStore.getState();
|
||||
const synchronizers = synchronizersStore[viewportId];
|
||||
@@ -558,16 +484,4 @@ function areEqual(prevProps, nextProps) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper function to check if display sets have changed
|
||||
function haveDisplaySetsChanged(prevDisplaySets, currentDisplaySets) {
|
||||
if (prevDisplaySets.length !== currentDisplaySets.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return currentDisplaySets.some((currentDS, index) => {
|
||||
const prevDS = prevDisplaySets[index];
|
||||
return currentDS.displaySetInstanceUID !== prevDS.displaySetInstanceUID;
|
||||
});
|
||||
}
|
||||
|
||||
export default OHIFCornerstoneViewport;
|
||||
@@ -1,12 +1,6 @@
|
||||
import React, { useEffect, useState, useMemo, useRef } from 'react';
|
||||
import React, { useEffect, useState, useMemo } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
metaData,
|
||||
Enums,
|
||||
Types,
|
||||
getEnabledElement,
|
||||
utilities as coreUtilities,
|
||||
} from '@cornerstonejs/core';
|
||||
import { metaData, Enums, getEnabledElement } from '@cornerstonejs/core';
|
||||
import { utilities } from '@cornerstonejs/tools';
|
||||
import { vec3 } from 'gl-matrix';
|
||||
|
||||
@@ -22,75 +16,36 @@ function ViewportOrientationMarkers({
|
||||
servicesManager,
|
||||
orientationMarkers = ['top', 'left'],
|
||||
}: withAppTypes) {
|
||||
// Rotation is in degrees
|
||||
const [rotation, setRotation] = useState(0);
|
||||
const [flipHorizontal, setFlipHorizontal] = useState(false);
|
||||
const [flipVertical, setFlipVertical] = useState(false);
|
||||
const [cameraModifiedTime, setCameraModifiedTime] = useState(0);
|
||||
const { isViewportBackgroundLight: isLight } = useViewportRendering(viewportId);
|
||||
const { cornerstoneViewportService } = servicesManager.services;
|
||||
|
||||
// Store initial viewUp and viewRight for volume viewports
|
||||
const initialVolumeOrientationRef = useRef<{
|
||||
initialViewUp: number[] | null;
|
||||
initialViewRight: number[] | null;
|
||||
}>({
|
||||
initialViewUp: null,
|
||||
initialViewRight: null,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
initialVolumeOrientationRef.current.initialViewUp = null;
|
||||
initialVolumeOrientationRef.current.initialViewRight = null;
|
||||
|
||||
if (viewportData?.viewportType !== 'stack' && element && getEnabledElement(element)) {
|
||||
const { viewport } = getEnabledElement(element);
|
||||
const { viewUp, viewPlaneNormal } = viewport.getCamera();
|
||||
|
||||
const viewRight = vec3.create();
|
||||
vec3.cross(viewRight, viewUp, viewPlaneNormal);
|
||||
|
||||
initialVolumeOrientationRef.current.initialViewUp = [...viewUp];
|
||||
initialVolumeOrientationRef.current.initialViewRight = [...viewRight];
|
||||
}
|
||||
}, [element, viewportData]);
|
||||
|
||||
useEffect(() => {
|
||||
const cameraModifiedListener = (evt: Types.EventTypes.CameraModifiedEvent) => {
|
||||
const { previousCamera, camera } = evt.detail;
|
||||
|
||||
const { rotation } = camera;
|
||||
if (rotation !== undefined) {
|
||||
setRotation(rotation);
|
||||
}
|
||||
|
||||
if (
|
||||
camera.flipHorizontal !== undefined &&
|
||||
previousCamera.flipHorizontal !== camera.flipHorizontal
|
||||
) {
|
||||
setFlipHorizontal(camera.flipHorizontal);
|
||||
}
|
||||
|
||||
if (
|
||||
camera.flipVertical !== undefined &&
|
||||
previousCamera.flipVertical !== camera.flipVertical
|
||||
) {
|
||||
setFlipVertical(camera.flipVertical);
|
||||
}
|
||||
};
|
||||
|
||||
const cameraModifiedListener = () => setCameraModifiedTime(Date.now());
|
||||
element.addEventListener(Enums.Events.CAMERA_MODIFIED, cameraModifiedListener);
|
||||
|
||||
return () => {
|
||||
element.removeEventListener(Enums.Events.CAMERA_MODIFIED, cameraModifiedListener);
|
||||
};
|
||||
}, []);
|
||||
}, [element]);
|
||||
|
||||
const markers = useMemo(() => {
|
||||
if (!viewportData) {
|
||||
if (!viewportData || cameraModifiedTime === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!element || !getEnabledElement(element)) {
|
||||
console.log(`ViewportOrientationMarkers :: Viewport element not enabled (${viewportId})`);
|
||||
return '';
|
||||
}
|
||||
|
||||
const ohifViewport = cornerstoneViewportService.getViewportInfo(viewportId);
|
||||
|
||||
if (!ohifViewport) {
|
||||
console.log(`ViewportOrientationMarkers :: No viewport (${viewportId})`);
|
||||
return '';
|
||||
}
|
||||
|
||||
let rowCosines, columnCosines, isDefaultValueSetForRowCosine, isDefaultValueSetForColumnCosine;
|
||||
if (viewportData.viewportType === 'stack') {
|
||||
const imageIndex = imageSliceData.imageIndex;
|
||||
const imageId = viewportData.data[0].imageIds?.[imageIndex];
|
||||
@@ -100,58 +55,25 @@ function ViewportOrientationMarkers({
|
||||
return false;
|
||||
}
|
||||
|
||||
({
|
||||
rowCosines,
|
||||
columnCosines,
|
||||
isDefaultValueSetForColumnCosine,
|
||||
isDefaultValueSetForColumnCosine,
|
||||
} = metaData.get('imagePlaneModule', imageId) || {});
|
||||
} else {
|
||||
if (!element || !getEnabledElement(element)) {
|
||||
return '';
|
||||
}
|
||||
const { isDefaultValueSetForRowCosine, isDefaultValueSetForColumnCosine } =
|
||||
metaData.get('imagePlaneModule', imageId) || {};
|
||||
|
||||
if (
|
||||
initialVolumeOrientationRef.current.initialViewUp &&
|
||||
initialVolumeOrientationRef.current.initialViewRight
|
||||
) {
|
||||
// Use initial orientation values for consistency, even as the camera changes
|
||||
columnCosines = [
|
||||
-initialVolumeOrientationRef.current.initialViewUp[0],
|
||||
-initialVolumeOrientationRef.current.initialViewUp[1],
|
||||
-initialVolumeOrientationRef.current.initialViewUp[2],
|
||||
];
|
||||
rowCosines = initialVolumeOrientationRef.current.initialViewRight;
|
||||
} else {
|
||||
console.warn('ViewportOrientationMarkers::No initial orientation values');
|
||||
if (isDefaultValueSetForColumnCosine || isDefaultValueSetForRowCosine) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!rowCosines ||
|
||||
!columnCosines ||
|
||||
rotation === undefined ||
|
||||
isDefaultValueSetForRowCosine ||
|
||||
isDefaultValueSetForColumnCosine
|
||||
) {
|
||||
return '';
|
||||
}
|
||||
const { viewport } = getEnabledElement(element);
|
||||
const p00 = viewport.canvasToWorld([0, 0]);
|
||||
const p10 = viewport.canvasToWorld([1, 0]);
|
||||
const p01 = viewport.canvasToWorld([0, 1]);
|
||||
const rowCosines = vec3.sub(vec3.create(), p10, p00);
|
||||
const columnCosines = vec3.sub(vec3.create(), p01, p00);
|
||||
|
||||
const markers = _getOrientationMarkers(
|
||||
rowCosines,
|
||||
columnCosines,
|
||||
rotation,
|
||||
flipVertical,
|
||||
flipHorizontal
|
||||
);
|
||||
vec3.normalize(rowCosines, rowCosines);
|
||||
vec3.normalize(columnCosines, columnCosines);
|
||||
|
||||
const ohifViewport = cornerstoneViewportService.getViewportInfo(viewportId);
|
||||
|
||||
if (!ohifViewport) {
|
||||
console.log('ViewportOrientationMarkers::No viewport');
|
||||
return null;
|
||||
}
|
||||
const markers = _getOrientationMarkers(rowCosines, columnCosines);
|
||||
|
||||
return orientationMarkers.map((m, index) => (
|
||||
<div
|
||||
@@ -168,16 +90,7 @@ function ViewportOrientationMarkers({
|
||||
<div className="orientation-marker-value">{markers[m]}</div>
|
||||
</div>
|
||||
));
|
||||
}, [
|
||||
viewportData,
|
||||
imageSliceData,
|
||||
rotation,
|
||||
flipVertical,
|
||||
flipHorizontal,
|
||||
orientationMarkers,
|
||||
element,
|
||||
isLight,
|
||||
]);
|
||||
}, [viewportData, imageSliceData, cameraModifiedTime, orientationMarkers, element, isLight]);
|
||||
|
||||
return <div className="ViewportOrientationMarkers select-none">{markers}</div>;
|
||||
}
|
||||
@@ -189,10 +102,8 @@ function ViewportOrientationMarkers({
|
||||
*
|
||||
* @param {*} rowCosines
|
||||
* @param {*} columnCosines
|
||||
* @param {*} rotation in degrees
|
||||
* @returns
|
||||
*/
|
||||
function _getOrientationMarkers(rowCosines, columnCosines, rotation, flipVertical, flipHorizontal) {
|
||||
function _getOrientationMarkers(rowCosines, columnCosines) {
|
||||
const rowString = getOrientationStringLPS(rowCosines);
|
||||
const columnString = getOrientationStringLPS(columnCosines);
|
||||
const oppositeRowString = invertOrientationStringLPS(rowString);
|
||||
@@ -205,43 +116,6 @@ function _getOrientationMarkers(rowCosines, columnCosines, rotation, flipVertica
|
||||
bottom: columnString,
|
||||
};
|
||||
|
||||
// If any vertical or horizontal flips are applied, change the orientation strings ahead of
|
||||
// the rotation applications
|
||||
if (flipVertical) {
|
||||
markers.top = invertOrientationStringLPS(markers.top);
|
||||
markers.bottom = invertOrientationStringLPS(markers.bottom);
|
||||
}
|
||||
|
||||
if (flipHorizontal) {
|
||||
markers.left = invertOrientationStringLPS(markers.left);
|
||||
markers.right = invertOrientationStringLPS(markers.right);
|
||||
}
|
||||
|
||||
// Swap the labels accordingly if the viewport has been rotated
|
||||
// This could be done in a more complex way for intermediate rotation values (e.g. 45 degrees)
|
||||
if (rotation === 90 || rotation === -270) {
|
||||
return {
|
||||
top: markers.left,
|
||||
left: invertOrientationStringLPS(markers.top),
|
||||
right: invertOrientationStringLPS(markers.bottom),
|
||||
bottom: markers.right, // left
|
||||
};
|
||||
} else if (rotation === -90 || rotation === 270) {
|
||||
return {
|
||||
top: invertOrientationStringLPS(markers.left),
|
||||
left: markers.top,
|
||||
bottom: markers.left,
|
||||
right: markers.bottom,
|
||||
};
|
||||
} else if (rotation === 180 || rotation === -180) {
|
||||
return {
|
||||
top: invertOrientationStringLPS(markers.top),
|
||||
left: invertOrientationStringLPS(markers.left),
|
||||
bottom: invertOrientationStringLPS(markers.bottom),
|
||||
right: invertOrientationStringLPS(markers.right),
|
||||
};
|
||||
}
|
||||
|
||||
return markers;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,9 @@ import { updateSegmentBidirectionalStats } from './utils/updateSegmentationStats
|
||||
import { generateSegmentationCSVReport } from './utils/generateSegmentationCSVReport';
|
||||
import { getUpdatedViewportsForSegmentation } from './utils/hydrationUtils';
|
||||
import { SegmentationRepresentations } from '@cornerstonejs/tools/enums';
|
||||
import { isMeasurementWithinViewport } from './utils/isMeasurementWithinViewport';
|
||||
import { getCenterExtent } from './utils/getCenterExtent';
|
||||
import { EasingFunctionEnum } from './utils/transitions';
|
||||
|
||||
const { DefaultHistoryMemo } = csUtils.HistoryMemo;
|
||||
const toggleSyncFunctions = {
|
||||
@@ -99,6 +102,7 @@ let segmentAIEnabled = false;
|
||||
function commandsModule({
|
||||
servicesManager,
|
||||
commandsManager,
|
||||
extensionManager,
|
||||
}: OhifTypes.Extensions.ExtensionParams): OhifTypes.Extensions.CommandsModule {
|
||||
const {
|
||||
viewportGridService,
|
||||
@@ -142,6 +146,91 @@ function commandsModule({
|
||||
}
|
||||
|
||||
const actions = {
|
||||
jumpToMeasurementViewport: ({ annotationUID, measurement }) => {
|
||||
cornerstoneTools.annotation.selection.setAnnotationSelected(annotationUID, true);
|
||||
const { metadata } = measurement;
|
||||
|
||||
const activeViewportId = viewportGridService.getActiveViewportId();
|
||||
// Finds the best viewport to jump to for showing the annotation view reference
|
||||
// This may be different from active if there is a viewport already showing the display set.
|
||||
const viewportId = cornerstoneViewportService.findNavigationCompatibleViewportId(
|
||||
activeViewportId,
|
||||
metadata
|
||||
);
|
||||
if (viewportId) {
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
viewport.setViewReference(metadata);
|
||||
viewport.render();
|
||||
|
||||
/**
|
||||
* If the measurement is not visible inside the current viewport,
|
||||
* we need to move the camera to the measurement.
|
||||
*/
|
||||
if (!isMeasurementWithinViewport(viewport, measurement)) {
|
||||
const camera = viewport.getCamera();
|
||||
const { focalPoint: cameraFocalPoint, position: cameraPosition } = camera;
|
||||
const { center, extent } = getCenterExtent(measurement);
|
||||
const position = vec3.sub(vec3.create(), cameraPosition, cameraFocalPoint);
|
||||
vec3.add(position, position, center);
|
||||
viewport.setCamera({ focalPoint: center, position: position as any });
|
||||
/** Zoom out if the measurement is too large */
|
||||
const measurementSize = vec3.dist(extent.min, extent.max);
|
||||
if (measurementSize > camera.parallelScale) {
|
||||
const scaleFactor = measurementSize / camera.parallelScale;
|
||||
viewport.setZoom(viewport.getZoom() / scaleFactor);
|
||||
}
|
||||
viewport.render();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const { displaySetInstanceUID: referencedDisplaySetInstanceUID } = measurement;
|
||||
if (!referencedDisplaySetInstanceUID) {
|
||||
console.warn('ViewportGrid::No display set found in', measurement);
|
||||
return;
|
||||
}
|
||||
|
||||
// Finds the viewport to update to show the given displayset/orientation.
|
||||
// This will choose a view already containing the measurement display set
|
||||
// if possible, otherwise will fallback to the active.
|
||||
const viewportToUpdate = cornerstoneViewportService.findUpdateableViewportConfiguration(
|
||||
activeViewportId,
|
||||
measurement
|
||||
);
|
||||
|
||||
if (!viewportToUpdate) {
|
||||
console.warn('Unable to find a viewport to show this in');
|
||||
return;
|
||||
}
|
||||
const updatedViewports = hangingProtocolService.getViewportsRequireUpdate(
|
||||
viewportToUpdate.viewportId,
|
||||
referencedDisplaySetInstanceUID
|
||||
);
|
||||
|
||||
if (!updatedViewports?.[0]) {
|
||||
console.warn(
|
||||
'ViewportGrid::Unable to navigate to viewport containing',
|
||||
referencedDisplaySetInstanceUID
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
updatedViewports[0].viewportOptions = viewportToUpdate.viewportOptions;
|
||||
|
||||
// Update stored position presentation
|
||||
commandsManager.run('updateStoredPositionPresentation', {
|
||||
viewportId: viewportToUpdate.viewportId,
|
||||
displaySetInstanceUIDs: [referencedDisplaySetInstanceUID],
|
||||
referencedImageId: measurement.referencedImageId,
|
||||
options: {
|
||||
...measurement.metadata,
|
||||
},
|
||||
});
|
||||
|
||||
commandsManager.run('setDisplaySetsForViewports', { viewportsToUpdate: updatedViewports });
|
||||
},
|
||||
|
||||
hydrateSecondaryDisplaySet: async ({ displaySet, viewportId }) => {
|
||||
if (!displaySet) {
|
||||
return;
|
||||
@@ -324,6 +413,8 @@ function commandsModule({
|
||||
type,
|
||||
});
|
||||
},
|
||||
|
||||
/** Stores the changed position presentation */
|
||||
updateStoredPositionPresentation: ({
|
||||
viewportId,
|
||||
displaySetInstanceUIDs,
|
||||
@@ -347,22 +438,23 @@ function commandsModule({
|
||||
([key, value]) => {
|
||||
return (
|
||||
displaySetInstanceUIDs.every(uid => key.includes(uid)) &&
|
||||
value.viewportId === viewportId
|
||||
value?.viewportId === viewportId
|
||||
);
|
||||
}
|
||||
)?.[0];
|
||||
}
|
||||
|
||||
// Create presentation data with referencedImageId and options if provided
|
||||
const presentationData = referencedImageId
|
||||
? {
|
||||
...presentations.positionPresentation,
|
||||
viewReference: {
|
||||
referencedImageId,
|
||||
...options,
|
||||
},
|
||||
}
|
||||
: presentations.positionPresentation;
|
||||
const presentationData =
|
||||
referencedImageId || options?.FrameOfReferenceUID
|
||||
? {
|
||||
...presentations.positionPresentation,
|
||||
viewReference: {
|
||||
referencedImageId,
|
||||
...options,
|
||||
},
|
||||
}
|
||||
: presentations.positionPresentation;
|
||||
|
||||
if (previousReferencedDisplaySetStoreKey) {
|
||||
setPositionPresentation(previousReferencedDisplaySetStoreKey, presentationData);
|
||||
@@ -426,8 +518,8 @@ function commandsModule({
|
||||
if (!labelConfig) {
|
||||
const label = await callInputDialog({
|
||||
uiDialogService,
|
||||
title: 'Edit Measurement Label',
|
||||
placeholder: measurement.label || 'Enter new label',
|
||||
title: i18n.t('Tools:Edit Measurement Label'),
|
||||
placeholder: measurement.label || i18n.t('Tools:Enter new label'),
|
||||
defaultValue: measurement.label,
|
||||
});
|
||||
|
||||
@@ -634,10 +726,22 @@ function commandsModule({
|
||||
|
||||
viewportGridService.setActiveViewportId(viewportId);
|
||||
},
|
||||
arrowTextCallback: async ({ callback }) => {
|
||||
arrowTextCallback: async ({ callback, data }) => {
|
||||
const labelConfig = customizationService.getCustomization('measurementLabels');
|
||||
const renderContent = customizationService.getCustomization('ui.labellingComponent');
|
||||
|
||||
if (!labelConfig) {
|
||||
const label = await callInputDialog({
|
||||
uiDialogService,
|
||||
title: i18n.t('Tools:Edit Arrow Text'),
|
||||
placeholder: data?.data?.label || i18n.t('Tools:Enter new text'),
|
||||
defaultValue: data?.data?.label || '',
|
||||
});
|
||||
|
||||
callback?.(label);
|
||||
return;
|
||||
}
|
||||
|
||||
const value = await callInputDialogAutoComplete({
|
||||
uiDialogService,
|
||||
labelConfig,
|
||||
@@ -874,8 +978,8 @@ function commandsModule({
|
||||
if (!cornerstoneViewportService.getCornerstoneViewport(activeViewportId)) {
|
||||
// Cannot download a non-cornerstone viewport (image).
|
||||
uiNotificationService.show({
|
||||
title: 'Download Image',
|
||||
message: 'Image cannot be downloaded',
|
||||
title: i18n.t('Tools:Download Image'),
|
||||
message: i18n.t('Tools:Image cannot be downloaded'),
|
||||
type: 'error',
|
||||
});
|
||||
return;
|
||||
@@ -886,7 +990,7 @@ function commandsModule({
|
||||
if (uiModalService) {
|
||||
uiModalService.show({
|
||||
content: CornerstoneViewportDownloadForm,
|
||||
title: 'Download High Quality Image',
|
||||
title: i18n.t('Tools:Download High Quality Image'),
|
||||
contentProps: {
|
||||
activeViewportId,
|
||||
cornerstoneViewportService,
|
||||
@@ -1350,7 +1454,7 @@ function commandsModule({
|
||||
|
||||
const segs = segmentationService.getSegmentations();
|
||||
|
||||
const label = options.label || `Segmentation ${segs.length + 1}`;
|
||||
const label = options.label || `${i18n.t('Tools:Segmentation')} ${segs.length + 1}`;
|
||||
const segmentationId = options.segmentationId || `${csUtils.uuidv4()}`;
|
||||
|
||||
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||
@@ -1364,7 +1468,7 @@ function commandsModule({
|
||||
segments: options.createInitialSegment
|
||||
? {
|
||||
1: {
|
||||
label: `${i18n.t('Segment')} 1`,
|
||||
label: `${i18n.t('Tools:Segment')} 1`,
|
||||
active: true,
|
||||
},
|
||||
}
|
||||
@@ -1415,7 +1519,33 @@ function commandsModule({
|
||||
segmentationId
|
||||
);
|
||||
segmentationService.setActiveSegment(segmentationId, segmentIndex);
|
||||
segmentationService.jumpToSegmentCenter(segmentationId, segmentIndex);
|
||||
|
||||
const { highlightAlpha, highlightSegment, animationLength, animationFunctionType } =
|
||||
(customizationService.getCustomization(
|
||||
'panelSegmentation.jumpToSegmentHighlightAnimationConfig'
|
||||
) as Object as {
|
||||
highlightAlpha?: number;
|
||||
highlightSegment?: boolean;
|
||||
animationLength?: number;
|
||||
animationFunctionType?: EasingFunctionEnum;
|
||||
}) ?? {};
|
||||
|
||||
const validAnimationFunctionType = Object.values(EasingFunctionEnum).includes(
|
||||
animationFunctionType
|
||||
)
|
||||
? animationFunctionType
|
||||
: undefined;
|
||||
|
||||
segmentationService.jumpToSegmentCenter(
|
||||
segmentationId,
|
||||
segmentIndex,
|
||||
undefined,
|
||||
highlightAlpha,
|
||||
highlightSegment,
|
||||
animationLength,
|
||||
undefined,
|
||||
validAnimationFunctionType
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1615,8 +1745,8 @@ function commandsModule({
|
||||
|
||||
callInputDialog({
|
||||
uiDialogService,
|
||||
title: 'Edit Segment Label',
|
||||
placeholder: 'Enter new label',
|
||||
title: i18n.t('Tools:Edit Segment Label'),
|
||||
placeholder: i18n.t('Tools:Enter new label'),
|
||||
defaultValue: segment.label,
|
||||
}).then(label => {
|
||||
segmentationService.setSegmentLabel(segmentationId, segmentIndex, label);
|
||||
@@ -1635,8 +1765,8 @@ function commandsModule({
|
||||
|
||||
callInputDialog({
|
||||
uiDialogService,
|
||||
title: 'Edit Segmentation Label',
|
||||
placeholder: 'Enter new label',
|
||||
title: i18n.t('Tools:Edit Segmentation Label'),
|
||||
placeholder: i18n.t('Tools:Enter new label'),
|
||||
defaultValue: label,
|
||||
}).then(label => {
|
||||
segmentationService.addOrUpdateSegmentation({ segmentationId, label });
|
||||
@@ -1658,7 +1788,7 @@ function commandsModule({
|
||||
|
||||
uiDialogService.show({
|
||||
content: colorPickerDialog,
|
||||
title: 'Segment Color',
|
||||
title: i18n.t('Tools:Segment Color'),
|
||||
contentProps: {
|
||||
value: rgbaColor,
|
||||
onSave: newRgbaColor => {
|
||||
@@ -1728,17 +1858,64 @@ function commandsModule({
|
||||
}
|
||||
});
|
||||
},
|
||||
toggleSegmentLabel: ({ toggle }) => {
|
||||
toggleSegmentLabel: ({ enabled }: { enabled?: boolean }) => {
|
||||
const toolName = cornerstoneTools.SegmentLabelTool.toolName;
|
||||
const toolGroupIds = toolGroupService.getToolGroupIds();
|
||||
|
||||
const isToolOn = toolGroupIds.some(toolGroupId => {
|
||||
const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(toolGroupId);
|
||||
const mode = toolGroup.getToolInstance(toolName)?.mode;
|
||||
return mode === 'Active';
|
||||
});
|
||||
|
||||
const enableTool = enabled !== undefined ? enabled : !isToolOn;
|
||||
|
||||
toolGroupIds.forEach(toolGroupId => {
|
||||
const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(toolGroupId);
|
||||
if (toggle) {
|
||||
toolGroup.setToolActive(cornerstoneTools.SegmentLabelTool.toolName);
|
||||
if (enableTool) {
|
||||
toolGroup.setToolActive(toolName);
|
||||
} else {
|
||||
toolGroup.setToolDisabled(cornerstoneTools.SegmentLabelTool.toolName);
|
||||
toolGroup.setToolDisabled(toolName);
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Used to sync the apps initial state with the config file settings.
|
||||
*
|
||||
* Will mutate the tools object of the given tool group and add the segmentLabelTool to the proper place.
|
||||
*
|
||||
* Use it before initializing the toolGroup with the tools.
|
||||
*/
|
||||
initializeSegmentLabelTool: ({ tools }) => {
|
||||
const appConfig = extensionManager.appConfig;
|
||||
const segmentLabelConfig = appConfig.segmentation?.segmentLabel;
|
||||
|
||||
if (segmentLabelConfig?.enabledByDefault) {
|
||||
const activeTools = tools?.active ?? [];
|
||||
activeTools.push({
|
||||
toolName: toolNames.SegmentLabel,
|
||||
configuration: {
|
||||
hoverTimeout: segmentLabelConfig?.hoverTimeout ?? 1,
|
||||
color: segmentLabelConfig?.labelColor,
|
||||
background: segmentLabelConfig?.background,
|
||||
},
|
||||
});
|
||||
|
||||
tools.active = activeTools;
|
||||
return tools;
|
||||
}
|
||||
|
||||
const disabledTools = tools?.disabled ?? [];
|
||||
disabledTools.push({
|
||||
toolName: toolNames.SegmentLabel,
|
||||
configuration: {
|
||||
hoverTimeout: segmentLabelConfig?.hoverTimeout ?? 1,
|
||||
color: segmentLabelConfig?.labelColor,
|
||||
},
|
||||
});
|
||||
tools.disabled = disabledTools;
|
||||
return tools;
|
||||
},
|
||||
toggleUseCenterSegmentIndex: ({ toggle }) => {
|
||||
let labelmapTools = getLabelmapTools({ toolGroupService });
|
||||
labelmapTools = labelmapTools.filter(tool => !tool.toolName.includes('Eraser'));
|
||||
@@ -1885,6 +2062,9 @@ function commandsModule({
|
||||
const { segmentationService } = servicesManager.services;
|
||||
const { activeViewportId } = viewportGridService.getState();
|
||||
const activeSegmentation = segmentationService.getActiveSegmentation(activeViewportId);
|
||||
if (!activeSegmentation) {
|
||||
return;
|
||||
}
|
||||
segmentationService.addSegment(activeSegmentation.segmentationId);
|
||||
},
|
||||
loadSegmentationDisplaySetsForViewport: ({ viewportId, displaySetInstanceUIDs }) => {
|
||||
@@ -2089,9 +2269,7 @@ function commandsModule({
|
||||
updateMeasurement: {
|
||||
commandFn: actions.updateMeasurement,
|
||||
},
|
||||
jumpToMeasurement: {
|
||||
commandFn: actions.jumpToMeasurement,
|
||||
},
|
||||
jumpToMeasurement: actions.jumpToMeasurement,
|
||||
removeMeasurement: {
|
||||
commandFn: actions.removeMeasurement,
|
||||
},
|
||||
@@ -2351,6 +2529,8 @@ function commandsModule({
|
||||
startRecordingForAnnotationGroup: actions.startRecordingForAnnotationGroup,
|
||||
endRecordingForAnnotationGroup: actions.endRecordingForAnnotationGroup,
|
||||
toggleSegmentLabel: actions.toggleSegmentLabel,
|
||||
jumpToMeasurementViewport: actions.jumpToMeasurementViewport,
|
||||
initializeSegmentLabelTool: actions.initializeSegmentLabelTool,
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -55,7 +55,7 @@ const DEFAULT_TYPES = [GroupAccordion, Content, Trigger];
|
||||
* measurements panel for a practical, working example.
|
||||
*/
|
||||
export function AccordionGroup(props) {
|
||||
const { grouping, items, children, sourceChildren, type } = props;
|
||||
const { grouping, items, children, sourceChildren } = props;
|
||||
const childProps = useSystem();
|
||||
let defaultValue = props.defaultValue;
|
||||
const groups = grouping.groupingFunction(items, grouping, childProps);
|
||||
|
||||
+43
-10
@@ -1,6 +1,20 @@
|
||||
import { useToolbar, useViewportMousePosition } from '@ohif/core/src/hooks';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import { useViewportRendering } from '../../hooks';
|
||||
import { ButtonLocation } from '@ohif/core/src/services/ToolBarService/ToolbarService';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const mouseNearControlsRanges = {
|
||||
[ButtonLocation.TopMiddle]: { minX: 0, minY: 0, maxX: 1, maxY: 0.1 },
|
||||
[ButtonLocation.BottomMiddle]: { minX: 0, minY: 0.9, maxX: 1, maxY: 1 },
|
||||
[ButtonLocation.LeftMiddle]: { minX: 0, minY: 0, maxX: 0.1, maxY: 1 },
|
||||
[ButtonLocation.RightMiddle]: { minX: 0.9, minY: 0, maxX: 1, maxY: 1 },
|
||||
};
|
||||
|
||||
const getFlexDirectionClassName = (location: ButtonLocation) =>
|
||||
location === ButtonLocation.LeftMiddle || location === ButtonLocation.RightMiddle
|
||||
? 'flex-col'
|
||||
: 'flex-row';
|
||||
|
||||
function AdvancedRenderingControls({
|
||||
viewportId,
|
||||
@@ -24,10 +38,11 @@ function AdvancedRenderingControls({
|
||||
});
|
||||
|
||||
const mousePosition = useViewportMousePosition(viewportId);
|
||||
const [isAtBottom, setIsAtBottom] = useState(false);
|
||||
const [isMouseNearControls, setIsMouseNearControls] = useState(false);
|
||||
const [showAllIcons, setShowAllIcons] = useState(true);
|
||||
const firstMountRef = useRef(true);
|
||||
const { hasColorbar } = useViewportRendering(viewportId);
|
||||
const [isAnItemOpen, setIsAnItemOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (firstMountRef.current) {
|
||||
@@ -43,13 +58,30 @@ function AdvancedRenderingControls({
|
||||
|
||||
useEffect(() => {
|
||||
if (!showAllIcons && mousePosition.isInViewport) {
|
||||
if (mousePosition.isInBottomPercentage(10)) {
|
||||
setIsAtBottom(true);
|
||||
const mouseHoverLocation = mouseNearControlsRanges[location];
|
||||
if (mousePosition.isWithinNormalizedBox(mouseHoverLocation)) {
|
||||
setIsMouseNearControls(true);
|
||||
} else {
|
||||
setIsAtBottom(false);
|
||||
setIsMouseNearControls(false);
|
||||
}
|
||||
}
|
||||
}, [mousePosition, showAllIcons]);
|
||||
}, [location, mousePosition, showAllIcons]);
|
||||
|
||||
const handleOnItemOpen = useCallback(
|
||||
(id, viewportId) => {
|
||||
openItem(id, viewportId);
|
||||
setIsAnItemOpen(true);
|
||||
},
|
||||
[openItem, setIsAnItemOpen]
|
||||
);
|
||||
|
||||
const handleOnItemClose = useCallback(
|
||||
(id, viewportId) => {
|
||||
closeItem(id, viewportId);
|
||||
setIsAnItemOpen(false);
|
||||
},
|
||||
[closeItem, setIsAnItemOpen]
|
||||
);
|
||||
|
||||
if (!toolbarButtons?.length) {
|
||||
return null;
|
||||
@@ -60,7 +92,7 @@ function AdvancedRenderingControls({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-row gap-2">
|
||||
<div className={classNames('flex gap-2', getFlexDirectionClassName(location))}>
|
||||
{toolbarButtons.map(toolDef => {
|
||||
if (!toolDef) {
|
||||
return null;
|
||||
@@ -73,8 +105,8 @@ function AdvancedRenderingControls({
|
||||
...componentProps,
|
||||
isOpen: isItemOpen(id, viewportId),
|
||||
isLocked: isItemLocked(id, viewportId),
|
||||
onOpen: () => openItem(id, viewportId),
|
||||
onClose: () => closeItem(id, viewportId),
|
||||
onOpen: () => handleOnItemOpen(id, viewportId),
|
||||
onClose: () => handleOnItemClose(id, viewportId),
|
||||
onToggleLock: () => toggleLock(id, viewportId),
|
||||
viewportId,
|
||||
};
|
||||
@@ -97,7 +129,8 @@ function AdvancedRenderingControls({
|
||||
|
||||
// Always show all icons on first mount for 3 seconds
|
||||
// After that, always show Colorbar, show others only when mouse is at bottom
|
||||
const shouldBeVisible = showAllIcons || id === 'Colorbar' || isAtBottom;
|
||||
const shouldBeVisible =
|
||||
isAnItemOpen || showAllIcons || id === 'Colorbar' || isMouseNearControls;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -259,22 +259,24 @@ function DicomUploadProgress({
|
||||
}, [getPercentCompleteRounded, percentComplete]);
|
||||
|
||||
/**
|
||||
* Gets the css style for the 'n of m' (files completed) text. The only css attribute
|
||||
* of the style is width such that the 'n of m' is always a fixed width and thus
|
||||
* as each file completes uploading the text on screen does not constantly shift
|
||||
* left and right.
|
||||
* Gets the CSS style for the 'n of m' (files completed) text.
|
||||
* The width changes according to numFilesCompleted and can vary,
|
||||
* e.g. "1 of 200", "10 of 200", "100 of 200" all have differents width.
|
||||
*/
|
||||
const getNofMFilesStyle = useCallback(() => {
|
||||
// the number of digits accounts for the digits being on each side of the ' of '
|
||||
const numDigits = 2 * dicomFileUploaderArr.length.toString().length;
|
||||
// the number of digits + 2 spaces and 2 characters for ' of '
|
||||
const numChars = numDigits + 4;
|
||||
const numDigits =
|
||||
numFilesCompleted.toString().length + dicomFileUploaderArr.length.toString().length;
|
||||
// The number of digits + 3 additional characters (accounts for ' of ').
|
||||
// Even though intuitively 4 should be better, this is the most accurate width.
|
||||
// The font may play a part in this discrepancy.
|
||||
const numChars = numDigits + 3;
|
||||
return { width: `${numChars}ch` };
|
||||
}, []);
|
||||
}, [numFilesCompleted]);
|
||||
|
||||
const getNumCompletedAndTimeRemainingComponent = (): ReactElement => {
|
||||
return (
|
||||
<div className="bg-primary-dark flex h-14 items-center px-1 pb-4 text-lg">
|
||||
<div className="bg-primary-dark flex h-14 items-center px-1 pb-4 text-lg text-white">
|
||||
{numFilesCompleted === dicomFileUploaderArr.length ? (
|
||||
<>
|
||||
<span className={NO_WRAP_ELLIPSIS_CLASS_NAMES}>{`${dicomFileUploaderArr.length} ${
|
||||
@@ -290,21 +292,24 @@ function DicomUploadProgress({
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className="flex flex-wrap">
|
||||
<span
|
||||
style={getNofMFilesStyle()}
|
||||
className={classNames(NO_WRAP_ELLIPSIS_CLASS_NAMES, 'text-right')}
|
||||
>
|
||||
{`${numFilesCompleted} of ${dicomFileUploaderArr.length}`}
|
||||
</span>
|
||||
<span className={NO_WRAP_ELLIPSIS_CLASS_NAMES}>{' files completed.'}</span>
|
||||
<br />
|
||||
<span>
|
||||
{timeRemaining ? `Less than ${getFormattedTimeRemaining()} remaining. ` : ''}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<span
|
||||
style={getNofMFilesStyle()}
|
||||
className={classNames(NO_WRAP_ELLIPSIS_CLASS_NAMES, 'text-end')}
|
||||
>
|
||||
{`${numFilesCompleted} of ${dicomFileUploaderArr.length}`}
|
||||
</span>
|
||||
<span className={NO_WRAP_ELLIPSIS_CLASS_NAMES}>{' files completed.'} </span>
|
||||
<span className={NO_WRAP_ELLIPSIS_CLASS_NAMES}>
|
||||
{timeRemaining ? `Less than ${getFormattedTimeRemaining()} remaining. ` : ''}
|
||||
</span>
|
||||
<span
|
||||
className={classNames(
|
||||
NO_WRAP_ELLIPSIS_CLASS_NAMES,
|
||||
'text-primary hover:text-primary-light active:text-aqua-pale ml-auto cursor-pointer'
|
||||
)}
|
||||
className={
|
||||
'text-primary hover:text-primary-lightactive:text-aqua-pale ml-auto cursor-pointer whitespace-nowrap'
|
||||
}
|
||||
onClick={cancelAllUploads}
|
||||
>
|
||||
Cancel All Uploads
|
||||
@@ -354,7 +359,7 @@ function DicomUploadProgress({
|
||||
></ProgressLoadingBar>
|
||||
</div>
|
||||
<div className="ml-1 flex w-24 items-center">
|
||||
<div className="w-10 text-right">{`${getPercentCompleteRounded()}%`}</div>
|
||||
<div className="w-10 text-right text-foreground">{`${getPercentCompleteRounded()}%`}</div>
|
||||
{getShowFailedOnlyIconComponent()}
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -75,7 +75,7 @@ const DicomUploadProgressItem = memo(
|
||||
<div className="self-top flex w-0 shrink grow flex-col gap-1">
|
||||
<div className="flex gap-4">
|
||||
<div className="flex w-6 shrink-0 items-center justify-center">{getStatusIcon()}</div>
|
||||
<div className="overflow-hidden text-ellipsis whitespace-nowrap">
|
||||
<div className="overflow-hidden text-ellipsis whitespace-nowrap text-white">
|
||||
{dicomFileUploader.getFileName()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,13 +17,13 @@ function ModalityLoadBadge({ viewportId }: { viewportId: string }) {
|
||||
|
||||
const { isTracked, isLocked } = useMeasurementTracking({ viewportId });
|
||||
|
||||
const { backgroundDisplaySet, overlayDisplaySets } = useViewportDisplaySets(viewportId);
|
||||
const { backgroundDisplaySet } = useViewportDisplaySets(viewportId);
|
||||
|
||||
const [specialDisplaySet, setSpecialDisplaySet] = useState(null);
|
||||
|
||||
const allDisplaySets = useMemo(() => {
|
||||
return [backgroundDisplaySet, ...overlayDisplaySets].filter(Boolean);
|
||||
}, [backgroundDisplaySet, overlayDisplaySets]);
|
||||
return [backgroundDisplaySet].filter(Boolean);
|
||||
}, [backgroundDisplaySet]);
|
||||
|
||||
useEffect(() => {
|
||||
const displaySet = allDisplaySets.find(ds => ds.isOverlayDisplaySet || ds?.Modality === 'SR');
|
||||
@@ -120,7 +120,10 @@ function ModalityLoadBadge({ viewportId }: { viewportId: string }) {
|
||||
const StatusArea = () => {
|
||||
if (!statusInfo.isHydrated) {
|
||||
return (
|
||||
<div className="flex h-6 cursor-default text-sm leading-6 text-white">
|
||||
<div
|
||||
data-cy={`ModalityLoadBadge-${viewportId}`}
|
||||
className="flex h-6 cursor-default text-sm leading-6 text-white"
|
||||
>
|
||||
<div className="bg-customgray-100 flex min-w-[45px] items-center rounded-l-xl rounded-r p-1">
|
||||
<StatusIcon />
|
||||
<span className="ml-1">{statusInfo.type}</span>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { useActiveViewportDisplaySets, useSystem, utils } from '@ohif/core';
|
||||
// import { AccordionContent, AccordionItem, AccordionTrigger } from '@ohif/ui-next';
|
||||
import { useActiveViewportDisplaySets, utils } from '@ohif/core';
|
||||
|
||||
import { AccordionGroup } from './AccordionGroup';
|
||||
import MeasurementsOrAdditionalFindings from './MeasurementsOrAdditionalFindings';
|
||||
@@ -24,36 +23,38 @@ export const groupByStudy = (items, grouping, childProps) => {
|
||||
|
||||
let firstSelected, firstGroup;
|
||||
|
||||
items.forEach(item => {
|
||||
const studyUID = getItemStudyInstanceUID(item);
|
||||
if (!groups.has(studyUID)) {
|
||||
const items = [];
|
||||
const filter = MeasurementFilters.filterAnd(
|
||||
MeasurementFilters.filterMeasurementsByStudyUID(studyUID),
|
||||
grouping.filter
|
||||
);
|
||||
const group = {
|
||||
...grouping,
|
||||
items,
|
||||
displayMeasurements: items,
|
||||
key: studyUID,
|
||||
isSelected: studyUID === activeStudyUID,
|
||||
StudyInstanceUID: studyUID,
|
||||
filter,
|
||||
measurementFilter: filter,
|
||||
};
|
||||
if (group.isSelected && !firstSelected) {
|
||||
firstSelected = group;
|
||||
items
|
||||
.filter(item => item.displaySetInstanceUID)
|
||||
.forEach(item => {
|
||||
const studyUID = getItemStudyInstanceUID(item);
|
||||
if (!groups.has(studyUID)) {
|
||||
const items = [];
|
||||
const filter = MeasurementFilters.filterAnd(
|
||||
MeasurementFilters.filterMeasurementsByStudyUID(studyUID),
|
||||
grouping.filter
|
||||
);
|
||||
const group = {
|
||||
...grouping,
|
||||
items,
|
||||
displayMeasurements: items,
|
||||
key: studyUID,
|
||||
isSelected: studyUID === activeStudyUID,
|
||||
StudyInstanceUID: studyUID,
|
||||
filter,
|
||||
measurementFilter: filter,
|
||||
};
|
||||
if (group.isSelected && !firstSelected) {
|
||||
firstSelected = group;
|
||||
}
|
||||
firstGroup ||= group;
|
||||
groups.set(studyUID, group);
|
||||
}
|
||||
firstGroup ||= group;
|
||||
groups.set(studyUID, group);
|
||||
}
|
||||
if (!firstSelected && firstGroup) {
|
||||
firstGroup.isSelected = true;
|
||||
}
|
||||
const group = groups.get(studyUID);
|
||||
group.items.push(item);
|
||||
});
|
||||
if (!firstSelected && firstGroup) {
|
||||
firstGroup.isSelected = true;
|
||||
}
|
||||
const group = groups.get(studyUID);
|
||||
group.items.push(item);
|
||||
});
|
||||
|
||||
return groups;
|
||||
};
|
||||
@@ -61,8 +62,7 @@ export const groupByStudy = (items, grouping, childProps) => {
|
||||
export function StudyMeasurements(props): React.ReactNode {
|
||||
const { items, grouping = {}, children } = props;
|
||||
|
||||
const system = useSystem();
|
||||
const activeDisplaySets = useActiveViewportDisplaySets(system);
|
||||
const activeDisplaySets = useActiveViewportDisplaySets();
|
||||
const activeStudyUID = activeDisplaySets?.[0]?.StudyInstanceUID;
|
||||
|
||||
return (
|
||||
|
||||
@@ -27,6 +27,9 @@ type ColorbarProps = {
|
||||
numColorbars: number;
|
||||
};
|
||||
|
||||
export const isHorizontal = (position: ColorbarPositionType): boolean =>
|
||||
position === 'top' || position === 'bottom';
|
||||
|
||||
/**
|
||||
* ViewportColorbar Component
|
||||
* A React wrapper for the cornerstone ViewportColorbar that adds a close button
|
||||
@@ -143,8 +146,9 @@ const ViewportColorbar = memo(function ViewportColorbar({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
pointerEvents: 'auto',
|
||||
minWidth: position === 'bottom' ? width / 2.5 : '17px',
|
||||
minHeight: position === 'bottom' ? '20px' : numColorbars === 1 ? height / 3 : height / 4,
|
||||
minWidth: isHorizontal(position) ? width / 2.5 : '17px',
|
||||
minHeight: isHorizontal(position) ? '20px' : numColorbars === 1 ? height / 3 : height / 4,
|
||||
height: '1px', // sometimes flex items with min-height need a starting point for its height calculation
|
||||
...positionStylesFromConfig,
|
||||
}}
|
||||
></div>
|
||||
|
||||
+2
-4
@@ -2,7 +2,7 @@ import React, { useEffect, useState, useMemo, memo, useCallback } from 'react';
|
||||
import { useSystem } from '@ohif/core';
|
||||
import { ColorbarCustomization } from '../../types/Colorbar';
|
||||
import type { ColorMapPreset } from '../../types/Colormap';
|
||||
import ViewportColorbar from './ViewportColorbar';
|
||||
import ViewportColorbar, { isHorizontal } from './ViewportColorbar';
|
||||
import useViewportRendering from '../../hooks/useViewportRendering';
|
||||
import { useViewportDisplaySets } from '../../hooks/useViewportDisplaySets';
|
||||
type ViewportColorbarsContainerProps = {
|
||||
@@ -74,10 +74,8 @@ const ViewportColorbarsContainer = memo(function ViewportColorbarsContainer({
|
||||
return null;
|
||||
}
|
||||
|
||||
const isBottom = position === 'bottom';
|
||||
|
||||
const isSingleViewport = viewportDisplaySets.length === 1;
|
||||
const showFullList = isSingleViewport || !isBottom;
|
||||
const showFullList = isSingleViewport || !isHorizontal(position);
|
||||
|
||||
const colorbarsToUse = showFullList
|
||||
? colorbars
|
||||
|
||||
+95
-35
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { cn, Icons, ToolButton, useIconPresentation } from '@ohif/ui-next';
|
||||
import { cn, Icons, useIconPresentation } from '@ohif/ui-next';
|
||||
import { useSystem } from '@ohif/core';
|
||||
import { Enums } from '@cornerstonejs/core';
|
||||
import { Popover, PopoverTrigger, PopoverContent, Button, useViewportGrid } from '@ohif/ui-next';
|
||||
@@ -22,13 +22,20 @@ function ViewportOrientationMenu({
|
||||
onClose?: () => void;
|
||||
disabled?: boolean;
|
||||
}>) {
|
||||
const { servicesManager, commandsManager } = useSystem();
|
||||
const { cornerstoneViewportService, toolbarService } = servicesManager.services;
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
|
||||
const viewportOrientation = viewportInfo.getOrientation();
|
||||
|
||||
const [gridState] = useViewportGrid();
|
||||
const viewportIdToUse = viewportId || gridState.activeViewportId;
|
||||
const { IconContainer, className: iconClassName, containerProps } = useIconPresentation();
|
||||
const { servicesManager, commandsManager } = useSystem();
|
||||
const { cornerstoneViewportService, toolbarService } = servicesManager.services;
|
||||
const [currentOrientation, setCurrentOrientation] = React.useState<string>(
|
||||
typeof viewportOrientation === 'string' ? viewportOrientation : 'axial'
|
||||
);
|
||||
|
||||
const handleOrientationChange = (orientation: string) => {
|
||||
setCurrentOrientation(orientation);
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportIdToUse);
|
||||
const currentViewportType = viewportInfo?.getViewportType();
|
||||
|
||||
@@ -56,6 +63,9 @@ function ViewportOrientationMenu({
|
||||
case 'coronal':
|
||||
orientationEnum = Enums.OrientationAxis.CORONAL;
|
||||
break;
|
||||
case 'reformat':
|
||||
orientationEnum = Enums.OrientationAxis.REFORMAT;
|
||||
break;
|
||||
default:
|
||||
orientationEnum = Enums.OrientationAxis.ACQUISITION;
|
||||
}
|
||||
@@ -106,7 +116,7 @@ function ViewportOrientationMenu({
|
||||
// Get proper alignment and side based on the location using toolbar service
|
||||
const { align, side } = toolbarService.getAlignAndSide(Number(location));
|
||||
|
||||
const Icon = <Icons.OrientationSwitch className={iconClassName} />;
|
||||
const Icon = React.createElement(getIcon(currentOrientation), { className: iconClassName });
|
||||
return (
|
||||
<Popover
|
||||
open={isOpen}
|
||||
@@ -139,43 +149,93 @@ function ViewportOrientationMenu({
|
||||
</div>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
className="w-[100px] p-1"
|
||||
className="h-[170px] w-[130px] flex-shrink-0 flex-col items-start rounded p-1"
|
||||
align={align}
|
||||
side={side}
|
||||
style={{ left: 0 }}
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="justify-start"
|
||||
onClick={() => handleOrientationChange('axial')}
|
||||
>
|
||||
Axial
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="justify-start"
|
||||
onClick={() => handleOrientationChange('sagittal')}
|
||||
>
|
||||
Sagittal
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="justify-start"
|
||||
onClick={() => handleOrientationChange('coronal')}
|
||||
>
|
||||
Coronal
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="justify-start"
|
||||
onClick={() => handleOrientationChange('acquisition')}
|
||||
>
|
||||
Acquisition
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0"
|
||||
onClick={() => handleOrientationChange('axial')}
|
||||
>
|
||||
<div className="mr-1 flex w-6 items-center justify-start">
|
||||
{currentOrientation === 'axial' ? (
|
||||
<Icons.Checked className="text-primary h-6 w-6" />
|
||||
) : null}
|
||||
</div>
|
||||
<div className="flex-1 text-left">Axial</div>
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0"
|
||||
onClick={() => handleOrientationChange('sagittal')}
|
||||
>
|
||||
<div className="mr-1 flex w-6 items-center justify-start">
|
||||
{currentOrientation === 'sagittal' ? (
|
||||
<Icons.Checked className="text-primary h-6 w-6" />
|
||||
) : null}
|
||||
</div>
|
||||
<div className="flex-1 text-left">Sagittal</div>
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0"
|
||||
onClick={() => handleOrientationChange('coronal')}
|
||||
>
|
||||
<div className="mr-1 flex w-6 items-center justify-start">
|
||||
{currentOrientation === 'coronal' ? (
|
||||
<Icons.Checked className="text-primary h-6 w-6" />
|
||||
) : null}
|
||||
</div>
|
||||
<div className="flex-1 text-left">Coronal</div>
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0"
|
||||
onClick={() => handleOrientationChange('acquisition')}
|
||||
>
|
||||
<div className="mr-1 flex w-6 items-center justify-start">
|
||||
{currentOrientation === 'acquisition' ? (
|
||||
<Icons.Checked className="text-primary h-6 w-6" />
|
||||
) : null}
|
||||
</div>
|
||||
<div className="flex-1 text-left">Acquisition</div>
|
||||
</Button>
|
||||
{/* Divider */}
|
||||
<div className="mx-1 my-2 border-t border-white/20" />
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0"
|
||||
onClick={() => handleOrientationChange('reformat')}
|
||||
>
|
||||
<div className="mr-1 flex w-6 items-center justify-start">
|
||||
{currentOrientation === 'reformat' ? (
|
||||
<Icons.Checked className="text-primary h-6 w-6" />
|
||||
) : null}
|
||||
</div>
|
||||
<div className="flex-1 text-left">Reformat</div>
|
||||
</Button>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
const getIcon = (orientationName: string) => {
|
||||
switch (orientationName.toLowerCase()) {
|
||||
case 'axial':
|
||||
return Icons.OrientationSwitchA;
|
||||
case 'sagittal':
|
||||
return Icons.OrientationSwitchS;
|
||||
case 'coronal':
|
||||
return Icons.OrientationSwitchC;
|
||||
case 'reformat':
|
||||
return Icons.OrientationSwitchR;
|
||||
case 'acquisition':
|
||||
return Icons.OrientationSwitch;
|
||||
default:
|
||||
return Icons.OrientationSwitch;
|
||||
}
|
||||
};
|
||||
|
||||
export default ViewportOrientationMenu;
|
||||
@@ -1,9 +1,11 @@
|
||||
import React, { ReactElement, useCallback } from 'react';
|
||||
import { Switch } from '@ohif/ui-next';
|
||||
import { useViewportRendering } from '../../hooks/useViewportRendering';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export function Colorbar({ viewportId }: { viewportId?: string } = {}): ReactElement {
|
||||
const { hasColorbar, toggleColorbar } = useViewportRendering(viewportId);
|
||||
const { t } = useTranslation('WindowLevelActionMenu');
|
||||
|
||||
const handleToggle = useCallback(() => {
|
||||
toggleColorbar();
|
||||
@@ -16,7 +18,7 @@ export function Colorbar({ viewportId }: { viewportId?: string } = {}): ReactEle
|
||||
className="flex-grow"
|
||||
onClick={handleToggle}
|
||||
>
|
||||
Display Color bar
|
||||
{t('Display Color bar')}
|
||||
</span>
|
||||
<Switch
|
||||
className="ml-2 flex-shrink-0"
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import React, { ReactElement, useEffect, useRef, useState } from 'react';
|
||||
import { AllInOneMenu, ScrollArea, Switch, Tabs, TabsList, TabsTrigger } from '@ohif/ui-next';
|
||||
import { useViewportRendering } from '../../hooks/useViewportRendering';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export function Colormap({ viewportId }: { viewportId?: string } = {}): ReactElement {
|
||||
const { viewportDisplaySets } = useViewportRendering(viewportId);
|
||||
const { t } = useTranslation('WindowLevelActionMenu');
|
||||
|
||||
const [activeDisplaySetUID, setActiveDisplaySetUID] = useState<string | undefined>(
|
||||
viewportDisplaySets?.[0]?.displaySetInstanceUID
|
||||
@@ -74,7 +76,7 @@ export function Colormap({ viewportId }: { viewportId?: string } = {}): ReactEle
|
||||
className="hover:bg-accent flex h-8 w-full flex-shrink-0 cursor-pointer items-center px-2 text-base hover:rounded"
|
||||
onClick={() => setShowPreview(!showPreview)}
|
||||
>
|
||||
<span className="flex-shrink-0">Preview in viewport</span>
|
||||
<span className="flex-shrink-0">{t('Preview in viewport')}</span>
|
||||
<Switch
|
||||
className="ml-auto flex-shrink-0"
|
||||
checked={showPreview}
|
||||
|
||||
+4
-2
@@ -7,6 +7,7 @@ import { WindowLevel } from './WindowLevel';
|
||||
import { VolumeRenderingPresets } from './VolumeRenderingPresets';
|
||||
import { VolumeRenderingOptions } from './VolumeRenderingOptions';
|
||||
import { useViewportRendering } from '../../hooks/useViewportRendering';
|
||||
import i18n from 'i18next';
|
||||
|
||||
export type WindowLevelActionMenuProps = {
|
||||
viewportId: string;
|
||||
@@ -58,6 +59,7 @@ export function WindowLevelActionMenuContent({
|
||||
isVisible={true}
|
||||
align={align}
|
||||
side={side}
|
||||
backLabel={i18n.t('WindowLevelActionMenu:Back to Display Options')}
|
||||
>
|
||||
<AllInOneMenu.ItemPanel>
|
||||
{!is3DVolume && <Colorbar viewportId={viewportId} />}
|
||||
@@ -65,7 +67,7 @@ export function WindowLevelActionMenuContent({
|
||||
{colorbarProperties?.colormaps && !is3DVolume && (
|
||||
<AllInOneMenu.SubMenu
|
||||
key="colorLUTPresets"
|
||||
itemLabel="Color LUT"
|
||||
itemLabel={t('Color LUT')}
|
||||
itemIcon="icon-color-lut"
|
||||
className="flex h-[calc(100%-32px)] flex-col"
|
||||
>
|
||||
@@ -86,7 +88,7 @@ export function WindowLevelActionMenuContent({
|
||||
{volumeRenderingPresets && is3DVolume && <VolumeRenderingPresets viewportId={viewportId} />}
|
||||
|
||||
{volumeRenderingQualityRange && is3DVolume && (
|
||||
<AllInOneMenu.SubMenu itemLabel="Rendering Options">
|
||||
<AllInOneMenu.SubMenu itemLabel={t('Rendering Options')}>
|
||||
<VolumeRenderingOptions viewportId={viewportId} />
|
||||
</AllInOneMenu.SubMenu>
|
||||
)}
|
||||
|
||||
@@ -108,6 +108,7 @@ export const CustomDropdownMenuContent = () => {
|
||||
e.preventDefault();
|
||||
actions.downloadCSVSegmentationReport(segmentationId);
|
||||
}}
|
||||
disabled={!allowExport}
|
||||
>
|
||||
{t('CSV Report')}
|
||||
</DropdownMenuItem>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { ImageModal, FooterAction } from '@ohif/ui-next';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
const MAX_TEXTURE_SIZE = 10000;
|
||||
const DEFAULT_FILENAME = 'image';
|
||||
|
||||
@@ -37,6 +37,7 @@ function ViewportDownloadFormNew({
|
||||
const [showWarningMessage, setShowWarningMessage] = useState(true);
|
||||
const [filename, setFilename] = useState(DEFAULT_FILENAME);
|
||||
const [fileType, setFileType] = useState('jpg');
|
||||
const { t } = useTranslation('CaptureViewportModal');
|
||||
|
||||
useEffect(() => {
|
||||
if (!viewportElement) {
|
||||
@@ -82,7 +83,7 @@ function ViewportDownloadFormNew({
|
||||
value={filename}
|
||||
onChange={e => setFilename(e.target.value)}
|
||||
>
|
||||
File name
|
||||
{t('File name')}
|
||||
</ImageModal.Filename>
|
||||
<ImageModal.Filetype
|
||||
selected={fileType}
|
||||
@@ -109,7 +110,7 @@ function ViewportDownloadFormNew({
|
||||
maxWidth={MAX_TEXTURE_SIZE.toString()}
|
||||
maxHeight={MAX_TEXTURE_SIZE.toString()}
|
||||
>
|
||||
Image size <span className="text-muted-foreground">px</span>
|
||||
{t('Image size')} <span className="text-muted-foreground">px</span>
|
||||
</ImageModal.ImageSize>
|
||||
|
||||
<ImageModal.SwitchOption
|
||||
@@ -117,7 +118,7 @@ function ViewportDownloadFormNew({
|
||||
checked={showAnnotations}
|
||||
onCheckedChange={onAnnotationsChange}
|
||||
>
|
||||
Include annotations
|
||||
{t('Include annotations')}
|
||||
</ImageModal.SwitchOption>
|
||||
{warningState.enabled && (
|
||||
<ImageModal.SwitchOption
|
||||
@@ -125,19 +126,21 @@ function ViewportDownloadFormNew({
|
||||
checked={showWarningMessage}
|
||||
onCheckedChange={setShowWarningMessage}
|
||||
>
|
||||
Include warning message
|
||||
{t('Include warning message')}
|
||||
</ImageModal.SwitchOption>
|
||||
)}
|
||||
<FooterAction className="mt-2">
|
||||
<FooterAction.Right>
|
||||
<FooterAction.Secondary onClick={onClose}>Cancel</FooterAction.Secondary>
|
||||
<FooterAction.Secondary onClick={onClose}>
|
||||
{t('Common:Cancel')}
|
||||
</FooterAction.Secondary>
|
||||
<FooterAction.Primary
|
||||
onClick={() => {
|
||||
onDownload(filename || DEFAULT_FILENAME, fileType);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
Save
|
||||
{t('Common:Save')}
|
||||
</FooterAction.Primary>
|
||||
</FooterAction.Right>
|
||||
</FooterAction>
|
||||
|
||||
@@ -34,15 +34,20 @@ export default {
|
||||
if (!viewportId) {
|
||||
return [];
|
||||
}
|
||||
const displaySetInsaneUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
||||
const displaySetInstanceUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
||||
|
||||
if (!displaySetInsaneUIDs) {
|
||||
if (!displaySetInstanceUIDs) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const displaySets = displaySetInsaneUIDs.map(uid =>
|
||||
displaySetService.getDisplaySetByUID(uid)
|
||||
);
|
||||
const displaySets = displaySetInstanceUIDs.map(uid => {
|
||||
const displaySet = displaySetService.getDisplaySetByUID(uid);
|
||||
const referencedDisplaySetUID = displaySet?.measurements?.[0]?.displaySetInstanceUID;
|
||||
if (displaySet.Modality === 'SR' && referencedDisplaySetUID) {
|
||||
return displaySetService.getDisplaySetByUID(referencedDisplaySetUID);
|
||||
}
|
||||
return displaySet;
|
||||
});
|
||||
|
||||
return hangingProtocols
|
||||
.map(hp => {
|
||||
|
||||
@@ -36,9 +36,9 @@ export default function getSegmentationPanelCustomization({ commandsManager, ser
|
||||
'segmentationToolbox.config': () => {
|
||||
// Get initial states based on current configuration
|
||||
const [previewEdits, setPreviewEdits] = useState(false);
|
||||
const [segmentLabelEnabled, setSegmentLabelEnabled] = useState(false);
|
||||
const [toggleSegmentEnabled, setToggleSegmentEnabled] = useState(false);
|
||||
const [useCenterAsSegmentIndex, setUseCenterAsSegmentIndex] = useState(false);
|
||||
const [shouldShowLabelOnHover, setShouldShowLabelOnHover] = useState(false);
|
||||
const handlePreviewEditsChange = checked => {
|
||||
setPreviewEdits(checked);
|
||||
commandsManager.run('toggleSegmentPreviewEdit', { toggle: checked });
|
||||
@@ -54,19 +54,19 @@ export default function getSegmentationPanelCustomization({ commandsManager, ser
|
||||
commandsManager.run('toggleUseCenterSegmentIndex', { toggle: checked });
|
||||
};
|
||||
|
||||
const handleToggleShowLabelOnHover = checked => {
|
||||
setShouldShowLabelOnHover(checked);
|
||||
commandsManager.run('toggleSegmentLabel', { toggle: checked });
|
||||
const handleSegmentLabelEnabledChange = checked => {
|
||||
setSegmentLabelEnabled(checked);
|
||||
commandsManager.run('toggleSegmentLabel', { enabled: checked });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-muted flex flex-col gap-4 border-b border-b-[2px] border-black px-2 py-3">
|
||||
<div className="bg-muted flex flex-col gap-2 border-b border-b-[2px] border-black px-2 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch
|
||||
checked={previewEdits}
|
||||
onCheckedChange={handlePreviewEditsChange}
|
||||
/>
|
||||
<span className="text-base text-white">Preview edits before creating</span>
|
||||
<span className="text-foreground text-base">Preview edits before creating</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -74,7 +74,7 @@ export default function getSegmentationPanelCustomization({ commandsManager, ser
|
||||
checked={useCenterAsSegmentIndex}
|
||||
onCheckedChange={handleUseCenterAsSegmentIndexChange}
|
||||
/>
|
||||
<span className="text-base text-white">Use center as segment index</span>
|
||||
<span className="text-foreground text-base">Use center as segment index</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -82,15 +82,15 @@ export default function getSegmentationPanelCustomization({ commandsManager, ser
|
||||
checked={toggleSegmentEnabled}
|
||||
onCheckedChange={handleToggleSegmentEnabledChange}
|
||||
/>
|
||||
<span className="text-base text-white">Hover on segment border to activate</span>
|
||||
<span className="text-foreground text-base">Hover on segment border to activate</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch
|
||||
checked={shouldShowLabelOnHover}
|
||||
onCheckedChange={handleToggleShowLabelOnHover}
|
||||
checked={segmentLabelEnabled}
|
||||
onCheckedChange={handleSegmentLabelEnabledChange}
|
||||
/>
|
||||
<span className="text-base text-white">Show segment label on mouse hover</span>
|
||||
<span className="text-foreground text-base">Show segment name on hover</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -12,13 +12,17 @@ import miscCustomization from './customizations/miscCustomization';
|
||||
import captureViewportModalCustomization from './customizations/captureViewportModalCustomization';
|
||||
import viewportDownloadWarningCustomization from './customizations/viewportDownloadWarningCustomization';
|
||||
|
||||
function getCustomizationModule({ commandsManager, servicesManager }) {
|
||||
function getCustomizationModule({ commandsManager, servicesManager, extensionManager }) {
|
||||
return [
|
||||
{
|
||||
name: 'default',
|
||||
value: {
|
||||
...viewportOverlayCustomization,
|
||||
...getSegmentationPanelCustomization({ commandsManager, servicesManager }),
|
||||
...getSegmentationPanelCustomization({
|
||||
commandsManager,
|
||||
servicesManager,
|
||||
extensionManager,
|
||||
}),
|
||||
...layoutSelectorCustomization,
|
||||
...viewportToolsCustomization,
|
||||
...viewportClickCommandsCustomization,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import debounce from 'lodash.debounce';
|
||||
import { useSystem } from '@ohif/core';
|
||||
|
||||
function mapMeasurementToDisplay(measurement, displaySetService) {
|
||||
const { referenceSeriesUID } = measurement;
|
||||
|
||||
|
||||
@@ -262,13 +262,13 @@ export function useViewportRendering(
|
||||
|
||||
if (volumeId) {
|
||||
properties = viewport.getProperties(volumeId);
|
||||
if (properties.voiRange) {
|
||||
if (properties?.voiRange) {
|
||||
setVoiRange(properties.voiRange);
|
||||
voiRangeRef.current = properties.voiRange;
|
||||
}
|
||||
|
||||
// Get opacity from colormap if available
|
||||
if (properties.colormap && properties.colormap.opacity !== undefined) {
|
||||
if (properties?.colormap?.opacity !== undefined) {
|
||||
const isArray = Array.isArray(properties.colormap.opacity);
|
||||
const opacity = isArray
|
||||
? properties.colormap.opacity.reduce((max, current) => Math.max(max, current), 0)
|
||||
@@ -279,7 +279,7 @@ export function useViewportRendering(
|
||||
}
|
||||
|
||||
// Get threshold from colormap if available
|
||||
if (properties.colormap && properties.colormap.threshold !== undefined) {
|
||||
if (properties?.colormap && properties.colormap.threshold !== undefined) {
|
||||
setThresholdState(properties.colormap.threshold);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,15 +152,27 @@ export function useViewportSegmentations({
|
||||
|
||||
const representations = segmentationService.getSegmentationRepresentations(viewportId);
|
||||
|
||||
const newSegmentationsWithRepresentations = representations.map(representation => {
|
||||
const segmentation = segmentationService.getSegmentation(representation.segmentationId);
|
||||
const mappedSegmentation = mapSegmentationToDisplay(segmentation, customizationService);
|
||||
return {
|
||||
representation,
|
||||
segmentation: mappedSegmentation,
|
||||
};
|
||||
// Deduplicate representations by segmentationId to prevent showing
|
||||
// the same segmentation multiple times in the panel when it has
|
||||
// multiple representation types (e.g., labelmap and surface)
|
||||
const uniqueSegmentationMap = new Map();
|
||||
representations.forEach(representation => {
|
||||
if (!uniqueSegmentationMap.has(representation.segmentationId)) {
|
||||
uniqueSegmentationMap.set(representation.segmentationId, representation);
|
||||
}
|
||||
});
|
||||
|
||||
const newSegmentationsWithRepresentations = Array.from(uniqueSegmentationMap.values()).map(
|
||||
representation => {
|
||||
const segmentation = segmentationService.getSegmentation(representation.segmentationId);
|
||||
const mappedSegmentation = mapSegmentationToDisplay(segmentation, customizationService);
|
||||
return {
|
||||
representation,
|
||||
segmentation: mappedSegmentation,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
setSegmentationsWithRepresentations({
|
||||
segmentationsWithRepresentations: newSegmentationsWithRepresentations,
|
||||
disabled: false,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
|
||||
|
||||
import i18n from 'i18next';
|
||||
export const fourUp = {
|
||||
id: 'fourUp',
|
||||
locked: true,
|
||||
name: '3D four up',
|
||||
name: i18n.t('Hps:3D four up'),
|
||||
icon: 'layout-advanced-3d-four-up',
|
||||
isPreset: true,
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Types } from '@ohif/core';
|
||||
|
||||
import i18n from 'i18next';
|
||||
const frameView: Types.HangingProtocol.Protocol = {
|
||||
id: '@ohif/frameView',
|
||||
description: 'Frame view for the active series',
|
||||
name: 'Frame View',
|
||||
description: i18n.t('Hps:Frame view for the active series'),
|
||||
name: i18n.t('Hps:Frame View'),
|
||||
icon: 'tool-stack-scroll',
|
||||
isPreset: true,
|
||||
toolGroupIds: ['default'],
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
|
||||
|
||||
import i18n from 'i18next';
|
||||
export const main3D = {
|
||||
id: 'main3D',
|
||||
locked: true,
|
||||
name: '3D main',
|
||||
name: i18n.t('Hps:3D main'),
|
||||
icon: 'layout-advanced-3d-main',
|
||||
isPreset: true,
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Types } from '@ohif/core';
|
||||
|
||||
import i18n from 'i18next';
|
||||
export const VOI_SYNC_GROUP = {
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
@@ -22,7 +22,7 @@ export const HYDRATE_SEG_SYNC_GROUP = {
|
||||
|
||||
export const mpr: Types.HangingProtocol.Protocol = {
|
||||
id: 'mpr',
|
||||
name: 'MPR',
|
||||
name: i18n.t('Hps:MPR'),
|
||||
locked: true,
|
||||
icon: 'layout-advanced-mpr',
|
||||
isPreset: true,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
|
||||
|
||||
import i18n from 'i18next';
|
||||
export const mprAnd3DVolumeViewport = {
|
||||
id: 'mprAnd3DVolumeViewport',
|
||||
locked: true,
|
||||
name: 'mpr',
|
||||
name: i18n.t('Hps:mpr'),
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
modifiedDate: '2023-03-15T10:29:44.894Z',
|
||||
availableTo: {},
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
|
||||
import i18n from 'i18next';
|
||||
|
||||
export const only3D = {
|
||||
id: 'only3D',
|
||||
locked: true,
|
||||
name: '3D only',
|
||||
name: i18n.t('Hps:3D only'),
|
||||
icon: 'layout-advanced-3d-only',
|
||||
isPreset: true,
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
|
||||
|
||||
import i18n from 'i18next';
|
||||
export const primary3D = {
|
||||
id: 'primary3D',
|
||||
locked: true,
|
||||
name: '3D primary',
|
||||
name: i18n.t('Hps:3D primary'),
|
||||
icon: 'layout-advanced-3d-primary',
|
||||
isPreset: true,
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
|
||||
|
||||
import i18n from 'i18next';
|
||||
export const primaryAxial = {
|
||||
id: 'primaryAxial',
|
||||
locked: true,
|
||||
name: 'Axial Primary',
|
||||
name: i18n.t('Hps:Axial Primary'),
|
||||
icon: 'layout-advanced-axial-primary',
|
||||
isPreset: true,
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
|
||||
@@ -195,7 +195,7 @@ const cornerstoneExtension: Types.Extensions.Extension = {
|
||||
{
|
||||
name: 'cornerstone',
|
||||
component: ExtendedOHIFCornerstoneViewport,
|
||||
isReferenceViewable: props => utils.isReferenceViewable({ ...props, servicesManager }),
|
||||
isReferenceViewable: utils.isReferenceViewable.bind(null, servicesManager),
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
@@ -55,6 +55,10 @@ export default async function init({
|
||||
extensionManager,
|
||||
appConfig,
|
||||
}: withAppTypes): Promise<void> {
|
||||
// Use a public library path of PUBLIC_URL plus the component name
|
||||
// This safely separates components that are loaded as-is.
|
||||
window.PUBLIC_LIB_URL ||= './${component}/';
|
||||
|
||||
// Note: this should run first before initializing the cornerstone
|
||||
// DO NOT CHANGE THE ORDER
|
||||
|
||||
@@ -189,15 +193,10 @@ export default async function init({
|
||||
initCineService(servicesManager);
|
||||
initStudyPrefetcherService(servicesManager);
|
||||
|
||||
[
|
||||
measurementService.EVENTS.JUMP_TO_MEASUREMENT_LAYOUT,
|
||||
measurementService.EVENTS.JUMP_TO_MEASUREMENT_VIEWPORT,
|
||||
].forEach(event => {
|
||||
measurementService.subscribe(event, evt => {
|
||||
const { measurement } = evt;
|
||||
const { uid: annotationUID } = measurement;
|
||||
cornerstoneTools.annotation.selection.setAnnotationSelected(annotationUID, true);
|
||||
});
|
||||
measurementService.subscribe(measurementService.EVENTS.JUMP_TO_MEASUREMENT, evt => {
|
||||
const { measurement } = evt;
|
||||
const { uid: annotationUID } = measurement;
|
||||
commandsManager.runCommand('jumpToMeasurementViewport', { measurement, annotationUID, evt });
|
||||
});
|
||||
|
||||
// When a custom image load is performed, update the relevant viewports
|
||||
|
||||
@@ -409,10 +409,6 @@ const connectMeasurementServiceToTools = ({
|
||||
setAnnotationLabel(sourceAnnotation, element, label);
|
||||
}
|
||||
|
||||
if (metadata.toolName === 'ArrowAnnotate') {
|
||||
data.text = label;
|
||||
}
|
||||
|
||||
// update the isLocked state
|
||||
annotation.locking.setAnnotationLocked(uid, isLocked);
|
||||
|
||||
@@ -440,7 +436,7 @@ const connectMeasurementServiceToTools = ({
|
||||
return;
|
||||
}
|
||||
|
||||
const { referenceSeriesUID, referenceStudyUID, SOPInstanceUID } = measurement;
|
||||
const { referenceSeriesUID, referenceStudyUID, SOPInstanceUID, metadata } = measurement;
|
||||
|
||||
const instance = DicomMetadataStore.getInstance(
|
||||
referenceStudyUID,
|
||||
@@ -454,7 +450,7 @@ const connectMeasurementServiceToTools = ({
|
||||
if (measurement?.metadata?.referencedImageId) {
|
||||
imageId = measurement.metadata.referencedImageId;
|
||||
frameNumber = getSOPInstanceAttributes(measurement.metadata.referencedImageId).frameNumber;
|
||||
} else {
|
||||
} else if (instance) {
|
||||
imageId = dataSource.getImageIdsForInstance({ instance });
|
||||
}
|
||||
|
||||
@@ -467,8 +463,12 @@ const connectMeasurementServiceToTools = ({
|
||||
annotationUID: measurement.uid,
|
||||
highlighted: false,
|
||||
isLocked: false,
|
||||
invalidated: false,
|
||||
// This is used to force a re-render of the annotation to
|
||||
// re-calculate cached stats since sometimes in SR we
|
||||
// get empty cached stats
|
||||
invalidated: true,
|
||||
metadata: {
|
||||
...metadata,
|
||||
toolName: measurement.toolName,
|
||||
FrameOfReferenceUID: measurement.FrameOfReferenceUID,
|
||||
referencedImageId: imageId,
|
||||
|
||||
@@ -78,6 +78,7 @@ export default function PanelMeasurement(props): React.ReactNode {
|
||||
);
|
||||
return cloned;
|
||||
}
|
||||
|
||||
// Need to merge defaults on the content props to ensure they get passed to children
|
||||
return <StudyMeasurements items={displayMeasurements} />;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { SegmentationTable } from '@ohif/ui-next';
|
||||
import { useActiveViewportSegmentationRepresentations } from '../hooks/useActiveViewportSegmentationRepresentations';
|
||||
import { metaData } from '@cornerstonejs/core';
|
||||
import { metaData, cache } from '@cornerstonejs/core';
|
||||
import { useSystem } from '@ohif/core/src';
|
||||
|
||||
export default function PanelSegmentation({ children }: withAppTypes) {
|
||||
@@ -104,6 +104,26 @@ export default function PanelSegmentation({ children }: withAppTypes) {
|
||||
return { segmentationId, isExportable: true };
|
||||
}
|
||||
|
||||
// Check if any segments have anything drawn in any of the viewports
|
||||
const hasAnySegmentData = (() => {
|
||||
const imageIds = Labelmap.imageIds;
|
||||
if (!imageIds?.length) return false;
|
||||
|
||||
for (const imageId of imageIds) {
|
||||
const pixelData = cache.getImage(imageId)?.getPixelData();
|
||||
if (!pixelData) continue;
|
||||
|
||||
for (let i = 0; i < pixelData.length; i++) {
|
||||
if (pixelData[i] !== 0) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})();
|
||||
|
||||
if (!hasAnySegmentData) {
|
||||
return { segmentationId, isExportable: false };
|
||||
}
|
||||
|
||||
const referencedImageIds = Labelmap.referencedImageIds;
|
||||
const firstImageId = referencedImageIds[0];
|
||||
const instance = metaData.get('instance', firstImageId);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -9,30 +9,34 @@ import {
|
||||
utilities as csUtils,
|
||||
metaData,
|
||||
} from '@cornerstonejs/core';
|
||||
import { ViewportType } from '@cornerstonejs/core/enums';
|
||||
|
||||
import {
|
||||
Enums as csToolsEnums,
|
||||
segmentation as cstSegmentation,
|
||||
Types as cstTypes,
|
||||
} from '@cornerstonejs/tools';
|
||||
|
||||
import { PubSubService, Types as OHIFTypes } from '@ohif/core';
|
||||
import i18n from '@ohif/i18n';
|
||||
import { easeInOutBell, easeInOutBellRelative } from '../../utils/transitions';
|
||||
import { mapROIContoursToRTStructData } from './RTSTRUCT/mapROIContoursToRTStructData';
|
||||
import { SegmentationRepresentations } from '@cornerstonejs/tools/enums';
|
||||
import { addColorLUT } from '@cornerstonejs/tools/segmentation/addColorLUT';
|
||||
import { getNextColorLUTIndex } from '@cornerstonejs/tools/segmentation/getNextColorLUTIndex';
|
||||
import { Segment } from '@cornerstonejs/tools/types/SegmentationStateTypes';
|
||||
import { ContourStyle, LabelmapStyle, SurfaceStyle } from '@cornerstonejs/tools/types';
|
||||
import { ViewportType } from '@cornerstonejs/core/enums';
|
||||
import { SegmentationPresentation, SegmentationPresentationItem } from '../../types/Presentation';
|
||||
import { updateLabelmapSegmentationImageReferences } from '@cornerstonejs/tools/segmentation/updateLabelmapSegmentationImageReferences';
|
||||
import { triggerSegmentationRepresentationModified } from '@cornerstonejs/tools/segmentation/triggerSegmentationEvents';
|
||||
import { convertStackToVolumeLabelmap } from '@cornerstonejs/tools/segmentation/helpers/convertStackToVolumeLabelmap';
|
||||
import { getLabelmapImageIds } from '@cornerstonejs/tools/segmentation';
|
||||
import { VOLUME_LOADER_SCHEME } from '../../constants';
|
||||
|
||||
const LABELMAP = csToolsEnums.SegmentationRepresentations.Labelmap;
|
||||
const CONTOUR = csToolsEnums.SegmentationRepresentations.Contour;
|
||||
import { VOLUME_LOADER_SCHEME } from '../../constants';
|
||||
import { mapROIContoursToRTStructData } from './RTSTRUCT/mapROIContoursToRTStructData';
|
||||
import { SegmentationPresentation, SegmentationPresentationItem } from '../../types/Presentation';
|
||||
import { EasingFunctionEnum, EasingFunctionMap } from '../../utils/transitions';
|
||||
|
||||
const {
|
||||
Labelmap: LABELMAP,
|
||||
Contour: CONTOUR,
|
||||
Surface: SURFACE,
|
||||
} = csToolsEnums.SegmentationRepresentations;
|
||||
|
||||
const {
|
||||
getLabelmapImageIds,
|
||||
helpers: { convertStackToVolumeLabelmap },
|
||||
state: { addColorLUT, updateLabelmapSegmentationImageReferences },
|
||||
triggerSegmentationEvents: { triggerSegmentationRepresentationModified },
|
||||
} = cstSegmentation;
|
||||
|
||||
export type SegmentRepresentation = {
|
||||
segmentIndex: number;
|
||||
@@ -149,13 +153,11 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
const representations = this.getSegmentationRepresentations(viewportId);
|
||||
for (const representation of representations) {
|
||||
const { segmentationId } = representation;
|
||||
|
||||
if (!representation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const { type } = representation;
|
||||
const { segmentationId, type } = representation;
|
||||
|
||||
segmentationsMap.set(segmentationId, {
|
||||
segmentationId,
|
||||
@@ -212,7 +214,7 @@ class SegmentationService extends PubSubService {
|
||||
viewportId: string,
|
||||
specifier: {
|
||||
segmentationId?: string;
|
||||
type?: SegmentationRepresentations;
|
||||
type?: csToolsEnums.SegmentationRepresentations;
|
||||
} = {}
|
||||
): SegmentationRepresentation[] {
|
||||
// Get all representations for the viewportId
|
||||
@@ -245,9 +247,19 @@ class SegmentationService extends PubSubService {
|
||||
this._onSegmentationDataModifiedFromSource
|
||||
);
|
||||
|
||||
eventTarget.removeEventListener(
|
||||
csToolsEnums.Events.SEGMENTATION_REPRESENTATION_MODIFIED,
|
||||
this._onSegmentationRepresentationModifiedFromSource
|
||||
);
|
||||
|
||||
eventTarget.removeEventListener(
|
||||
csToolsEnums.Events.SEGMENTATION_REPRESENTATION_ADDED,
|
||||
this._onSegmentationModifiedFromSource
|
||||
this._onSegmentationRepresentationModifiedFromSource
|
||||
);
|
||||
|
||||
eventTarget.removeEventListener(
|
||||
csToolsEnums.Events.SEGMENTATION_REPRESENTATION_REMOVED,
|
||||
this._onSegmentationRepresentationModifiedFromSource
|
||||
);
|
||||
|
||||
eventTarget.removeEventListener(
|
||||
@@ -283,11 +295,13 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
const colorLUTIndex = this._segmentationIdToColorLUTIndexMap.get(segmentationId);
|
||||
|
||||
const defaultRepresentationType = csToolsEnums.SegmentationRepresentations.Labelmap;
|
||||
let representationTypeToUse = type || defaultRepresentationType;
|
||||
let isConverted = false;
|
||||
|
||||
if (type === csToolsEnums.SegmentationRepresentations.Labelmap) {
|
||||
const defaultRepresentationType: csToolsEnums.SegmentationRepresentations =
|
||||
csViewport.type === ViewportType.VOLUME_3D ? SURFACE : LABELMAP;
|
||||
let representationTypeToUse = type || defaultRepresentationType;
|
||||
|
||||
if (representationTypeToUse === LABELMAP) {
|
||||
const { isVolumeViewport, isVolumeSegmentation } = this.determineViewportAndSegmentationType(
|
||||
csViewport,
|
||||
segmentation
|
||||
@@ -354,7 +368,7 @@ class SegmentationService extends PubSubService {
|
||||
const derivedImages = await imageLoader.createAndCacheDerivedLabelmapImages(referenceImageIds);
|
||||
|
||||
const segs = this.getSegmentations();
|
||||
const label = options.label || `Segmentation ${segs.length + 1}`;
|
||||
const label = options?.label || `Segmentation ${segs.length + 1}`;
|
||||
|
||||
const segImageIds = derivedImages.map(image => image.imageId);
|
||||
|
||||
@@ -371,7 +385,7 @@ class SegmentationService extends PubSubService {
|
||||
config: {
|
||||
label,
|
||||
segments:
|
||||
options.segments && Object.keys(options.segments).length > 0
|
||||
options?.segments && Object.keys(options.segments).length > 0
|
||||
? options.segments
|
||||
: {
|
||||
1: {
|
||||
@@ -393,7 +407,7 @@ class SegmentationService extends PubSubService {
|
||||
segDisplaySet,
|
||||
options: {
|
||||
segmentationId?: string;
|
||||
type: SegmentationRepresentations;
|
||||
type: csToolsEnums.SegmentationRepresentations;
|
||||
} = {
|
||||
type: LABELMAP,
|
||||
}
|
||||
@@ -503,9 +517,7 @@ class SegmentationService extends PubSubService {
|
||||
};
|
||||
});
|
||||
|
||||
// get next color lut index
|
||||
const colorLUTIndex = getNextColorLUTIndex();
|
||||
addColorLUT(colorLUT, colorLUTIndex);
|
||||
const colorLUTIndex = addColorLUT(colorLUT);
|
||||
this._segmentationIdToColorLUTIndexMap.set(segmentationId, colorLUTIndex);
|
||||
|
||||
this._broadcastEvent(EVENTS.SEGMENTATION_LOADING_COMPLETE, {
|
||||
@@ -540,7 +552,7 @@ class SegmentationService extends PubSubService {
|
||||
rtDisplaySet,
|
||||
options: {
|
||||
segmentationId?: string;
|
||||
type: SegmentationRepresentations;
|
||||
type: csToolsEnums.SegmentationRepresentations;
|
||||
} = {
|
||||
type: CONTOUR,
|
||||
}
|
||||
@@ -574,10 +586,19 @@ class SegmentationService extends PubSubService {
|
||||
// find the first image id that contains a referenced SOP instance UID
|
||||
const firstSegmentedSliceImageId =
|
||||
referencedImageIds?.find(imageId =>
|
||||
referencedImageIdsWithGeometry.some(referencedId => imageId.includes(referencedId))
|
||||
referencedImageIdsWithGeometry.some(referencedId =>
|
||||
imageId.includes(referencedId as string)
|
||||
)
|
||||
) || null;
|
||||
|
||||
rtDisplaySet.firstSegmentedSliceImageId = firstSegmentedSliceImageId;
|
||||
|
||||
if (!structureSet.ROIContours?.length) {
|
||||
throw new Error(
|
||||
'The structureSet does not contain any ROIContours. Please ensure the structureSet is loaded first.'
|
||||
);
|
||||
}
|
||||
|
||||
// Map ROI contours to RT Struct Data
|
||||
const allRTStructData = mapROIContoursToRTStructData(structureSet, rtDisplaySetUID);
|
||||
|
||||
@@ -600,12 +621,6 @@ class SegmentationService extends PubSubService {
|
||||
},
|
||||
};
|
||||
|
||||
if (!structureSet.ROIContours?.length) {
|
||||
throw new Error(
|
||||
'The structureSet does not contain any ROIContours. Please ensure the structureSet is loaded first.'
|
||||
);
|
||||
}
|
||||
|
||||
const segments: { [segmentIndex: string]: cstTypes.Segment } = {};
|
||||
let segmentsCachedStats = {};
|
||||
|
||||
@@ -613,7 +628,9 @@ class SegmentationService extends PubSubService {
|
||||
const colorLUT = [[0, 0, 0, 0]]; // First entry is transparent for index 0
|
||||
|
||||
// Process each segment similarly to the SEG function
|
||||
for (const rtStructData of allRTStructData) {
|
||||
for (let i = 0; i < allRTStructData.length; i++) {
|
||||
const rtStructData = allRTStructData[i];
|
||||
|
||||
const { data, id, color, segmentIndex, geometryId, group } = rtStructData;
|
||||
|
||||
// Add the color to the colorLUT array
|
||||
@@ -662,8 +679,7 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
|
||||
// Create and register the colorLUT
|
||||
const colorLUTIndex = getNextColorLUTIndex();
|
||||
addColorLUT(colorLUT, colorLUTIndex);
|
||||
const colorLUTIndex = addColorLUT(colorLUT);
|
||||
this._segmentationIdToColorLUTIndexMap.set(segmentationId, colorLUTIndex);
|
||||
|
||||
// Assign processed segments to segmentation config
|
||||
@@ -760,7 +776,7 @@ class SegmentationService extends PubSubService {
|
||||
public hasCustomStyles(specifier: {
|
||||
viewportId: string;
|
||||
segmentationId: string;
|
||||
type: SegmentationRepresentations;
|
||||
type: csToolsEnums.SegmentationRepresentations;
|
||||
}): boolean {
|
||||
return cstSegmentation.config.style.hasCustomStyle(specifier);
|
||||
}
|
||||
@@ -768,7 +784,7 @@ class SegmentationService extends PubSubService {
|
||||
public getStyle = (specifier: {
|
||||
viewportId: string;
|
||||
segmentationId: string;
|
||||
type: SegmentationRepresentations;
|
||||
type: csToolsEnums.SegmentationRepresentations;
|
||||
segmentIndex?: number;
|
||||
}) => {
|
||||
const style = cstSegmentation.config.style.getStyle(specifier);
|
||||
@@ -778,12 +794,12 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
public setStyle = (
|
||||
specifier: {
|
||||
type: SegmentationRepresentations;
|
||||
type: csToolsEnums.SegmentationRepresentations;
|
||||
viewportId?: string;
|
||||
segmentationId?: string;
|
||||
segmentIndex?: number;
|
||||
},
|
||||
style: LabelmapStyle | ContourStyle | SurfaceStyle
|
||||
style: cstTypes.LabelmapStyle | cstTypes.ContourStyle | cstTypes.SurfaceStyle
|
||||
) => {
|
||||
cstSegmentation.config.style.setStyle(specifier, style);
|
||||
};
|
||||
@@ -901,7 +917,7 @@ class SegmentationService extends PubSubService {
|
||||
segmentationId: string,
|
||||
segmentIndex: number,
|
||||
isVisible: boolean,
|
||||
type?: SegmentationRepresentations
|
||||
type?: csToolsEnums.SegmentationRepresentations
|
||||
): void {
|
||||
this._setSegmentVisibility(viewportId, segmentationId, segmentIndex, isVisible, type);
|
||||
}
|
||||
@@ -938,7 +954,7 @@ class SegmentationService extends PubSubService {
|
||||
viewportId: string,
|
||||
segmentationId: string,
|
||||
segmentIndex: number,
|
||||
type: SegmentationRepresentations
|
||||
type: csToolsEnums.SegmentationRepresentations
|
||||
): void {
|
||||
const isVisible = cstSegmentation.config.visibility.getSegmentIndexVisibility(
|
||||
viewportId,
|
||||
@@ -969,6 +985,12 @@ class SegmentationService extends PubSubService {
|
||||
segmentIndex: number,
|
||||
color: csTypes.Color
|
||||
): void {
|
||||
const segmentationRepresentations = this.getSegmentationRepresentations(viewportId, {
|
||||
segmentationId,
|
||||
});
|
||||
const { colorLUTIndex } = segmentationRepresentations[0];
|
||||
this._segmentationIdToColorLUTIndexMap.set(segmentationId, colorLUTIndex);
|
||||
|
||||
cstSegmentation.config.color.setSegmentIndexColor(
|
||||
viewportId,
|
||||
segmentationId,
|
||||
@@ -1010,7 +1032,7 @@ class SegmentationService extends PubSubService {
|
||||
public getLabelmapVolume(segmentationId: string) {
|
||||
const csSegmentation = cstSegmentation.state.getSegmentation(segmentationId);
|
||||
const labelmapData = csSegmentation.representationData[
|
||||
SegmentationRepresentations.Labelmap
|
||||
LABELMAP
|
||||
] as cstTypes.LabelmapToolOperationDataVolume;
|
||||
|
||||
if (!labelmapData || !labelmapData.volumeId) {
|
||||
@@ -1112,7 +1134,10 @@ class SegmentationService extends PubSubService {
|
||||
*/
|
||||
public toggleSegmentationRepresentationVisibility = (
|
||||
viewportId: string,
|
||||
{ segmentationId, type }: { segmentationId: string; type: SegmentationRepresentations }
|
||||
{
|
||||
segmentationId,
|
||||
type,
|
||||
}: { segmentationId: string; type: csToolsEnums.SegmentationRepresentations }
|
||||
): void => {
|
||||
this._toggleSegmentationRepresentationVisibility(viewportId, segmentationId, type);
|
||||
};
|
||||
@@ -1161,7 +1186,7 @@ class SegmentationService extends PubSubService {
|
||||
viewportId: string,
|
||||
specifier: {
|
||||
segmentationId?: string;
|
||||
type?: SegmentationRepresentations;
|
||||
type?: csToolsEnums.SegmentationRepresentations;
|
||||
} = {}
|
||||
): void {
|
||||
cstSegmentation.removeSegmentationRepresentations(viewportId, specifier);
|
||||
@@ -1175,7 +1200,7 @@ class SegmentationService extends PubSubService {
|
||||
highlightSegment = true,
|
||||
animationLength = 750,
|
||||
highlightHideOthers = false,
|
||||
highlightFunctionType = 'ease-in-out' // todo: make animation functions configurable from outside
|
||||
animationFunctionType: EasingFunctionEnum = EasingFunctionEnum.EASE_IN_OUT
|
||||
): void {
|
||||
const center = this._getSegmentCenter(segmentationId, segmentIndex);
|
||||
if (!center) {
|
||||
@@ -1201,7 +1226,8 @@ class SegmentationService extends PubSubService {
|
||||
viewportId,
|
||||
highlightAlpha,
|
||||
animationLength,
|
||||
highlightHideOthers
|
||||
highlightHideOthers,
|
||||
animationFunctionType
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -1213,7 +1239,7 @@ class SegmentationService extends PubSubService {
|
||||
alpha = 0.9,
|
||||
animationLength = 750,
|
||||
hideOthers = true,
|
||||
highlightFunctionType = 'ease-in-out'
|
||||
animationFunctionType: EasingFunctionEnum = EasingFunctionEnum.EASE_IN_OUT
|
||||
): void {
|
||||
if (this.highlightIntervalId) {
|
||||
clearInterval(this.highlightIntervalId);
|
||||
@@ -1246,7 +1272,8 @@ class SegmentationService extends PubSubService {
|
||||
segments,
|
||||
viewportId,
|
||||
animationLength,
|
||||
representation
|
||||
representation,
|
||||
animationFunctionType
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -1271,7 +1298,7 @@ class SegmentationService extends PubSubService {
|
||||
private _setSegmentationRepresentationVisibility(
|
||||
viewportId: string,
|
||||
segmentationId: string,
|
||||
type: SegmentationRepresentations,
|
||||
type: csToolsEnums.SegmentationRepresentations,
|
||||
isVisible: boolean
|
||||
): void {
|
||||
const representations = this.getSegmentationRepresentations(viewportId, {
|
||||
@@ -1331,14 +1358,17 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
private async handleVolumeViewportCase(csViewport, segmentation, isVolumeSegmentation) {
|
||||
if (csViewport.type === ViewportType.VOLUME_3D) {
|
||||
return { representationTypeToUse: SegmentationRepresentations.Surface, isConverted: false };
|
||||
return {
|
||||
representationTypeToUse: SURFACE,
|
||||
isConverted: false,
|
||||
};
|
||||
} else {
|
||||
await this.handleVolumeViewport(
|
||||
csViewport as csTypes.IVolumeViewport,
|
||||
segmentation,
|
||||
isVolumeSegmentation
|
||||
);
|
||||
return { representationTypeToUse: SegmentationRepresentations.Labelmap, isConverted: false };
|
||||
return { representationTypeToUse: LABELMAP, isConverted: false };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1348,14 +1378,17 @@ class SegmentationService extends PubSubService {
|
||||
isVolumeSegmentation: boolean,
|
||||
viewportId: string,
|
||||
segmentationId: string
|
||||
): Promise<{ representationTypeToUse: SegmentationRepresentations; isConverted: boolean }> {
|
||||
): Promise<{
|
||||
representationTypeToUse: csToolsEnums.SegmentationRepresentations;
|
||||
isConverted: boolean;
|
||||
}> {
|
||||
if (isVolumeSegmentation) {
|
||||
const isConverted = await this.convertStackToVolumeViewport(csViewport);
|
||||
return { representationTypeToUse: SegmentationRepresentations.Labelmap, isConverted };
|
||||
return { representationTypeToUse: LABELMAP, isConverted };
|
||||
}
|
||||
|
||||
if (updateLabelmapSegmentationImageReferences(viewportId, segmentationId)) {
|
||||
return { representationTypeToUse: SegmentationRepresentations.Labelmap, isConverted: false };
|
||||
return { representationTypeToUse: LABELMAP, isConverted: false };
|
||||
}
|
||||
|
||||
const isConverted = await this.attemptStackToVolumeConversion(
|
||||
@@ -1365,7 +1398,7 @@ class SegmentationService extends PubSubService {
|
||||
segmentationId
|
||||
);
|
||||
|
||||
return { representationTypeToUse: SegmentationRepresentations.Labelmap, isConverted };
|
||||
return { representationTypeToUse: LABELMAP, isConverted };
|
||||
}
|
||||
|
||||
private async _addSegmentationRepresentation(
|
||||
@@ -1476,11 +1509,7 @@ class SegmentationService extends PubSubService {
|
||||
segImage.FrameOfReferenceUID === frameOfReferenceUID
|
||||
) {
|
||||
const isConverted = await this.convertStackToVolumeViewport(viewport);
|
||||
triggerSegmentationRepresentationModified(
|
||||
viewportId,
|
||||
segmentationId,
|
||||
SegmentationRepresentations.Labelmap
|
||||
);
|
||||
triggerSegmentationRepresentationModified(viewportId, segmentationId, LABELMAP);
|
||||
|
||||
return isConverted;
|
||||
}
|
||||
@@ -1608,10 +1637,11 @@ class SegmentationService extends PubSubService {
|
||||
segmentIndex: number,
|
||||
alpha: number,
|
||||
hideOthers: boolean,
|
||||
segments: Segment[],
|
||||
segments: cstTypes.Segment[],
|
||||
viewportId: string,
|
||||
animationLength: number,
|
||||
representation: cstTypes.SegmentationRepresentation
|
||||
representation: cstTypes.SegmentationRepresentation,
|
||||
animationFunctionType: EasingFunctionEnum
|
||||
) {
|
||||
const { segmentationId } = representation;
|
||||
const newSegmentSpecificConfig = {
|
||||
@@ -1645,6 +1675,8 @@ class SegmentationService extends PubSubService {
|
||||
const elapsed = timestamp - startTime;
|
||||
const progress = Math.min(elapsed / animationLength, 1);
|
||||
|
||||
const easingFunction = EasingFunctionMap.get(animationFunctionType);
|
||||
|
||||
cstSegmentation.config.style.setStyle(
|
||||
{
|
||||
segmentationId,
|
||||
@@ -1652,7 +1684,7 @@ class SegmentationService extends PubSubService {
|
||||
type: LABELMAP,
|
||||
},
|
||||
{
|
||||
fillAlpha: easeInOutBell(progress, fillAlpha),
|
||||
fillAlpha: easingFunction(progress, fillAlpha),
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1677,21 +1709,20 @@ class SegmentationService extends PubSubService {
|
||||
segmentIndex: number,
|
||||
alpha: number,
|
||||
hideOthers: boolean,
|
||||
segments: Segment[],
|
||||
segments: cstTypes.Segment[],
|
||||
viewportId: string,
|
||||
animationLength: number,
|
||||
representation: cstTypes.SegmentationRepresentation
|
||||
representation: cstTypes.SegmentationRepresentation,
|
||||
animationFunctionType: EasingFunctionEnum
|
||||
) {
|
||||
const { segmentationId } = representation;
|
||||
const startTime = performance.now();
|
||||
|
||||
const prevStyle = cstSegmentation.config.style.getStyle({
|
||||
type: CONTOUR,
|
||||
}) as ContourStyle;
|
||||
}) as cstTypes.ContourStyle;
|
||||
|
||||
const prevOutlineWidth = prevStyle.outlineWidth;
|
||||
// make this configurable
|
||||
const baseline = Math.max(prevOutlineWidth * 3.5, 5);
|
||||
|
||||
const animate = (currentTime: number) => {
|
||||
const progress = (currentTime - startTime) / animationLength;
|
||||
@@ -1700,7 +1731,8 @@ class SegmentationService extends PubSubService {
|
||||
return;
|
||||
}
|
||||
|
||||
const reversedProgress = easeInOutBellRelative(progress, baseline, prevOutlineWidth);
|
||||
const OUTLINE_ANIMATION_SCALE_FACTOR = 5;
|
||||
const easingFunction = EasingFunctionMap.get(animationFunctionType);
|
||||
|
||||
cstSegmentation.config.style.setStyle(
|
||||
{
|
||||
@@ -1709,7 +1741,7 @@ class SegmentationService extends PubSubService {
|
||||
type: CONTOUR,
|
||||
},
|
||||
{
|
||||
outlineWidth: reversedProgress,
|
||||
outlineWidth: easingFunction(progress, prevOutlineWidth, OUTLINE_ANIMATION_SCALE_FACTOR),
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1722,7 +1754,7 @@ class SegmentationService extends PubSubService {
|
||||
private _toggleSegmentationRepresentationVisibility = (
|
||||
viewportId: string,
|
||||
segmentationId: string,
|
||||
type: SegmentationRepresentations
|
||||
type: csToolsEnums.SegmentationRepresentations
|
||||
): void => {
|
||||
const representations = this.getSegmentationRepresentations(viewportId, {
|
||||
segmentationId,
|
||||
@@ -1754,7 +1786,10 @@ class SegmentationService extends PubSubService {
|
||||
return `${volumeLoaderSchema}:${displaySet.displaySetInstanceUID}`;
|
||||
}
|
||||
|
||||
private _getSegmentCenter(segmentationId, segmentIndex) {
|
||||
private _getSegmentCenter(
|
||||
segmentationId: string,
|
||||
segmentIndex: number
|
||||
): { image?: csTypes.Point3; world: csTypes.Point3 } | undefined {
|
||||
const segmentation = this.getSegmentation(segmentationId);
|
||||
|
||||
if (!segmentation) {
|
||||
@@ -1765,19 +1800,17 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
const { cachedStats } = segments[segmentIndex];
|
||||
|
||||
if (!cachedStats) {
|
||||
return;
|
||||
if (cachedStats?.center) {
|
||||
const { center } = cachedStats;
|
||||
|
||||
return center as { image: csTypes.Point3; world: csTypes.Point3 };
|
||||
}
|
||||
|
||||
const { center } = cachedStats;
|
||||
|
||||
if (!center) {
|
||||
if (cachedStats?.namedStats?.center) {
|
||||
return {
|
||||
world: cachedStats.namedStats.center.value,
|
||||
};
|
||||
}
|
||||
|
||||
return center;
|
||||
}
|
||||
|
||||
private _setSegmentLockedStatus(segmentationId: string, segmentIndex: number, isLocked: boolean) {
|
||||
@@ -1789,7 +1822,7 @@ class SegmentationService extends PubSubService {
|
||||
segmentationId: string,
|
||||
segmentIndex: number,
|
||||
isVisible: boolean,
|
||||
type?: SegmentationRepresentations
|
||||
type?: csToolsEnums.SegmentationRepresentations
|
||||
) {
|
||||
cstSegmentation.config.visibility.setSegmentIndexVisibility(
|
||||
viewportId,
|
||||
|
||||
@@ -36,7 +36,6 @@ import { useLutPresentationStore } from '../../stores/useLutPresentationStore';
|
||||
import { usePositionPresentationStore } from '../../stores/usePositionPresentationStore';
|
||||
import { useSynchronizersStore } from '../../stores/useSynchronizersStore';
|
||||
import { useSegmentationPresentationStore } from '../../stores/useSegmentationPresentationStore';
|
||||
import { VOLUME_LOADER_SCHEME } from '../../constants';
|
||||
|
||||
const EVENTS = {
|
||||
VIEWPORT_DATA_CHANGED: 'event::cornerstoneViewportService:viewportDataChanged',
|
||||
@@ -47,6 +46,7 @@ const MIN_STACK_VIEWPORTS_TO_ENQUEUE_RESIZE = 12;
|
||||
const MIN_VOLUME_VIEWPORTS_TO_ENQUEUE_RESIZE = 6;
|
||||
|
||||
export const WITH_NAVIGATION = { withNavigation: true, withOrientation: false };
|
||||
export const WITH_ORIENTATION = { withNavigation: true, withOrientation: true };
|
||||
|
||||
/**
|
||||
* Handles cornerstone viewport logic including enabling, disabling, and
|
||||
@@ -345,6 +345,11 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
delete properties?.voiRange;
|
||||
delete properties?.VOILUTFunction;
|
||||
}
|
||||
if (properties?.colormap) {
|
||||
if (properties.colormap?.opacity?.length === 0) {
|
||||
delete properties.colormap.opacity;
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
};
|
||||
|
||||
@@ -412,6 +417,11 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
// and we would lose the presentation.
|
||||
this.storePresentation({ viewportId: viewportInfo.getViewportId() });
|
||||
|
||||
// Todo: i don't like this here, move it
|
||||
this.servicesManager.services.segmentationService.clearSegmentationRepresentations(
|
||||
viewportInfo.getViewportId()
|
||||
);
|
||||
|
||||
if (!viewportInfo) {
|
||||
throw new Error('element is not enabled for the given viewportId');
|
||||
}
|
||||
@@ -546,10 +556,13 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
* was initiated.
|
||||
* @return the viewportId that the measurement should be displayed in.
|
||||
*/
|
||||
public getViewportIdToJump(activeViewportId: string, metadata): string {
|
||||
public findNavigationCompatibleViewportId(activeViewportId: string, metadata): string {
|
||||
// First check if the active viewport can just be navigated to show the given item
|
||||
const activeViewport = this.getCornerstoneViewport(activeViewportId);
|
||||
if (activeViewport.isReferenceViewable(metadata, { withNavigation: true })) {
|
||||
if (!activeViewport) {
|
||||
console.warn('No active viewport found for', activeViewportId);
|
||||
}
|
||||
if (activeViewport?.isReferenceViewable(metadata, { withNavigation: true })) {
|
||||
return activeViewportId;
|
||||
}
|
||||
|
||||
@@ -565,7 +578,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
// No viewport is in the right display set/orientation to show this, so see if
|
||||
// the active viewport could change orientations to show this
|
||||
if (
|
||||
activeViewport.isReferenceViewable(metadata, { withNavigation: true, withOrientation: true })
|
||||
activeViewport?.isReferenceViewable(metadata, { withNavigation: true, withOrientation: true })
|
||||
) {
|
||||
return activeViewportId;
|
||||
}
|
||||
@@ -584,6 +597,86 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Figures out which viewport to update when the viewport type needs to change.
|
||||
* This may not be the active viewport if there is already a viewport showing
|
||||
* the display set, but in the wrong orientation.
|
||||
*
|
||||
* The viewport will need to update the viewport type and/or display set to
|
||||
* display the resulting data.
|
||||
*
|
||||
* The first choice will be a viewport already showing the correct display set,
|
||||
* but showing it as a stack.
|
||||
*
|
||||
* Second choice is to see if there is a viewport already showing the right
|
||||
* orientation for the image, but the wrong display set. This fixes the
|
||||
* case where the user is in MPR and a viewport other than active should be
|
||||
* the one to change to display the iamge.
|
||||
*
|
||||
* Final choice is to use the provide activeViewportId. This will cover
|
||||
* changes to/from video and wsi viewports and other cases where no
|
||||
* viewport is really even close to being able to display the measurement.
|
||||
*/
|
||||
public findUpdateableViewportConfiguration(activeViewportId: string, measurement) {
|
||||
const { metadata, displaySetInstanceUID } = measurement;
|
||||
const { volumeId, referencedImageId } = metadata;
|
||||
const { displaySetService, viewportGridService } = this.servicesManager.services;
|
||||
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||
|
||||
let { viewportType } = displaySet;
|
||||
if (!viewportType) {
|
||||
if (referencedImageId && !displaySet.isReconstructable) {
|
||||
viewportType = csEnums.ViewportType.STACK;
|
||||
} else if (volumeId) {
|
||||
viewportType = 'volume';
|
||||
}
|
||||
}
|
||||
|
||||
// Find viewports that could be updated to be volumes to show this view
|
||||
// That prefers a viewport already showing the right display set.
|
||||
if (volumeId) {
|
||||
for (const id of this.viewportsById.keys()) {
|
||||
const viewport = this.getCornerstoneViewport(id);
|
||||
if (viewport?.isReferenceViewable(metadata, { asVolume: true, withNavigation: true })) {
|
||||
return {
|
||||
viewportId: id,
|
||||
displaySetInstanceUID,
|
||||
viewportOptions: { viewportType },
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find a viewport in the correct orientation showing a different display set
|
||||
// which could be used to display the annotation.
|
||||
const altMetadata = { ...metadata, volumeId: null, referencedImageId: null };
|
||||
for (const id of this.viewportsById.keys()) {
|
||||
const viewport = this.getCornerstoneViewport(id);
|
||||
const viewportDisplaySetUID = viewportGridService.getDisplaySetsUIDsForViewport(id)?.[0];
|
||||
if (!viewportDisplaySetUID || !viewport) {
|
||||
continue;
|
||||
}
|
||||
if (volumeId) {
|
||||
altMetadata.volumeId = viewportDisplaySetUID;
|
||||
}
|
||||
altMetadata.FrameOfReferenceUID = this._getFrameOfReferenceUID(viewportDisplaySetUID);
|
||||
if (viewport.isReferenceViewable(altMetadata, { asVolume: true, withNavigation: true })) {
|
||||
return {
|
||||
viewportId: id,
|
||||
displaySetInstanceUID,
|
||||
viewportOptions: { viewportType },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Just display in the active viewport
|
||||
return {
|
||||
viewportId: activeViewportId,
|
||||
displaySetInstanceUID,
|
||||
viewportOptions: { viewportType },
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the image data for the given viewport.
|
||||
*/
|
||||
@@ -621,7 +714,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
// is being used to navigate to the initial view position for measurement
|
||||
// navigation and other navigation forcing specific views.
|
||||
let initialImageIndexToUse =
|
||||
presentations?.positionPresentation?.initialImageIndex ?? initialImageIndex;
|
||||
presentations?.positionPresentation?.initialImageIndex ?? <number>initialImageIndex;
|
||||
|
||||
const { rotation, flipHorizontal, displayArea } = viewportInfo.getViewportOptions();
|
||||
|
||||
@@ -657,7 +750,11 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
initialImageIndexToUse = imageIds.indexOf(referencedImageId);
|
||||
}
|
||||
|
||||
if (initialImageIndexToUse === undefined || initialImageIndexToUse === null) {
|
||||
if (
|
||||
initialImageIndexToUse === undefined ||
|
||||
initialImageIndexToUse === null ||
|
||||
initialImageIndexToUse < 0
|
||||
) {
|
||||
initialImageIndexToUse = this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0;
|
||||
}
|
||||
|
||||
@@ -1209,7 +1306,10 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
): void {
|
||||
const viewRef = positionPresentation?.viewReference;
|
||||
if (viewRef) {
|
||||
if (viewport.isReferenceViewable(viewRef, WITH_NAVIGATION)) {
|
||||
// The orientation can be updated here to navigate to the specified
|
||||
// measurement or previous item, but this will not switch to volume
|
||||
// or to stack from the other type
|
||||
if (viewport.isReferenceViewable(viewRef, WITH_ORIENTATION)) {
|
||||
viewport.setViewReference(viewRef);
|
||||
} else {
|
||||
console.warn('Unable to apply reference viewable', viewRef);
|
||||
@@ -1235,10 +1335,23 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
segmentationPresentation.forEach((presentationItem: SegmentationPresentationItem) => {
|
||||
const { segmentationId, type, hydrated } = presentationItem;
|
||||
|
||||
const { Labelmap, Surface } = csToolsEnums.SegmentationRepresentations;
|
||||
const representationType = (() => {
|
||||
if (type === Surface) {
|
||||
if (viewport.type === csEnums.ViewportType.VOLUME_3D) {
|
||||
return Surface;
|
||||
} else {
|
||||
return Labelmap;
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
})();
|
||||
|
||||
if (hydrated) {
|
||||
segmentationService.addSegmentationRepresentation(viewport.id, {
|
||||
segmentationId,
|
||||
type,
|
||||
type: representationType,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -120,7 +120,7 @@ class DicomLoaderService {
|
||||
const imageInstance = getImageInstance(dataset);
|
||||
|
||||
if (imageInstance) {
|
||||
const imageId = getImageInstanceId(imageInstance);
|
||||
let imageId = getImageInstanceId(imageInstance);
|
||||
let getDicomDataMethod = fetchIt;
|
||||
const loaderType = getImageLoaderType(imageId);
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
import { findNearbyToolData } from './findNearbyToolData';
|
||||
|
||||
describe('findNearbyToolData', () => {
|
||||
const mockCommandsManager = {
|
||||
runCommand: jest.fn(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should return undefined when event is null', () => {
|
||||
const result = findNearbyToolData(mockCommandsManager, null);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(mockCommandsManager.runCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return undefined when event is undefined', () => {
|
||||
const result = findNearbyToolData(mockCommandsManager, undefined);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(mockCommandsManager.runCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return undefined when event has no detail', () => {
|
||||
const event = {};
|
||||
const result = findNearbyToolData(mockCommandsManager, event);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(mockCommandsManager.runCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return undefined when event detail is null', () => {
|
||||
const event = { detail: null };
|
||||
const result = findNearbyToolData(mockCommandsManager, event);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(mockCommandsManager.runCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call runCommand with correct parameters when event has valid detail', () => {
|
||||
const mockElement = document.createElement('div');
|
||||
const mockCurrentPoints = { canvas: { x: 100, y: 200 } };
|
||||
const mockToolData = { id: 'annotation-1' };
|
||||
const event = {
|
||||
detail: {
|
||||
element: mockElement,
|
||||
currentPoints: mockCurrentPoints,
|
||||
},
|
||||
};
|
||||
|
||||
mockCommandsManager.runCommand.mockReturnValue(mockToolData);
|
||||
|
||||
const result = findNearbyToolData(mockCommandsManager, event);
|
||||
|
||||
expect(mockCommandsManager.runCommand).toHaveBeenCalledWith(
|
||||
'getNearbyAnnotation',
|
||||
{
|
||||
element: mockElement,
|
||||
canvasCoordinates: mockCurrentPoints.canvas,
|
||||
},
|
||||
'CORNERSTONE'
|
||||
);
|
||||
expect(result).toBe(mockToolData);
|
||||
});
|
||||
|
||||
it('should handle event with element but no currentPoints', () => {
|
||||
const mockElement = document.createElement('div');
|
||||
const event = {
|
||||
detail: {
|
||||
element: mockElement,
|
||||
},
|
||||
};
|
||||
|
||||
findNearbyToolData(mockCommandsManager, event);
|
||||
|
||||
expect(mockCommandsManager.runCommand).toHaveBeenCalledWith(
|
||||
'getNearbyAnnotation',
|
||||
{
|
||||
element: mockElement,
|
||||
canvasCoordinates: undefined,
|
||||
},
|
||||
'CORNERSTONE'
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle event with currentPoints but no canvas coordinates', () => {
|
||||
const mockElement = document.createElement('div');
|
||||
const mockCurrentPoints = {};
|
||||
const event = {
|
||||
detail: {
|
||||
element: mockElement,
|
||||
currentPoints: mockCurrentPoints,
|
||||
},
|
||||
};
|
||||
|
||||
findNearbyToolData(mockCommandsManager, event);
|
||||
|
||||
expect(mockCommandsManager.runCommand).toHaveBeenCalledWith(
|
||||
'getNearbyAnnotation',
|
||||
{
|
||||
element: mockElement,
|
||||
canvasCoordinates: undefined,
|
||||
},
|
||||
'CORNERSTONE'
|
||||
);
|
||||
});
|
||||
|
||||
it('should return result from runCommand', () => {
|
||||
const mockToolData = { id: 'test-annotation', data: 'test-data' };
|
||||
const event = {
|
||||
detail: {
|
||||
element: document.createElement('div'),
|
||||
currentPoints: { canvas: { x: 50, y: 75 } },
|
||||
},
|
||||
};
|
||||
|
||||
mockCommandsManager.runCommand.mockReturnValue(mockToolData);
|
||||
|
||||
const result = findNearbyToolData(mockCommandsManager, event);
|
||||
|
||||
expect(result).toBe(mockToolData);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,319 @@
|
||||
import { generateSegmentationCSVReport } from './generateSegmentationCSVReport';
|
||||
|
||||
// Mock DOM APIs
|
||||
Object.defineProperty(global, 'Blob', {
|
||||
writable: true,
|
||||
value: jest.fn().mockImplementation((content, options) => ({
|
||||
content,
|
||||
options,
|
||||
})),
|
||||
});
|
||||
|
||||
Object.defineProperty(global, 'URL', {
|
||||
writable: true,
|
||||
value: {
|
||||
createObjectURL: jest.fn().mockReturnValue('mock-url'),
|
||||
},
|
||||
});
|
||||
|
||||
const mockDocument = {
|
||||
addEventListener: jest.fn(),
|
||||
createElement: jest.fn().mockReturnValue({
|
||||
setAttribute: jest.fn(),
|
||||
click: jest.fn(),
|
||||
style: {},
|
||||
}),
|
||||
body: {
|
||||
appendChild: jest.fn(),
|
||||
removeChild: jest.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
Object.defineProperty(global, 'document', {
|
||||
writable: true,
|
||||
value: mockDocument,
|
||||
});
|
||||
|
||||
describe('generateSegmentationCSVReport', () => {
|
||||
const mockInfo = {
|
||||
reference: {
|
||||
SeriesNumber: '1',
|
||||
SeriesInstanceUID: 'series-uid-123',
|
||||
StudyInstanceUID: 'study-uid-456',
|
||||
SeriesDate: '20231201',
|
||||
SeriesTime: '120000',
|
||||
SeriesDescription: 'Test Series',
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should generate CSV with basic segmentation data', () => {
|
||||
const segmentationData = {
|
||||
segmentationId: 'seg-123',
|
||||
label: 'Test Segmentation',
|
||||
};
|
||||
|
||||
generateSegmentationCSVReport(segmentationData, mockInfo);
|
||||
|
||||
expect(global.Blob).toHaveBeenCalledWith([expect.stringContaining('Segmentation ID,seg-123')], {
|
||||
type: 'text/csv;charset=utf-8;',
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle segmentation data without id and label', () => {
|
||||
const segmentationData = {};
|
||||
|
||||
generateSegmentationCSVReport(segmentationData, mockInfo);
|
||||
|
||||
expect(global.Blob).toHaveBeenCalledWith(
|
||||
[expect.stringContaining('Segmentation ID,\nSegmentation Label,')],
|
||||
{ type: 'text/csv;charset=utf-8;' }
|
||||
);
|
||||
});
|
||||
|
||||
it('should include reference information when provided', () => {
|
||||
const segmentationData = {
|
||||
segmentationId: 'seg-123',
|
||||
label: 'Test Segmentation',
|
||||
};
|
||||
|
||||
generateSegmentationCSVReport(segmentationData, mockInfo);
|
||||
|
||||
expect(global.Blob).toHaveBeenCalledWith(
|
||||
[expect.stringContaining('reference Series Number,1')],
|
||||
{ type: 'text/csv;charset=utf-8;' }
|
||||
);
|
||||
});
|
||||
|
||||
it('should skip empty reference values', () => {
|
||||
const segmentationData = {
|
||||
segmentationId: 'seg-123',
|
||||
label: 'Test Segmentation',
|
||||
};
|
||||
const infoWithEmptyValues = {
|
||||
reference: {
|
||||
SeriesNumber: '1',
|
||||
SeriesInstanceUID: '',
|
||||
StudyInstanceUID: null,
|
||||
SeriesDate: undefined,
|
||||
SeriesTime: '120000',
|
||||
SeriesDescription: 'Test Series',
|
||||
},
|
||||
};
|
||||
|
||||
generateSegmentationCSVReport(segmentationData, infoWithEmptyValues);
|
||||
|
||||
const csvContent = (global.Blob as jest.Mock).mock.calls[0][0][0];
|
||||
expect(csvContent).toContain('reference Series Number,1');
|
||||
expect(csvContent).toContain('reference Series Time,120000');
|
||||
expect(csvContent).not.toContain('reference Series Instance UID');
|
||||
expect(csvContent).not.toContain('reference Study Instance UID');
|
||||
expect(csvContent).not.toContain('reference Series Date');
|
||||
});
|
||||
|
||||
it('should handle segments with basic properties', () => {
|
||||
const segmentationData = {
|
||||
segmentationId: 'seg-123',
|
||||
label: 'Test Segmentation',
|
||||
segments: {
|
||||
'1': {
|
||||
segmentIndex: 1,
|
||||
label: 'Segment 1',
|
||||
locked: true,
|
||||
active: false,
|
||||
},
|
||||
'2': {
|
||||
segmentIndex: 2,
|
||||
label: 'Segment 2',
|
||||
locked: false,
|
||||
active: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
generateSegmentationCSVReport(segmentationData, mockInfo);
|
||||
|
||||
const csvContent = (global.Blob as jest.Mock).mock.calls[0][0][0];
|
||||
expect(csvContent).toContain('Label,Segment 1,Segment 2');
|
||||
expect(csvContent).toContain('Segment Index,1,2');
|
||||
expect(csvContent).toContain('Locked,Yes,No');
|
||||
expect(csvContent).toContain('Active,No,Yes');
|
||||
});
|
||||
|
||||
it('should handle segments with statistics', () => {
|
||||
const segmentationData = {
|
||||
segmentationId: 'seg-123',
|
||||
label: 'Test Segmentation',
|
||||
segments: {
|
||||
'1': {
|
||||
segmentIndex: 1,
|
||||
label: 'Segment 1',
|
||||
locked: false,
|
||||
active: true,
|
||||
cachedStats: {
|
||||
namedStats: {
|
||||
mean: {
|
||||
name: 'mean',
|
||||
label: 'Mean',
|
||||
value: 100.5,
|
||||
unit: 'HU',
|
||||
},
|
||||
volume: {
|
||||
name: 'volume',
|
||||
label: 'Volume',
|
||||
value: 250.75,
|
||||
unit: 'mm³',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
generateSegmentationCSVReport(segmentationData, mockInfo);
|
||||
|
||||
const csvContent = (global.Blob as jest.Mock).mock.calls[0][0][0];
|
||||
expect(csvContent).toContain('Mean (HU),100.5');
|
||||
expect(csvContent).toContain('Volume (mm³),250.75');
|
||||
});
|
||||
|
||||
it('should handle segments with statistics without units', () => {
|
||||
const segmentationData = {
|
||||
segmentationId: 'seg-123',
|
||||
segments: {
|
||||
'1': {
|
||||
segmentIndex: 1,
|
||||
label: 'Segment 1',
|
||||
cachedStats: {
|
||||
namedStats: {
|
||||
count: {
|
||||
name: 'count',
|
||||
label: 'Count',
|
||||
value: 42,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
generateSegmentationCSVReport(segmentationData, mockInfo);
|
||||
|
||||
const csvContent = (global.Blob as jest.Mock).mock.calls[0][0][0];
|
||||
expect(csvContent).toContain('Count,42');
|
||||
});
|
||||
|
||||
it('should handle segments without cachedStats', () => {
|
||||
const segmentationData = {
|
||||
segmentationId: 'seg-123',
|
||||
segments: {
|
||||
'1': {
|
||||
segmentIndex: 1,
|
||||
label: 'Segment 1',
|
||||
locked: false,
|
||||
active: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
generateSegmentationCSVReport(segmentationData, mockInfo);
|
||||
|
||||
expect(global.Blob).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle segments with empty namedStats', () => {
|
||||
const segmentationData = {
|
||||
segmentationId: 'seg-123',
|
||||
segments: {
|
||||
'1': {
|
||||
segmentIndex: 1,
|
||||
label: 'Segment 1',
|
||||
cachedStats: {
|
||||
namedStats: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
generateSegmentationCSVReport(segmentationData, mockInfo);
|
||||
|
||||
expect(global.Blob).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should escape CSV special characters', () => {
|
||||
const segmentationData = {
|
||||
segmentationId: 'seg,with,commas',
|
||||
label: 'Test "quoted" label',
|
||||
segments: {
|
||||
'1': {
|
||||
segmentIndex: 1,
|
||||
label: 'Segment\nwith\nnewlines',
|
||||
cachedStats: {
|
||||
namedStats: {
|
||||
test: {
|
||||
name: 'test',
|
||||
label: 'Test,Value',
|
||||
value: 'value"with"quotes',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
generateSegmentationCSVReport(segmentationData, mockInfo);
|
||||
|
||||
const csvContent = (global.Blob as jest.Mock).mock.calls[0][0][0];
|
||||
expect(csvContent).toContain('"seg,with,commas"');
|
||||
expect(csvContent).toContain('"Test ""quoted"" label"');
|
||||
expect(csvContent).toContain('"Segment\nwith\nnewlines"');
|
||||
});
|
||||
|
||||
it('should create download link with correct attributes', () => {
|
||||
const mockLink = {
|
||||
setAttribute: jest.fn(),
|
||||
click: jest.fn(),
|
||||
style: {},
|
||||
};
|
||||
mockDocument.createElement.mockReturnValue(mockLink);
|
||||
|
||||
const segmentationData = {
|
||||
segmentationId: 'seg-123',
|
||||
label: 'Test Segmentation',
|
||||
};
|
||||
|
||||
generateSegmentationCSVReport(segmentationData, mockInfo);
|
||||
|
||||
expect(mockLink.setAttribute).toHaveBeenCalledWith('href', 'mock-url');
|
||||
expect(mockLink.setAttribute).toHaveBeenCalledWith(
|
||||
'download',
|
||||
expect.stringMatching(/Test Segmentation_Report_\d{4}-\d{2}-\d{2}\.csv/)
|
||||
);
|
||||
expect(mockLink.click).toHaveBeenCalled();
|
||||
expect(mockDocument.body.appendChild).toHaveBeenCalledWith(mockLink);
|
||||
expect(mockDocument.body.removeChild).toHaveBeenCalledWith(mockLink);
|
||||
});
|
||||
|
||||
it('should use default filename when label is missing', () => {
|
||||
const mockLink = {
|
||||
setAttribute: jest.fn(),
|
||||
click: jest.fn(),
|
||||
style: {},
|
||||
};
|
||||
mockDocument.createElement.mockReturnValue(mockLink);
|
||||
|
||||
const segmentationData = {
|
||||
segmentationId: 'seg-123',
|
||||
};
|
||||
|
||||
generateSegmentationCSVReport(segmentationData, mockInfo);
|
||||
|
||||
expect(mockLink.setAttribute).toHaveBeenCalledWith(
|
||||
'download',
|
||||
expect.stringMatching(/Segmentation_Report_\d{4}-\d{2}-\d{2}\.csv/)
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import { getViewportEnabledElement } from './getViewportEnabledElement';
|
||||
import getActiveViewportEnabledElement from './getActiveViewportEnabledElement';
|
||||
|
||||
jest.mock('./getViewportEnabledElement', () => ({
|
||||
getViewportEnabledElement: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('getActiveViewportEnabledElement', () => {
|
||||
const mockViewportGridService = {
|
||||
getState: jest.fn(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should return enabled element for active viewport', () => {
|
||||
const mockEnabledElement = { viewport: 'test-viewport' };
|
||||
mockViewportGridService.getState.mockReturnValue({ activeViewportId: 'viewport-1' });
|
||||
(getViewportEnabledElement as jest.Mock).mockReturnValue(mockEnabledElement);
|
||||
|
||||
const result = getActiveViewportEnabledElement(mockViewportGridService);
|
||||
|
||||
expect(mockViewportGridService.getState).toHaveBeenCalledTimes(1);
|
||||
expect(getViewportEnabledElement).toHaveBeenCalledWith('viewport-1');
|
||||
expect(result).toBe(mockEnabledElement);
|
||||
});
|
||||
|
||||
it('should handle null activeViewportId', () => {
|
||||
const mockEnabledElement = null;
|
||||
mockViewportGridService.getState.mockReturnValue({ activeViewportId: null });
|
||||
(getViewportEnabledElement as jest.Mock).mockReturnValue(mockEnabledElement);
|
||||
|
||||
const result = getActiveViewportEnabledElement(mockViewportGridService);
|
||||
|
||||
expect(getViewportEnabledElement).toHaveBeenCalledWith(null);
|
||||
expect(result).toBe(null);
|
||||
});
|
||||
|
||||
it('should handle undefined activeViewportId', () => {
|
||||
const mockEnabledElement = undefined;
|
||||
mockViewportGridService.getState.mockReturnValue({ activeViewportId: undefined });
|
||||
(getViewportEnabledElement as jest.Mock).mockReturnValue(mockEnabledElement);
|
||||
|
||||
const result = getActiveViewportEnabledElement(mockViewportGridService);
|
||||
|
||||
expect(getViewportEnabledElement).toHaveBeenCalledWith(undefined);
|
||||
expect(result).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should handle empty state object', () => {
|
||||
const mockEnabledElement = undefined;
|
||||
mockViewportGridService.getState.mockReturnValue({});
|
||||
(getViewportEnabledElement as jest.Mock).mockReturnValue(mockEnabledElement);
|
||||
|
||||
const result = getActiveViewportEnabledElement(mockViewportGridService);
|
||||
|
||||
expect(getViewportEnabledElement).toHaveBeenCalledWith(undefined);
|
||||
expect(result).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should handle getViewportEnabledElement returning null', () => {
|
||||
mockViewportGridService.getState.mockReturnValue({ activeViewportId: 'viewport-1' });
|
||||
(getViewportEnabledElement as jest.Mock).mockReturnValue(null);
|
||||
|
||||
const result = getActiveViewportEnabledElement(mockViewportGridService);
|
||||
|
||||
expect(result).toBe(null);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,313 @@
|
||||
import { getCenterExtent } from './getCenterExtent';
|
||||
|
||||
describe('getCenterExtent', () => {
|
||||
it('should return default values when points is undefined', () => {
|
||||
const measurement = {};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [0, 0, 0],
|
||||
extent: {
|
||||
min: [0, 0, 0],
|
||||
max: [0, 0, 0],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should return default values when points is null', () => {
|
||||
const measurement = { points: null };
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [0, 0, 0],
|
||||
extent: {
|
||||
min: [0, 0, 0],
|
||||
max: [0, 0, 0],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should return default values when points is not an array', () => {
|
||||
const measurement = { points: 'invalid' };
|
||||
|
||||
// @ts-expect-error - purposely passing an invalid type
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [0, 0, 0],
|
||||
extent: {
|
||||
min: [0, 0, 0],
|
||||
max: [0, 0, 0],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should return default values when points array is empty', () => {
|
||||
const measurement = { points: [] };
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [0, 0, 0],
|
||||
extent: {
|
||||
min: [0, 0, 0],
|
||||
max: [0, 0, 0],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle single point correctly', () => {
|
||||
const measurement = {
|
||||
points: [[5, 10, 15]],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [5, 10, 15],
|
||||
extent: {
|
||||
min: [5, 10, 15],
|
||||
max: [5, 10, 15],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should calculate center and extent for two points', () => {
|
||||
const measurement = {
|
||||
points: [
|
||||
[0, 0, 0],
|
||||
[10, 20, 30],
|
||||
],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [5, 10, 15],
|
||||
extent: {
|
||||
min: [0, 0, 0],
|
||||
max: [10, 20, 30],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should calculate center and extent for multiple points', () => {
|
||||
const measurement = {
|
||||
points: [
|
||||
[0, 0, 0],
|
||||
[10, 20, 30],
|
||||
[5, 5, 5],
|
||||
[-5, 15, 25],
|
||||
],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [2.5, 10, 15],
|
||||
extent: {
|
||||
min: [-5, 0, 0],
|
||||
max: [10, 20, 30],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle negative coordinates', () => {
|
||||
const measurement = {
|
||||
points: [
|
||||
[-10, -20, -30],
|
||||
[-5, -15, -25],
|
||||
],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [-7.5, -17.5, -27.5],
|
||||
extent: {
|
||||
min: [-10, -20, -30],
|
||||
max: [-5, -15, -25],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle mixed positive and negative coordinates', () => {
|
||||
const measurement = {
|
||||
points: [
|
||||
[-10, -5, 0],
|
||||
[10, 5, 20],
|
||||
[0, 0, -10],
|
||||
],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [0, 0, 5],
|
||||
extent: {
|
||||
min: [-10, -5, -10],
|
||||
max: [10, 5, 20],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle floating point coordinates', () => {
|
||||
const measurement = {
|
||||
points: [
|
||||
[1.5, 2.3, 3.1],
|
||||
[4.2, 8.9, 6.3],
|
||||
],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [2.85, 5.6, 4.7],
|
||||
extent: {
|
||||
min: [1.5, 2.3, 3.1],
|
||||
max: [4.2, 8.9, 6.3],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle points with same coordinates', () => {
|
||||
const measurement = {
|
||||
points: [
|
||||
[5, 5, 5],
|
||||
[5, 5, 5],
|
||||
[5, 5, 5],
|
||||
],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [5, 5, 5],
|
||||
extent: {
|
||||
min: [5, 5, 5],
|
||||
max: [5, 5, 5],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle zero coordinates', () => {
|
||||
const measurement = {
|
||||
points: [
|
||||
[0, 0, 0],
|
||||
[0, 0, 0],
|
||||
],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [0, 0, 0],
|
||||
extent: {
|
||||
min: [0, 0, 0],
|
||||
max: [0, 0, 0],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle large coordinate values', () => {
|
||||
const measurement = {
|
||||
points: [
|
||||
[1000000, 2000000, 3000000],
|
||||
[1000001, 2000001, 3000001],
|
||||
],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [1000000.5, 2000000.5, 3000000.5],
|
||||
extent: {
|
||||
min: [1000000, 2000000, 3000000],
|
||||
max: [1000001, 2000001, 3000001],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle points in different order', () => {
|
||||
const measurement = {
|
||||
points: [
|
||||
[10, 20, 30],
|
||||
[0, 0, 0],
|
||||
[5, 10, 15],
|
||||
],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [5, 10, 15],
|
||||
extent: {
|
||||
min: [0, 0, 0],
|
||||
max: [10, 20, 30],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle points where min and max are not the first point', () => {
|
||||
const measurement = {
|
||||
points: [
|
||||
[5, 5, 5],
|
||||
[0, 0, 0],
|
||||
[10, 10, 10],
|
||||
[3, 3, 3],
|
||||
],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [5, 5, 5],
|
||||
extent: {
|
||||
min: [0, 0, 0],
|
||||
max: [10, 10, 10],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle asymmetric extent distribution', () => {
|
||||
const measurement = {
|
||||
points: [
|
||||
[0, 0, 0],
|
||||
[100, 10, 1],
|
||||
[50, 50, 50],
|
||||
],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [50, 25, 25],
|
||||
extent: {
|
||||
min: [0, 0, 0],
|
||||
max: [100, 50, 50],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle points with different ranges per dimension', () => {
|
||||
const measurement = {
|
||||
points: [
|
||||
[0, 100, 1000],
|
||||
[1, 101, 1001],
|
||||
[0.5, 100.5, 1000.5],
|
||||
],
|
||||
};
|
||||
|
||||
const result = getCenterExtent(measurement);
|
||||
|
||||
expect(result).toEqual({
|
||||
center: [0.5, 100.5, 1000.5],
|
||||
extent: {
|
||||
min: [0, 100, 1000],
|
||||
max: [1, 101, 1001],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Calculates the center point and bounding box extent of a measurement based on its points.
|
||||
* @param {Object} measurement - The measurement object containing points
|
||||
* @param {Array<Array<number>>} measurement.points - Array of 3D points [x, y, z]
|
||||
* @returns {Object} Object containing center and extent
|
||||
* @returns {Array<number>} returns.center - The center point [x, y, z]
|
||||
* @returns {Object} returns.extent - The bounding box extent with min and max points
|
||||
*/
|
||||
export const getCenterExtent = (measurement: { points?: number[][] }) => {
|
||||
const { points } = measurement;
|
||||
|
||||
if (!points || !Array.isArray(points) || points.length === 0) {
|
||||
// Return default values if no points are available
|
||||
const defaultCenter: [number, number, number] = [0, 0, 0];
|
||||
const defaultExtent = {
|
||||
min: [0, 0, 0] as [number, number, number],
|
||||
max: [0, 0, 0] as [number, number, number],
|
||||
};
|
||||
return { center: defaultCenter, extent: defaultExtent };
|
||||
}
|
||||
|
||||
// Initialize min and max with the first point
|
||||
const min: [number, number, number] = [...points[0]] as [number, number, number];
|
||||
const max: [number, number, number] = [...points[0]] as [number, number, number];
|
||||
|
||||
// Find the bounding box by iterating through all points
|
||||
for (let i = 1; i < points.length; i++) {
|
||||
const point = points[i];
|
||||
for (let j = 0; j < 3; j++) {
|
||||
min[j] = Math.min(min[j], point[j]);
|
||||
max[j] = Math.max(max[j], point[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the center point
|
||||
const center: [number, number, number] = [
|
||||
(min[0] + max[0]) / 2,
|
||||
(min[1] + max[1]) / 2,
|
||||
(min[2] + max[2]) / 2,
|
||||
];
|
||||
|
||||
return {
|
||||
center,
|
||||
extent: { min, max },
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
import { Enums } from '@cornerstonejs/core';
|
||||
import getCornerstoneBlendMode from './getCornerstoneBlendMode';
|
||||
|
||||
jest.mock('@cornerstonejs/core', () => ({
|
||||
Enums: {
|
||||
BlendModes: {
|
||||
COMPOSITE: 'composite',
|
||||
MAXIMUM_INTENSITY_BLEND: 'mip',
|
||||
MINIMUM_INTENSITY_BLEND: 'minip',
|
||||
AVERAGE_INTENSITY_BLEND: 'avg',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('getCornerstoneBlendMode', () => {
|
||||
it('should return COMPOSITE when blendMode is null', () => {
|
||||
const result = getCornerstoneBlendMode(null);
|
||||
expect(result).toBe(Enums.BlendModes.COMPOSITE);
|
||||
});
|
||||
|
||||
it('should return COMPOSITE when blendMode is undefined', () => {
|
||||
const result = getCornerstoneBlendMode(undefined);
|
||||
expect(result).toBe(Enums.BlendModes.COMPOSITE);
|
||||
});
|
||||
|
||||
it('should return COMPOSITE when blendMode is empty string', () => {
|
||||
const result = getCornerstoneBlendMode('');
|
||||
expect(result).toBe(Enums.BlendModes.COMPOSITE);
|
||||
});
|
||||
|
||||
it('should return MAXIMUM_INTENSITY_BLEND when blendMode is mip', () => {
|
||||
const result = getCornerstoneBlendMode('mip');
|
||||
expect(result).toBe(Enums.BlendModes.MAXIMUM_INTENSITY_BLEND);
|
||||
});
|
||||
|
||||
it('should return MAXIMUM_INTENSITY_BLEND when blendMode is MIP (uppercase)', () => {
|
||||
const result = getCornerstoneBlendMode('MIP');
|
||||
expect(result).toBe(Enums.BlendModes.MAXIMUM_INTENSITY_BLEND);
|
||||
});
|
||||
|
||||
it('should return MINIMUM_INTENSITY_BLEND when blendMode is MINIP (uppercase)', () => {
|
||||
const result = getCornerstoneBlendMode('MINIP');
|
||||
expect(result).toBe(Enums.BlendModes.MINIMUM_INTENSITY_BLEND);
|
||||
});
|
||||
|
||||
it('should return AVERAGE_INTENSITY_BLEND when blendMode is avg', () => {
|
||||
const result = getCornerstoneBlendMode('avg');
|
||||
expect(result).toBe(Enums.BlendModes.AVERAGE_INTENSITY_BLEND);
|
||||
});
|
||||
|
||||
it('should throw error for unsupported blend mode', () => {
|
||||
expect(() => getCornerstoneBlendMode('invalid')).toThrow('Unsupported blend mode: invalid');
|
||||
});
|
||||
|
||||
it('should handle mixed case blend mode', () => {
|
||||
const result = getCornerstoneBlendMode('MiP');
|
||||
expect(result).toBe(Enums.BlendModes.MAXIMUM_INTENSITY_BLEND);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Enums } from '@cornerstonejs/core';
|
||||
import getCornerstoneOrientation from './getCornerstoneOrientation';
|
||||
|
||||
jest.mock('@cornerstonejs/core', () => ({
|
||||
Enums: {
|
||||
OrientationAxis: {
|
||||
AXIAL: 'axial',
|
||||
SAGITTAL: 'sagittal',
|
||||
CORONAL: 'coronal',
|
||||
ACQUISITION: 'acquisition',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('getCornerstoneOrientation', () => {
|
||||
it('should return AXIAL when orientation is axial', () => {
|
||||
const result = getCornerstoneOrientation('axial');
|
||||
expect(result).toBe(Enums.OrientationAxis.AXIAL);
|
||||
});
|
||||
|
||||
it('should return AXIAL when orientation is AXIAL (uppercase)', () => {
|
||||
const result = getCornerstoneOrientation('AXIAL');
|
||||
expect(result).toBe(Enums.OrientationAxis.AXIAL);
|
||||
});
|
||||
|
||||
it('should return SAGITTAL when orientation is sagittal', () => {
|
||||
const result = getCornerstoneOrientation('sagittal');
|
||||
expect(result).toBe(Enums.OrientationAxis.SAGITTAL);
|
||||
});
|
||||
|
||||
it('should return CORONAL when orientation is coronal', () => {
|
||||
const result = getCornerstoneOrientation('coronal');
|
||||
expect(result).toBe(Enums.OrientationAxis.CORONAL);
|
||||
});
|
||||
|
||||
it('should return ACQUISITION for unknown orientation', () => {
|
||||
const result = getCornerstoneOrientation('unknown');
|
||||
expect(result).toBe(Enums.OrientationAxis.ACQUISITION);
|
||||
});
|
||||
|
||||
it('should return ACQUISITION when orientation is null', () => {
|
||||
const result = getCornerstoneOrientation(null);
|
||||
expect(result).toBe(Enums.OrientationAxis.ACQUISITION);
|
||||
});
|
||||
|
||||
it('should return ACQUISITION when orientation is undefined', () => {
|
||||
const result = getCornerstoneOrientation(undefined);
|
||||
expect(result).toBe(Enums.OrientationAxis.ACQUISITION);
|
||||
});
|
||||
|
||||
it('should return ACQUISITION when orientation is empty string', () => {
|
||||
const result = getCornerstoneOrientation('');
|
||||
expect(result).toBe(Enums.OrientationAxis.ACQUISITION);
|
||||
});
|
||||
|
||||
it('should handle mixed case orientation', () => {
|
||||
const result = getCornerstoneOrientation('CoRoNaL');
|
||||
expect(result).toBe(Enums.OrientationAxis.CORONAL);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,91 @@
|
||||
import type { Types } from '@ohif/core';
|
||||
import { Enums } from '@cornerstonejs/core';
|
||||
import getCornerstoneViewportType from './getCornerstoneViewportType';
|
||||
|
||||
jest.mock('@cornerstonejs/core', () => ({
|
||||
Enums: {
|
||||
ViewportType: {
|
||||
STACK: 'stack',
|
||||
VIDEO: 'video',
|
||||
WHOLE_SLIDE: 'wholeslide',
|
||||
ORTHOGRAPHIC: 'orthographic',
|
||||
VOLUME_3D: 'volume3d',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('getCornerstoneViewportType', () => {
|
||||
it('should return STACK when viewportType is stack', () => {
|
||||
const result = getCornerstoneViewportType('stack');
|
||||
expect(result).toBe(Enums.ViewportType.STACK);
|
||||
});
|
||||
|
||||
it('should return STACK when viewportType is STACK (uppercase)', () => {
|
||||
const result = getCornerstoneViewportType('STACK');
|
||||
expect(result).toBe(Enums.ViewportType.STACK);
|
||||
});
|
||||
|
||||
it('should return VIDEO when viewportType is video', () => {
|
||||
const result = getCornerstoneViewportType('video');
|
||||
expect(result).toBe(Enums.ViewportType.VIDEO);
|
||||
});
|
||||
|
||||
it('should return WHOLE_SLIDE when viewportType is wholeslide', () => {
|
||||
const result = getCornerstoneViewportType('wholeslide');
|
||||
expect(result).toBe(Enums.ViewportType.WHOLE_SLIDE);
|
||||
});
|
||||
|
||||
it('should return ORTHOGRAPHIC when viewportType is volume', () => {
|
||||
const result = getCornerstoneViewportType('volume');
|
||||
expect(result).toBe(Enums.ViewportType.ORTHOGRAPHIC);
|
||||
});
|
||||
|
||||
it('should return ORTHOGRAPHIC when viewportType is orthographic', () => {
|
||||
const result = getCornerstoneViewportType('orthographic');
|
||||
expect(result).toBe(Enums.ViewportType.ORTHOGRAPHIC);
|
||||
});
|
||||
|
||||
it('should return VOLUME_3D when viewportType is volume3d', () => {
|
||||
const result = getCornerstoneViewportType('volume3d');
|
||||
expect(result).toBe(Enums.ViewportType.VOLUME_3D);
|
||||
});
|
||||
|
||||
it('should throw error for invalid viewport type', () => {
|
||||
expect(() => getCornerstoneViewportType('invalid')).toThrow(
|
||||
'Invalid viewport type: invalid. Valid types are: stack, volume, video, wholeslide'
|
||||
);
|
||||
});
|
||||
|
||||
it('should use displaySet viewportType when provided', () => {
|
||||
const displaySets = [{ viewportType: 'stack' }] as Types.DisplaySet[];
|
||||
const result = getCornerstoneViewportType('volume', displaySets);
|
||||
expect(result).toBe(Enums.ViewportType.STACK);
|
||||
});
|
||||
|
||||
it('should use displaySet viewportType with case insensitive matching', () => {
|
||||
const displaySets = [{ viewportType: 'VIDEO' }] as Types.DisplaySet[];
|
||||
const result = getCornerstoneViewportType('stack', displaySets);
|
||||
expect(result).toBe(Enums.ViewportType.VIDEO);
|
||||
});
|
||||
|
||||
it('should fallback to viewportType when displaySet has no viewportType', () => {
|
||||
const displaySets = [{}] as Types.DisplaySet[];
|
||||
const result = getCornerstoneViewportType('volume', displaySets);
|
||||
expect(result).toBe(Enums.ViewportType.ORTHOGRAPHIC);
|
||||
});
|
||||
|
||||
it('should handle empty displaySets array', () => {
|
||||
const result = getCornerstoneViewportType('stack', []);
|
||||
expect(result).toBe(Enums.ViewportType.STACK);
|
||||
});
|
||||
|
||||
it('should handle null displaySets', () => {
|
||||
const result = getCornerstoneViewportType('video', null);
|
||||
expect(result).toBe(Enums.ViewportType.VIDEO);
|
||||
});
|
||||
|
||||
it('should handle undefined displaySets', () => {
|
||||
const result = getCornerstoneViewportType('wholeslide', undefined);
|
||||
expect(result).toBe(Enums.ViewportType.WHOLE_SLIDE);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,85 @@
|
||||
import getInterleavedFrames from './getInterleavedFrames';
|
||||
|
||||
describe('getInterleavedFrames', () => {
|
||||
it('should return single element when input has one element', () => {
|
||||
const imageIds = ['image-1'];
|
||||
const result = getInterleavedFrames(imageIds);
|
||||
|
||||
expect(result).toEqual([{ imageId: 'image-1', imageIdIndex: 0 }]);
|
||||
});
|
||||
|
||||
it('should return correct order for three elements', () => {
|
||||
const imageIds = ['image-1', 'image-2', 'image-3'];
|
||||
const result = getInterleavedFrames(imageIds);
|
||||
|
||||
expect(result).toEqual([
|
||||
{ imageId: 'image-2', imageIdIndex: 1 },
|
||||
{ imageId: 'image-1', imageIdIndex: 0 },
|
||||
{ imageId: 'image-3', imageIdIndex: 2 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should start with middle element', () => {
|
||||
const imageIds = ['image-1', 'image-2', 'image-3', 'image-4', 'image-5'];
|
||||
const result = getInterleavedFrames(imageIds);
|
||||
|
||||
expect(result[0]).toEqual({ imageId: 'image-3', imageIdIndex: 2 });
|
||||
});
|
||||
|
||||
it('should interleave elements correctly for even length array', () => {
|
||||
const imageIds = ['image-1', 'image-2', 'image-3', 'image-4', 'image-5', 'image-6'];
|
||||
const result = getInterleavedFrames(imageIds);
|
||||
|
||||
expect(result).toEqual([
|
||||
{ imageId: 'image-4', imageIdIndex: 3 },
|
||||
{ imageId: 'image-3', imageIdIndex: 2 },
|
||||
{ imageId: 'image-5', imageIdIndex: 4 },
|
||||
{ imageId: 'image-2', imageIdIndex: 1 },
|
||||
{ imageId: 'image-6', imageIdIndex: 5 },
|
||||
{ imageId: 'image-1', imageIdIndex: 0 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should interleave elements correctly for odd length array', () => {
|
||||
const imageIds = ['image-1', 'image-2', 'image-3', 'image-4', 'image-5', 'image-6', 'image-7'];
|
||||
const result = getInterleavedFrames(imageIds);
|
||||
|
||||
expect(result).toEqual([
|
||||
{ imageId: 'image-4', imageIdIndex: 3 },
|
||||
{ imageId: 'image-3', imageIdIndex: 2 },
|
||||
{ imageId: 'image-5', imageIdIndex: 4 },
|
||||
{ imageId: 'image-2', imageIdIndex: 1 },
|
||||
{ imageId: 'image-6', imageIdIndex: 5 },
|
||||
{ imageId: 'image-1', imageIdIndex: 0 },
|
||||
{ imageId: 'image-7', imageIdIndex: 6 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle large array correctly', () => {
|
||||
const imageIds = Array.from({ length: 10 }, (_, i) => `image-${i + 1}`);
|
||||
const result = getInterleavedFrames(imageIds);
|
||||
|
||||
expect(result).toHaveLength(10);
|
||||
expect(result[0]).toEqual({ imageId: 'image-6', imageIdIndex: 5 });
|
||||
expect(result[8]).toEqual({ imageId: 'image-10', imageIdIndex: 9 });
|
||||
expect(result[9]).toEqual({ imageId: 'image-1', imageIdIndex: 0 });
|
||||
});
|
||||
|
||||
it('should handle empty array', () => {
|
||||
const imageIds = [];
|
||||
const result = getInterleavedFrames(imageIds);
|
||||
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle duplicate imageIds with different indices', () => {
|
||||
const imageIds = ['duplicate', 'unique', 'duplicate'];
|
||||
const result = getInterleavedFrames(imageIds);
|
||||
|
||||
expect(result).toEqual([
|
||||
{ imageId: 'unique', imageIdIndex: 1 },
|
||||
{ imageId: 'duplicate', imageIdIndex: 0 },
|
||||
{ imageId: 'duplicate', imageIdIndex: 2 },
|
||||
]);
|
||||
});
|
||||
});
|
||||
+15
-2
@@ -1,4 +1,17 @@
|
||||
export default function getInterleavedFrames(imageIds) {
|
||||
interface ImageIdToPrefetch {
|
||||
imageId: string;
|
||||
imageIdIndex: number;
|
||||
}
|
||||
|
||||
export default function getInterleavedFrames(imageIds: string[]): ImageIdToPrefetch[] {
|
||||
if (imageIds.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (imageIds.length === 1) {
|
||||
return [{ imageId: imageIds[0], imageIdIndex: 0 }];
|
||||
}
|
||||
|
||||
const minImageIdIndex = 0;
|
||||
const maxImageIdIndex = imageIds.length - 1;
|
||||
|
||||
@@ -8,7 +21,7 @@ export default function getInterleavedFrames(imageIds) {
|
||||
let upperImageIdIndex = middleImageIdIndex;
|
||||
|
||||
// Build up an array of images to prefetch, starting with the current image.
|
||||
const imageIdsToPrefetch = [
|
||||
const imageIdsToPrefetch: ImageIdToPrefetch[] = [
|
||||
{ imageId: imageIds[middleImageIdIndex], imageIdIndex: middleImageIdIndex },
|
||||
];
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
import getNthFrames from './getNthFrames';
|
||||
|
||||
describe('getNthFrames', () => {
|
||||
const createMockImageLoadRequest = (imageId: string, imageIdIndex: number) => ({
|
||||
imageId,
|
||||
callLoadImage: jest.fn(),
|
||||
additionalDetails: 'test-details',
|
||||
imageIdIndex,
|
||||
options: { test: 'option' },
|
||||
});
|
||||
|
||||
it('should return empty array when input is empty', () => {
|
||||
const result = getNthFrames([]);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return same array when input has one element', () => {
|
||||
const imageIds = [createMockImageLoadRequest('image-1', 0)];
|
||||
const result = getNthFrames(imageIds);
|
||||
expect(result).toEqual(imageIds);
|
||||
});
|
||||
|
||||
it('should return same array when input has two elements', () => {
|
||||
const imageIds = [
|
||||
createMockImageLoadRequest('image-1', 0),
|
||||
createMockImageLoadRequest('image-2', 1),
|
||||
];
|
||||
const result = getNthFrames(imageIds);
|
||||
expect(result).toEqual(imageIds);
|
||||
});
|
||||
|
||||
it('should prioritize first two elements', () => {
|
||||
const imageIds = Array.from({ length: 10 }, (_, i) =>
|
||||
createMockImageLoadRequest(`image-${i}`, i)
|
||||
);
|
||||
const result = getNthFrames(imageIds);
|
||||
|
||||
expect(result[0]).toBe(imageIds[0]);
|
||||
expect(result[1]).toBe(imageIds[1]);
|
||||
});
|
||||
|
||||
it('should prioritize last three elements', () => {
|
||||
const imageIds = Array.from({ length: 10 }, (_, i) =>
|
||||
createMockImageLoadRequest(`image-${i}`, i)
|
||||
);
|
||||
const result = getNthFrames(imageIds);
|
||||
|
||||
expect(result).toContain(imageIds[7]);
|
||||
expect(result).toContain(imageIds[8]);
|
||||
expect(result).toContain(imageIds[9]);
|
||||
});
|
||||
|
||||
it('should include center elements', () => {
|
||||
const imageIds = Array.from({ length: 20 }, (_, i) =>
|
||||
createMockImageLoadRequest(`image-${i}`, i)
|
||||
);
|
||||
const result = getNthFrames(imageIds);
|
||||
const centerStart = imageIds.length / 2 - 3;
|
||||
const centerEnd = centerStart + 6;
|
||||
|
||||
for (let i = Math.ceil(centerStart); i < centerEnd; i++) {
|
||||
if (i >= 0 && i < imageIds.length) {
|
||||
expect(result).toContain(imageIds[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should include nth elements where i % 7 === 2', () => {
|
||||
const imageIds = Array.from({ length: 30 }, (_, i) =>
|
||||
createMockImageLoadRequest(`image-${i}`, i)
|
||||
);
|
||||
const result = getNthFrames(imageIds);
|
||||
|
||||
for (let i = 0; i < imageIds.length; i++) {
|
||||
if (i % 7 === 2 && i >= 2 && i <= imageIds.length - 4) {
|
||||
const centerStart = imageIds.length / 2 - 3;
|
||||
const centerEnd = centerStart + 6;
|
||||
if (!(i > centerStart && i < centerEnd)) {
|
||||
expect(result).toContain(imageIds[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should include nth elements where i % 7 === 5', () => {
|
||||
const imageIds = Array.from({ length: 30 }, (_, i) =>
|
||||
createMockImageLoadRequest(`image-${i}`, i)
|
||||
);
|
||||
const result = getNthFrames(imageIds);
|
||||
|
||||
for (let i = 0; i < imageIds.length; i++) {
|
||||
if (i % 7 === 5 && i >= 2 && i <= imageIds.length - 4) {
|
||||
const centerStart = imageIds.length / 2 - 3;
|
||||
const centerEnd = centerStart + 6;
|
||||
if (!(i > centerStart && i < centerEnd)) {
|
||||
expect(result).toContain(imageIds[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should handle large arrays correctly', () => {
|
||||
const imageIds = Array.from({ length: 100 }, (_, i) =>
|
||||
createMockImageLoadRequest(`image-${i}`, i)
|
||||
);
|
||||
const result = getNthFrames(imageIds);
|
||||
|
||||
expect(result.length).toBe(100);
|
||||
expect(result[0]).toBe(imageIds[0]);
|
||||
expect(result[1]).toBe(imageIds[1]);
|
||||
expect(result).toContain(imageIds[97]);
|
||||
expect(result).toContain(imageIds[98]);
|
||||
expect(result).toContain(imageIds[99]);
|
||||
});
|
||||
|
||||
it('should handle arrays where centerStart is negative', () => {
|
||||
const imageIds = Array.from({ length: 3 }, (_, i) =>
|
||||
createMockImageLoadRequest(`image-${i}`, i)
|
||||
);
|
||||
const result = getNthFrames(imageIds);
|
||||
|
||||
expect(result).toEqual(imageIds);
|
||||
});
|
||||
|
||||
it('should handle arrays where centerEnd exceeds length', () => {
|
||||
const imageIds = Array.from({ length: 4 }, (_, i) =>
|
||||
createMockImageLoadRequest(`image-${i}`, i)
|
||||
);
|
||||
const result = getNthFrames(imageIds);
|
||||
|
||||
expect(result).toEqual(expect.arrayContaining(imageIds));
|
||||
expect(result.length).toBe(4);
|
||||
});
|
||||
|
||||
it('should preserve object references', () => {
|
||||
const imageIds = Array.from({ length: 10 }, (_, i) =>
|
||||
createMockImageLoadRequest(`image-${i}`, i)
|
||||
);
|
||||
const result = getNthFrames(imageIds);
|
||||
|
||||
result.forEach(item => {
|
||||
expect(imageIds).toContain(item);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loaded 100 of 887 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user