# Converting segmentation to numpy array and back does not conserve layer ordering

**URL:** <https://discourse.slicer.org/t/converting-segmentation-to-numpy-array-and-back-does-not-conserve-layer-ordering/34079>\
**Category:** Development\
**Created:** [February 1, 2024, 10:03am UTC](https://discourse.slicer.org/t/converting-segmentation-to-numpy-array-and-back-does-not-conserve-layer-ordering/34079 "2024-02-01T10:03:57Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![tueboesen](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/tueboesen/32/69242_2.png) [@tueboesen](https://discourse.slicer.org/u/tueboesen)\
**Post date:** [February 1, 2024, 10:03am UTC](https://discourse.slicer.org/t/converting-segmentation-to-numpy-array-and-back-does-not-conserve-layer-ordering/34079/1 "2024-02-01T10:03:58Z")

</div>

I have the following function in my custom built segment editor module, built upon the standard extension script. The problem is that the segments I manually put in gets moved to a different layer when I run this code, and I don’t understand how this can happen.

Here is what it might look like before

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/9/1/9125025b805c00c17adca6d34510284989076086.jpeg)

And here is where the segmentation shows up after applying it. As you can see the slider is in a completely different layer, and there now no longer any segmentation in the layer it was originally applied in

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/2/a/2ac4aef4d5d004d019f5238439753b0d9223f64e.png)

The full function is given below. But I think the interesting part is this:

`labelImage = sitk.GetImageFromArray(labelImage_np)`  
which is how I get the numpy array back into a format that slicer can interact with, but maybe this is not the correct way to do that?

```auto
    def onApply(self):
        # Make sure the user wants to do the operation, even if the segment is not visible
        print(self.scriptedEffect.confirmCurrentSegmentVisible())
        if not self.scriptedEffect.confirmCurrentSegmentVisible():
            return
        #
        # Get list of visible segment IDs, as the effect ignores hidden segments.
        segmentationNode = self.scriptedEffect.parameterSetNode().GetSegmentationNode()
        visibleSegmentIds = vtk.vtkStringArray()
        segmentationNode.GetDisplayNode().GetVisibleSegmentIDs(visibleSegmentIds)
        if visibleSegmentIds.GetNumberOfValues() == 0:
            logging.info("Smoothing operation skipped: there are no visible segments")
            return

        # This can be a long operation - indicate it to the user
        qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor)

        # Allow users revert to this state by clicking Undo
        self.scriptedEffect.saveStateForUndo()

        # Export source image data to temporary new volume node.
        # Note: Although the original source volume node is already in the scene, we do not use it here,
        # because the source volume may have been resampled to match segmentation geometry.
        sourceVolumeNode = slicer.vtkMRMLScalarVolumeNode()
        slicer.mrmlScene.AddNode(sourceVolumeNode)
        sourceVolumeNode.SetAndObserveTransformNodeID(segmentationNode.GetTransformNodeID())
        slicer.vtkSlicerSegmentationsModuleLogic.CopyOrientedImageDataToVolumeNode(self.scriptedEffect.sourceVolumeImageData(), sourceVolumeNode)

        # Generate merged labelmap of all visible segments, as the filter expects a single labelmap with all the labels.
        mergedLabelmapNode = slicer.vtkMRMLLabelMapVolumeNode()
        slicer.mrmlScene.AddNode(mergedLabelmapNode)
        slicer.vtkSlicerSegmentationsModuleLogic.ExportSegmentsToLabelmapNode(segmentationNode, visibleSegmentIds, mergedLabelmapNode, sourceVolumeNode)

        # Run segmentation algorithm

        # Read input data from Slicer into SimpleITK
        labelImage = sitk.ReadImage(sitkUtils.GetSlicerITKReadWriteAddress(mergedLabelmapNode.GetName()))
        backgroundImage = sitk.ReadImage(sitkUtils.GetSlicerITKReadWriteAddress(sourceVolumeNode.GetName()))

        Image_np = sitk.GetArrayFromImage(backgroundImage)
        labelImage_np = sitk.GetArrayFromImage(labelImage)
        m = labelImage_np != 0
        m2 = np.sum(m,axis=(1,2))
        idx = np.argmax(m2)
       
        labelImage_np[idx] = dummy(Image_np[idx], labelImage_np[idx])
        labelImage = sitk.GetImageFromArray(labelImage_np)

        sitk.WriteImage(labelImage, sitkUtils.GetSlicerITKReadWriteAddress(mergedLabelmapNode.GetName()))

        slicer.vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode(mergedLabelmapNode, segmentationNode, visibleSegmentIds)

        mergedLabelmapNode.GetImageData().Modified()
        mergedLabelmapNode.Modified()
        
        # Update segmentation from labelmap node and remove temporary nodes
        slicer.vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode(mergedLabelmapNode, segmentationNode, visibleSegmentIds)
        slicer.mrmlScene.RemoveNode(sourceVolumeNode)
        slicer.mrmlScene.RemoveNode(mergedLabelmapNode)
        
        qt.QApplication.restoreOverrideCursor()

```
