How to display "Change layout (tool-layout)" features which not display currently?

HELLO.

Using these following Packages in my package.json:

"cornerstone-core": "^2.2.8",
    "cornerstone-math": "^0.1.7",
    "cornerstone-tools": "^2.4.0",
    "cornerstone-wado-image-loader": "^2.2.3",
    "dicom-parser": "^1.8.3",
    "hammerjs": "^2.0.8",
    "underscore": "^1.13.1"

In my case, I’ve noticed that the DICOM Viewer doesn’t support viewing multiple images simultaneously. Specifically, when you click the “Change layout (tool-layout)” icon (circled in orange in the attached OHIF DICOM Viewer screenshot), its contents don’t appear in the dropdown menu (also highlighted in yellow in the same screenshot), preventing you from changing or selecting a new layout. This isn’t normal.

So, how to fix that problem and make “Change layout (tool-layout)” dropwon work in my DICOM VIEWER like that above OHIF Viewer screenshot ???

How to enable that feature so that when we clique on it it works ??? Because, at this time, it’s unable and does not show its dropdown and features.

Awaiting your answer.

Welcome @chegmarco to the forum.

Thanks for your question, but I need some clarification. Are you describing a problem in OHIF or in a separate distinct viewer based on Cornerstone 3D?

Thanks @jbocce for your answer.

I’m using this DICOM Viewer “NEXTCLOUD DICOM-VIEWER” that I downloaded and edited into LARAVEL (in /modules/insurance/dicomviewer folder of my LARAVEL Application).
I think this DICOM Viewer is based on OHIF because of its design. This DICOM Viewer requires thses following Packages:

"cornerstone-core": "^2.2.8",
    "cornerstone-math": "^0.1.7",
    "cornerstone-tools": "^2.4.0",
    "cornerstone-wado-image-loader": "^2.2.3",
    "dicom-parser": "^1.8.3",
    "hammerjs": "^2.0.8",
    "underscore": "^1.13.1"

AND HAVE THIS FOLLOWING COMPILED CODE in Modules\Insurance\dicomviewer\js\public\viewer\app-config.js FILE:

