diff --git a/extensions/cornerstone-dicom-seg/src/utils/_hydrateSEG.ts b/extensions/cornerstone-dicom-seg/src/utils/_hydrateSEG.ts index 343f583b12..f6b1522be7 100644 --- a/extensions/cornerstone-dicom-seg/src/utils/_hydrateSEG.ts +++ b/extensions/cornerstone-dicom-seg/src/utils/_hydrateSEG.ts @@ -31,8 +31,6 @@ async function _hydrateSEGDisplaySet({ displaySetInstanceUID ); - viewportGridService.setDisplaySetsForViewports(updatedViewports); - // Todo: fix this after we have a better way for stack viewport segmentations // check every viewport in the viewports to see if the displaySetInstanceUID @@ -50,7 +48,7 @@ async function _hydrateSEGDisplaySet({ ); if (shouldDisplaySeg) { - viewportGridService.setDisplaySetsForViewport({ + updatedViewports.push({ viewportIndex: index, displaySetInstanceUIDs: viewport.displaySetInstanceUIDs, viewportOptions: { @@ -62,6 +60,9 @@ async function _hydrateSEGDisplaySet({ } }); + // Do the entire update at once + viewportGridService.setDisplaySetsForViewports(updatedViewports); + return true; } diff --git a/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx b/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx index 411e17a101..83d012ef21 100644 --- a/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx +++ b/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx @@ -10,7 +10,6 @@ import { utilities as csUtils, CONSTANTS, } from '@cornerstonejs/core'; -import { Services } from '@ohif/core'; import { setEnabledElement } from '../state'; @@ -23,9 +22,6 @@ import { import getSOPInstanceAttributes from '../utils/measurementServiceMappings/utils/getSOPInstanceAttributes'; import { CinePlayer, useCine, useViewportGrid } from '@ohif/ui'; -import { CornerstoneViewportService } from '../services/ViewportService/CornerstoneViewportService'; -import Presentation from '../types/Presentation'; - const STACK = 'stack'; function areEqual(prevProps, nextProps) { @@ -407,7 +403,6 @@ const OHIFCornerstoneViewport = React.memo(props => { lutPresentation: lutPresentationStore[presentationIds?.lutPresentationId], }; - console.log('Using presentations', presentations); cornerstoneViewportService.setViewportData( viewportIndex, diff --git a/extensions/cornerstone/src/getHangingProtocolModule.ts b/extensions/cornerstone/src/getHangingProtocolModule.ts index 17190e8e59..2c21e0ab16 100644 --- a/extensions/cornerstone/src/getHangingProtocolModule.ts +++ b/extensions/cornerstone/src/getHangingProtocolModule.ts @@ -11,7 +11,7 @@ const mpr: Types.HangingProtocol.Protocol = { // Unknown number of priors referenced - so just match any study numberOfPriorsReferenced: 0, protocolMatchingRules: [], - imageLoadStrategy: 'interleaveTopToBottom', + imageLoadStrategy: 'nth', callbacks: { // Switches out of MPR mode when the layout change button is used onLayoutChange: [ @@ -303,11 +303,11 @@ const mprAnd3DVolumeViewport = { function getHangingProtocolModule() { return [ { - id: 'mpr', + name: 'mpr', protocol: mpr, }, { - id: mprAnd3DVolumeViewport.id, + name: mprAnd3DVolumeViewport.id, protocol: mprAnd3DVolumeViewport, }, ]; diff --git a/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts b/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts index 363c82985a..946dee124d 100644 --- a/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts +++ b/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts @@ -155,9 +155,14 @@ class CornerstoneViewportService extends PubSubService /** * Disables the viewport inside the renderingEngine, if no viewport is left * it destroys the renderingEngine. + * + * This is called when the element goes away entirely - with new viewportId's + * created for every new viewport, this will be called whenever the set of + * viewports is changed, but NOT when the viewport position changes only. + * * @param viewportIndex */ - public disableElement(viewportIndex: number) { + public disableElement(viewportIndex: number): void { const viewportInfo = this.viewportsInfo.get(viewportIndex); if (!viewportInfo) { return; @@ -254,12 +259,6 @@ class CornerstoneViewportService extends PubSubService viewportInfo.setDisplaySetOptions(displaySetOptions); viewportInfo.setViewportData(viewportData); - this._broadcastEvent(this.EVENTS.VIEWPORT_DATA_CHANGED, { - viewportData, - viewportIndex, - viewportId, - }); - const element = viewportInfo.getElement(); const type = viewportInfo.getViewportType(); const background = viewportInfo.getBackground(); @@ -283,6 +282,15 @@ class CornerstoneViewportService extends PubSubService const viewport = renderingEngine.getViewport(viewportId); this._setDisplaySets(viewport, viewportData, viewportInfo, presentations); + + // The broadcast event here ensures that listeners have a valid, up to date + // viewport to access. Doing it too early can result in exceptions or + // invalid data. + this._broadcastEvent(this.EVENTS.VIEWPORT_DATA_CHANGED, { + viewportData, + viewportIndex, + viewportId, + }); } public getCornerstoneViewport( @@ -386,11 +394,7 @@ class CornerstoneViewportService extends PubSubService } } - // There is a bug in CS3D that the setStack does not - // navigate to the desired image. - viewport.setStack(imageIds, 0).then(() => { - // The scroll, however, works fine in CS3D - viewport.scroll(initialImageIndexToUse); + viewport.setStack(imageIds, initialImageIndexToUse).then(() => { viewport.setProperties(properties); const camera = presentations.positionPresentation?.camera; if (camera) viewport.setCamera(camera); @@ -621,6 +625,10 @@ class CornerstoneViewportService extends PubSubService const viewportInfo = this.getViewportInfo(viewport.id); + if (!viewportInfo) { + console.warn('Viewport info not defined for', viewport.id); + } + const toolGroup = toolGroupService.getToolGroupForViewport(viewport.id); csToolsUtils.segmentation.triggerSegmentationRender(toolGroup.id); diff --git a/extensions/cornerstone/src/utils/nthLoader.ts b/extensions/cornerstone/src/utils/nthLoader.ts index a34066eb2c..bce0d22f5f 100644 --- a/extensions/cornerstone/src/utils/nthLoader.ts +++ b/extensions/cornerstone/src/utils/nthLoader.ts @@ -18,7 +18,6 @@ const viewportIdVolumeInputArrayMap = new Map(); export default function interleaveNthLoader({ data: { viewportId, volumeInputArray }, displaySetsMatchDetails, - viewportMatchDetails: matchDetails, }) { viewportIdVolumeInputArrayMap.set(viewportId, volumeInputArray); @@ -29,6 +28,7 @@ export default function interleaveNthLoader({ const volume = cache.getVolume(volumeId); if (!volume) { + console.log("interleaveNthLoader::No volume, can't load it"); return; } @@ -39,33 +39,6 @@ export default function interleaveNthLoader({ } } - /** - * The following is checking if all the viewports that were matched in the HP has been - * successfully created their cornerstone viewport or not. Todo: This can be - * improved by not checking it, and as soon as the matched DisplaySets have their - * volume loaded, we start the loading, but that comes at the cost of viewports - * not being created yet (e.g., in a 10 viewport ptCT fusion, when one ct viewport and one - * pt viewport are created we have a guarantee that the volumes are created in the cache - * but the rest of the viewports (fusion, mip etc.) are not created yet. So - * we can't initiate setting the volumes for those viewports. One solution can be - * to add an event when a viewport is created (not enabled element event) and then - * listen to it and as the other viewports are created we can set the volumes for them - * since volumes are already started loading. - */ - if (matchDetails.size !== viewportIdVolumeInputArrayMap.size) { - return; - } - - // Check if all the matched volumes are loaded - for (const [_, details] of displaySetsMatchDetails.entries()) { - const { SeriesInstanceUID } = details; - - // HangingProtocol has matched, but don't have all the volumes created yet, so return - if (!Array.from(volumeIdMapsToLoad.values()).includes(SeriesInstanceUID)) { - return; - } - } - const volumeIds = Array.from(volumeIdMapsToLoad.keys()).slice(); // get volumes from cache const volumes = volumeIds.map(volumeId => { diff --git a/extensions/default/src/getHangingProtocolModule.js b/extensions/default/src/getHangingProtocolModule.js index 3df2c9a564..a975a89680 100644 --- a/extensions/default/src/getHangingProtocolModule.js +++ b/extensions/default/src/getHangingProtocolModule.js @@ -290,7 +290,7 @@ const defaultProtocol = { function getHangingProtocolModule() { return [ { - id: defaultProtocol.id, + name: defaultProtocol.id, protocol: defaultProtocol, }, ]; diff --git a/extensions/test-extension/src/hp/index.ts b/extensions/test-extension/src/hp/index.ts index a24aebb598..a1b0c22c21 100644 --- a/extensions/test-extension/src/hp/index.ts +++ b/extensions/test-extension/src/hp/index.ts @@ -2,7 +2,7 @@ import hpMN from './hpMN'; const hangingProtocols = [ { - id: '@ohif/hp-extension.mn', + name: '@ohif/hp-extension.mn', protocol: hpMN, }, ]; diff --git a/extensions/tmtv/src/getHangingProtocolModule.js b/extensions/tmtv/src/getHangingProtocolModule.js index 63a9ba0550..45720c10d5 100644 --- a/extensions/tmtv/src/getHangingProtocolModule.js +++ b/extensions/tmtv/src/getHangingProtocolModule.js @@ -323,7 +323,7 @@ const ptCT = { function getHangingProtocolModule() { return [ { - id: ptCT.id, + name: ptCT.id, protocol: ptCT, }, ]; diff --git a/platform/core/src/extensions/ExtensionManager.test.js b/platform/core/src/extensions/ExtensionManager.test.js index 4177deab74..2af3ce52a0 100644 --- a/platform/core/src/extensions/ExtensionManager.test.js +++ b/platform/core/src/extensions/ExtensionManager.test.js @@ -206,40 +206,40 @@ describe('ExtensionManager.ts', () => { const extension = { id: 'hello-world', getViewportModule: () => { - return [{}]; + return [{ name: 'test' }]; }, getSopClassHandlerModule: () => { - return [{}]; + return [{ name: 'test' }]; }, getPanelModule: () => { - return [{}]; + return [{ name: 'test' }]; }, getToolbarModule: () => { - return [{}]; + return [{ name: 'test' }]; }, getCommandsModule: () => { - return [{}]; + return [{ name: 'test' }]; }, getLayoutTemplateModule: () => { - return [{}]; + return [{ name: 'test' }]; }, getDataSourcesModule: () => { - return [{}]; + return [{ name: 'test' }]; }, getHangingProtocolModule: () => { - return [{}]; + return [{ name: 'test' }]; }, getContextModule: () => { - return [{}]; + return [{ name: 'test' }]; }, getUtilityModule: () => { - return [{}]; + return [{ name: 'test' }]; }, getCustomizationModule: () => { - return [{}]; + return [{ name: 'test' }]; }, getStateSyncModule: () => { - return [{}]; + return [{ name: 'test' }]; }, }; diff --git a/platform/core/src/extensions/ExtensionManager.ts b/platform/core/src/extensions/ExtensionManager.ts index f4f6292246..188da5adda 100644 --- a/platform/core/src/extensions/ExtensionManager.ts +++ b/platform/core/src/extensions/ExtensionManager.ts @@ -283,6 +283,11 @@ export default class ExtensionManager { // Default for most extension points, // Just adds each entry ready for consumption by mode. extensionModule.forEach(element => { + if (!element.name) { + throw new Error( + `Extension ID ${extensionId} module ${moduleType} element has no name` + ); + } const id = `${extensionId}.${moduleType}.${element.name}`; element.id = id; this.modulesMap[id] = element; @@ -366,10 +371,10 @@ export default class ExtensionManager { _initHangingProtocolsModule = (extensionModule, extensionId) => { const { hangingProtocolService } = this._servicesManager.services; - extensionModule.forEach(({ id, protocol }) => { + extensionModule.forEach(({ name, protocol }) => { if (protocol) { // Only auto-register if protocol specified, otherwise let mode register - hangingProtocolService.addProtocol(id, protocol); + hangingProtocolService.addProtocol(name, protocol); } }); }; diff --git a/platform/core/src/services/ViewportGridService/ViewportGridService.ts b/platform/core/src/services/ViewportGridService/ViewportGridService.ts index be98756701..239db4f88b 100644 --- a/platform/core/src/services/ViewportGridService/ViewportGridService.ts +++ b/platform/core/src/services/ViewportGridService/ViewportGridService.ts @@ -26,7 +26,6 @@ class ViewportGridService extends PubSubService { public setServiceImplementation({ getState: getStateImplementation, setActiveViewportIndex: setActiveViewportIndexImplementation, - setDisplaySetsForViewport: setDisplaySetsForViewportImplementation, setDisplaySetsForViewports: setDisplaySetsForViewportsImplementation, setLayout: setLayoutImplementation, reset: resetImplementation, @@ -40,9 +39,6 @@ class ViewportGridService extends PubSubService { if (setActiveViewportIndexImplementation) { this.serviceImplementation._setActiveViewportIndex = setActiveViewportIndexImplementation; } - if (setDisplaySetsForViewportImplementation) { - this.serviceImplementation._setDisplaySetsForViewport = setDisplaySetsForViewportImplementation; - } if (setDisplaySetsForViewportsImplementation) { this.serviceImplementation._setDisplaySetsForViewports = setDisplaySetsForViewportsImplementation; } @@ -77,22 +73,13 @@ class ViewportGridService extends PubSubService { return this.serviceImplementation._getState(); } - public setDisplaySetsForViewport({ - viewportIndex, - displaySetInstanceUIDs, - viewportOptions, - displaySetOptions, - }) { - this.serviceImplementation._setDisplaySetsForViewport({ - viewportIndex, - displaySetInstanceUIDs, - viewportOptions, - displaySetOptions, - }); + public setDisplaySetsForViewport(props) { + // Just update a single viewport, but use the multi-viewport update for it. + this.serviceImplementation._setDisplaySetsForViewports([props]); } - public setDisplaySetsForViewports(viewports) { - this.serviceImplementation._setDisplaySetsForViewports(viewports); + public setDisplaySetsForViewports(props) { + this.serviceImplementation._setDisplaySetsForViewports(props); } /** diff --git a/platform/ui/src/contextProviders/ViewportGridProvider.tsx b/platform/ui/src/contextProviders/ViewportGridProvider.tsx index d74a6d7158..85fbb45db4 100644 --- a/platform/ui/src/contextProviders/ViewportGridProvider.tsx +++ b/platform/ui/src/contextProviders/ViewportGridProvider.tsx @@ -34,54 +34,85 @@ const DEFAULT_STATE = { export const ViewportGridContext = createContext(DEFAULT_STATE); +/** A viewport is reuseable if it is the same size as the old + * one and has the same display sets, in the same position. + * It SHOULD be possible to re-use them at different positions, but + * this causes problems with segmentation. + */ +const isReuseableViewport = (oldViewport, newViewport) => { + const sameDiplaySets = isEqual( + oldViewport.displaySetInstanceUIDs, + newViewport.displaySetInstanceUIDs + ); + return ( + oldViewport.viewportIndex === newViewport.viewportIndex && + sameDiplaySets && + oldViewport.height === newViewport.height && + oldViewport.width === newViewport.width + ); +}; + +// Holds a global viewport counter - used to assign new id's to viewports +// Starts at a value above zero so that any of the old viewport id's are +// immediately obvious and if we get any index generated viewports, they are +// definitely distinct from these ones. +let viewportCounter = 5000; + /** - * Find a viewport to re-use, and then set the viewportId + * Find a viewportId to re-use if possible, preserving the existing + * viewport information, OR create a new one if the viewport given isn't + * compatible with what was there before. * - * @param idSet + * @param viewportIdSet * @param viewport * @param stateViewports * @returns */ -const reuseViewport = (idSet, viewport, stateViewports) => { - const oldIds = {}; +const reuseViewportId = (viewportIdSet: Set, viewport, stateViewports) => { for (const oldViewport of stateViewports) { const { viewportId: oldId } = oldViewport; - oldIds[oldId] = true; - if (!oldId || idSet[oldId]) continue; - if ( - !isEqual( - oldViewport.displaySetInstanceUIDs, - viewport.displaySetInstanceUIDs - ) - ) { + if (!oldId) { + // This occurs on startup, so skip re-using it continue; } - idSet[oldId] = true; - // TODO re-use viewports once the flickering/wrong size redraw is fixed - // return { - // ...oldViewport, - // ...viewport, - // viewportOptions: { - // ...oldViewport.viewportOptions, - - // viewportId: oldViewport.viewportId, - // }, - // }; - } - // Find a viewport instance number different from earlier viewports having - // the same presentationIds as this one would - will be less than 10k - // viewports hopefully :-) - for (let i = 0; i < 10000; i++) { - const viewportId = 'viewport-' + i; - if (idSet[viewportId] || oldIds[viewportId]) continue; - idSet[viewportId] = true; - return { - ...viewport, - viewportId, - viewportOptions: { ...viewport.viewportOptions, viewportId }, - }; + if (viewportIdSet.has(oldId)) { + // oldId is already used - we can't reuse it + continue; + } + if (isReuseableViewport(oldViewport, viewport)) { + viewportIdSet.add(oldId); + // This means the old and the new viewport are compatible, and + // since we have gotten here, the viewport ID isn't used, so we + // are good to reuse it. + // This will remember the old viewport options, assuming they are unchanging. + return { + ...oldViewport, + ...viewport, + id: oldId, + viewportId: oldId, + viewportOptions: { + // Update any viewport options from new + ...viewport.viewportOptions, + viewportId: oldId, + }, + }; + } } - throw new Error('No ID found'); + + // There wasn't an old id found to be reused, so create a new one + // Find a viewport instance number different from earlier viewports + const viewportId = 'viewport-' + viewportCounter; + viewportIdSet.add(viewportId); + // Loop over viewport counters in case of a really long lived display + viewportCounter = (viewportCounter + 1) % 100000; + // viewportOptions is already a copy, so can just update direct + viewport.viewportOptions.viewportId = viewportId; + + return { + ...viewport, + id: viewportId, + viewportId, + }; }; export function ViewportGridProvider({ children, service }) { @@ -90,53 +121,72 @@ export function ViewportGridProvider({ children, service }) { case 'SET_ACTIVE_VIEWPORT_INDEX': { return { ...state, ...{ activeViewportIndex: action.payload } }; } - case 'SET_DISPLAYSET_FOR_VIEWPORT': { - const payload = action.payload; - const { viewportIndex, displaySetInstanceUIDs } = payload; - - // Note: there should be no inheritance happening at this level, - // we can't assume the new displaySet can inherit the previous - // displaySet's or viewportOptions at all. For instance, dragging - // and dropping a SEG/RT displaySet without any viewportOptions - // or displaySetOptions should not inherit the previous displaySet's - // which might have been a PDF Viewport. The viewport itself - // will deal with inheritance if required. Here is just a simple - // provider. - const viewport = state.viewports[viewportIndex] || {}; - const viewportOptions = { ...payload.viewportOptions }; - - const displaySetOptions = payload.displaySetOptions || []; - if (displaySetOptions.length === 0) { - // Only copy index 0, as that is all that is currently supported by this - // method call. - displaySetOptions.push({ ...viewport.displaySetOptions?.[0] }); - } + /** + * Sets the display sets for multiple viewports. + * This is a replacement for the older set display set for viewport (single) + * because the old one had race conditions wherein the viewports could + * render partially in various ways causing exceptions. + */ + case 'SET_DISPLAYSETS_FOR_VIEWPORTS': { + const { payload } = action; const viewports = state.viewports.slice(); - let newView = { - ...viewport, - displaySetInstanceUIDs, - viewportOptions, - displaySetOptions, - viewportLabel: viewportLabels[viewportIndex], - }; - viewportOptions.presentationIds = getPresentationIds( - newView, - viewports - ); - - // Make sure we assign a viewport id - newView = reuseViewport({}, newView, state.viewports); - console.log( - 'Creating new viewport', - viewportIndex, - newView.viewportOptions.viewportId, - displaySetInstanceUIDs, - displaySetOptions - ); - - viewports[viewportIndex] = newView; + // Have the initial id set contain all viewports not updated here + const viewportIdSet = new Set(); + viewports.forEach((viewport, index) => { + if (!viewport.viewportId) return; + const isUpdated = payload.find( + newViewport => newViewport.viewportIndex === index + ); + if (isUpdated) { + return; + } + viewportIdSet.add(viewport.viewportId); + }); + + for (const updatedViewport of payload) { + // Use the newly provide viewportOptions and display set options + // when provided, and otherwise fall back to the previous ones. + // That allows for easy updates of just the display set. + const { viewportIndex, displaySetInstanceUIDs } = updatedViewport; + const previousViewport = viewports[viewportIndex] || {}; + const viewportOptions = { + ...(updatedViewport.viewportOptions || + previousViewport.viewportOptions), + }; + + const displaySetOptions = updatedViewport.displaySetOptions || []; + if (!displaySetOptions.length) { + // Copy all the display set options, assuming a full set of displa + // set UID's is provided. + displaySetOptions.push(...previousViewport.displaySetOptions); + if (!displaySetOptions.length) { + displaySetOptions.push({}); + } + } + + let newViewport = { + ...previousViewport, + displaySetInstanceUIDs, + viewportOptions, + displaySetOptions, + viewportLabel: viewportLabels[viewportIndex], + }; + viewportOptions.presentationIds = getPresentationIds( + newViewport, + viewports + ); + + newViewport = reuseViewportId( + viewportIdSet, + newViewport, + state.viewports + ); + newViewport.viewportIndex = previousViewport.viewportIndex; + + viewports[viewportIndex] = newViewport; + } return { ...state, viewports }; } @@ -203,13 +253,13 @@ export function ViewportGridProvider({ children, service }) { activeViewportIndexToSet = activeViewportIndexToSet ?? 0; - const viewportIdSet = {}; + const viewportIdSet = new Set(); for ( let viewportIndex = 0; viewportIndex < viewports.length; viewportIndex++ ) { - const viewport = reuseViewport( + const viewport = reuseViewportId( viewportIdSet, viewports[viewportIndex], state.viewports @@ -268,36 +318,15 @@ export function ViewportGridProvider({ children, service }) { [dispatch] ); - const setDisplaySetsForViewport = useCallback( - ({ - viewportIndex, - displaySetInstanceUIDs, - viewportOptions, - displaySetSelectors, - displaySetOptions, - }) => + const setDisplaySetsForViewports = useCallback( + viewports => dispatch({ - type: 'SET_DISPLAYSET_FOR_VIEWPORT', - payload: { - viewportIndex, - displaySetInstanceUIDs, - viewportOptions, - displaySetSelectors, - displaySetOptions, - }, + type: 'SET_DISPLAYSETS_FOR_VIEWPORTS', + payload: viewports, }), [dispatch] ); - const setDisplaySetsForViewports = useCallback( - viewports => { - viewports.forEach(data => { - setDisplaySetsForViewport(data); - }); - }, - [setDisplaySetsForViewport] - ); - const setLayout = useCallback( ({ layoutType, @@ -355,7 +384,6 @@ export function ViewportGridProvider({ children, service }) { service.setServiceImplementation({ getState, setActiveViewportIndex, - setDisplaySetsForViewport, setDisplaySetsForViewports, setLayout, reset, @@ -368,7 +396,6 @@ export function ViewportGridProvider({ children, service }) { getState, service, setActiveViewportIndex, - setDisplaySetsForViewport, setDisplaySetsForViewports, setLayout, reset, @@ -379,7 +406,6 @@ export function ViewportGridProvider({ children, service }) { const api = { getState, setActiveViewportIndex: index => service.setActiveViewportIndex(index), // run it through the service itself since we want to publish events - setDisplaySetsForViewport, setDisplaySetsForViewports, setLayout: layout => service.setLayout(layout), // run it through the service itself since we want to publish events reset, diff --git a/platform/viewer/public/config/multiple.js b/platform/viewer/public/config/multiple.js index 7179bb74b7..f456575af4 100644 --- a/platform/viewer/public/config/multiple.js +++ b/platform/viewer/public/config/multiple.js @@ -42,6 +42,31 @@ window.config = { singlepart: 'bulkdata,video,pdf', }, }, + { + friendlyName: 'dcmjs DICOMWeb Server', + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'ohif', + configuration: { + name: 'aws', + // old server + // wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado', + // qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs', + // wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs', + // new server + wadoUriRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb', + qidoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb', + wadoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb', + qidoSupportsIncludeField: false, + supportsReject: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'bulkdata,video,pdf', + }, + }, { friendlyName: 'AWS S3 OHIF', namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',