DICOM Integration
DICOMweb plugin for xOpat
| ID | dicom |
| Version | 1.0.0 |
| Author | Aiosa |
| Source | plugins/dicom |
Required configuration
serviceUrl
Additional configuration keys
serviceUrl, defaultStudy
See include.json for details and defaults.
Documentation
xOpat DICOM Plugin (WSI via DICOMweb)
This plugin enables xOpat to load Whole Slide Images (WSI) from any DICOMweb server
(e.g. Google Cloud Healthcare, Orthanc, dcm4chee). You need to run a build task
for the plugin to work - it uses package.json. See the workspace item readme for details.
Features
- Detects WSI pyramid levels automatically
- Renders tiles from multi-frame DICOM
- Supports raw or rendered tiles (
/frames/{n}vs/frames/{n}/rendered) - Integrates with slide browser: patients → studies → series → slides
- Handles auth tokens automatically
- Per-slide frame order overrides for correct tile alignment
- Optional annotation import/export (DICOM SR)
Basic Configuration
{
"dicom": {
"serviceUrl": "https://your-server/dicomWeb"
}
}
Opening Slides Automatically
Open one specific slide
{
"dicom": {
"serviceUrl": "...",
"studyUID": "1.2.3...",
"seriesUID": "4.5.6..."
}
}
Browse a whole study
{
"dicom": {
"serviceUrl": "...",
"studyUID": "1.2.3..."
}
}
Browse by patient
{
"dicom": {
"serviceUrl": "...",
"patientUID": "PAT123"
}
}
Tile Rendering Options
Rendered vs Raw tiles
{
"useRendered": true
}
Rendered tiles (/rendered) are recommended for cloud servers
(Google / Orthanc JPEG rendering is fast and lighter).
Fixing Misaligned / Scrambled Tiles
The plugin picks a tile-ordering strategy per pyramid level using the following priority (first one that fully and uniquely covers the grid wins):
pixel-pos—ColumnPositionInTotalImagePixelMatrix/RowPositionInTotalImagePixelMatrixfromPerFrameFunctionalGroupsSequence(ground truth, unambiguous).div-dis—DimensionIndexValuesinterpreted viaDimensionIndexSequence/DimensionIndexPointerfrom the Shared Functional Groups.div-heuristic-xy/div-heuristic-yx— legacy DIV-axis guess. Accepted only when one axis assignment fully maps the grid and the other does not. Ambiguous cases (both fully map) are rejected and reported.sequential-…— last resort. Used whenDimensionOrganizationTypeisTILED_FULL(or unknown) andNumberOfFrames === tilesX*tilesY. ATILED_SPARSEfile with no usable per-frame positions is flagged as malformed and tiles fail-fast.
When some levels in the same series resolve via per-frame data (1–3) and other levels fall through to sequential, the plugin auto-infers the canonical sequential layout from the truth maps and applies it to the sequential levels. It scores the eight supported sequential patterns (row/col-major × plain/serpentine × flipY off/on) against every truth level and accepts only when one pattern explains ≥99% of cells on every truth level. The inferred name is printed:
[DICOM] inferred sequential layout=row-major-serpentine (min truth-level match=100.0%, truth dims=[7780×4178, 1945×1044]); applied to 2 level(s)
Explicit frameOrderByInstance / frameOrderBySeries / frameOrder
options always win over the inference pass — if you've pinned a layout in
config, it is respected even if inference would have chosen differently.
Each level logs one console.info line at load time so you can confirm
which strategy was chosen:
[DICOM] level=0 dims=98304×65536 grid=192×128 frames=24576 strategy=pixel-pos coverage=100.0% collisions=0 oob=0 instance=…
If the chosen strategy is wrong (visible stripes / zig-zag artifacts), override the sequential layout per instance or per series.
Per-instance fix (recommended)
{
"dicom": {
"serviceUrl": "...",
"frameOrderByInstance": {
"INSTANCE_UID_HERE": "row-major-flipY"
}
}
}
Per-series fix
{
"dicom": {
"serviceUrl": "...",
"frameOrderBySeries": {
"SERIES_UID_HERE": "row-major-serpentine"
}
}
}
Available values (sequential fallback only)
These override the sequential strategy only — they do not override explicit per-frame positions or DIV mapping (those are authoritative).
row-majorrow-major-flipYrow-major-serpentinerow-major-serpentine-flipYcol-majorcol-major-serpentinecol-major-flipY
Slide Browser Integration
The plugin adds a DICOM hierarchy:
- If
/patientsis supported → Patient → Study → Series → Slides - Otherwise → Study → Series → Slides
Each WSI-capable series becomes a slide in Slide Switcher.
Annotations (optional)
If the xOpat annotations module is present and configured:
"io": {
"bindings": {
"annotations": {
"bundle-export": ["dicom-sr-annotations"],
"bundle-import": ["dicom-sr-annotations"]
}
}
}
- Load: Latest SR referencing the slide is loaded automatically
- Save: Annotations are converted to DICOM SR and uploaded via STOW-RS
Troubleshooting
- Tiles misaligned → check the
[DICOM] level=… strategy=…log line; if strategy isdiv-heuristic-*, the file lacks unambiguous metadata — setframeOrderByInstanceorframeOrderBySeries - High-res only broken → before this hardening,
div-heuristic-xysilently won when both axis assignments fully mapped the grid; now this case is rejected and logged. If you still see misalignment, capture the log line and the affected instance's DIV/DIS metadata and file an issue - White tiles → missing frames; check server logs/network tab
- 401 errors → user token expired; log in again
- Slow loading → enable
"useRendered": true
Summary
The DICOM plugin gives xOpat full DICOMweb WSI support with:
- automatic pyramid detection
- tile rendering
- slide browser integration
- annotation support
- fine-grained frame ordering fixes for vendor quirks
Perfect for Google Cloud DICOM, Orthanc, and other DICOMweb servers.