window.config={routerBasename:"/modules/insurance/dicomviewer/apps/dicomviewer/ncviewer",extensions:[],modes:[],customizationService:{cornerstoneViewportActionBar:{disabled:!1},cornerstoneOverlayTopLeft:{id:"cornerstoneOverlayTopLeft",items:[{id:"PatientName",customizationType:"ohif.overlayItem",color:"#fff",label:"",condition:({instance:e})=>e&&e.PatientName&&("string"==typeof e.PatientName||e.PatientName.Alphabetic),contentF:({instance:e,formatters:{formatPN:t}})=>("string"==typeof e.PatientName?t(e.PatientName):t(e.PatientName.Alphabetic))+" "+(e.PatientSex?"("+e.PatientSex+")":"")},{id:"PID",customizationType:"ohif.overlayItem",color:"#fff",label:"",title:"Patient PID",condition:({instance:e})=>e&&e.PatientID,contentF:({instance:e})=>e.PatientID},{id:"PatientBirthDate",customizationType:"ohif.overlayItem",color:"#fff",label:"DOB:",title:"Patient's Date of birth",condition:({instance:e})=>e&&e.PatientBirthDate,contentF:({instance:e})=>e.PatientBirthDate},{id:"OtherPid",customizationType:"ohif.overlayItem",color:"#fff",label:"Other PID:",title:"Other Patient IDs",condition:({instance:e})=>e&&e.OtherPatientIDs,contentF:({instance:e,formatters:{formatPN:t}})=>t(e.OtherPatientIDs)}]},cornerstoneOverlayTopRight:{id:"cornerstoneOverlayTopRight",items:[{id:"SeriesDescription",customizationType:"ohif.overlayItem",color:"#fff",label:"",title:"Series Description",condition:({instance:e})=>e&&e.SeriesDescription,contentF:({instance:e})=>e.SeriesDescription},{id:"StudyDateTime",customizationType:"ohif.overlayItem",color:"#fff",label:"",title:"Study date",condition:({instance:e})=>e&&(e.StudyDate||e.StudyTime),contentF:({instance:e,formatters:{formatDate:t,formatTime:o}})=>[e.StudyDate?t(e.StudyDate):"",e.StudyTime?o(e.StudyTime):""].join(" ")}]},cornerstoneOverlayBottomLeft:{id:"cornerstoneOverlayBottomLeft",items:[{id:"SeriesNumber",customizationType:"ohif.overlayItem",color:"#fff",label:"Ser:",title:"Series Number",condition:({instance:e})=>e&&e.SeriesNumber,contentF:({instance:e})=>e.SeriesNumber},{id:"InstanceNmber",customizationType:"ohif.overlayItem.instanceNumber",color:"#fff"},{id:"ColumnsRows",customizationType:"ohif.overlayItem",color:"#fff",label:"",condition:({instance:e})=>e&&e.Columns&&e.Rows,contentF:({instance:e})=>`${e.Columns} x ${e.Rows}`},{id:"SliceLocation",customizationType:"ohif.overlayItem",color:"#fff",label:"Loc:",title:"Slice Location",condition:({instance:e})=>e&&e.SliceLocation,contentF:({instance:e,formatters:{formatNumberPrecision:t}})=>t(e.SliceLocation,2)+" mm"},{id:"SliceThickness",customizationType:"ohif.overlayItem",color:"#fff",label:"Thick:",title:"Slice Thickness",condition:({instance:e})=>e&&e.SliceThickness,contentF:({instance:e,formatters:{formatNumberPrecision:t}})=>t(e.SliceThickness,2)+" mm"}]},cornerstoneOverlayBottomRight:{id:"cornerstoneOverlayBottomRight",items:[{id:"ZoomLevel",customizationType:"ohif.overlayItem.zoomLevel",color:"#fff"},{id:"WindowLevel",customizationType:"ohif.overlayItem.windowLevel",color:"#fff"}]}},showStudyList:!1,maxNumberOfWebWorkers:3,showWarningMessageForCrossOrigin:!0,showCPUFallbackMessage:!0,showLoadingIndicator:!0,strictZSpacingForVolumeViewport:!0,maxNumRequests:{interaction:100,thumbnail:75,prefetch:25},defaultDataSourceName:"dicomjson",investigationalUseDialog:{option:"configure",days:90},hangingProtocolModule:"@ohif/extension-default.hangingProtocolModule.default",hangingProtocols:[{id:"mpr2x2",locked:!0,hasUpdatedPriorsInformation:!1,name:"2x2 MPR",createdDate:"2024-01-01T00:00:00.000Z",modifiedDate:"2024-01-01T00:00:00.000Z",availableTo:{},editableBy:{},protocolMatchingRules:[{attribute:"numberOfDisplaySetsWithImages",constraint:{greaterThan:1}}],displaySetSelectors:{"mpr-display-set":{seriesMatchingRules:[{weight:1,attribute:"numImageFrames",constraint:{greaterThan:0}}]}},stages:[{id:"default",name:"default",viewportStructure:{layoutType:"grid",properties:{rows:2,columns:2}},viewports:[{viewportOptions:{viewportId:"mpr-axial",viewportType:"volume",orientation:"axial",toolGroupId:"mpr",initialImageOptions:{preset:"middle"}},displaySets:[{id:"mpr-display-set"}]},{viewportOptions:{viewportId:"mpr-sagittal",viewportType:"volume",orientation:"sagittal",toolGroupId:"mpr",initialImageOptions:{preset:"middle"}},displaySets:[{id:"mpr-display-set"}]},{viewportOptions:{viewportId:"mpr-coronal",viewportType:"volume",orientation:"coronal",toolGroupId:"mpr",initialImageOptions:{preset:"middle"}},displaySets:[{id:"mpr-display-set"}]},{viewportOptions:{viewportId:"mpr-3d",viewportType:"volume3d",orientation:"coronal",toolGroupId:"mpr",initialImageOptions:{preset:"middle"}},displaySets:[{id:"mpr-display-set"}]}],createdDate:"2024-01-01T00:00:00.000Z"}],numberOfPriorsReferenced:-1},{id:"default2x2",locked:!0,hasUpdatedPriorsInformation:!1,name:"Default 2x2",createdDate:"2024-01-01T00:00:00.000Z",modifiedDate:"2024-01-01T00:00:00.000Z",availableTo:{},editableBy:{},protocolMatchingRules:[],displaySetSelectors:{"default-display-set":{seriesMatchingRules:[{weight:1,attribute:"numImageFrames",constraint:{greaterThan:0}}]}},stages:[{id:"default",name:"default",viewportStructure:{layoutType:"grid",properties:{rows:2,columns:2}},viewports:[{viewportOptions:{viewportId:"viewport-1",viewportType:"stack",background:[0,0,0]},displaySets:[{id:"default-display-set",matchedDisplaySetsIndex:0}]},{viewportOptions:{viewportId:"viewport-2",viewportType:"stack",background:[0,0,0]},displaySets:[{id:"default-display-set",matchedDisplaySetsIndex:1}]},{viewportOptions:{viewportId:"viewport-3",viewportType:"stack",background:[0,0,0]},displaySets:[{id:"default-display-set",matchedDisplaySetsIndex:2}]},{viewportOptions:{viewportId:"viewport-4",viewportType:"stack",background:[0,0,0]},displaySets:[{id:"default-display-set",matchedDisplaySetsIndex:3}]}],createdDate:"2024-01-01T00:00:00.000Z"}],numberOfPriorsReferenced:-1}],dataSources:[{namespace:"@ohif/extension-default.dataSourcesModule.dicomjson",sourceName:"dicomjson",configuration:{friendlyName:"dicom json",name:"json"}}],httpErrorHandler:e=>{console.warn(e)},whiteLabeling:{createLogoComponentFn:function(e){return e.createElement("a",{target:"_blank",href:"https://acan.io"},e.createElement("div",{className:"h-8",style:{display:"flex",flexDirection:"row",alignItems:"center"}},e.createElement("img",{src:"./assets/acanio.svg",className:"w-10 h-10",style:{display:"inline-block"}}),e.createElement("span",{className:"ml-3 text-xl",style:{color:"#fff",marginRight:"250px"}},"Acan.io Viewer")))}},hotkeys:[{commandName:"incrementActiveViewport",label:"Next Viewport",keys:["right"]},{commandName:"decrementActiveViewport",label:"Previous Viewport",keys:["left"]},{commandName:"rotateViewportCW",label:"Rotate Right",keys:["r"]},{commandName:"rotateViewportCCW",label:"Rotate Left",keys:["l"]},{commandName:"invertViewport",label:"Invert",keys:["i"]},{commandName:"flipViewportHorizontal",label:"Flip Horizontally",keys:["h"]},{commandName:"flipViewportVertical",label:"Flip Vertically",keys:["v"]},{commandName:"scaleUpViewport",label:"Zoom In",keys:["+"]},{commandName:"scaleDownViewport",label:"Zoom Out",keys:["-"]},{commandName:"fitViewportToWindow",label:"Zoom to Fit",keys:["="]},{commandName:"resetViewport",label:"Reset",keys:["space"]},{commandName:"nextImage",label:"Next Image",keys:["down"]},{commandName:"previousImage",label:"Previous Image",keys:["up"]},{commandName:"setToolActive",commandOptions:{toolName:"Zoom"},label:"Zoom",keys:["z"]},{commandName:"windowLevelPreset1",label:"W/L Preset 1",keys:["1"]},{commandName:"windowLevelPreset2",label:"W/L Preset 2",keys:["2"]},{commandName:"windowLevelPreset3",label:"W/L Preset 3",keys:["3"]},{commandName:"windowLevelPreset4",label:"W/L Preset 4",keys:["4"]},{commandName:"windowLevelPreset5",label:"W/L Preset 5",keys:["5"]},{commandName:"windowLevelPreset6",label:"W/L Preset 6",keys:["6"]},{commandName:"windowLevelPreset7",label:"W/L Preset 7",keys:["7"]},{commandName:"windowLevelPreset8",label:"W/L Preset 8",keys:["8"]},{commandName:"windowLevelPreset9",label:"W/L Preset 9",keys:["9"]}]};

