# 3D View interactive ROI Cropping

**URL:** <https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735>\
**Category:** Support\
**Created:** [May 22, 2021, 3:48pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735 "2021-05-22T15:48:16Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [May 22, 2021, 3:48pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/1 "2021-05-22T15:48:16Z")

</div>

@jamesobutler @jcfr @lassoan @pieper

![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/6/9/6979953ae7b19fdf9d90c8f2415691ab799002b4.png)

Could you point me to how I can enable interactive 3D cropping on a 3D rendering in 3D view with Python?

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [May 22, 2021, 4:23pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/2 "2021-05-22T16:23:13Z")

</div>

Here’s the recipe for finding the code to implement GUI features - it’s very powerful - it will help you better understand the code and find solutions to a lot of questions:

[https://slicer.readthedocs.io/en/latest/developer\_guide/python\_faq.html#how-to-find-a-python-function-for-any-slicer-features](https://slicer.readthedocs.io/en/latest/developer_guide/python_faq.html#how-to-find-a-python-function-for-any-slicer-features)

Also in this case there’s already useful information in the script repository, so its recommended to read through all the snippets there to save time in the future:

[https://slicer.readthedocs.io/en/latest/developer\_guide/script\_repository.html#limit-volume-rendering-to-a-specific-region-of-the-volume](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#limit-volume-rendering-to-a-specific-region-of-the-volume)

---

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [May 22, 2021, 6:34pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/3 "2021-05-22T18:34:59Z")

</div>

Thanks you Steve. That’s the best response ever. Teach me to fish. I’ll get my pole and tackle and get to work.

🙂

---

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [May 23, 2021, 8:00pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/4 "2021-05-23T20:00:17Z")

</div>

OK, I’m trying to get through the docs. I will keep struggling through them, but here’s where I am so far.

I’ve enabled cropping with this code…

```
   def enable3DCroppingUI(self, volumeNode):

    displayNode = slicer.mrmlScene.GetFirstNodeByClass("vtkMRMLViewNode")

    roiNode = slicer.vtkMRMLAnnotationROINode()
    roiNode.Initialize(slicer.mrmlScene)

    displayNode.SetAndObserveROINodeID(roiNode.GetID())
    displayNode.CroppingEnabled = True

```

Here’s what I get.

![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/2/d/2daf6265daa98040f152054cebdfe545310afac9.jpeg)

AttributeError: ‘MRMLCore.vtkMRMLViewNode’ object has no attribute ‘SetAndObserveROINodeID’

How do I get it to crop? It seems my ROI and/or cropping is not associated with the rendering. I’m almost there. Shall I play around with the code in the “CropVolumeSelfTest.py” function (found via @pieper recipe for finding the code)?

I am really excited about displaying this powerful Slicer capability to my physicians this week since they tell me the slice planes rendering is useless. They will be pleasantly surprised I think.

---

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [May 23, 2021, 9:48pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/5 "2021-05-23T21:48:26Z")

</div>

This comes up first when I initially turn on cropping. This has to be ROI related I think…

![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/3/4/340d925ef20b739a3a6530bc2eb35d146344a9ad.jpeg)

Here’s my code…

```
def enable3DCroppingUI(self, volumeNode):

    roi = slicer.vtkMRMLAnnotationROINode()
    roi.Initialize(slicer.mrmlScene)

    cropVolumeNode = slicer.vtkMRMLCropVolumeParametersNode()
    cropVolumeNode.SetScene(slicer.mrmlScene)

    cropVolumeNode.SetIsotropicResampling(True)
    cropVolumeNode.SetSpacingScalingConst(0.5)
    slicer.mrmlScene.AddNode(cropVolumeNode)

    cropVolumeNode.SetInputVolumeNodeID(volumeNode.GetID())
    cropVolumeNode.SetROINodeID(roi.GetID())

    cropVolumeLogic = slicer.modules.cropvolume.logic()
    cropVolumeLogic.Apply(cropVolumeNode)

```

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mau_igna_06/32/9056_2.png) [@mau\_igna\_06](https://discourse.slicer.org/u/mau_igna_06)\
**Post date:** [May 23, 2021, 10:57pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/6 "2021-05-23T22:57:31Z")

</div>

I think your displayNode definition is wrong.

I think this could work:

```auto
   def enable3DCroppingUI(self, volumeNode):

    displayNode = slicer.modules.volumerendering.logic().GetFirstVolumeRenderingDisplayNode(volumeNode)

    roiNode = slicer.vtkMRMLAnnotationROINode()
    roiNode.Initialize(slicer.mrmlScene)

    displayNode.SetAndObserveROINodeID(roiNode.GetID())
    displayNode.CroppingEnabled = True

```

I don’t know if there are more mistakes in the above code.

---

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [May 24, 2021, 5:24pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/7 "2021-05-24T17:24:14Z")

</div>

> [@mau\_igna\_06](#):
>
> I think your displayNode definition is wrong.

Hello @mau_igna_06,

Thank you for the response. I tried that and as you implied, there are obviously other mistakes. Do you have or know of other slicer modules that successfully implement 3D cropping? How do you initially set up your 3D View? My renderings always includes the 3 slice planes. If you can help me to achieve this goal, that would be great.

I’m thinking the slice planes rendering is getting in the way, and maybe the ROI is using it.

![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/0/5/05886d8642bbae3a5fb60581ba64a1eee0e6ff47.png)

---

<div class="post-metadata">

**Author:** ![jamesobutler](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jamesobutler/32/7511_2.png) [@jamesobutler](https://discourse.slicer.org/u/jamesobutler)\
**Post date:** [May 24, 2021, 6:42pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/8 "2021-05-24T18:42:41Z")

</div>

In your image there you have both the volume rendering shown and also the slice intersections. You need to turn off/on slice intersections as you want. See this example of how to turn on slice intersections. [Script repository — 3D Slicer documentation](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#turn-on-slice-intersections)

---

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [May 25, 2021, 10:21pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/9 "2021-05-25T22:21:44Z")

</div>

@lassoan @jamesobutler @pieper

OK, after 5, 12 hour days in a row, I am still having the most difficult time getting my cropping ROI associated with my 3D View image. Can I pay someone to show look at my code and show me what I’m doing wrong? $$$ Sensing some desperation here? You’re right! This is clearly beyond my threshold of complexity. If you’re interested, we can take this off line and I’ll hire you. mail me at [knufunk@live.com](mailto:knufunk@live.com). This is not necessarily for work, just for my knowledge and then I’ll use my knowledge for work. Consider it a private lesson. An education.

I just want this functionality,

![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/4/b/4b175b596f7182f2e1eff63669bb106e9f936802.png)

If it can’t be done, please let me know so that I can stop wasting my time. Thanks! 😑

---

<div class="post-metadata">

**Author:** ![jamesobutler](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jamesobutler/32/7511_2.png) [@jamesobutler](https://discourse.slicer.org/u/jamesobutler)\
**Post date:** [May 26, 2021, 2:38am UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/10 "2021-05-26T02:38:54Z")

</div>

Hi @spycolyf, I don’t know all of your individual requirements, but addressing turning on the VolumeRendering crop ROI for interactive cropping in the 3D View these are the steps for learning how to do this task.

Starting with the Slicer script repository, [Script repository — 3D Slicer documentation](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#limit-volume-rendering-to-a-specific-region-of-the-volume), provides information about how to use a specific ROI node for cropping in the volume rendering widget.

From this example we learn that we need a VolumeRenderingDisplayNode object to manipulate cropping. From another [Slicer script repository example](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#display-volume-using-volume-rendering) we learn how to get that object. There are different ways to do this, but I will use this existing example.

```python
logic = slicer.modules.volumerendering.logic()
volumeNode = slicer.mrmlScene.GetNodeByID('vtkMRMLScalarVolumeNode1')
displayNode = logic.CreateVolumeRenderingDisplayNode()
displayNode.UnRegister(logic)
slicer.mrmlScene.AddNode(displayNode)
volumeNode.AddAndObserveDisplayNodeID(displayNode.GetID())
logic.UpdateDisplayNodeFromVolumeNode(displayNode, volumeNode)

```

A good method for making sure you get the correct object is to try things out in the Slicer python interactor and examine the type as such. Here we see that we currently have a special type of VolumeRenderingDisplayNode which is specific to GPU rendering and not the CPU type volume rendering. We can see how it inherits thing in its [documentation](https://apidocs.slicer.org/master/classvtkMRMLGPURayCastVolumeRenderingDisplayNode.html).

```python
>>> displayNode
(vtkSlicerVolumeRenderingModuleMRML.vtkMRMLGPURayCastVolumeRenderingDisplayNode)000001E46534FB28

```

From there a common technique I use is to see what options are available to the object that I have. Therefore I do “displayNode.[TAB]” where pressing the tab key after the dot will break up autocompletion of available methods and attributes for this object. It will show all inherited things as well. When viewing documentation online it usually shows only methods introduced in that object specifically and links to documentation of classes that it inherits. This method of searching is not always efficient, but it allows you to learn to see what is available and to try things out and explore the API.

I can find how to turn on the display node which shows the volume rendering in the 3D view.

```python
displayNode.SetVisibility(True)

```

I can also scroll through the autocompletion and find that there is a method for turning on/off cropping.

```python
displayNode.SetCroppingEnabled(True)

```

I also find the ROI Node associated with the volume rendering display node for cropping.

```python
>>> displayNode.GetROINode()
(vtkSlicerAnnotationsModuleMRML.vtkMRMLAnnotationROINode)00000180F1134D08

```

From here I have learned that the ROI is a vtkMRMLAnnotationROINode type. Now I just need to figure out how to turn the visibility on for that ROI so it can be seen in the 3D view. I can search vtkMRMLAnnotationROINode documentation online or use tab completion on this object to look for methods to turn on visibility. Is it `setVisible` or `VisibilityOn()` or `SetDisplayVisibility`? I can search for methods like this.

I then find that for a vtkMRMLAnnotationROINode it is `SetDisplayVisibility` that is available and works to show the ROI in all the views including the slice views and 3D view.

```python
displayNode.GetROINode().SetDisplayVisibility(True)

```

Putting everything together into a self contained example that can be pasted into the Python interactor upon starting Slicer.

```python
import SampleData
sampleDataLogic = SampleData.SampleDataLogic()
volumeNode= sampleDataLogic.downloadMRHead()

logic = slicer.modules.volumerendering.logic()
displayNode = logic.CreateVolumeRenderingDisplayNode()
displayNode.UnRegister(slicer.mrmlScene) # See https://www.slicer.org/wiki/Documentation/Nightly/Developers/Tutorials/MemoryManagement
slicer.mrmlScene.AddNode(displayNode)
volumeNode.AddAndObserveDisplayNodeID(displayNode.GetID())
logic.UpdateDisplayNodeFromVolumeNode(displayNode, volumeNode)

displayNode.SetVisibility(True) # Volume Rendering shown in 3D view
displayNode.SetCroppingEnabled(True) # Cropping Enabled
displayNode.GetROINode().SetDisplayVisibility(True) # Show ROI used for cropping Volume Rendering

```

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/e/a/ea989fef1f4a612b516e3ef0a573efd614602e10.jpeg)

Here I’ve manually rotated the volume in the 3D view and clicked a control point on the ROI to crop the volume rendering.

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/6/a/6a11bcaf481dff14ccac8914abaded953058eec7.jpeg)

---

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [May 26, 2021, 3:01pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/11 "2021-05-26T15:01:46Z")

</div>

Oh wow @jamesobutler! I am so grateful for your response and for making an attempt to help me out. I show onw physician/Radiologist this functionality in Slicer and he was blown away and said “Surgical Services would go nuts over this (in a good way).” I continue to be amazed by the lack of awareness of Kitware and Slicer in the medical imaging community. This will definitely expand that awareness here. Anyway, thanks so much for giving me a flashlight if you will. I’m eager to continue this endeavor. I’ll let you know my progress.

---

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [May 26, 2021, 3:05pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/12 "2021-05-26T15:05:38Z")

</div>

And thank you for showing me a little more about how to use the documentation and put things together.

---

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [May 27, 2021, 3:39pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/13 "2021-05-27T15:39:42Z")

</div>

@jamesobutler

Thanks to your response I was able to accomplish what I needed. Soon, I will post instructions describing all that I did to achieve my solution. I think it will help others.

Thanks so much!

---

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [May 27, 2021, 10:25pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/14 "2021-05-27T22:25:08Z")

</div>

@jamesobutler,

Hello, do you know a way to reset the cropping ROI back to be fully enclosing as when initally created?

Thanks

---

<div class="post-metadata">

**Author:** ![jamesobutler](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jamesobutler/32/7511_2.png) [@jamesobutler](https://discourse.slicer.org/u/jamesobutler)\
**Post date:** [May 27, 2021, 10:37pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/15 "2021-05-27T22:37:02Z")

</div>

You are describing the functionality of the following button in the GUI. Determining how to do this in Python would be a good practice if you haven’t already. I would suggest that you start by searching for the methods available in `slicer.modules.volumerendering.logic()`. There is a method name in the logic class that should pop out to you for doing this action.

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/2/d/2dce28ae019950b769d52b52802a7ae82e483a6c.jpeg)

---

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [May 27, 2021, 10:57pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/16 "2021-05-27T22:57:01Z")

</div>

ok thanks! 🙂 @jamesobutler

---

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [June 1, 2021, 8:54pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/17 "2021-06-01T20:54:06Z")

</div>

Hello @jamesobutler,

Every advice you gave led me to success. Thanks You so much!

Now there’s one final (I think) thing that need to accomplish and I have sort of working, but it’s not smooth. I’m trying to implement the shift function in the following figure.

![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/4/b/4b175b596f7182f2e1eff63669bb106e9f936802.png)

I’m changing the Gradient Threshold with the value of a slider (0 to 99). But, it’s pretty jerky (not smooth changes). It works best if I slide the slider slowly. What is the proper way to do this in Python? Do I need to add delays in the event handler to give the display time to catch up as I slide?

Here’s my code:

```
def updateRenderShift(self):

    # Here's where I assign the slider value (0 to 99) to the gradient threshold
    gradientThreshold = self.ui.RenderShiftSlider.value

    maxOpacity = 1.0
    gradientOpacityTransferFunction = self.displayNode.GetVolumePropertyNode().GetVolumeProperty().GetGradientOpacity()
    gradientOpacityTransferFunction.RemoveAllPoints()
    gradientOpacityTransferFunction.AddPoint(0, 0.0)
    gradientOpacityTransferFunction.AddPoint(gradientThreshold-1, 0.0)
    gradientOpacityTransferFunction.AddPoint(gradientThreshold+1, maxOpacity)

```

---

<div class="post-metadata">

**Author:** ![jamesobutler](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jamesobutler/32/7511_2.png) [@jamesobutler](https://discourse.slicer.org/u/jamesobutler)\
**Post date:** [June 2, 2021, 7:22pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/18 "2021-06-02T19:22:11Z")

</div>

When I change the shift slider as you indicate in your picture when displaying the volume rendering of the MRHead sample data it is smooth for me. What GPU is being used when you observe that it is not smooth?

---

<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:** [June 2, 2021, 7:57pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/19 "2021-06-02T19:57:16Z")

</div>

You can enter interactive rendering mode when you start moving the slider and exit when you release the slider (this is particularly effective if you use CPU volume rendering, and this is used in Volume rendering module to make the updates smoother).

You can also disable tracking in the slider, which make the slider only generate value changed events when the slider is released.

---

<div class="post-metadata">

**Author:** ![spycolyf](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@spycolyf](https://discourse.slicer.org/u/spycolyf)\
**Post date:** [June 8, 2021, 3:38pm UTC](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735/20 "2021-06-08T15:38:28Z")

</div>

Hello @lassoan @pieper @jcfr

This thread is very long and all over the place. My Bad. How can I extract an earlier part of it to a new topic?

Thanks

[Next page](https://discourse.slicer.org/t/3d-view-interactive-roi-cropping/17735.md?page=2)
