docs(faq, migrations, orthanc): Add FAQ for dynamic measurements, migration guides, and fix orthanc docker (#4217)

This commit is contained in:
Alireza 2024-06-08 08:52:03 -04:00 committed by GitHub
parent f044587b73
commit 4a3b37c6bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 654 additions and 290 deletions

View File

@ -24,9 +24,15 @@ const tools = {
},
{ toolName: toolNames.StackScrollMouseWheel, bindings: [] },
],
enabled: [{ toolName: toolNames.SegmentationDisplay }, { toolName: toolNames.PlanarFreehandContourSegmentation, configuration: {
displayOnePointAsCrosshairs: true,
}}],
enabled: [
{ toolName: toolNames.SegmentationDisplay },
{
toolName: toolNames.PlanarFreehandContourSegmentation,
configuration: {
displayOnePointAsCrosshairs: true,
},
},
],
};
function getCustomizationModule() {

View File

@ -36,7 +36,7 @@
"dev:orthanc:no:cache": "lerna run dev:orthanc:no:cache --stream",
"dev:dcm4chee": "lerna run dev:dcm4chee --stream",
"dev:static": "lerna run dev:static --stream",
"orthanc:up": "docker-compose -f platform/app/.recipes/OpenResty-Orthanc/docker-compose.yml up",
"orthanc:up": "docker-compose -f platform/app/.recipes/Nginx-Orthanc/docker-compose.yml up",
"preinstall": "node preinstall.js",
"start": "yarn run dev",
"test": "yarn run test:unit",

View File

@ -0,0 +1,2 @@
logs/*
volumes/*

View File

@ -0,0 +1,86 @@
worker_processes 2;
error_log /var/logs/nginx/mydomain.error.log;
pid /var/run/nginx.pid;
include /usr/share/nginx/modules/*.conf; # See /usr/share/doc/nginx/README.dynamic.
events {
worker_connections 1024; ## Default: 1024
use epoll; # http://nginx.org/en/docs/events.html
multi_accept on; # http://nginx.org/en/docs/ngx_core_module.html#multi_accept
}
# Core Modules Docs:
# http://nginx.org/en/docs/http/ngx_http_core_module.html
http {
include '/etc/nginx/mime.types';
default_type application/octet-stream;
keepalive_timeout 65;
keepalive_requests 100000;
tcp_nopush on;
tcp_nodelay on;
# Nginx `listener` block
server {
listen [::]:80 default_server;
listen 80;
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
gzip_comp_level 9;
etag on;
# Reverse Proxy for `orthanc` APIs (including DICOMWeb)
#
location /pacs/ {
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
expires 0;
add_header Cache-Control private;
# Add CORS headers
# Note: uncomment the following line to allow all domains to access the Orthanc APIs
# You should actually only allow the domains you trust to access the APIs
# add_header 'Access-Control-Allow-Origin' '*' always;
proxy_pass http://orthanc:8042/;
# By default, this endpoint is protected by CORS (cross-origin-resource-sharing)
# You can add headers to allow other domains to request this resource.
# See the "Updating CORS Settings" example below
}
# Do not cache sw.js, required for offline-first updates.
location /sw.js {
add_header Cache-Control "no-cache";
proxy_cache_bypass $http_pragma;
proxy_cache_revalidate on;
expires off;
access_log off;
}
# Single Page App
# Try files, fallback to index.html
#
location / {
root /var/www/html;
index index.html;
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-store, no-cache, must-revalidate";
add_header 'Cross-Origin-Opener-Policy' 'same-origin' always;
add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always;
}
}
}

View File

@ -0,0 +1,89 @@
{
"Name": "Orthanc inside Docker",
"StorageDirectory": "/var/lib/orthanc/db",
"IndexDirectory": "/var/lib/orthanc/db",
"StorageCompression": false,
"MaximumStorageSize": 0,
"MaximumPatientCount": 0,
"LuaScripts": [],
"Plugins": ["/usr/share/orthanc/plugins", "/usr/local/share/orthanc/plugins"],
"ConcurrentJobs": 2,
"HttpServerEnabled": true,
"HttpPort": 8042,
"HttpDescribeErrors": true,
"HttpCompressionEnabled": true,
"DicomServerEnabled": true,
"DicomAet": "ORTHANC",
"DicomCheckCalledAet": false,
"DicomPort": 4242,
"DefaultEncoding": "Latin1",
"DeflatedTransferSyntaxAccepted": true,
"JpegTransferSyntaxAccepted": true,
"Jpeg2000TransferSyntaxAccepted": true,
"JpegLosslessTransferSyntaxAccepted": true,
"JpipTransferSyntaxAccepted": true,
"Mpeg2TransferSyntaxAccepted": true,
"RleTransferSyntaxAccepted": true,
"UnknownSopClassAccepted": false,
"DicomScpTimeout": 30,
"RemoteAccessAllowed": true,
"SslEnabled": false,
"SslCertificate": "certificate.pem",
"AuthenticationEnabled": false,
"RegisteredUsers": {
"test": "test"
},
"DicomModalities": {},
"DicomModalitiesInDatabase": false,
"DicomAlwaysAllowEcho": true,
"DicomAlwaysAllowStore": true,
"DicomCheckModalityHost": false,
"DicomScuTimeout": 10,
"OrthancPeers": {},
"OrthancPeersInDatabase": false,
"HttpProxy": "",
"HttpVerbose": true,
"HttpTimeout": 10,
"HttpsVerifyPeers": true,
"HttpsCACertificates": "",
"UserMetadata": {},
"UserContentType": {},
"StableAge": 60,
"StrictAetComparison": false,
"StoreMD5ForAttachments": true,
"LimitFindResults": 0,
"LimitFindInstances": 0,
"LimitJobs": 10,
"LogExportedResources": false,
"KeepAlive": true,
"TcpNoDelay": true,
"HttpThreadsCount": 50,
"StoreDicom": true,
"DicomAssociationCloseDelay": 5,
"QueryRetrieveSize": 10,
"CaseSensitivePN": false,
"LoadPrivateDictionary": true,
"Dictionary": {},
"SynchronousCMove": true,
"JobsHistorySize": 10,
"SaveJobs": true,
"OverwriteInstances": false,
"MediaArchiveSize": 1,
"StorageAccessOnFind": "Always",
"MetricsEnabled": true,
"DicomWeb": {
"Enable": true,
"Root": "/dicom-web/",
"EnableWado": true,
"WadoRoot": "/wado",
"Host": "127.0.0.1",
"Ssl": false,
"StowMaxInstances": 10,
"StowMaxSize": 10,
"QidoCaseSensitive": false
}
}

View File

@ -0,0 +1,46 @@
# Reference:
# - https://docs.docker.com/compose/compose-file
# - https://eclipsesource.com/blogs/2018/01/11/authenticating-reverse-proxy-with-keycloak/
services:
# Exposed server that's handling incoming web requests
ohif_viewer:
build:
# Project root
context: ./../../../../
# Relative to context
dockerfile: ./platform/app/.recipes/Nginx-Orthanc/dockerfile
image: webapp:latest
container_name: ohif_orthanc
volumes:
# Nginx config
- ./config/nginx.conf:/etc/nginx/nginx.conf
# Logs
- ./logs/nginx:/var/logs/nginx
# Let's Encrypt
# - letsencrypt_certificates:/etc/letsencrypt
# - letsencrypt_challenges:/var/www/letsencrypt
ports:
- '443:443' # SSL
- '80:80' # Web
depends_on:
# - keycloak
- orthanc
restart: on-failure
# LINK: https://hub.docker.com/r/jodogne/orthanc-plugins/
# TODO: Update to use Postgres
# https://github.com/mrts/docker-postgresql-multiple-databases
orthanc:
image: jodogne/orthanc-plugins
hostname: orthanc
container_name: orthancPACS
volumes:
# Config
- ./config/orthanc.json:/etc/orthanc/orthanc.json:ro
# Persist data
- ./volumes/orthanc-db/:/var/lib/orthanc/db/
restart: unless-stopped
ports:
- '4242:4242' # Orthanc REST API
- '8042:8042' # Orthanc HTTP

View File

@ -0,0 +1,44 @@
# Stage 1: Build the application
FROM node:18.16.1-slim as builder
# Setup the working directory
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
# Install dependencies
# apt-get update is combined with apt-get install to avoid using outdated packages
RUN apt-get update && apt-get install -y build-essential python3
# Copy package.json and other dependency-related files first
# Assuming your package.json and yarn.lock or similar are located in the project root
COPY . .
# Install node dependencies
# RUN yarn config set workspaces-experimental true
# RUN yarn install
# Copy the rest of the application code
# set QUICK_BUILD to true to make the build faster for dev
ENV APP_CONFIG=config/docker_nginx-orthanc-keycloak.js
# Build the application
# RUN yarn run build
# # Stage 2: Bundle the built application into a Docker container which runs NGINX using Alpine Linux
FROM nginx:alpine
# # Create directories for logs and html content if they don't already exist
RUN mkdir -p /var/log/nginx /var/www/html
# # Copy build output to serve static files
# COPY --from=builder /usr/src/app/platform/app/dist /var/www/html
# # Expose HTTP and HTTPS ports
EXPOSE 80 443
# # Start NGINX
CMD ["nginx", "-g", "daemon off;"]

View File

@ -2,6 +2,10 @@
window.config = {
routerBasename: '/',
showStudyList: true,
customizationService: {
dicomUploadComponent:
'@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent',
},
extensions: [],
modes: [],
// below flag is for performance reasons, but it might not work for all servers
@ -23,6 +27,7 @@ window.config = {
qidoSupportsIncludeField: false,
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
dicomUploadEnabled: true,
omitQuotationForMultipartRequest: true,
},
},

View File

@ -27,7 +27,8 @@ const areLocationsTheSame = (location0, location1) => {
* @param {object} props
* @param {function} props.children - Layout Template React Component
*/
function DataSourceWrapper(props) {
function DataSourceWrapper(props: withAppTypes) {
const { servicesManager } = props;
const navigate = useNavigate();
const { children: LayoutTemplate, ...rest } = props;
const params = useParams();
@ -188,14 +189,29 @@ function DataSourceWrapper(props) {
if (isDataInvalid) {
getData().catch(e => {
console.error(e);
const { configurationAPI, friendlyName } = dataSource.getConfig();
// If there is a data source configuration API, then the Worklist will popup the dialog to attempt to configure it
// and attempt to resolve this issue.
if (dataSource.getConfig().configurationAPI) {
if (configurationAPI) {
return;
}
// No data source configuration API, so navigate to the not found server page.
navigate('/notfoundserver', '_self');
servicesManager.services.uiModalService.show({
title: 'Data Source Connection Error',
containerDimensions: 'w-1/2',
content: () => {
return (
<div>
<p className="text-red-600">Error: {e.message}</p>
<p>
Please ensure the following data source is configured correctly or is running:
</p>
<div className="mt-2 font-bold">{friendlyName}</div>
</div>
);
},
});
});
}
} catch (ex) {

View File

@ -65,11 +65,9 @@ yarn run orthanc:up
_Upload your first Study:_
1. Navigate to
[Orthanc's web interface](http://localhost:8042/app/explorer.html) at
`http://localhost:8042/app/explorer.html` in a web browser.
2. In the top right corner, click "Upload"
3. Click "Select files to upload..." and select one or more DICOM files
4. Click "Start the upload"
[Orthanc's web interface](http://localhost:8042/ui/app/index.html#/) at
`http://localhost:8042/ui/app/index.html#/` in a web browser.
2. In the left you can see the upload button where you can drag and drop your DICOM files
#### Orthanc: Learn More
@ -169,6 +167,16 @@ then consider switching to using [DICOMweb instead](https://book.orthanc-server.
![toolbarModule-layout](../../assets/img/uploader.gif)
Don't forget to add the customization to the config as well
```js
customizationService: {
dicomUploadComponent:
'@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent',
},
```
#### `singlepart`
A comma delimited string specifying which payloads the data source responds with as single part. Those not listed are considered multipart. Values that can be included here are `pdf`, `video`, `bulkdata`, `thumbnail` and `image`.
@ -180,6 +188,15 @@ To learn more about how you can configure the OHIF Viewer, check out our
### DICOM Upload
See the [`dicomUploadEnabled`](#dicomuploadenabled) data source configuration option.
Don't forget to add the customization to the config as well
```js
customizationService: {
dicomUploadComponent:
'@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent',
},
```
### DICOM PDF
See the [`singlepart`](#singlepart) data source configuration option.

View File

@ -1,5 +1,5 @@
---
sidebar_position: 10
sidebar_position: 12
sidebar_label: DICOM Conformance Statement (NEW)
title: DICOM Conformance Statement
---

View File

@ -0,0 +1,4 @@
{
"label": "FAQ",
"position": 13
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

View File

@ -0,0 +1,82 @@
---
id: general
---
# General FAQ
## How do I report a bug?
Navigate to our [GitHub Repository][new-issue], and submit a new bug report.
Follow the steps outlined in the [Bug Report Template][bug-report-template].
## How can I request a new feature?
At the moment we are in the process of defining our roadmap and will do our best
to communicate this to the community. If your requested feature is on the
roadmap, then it will most likely be built at some point. If it is not, you are
welcome to build it yourself and [contribute it](../development/contributing.md).
If you have resources and would like to fund the development of a feature,
please [contact us](https://ohif.org/get-support).
## Who should I contact about Academic Collaborations?
[Gordon J. Harris](https://www.dfhcc.harvard.edu/insider/member-detail/member/gordon-j-harris-phd/)
at Massachusetts General Hospital is the primary contact for any academic
collaborators. We are always happy to hear about new groups interested in using
the OHIF framework, and may be able to provide development support if the
proposed collaboration has an impact on cancer research.
## Does OHIF offer support?
yes, you can contact us for more information [here](https://ohif.org/get-support)
## Does The OHIF Viewer have [510(k) Clearance][501k-clearance] from the U.S. F.D.A or [CE Marking][ce-marking] from the European Commission?
**NO.** The OHIF Viewer is **NOT** F.D.A. cleared or CE Marked. It is the users'
responsibility to ensure compliance with applicable rules and regulations. The
[License](https://github.com/OHIF/Viewers/blob/master/LICENSE) for the OHIF
Platform does not prevent your company or group from seeking F.D.A. clearance
for a product built using the platform.
If you have gone this route (or are going there), please let us know because we
would be interested to hear about your experience.
## Is there a DICOM Conformance Statement for the OHIF Viewer?
Yes, check it here [DICOM Conformance Statement](https://docs.google.com/document/d/1hbDlUApX4svX33gAUGxGfD7fXXZNaBsX0hSePbc-hNA/edit?usp=sharing)
## Is The OHIF Viewer [HIPAA][hipaa-def] Compliant?
**NO.** The OHIF Viewer **DOES NOT** fulfill all of the criteria to become HIPAA
Compliant. It is the users' responsibility to ensure compliance with applicable
rules and regulations.
## Could you provide me with a particular study from the OHIF Viewer Demo?
You can check out the studies that we have put in this [Dropbox link](https://www.dropbox.com/scl/fo/66xidsx13pn0zf3b9cbfq/ADaCgn7aT29WMlnTdT_WRXM?rlkey=rratvx6g4kfxnswjdbupewjye&dl=0)
<!--
Links
-->
[general]: ../faq.md#general
[technical]: ../faq.md#technical
[report-bug]: ../faq.md#how-do-i-report-a-bug
[new-feature]: ../faq.md#how-can-i-request-a-new-feature
[commercial-support]: ../faq.md#does-ohif-offer-commercial-support
[academic]: ../faq.md#who-should-i-contact-about-academic-collaborations
[fda-clearance]: ../faq.md#does-the-ohif-viewer-have-510k-clearance-from-the-us-fda-or-ce-marking-from-the-european-commission
[hipaa]: ../faq.md#is-the-ohif-viewer-hipaa-compliant
[501k-clearance]: https://www.fda.gov/MedicalDevices/DeviceRegulationandGuidance/HowtoMarketYourDevice/PremarketSubmissions/PremarketNotification510k/
[ce-marking]: https://ec.europa.eu/growth/single-market/ce-marking_en
[hipaa-def]: https://en.wikipedia.org/wiki/Health_Insurance_Portability_and_Accountability_Act
[new-issue]: https://github.com/OHIF/Viewers/issues/new/choose
[bug-report-template]: https://github.com/OHIF/Viewers/issues/new?assignees=&labels=Bug+Report+%3Abug%3A&template=---bug-report.md&title=

View File

@ -0,0 +1,92 @@
---
id: index
---
- [General FAQ](../faq.md#general-faq)
- [How do I report a bug?](../faq.md#how-do-i-report-a-bug)
- [How can I request a new feature?](../faq.md#how-can-i-request-a-new-feature)
- [Who should I contact about Academic Collaborations?](../faq.md#who-should-i-contact-about-academic-collaborations)
- [Does OHIF offer support?](../faq.md#does-ohif-offer-support)
- [Does The OHIF Viewer have 510(k) Clearance from the U.S. F.D.A or CE Marking from the European Commission?](../faq.md#does-the-ohif-viewer-have-510k-clearance-from-the-us-fda-or-ce-marking-from-the-european-commission)
- [Is there a DICOM Conformance Statement for the OHIF Viewer?](../faq.md#is-there-a-dicom-conformance-statement-for-the-ohif-viewer)
- [Is The OHIF Viewer HIPAA Compliant?](../faq.md#is-the-ohif-viewer-hipaa-compliant)
- [Could you provide me with a particular study from the OHIF Viewer Demo?](../faq.md#could-you-provide-me-with-a-particular-study-from-the-ohif-viewer-demo)
# General FAQ
## How do I report a bug?
Navigate to our [GitHub Repository][new-issue], and submit a new bug report.
Follow the steps outlined in the [Bug Report Template][bug-report-template].
## How can I request a new feature?
At the moment we are in the process of defining our roadmap and will do our best
to communicate this to the community. If your requested feature is on the
roadmap, then it will most likely be built at some point. If it is not, you are
welcome to build it yourself and [contribute it](../development/contributing.md).
If you have resources and would like to fund the development of a feature,
please [contact us](https://ohif.org/get-support).
## Who should I contact about Academic Collaborations?
[Gordon J. Harris](https://www.dfhcc.harvard.edu/insider/member-detail/member/gordon-j-harris-phd/)
at Massachusetts General Hospital is the primary contact for any academic
collaborators. We are always happy to hear about new groups interested in using
the OHIF framework, and may be able to provide development support if the
proposed collaboration has an impact on cancer research.
## Does OHIF offer support?
yes, you can contact us for more information [here](https://ohif.org/get-support)
## Does The OHIF Viewer have [510(k) Clearance][501k-clearance] from the U.S. F.D.A or [CE Marking][ce-marking] from the European Commission?
**NO.** The OHIF Viewer is **NOT** F.D.A. cleared or CE Marked. It is the users'
responsibility to ensure compliance with applicable rules and regulations. The
[License](https://github.com/OHIF/Viewers/blob/master/LICENSE) for the OHIF
Platform does not prevent your company or group from seeking F.D.A. clearance
for a product built using the platform.
If you have gone this route (or are going there), please let us know because we
would be interested to hear about your experience.
## Is there a DICOM Conformance Statement for the OHIF Viewer?
Yes, check it here [DICOM Conformance Statement](https://docs.google.com/document/d/1hbDlUApX4svX33gAUGxGfD7fXXZNaBsX0hSePbc-hNA/edit?usp=sharing)
## Is The OHIF Viewer [HIPAA][hipaa-def] Compliant?
**NO.** The OHIF Viewer **DOES NOT** fulfill all of the criteria to become HIPAA
Compliant. It is the users' responsibility to ensure compliance with applicable
rules and regulations.
## Could you provide me with a particular study from the OHIF Viewer Demo?
You can check out the studies that we have put in this [Dropbox link](https://www.dropbox.com/scl/fo/66xidsx13pn0zf3b9cbfq/ADaCgn7aT29WMlnTdT_WRXM?rlkey=rratvx6g4kfxnswjdbupewjye&dl=0)
<!--
Links
-->
[general]: ../faq.md#general
[technical]: ../faq.md#technical
[report-bug]: ../faq.md#how-do-i-report-a-bug
[new-feature]: ../faq.md#how-can-i-request-a-new-feature
[commercial-support]: ../faq.md#does-ohif-offer-commercial-support
[academic]: ../faq.md#who-should-i-contact-about-academic-collaborations
[fda-clearance]: ../faq.md#does-the-ohif-viewer-have-510k-clearance-from-the-us-fda-or-ce-marking-from-the-european-commission
[hipaa]: ../faq.md#is-the-ohif-viewer-hipaa-compliant
[501k-clearance]: https://www.fda.gov/MedicalDevices/DeviceRegulationandGuidance/HowtoMarketYourDevice/PremarketSubmissions/PremarketNotification510k/
[ce-marking]: https://ec.europa.eu/growth/single-market/ce-marking_en
[hipaa-def]: https://en.wikipedia.org/wiki/Health_Insurance_Portability_and_Accountability_Act
[new-issue]: https://github.com/OHIF/Viewers/issues/new/choose
[bug-report-template]: https://github.com/OHIF/Viewers/issues/new?assignees=&labels=Bug+Report+%3Abug%3A&template=---bug-report.md&title=

View File

@ -1,92 +1,9 @@
---
sidebar_position: 8
sidebar_label: FAQ
---
- [General FAQ](#general-faq)
- [How do I report a bug?](#how-do-i-report-a-bug)
- [How can I request a new feature?](#how-can-i-request-a-new-feature)
- [Who should I contact about Academic Collaborations?](#who-should-i-contact-about-academic-collaborations)
- [Does OHIF offer support?](#does-ohif-offer-support)
- [Does The OHIF Viewer have 510(k) Clearance from the U.S. F.D.A or CE Marking from the European Commission?](#does-the-ohif-viewer-have-510k-clearance-from-the-us-fda-or-ce-marking-from-the-european-commission)
- [Is there a DICOM Conformance Statement for the OHIF Viewer?](#is-there-a-dicom-conformance-statement-for-the-ohif-viewer)
- [Is The OHIF Viewer HIPAA Compliant?](#is-the-ohif-viewer-hipaa-compliant)
- [Could you provide me with a particular study from the OHIF Viewer Demo?](#could-you-provide-me-with-a-particular-study-from-the-ohif-viewer-demo)
- [Technical FAQ](#technical-faq)
- [Why do I keep seeing a Cross Origin Isolation warning](#why-do-i-keep-seeing-a-cross-origin-isolation-warning)
- [What if my setup does not support the Shared Array Buffers API?](#what-if-my-setup-does-not-support-the-shared-array-buffers-api)
- [Viewer opens but does not show any thumbnails](#viewer-opens-but-does-not-show-any-thumbnails)
- [What are the list of required metadata for the OHIF Viewer to work?](#what-are-the-list-of-required-metadata-for-the-ohif-viewer-to-work)
- [Mandatory](#mandatory)
- [Optional](#optional)
- [How do I handle large volumes for MPR and Volume Rendering](#how-do-i-handle-large-volumes-for-mpr-and-volume-rendering)
- [`useNorm16Texture`](#usenorm16texture)
- [`preferSizeOverAccuracy`](#prefersizeoveraccuracy)
# General FAQ
## How do I report a bug?
Navigate to our [GitHub Repository][new-issue], and submit a new bug report.
Follow the steps outlined in the [Bug Report Template][bug-report-template].
## How can I request a new feature?
At the moment we are in the process of defining our roadmap and will do our best
to communicate this to the community. If your requested feature is on the
roadmap, then it will most likely be built at some point. If it is not, you are
welcome to build it yourself and [contribute it](development/contributing.md).
If you have resources and would like to fund the development of a feature,
please [contact us](https://ohif.org/get-support).
## Who should I contact about Academic Collaborations?
[Gordon J. Harris](https://www.dfhcc.harvard.edu/insider/member-detail/member/gordon-j-harris-phd/)
at Massachusetts General Hospital is the primary contact for any academic
collaborators. We are always happy to hear about new groups interested in using
the OHIF framework, and may be able to provide development support if the
proposed collaboration has an impact on cancer research.
## Does OHIF offer support?
yes, you can contact us for more information [here](https://ohif.org/get-support)
## Does The OHIF Viewer have [510(k) Clearance][501k-clearance] from the U.S. F.D.A or [CE Marking][ce-marking] from the European Commission?
**NO.** The OHIF Viewer is **NOT** F.D.A. cleared or CE Marked. It is the users'
responsibility to ensure compliance with applicable rules and regulations. The
[License](https://github.com/OHIF/Viewers/blob/master/LICENSE) for the OHIF
Platform does not prevent your company or group from seeking F.D.A. clearance
for a product built using the platform.
If you have gone this route (or are going there), please let us know because we
would be interested to hear about your experience.
## Is there a DICOM Conformance Statement for the OHIF Viewer?
Yes, check it here [DICOM Conformance Statement](https://docs.google.com/document/d/1hbDlUApX4svX33gAUGxGfD7fXXZNaBsX0hSePbc-hNA/edit?usp=sharing)
## Is The OHIF Viewer [HIPAA][hipaa-def] Compliant?
**NO.** The OHIF Viewer **DOES NOT** fulfill all of the criteria to become HIPAA
Compliant. It is the users' responsibility to ensure compliance with applicable
rules and regulations.
## Could you provide me with a particular study from the OHIF Viewer Demo?
You can check out the studies that we have put in this [Dropbox link](https://www.dropbox.com/scl/fo/66xidsx13pn0zf3b9cbfq/ADaCgn7aT29WMlnTdT_WRXM?rlkey=rratvx6g4kfxnswjdbupewjye&dl=0)
# Technical FAQ
## Why do I keep seeing a Cross Origin Isolation warning
If you encounter a warning while running OHIF indicating that your application is not cross-origin isolated, it implies that volume rendering, such as MPR, will not function properly since they depend on Shared Array Buffers. To resolve this issue, we recommend referring to our comprehensive guide on Cross Origin Isolation available at [our dedicated cors page](./deployment/cors.md).
If you encounter a warning while running OHIF indicating that your application is not cross-origin isolated, it implies that volume rendering, such as MPR, will not function properly since they depend on Shared Array Buffers. To resolve this issue, we recommend referring to our comprehensive guide on Cross Origin Isolation available at [our dedicated cors page](../deployment/cors.md).
## What if my setup does not support the Shared Array Buffers API?
You can simply disable that by adding the `useSharedArrayBuffer: 'FALSE'` (notice the string FALSE), and the volumes will only use a regular
@ -101,7 +18,7 @@ One
For instance for the following filtering in the worklist tab we send this request
![](assets/img/filtering-worklist.png)
![](../assets/img/filtering-worklist.png)
`https://d33do7qe4w26qo.cloudfront.net/dicomweb/studies?PatientName=*Head*&limit=101&offset=0&fuzzymatching=false&includefield=00081030%2C00080060`
@ -223,25 +140,25 @@ WebGL officially supports only 8-bit and 32-bit data types. For most images, 8 b
Through [EXT_texture_norm16](https://registry.khronos.org/webgl/extensions/EXT_texture_norm16/) , WebGL can support 16 bit data type which is ideal
for most images. You can look into the [webgl report](https://webglreport.com/?v=2) to check if you have that extension enabled.
![](assets/img/webgl-report-norm16.png)
![](../assets/img/webgl-report-norm16.png)
This is a flag that you can set in your [configuration file](./configuration/configurationFiles.md) to force usage of 16 bit data type for the volume rendering and MPR. This will reduce the memory usage by half.
This is a flag that you can set in your [configuration file](../configuration/configurationFiles.md) to force usage of 16 bit data type for the volume rendering and MPR. This will reduce the memory usage by half.
For instance for a large pt/ct study
![](assets/img/large-pt-ct.png)
![](../assets/img/large-pt-ct.png)
Before (without the flag) the app shows 399 MB of memory usage
![](assets/img/memory-profiling-regular.png)
![](../assets/img/memory-profiling-regular.png)
After (with flag, running locally) the app shows 249 MB of memory usage
![](assets/img/webgl-int16.png)
![](../assets/img/webgl-int16.png)
:::note
Using the 16 bit texture (if supported) will not have any effect in the rendering what so ever, and pixelData
@ -264,7 +181,7 @@ to be still some issues with it. You can read and track bugs below.
### `preferSizeOverAccuracy`
This is another flag that you can set in your [configuration file](./configuration/configurationFiles.md) to force the usage of the `half_float` data type for volume rendering and MPR. The main reason to choose this option over `useNorm16Texture` is its broader support across hardware and browsers. However, it is less accurate than the 16-bit data type and may lead to some rendering artifacts.
This is another flag that you can set in your [configuration file](../configuration/configurationFiles.md) to force the usage of the `half_float` data type for volume rendering and MPR. The main reason to choose this option over `useNorm16Texture` is its broader support across hardware and browsers. However, it is less accurate than the 16-bit data type and may lead to some rendering artifacts.
```js
Integers between 0 and 2048 can be exactly represented (and also between 2048 and 0)
@ -279,24 +196,79 @@ As you see in the ranges above 2048 there will be inaccuracies in the rendering.
Memory snapshot after enabling `preferSizeOverAccuracy` for the same study as above
![](assets/img/preferSizeOverAccuracy.png)
![](../assets/img/preferSizeOverAccuracy.png)
## How to dynamically load a measurement
You can dynamically load a measurement by using a combination of `MeasurementService` and `CornerstoneTools` Annotation API. Here, we will demonstrate this with an example of loading a `Rectangle` measurement.
![alt text](faq-measure-1.png)
So if we look at the terminal and get the measurement service we can see there is one measurement
![alt text](faq-measure-2.png)
However, this is the `mapped` cornerstone measurement inside OHIF, and it has additional information such as `geReport` and `source`, which are internal details of OHIF Viewers that you don't need to worry about.
we can call the `cornerstoneTools` api to grab the raw annotation data with the `uid`
`cornerstoneTools.annotation.state.getAnnotation("ea45a45c-0731-47d4-9438-d2a53ffea4ff")`
![alt text](faq-measure3.png)
<!--
Links
-->
[general]: #general
[technical]: #technical
[report-bug]: #how-do-i-report-a-bug
[new-feature]: #how-can-i-request-a-new-feature
[commercial-support]: #does-ohif-offer-commercial-support
[academic]: #who-should-i-contact-about-academic-collaborations
[fda-clearance]: #does-the-ohif-viewer-have-510k-clearance-from-the-us-fda-or-ce-marking-from-the-european-commission
[hipaa]: #is-the-ohif-viewer-hipaa-compliant
[501k-clearance]: https://www.fda.gov/MedicalDevices/DeviceRegulationandGuidance/HowtoMarketYourDevice/PremarketSubmissions/PremarketNotification510k/
[ce-marking]: https://ec.europa.eu/growth/single-market/ce-marking_en
[hipaa-def]: https://en.wikipedia.org/wiki/Health_Insurance_Portability_and_Accountability_Act
[new-issue]: https://github.com/OHIF/Viewers/issues/new/choose
[bug-report-template]: https://github.com/OHIF/Viewers/issues/new?assignees=&labels=Bug+Report+%3Abug%3A&template=---bug-report.md&title=
:::note
Note: There is a `pointsInShape` attribute inside the data that stores the points within the annotation for some tools like `Rectangle` and `EllipticalRoi`. However, you can remove that attribute as well.
:::
For the sake of this example, I have extracted those keys and uploaded them to our server for fetching.
`
https://ohif-assets.s3.us-east-2.amazonaws.com/ohif-faq/rectangle-roi.json
`
Now, let's discuss how to load this measurement dynamically and programmatically.
There are numerous places in OHIF where you can add annotations, but we always recommend having your own extensions and modes to maintain full control over your custom API.
For this example, I will add the logic in the `longitudinal` mode. However, as mentioned, you can create your own extension and mode, and either use `onModeEnter` or other lifecycle hooks to add annotations. Learn more about lifecycle hooks [here](../platform/extensions/lifecycle.md).
Of course, you need to load the appropriate measurement for each study. However, for simplicity's sake, I will hardcode the URL in this example.
```js
import * as cs3dTools from '@cornerstonejs/tools';
onModeEnter: function ({ servicesManager, extensionManager, commandsManager }: withAppTypes) {
// rest of logic
const annotationResponse = await fetch(
'https://ohif-assets.s3.us-east-2.amazonaws.com/ohif-faq/rectangle-roi.json'
);
const annotationData = await annotationResponse.json();
cs3dTools.annotation.state.addAnnotation(annotationData);
},
```
As you can see, we use the CornerstoneTools API to add the annotation. Since OHIF has mappers set up for CornerstoneTools (`extensions/cornerstone/src/utils/measurementServiceMappings/measurementServiceMappingsFactory.ts`), it will automatically map the annotation to the OHIF measurement service.
If you refresh the viewer, you'll see the measurement loaded on the image.
![alt text](faq-measure-4.png)
But if you notice it does not appear on the right panel, the reason is that the right panel is the tracking measurement panel. You can switch to a non-tracking measurement by changing
`rightPanels: [dicomSeg.panel, tracked.measurements],`
to
`rightPanels: [dicomSeg.panel, '@ohif/extension-default.panelModule.measure'],`
which then it will look like
![alt text](faq-measure-5.png)

View File

@ -132,6 +132,15 @@ Additional Resources
- For more information on the new toolbar module and its usage, refer to the [Toolbar documentation](../platform/extensions/modules/toolbar.md).
- Consult the updated button definitions in `modes/longitudinal/src/toolbarButtons.ts` for examples of the new object-based button definition format and the usage of evaluators.
## Toolbar Service
toolbarService.init is not a function.
**Action Needed**
remove the call to toolbarService.init() from your codebase.
## leftPanelDefaultClosed and rightPanelDefaultClosed
Now they are renamed to `leftPanelClosed` and `rightPanelClosed` respectively.
@ -140,3 +149,24 @@ Now they are renamed to `leftPanelClosed` and `rightPanelClosed` respectively.
## StudyInstanceUID in the URL param
Previously there were two params that you could choose: seriesInstanceUID and seriesInstanceUIDs, they have been replaced with seriesInstanceUIDs so even if you would like to filter one series use ``seriesInstanceUIDs`
## UI
### Header
Header in @ohif/ui now needs servicesManager and appConfig as input.
### Panels
Left and right panel lists are no longer injected into the LayoutTemplate, and have been moved to a PanelService where you have to fetch them from.
If you're using the main layout, you're fine. However, if you have a custom layout, you'll need to update it. To get the panels, see the
`extensions/default/src/ViewerLayout/index.tsx`
## Refactoring
- TimingEnum (and I guess all enums exported from OHIF core have now moved from Types to Enums export).

View File

@ -0,0 +1,13 @@
---
id: index
---
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
# Migration Guides
Based on the version you are migrating from, you can find the migration guide for the latest version of the platform.
<DocCardList items={useCurrentSidebarCategory().items}/>

View File

@ -1,5 +1,5 @@
---
sidebar_position: 9
sidebar_position: 13
sidebar_label: Resources
---

View File

@ -1,138 +0,0 @@
---
sidebar_position: 12
sidebar_label: Testing
---
# Writing PlayWright Tests
Our Playwright tests are written using the Playwright test framework. We use these tests to test our OHIF Viewer and ensure that it is working as expected.
In this guide, we will show you how to write Playwright tests for the OHIF Viewer.
## Using a specific study and mode
If you would like to use a specific study, you can use the `studyInstanceUID` property to reference the study you would like to visit. for example, if you would like to use the study with StudyInstanceUID `2.16.840.1.114362.1.11972228.22789312658.616067305.306.2` and the mode `Basic Viewer`, you can use the following code snippet:
```ts
import { test } from '@playwright/test';
import { visitStudy, checkForScreenshot, screenShotPaths } from './utils/index';
test.beforeEach(async ({ page }) => {
const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2';
const mode = 'Basic Viewer';
await visitStudy(page, studyInstanceUID, mode);
});
test.describe('Some Test', async () => {
test('should do something.', async ({ page }) => {
// Your test code here...
});
});
```
## Screenshots
A good way to check your tests is working as expected is to capture screenshots at different stages of the test. You can use our `checkForScreenshot` function located in `tests/utils/checkForScreenshot.ts` to capture screenshots. You should also plan your screenshots in advance, screenshots need to be defined in the `tests/utils/screenshotPaths.ts` file. For example, if you would to capture a screenshot after a measurement is added, you can define a screenshot path like this:
```ts
const screenShotPaths = {
your_test_name: {
measurementAdded: 'measurementAdded.png',
measurementRemoved: 'measurementRemoved.png',
},
};
```
It's okay if the screenshot doesn't exist yet, this will be dealt with in the next step. Once you have defined your screenshot path, you can use the `checkForScreenshot` function in your test to capture the screenshot. For example, if you would like to capture a screenshot of the page after a measurement is added, you can use the following code snippet:
```ts
import { test } from '@playwright/test';
import {
visitStudy,
checkForScreenshot,
screenshotPath,
} from './utils/index';
test.beforeEach(async ({ page }) => {
const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2';
const mode = 'Basic Viewer';
await visitStudy(page, studyInstanceUID, mode);
});
test.describe('Some test', async () => {
test('should do something', async ({ page }) => {
// Your test code here to add a measurement
await checkForScreenshot(
page,
page,
screenshotPath.your_test_name.measurementAdded
);
});
});
```
The test will automatically fail the first time you run it, it will however generate the screenshot for you, you will notice 3 new entries in the `tests/screenshots` folder, under `chromium/your-test.spec.js/measurementAdded.png`, `firefox/your-test.spec.js/measurementAdded.png` and `webkit/your-test.spec.js/measurementAdded.png` folders. You can now run the test again and it will use those screenshots to compare against the current state of the example. Please verify that the ground truth screenshots are correct before committing them or testing against them.
## Simulating mouse drags
If you would like to simulate a mouse drag, you can use the `simulateDrag` function located in `tests/utils/simulateDrag.ts`. You can use this function to simulate a mouse drag on an element. For example, if you would like to simulate a mouse drag on the `cornerstone-canvas` element, you can use the following code snippet:
```ts
import {
visitStudy,
checkForScreenshot,
screenShotPaths,
simulateDrag,
} from './utils/index';
test.beforeEach(async ({ page }) => {
const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2';
const mode = 'Basic Viewer';
await visitStudy(page, studyInstanceUID, mode);
});
test.describe('Some Test', async () => {
test('should do something..', async ({
page,
}) => {
const locator = page.locator('.cornerstone-canvas');
await simulateDrag(page, locator);
});
});
```
Our simulate drag utility can simulate a drag on any element, and avoid going out of bounds. It will calculuate the bounding box of the element and ensure that the drag stays within the bounds of the element. This should be good enough for most tools, and better than providing custom x, and y coordinates which can be error prone and make the code difficult to maintain.
## Running the tests
After you have wrote your tests, you can run them by using the following command:
```bash
yarn test:e2e:ci
```
If you want to use headed mode, you can use the following command:
```bash
yarn test:e2e:headed
```
You will see the test results in your terminal, if you want an indepth report, you can use the following command:
```bash
yarn playwright show-report tests/playwright-report
```
## Serving the viewer manually for development
By default, when you run the tests, it will call the `yarn start` command to serve the viewer first, then run the tests, if you would like to serve the viewer manually, you can use the same command. The viewer will be available at `http://localhost:3000`. This could speed up your development process since playwright will skip this step and use the existing server on port 3000.
## Playwright VSCode Extension and Recording Tests
If you are using VSCode, you can use the Playwright extension to help you write your tests. The extension provides a test runner and many great features such as picking a locator using your mouse, recording a new test, and more. You can install the extension by searching for `Playwright` in the extensions tab in VSCode or by visiting the [Playwright extension page](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright). The below recording is for CornestoneJS, but the same principles apply to OHIF Viewer.
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/947471524?h=6720407fef&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479"
frameBorder="0" allow="cross-origin-isolated" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="Playwright Extension"></iframe>
</div>

View File

@ -56,11 +56,9 @@ yarn run orthanc:up
_Upload your first Study:_
1. Navigate to
[Orthanc's web interface](http://localhost:8042/app/explorer.html) at
`http://localhost:8042/app/explorer.html` in a web browser.
2. In the top right corner, click "Upload"
3. Click "Select files to upload..." and select one or more DICOM files
4. Click "Start the upload"
[Orthanc's web interface](http://localhost:8042/ui/app/index.html#/) at
`http://localhost:8042/ui/app/index.html#/` in a web browser.
2. In the left you can see the upload button where you can drag and drop your DICOM files
#### Orthanc: Learn More

View File

@ -2329,13 +2329,13 @@
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
"@cornerstonejs/adapters@^1.77.3":
version "1.77.3"
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.77.3.tgz#3cac2b8747f437af98fb7a586473445d786ede69"
integrity sha512-+Ik0SLgTzBfcAeys8naiNxXxS5N5+JVKfWzvDi5qDprsK4xXvcJZpfg0O/Ry6rO9kZpjnQl61CMiHaMzMmyERw==
"@cornerstonejs/adapters@^1.77.6":
version "1.77.12"
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.77.12.tgz#288ae3b5a58fb000fbdaf532ec210c405ef3e609"
integrity sha512-I1KwTLPRCXy/9VmZXEKNMv1RX5sBbJ6T4lapzMas4LPDX+DlItMa+t2A0CnE+pXF7yv5lN4qTH9Emkp3qDkFtg==
dependencies:
"@babel/runtime-corejs2" "^7.17.8"
"@cornerstonejs/tools" "^1.77.3"
"@cornerstonejs/tools" "^1.77.12"
buffer "^6.0.3"
dcmjs "^0.29.8"
gl-matrix "^3.4.3"
@ -2382,10 +2382,10 @@
resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.5.tgz#8690b61a86fa53ef38a70eee9d665a79229517c0"
integrity sha512-MZCUy8VG0VG5Nl1l58+g+kH3LujAzLYTfJqkwpWI2gjSrGXnP6lgwyy4GmPRZWVoS40/B1LDNALK905cNWm+sg==
"@cornerstonejs/core@^1.77.3":
version "1.77.3"
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.77.3.tgz#e29455259ed151fbd772a24a7574414217a6675c"
integrity sha512-QSu8TkIWc0lZBWbCByYhEySqmU8xleiqbQqQrgO9iMp2M4M+XOz8pIvox2WsQteqCLonZWMVI2T4J7q6osSX6A==
"@cornerstonejs/core@^1.77.12", "@cornerstonejs/core@^1.77.6":
version "1.77.12"
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.77.12.tgz#d3f199688b3dfc6c982c2dd67ec20e68a267ef80"
integrity sha512-wWgCEtAPCtiYsSwx6vFQYO5usr/YY+t6fZFP+BSr6AszWCXaVeOhpwAYFjUd8k9MEjm8VPYj+PTo9un3e8864Q==
dependencies:
"@kitware/vtk.js" "30.4.1"
comlink "^4.4.1"
@ -2393,34 +2393,34 @@
gl-matrix "^3.4.3"
lodash.clonedeep "4.5.0"
"@cornerstonejs/dicom-image-loader@^1.77.3":
version "1.77.3"
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.77.3.tgz#90fb8407a20bd6f52b4e2921a2bd62e791810b07"
integrity sha512-b+ysKZvmA1+sFEb+6//GsjmhhPstsX4a7Gj7pflKGqX+8aPMQ+nF8zv3R0D26eAejoC9hGcaGupYlXfiVq7dBA==
"@cornerstonejs/dicom-image-loader@^1.77.6":
version "1.77.12"
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.77.12.tgz#ca943b6a29b230d947e46c6ad73d419bf840f00e"
integrity sha512-EgZqaBkMfuHGiDgx0kdCEmxsXKR/2rGRjERzbWU/tjbR5HV2sHra1JPjKu3osNUO6iQ0vXszwRlRpop+v1OvGA==
dependencies:
"@cornerstonejs/codec-charls" "^1.2.3"
"@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2"
"@cornerstonejs/codec-openjpeg" "^1.2.2"
"@cornerstonejs/codec-openjph" "^2.4.5"
"@cornerstonejs/core" "^1.77.3"
"@cornerstonejs/core" "^1.77.12"
dicom-parser "^1.8.9"
pako "^2.0.4"
uuid "^9.0.0"
"@cornerstonejs/streaming-image-volume-loader@^1.77.3":
version "1.77.3"
resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.77.3.tgz#6ce50784106282ab3db65a5561515b8c23b3411f"
integrity sha512-HqJ+Qj8IfmR+0kpw+XXTKNs09WVzdAubmE41RR2i8b4BckT4qaY0EmYaAMlG+sxJtIVBsb4QnvQ6lXkRhjJW4w==
"@cornerstonejs/streaming-image-volume-loader@^1.77.6":
version "1.77.12"
resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.77.12.tgz#7911be10c9ca8bc6b2096c945d9467ecfde8e6f8"
integrity sha512-W+hgNNMVPgT1jU+lE/9jtzn5yM2Fmk8sPdrhUu9aetNMM+cxyJagMzDNLhf36asmK9bwkOBJdOjOx8Of3XoCyQ==
dependencies:
"@cornerstonejs/core" "^1.77.3"
"@cornerstonejs/core" "^1.77.12"
comlink "^4.4.1"
"@cornerstonejs/tools@^1.77.3":
version "1.77.3"
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.77.3.tgz#7a26df4a95ad7d25de272adf52da072f3717e4a0"
integrity sha512-vUi0+2pSJ0xLwysj2mWMiFEZJ50ZAfU+5JjKly30aECxCfmURrhnEEOMsECwVxEeBGM5hHNc/Cl4SZGy87dV2Q==
"@cornerstonejs/tools@^1.77.12", "@cornerstonejs/tools@^1.77.6":
version "1.77.12"
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.77.12.tgz#1dd96e04cd4ec2b421d0feea1e27510d680c5697"
integrity sha512-yRvTHx/w+dPe7npjOeXp+4zdR4IUmpTcwwLyMAXIJSlipZqhJ+gYHhQn38yonj3plSzp4xUOaqLUR55v/aX43Q==
dependencies:
"@cornerstonejs/core" "^1.77.3"
"@cornerstonejs/core" "^1.77.12"
"@icr/polyseg-wasm" "0.4.0"
"@types/offscreencanvas" "2019.7.3"
comlink "^4.4.1"