So, how to fix that problem and make “Change layout (tool-layout)” dropwon work in my DICOM VIEWER like that above OHIF Viewer screenshot ???

How to enable that feature so that when we clique on it it works ??? Because, at this time, it’s unable and does not show its dropdown and features.

REALLY NEED YOUR HELP.

Unfortunately, I know nothing about the NEXTCLOUD DICOM-VIEWER. So I really don’t know where to go from here. Furthermore considering that the drop down works in OHIF, it must be something that this other viewer has introduced. Perhaps consider just using OHIF? Sorry I couldn’t be more of a help.

Hello .

After installed “OHIF Viewer” in our Laravel Project, I can change layout out now, But after changed “2x2” “1x1x1”, … by example, only the first Image appear correctly with real dimensions. The rest shows but cannot display perfectly as you can see on the following screenshot:

As you can see in the attached screenshot, when I change the display layout in the Tools panel, the other images don’t display correctly. Only thin lines appear; only the first image displays correctly and is clearly visible.

I’m referring to images larger than 1 pixel.

It seems that the images in the other areas are quite thin and display in small strips.

HERE IS THE CODE OF IMPLEMENTATION IN OUR LARAVEL PHP PROJECT:

<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/>
    <meta name="theme-color" content="#000000"/>
    <title>{{ __('insurance::lang.dicom_viewer') }} - {{ $document->procedure->procedure_number ?? $document->procedure->id ?? 'Procedure' }} - {{ $document->procedure->patient->full_name ?? $document->dicom_patient_name ?? 'Patient' }}</title>
    <link href="{{ asset('modules/insurance/advanced-dicomviewer/app.bundle.css') }}" rel="stylesheet">

