@cornerstonejs/adapters 1.58.1 → 1.58.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48430,6 +48430,262 @@ let state = {
48430
48430
  handleRadius: 6
48431
48431
  };
48432
48432
 
48433
+ const defaultContourConfig$1 = {
48434
+ renderOutline: true,
48435
+ outlineWidthAutoGenerated: 3,
48436
+ outlineWidthActive: 2,
48437
+ outlineWidthInactive: 1,
48438
+ outlineOpacity: 1,
48439
+ outlineOpacityInactive: 0.85,
48440
+ outlineDashActive: undefined,
48441
+ outlineDashInactive: undefined,
48442
+ outlineDashAutoGenerated: '5,3',
48443
+ activeSegmentOutlineWidthDelta: 0,
48444
+ renderFill: true,
48445
+ fillAlpha: 0.5,
48446
+ fillAlphaInactive: 0.3,
48447
+ fillAlphaAutoGenerated: 0.3
48448
+ };
48449
+ function getDefaultContourConfig() {
48450
+ return defaultContourConfig$1;
48451
+ }
48452
+
48453
+ const defaultLabelmapConfig$1 = {
48454
+ renderOutline: true,
48455
+ outlineWidthActive: 3,
48456
+ outlineWidthInactive: 2,
48457
+ activeSegmentOutlineWidthDelta: 0,
48458
+ renderFill: true,
48459
+ renderFillInactive: true,
48460
+ fillAlpha: 0.7,
48461
+ fillAlphaInactive: 0.65,
48462
+ outlineOpacity: 1,
48463
+ outlineOpacityInactive: 0.85
48464
+ };
48465
+ function getDefaultLabelmapConfig() {
48466
+ return defaultLabelmapConfig$1;
48467
+ }
48468
+
48469
+ const defaultSurfaceConfig$1 = {
48470
+ renderFill: true,
48471
+ fillAlpha: 1
48472
+ };
48473
+ function getDefaultSurfaceConfig() {
48474
+ return defaultSurfaceConfig$1;
48475
+ }
48476
+
48477
+ const defaultLabelmapConfig = getDefaultLabelmapConfig();
48478
+ const defaultContourConfig = getDefaultContourConfig();
48479
+ const defaultSurfaceConfig = getDefaultSurfaceConfig();
48480
+ const newGlobalConfig = {
48481
+ renderInactiveSegmentations: true,
48482
+ representations: {
48483
+ [Representations.Labelmap]: defaultLabelmapConfig,
48484
+ [Representations.Contour]: defaultContourConfig,
48485
+ [Representations.Surface]: defaultSurfaceConfig
48486
+ }
48487
+ };
48488
+ const initialDefaultState = {
48489
+ colorLUT: [],
48490
+ segmentations: [],
48491
+ globalConfig: newGlobalConfig,
48492
+ toolGroups: {}
48493
+ };
48494
+ class SegmentationStateManager {
48495
+ constructor(uid) {
48496
+ if (!uid) {
48497
+ uid = uuidv4$1();
48498
+ }
48499
+ this.state = cloneDeep(initialDefaultState);
48500
+ this.uid = uid;
48501
+ }
48502
+ getState() {
48503
+ return this.state;
48504
+ }
48505
+ getToolGroups() {
48506
+ return Object.keys(this.state.toolGroups);
48507
+ }
48508
+ getColorLUT(lutIndex) {
48509
+ return this.state.colorLUT[lutIndex];
48510
+ }
48511
+ getNextColorLUTIndex() {
48512
+ return this.state.colorLUT.length;
48513
+ }
48514
+ resetState() {
48515
+ this.state = cloneDeep(initialDefaultState);
48516
+ }
48517
+ getSegmentation(segmentationId) {
48518
+ return this.state.segmentations.find(segmentation => segmentation.segmentationId === segmentationId);
48519
+ }
48520
+ addSegmentation(segmentation) {
48521
+ if (this.getSegmentation(segmentation.segmentationId)) {
48522
+ throw new Error(`Segmentation with id ${segmentation.segmentationId} already exists`);
48523
+ }
48524
+ this.state.segmentations.push(segmentation);
48525
+ }
48526
+ getSegmentationRepresentations(toolGroupId) {
48527
+ const toolGroupSegRepresentationsWithConfig = this.state.toolGroups[toolGroupId];
48528
+ if (!toolGroupSegRepresentationsWithConfig) {
48529
+ return;
48530
+ }
48531
+ return toolGroupSegRepresentationsWithConfig.segmentationRepresentations;
48532
+ }
48533
+ getAllSegmentationRepresentations() {
48534
+ const toolGroupSegReps = {};
48535
+ Object.entries(this.state.toolGroups).forEach(([toolGroupId, toolGroupSegRepresentationsWithConfig]) => {
48536
+ toolGroupSegReps[toolGroupId] = toolGroupSegRepresentationsWithConfig.segmentationRepresentations;
48537
+ });
48538
+ return toolGroupSegReps;
48539
+ }
48540
+ addSegmentationRepresentation(toolGroupId, segmentationRepresentation) {
48541
+ if (!this.state.toolGroups[toolGroupId]) {
48542
+ this.state.toolGroups[toolGroupId] = {
48543
+ segmentationRepresentations: [],
48544
+ config: {}
48545
+ };
48546
+ }
48547
+ this.state.toolGroups[toolGroupId].segmentationRepresentations.push(segmentationRepresentation);
48548
+ this._handleActiveSegmentation(toolGroupId, segmentationRepresentation);
48549
+ }
48550
+ getGlobalConfig() {
48551
+ return this.state.globalConfig;
48552
+ }
48553
+ setGlobalConfig(config) {
48554
+ this.state.globalConfig = config;
48555
+ }
48556
+ getSegmentationRepresentationByUID(toolGroupId, segmentationRepresentationUID) {
48557
+ const toolGroupSegRepresentations = this.getSegmentationRepresentations(toolGroupId);
48558
+ const segmentationData = toolGroupSegRepresentations?.find(representation => representation.segmentationRepresentationUID === segmentationRepresentationUID);
48559
+ return segmentationData;
48560
+ }
48561
+ removeSegmentation(segmentationId) {
48562
+ this.state.segmentations = this.state.segmentations.filter(segmentation => segmentation.segmentationId !== segmentationId);
48563
+ }
48564
+ removeSegmentationRepresentation(toolGroupId, segmentationRepresentationUID) {
48565
+ const toolGroupSegmentationRepresentations = this.getSegmentationRepresentations(toolGroupId);
48566
+ if (!toolGroupSegmentationRepresentations || !toolGroupSegmentationRepresentations.length) {
48567
+ throw new Error(`No viewport specific segmentation state found for viewport ${toolGroupId}`);
48568
+ }
48569
+ const state = toolGroupSegmentationRepresentations;
48570
+ const index = state.findIndex(segData => segData.segmentationRepresentationUID === segmentationRepresentationUID);
48571
+ if (index === -1) {
48572
+ console.warn(`No viewport specific segmentation state data found for viewport ${toolGroupId} and segmentation data UID ${segmentationRepresentationUID}`);
48573
+ }
48574
+ const removedSegmentationRepresentation = toolGroupSegmentationRepresentations[index];
48575
+ toolGroupSegmentationRepresentations.splice(index, 1);
48576
+ this._handleActiveSegmentation(toolGroupId, removedSegmentationRepresentation);
48577
+ }
48578
+ setActiveSegmentationRepresentation(toolGroupId, segmentationRepresentationUID) {
48579
+ const toolGroupSegmentations = this.getSegmentationRepresentations(toolGroupId);
48580
+ if (!toolGroupSegmentations || !toolGroupSegmentations.length) {
48581
+ throw new Error(`No segmentation data found for toolGroupId: ${toolGroupId}`);
48582
+ }
48583
+ const segmentationData = toolGroupSegmentations.find(segmentationData => segmentationData.segmentationRepresentationUID === segmentationRepresentationUID);
48584
+ if (!segmentationData) {
48585
+ throw new Error(`No segmentation data found for segmentation data UID ${segmentationRepresentationUID}`);
48586
+ }
48587
+ segmentationData.active = true;
48588
+ this._handleActiveSegmentation(toolGroupId, segmentationData);
48589
+ }
48590
+ getToolGroupSpecificConfig(toolGroupId) {
48591
+ const toolGroupStateWithConfig = this.state.toolGroups[toolGroupId];
48592
+ if (!toolGroupStateWithConfig) {
48593
+ return;
48594
+ }
48595
+ return toolGroupStateWithConfig.config;
48596
+ }
48597
+ getSegmentationRepresentationSpecificConfig(toolGroupId, segmentationRepresentationUID) {
48598
+ const segmentationRepresentation = this.getSegmentationRepresentationByUID(toolGroupId, segmentationRepresentationUID);
48599
+ if (!segmentationRepresentation) {
48600
+ return;
48601
+ }
48602
+ return segmentationRepresentation.segmentationRepresentationSpecificConfig;
48603
+ }
48604
+ setSegmentationRepresentationSpecificConfig(toolGroupId, segmentationRepresentationUID, config) {
48605
+ const segmentationRepresentation = this.getSegmentationRepresentationByUID(toolGroupId, segmentationRepresentationUID);
48606
+ if (!segmentationRepresentation) {
48607
+ return;
48608
+ }
48609
+ segmentationRepresentation.segmentationRepresentationSpecificConfig = config;
48610
+ }
48611
+ getSegmentSpecificConfig(toolGroupId, segmentationRepresentationUID, segmentIndex) {
48612
+ const segmentationRepresentation = this.getSegmentationRepresentationByUID(toolGroupId, segmentationRepresentationUID);
48613
+ if (!segmentationRepresentation) {
48614
+ return;
48615
+ }
48616
+ return segmentationRepresentation.segmentSpecificConfig[segmentIndex];
48617
+ }
48618
+ setSegmentSpecificConfig(toolGroupId, segmentationRepresentationUID, config, options) {
48619
+ const segmentationRepresentation = this.getSegmentationRepresentationByUID(toolGroupId, segmentationRepresentationUID);
48620
+ if (!segmentationRepresentation) {
48621
+ return;
48622
+ }
48623
+ if (!segmentationRepresentation.segmentSpecificConfig || options?.clear) {
48624
+ segmentationRepresentation.segmentSpecificConfig = {};
48625
+ }
48626
+ Object.keys(config).forEach(key => {
48627
+ segmentationRepresentation.segmentSpecificConfig[key] = config[key];
48628
+ });
48629
+ }
48630
+ setSegmentationRepresentationConfig(toolGroupId, config) {
48631
+ let toolGroupStateWithConfig = this.state.toolGroups[toolGroupId];
48632
+ if (!toolGroupStateWithConfig) {
48633
+ this.state.toolGroups[toolGroupId] = {
48634
+ segmentationRepresentations: [],
48635
+ config: {
48636
+ renderInactiveSegmentations: true,
48637
+ representations: {}
48638
+ }
48639
+ };
48640
+ toolGroupStateWithConfig = this.state.toolGroups[toolGroupId];
48641
+ }
48642
+ toolGroupStateWithConfig.config = {
48643
+ ...toolGroupStateWithConfig.config,
48644
+ ...config
48645
+ };
48646
+ }
48647
+ addColorLUT(colorLUT, lutIndex) {
48648
+ if (this.state.colorLUT[lutIndex]) {
48649
+ console.warn('Color LUT table already exists, overwriting');
48650
+ }
48651
+ this.state.colorLUT[lutIndex] = structuredClone(colorLUT);
48652
+ }
48653
+ removeColorLUT(colorLUTIndex) {
48654
+ delete this.state.colorLUT[colorLUTIndex];
48655
+ }
48656
+ _handleActiveSegmentation(toolGroupId, recentlyAddedOrRemovedSegmentationRepresentation) {
48657
+ const segmentationRepresentations = this.getSegmentationRepresentations(toolGroupId);
48658
+ if (segmentationRepresentations.length === 0) {
48659
+ return;
48660
+ }
48661
+ if (segmentationRepresentations.length === 1) {
48662
+ segmentationRepresentations[0].active = true;
48663
+ return;
48664
+ }
48665
+ const activeSegmentationRepresentations = segmentationRepresentations.filter(representation => representation.active);
48666
+ if (activeSegmentationRepresentations.length === 0) {
48667
+ segmentationRepresentations[0].active = true;
48668
+ return;
48669
+ }
48670
+ if (recentlyAddedOrRemovedSegmentationRepresentation.active) {
48671
+ segmentationRepresentations.forEach(representation => {
48672
+ if (representation.segmentationRepresentationUID !== recentlyAddedOrRemovedSegmentationRepresentation.segmentationRepresentationUID) {
48673
+ representation.active = false;
48674
+ }
48675
+ });
48676
+ }
48677
+ }
48678
+ }
48679
+ const defaultSegmentationStateManager = new SegmentationStateManager('DEFAULT');
48680
+
48681
+ function getDefaultSegmentationStateManager() {
48682
+ return defaultSegmentationStateManager;
48683
+ }
48684
+ function getSegmentation(segmentationId) {
48685
+ const segmentationStateManager = getDefaultSegmentationStateManager();
48686
+ return segmentationStateManager.getSegmentation(segmentationId);
48687
+ }
48688
+
48433
48689
  const {
48434
48690
  isEqual: isEqual$1
48435
48691
  } = utilities;
