# Python script to get axis-aligned bounding box

**URL:** <https://discourse.slicer.org/t/python-script-to-get-axis-aligned-bounding-box/26227>\
**Category:** Development\
**Created:** [November 14, 2022, 1:37pm UTC](https://discourse.slicer.org/t/python-script-to-get-axis-aligned-bounding-box/26227 "2022-11-14T13:37:33Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![xackey](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/xackey/32/10860_2.png) [@xackey](https://discourse.slicer.org/u/xackey)\
**Post date:** [November 14, 2022, 1:37pm UTC](https://discourse.slicer.org/t/python-script-to-get-axis-aligned-bounding-box/26227/1 "2022-11-14T13:37:33Z")

</div>

Could you tell me how to get an axis-aligned bounding box that fits a segment using python interactor? The script repository describes how to create an oriented bounding box, but not an axis-aligned bounding box. I would like to know a script to make a roi like attached image.  
Thank you!

 ![axis-aligned bounding box](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/0/4/04d9d9b3d38c873656992e4faa7f35ab365d0c0a.jpeg)

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [November 14, 2022, 6:32pm UTC](https://discourse.slicer.org/t/python-script-to-get-axis-aligned-bounding-box/26227/2 "2022-11-14T18:32:37Z")

</div>

Probably the easiest is to get the segment as a numpy array as shown [here](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#read-and-write-a-segment-as-a-numpy-array) and then use basic numpy function to get index range of non-zero elements.

---

<div class="post-metadata">

**Author:** ![xackey](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/xackey/32/10860_2.png) [@xackey](https://discourse.slicer.org/u/xackey)\
**Post date:** [November 14, 2022, 10:41pm UTC](https://discourse.slicer.org/t/python-script-to-get-axis-aligned-bounding-box/26227/3 "2022-11-14T22:41:42Z")

</div>

Could you give a sample script because I am new to python.  
Thank you in advance.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [November 14, 2022, 10:59pm UTC](https://discourse.slicer.org/t/python-script-to-get-axis-aligned-bounding-box/26227/4 "2022-11-14T22:59:24Z")

</div>

You can use the code snippet that I linked to get the numpy array, then search on Google/StackOverflow for code snippets to get range of non-zero elements in a numpy array.

---

<div class="post-metadata">

**Author:** ![xackey](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/xackey/32/10860_2.png) [@xackey](https://discourse.slicer.org/u/xackey)\
**Post date:** [November 15, 2022, 9:59am UTC](https://discourse.slicer.org/t/python-script-to-get-axis-aligned-bounding-box/26227/5 "2022-11-15T09:59:24Z")

</div>

I was able to make a script but it is very long. Can you make it simpler?

```auto
#Get volume and segmentation
volumeNode = slicer.mrmlScene.GetFirstNodeByClass("vtkMRMLScalarVolumeNode")
segmentationNode = slicer.mrmlScene. GetFirstNodeByClass ("vtkMRMLSegmentationNode")

# Export "Segment_1" to LabelmapNode
labelmapVolumeNode=slicer.mrmlScene.AddNewNodeByClass("vtkMRMLLabelMapVolumeNode")
segmentIds = vtk.vtkStringArray()
segmentId = segmentationNode.GetSegmentation().GetSegmentIdBySegmentName("Segment_1")
segmentIds.InsertNextValue(segmentId)
slicer.modules.segmentations.logic().ExportSegmentsToLabelmapNode(segmentationNode, segmentIds, labelmapVolumeNode, volumeNode)

#Get 3 axis length and center coordinate (kJI coordinate) of a bounding box
import numpy as np
label = array("LabelMapVolume")
points = np.where( label == 1 )
length_z=np.max(points[0])- np.min(points[0])+1
length_y=np.max(points[1])- np.min(points[1])+1
length_x=np.max(points[2])- np.min(points[2])+1
center=[(np.max(points[0])+ np.min(points[0]))/2, (np.max(points[1])+ np.min(points[1]))/2, (np.max(points[2])+ np.min(points[2]))/2]

#Transform KJI to RAS coordinate
ijkToRasMatrix = vtk.vtkMatrix4x4()
volumeNode.GetIJKToRASMatrix(ijkToRasMatrix)
ijkPoint = np.array([center[2], center[1], center[0]]) # This is IJK, opposite order compared to KJI.
rasPoint = ijkToRasMatrix.MultiplyFloatPoint(np.append(ijkPoint,1))

#Make an axis-alinged bounding box of "Segment_1". 
roi=slicer.mrmlScene.AddNewNodeByClass("vtkMRMLAnnotationROINode")
roi.SetXYZ(rasPoint[0], rasPoint[1], rasPoint[2])
spacing = volumeNode.GetSpacing()
roi.SetRadiusXYZ(length_x*spacing[0]/2, length_y*spacing[1]/2, length_z*spacing[2]/2)

```

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [November 15, 2022, 5:58pm UTC](https://discourse.slicer.org/t/python-script-to-get-axis-aligned-bounding-box/26227/6 "2022-11-15T17:58:16Z")

</div>

This looks simple enough. Note that the Annotations module is deprecated and will be removed in Slicer-5.4, so I would recommend to use Markups module instead.

---

<div class="post-metadata">

**Author:** ![xackey](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/xackey/32/10860_2.png) [@xackey](https://discourse.slicer.org/u/xackey)\
**Post date:** [November 16, 2022, 8:28am UTC](https://discourse.slicer.org/t/python-script-to-get-axis-aligned-bounding-box/26227/7 "2022-11-16T08:28:28Z")

</div>

I changed to use markups module and leave the script below for other users.  
Thank you for your help.

```auto
#Get volume and segmentation. 
volumeNode = slicer.mrmlScene.GetFirstNodeByClass("vtkMRMLScalarVolumeNode")
segmentationNode = slicer.mrmlScene. GetFirstNodeByClass ("vtkMRMLSegmentationNode")

# Export “Segment_1” to LabelmapNode
labelmapVolumeNode=slicer.mrmlScene.AddNewNodeByClass("vtkMRMLLabelMapVolumeNode")
segmentIds = vtk.vtkStringArray()
segmentId = segmentationNode.GetSegmentation().GetSegmentIdBySegmentName("Segment_1")
segmentIds.InsertNextValue(segmentId)
slicer.modules.segmentations.logic().ExportSegmentsToLabelmapNode(segmentationNode, segmentIds, labelmapVolumeNode, volumeNode)

#Get three axis length and center coordinate (kJI coordinate) of a bounding box
import numpy as np
label = array("LabelMapVolume")
points = np.where( label == 1 )
length_z=np.max(points[0])- np.min(points[0])+1
length_y=np.max(points[1])- np.min(points[1])+1
length_x=np.max(points[2])- np.min(points[2])+1
center=[(np.max(points[0])+ np.min(points[0]))/2, (np.max(points[1])+ np.min(points[1]))/2, (np.max(points[2])+ np.min(points[2]))/2]

#Transform KJI to RAS coordinate
ijkToRasMatrix = vtk.vtkMatrix4x4()
volumeNode.GetIJKToRASMatrix(ijkToRasMatrix)
ijkPoint = np.array([center[2], center[1], center[0]]) # This is IJK, opposite order compared to KJI.
rasPoint = ijkToRasMatrix.MultiplyFloatPoint(np.append(ijkPoint,1))
print(rasPoint)

#Make an axis-alinged bounding box of "Segment_1". 
roi=slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsROINode")
roi.SetXYZ(rasPoint[0], rasPoint[1], rasPoint[2])
spacing = volumeNode.GetSpacing()
roi.SetRadiusXYZ(length_x*spacing[0]/2, length_y*spacing[1]/2, length_z*spacing[2]/2)

```

---

<div class="post-metadata">

**Author:** ![SummerZ2020](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/summerz2020/32/7137_2.png) [@SummerZ2020](https://discourse.slicer.org/u/SummerZ2020)\
**Post date:** [March 26, 2025, 12:17pm UTC](https://discourse.slicer.org/t/python-script-to-get-axis-aligned-bounding-box/26227/8 "2025-03-26T12:17:31Z")

</div>

> [@xackey](#):
>
> `label = array("LabelMapVolume")`

In version 5.6.2, the method for obtaining the array needs to be updated as follows. Otherwise, an error will occur: “slicer.util.MRMLNodeNotFoundException: could not find nodes in the scene by name or id ‘LabelMapVolume’”.  
label = slicer.util.arrayFromVolume(labelmapVolumeNode)