</head>
<body>
    <noscript>{{ __('insurance::lang.javascript_required') }}</noscript>
    
    <div id="root"></div>

    <!-- Configuration & Scripts -->
    <script>
        // Set Public URL for webpack chunks
        window.PUBLIC_URL = '{{ asset("modules/insurance/advanced-dicomviewer") }}/';
        
        // Routing Logic
        @if($role === 'policy_holder')
            var jsonRoute = "{{ route('insurance.policy-holder-portal.medical-imaging.dicom-json') }}";
        @else
            var jsonRoute = "{{ route('insurance.medical-imaging.document.dicom-json') }}";
        @endif
        
        const jsonApiUrl = jsonRoute + "?file={{ $document->id }}";

        // OHIF Configuration
        window.config = {
            routerBasename: window.location.pathname.replace(/\/viewer.*$/, ''),
            showStudyList: false, 
            extensions: [],
            modes: [],
            dataSources: [
                {
                    namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
                    sourceName: 'dicomjson',
                    configuration: {
                        friendlyName: 'Laravel DICOM JSON',
                        name: 'json',
                    },
                }
            ],
            defaultDataSourceName: 'dicomjson',
        };

        // URL Handling for DicomJSON
        // Use window.history to ensure the 'url' parameter is present for OHIF to read
        const currentUrl = new URL(window.location.href);
        if (!currentUrl.searchParams.has('url')) {
            currentUrl.searchParams.set('url', jsonApiUrl);
            window.history.replaceState({}, '', currentUrl);
        }

        // Use MutationObserver to handle dynamically loaded content
        let mutationTimeout;
        const observer = new MutationObserver(function(mutations) {
            clearTimeout(mutationTimeout);
            mutationTimeout = setTimeout(customizeDicomViewer, 50);
        });

        // Start observing when document is ready
        window.addEventListener('load', function() {
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
            
            // Force resize events to fix viewport layout issues
            setTimeout(() => window.dispatchEvent(new Event('resize')), 500);
            setTimeout(() => window.dispatchEvent(new Event('resize')), 2000);
            setTimeout(() => window.dispatchEvent(new Event('resize')), 4000);
        });
    </script>

    <!-- Bundle Scripts -->
    <script defer="defer" src="{{ asset('modules/insurance/advanced-dicomviewer/app.bundle.b431c7757a418c9d162d.js') }}"></script>
</body>
</html>

HOW TO FIX THIS PROBLEM, PLEASE, HELP US.

Hmmm… which layout/view did you choose to produce the screenshot that you included? To me it looks like 3D four up. Is that correct? If so you can try comparing what OHIF itself shows for the study in question here. Considering the acquisition series only has 4 images there is a very good chance that the screen shot is correct. Hope this helps!

Hello and thanks for your help.

After tried on OHIF VIEWER LOCALBASIC LINK that you gave me, I notice that it is the same problem as you can see on following screenshot:

But, I’m wondering why it is only the first image we can see correctly ??? Why and how to fix it ???

I believe there is nothing to fix. The DICOM you loaded ONLY has 4 images. The other two viewports (I suspect you are viewing mpr here?) are reconstructions of that other 4 image display set. So the viewport on the far left is that of the acquisition (i.e. the 4 axial images you uploaded). The middle is a sagittal reconstruction of the 4 images and the right is a coronal reconstruction. But there are only 4 images likely spaced very close together in space and thus that is what the reconstructions looks like. Does this make sense?

1 Like

Maybe this might help… OHIF Viewer

But in this case the original DICOM series has 128 images for the reconstructions!

Yes. Thank you very much

1 Like