@@ -49021,11 +49277,6 @@ function generateContourSetsFromLabelmap$2({
49021
49277
  return;
49022
49278
  }
49023
49279
  const numSlices = vol.dimensions[2];
49024
- const imageVol = cache$1.getVolume(vol.referencedVolumeId);
49025
- if (!imageVol) {
49026
- console.warn(`No volume found for ${vol.referencedVolumeId}`);
49027
- return;
49028
- }
49029
49280
  const segData = vol.imageData.getPointData().getScalars().getData();
49030
49281
  const pixelsPerSlice = vol.dimensions[0] * vol.dimensions[1];
49031
49282
  for (let z = 0; z < numSlices; z++) {
@@ -49038,7 +49289,7 @@ function generateContourSetsFromLabelmap$2({
49038
49289
  const ContourSets = [];
49039
49290
  const {
49040
49291
  FrameOfReferenceUID
49041
- } = imageVol.metadata;
49292
+ } = vol.metadata;
49042
49293
  const numSegments = segments.length;
49043
49294
  for (let segIndex = 0; segIndex < numSegments; segIndex++) {
49044
49295
  const segment = segments[segIndex];
@@ -49084,7 +49335,6 @@ function generateContourSetsFromLabelmap$2({
49084
49335
  if (reducedSet.points?.length) {
49085
49336
  const contours = findContoursFromReducedSet(reducedSet.lines);
49086
49337
  sliceContours.push({
49087
- referencedImageId: imageVol.imageIds[sliceIndex],
49088
49338
  contours,
49089
49339
  polyData: reducedSet,
49090
49340
  FrameNumber: sliceIndex + 1,
@@ -49098,7 +49348,6 @@ function generateContourSetsFromLabelmap$2({
49098
49348
  }
49099
49349
  }
49100
49350
  const metadata = {
49101
- referencedImageId: imageVol.imageIds[0],
49102
49351
  FrameOfReferenceUID
49103
49352
  };
49104
49353
  const ContourSet = {
@@ -49370,6 +49619,7 @@ function updateContourPolyline(annotation, polylineData, transforms, options) {
49370
49619
  invalidateAnnotation(annotation);
49371
49620
  }
49372
49621
 
49622
+ const DEFAULT_CONTOUR_SEG_TOOLNAME = 'PlanarFreehandContourSegmentationTool';
49373
49623
  function getInterpolationData(viewportData, filterParams = []) {
49374
49624
  const {
49375
49625
  viewport,
@@ -49377,8 +49627,24 @@ function getInterpolationData(viewportData, filterParams = []) {
49377
49627
  annotation
49378
49628
  } = viewportData;
49379
49629
  const interpolationDatas = new Map();
49380
- const annotations = getAnnotations(annotation.metadata.toolName, viewport.element);
49381
- if (!annotations) {
49630
+ const {
49631
+ toolName,
49632
+ originalToolName
49633
+ } = annotation.metadata;
49634
+ const testToolName = originalToolName || toolName;
49635
+ const annotations = getAnnotations(testToolName, viewport.element) || [];
49636
+ const modifiedAnnotations = getAnnotations(DEFAULT_CONTOUR_SEG_TOOLNAME, viewport.element);
49637
+ if (modifiedAnnotations?.length) {
49638
+ modifiedAnnotations.forEach(annotation => {
49639
+ const {
49640
+ metadata
49641
+ } = annotation;
49642
+ if (metadata.originalToolName === testToolName && !annotations.find(it => it === annotation)) {
49643
+ annotations.push(annotation);
49644
+ }
49645
+ });
49646
+ }
49647
+ if (!annotations?.length) {
49382
49648
  return interpolationDatas;
49383
49649
  }
49384
49650
  for (let i = 0; i < sliceData.numberOfSlices; i++) {
@@ -49557,7 +49823,7 @@ function _getBoundingPair(sliceIndex, sliceRange, interpolationData) {
49557
49823
  const {
49558
49824
  PointsManager: PointsManager$1
49559
49825
  } = utilities;
49560
- function selectHandles(polyline, handleCount = 8) {
49826
+ function selectHandles(polyline, handleCount = 12) {
49561
49827
  const handles = PointsManager$1.create3(handleCount);
49562
49828
  handles.sources = [];
49563
49829
  const {
@@ -49569,10 +49835,9 @@ function selectHandles(polyline, handleCount = 8) {
49569
49835
  } = polyline;
49570
49836
  const distance = 6;
49571
49837
  if (length < distance * 3) {
49572
- console.log('Adding subselect handles', handleCount, length);
49573
49838
  return polyline.subselect(handleCount);
49574
49839
  }
49575
- const interval = Math.min(30, Math.floor(length / 3));
49840
+ const interval = Math.floor(Math.max(2 * length / handleCount, distance * 5));
49576
49841
  sourcePoints.forEach(() => destPoints.push(PointsManager$1.create3(handleCount)));
49577
49842
  const dotValues = createDotValues(polyline, distance);
49578
49843
  const minimumRegions = findMinimumRegions(dotValues, handleCount);
@@ -49731,12 +49996,10 @@ const {
49731
49996
  PointsManager
49732
49997
  } = utilities;
49733
49998
  const dP = 0.2;
49734
- let interpolating = false;
49735
49999
  function interpolate(viewportData) {
49736
- if (interpolating || !viewportData.annotation) {
50000
+ if (!viewportData.annotation) {
49737
50001
  return;
49738
50002
  }
49739
- interpolating = true;
49740
50003
  const {
49741
50004
  isInterpolationUpdate,
49742
50005
  annotation
@@ -49749,7 +50012,6 @@ function interpolate(viewportData) {
49749
50012
  }
49750
50013
  startInterpolation(viewportData);
49751
50014
  } finally {
49752
- interpolating = false;
49753
50015
  if (isInterpolationUpdate) {
49754
50016
  annotation.autoGenerated = true;
49755
50017
  }
@@ -50117,6 +50379,31 @@ function deleteRelatedAnnotations(viewportData) {
50117
50379
  }
50118
50380
  }
50119
50381
 
50382
+ function addContourSegmentationAnnotation(annotation) {
50383
+ if (!annotation.data.segmentation) {
50384
+ throw new Error('addContourSegmentationAnnotation: annotation does not have a segmentation data');
50385
+ }
50386
+ const {
50387
+ segmentationId,
50388
+ segmentIndex
50389
+ } = annotation.data.segmentation;
50390
+ const segmentation = getSegmentation(segmentationId);
50391
+ if (!segmentation.representationData.CONTOUR) {
50392
+ segmentation.representationData.CONTOUR = {
50393
+ annotationUIDsMap: new Map()
50394
+ };
50395
+ }
50396
+ const {
50397
+ annotationUIDsMap
50398
+ } = segmentation.representationData.CONTOUR;
50399
+ let annotationsUIDsSet = annotationUIDsMap.get(segmentIndex);
50400
+ if (!annotationsUIDsSet) {
50401
+ annotationsUIDsSet = new Set();
50402
+ annotationUIDsMap.set(segmentIndex, annotationsUIDsSet);
50403
+ }
50404
+ annotationUIDsMap.set(segmentIndex, annotationsUIDsSet.add(annotation.annotationUID));
50405
+ }
50406
+
50120
50407
  const {
50121
50408
  uuidv4
50122
50409
  } = utilities;
@@ -50144,10 +50431,14 @@ class InterpolationManager {
50144
50431
  }
50145
50432
  for (const annotation of annotations) {
50146
50433
  const {
50434
+ interpolationUID,
50147
50435
  data,
50148
50436
  autoGenerated,
50149
50437
  metadata
50150
50438
  } = annotation;
50439
+ if (interpolationUID) {
50440
+ annotation.interpolationCompleted = true;
50441
+ }
50151
50442
  if (!autoGenerated) {
50152
50443
  continue;
50153
50444
  }
@@ -50160,6 +50451,7 @@ class InterpolationManager {
50160
50451
  if (segmentationId && segmentationId !== data.segmentation.segmentationId) {
50161
50452
  continue;
50162
50453
  }
50454
+ addContourSegmentationAnnotation(annotation);
50163
50455
  annotation.autoGenerated = false;
50164
50456
  }
50165
50457
  }
@@ -50171,11 +50463,13 @@ class InterpolationManager {
50171
50463
  return;
50172
50464
  }
50173
50465
  const {
50174
- toolName
50466
+ toolName,
50467
+ originalToolName
50175
50468
  } = annotation.metadata;
50176
- if (!this.toolNames.includes(toolName)) {
50469
+ if (!this.toolNames.includes(toolName) && !this.toolNames.includes(originalToolName)) {
50177
50470
  return;
50178
50471
  }
50472
+ console.log('Interpolation annotation', annotation.annotationUID);
50179
50473
  const viewport = getViewportForAnnotation(annotation);
50180
50474
  if (!viewport) {
50181
50475
  console.warn('Unable to find viewport for', annotation);
@@ -50209,11 +50503,21 @@ class InterpolationManager {
50209
50503
  parentKey: annotation => annotation.metadata
50210
50504
  }];
50211
50505
  let interpolationAnnotations = getInterpolationDataCollection(viewportData, filterData);
50212
- interpolationAnnotations = interpolationAnnotations.filter(interpolationAnnotation => interpolationAnnotation.interpolationUID);
50213
- if (!annotation.interpolationUID) {
50214
- annotation.interpolationUID = interpolationAnnotations[0]?.interpolationUID || uuidv4();
50215
- viewportData.interpolationUID = annotation.interpolationUID;
50216
- }
50506
+ const {
50507
+ sliceIndex
50508
+ } = annotation.metadata;
50509
+ const skipUIDs = new Set();
50510
+ interpolationAnnotations.forEach(interpolationAnnotation => {
50511
+ if (interpolationAnnotation.interpolationCompleted || interpolationAnnotation.metadata.sliceIndex === sliceIndex) {
50512
+ const {
50513
+ interpolationUID
50514
+ } = interpolationAnnotation;
50515
+ skipUIDs.add(interpolationUID);
50516
+ }
50517
+ });
50518
+ interpolationAnnotations = interpolationAnnotations.filter(interpolationAnnotation => !skipUIDs.has(interpolationAnnotation.interpolationUID));
50519
+ annotation.interpolationUID = interpolationAnnotations[0]?.interpolationUID || uuidv4();
50520
+ viewportData.interpolationUID = annotation.interpolationUID;
50217
50521
  interpolate(viewportData);
50218
50522
  };
50219
50523
  }
@@ -50227,9 +50531,10 @@ class InterpolationManager {
50227
50531
  return;
50228
50532
  }
50229
50533
  const {
50230
- toolName
50534
+ toolName,
50535
+ originalToolName
50231
50536
  } = annotation.metadata;
50232
- if (!this.toolNames.includes(toolName) || !ChangeTypesForInterpolation.includes(changeType)) {
50537
+ if (!this.toolNames.includes(toolName) && !this.toolNames.includes(originalToolName) || !ChangeTypesForInterpolation.includes(changeType)) {
50233
50538
  return;
50234
50539
  }
50235
50540
  const viewport = getViewportForAnnotation(annotation);
@@ -50237,7 +50542,10 @@ class InterpolationManager {
50237
50542
  console.warn('Unable to find matching viewport for annotation interpolation', annotation);
50238
50543
  return;
50239
50544
  }
50240
- annotation.autoGenerated = false;
50545
+ if (annotation.autoGenerated) {
50546
+ addContourSegmentationAnnotation(annotation);
50547
+ annotation.autoGenerated = false;
50548
+ }
50241
50549
  const sliceData = getSliceData(viewport);
50242
50550
  const viewportData = {
50243
50551
  viewport,