Skip to main content
Version: 3.10

Below we will review the changes to the API of the SegmentationService

SegmentationService API

Events

SEGMENTATION_UPDATED -> SEGMENTATION_MODIFIED

Just a rename to match the cornerstone terminology

VolumeId vs SegmentationId

Previously, we used the SegmentationId as the VolumeId for volume-based segmentations, which led to confusion and issues.

Now, we have two separate IDs: one for the segmentation and one for the volume.

segmentationService.getLabelmapVolume(segmentationId) will return the volume associated with the segmentation.

If your code uses cache.getVolume(segmentationId), update it to use the new getLabelmapVolume method.

getSegmentation(segmentationId)

remains the same it will return the segmentation object = cornerstone segmentation object with the following properties:

/**
* Global Segmentation Data which is used for the segmentation
*/
type Segmentation = {
/** segmentation id */
segmentationId: string;
/** segmentation label */
label: string;
segments: {
[segmentIndex: number]: Segment;
};
/**
* Representations of the segmentation. Each segmentation "can" be viewed
* in various representations. For instance, if a DICOM SEG is loaded, the main
* representation is the labelmap. However, for DICOM RT the main representation
* is contours, and other representations can be derived from the contour (currently
* only labelmap representation is supported)
*/
representationData: RepresentationsData;
/**
* Segmentation level stats, Note each segment can have its own stats
* This is used for caching stats for the segmentation level
*/
cachedStats: { [key: string]: unknown };
};

export type Segment = {
/** segment index */
segmentIndex: number;
/** segment label */
label: string;
/** is segment locked for editing */
locked: boolean;
/** cached stats for the segment, e.g., pt suv mean, max etc. */
cachedStats: { [key: string]: unknown };
/** is segment active for editing, at the same time only one segment can be active for editing */
active: boolean;
};
Compared to Cornerstone3D 1.x

Previously this function was returning this

export type Segmentation = {
segmentationId: string;
type: Enums.SegmentationRepresentations;
label: string;
activeSegmentIndex: number;
segmentsLocked: Set<number>;
cachedStats: { [key: string]: number };
segmentLabels: { [key: string]: string };
representationData: SegmentationRepresentationData;
};

As you can see segmentLabels, segmentsLocked, activeSegmentIndex, are all gathered under the new segments object. We now have support for per segment cachedStats as well.


getSegmentations

It provides all segmentations in the state. Previously, it accepted a filterNonhydrated flag, but since we've moved away from hydration and every loaded segmentation is now hydrated by default, it returns all segmentations.


getActiveSegmentation

After migrating to viewport-specific segmentations, different viewports can have distinct active segmentations for editing. The panel will always display the active segmentation when the active viewport changes.

Before (3.8)

// Returns full segmentation object
public getActiveSegmentation(): Segmentation {
const segmentations = this.getSegmentations();
return segmentations.find(segmentation => segmentation.isActive);
}

After (3.9)

public getActiveSegmentation(viewportId: string): Segmentation | null {
return cstSegmentation.activeSegmentation.getActiveSegmentation(viewportId);
}
Key Changes
  1. Viewport Specificity
    • Before: Global active segmentation across all tool groups
    • After: Active segmentation per viewport
  2. Required Parameters
    • Before: No parameters needed
    • After: Requires viewportId parameter
Migration Examples

Before:

// Get active segmentation
const activeSegmentation = segmentationService.getActiveSegmentation();
if (activeSegmentation) {
console.log('Active segmentation:', activeSegmentation.segmentationId);
console.log('Active segment:', activeSegmentation.activeSegmentIndex);
}

After:

// Get active segmentation for specific viewport
const activeSegmentation = segmentationService.getActiveSegmentation('viewport1');


getToolGroupIdsWithSegmentation

is now -> getViewportIdsWithSegmentation as you guessed

setActiveSegmentationForToolGroup

-> setActiveSegmentation

Before (OHIF 3.8)

setActiveSegmentationForToolGroup(
segmentationId: string,
toolGroupId?: string,
suppressEvents?: boolean
): void

After (OHIF 3.9)

setActiveSegmentation(
viewportId: string,
segmentationId: string
): void
Migration Examples
  1. Basic Usage Update

    // Before - OHIF 3.8
    segmentationService.setActiveSegmentationForToolGroup(
    segmentationId,
    toolGroupId
    );
    // After - OHIF 3.9
    segmentationService.setActiveSegmentation(
    viewportId,
    segmentationId
    );

