@@ -62,6 +62,7 @@ export default class MonaiLabelPanel extends Component {
6262 info : { models : [ ] , datasets : [ ] } ,
6363 action : { } ,
6464 options : { } ,
65+ segmentationSeriesUID : null , // Track which series the segmentation belongs to
6566 } ;
6667 }
6768
@@ -214,7 +215,7 @@ export default class MonaiLabelPanel extends Component {
214215
215216 // Wait for Above Segmentations to be added/available
216217 setTimeout ( ( ) => {
217- const { viewport } = this . getActiveViewportInfo ( ) ;
218+ const { viewport, displaySet } = this . getActiveViewportInfo ( ) ;
218219 for ( const segmentIndex of Object . keys ( initialSegs ) ) {
219220 cornerstoneTools . segmentation . config . color . setSegmentIndexColor (
220221 viewport . viewportId ,
@@ -223,6 +224,8 @@ export default class MonaiLabelPanel extends Component {
223224 initialSegs [ segmentIndex ] . color
224225 ) ;
225226 }
227+ // Store the series UID for the initial segmentation
228+ this . setState ( { segmentationSeriesUID : displaySet ?. SeriesInstanceUID } ) ;
226229 } , 1000 ) ;
227230 }
228231
@@ -268,7 +271,8 @@ export default class MonaiLabelPanel extends Component {
268271 labels ,
269272 override = false ,
270273 label_class_unknown = false ,
271- sidx = - 1
274+ sidx = - 1 ,
275+ inferenceSeriesUID = null
272276 ) => {
273277 console . log ( 'UpdateView: ' , {
274278 model_id,
@@ -314,63 +318,205 @@ export default class MonaiLabelPanel extends Component {
314318 console . log ( 'Index Remap' , labels , modelToSegMapping ) ;
315319 const data = new Uint8Array ( ret . image ) ;
316320
317- const { segmentationService } = this . props . servicesManager . services ;
318- const volumeLoadObject = segmentationService . getLabelmapVolume ( '1' ) ;
321+ const { segmentationService, viewportGridService } = this . props . servicesManager . services ;
322+ let volumeLoadObject = segmentationService . getLabelmapVolume ( '1' ) ;
323+ const { displaySet } = this . getActiveViewportInfo ( ) ;
324+ const currentSeriesUID = displaySet ?. SeriesInstanceUID ;
325+
326+ // If inferenceSeriesUID is not provided, assume it's for the current series
327+ if ( ! inferenceSeriesUID ) {
328+ inferenceSeriesUID = currentSeriesUID ;
329+ }
330+
331+ // Validate inference was run on the current series
332+ if ( currentSeriesUID !== inferenceSeriesUID ) {
333+ this . notification . show ( {
334+ title : 'MONAI Label - Series Mismatch' ,
335+ message : 'Please run inference on the current series' ,
336+ type : 'error' ,
337+ duration : 5000 ,
338+ } ) ;
339+ return ;
340+ }
341+
342+ // Check if we have a stored series UID for the existing segmentation
343+ const storedSeriesUID = this . state . segmentationSeriesUID ;
344+
319345 if ( volumeLoadObject ) {
320- // console.log('Volume Object is In Cache....');
321- let convertedData = data ;
322- for ( let i = 0 ; i < convertedData . length ; i ++ ) {
323- const midx = convertedData [ i ] ;
324- const sidx = modelToSegMapping [ midx ] ;
325- if ( midx && sidx ) {
326- convertedData [ i ] = sidx ;
327- } else if ( override && label_class_unknown && labels . length === 1 ) {
328- convertedData [ i ] = midx ? labelNames [ labels [ 0 ] ] : 0 ;
329- } else if ( labels . length > 0 ) {
330- convertedData [ i ] = 0 ;
346+ const { voxelManager } = volumeLoadObject ;
347+ const existingData = voxelManager ?. getCompleteScalarDataArray ( ) ;
348+ const dimensionsMatch = existingData ?. length === data . length ;
349+ const seriesMatch = storedSeriesUID === currentSeriesUID ;
350+
351+ // If series don't match OR dimensions don't match, this is a different series - need to recreate segmentation
352+ // BUT: if storedSeriesUID is null, this is the first inference, so don't recreate
353+ if ( storedSeriesUID !== null && ( ! seriesMatch || ! dimensionsMatch ) ) {
354+ // Remove the old segmentation
355+ try {
356+ segmentationService . remove ( '1' ) ;
357+ this . setState ( { segmentationSeriesUID : null } ) ;
358+ } catch ( e ) {
359+ return ;
331360 }
361+
362+ // Create a new segmentation for the current series
363+ if ( ! this . state . info || ! this . state . info . initialSegs ) {
364+ return ;
365+ }
366+
367+ const segmentations = [
368+ {
369+ segmentationId : '1' ,
370+ representation : {
371+ type : Enums . SegmentationRepresentations . Labelmap ,
372+ } ,
373+ config : {
374+ label : 'Segmentations' ,
375+ segments : this . state . info . initialSegs ,
376+ } ,
377+ } ,
378+ ] ;
379+
380+ this . props . commandsManager . runCommand ( 'loadSegmentationsForViewport' , {
381+ segmentations,
382+ } ) ;
383+
384+ const responseData = response . data ;
385+ setTimeout ( ( ) => {
386+ const { viewport } = this . getActiveViewportInfo ( ) ;
387+ const initialSegs = this . state . info . initialSegs ;
388+
389+ for ( const segmentIndex of Object . keys ( initialSegs ) ) {
390+ cornerstoneTools . segmentation . config . color . setSegmentIndexColor (
391+ viewport . viewportId ,
392+ '1' ,
393+ initialSegs [ segmentIndex ] . segmentIndex ,
394+ initialSegs [ segmentIndex ] . color
395+ ) ;
396+ }
397+
398+ // Recursively call updateView to populate the newly created segmentation
399+ this . updateView (
400+ { data : responseData } ,
401+ model_id ,
402+ labels ,
403+ override ,
404+ label_class_unknown ,
405+ sidx ,
406+ currentSeriesUID
407+ ) ;
408+ } , 1000 ) ;
409+ return ;
332410 }
333-
334- if ( override === true ) {
335- const { segmentationService } = this . props . servicesManager . services ;
336- const volumeLoadObject = segmentationService . getLabelmapVolume ( '1' ) ;
337- const { voxelManager } = volumeLoadObject ;
338- const scalarData = voxelManager ?. getCompleteScalarDataArray ( ) ;
339-
340- // console.log('Current ScalarData: ', scalarData);
341- const currentSegArray = new Uint8Array ( scalarData . length ) ;
342- currentSegArray . set ( scalarData ) ;
343-
344- // get unique values to determine which organs to update, keep rest
345- const updateTargets = new Set ( convertedData ) ;
346- const numImageFrames =
347- this . getActiveViewportInfo ( ) . displaySet . numImageFrames ;
348- const sliceLength = scalarData . length / numImageFrames ;
349- const sliceBegin = sliceLength * sidx ;
350- const sliceEnd = sliceBegin + sliceLength ;
351-
411+
412+ if ( volumeLoadObject ) {
413+ // console.log('Volume Object is In Cache....');
414+ let convertedData = data ;
352415 for ( let i = 0 ; i < convertedData . length ; i ++ ) {
353- if ( sidx >= 0 && ( i < sliceBegin || i >= sliceEnd ) ) {
354- continue ;
416+ const midx = convertedData [ i ] ;
417+ const sidx = modelToSegMapping [ midx ] ;
418+ if ( midx && sidx ) {
419+ convertedData [ i ] = sidx ;
420+ } else if ( override && label_class_unknown && labels . length === 1 ) {
421+ convertedData [ i ] = midx ? labelNames [ labels [ 0 ] ] : 0 ;
422+ } else if ( labels . length > 0 ) {
423+ convertedData [ i ] = 0 ;
355424 }
425+ }
356426
357- if (
358- convertedData [ i ] !== 255 &&
359- updateTargets . has ( currentSegArray [ i ] )
360- ) {
361- currentSegArray [ i ] = convertedData [ i ] ;
427+ if ( override === true ) {
428+ const { segmentationService } = this . props . servicesManager . services ;
429+ const volumeLoadObject = segmentationService . getLabelmapVolume ( '1' ) ;
430+ const { voxelManager } = volumeLoadObject ;
431+ const scalarData = voxelManager ?. getCompleteScalarDataArray ( ) ;
432+
433+ // console.log('Current ScalarData: ', scalarData);
434+ const currentSegArray = new Uint8Array ( scalarData . length ) ;
435+ currentSegArray . set ( scalarData ) ;
436+
437+ // get unique values to determine which organs to update, keep rest
438+ const updateTargets = new Set ( convertedData ) ;
439+ const numImageFrames =
440+ this . getActiveViewportInfo ( ) . displaySet . numImageFrames ;
441+ const sliceLength = scalarData . length / numImageFrames ;
442+ const sliceBegin = sliceLength * sidx ;
443+ const sliceEnd = sliceBegin + sliceLength ;
444+
445+ for ( let i = 0 ; i < convertedData . length ; i ++ ) {
446+ if ( sidx >= 0 && ( i < sliceBegin || i >= sliceEnd ) ) {
447+ continue ;
448+ }
449+
450+ if (
451+ convertedData [ i ] !== 255 &&
452+ updateTargets . has ( currentSegArray [ i ] )
453+ ) {
454+ currentSegArray [ i ] = convertedData [ i ] ;
455+ }
362456 }
457+ convertedData = currentSegArray ;
363458 }
364- convertedData = currentSegArray ;
459+ // voxelManager already declared above
460+ voxelManager ?. setCompleteScalarDataArray ( convertedData ) ;
461+ triggerEvent ( eventTarget , Enums . Events . SEGMENTATION_DATA_MODIFIED , {
462+ segmentationId : '1' ,
463+ } ) ;
464+ console . log ( "updated the segmentation's scalar data" ) ;
465+
466+ // Store the series UID for this segmentation
467+ this . setState ( { segmentationSeriesUID : currentSeriesUID } ) ;
365468 }
366- const { voxelManager } = volumeLoadObject ;
367- voxelManager ?. setCompleteScalarDataArray ( convertedData ) ;
368- triggerEvent ( eventTarget , Enums . Events . SEGMENTATION_DATA_MODIFIED , {
369- segmentationId : '1' ,
370- } ) ;
371- console . log ( "updated the segmentation's scalar data" ) ;
372469 } else {
373- console . log ( 'TODO:: Volume Object is NOT In Cache....' ) ;
470+ // Create new segmentation
471+ if ( ! this . state . info || ! this . state . info . initialSegs ) {
472+ return ;
473+ }
474+
475+ const segmentations = [
476+ {
477+ segmentationId : '1' ,
478+ representation : {
479+ type : Enums . SegmentationRepresentations . Labelmap ,
480+ } ,
481+ config : {
482+ label : 'Segmentations' ,
483+ segments : this . state . info . initialSegs ,
484+ } ,
485+ } ,
486+ ] ;
487+
488+ // Create the segmentation for this viewport
489+ this . props . commandsManager . runCommand ( 'loadSegmentationsForViewport' , {
490+ segmentations,
491+ } ) ;
492+
493+ // Wait for segmentation to be created, then populate it with inference data
494+ const responseData = response . data ;
495+ setTimeout ( ( ) => {
496+ const { viewport } = this . getActiveViewportInfo ( ) ;
497+ const initialSegs = this . state . info . initialSegs ;
498+
499+ // Set colors
500+ for ( const segmentIndex of Object . keys ( initialSegs ) ) {
501+ cornerstoneTools . segmentation . config . color . setSegmentIndexColor (
502+ viewport . viewportId ,
503+ '1' ,
504+ initialSegs [ segmentIndex ] . segmentIndex ,
505+ initialSegs [ segmentIndex ] . color
506+ ) ;
507+ }
508+
509+ // Recursively call updateView to populate the newly created segmentation
510+ this . updateView (
511+ { data : responseData } ,
512+ model_id ,
513+ labels ,
514+ override ,
515+ label_class_unknown ,
516+ sidx ,
517+ currentSeriesUID // Pass the series UID
518+ ) ;
519+ } , 1000 ) ;
374520 }
375521 } ;
376522
0 commit comments