Skip to content

Add DICOM data loader tutorial - #42

Draft
msadowski wants to merge 3 commits into
mainfrom
cursor/dicom-data-loader-tutorial-c6d4
Draft

msadowski wants to merge 3 commits into
mainfrom
cursor/dicom-data-loader-tutorial-c6d4

Conversation

@msadowski

@msadowski msadowski commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Adds foxglove_sdk/dicom_data_loader: a Foxglove data loader extension (Rust compiled to WASM) that opens folders of uncompressed DICOM .dcm files directly in Foxglove. It needs no MCAP conversion and no custom panel. It registers .dcm with supportsMultiFile: true, so a whole series is selected at once.

Navigation uses the Foxglove timeline, not a slice slider:

  • Sweep mode (single series): the LIDC-IDRI-0001 chest CT has 133 slices, each shown for 100 ms, from inferior to superior. Coronal and sagittal views carry a line tracking the current slice. The 3D panel shows the rib cage and lungs as point clouds, with the current slice moving through them.
  • 4D mode (series that share a frame of reference and geometry): 4D-Lung patient 100_HM10395, study S300, has 10 respiratory phases of 142 slices. Each phase plays for 400 ms, repeated for 3 breathing cycles. The coronal view and the lung cloud move with the diaphragm, and /dicom/stats.lung_volume_ml traces the breathing curve (about 4.0–4.8 L).
Chest CT (axial / coronal) 4D-Lung coronal, 0% vs 50% phase
lidc-axial.png lidc-coronal.png 4dlung-coronal-0.png 4dlung-coronal-50.png

These images are decoded from the loader's RawImage output when the built .wasm runs outside Foxglove.

How it works

  • Two-pass loading. A header pass reads each file up to Pixel Data, groups slices by series, and picks sweep or 4D mode. A pixel pass then loads one series at a time, encodes its messages, and frees the voxels. Peak WASM memory is about 130 MB for the chest CT and about 95 MB for the 750 MB 4D study.
  • Precomputed timeline. Encoded messages are stored in a timeline; repeated breathing cycles share the same bytes. create_iter is a partition_point plus a channel filter. get_backfill returns the latest message per channel.
  • Topics. Axial, coronal, and sagittal RawImages (lung window, with coronal and sagittal resampled to square pixels); ImageAnnotations; bone, lung, and slice PointClouds; a SceneUpdate bounding box; FrameTransforms; custom stats; and a metadata message with no patient identifiers.
  • Supporting files. A sample-data download script (NCI Imaging Data Commons, CC BY 3.0, with attribution in the README), a layout, and an optional smoke test (wasm-tools + jco) that runs the built loader in Node.

Verification

  • cargo fmt --check, cargo clippy --target wasm32-unknown-unknown --all-targets -D warnings, release WASM build
  • cargo test --release: runs against both sample datasets; the dataset tests skip when the data is absent
  • node scripts/wasm_smoke.mjs: both datasets, with ordered log times, per-channel counts, backfill, and preview images
  • npm run lint:ci, npm run package (writes the .foxe), and .utils/generate_readme.py (root README regenerated)

I have not tested it inside the Foxglove app itself, because that needs a signed-in Foxglove session.

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

cursoragent and others added 3 commits September 26, 2026 11:00
Co-authored-by: Mateusz Sadowski <msadowski@users.noreply.github.com>
…ader

- Two-pass loading (headers, then one series of pixels at a time) keeps peak
  WASM memory ~130 MB for the chest CT and ~95 MB for the 750 MB 4D study
- Precomputed timeline of encoded messages drives create_iter and backfill
- 4D-Lung study S300 (142 slices/phase) keeps the diaphragm in view
- Tests decode with prost; tests and smoke script read data/chest and data/breathing
- Smoke script implements the full WIT reader resource

Co-authored-by: Mateusz Sadowski <msadowski@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants