feat(ecg): add DICOM ECG waveform extension (#5856)

* feat(ecg): add DICOM ECG waveform extension

Introduce @ohif/extension-dicom-ecg for rendering DICOM waveform (ECG)
data. Register the extension in the basic mode and pluginConfig.json,
and remove ECG from NON_IMAGE_MODALITIES so waveform display sets are
handled by the new viewport.

* refactor(ecg): move ECG support into cornerstone extension per review feedback

- Remove standalone dicom-ecg extension; fold all ECG functionality into
  the cornerstone extension as requested by reviewer
- Add ECG SOP class handler (DicomEcgSopClassHandler) to the cornerstone
  extension getSopClassHandlerModule, registering ECG waveform metadata
  via genericMetadataProvider on display set creation
- Move ECG helpers (buildEcgModule, decodeInt16Multiplex, base64ToArrayBuffer)
  into extensions/cornerstone/src/utils/ecgMetadata.ts
- Handle ECGViewport in CornerstoneViewportService._setDisplaySets by
  detecting ECGViewport instanceof and calling setEcg(imageId) directly,
  so OHIFCornerstoneViewport can be used without a custom ECG viewport component
- Add ECG support to getCornerstoneViewportType utility
- Update basic mode to reference the cornerstone extension's ECG SOP handler
  and use the base cornerstone viewport for ECG display sets
- Migrate ecgMetadata and getCornerstoneViewportType tests

* chore: revert bun.lock to upstream origin/master

---------

Co-authored-by: Bill Wallace <wayfarer3130@gmail.com>
This commit is contained in:
TFRadicalImagingandBill Wallace authored and GitHub committed 2026-03-05 12:56:52 -05:00
1 parent 30bb5d0652
commit 70f76aeba1
8 files changed
+466 -5

No files matched your search

+7 -1
View File
@@ -15,7 +15,7 @@ const { structuredCloneWithFunctions } = utils;
* This list used to include SM, for whole slide imaging, but this is now supported
* by cornerstone. Others of these may get added.
*/
export const NON_IMAGE_MODALITIES = ['ECG', 'SEG', 'RTSTRUCT', 'RTPLAN', 'PR', 'SR'];
export const NON_IMAGE_MODALITIES = ['SEG', 'RTSTRUCT', 'RTPLAN', 'PR', 'SR'];
export const ohif = {
layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout',
@@ -47,6 +47,10 @@ export const dicomvideo = {
viewport: '@ohif/extension-dicom-video.viewportModule.dicom-video',
};
export const dicomecg = {
sopClassHandler: '@ohif/extension-cornerstone.sopClassHandlerModule.DicomEcgSopClassHandler',
};
export const dicompdf = {
sopClassHandler: '@ohif/extension-dicom-pdf.sopClassHandlerModule.dicom-pdf',
viewport: '@ohif/extension-dicom-pdf.viewportModule.dicom-pdf',
@@ -86,6 +90,7 @@ export const extensionDependencies = {
export const sopClassHandlers = [
dicomvideo.sopClassHandler,
dicomecg.sopClassHandler,
dicomSeg.sopClassHandler,
dicomPmap.sopClassHandler,
ohif.sopClassHandler,
@@ -291,6 +296,7 @@ export const basicLayout = {
ohif.sopClassHandler,
dicomvideo.sopClassHandler,
ohif.wsiSopClassHandler,
dicomecg.sopClassHandler,
],
},
{