addSegment

The addSegment method in OHIF 3.9 has been updated to handle segmentation properties in a viewport-centric way, removing tool group dependencies and simplifying the configuration structure.

Before (OHIF 3.8)

addSegment(
segmentationId: string,
config: {
segmentIndex?: number;
toolGroupId?: string;
properties?: {
label?: string;
color?: ohifTypes.RGB;
opacity?: number;
visibility?: boolean;
isLocked?: boolean;
active?: boolean;
};
}
): void

After (OHIF 3.9)

addSegment(
segmentationId: string,
config: {
segmentIndex?: number;
label?: string;
isLocked?: boolean;
active?: boolean;
color?: csTypes.Color;
visibility?: boolean;
}
): void
Key Changes
  1. Configuration Structure
    • Removed double nested properties object
    • Configuration options now at top level
    • Removed toolGroupId parameter
    • Removed opacity parameter (now part of color)
  2. Segment Index Generation
    • Changed from length-based to max-value-based indexing
    • More reliable for non-sequential segment indices
  3. Color Handling
    • Color now includes alpha channel (opacity)
    • Applied to all relevant viewports automatically
Migration Examples
  1. Basic Segment Creation

    // Before - OHIF 3.8
    segmentationService.addSegment(segmentationId, {
    properties: {
    label: 'Segment 1'
    }
    });
    // After - OHIF 3.9
    segmentationService.addSegment(segmentationId, {
    label: 'Segment 1'
    });
  2. Creating Segment with Color

    // Before - OHIF 3.8
    segmentationService.addSegment(segmentationId, {
    properties: {
    color: [255, 0, 0],
    opacity: 255
    }
    });
    // After - OHIF 3.9
    segmentationService.addSegment(segmentationId, {
    color: [255, 0, 0, 255] // RGB + Alpha
    });
  3. Setting Visibility and Lock Status

    // Before - OHIF 3.8
    segmentationService.addSegment(segmentationId, {
    toolGroupId: 'myToolGroup',
    properties: {
    visibility: true,
    isLocked: true
    }
    });
    // After - OHIF 3.9
    segmentationService.addSegment(segmentationId, {
    visibility: true,
    isLocked: true
    });
  4. Complete Configuration Example

    // Before - OHIF 3.8
    segmentationService.addSegment(segmentationId, {
    segmentIndex: 1,
    toolGroupId: 'myToolGroup',
    properties: {
    label: 'Tumor',
    color: [255, 0, 0],
    opacity: 200,
    visibility: true,
    isLocked: false,
    active: true
    }
    });
    // After - OHIF 3.9
    segmentationService.addSegment(segmentationId, {
    segmentIndex: 1,
    label: 'Tumor',
    color: [255, 0, 0, 200], // RGB + Alpha
    visibility: true,
    isLocked: false,
    active: true
    });
Important Changes
  1. Tool Group Removal

    // Before - OHIF 3.8
    segmentationService.addSegment(segmentationId, {
    toolGroupId: 'myToolGroup'
    // ... other properties
    });
    // After - OHIF 3.9
    // No tool group needed - automatically applies to all relevant viewports
    segmentationService.addSegment(segmentationId, {
    // ... properties
    });
  2. Segment Index Generation

    // Before - OHIF 3.8
    // Used array length
    segmentIndex = segmentation.segments.length === 0 ? 1 : segmentation.segments.length;
    // After - OHIF 3.9
    // Uses highest existing index + 1
    segmentIndex = Math.max(...Object.keys(csSegmentation.segments).map(Number)) + 1;
  3. Color and Opacity

    // Before - OHIF 3.8
    segmentationService.addSegment(segmentationId, {
    properties: {
    color: [255, 0, 0],
    opacity: 200
    }
    });

    // After - OHIF 3.9
    segmentationService.addSegment(segmentationId, {
    color: [255, 0, 0, 200] // Combined color and opacity
    });


getActiveSegment

now requires viewportId, since we have moved away from global active segmentation to viewport specific one

API Changes

// Before
getActiveSegment(): Segment

// After
getActiveSegment(viewportId: string): Segment | null