# How to Enable Maximum Intensity Projection (MIP) Automatically for MRML Presets?

**URL:** https://discourse.slicer.org/t/how-to-enable-maximum-intensity-projection-mip-automatically-for-mrml-presets/40679
**Category:** Development
**Tags:** rendering, mrml, volume-rendering, extensions
**Created:** [December 13, 2024, 12:10pm UTC](https://discourse.slicer.org/t/how-to-enable-maximum-intensity-projection-mip-automatically-for-mrml-presets/40679 "2024-12-13T12:10:19Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![LounesAl](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lounesal/32/78861_2.png) [@LounesAl](https://discourse.slicer.org/u/LounesAl)
#### Post date: [December 13, 2024, 12:10pm UTC](https://discourse.slicer.org/t/how-to-enable-maximum-intensity-projection-mip-automatically-for-mrml-presets/40679/1 "2024-12-13T12:10:19Z")

</div>

Hello,

I have created custom volume rendering presets in an MRML file. Below is an example structure:

```xml
<MRML version="Slicer4.4.0">
  <VolumeProperty id="vtkMRMLVolumeProperty1" name="MyPreset1" references="IconVolume:vtkMRMLVectorVolumeNode1;" interpolation="1" shade="1" diffuse="0.66" ambient="0.1" specular="0.62" specularPower="14" scalarOpacity="10 -3.52844023704529 0 56.7852325439453 0 79.2550277709961 0.428571432828903 415.119384765625 1 641 1" gradientOpacity="4 0 1 160.25 1" colorTransfer="16 0 0 0 0 98.7223 0.196078431372549 0.945098039215686 0.956862745098039 412.406 0 0.592157 0.807843 641 1 1 1" />
  <VectorVolume id="vtkMRMLVectorVolumeNode1" references="storage:vtkMRMLVolumeArchetypeStorageNode1;" />
  <VolumeArchetypeStorage id="vtkMRMLVolumeArchetypeStorageNode1" fileName="MyPreset1.png" fileListMember0="MyPreset1.png" />

  <VolumeProperty id="vtkMRMLVolumeProperty2" name="MyPreset2" references="IconVolume:vtkMRMLVectorVolumeNode2;" interpolation="1" shade="1" diffuse="0.66" ambient="0.1" specular="0.62" specularPower="14" scalarOpacity="10 -3.52844023704529 0 56.7852325439453 0 79.2550277709961 0.428571432828903 415.119384765625 1 641 1" gradientOpacity="4 0 1 160.25 1" colorTransfer="16 0 0 0 0 98.7223 0.196078431372549 0.945098039215686 0.956862745098039 412.406 0 0.592157 0.807843 641 1 1 1" />
  <VectorVolume id="vtkMRMLVectorVolumeNode2" references="storage:vtkMRMLVolumeArchetypeStorageNode2;" />
  <VolumeArchetypeStorage id="vtkMRMLVolumeArchetypeStorageNode2" fileName="MyPreset2.png" fileListMember0="MyPreset2.png" />
</MRML>

```

I would like to automatically enable **Maximum Intensity Projection (MIP)** when switching to the `MyPreset2` preset.

Do I need to add a `ViewNode`, a `VolumeRenderingDisplayNode`, or some other configuration in the MRML file? If not, what is the best way to associate MIP with specific presets?

Thank you for your help!

---

<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: [December 13, 2024, 3:46pm UTC](https://discourse.slicer.org/t/how-to-enable-maximum-intensity-projection-mip-automatically-for-mrml-presets/40679/2 "2024-12-13T15:46:45Z")

</div>

MIP mode has to be enabled on the view node - see [full example in the script repository](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#show-volume-rendering-using-maximum-intensity-projection).

It would make more sense to include raycast technique in the volume rendering preset. I’ve added an [issue to track this task](https://github.com/Slicer/Slicer/issues/8095). But to reduce API churn, we probably will not change this until we need to make other significant changes/improvements to rendering presets. A grant proposal was submitted for improving volume rendering presets, so if it is successful (or if other funding sources come in) then this will all be implemented.

---

<div class="post-metadata">

### Author: ![LounesAl](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lounesal/32/78861_2.png) [@LounesAl](https://discourse.slicer.org/u/LounesAl)
#### Post date: [December 13, 2024, 5:35pm UTC](https://discourse.slicer.org/t/how-to-enable-maximum-intensity-projection-mip-automatically-for-mrml-presets/40679/3 "2024-12-13T17:35:15Z")

</div>

Thank you @lassoan for the clarification and for adding this to the issue tracker.

I plan to implement a workaround using a Python function `onPresetChanged` in my module within my extension. The function would trigger when the preset changes, allowing me to manually set the raycast technique for specific presets. For example:

```python
def onPresetChanged(presetName):
    if presetName == "MyPreset2":
        # Switch views to MIP mode
        for viewNode in slicer.util.getNodesByClass("vtkMRMLViewNode"):
            viewNode.SetRaycastTechnique(slicer.vtkMRMLViewNode.MaximumIntensityProjection)

```

Is there a way to integrate such a function so that it is automatically triggered when a preset is changed?

---

<div class="post-metadata">

### Author: ![chir.set](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/chir.set/32/66982_2.png) [@chir.set](https://discourse.slicer.org/u/chir.set)
#### Post date: [December 13, 2024, 7:00pm UTC](https://discourse.slicer.org/t/how-to-enable-maximum-intensity-projection-mip-automatically-for-mrml-presets/40679/4 "2024-12-13T19:00:01Z")

</div>

> [@LounesAl](#):
>
> when a preset is changed

May be there’s a cleaner way to do this, but the following should work however:

```auto
presetComboBox = slicer.util.mainWindow().findChild(slicer.qSlicerVolumeRenderingPresetComboBox, "PresetComboBox")
presetComboBox.connect("currentNodeIDChanged(QString)", yourFunction)

```

‘`yourFunction`’ will receive a preset ID, which you can follow to get the name.

_BTW, I just noticed that the preset combobox does not select the chosen preset actually; that’s on preview in Linux. It is indeed selected in 5.6._

---

<div class="post-metadata">

### Author: ![LounesAl](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lounesal/32/78861_2.png) [@LounesAl](https://discourse.slicer.org/u/LounesAl)
#### Post date: [December 16, 2024, 4:45pm UTC](https://discourse.slicer.org/t/how-to-enable-maximum-intensity-projection-mip-automatically-for-mrml-presets/40679/5 "2024-12-16T16:45:52Z")

</div>

Thank you for your suggestion! Unfortunately, this line of code

```python
presetComboBox = slicer.util.mainWindow().findChild(slicer.qSlicerVolumeRenderingPresetComboBox, "PresetComboBox")

```

is not working in my case. The `presetComboBox` is returning `None`, so it seems the `PresetComboBox` is either not found or not available in my setup.

I’ve tried listing all child objects under `slicer.util.mainWindow()` but couldn’t locate it there. Could it be named differently or located somewhere else, like within the Volume Rendering module widget? Any additional pointers would be appreciated!

---

<div class="post-metadata">

### Author: ![chir.set](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/chir.set/32/66982_2.png) [@chir.set](https://discourse.slicer.org/u/chir.set)
#### Post date: [December 16, 2024, 5:55pm UTC](https://discourse.slicer.org/t/how-to-enable-maximum-intensity-projection-mip-automatically-for-mrml-presets/40679/6 "2024-12-16T17:55:34Z")

</div>

```auto
w = getModuleWidget("VolumeRendering")
presetComboBox = w.findChild(slicer.qSlicerVolumeRenderingPresetComboBox, "PresetComboBox")

```

should work. It’s quick and dirty, but does help.

It’s likely that the previous code needs the VolumeRendering module to have been shown once.

---

<div class="post-metadata">

### Author: ![LounesAl](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lounesal/32/78861_2.png) [@LounesAl](https://discourse.slicer.org/u/LounesAl)
#### Post date: [December 17, 2024, 10:43am UTC](https://discourse.slicer.org/t/how-to-enable-maximum-intensity-projection-mip-automatically-for-mrml-presets/40679/7 "2024-12-17T10:43:48Z")

</div>

Thank you for the help! I managed to get it working with this approach:

```python
def OnPresetChanged(ID: str):
    """Automatically switch to MIP when a preset is changed."""
    vrLogic = slicer.modules.volumerendering.logic()
    presetsScene = vrLogic.GetPresetsScene()
    vrNodes = presetsScene.GetNodesByClass("vtkMRMLVolumePropertyNode")
    for i in range(vrNodes.GetNumberOfItems()):
        node = vrNodes.GetItemAsObject(i)
        if node.GetID() == ID:
            raycastTechnique = "Max" if node.GetName().lower().endswith("max") else "Composite"
            SetRaycastTechnique(raycastTechnique)
            break

w = slicer.util.getModuleWidget("VolumeRendering")
presetComboBox = w.findChild(slicer.qSlicerVolumeRenderingPresetComboBox, "PresetComboBox")
presetComboBox.connect("currentNodeIDChanged(QString)", OnPresetChanged)

```

I made sure that the presets I want to activate MIP for have “Max” at the end of their names. This works well, but I’m sure there’s a cleaner or more efficient way to achieve this. Let me know if you have any suggestions!
