diff --git a/extensions/cornerstone-dicom-seg/package.json b/extensions/cornerstone-dicom-seg/package.json index 9ea04bac0..3a42b33d2 100644 --- a/extensions/cornerstone-dicom-seg/package.json +++ b/extensions/cornerstone-dicom-seg/package.json @@ -44,8 +44,8 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^1.20.3", - "@cornerstonejs/tools": "^1.20.3", + "@cornerstonejs/adapters": "^1.27.3", + "@cornerstonejs/tools": "^1.27.3", "@kitware/vtk.js": "27.3.1", "react-color": "^2.19.3" } diff --git a/extensions/cornerstone-dicom-sr/package.json b/extensions/cornerstone-dicom-sr/package.json index 3808c2443..6fff62b5b 100644 --- a/extensions/cornerstone-dicom-sr/package.json +++ b/extensions/cornerstone-dicom-sr/package.json @@ -36,7 +36,7 @@ "@ohif/extension-cornerstone": "3.8.0-beta.9", "@ohif/extension-measurement-tracking": "3.8.0-beta.9", "@ohif/ui": "3.8.0-beta.9", - "dcmjs": "^0.29.11", + "dcmjs": "^0.29.12", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", "prop-types": "^15.6.2", @@ -44,9 +44,9 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^1.20.3", - "@cornerstonejs/core": "^1.20.3", - "@cornerstonejs/tools": "^1.20.3", + "@cornerstonejs/adapters": "^1.27.3", + "@cornerstonejs/core": "^1.27.3", + "@cornerstonejs/tools": "^1.27.3", "classnames": "^2.3.2" } } diff --git a/extensions/cornerstone/package.json b/extensions/cornerstone/package.json index 445022e76..0a5ec8dc1 100644 --- a/extensions/cornerstone/package.json +++ b/extensions/cornerstone/package.json @@ -36,7 +36,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.2", - "@cornerstonejs/dicom-image-loader": "^1.20.3", + "@cornerstonejs/dicom-image-loader": "^1.27.3", "@ohif/core": "3.8.0-beta.9", "@ohif/ui": "3.8.0-beta.9", "dcmjs": "^0.29.11", @@ -52,10 +52,10 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^1.20.3", - "@cornerstonejs/core": "^1.20.3", - "@cornerstonejs/streaming-image-volume-loader": "^1.20.3", - "@cornerstonejs/tools": "^1.20.3", + "@cornerstonejs/adapters": "^1.27.3", + "@cornerstonejs/core": "^1.27.3", + "@cornerstonejs/streaming-image-volume-loader": "^1.27.3", + "@cornerstonejs/tools": "^1.27.3", "@kitware/vtk.js": "27.3.1", "html2canvas": "^1.4.1", "lodash.debounce": "4.0.8", diff --git a/extensions/cornerstone/src/init.tsx b/extensions/cornerstone/src/init.tsx index 99755fa73..ef6e866e7 100644 --- a/extensions/cornerstone/src/init.tsx +++ b/extensions/cornerstone/src/init.tsx @@ -59,8 +59,8 @@ export default async function init({ await cs3DInit({ rendering: { - preferSizeOverAccuracy: Boolean(appConfig.use16BitDataType), - useNorm16Texture: Boolean(appConfig.use16BitDataType), + preferSizeOverAccuracy: Boolean(appConfig.preferSizeOverAccuracy), + useNorm16Texture: Boolean(appConfig.useNorm16Texture), }, }); @@ -308,8 +308,8 @@ export default async function init({ viewportGridService.subscribe( viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED, activeViewportEventListener - ); - } + ); +} function CPUModal() { return ( diff --git a/extensions/cornerstone/src/initWADOImageLoader.js b/extensions/cornerstone/src/initWADOImageLoader.js index 1beda3885..622a42625 100644 --- a/extensions/cornerstone/src/initWADOImageLoader.js +++ b/extensions/cornerstone/src/initWADOImageLoader.js @@ -49,7 +49,8 @@ export default function initWADOImageLoader( // Until the default is set to true (which is the case for cornerstone3D), // we should set this flag to false. convertFloatPixelDataToInt: false, - use16BitDataType: Boolean(appConfig.use16BitDataType), + use16BitDataType: + Boolean(appConfig.useNorm16Texture) || Boolean(appConfig.preferSizeOverAccuracy), }, beforeSend: function (xhr) { //TODO should be removed in the future and request emitted by DicomWebDataSource diff --git a/extensions/default/package.json b/extensions/default/package.json index 1bd772a61..3f81a641b 100644 --- a/extensions/default/package.json +++ b/extensions/default/package.json @@ -32,7 +32,7 @@ "peerDependencies": { "@ohif/core": "3.8.0-beta.9", "@ohif/i18n": "3.8.0-beta.9", - "dcmjs": "^0.29.11", + "dcmjs": "^0.29.12", "dicomweb-client": "^0.10.2", "prop-types": "^15.6.2", "react": "^17.0.2", diff --git a/extensions/default/src/init.ts b/extensions/default/src/init.ts index 973ae0722..1dfc7de25 100644 --- a/extensions/default/src/init.ts +++ b/extensions/default/src/init.ts @@ -51,10 +51,16 @@ export default function init({ servicesManager, configuration = {} }): void { const handlePETImageMetadata = ({ SeriesInstanceUID, StudyInstanceUID }) => { const { instances } = DicomMetadataStore.getSeries(StudyInstanceUID, SeriesInstanceUID); - const modality = instances[0].Modality; - if (modality !== 'PT') { + if (!instances?.length) { return; } + + const modality = instances[0].Modality; + + if (!modality || modality !== 'PT') { + return; + } + const imageIds = instances.map(instance => instance.imageId); const instanceMetadataArray = []; imageIds.forEach(imageId => { diff --git a/extensions/dicom-pdf/package.json b/extensions/dicom-pdf/package.json index 063656eeb..add7e06ec 100644 --- a/extensions/dicom-pdf/package.json +++ b/extensions/dicom-pdf/package.json @@ -30,7 +30,7 @@ "peerDependencies": { "@ohif/core": "3.8.0-beta.9", "@ohif/ui": "3.8.0-beta.9", - "dcmjs": "^0.29.11", + "dcmjs": "^0.29.12", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", "prop-types": "^15.6.2", diff --git a/extensions/dicom-video/package.json b/extensions/dicom-video/package.json index 9f3371dfd..bde6d76ae 100644 --- a/extensions/dicom-video/package.json +++ b/extensions/dicom-video/package.json @@ -30,7 +30,7 @@ "peerDependencies": { "@ohif/core": "3.8.0-beta.9", "@ohif/ui": "3.8.0-beta.9", - "dcmjs": "^0.29.11", + "dcmjs": "^0.29.12", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", "prop-types": "^15.6.2", diff --git a/extensions/measurement-tracking/package.json b/extensions/measurement-tracking/package.json index 63a66e954..f1f2cc080 100644 --- a/extensions/measurement-tracking/package.json +++ b/extensions/measurement-tracking/package.json @@ -30,13 +30,13 @@ "start": "yarn run dev" }, "peerDependencies": { - "@cornerstonejs/core": "^1.20.3", - "@cornerstonejs/tools": "^1.20.3", + "@cornerstonejs/core": "^1.27.3", + "@cornerstonejs/tools": "^1.27.3", "@ohif/core": "3.8.0-beta.9", "@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.9", "@ohif/ui": "3.8.0-beta.9", "classnames": "^2.3.2", - "dcmjs": "^0.29.11", + "dcmjs": "^0.29.12", "lodash.debounce": "^4.17.21", "prop-types": "^15.6.2", "react": "^17.0.2", diff --git a/extensions/tmtv/package.json b/extensions/tmtv/package.json index 01c7c0b58..9d7b34adc 100644 --- a/extensions/tmtv/package.json +++ b/extensions/tmtv/package.json @@ -30,7 +30,7 @@ "peerDependencies": { "@ohif/core": "3.8.0-beta.9", "@ohif/ui": "3.8.0-beta.9", - "dcmjs": "^0.29.11", + "dcmjs": "^0.29.12", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", "prop-types": "^15.6.2", diff --git a/modes/segmentation/src/index.tsx b/modes/segmentation/src/index.tsx index a6f552c5a..0282435b2 100644 --- a/modes/segmentation/src/index.tsx +++ b/modes/segmentation/src/index.tsx @@ -120,9 +120,16 @@ function modeFactory({ modeConfiguration }) { }, /** * A boolean return value that indicates whether the mode is valid for the - * modalities of the selected studies. For instance a PET/CT mode should be + * modalities of the selected studies. Currently we don't have stack viewport + * segmentations and we should exclude them */ - isValidMode: ({ modalities }) => true, + isValidMode: ({ modalities }) => { + if (modalities.length === 1) { + return !['SM', 'US', 'MG', 'OT', 'DOC', 'CR'].includes(modalities[0]); + } + + return true; + }, /** * Mode Routes are used to define the mode's behavior. A list of Mode Route * that includes the mode's path and the layout to be used. The layout will diff --git a/platform/app/cypress/integration/measurement-tracking/OHIFStudyBrowser.spec.js b/platform/app/cypress/integration/measurement-tracking/OHIFStudyBrowser.spec.js index c43cb2c93..4a52b0030 100644 --- a/platform/app/cypress/integration/measurement-tracking/OHIFStudyBrowser.spec.js +++ b/platform/app/cypress/integration/measurement-tracking/OHIFStudyBrowser.spec.js @@ -18,12 +18,17 @@ describe('OHIF Study Browser', function () { const dataTransfer = new DataTransfer(); - cy.get('[data-cy="study-browser-thumbnail"]:nth-child(2)') + cy.get('[data-cy="study-browser-thumbnail"]:nth-child(2)').as('seriesThumbnail'); + + cy.get('@seriesThumbnail') .first() .trigger('mousedown', { which: 1, button: 0 }) .trigger('dragstart', { dataTransfer }) .trigger('drag', {}); - cy.get('.cornerstone-canvas') + + cy.get('.cornerstone-canvas').as('viewport'); + + cy.get('@viewport') .trigger('mousemove', 'center') .trigger('dragover', { dataTransfer, force: true }) .trigger('drop', { dataTransfer, force: true }); diff --git a/platform/app/cypress/support/commands.js b/platform/app/cypress/support/commands.js index 58bcd192d..a84997598 100644 --- a/platform/app/cypress/support/commands.js +++ b/platform/app/cypress/support/commands.js @@ -125,6 +125,8 @@ Cypress.Commands.add('openStudyList', () => { }); Cypress.Commands.add('waitStudyList', () => { + // wait 1 second for the studies to get updated + cy.wait(1000); cy.get('@searchResult').should($list => { expect($list).to.not.have.class('no-hover'); }); @@ -132,7 +134,7 @@ Cypress.Commands.add('waitStudyList', () => { Cypress.Commands.add('waitViewportImageLoading', () => { // Wait for finish loading - cy.get('[data-cy="viewprt-grid"]', { timeout: 30000 }).should($grid => { + cy.get('[data-cy="viewport-grid"]', { timeout: 30000 }).should($grid => { expect($grid).not.to.contain.text('Load'); }); }); diff --git a/platform/app/package.json b/platform/app/package.json index 6a667000a..5225d245f 100644 --- a/platform/app/package.json +++ b/platform/app/package.json @@ -51,7 +51,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.2", - "@cornerstonejs/dicom-image-loader": "^1.20.3", + "@cornerstonejs/dicom-image-loader": "^1.27.3", "@ohif/core": "3.8.0-beta.9", "@ohif/extension-cornerstone": "3.8.0-beta.9", "@ohif/extension-cornerstone-dicom-rt": "3.8.0-beta.9", @@ -72,7 +72,7 @@ "classnames": "^2.3.2", "core-js": "^3.16.1", "cornerstone-math": "^0.1.9", - "dcmjs": "^0.29.11", + "dcmjs": "^0.29.12", "detect-gpu": "^4.0.16", "dicom-parser": "^1.8.9", "dotenv-webpack": "^1.7.0", diff --git a/platform/app/public/config/default_16bit.js b/platform/app/public/config/default_16bit.js index 20b14d6b9..6ea743999 100644 --- a/platform/app/public/config/default_16bit.js +++ b/platform/app/public/config/default_16bit.js @@ -15,7 +15,7 @@ window.config = { showWarningMessageForCrossOrigin: false, showCPUFallbackMessage: true, showLoadingIndicator: true, - use16BitDataType: true, + useNorm16Texture: true, useSharedArrayBuffer: 'AUTO', maxNumRequests: { interaction: 100, diff --git a/platform/core/package.json b/platform/core/package.json index 7de7abe29..66ab684d2 100644 --- a/platform/core/package.json +++ b/platform/core/package.json @@ -35,14 +35,14 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.2", - "@cornerstonejs/dicom-image-loader": "^1.20.3", + "@cornerstonejs/dicom-image-loader": "^1.27.3", "@ohif/ui": "3.8.0-beta.9", "cornerstone-math": "0.1.9", "dicom-parser": "^1.8.21" }, "dependencies": { "@babel/runtime": "^7.20.13", - "dcmjs": "^0.29.11", + "dcmjs": "^0.29.12", "dicomweb-client": "^0.10.2", "gl-matrix": "^3.4.3", "isomorphic-base64": "^1.0.2", diff --git a/platform/core/src/services/DisplaySetService/DisplaySetService.ts b/platform/core/src/services/DisplaySetService/DisplaySetService.ts index 8d01a28dc..3db737c0c 100644 --- a/platform/core/src/services/DisplaySetService/DisplaySetService.ts +++ b/platform/core/src/services/DisplaySetService/DisplaySetService.ts @@ -36,7 +36,7 @@ export default class DisplaySetService extends PubSubService { }; public activeDisplaySets = []; - public unsuportedSOPClassHandler; + public unsupportedSOPClassHandler; extensionManager: ExtensionManager; protected activeDisplaySetsMap = new Map(); @@ -47,7 +47,7 @@ export default class DisplaySetService extends PubSubService { constructor() { super(EVENTS); - this.unsuportedSOPClassHandler = + this.unsupportedSOPClassHandler = '@ohif/extension-default.sopClassHandlerModule.not-supported-display-sets-handler'; } @@ -81,7 +81,7 @@ export default class DisplaySetService extends PubSubService { * @param sopClassHandlerUID */ public setUnsuportedSOPClassHandler(sopClassHandler) { - this.unsuportedSOPClassHandler = sopClassHandler; + this.unsupportedSOPClassHandler = sopClassHandler; } /** @@ -384,7 +384,7 @@ export default class DisplaySetService extends PubSubService { // applying the default sopClassUID handler if (allDisplaySets.length === 0) { // applying hp-defined viewport settings to the displaysets - const handler = this.extensionManager.getModuleEntry(this.unsuportedSOPClassHandler); + const handler = this.extensionManager.getModuleEntry(this.unsupportedSOPClassHandler); const displaySets = handler.getDisplaySetsFromSeries(instances); if (displaySets?.length) { displaySets.forEach(ds => { diff --git a/platform/core/src/utils/isDisplaySetReconstructable.js b/platform/core/src/utils/isDisplaySetReconstructable.js index 8b348177d..2d36266c4 100644 --- a/platform/core/src/utils/isDisplaySetReconstructable.js +++ b/platform/core/src/utils/isDisplaySetReconstructable.js @@ -14,15 +14,12 @@ export default function isDisplaySetReconstructable(instances) { if (!instances.length) { return { value: false }; } - const firstInstance = instances[0]; - const Modality = firstInstance.Modality; const isMultiframe = firstInstance.NumberOfFrames > 1; - if (!constructableModalities.includes(Modality)) { - return { value: false }; - } + // We used to check is reconstructable modalities here, but the logic is removed + // in favor of the calculation by metadata (orientation and positions) // Can't reconstruct if we only have one image. if (!isMultiframe && instances.length === 1) { diff --git a/platform/docs/docs/assets/img/filtering-worklist.png b/platform/docs/docs/assets/img/filtering-worklist.png new file mode 100644 index 000000000..47ab317d9 Binary files /dev/null and b/platform/docs/docs/assets/img/filtering-worklist.png differ diff --git a/platform/docs/docs/assets/img/large-pt-ct.png b/platform/docs/docs/assets/img/large-pt-ct.png new file mode 100644 index 000000000..16c16bcba Binary files /dev/null and b/platform/docs/docs/assets/img/large-pt-ct.png differ diff --git a/platform/docs/docs/assets/img/memory-profiling-regular.png b/platform/docs/docs/assets/img/memory-profiling-regular.png new file mode 100644 index 000000000..dd87a3430 Binary files /dev/null and b/platform/docs/docs/assets/img/memory-profiling-regular.png differ diff --git a/platform/docs/docs/assets/img/preferSizeOverAccuracy.png b/platform/docs/docs/assets/img/preferSizeOverAccuracy.png new file mode 100644 index 000000000..253414cdd Binary files /dev/null and b/platform/docs/docs/assets/img/preferSizeOverAccuracy.png differ diff --git a/platform/docs/docs/assets/img/webgl-int16.png b/platform/docs/docs/assets/img/webgl-int16.png new file mode 100644 index 000000000..1a9abd8cf Binary files /dev/null and b/platform/docs/docs/assets/img/webgl-int16.png differ diff --git a/platform/docs/docs/assets/img/webgl-report-norm16.png b/platform/docs/docs/assets/img/webgl-report-norm16.png new file mode 100644 index 000000000..766938ba5 Binary files /dev/null and b/platform/docs/docs/assets/img/webgl-report-norm16.png differ diff --git a/platform/docs/docs/configuration/configurationFiles.md b/platform/docs/docs/configuration/configurationFiles.md index 96325b2d9..b35ed758d 100644 --- a/platform/docs/docs/configuration/configurationFiles.md +++ b/platform/docs/docs/configuration/configurationFiles.md @@ -179,7 +179,7 @@ if auth headers are used, a preflight request is required. } ``` - `showLoadingIndicator`: (default to true), if set to false, the loading indicator will not be shown when navigating between studies. -- `use16BitDataType`: (default to false), if set to true, it will use 16 bit data type for the image data wherever possible which has +- `useNorm16Texture`: (default to false), if set to true, it will use 16 bit data type for the image data wherever possible which has significant impact on reducing the memory usage. However, the 16Bit textures require EXT_texture_norm16 extension in webGL 2.0 (you can check if you have it here https://webglreport.com/?v=2). In addition to the extension, there are reported problems for Intel Macs that might cause the viewer to crash. In summary, it is great a configuration if you have support for it. - `useSharedArrayBuffer` (default to 'TRUE', options: 'AUTO', 'FALSE', 'TRUE', note that these are strings), for volume loading we use sharedArrayBuffer to be able to load the volume progressively as the data arrives (each webworker has the shared buffer and can write to it). However, there might be certain environments that do not support sharedArrayBuffer. In that case, you can set this flag to false and the viewer will use the regular arrayBuffer which might be slower for large volume loading. diff --git a/platform/docs/docs/faq.md b/platform/docs/docs/faq.md index 01d42ee95..8746e5d98 100644 --- a/platform/docs/docs/faq.md +++ b/platform/docs/docs/faq.md @@ -3,36 +3,45 @@ sidebar_position: 8 sidebar_label: FAQ --- -# Frequently Asked Questions -## Index +- [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 The OHIF Viewer HIPAA Compliant?](#is-the-ohif-viewer-hipaa-compliant) +- [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) -- [Report a bug][report-bug] -- [Request a feature][new-feature] -- [Commercial Support & Consulting][commercial-support] -- [Academic collaborations][academic] -- [FDA Clearance or CE Marking][fda-clearance] -- [HIPAA Compliance][hipaa] -### How do I report a bug? +# 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? +## 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://www.ohif.org) or work with community members that -offer [consulting services][commercial-support]. +please [contact us](https://ohif.org/get-support). -### 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 [./deployment/cors.md](./deployment/cors.md). -### Who should I contact about Academic Collaborations? +## 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 @@ -40,12 +49,12 @@ 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? +## 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? +## 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 @@ -56,28 +65,226 @@ 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 The OHIF Viewer [HIPAA][hipaa-def] Compliant? +## 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. +# 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). + +## 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 +array buffer which is a bit slower but will work on all browsers. + + +## Viewer opens but does not show any thumbnails + +Thumbnails may not appear in your DICOMWeb application for various reasons. This guide focuses on one primary scenario, which is you are using +the `supportsWildcard: true` in your configuration file while your sever does not support it. +One + +For instance for the following filtering in the worklist tab we send this request + +![](assets/img/filtering-worklist.png) + +`https://d33do7qe4w26qo.cloudfront.net/dicomweb/studies?PatientName=*Head*&limit=101&offset=0&fuzzymatching=false&includefield=00081030%2C00080060` + +Which our server can respond properly. If your server does not support this type of filtering, you can disable it by setting `supportsWildcard: false` in your configuration file, +or edit your server code to support it for instance something like + +```js +Pseudocode: +For each filter in filters: + if filter.value contains "*": + Convert "*" to SQL LIKE wildcard ("%") + Add "metadataField LIKE ?" to query + else: + Add "metadataField = ?" to query +``` + + + +## What are the list of required metadata for the OHIF Viewer to work? + + +### Mandatory + +**All Modalities** + +- `StudyInstanceUID`, `SeriesInstanceUID`, `SOPInstanceUID`: Unique identifiers for the study, series, and object. +- `PhotometricInterpretation`: Describes the color space of the image. +- `Rows`, `Columns`: Image dimensions. +- `PixelRepresentation`: Indicates how pixel data should be interpreted. +- `Modality`: Type of modality (e.g., CT, MR, etc.). +- `PixelSpacing`: Spacing between pixels. +- `BitsAllocated`: Number of bits allocated for each pixel sample. +- `SOPClassUID`: Specifies the DICOM service class of the object (though you might be able to render without it for most regular images datasets, but it is pretty normal to have it) + +**Rendering** + +You need to have the following tags for the viewer to render the image properly, otherwise you should +use the windowing tools to adjust the image to your liking: + +- `RescaleIntercept`, `RescaleSlope`: Values used for rescaling pixel values for visualization. +- `WindowCenter`, `WindowWidth`: Windowing parameters for display. + +**Some Datasets** + +- `InstanceNumber`: Useful for sorting instances (without it the instances might be out of order) + +**For MPR (Multi-Planar Reformatting) rendering and tools** + +- `ImagePositionPatient`, `ImageOrientationPatient`: Position and orientation of the image in the patient. + +**SEG (Segmentation)** + +- `FrameOfReferenceUID` for handling segmentation layers. +- sequences + - `ReferencedSeriesSequence` + - `SharedFunctionalGroupsSequence` + - `PerFrameFunctionalGroupsSequence` + +**RTSTRUCT (Radiotherapy Structure)** + +- `FrameOfReferenceUID` for handling segmentation layers. +- sequences + - `ROIContourSequence` + - `StructureSetROISequence` + - `ReferencedFrameOfReferenceSequence` + +**US (Ultrasound)** + +- `NumberOfFrames`: Number of frames in a multi-frame image. +- `SequenceOfUltrasoundRegions`: For measurements. +- `FrameTime`: Time between frames if specified. + +**SR (Structured Reporting)** + +- Various sequences for encoding the report content and template. + - `ConceptNameCodeSequence` + - `ContentSequence` + - `ContentTemplateSequence` + - `CurrentRequestedProcedureEvidenceSequence` + - `ContentTemplateSequence` + - `CodingSchemeIdentificationSequence` + +**PT with SUV Correction (Positron Tomography Standardized Uptake Value)** + +- Sequences and tags related to radiopharmaceuticals, units, corrections, and timing. + - `RadiopharmaceuticalInformationSequence` + - `SeriesDate` + - `SeriesTime` + - `CorrectedImage` + - `Units` + - `DecayCorrection` + - `AcquisitionDate` + - `AcquisitionTime` + - `PatientWeight` + +**PDF** + +- `EncapsulatedDocument`: Contains the PDF document. + +**Video** + +- `NumberOfFrames`: Video frame count . + + +### Optional +There are various other optional tags that will add to the viewer experience, but are not required for basic functionality. These include: +Patient Information, Study Information, Series Information, Instance Information, and Frame Information. + + +## How do I handle large volumes for MPR and Volume Rendering + +Currently there are two ways to handle large volumes for MPR and Volume Rendering if that does not +fit in the memory of the client machine. + +### `useNorm16Texture` + +WebGL officially supports only 8-bit and 32-bit data types. For most images, 8 bits are not enough, and 32 bits are too much. However, we have to use the 32-bit data type for volume rendering and MPR, which results in suboptimal memory consumption for the application. + +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) + + +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) + +Before (without the flag) the app shows 399 MB of memory usage + +![](assets/img/memory-profiling-regular.png) + + +After (with flag, running locally) the app shows 249 MB of memory usage + + +![](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 +would be exactly shown as it is. For datasets that cannot be represented with 16 bit data type, the flag will be ignored +and the 32 bit data type will be used. + + +Read more about these discussions in our PRs +- https://github.com/Kitware/vtk-js/pull/2058 +::: + + +:::warning +Although the support for 16 bit data type is available in WebGL, in some settings (e.g., Intel-based Macos) there seems +to be still some issues with it. You can read and track bugs below. + +- https://bugs.chromium.org/p/chromium/issues/detail?id=1246379 +- https://bugs.chromium.org/p/chromium/issues/detail?id=1408247 +::: + +### `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. + +```js +Integers between 0 and 2048 can be exactly represented (and also between −2048 and 0) +Integers between 2048 and 4096 round to a multiple of 2 (even number) +Integers between 4096 and 8192 round to a multiple of 4 +Integers between 8192 and 16384 round to a multiple of 8 +Integers between 16384 and 32768 round to a multiple of 16 +Integers between 32768 and 65519 round to a multiple of 32 +``` + +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) + + + + - - - +[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= - diff --git a/platform/ui/src/components/StudyItem/StudyItem.tsx b/platform/ui/src/components/StudyItem/StudyItem.tsx index f382bf652..6e7804fab 100644 --- a/platform/ui/src/components/StudyItem/StudyItem.tsx +++ b/platform/ui/src/components/StudyItem/StudyItem.tsx @@ -67,7 +67,7 @@ const StudyItem = ({ StudyItem.propTypes = { date: PropTypes.string.isRequired, - description: PropTypes.string.isRequired, + description: PropTypes.string, modalities: PropTypes.string.isRequired, numInstances: PropTypes.number.isRequired, trackedSeries: PropTypes.number, diff --git a/yarn.lock b/yarn.lock index a52cf2fb7..bdf462091 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1487,10 +1487,10 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@cornerstonejs/adapters@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.20.3.tgz#9a01c4922edf2f53b3245accf47a93cb4db69119" - integrity sha512-YfI656cb09xVjZ25/bkkbgFJjEf57jhCjexabvkytK7rcE5hfpru3+ztHjl1b8GUOGqT2tYu4n8XsJwVkbK1GA== +"@cornerstonejs/adapters@^1.27.3": + version "1.27.3" + resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.27.3.tgz#537ce2f53532fe69fdd0630a3990409f75c92035" + integrity sha512-b71ne2Bb10qFud2GZ5td7HgpEOuWwR0tkD9P040mpvfOSHOiLfCuMihwH8dGML5Zuyl6X0nR1UcOyzVjQra3QQ== dependencies: "@babel/runtime-corejs2" "^7.17.8" buffer "^6.0.3" @@ -1539,43 +1539,43 @@ resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.2.tgz#e96721d56f6ec96f7f95c16321d88cc8467d8d81" integrity sha512-lgdvBvvNezleY+4pIe2ceUsJzlZe/0PipdeubQ3vZZOz3xxtHHMR1XFCl4fgd8gosR8COHuD7h6q+MwgrwBsng== -"@cornerstonejs/core@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.20.3.tgz#6b9c2fb1e7c697ea739bd7c1ab2fb0a70eb51728" - integrity sha512-EDmGbkzu+oW+n62Vtzjf2SxdavYYOGoGaRn/GGipU1fD1R6ffgq8W0CfGEKZ61O2vOvx7IHGLbqWZj9eKD85zA== +"@cornerstonejs/core@^1.27.3": + version "1.27.3" + resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.27.3.tgz#37084038c30bed71ad260f969dec5ebd9fdc2e16" + integrity sha512-F84+XnhM6PeymE7m58Zr0PUuwIEgW+9lxy2mZcOkOQdjgq86cRLM4bW8kIli+WlFMB1NA2B26TbA4T0cbwHw5A== dependencies: "@kitware/vtk.js" "27.3.1" detect-gpu "^5.0.22" gl-matrix "^3.4.3" lodash.clonedeep "4.5.0" -"@cornerstonejs/dicom-image-loader@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.20.3.tgz#37f4347826645d26b1819922d8ebc48ad3f23d95" - integrity sha512-rm2o1kfLwm0VDZMwOuPD78sVS3UZsCHoUZFeZBfLdfw+DTBdnNkkKMAbA617c61XSaR85CM7erwWG3wAJG9+vw== +"@cornerstonejs/dicom-image-loader@^1.27.3": + version "1.27.3" + resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.27.3.tgz#5fdfda4294a1a4feb77e06972a354ecb7dad61a9" + integrity sha512-C8/D/AkoZzurY/O8DiTKzchcUB0LXZ1+A5mWVpE1NFrlXjKMwAi+O4vbyRIJX/h/96QgtP6NVo4ilLJk/EN0qQ== 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.2" - "@cornerstonejs/core" "^1.20.3" + "@cornerstonejs/core" "^1.27.3" dicom-parser "^1.8.9" pako "^2.0.4" uuid "^9.0.0" -"@cornerstonejs/streaming-image-volume-loader@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.20.3.tgz#1520efda9bbebcb23b6574293cc166bbe65f3e9f" - integrity sha512-3C+NZ2elT8Do3Oi7jTB6w0D7SogE6ttLxxg7DdXNuhZuB/osJaoGLzhbnpyjyq5mnz8T89F8gY6RWdaK5cNaIw== +"@cornerstonejs/streaming-image-volume-loader@^1.27.3": + version "1.27.3" + resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.27.3.tgz#c19cc4fc5e0aefe6a421b6c1994ed46c8c516132" + integrity sha512-1EVYHfbIkx9MAMT6hNsKcuzsnlCUmKvSxHZJMSNQCERlBwCxoUKymGAE9dcBsa0CBKwsBri0dnQmMKEEL2R7sQ== dependencies: - "@cornerstonejs/core" "^1.20.3" + "@cornerstonejs/core" "^1.27.3" -"@cornerstonejs/tools@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.20.3.tgz#c93165c17fab3995e06efafe1676cde119425c67" - integrity sha512-VFkvUvy45zsWZ8WSaL9QTwNDI7VV7tL4q4KjI5y7X++nFZBrV8redJfMun6vnCNPIbwsb0nuUYqadrHv6gOEZQ== +"@cornerstonejs/tools@^1.27.3": + version "1.27.3" + resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.27.3.tgz#66b3ab96ceafc525f0d460f7063e304eb4decbfa" + integrity sha512-coN7+nLyn+RZ5gz6Mq7ylLBNGKt50ifnn7J9ggeGtHf7acWkH8GngWLyVBYM+bh3WCUpai3RhvWK6pAbx+oRHw== dependencies: - "@cornerstonejs/core" "^1.20.3" + "@cornerstonejs/core" "^1.27.3" lodash.clonedeep "4.5.0" lodash.get "^4.4.2" @@ -8458,10 +8458,10 @@ dcmjs@^0.27: loglevelnext "^3.0.1" ndarray "^1.0.19" -dcmjs@^0.29.11: - version "0.29.11" - resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.29.11.tgz#82e19d7c5212218c3225f8022ce97b0102ed3cc8" - integrity sha512-B5fO5D+USzfnuUG7ephnaKMluqBOP4qcckV2LgROXvn0hmWc53Gs2YzlokjcYcDeBAXNfssOOhDekUc+AduwkQ== +dcmjs@^0.29.12: + version "0.29.12" + resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.29.12.tgz#94f484f6ee4901e44d17113f005a917500544cd3" + integrity sha512-LQBxinj4CZQU2J61hf0/QXHe/OA+EM0ie+JbZ4eMaQAYfMOaDDkYG25zP3bNNDBFlY5ytgwsfWLvmvanQ9ixYg== dependencies: "@babel/runtime-corejs3" "^7.22.5" adm-zip "^0.5.10"