# Is it better to integrate settings from Module B into Module A for improved user workflow (or user convenience)?

**URL:** <https://discourse.slicer.org/t/is-it-better-to-integrate-settings-from-module-b-into-module-a-for-improved-user-workflow-or-user-convenience/41189>\
**Category:** Development\
**Created:** [January 21, 2025, 11:34am UTC](https://discourse.slicer.org/t/is-it-better-to-integrate-settings-from-module-b-into-module-a-for-improved-user-workflow-or-user-convenience/41189 "2025-01-21T11:34:07Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![shahrokh](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/shahrokh/32/1499_2.png) [@shahrokh](https://discourse.slicer.org/u/shahrokh)\
**Post date:** [January 21, 2025, 11:34am UTC](https://discourse.slicer.org/t/is-it-better-to-integrate-settings-from-module-b-into-module-a-for-improved-user-workflow-or-user-convenience/41189/1 "2025-01-21T11:34:07Z")

</div>

Hello Dear Developers and Users,

I wanted to get some advice on an issue.  
Suppose I am trying to develop a module named **A** , where one of the inputs of Module **A** is the output from another module, Module **B** which has already been developed. In this case, I could develop Module **A** completely independently. However, this would mean that the user would first need to go to Module **B** to generate its output, which is required as an input for Module **A**. Then, user would have to go to Module **A** and select the output from Module **B** as one of the inputs before running it.

My question is: for the sake of user convenience, would it be logical to integrate the settings/options of Module **B** directly into Module **A** , so that the user doesn’t need to first run Module **B** and then go to Module **A**?

Maybe it will be clearer if I explain with an example. In the implementation of Module **A** , I need the output from the **Isodose** module, specifically the _ **Number of iso levels** _ and _ **Labels** _ (which seem to be in terms of **Dose (Gy)** in **Iso levels table** ) which need to be set or adjusted by the user. Can I add these two inputs from the **Isodose** panel (including _ **number of iso levels** _ and _ **Label** _ (in Gy)) as _Spin boxes_ to the panel of Module **A** so that when Module **A** runs, the **Isodose** module will be executed in the background?

In this regard, I realized that it is possible to access the **Isodose** module in the _Python Interactor_ using `slicer.util.getModule('Isodose')`. There is also a method called `setProperty`. Can I achieve my goal by specifying the arguments of this method?

 ![1](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/2/9/29c3dabcf69a50491156e730d74110364ef754ac.png)

Best regards.  
Shahrokh

---

<div class="post-metadata">

**Author:** ![shahrokh](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/shahrokh/32/1499_2.png) [@shahrokh](https://discourse.slicer.org/u/shahrokh)\
**Post date:** [January 22, 2025, 12:31pm UTC](https://discourse.slicer.org/t/is-it-better-to-integrate-settings-from-module-b-into-module-a-for-improved-user-workflow-or-user-convenience/41189/2 "2025-01-22T12:31:53Z")

</div>

Regarding this issue, I came across a question titled [Call SlicerRT Isodose (or create isodoses) from python](https://discourse.slicer.org/t/call-slicerrt-isodose-or-create-isodoses-from-python/4506) which was asked in the 3DSlicer Community.

I realized that in the Python Interactor, in addition to the `slicer.util.getModule` method which I mentioned in my previous message, there is another method called `slicer.util.getModuleLogic` that seems to provide access to the settings (logic) of modules, including **Isodose** module. In other words, it seems that the `getModuleLogic` method in `slicer.util` is used for setting the settings of modules.

According to the help provided for the `SetNumberOfIsodoseLevels` method, it seems that this method takes two input arguments: a `vtkMRMLIsodoseNode` type and an `integer`.

 ![Screenshot from 2025-01-22 15-45-45](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/2/3/23aa647d0bda0ffa37784c7e0c8f851a7aebc1a7.png)

The following commands were executed.

```auto
>>> object_vtkMRMLIsodoseNode = slicer.vtkMRMLIsodoseNode().CreateNodeInstance()
>>> type(object_vtkMRMLIsodoseNode)
<class 'vtkSlicerIsodoseModuleLogic.vtkMRMLIsodoseNode'>
>>> numberOfColors = 1
>>> myIsodose = slicer.util.getModuleLogic('Isodose').SetNumberOfIsodoseLevels(object_vtkMRMLIsodoseNode, numberOfColors)
>>> type(myIsodose)
<class 'NoneType'>
>>> myIsodose. __dir__ ()
[' __repr__', ' __bool__', ' __new__', ' __doc__', ' __hash__', ' __str__', ' __getattribute__', ' __setattr__', ' __delattr__', ' __lt__', ' __le__', ' __eq__', ' __ne__', ' __gt__', ' __ge__', ' __init__', ' __reduce_ex__', ' __reduce__', ' __subclasshook__', ' __init_subclass__', ' __format__', ' __sizeof__', ' __dir__', ' __class__']
>>> 

```

It seems that there was no syntax error when executing the above commands, but since the output type is` NoneType`, it seems that a logical error must have occurred.

Please guide me on how to implement the settings of the **Isodose** module in Python so that I can generate the output of this module by taking the RTDose input.

Best regards.  
Shahrokh.

---

<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:** [January 22, 2025, 6:55pm UTC](https://discourse.slicer.org/t/is-it-better-to-integrate-settings-from-module-b-into-module-a-for-improved-user-workflow-or-user-convenience/41189/3 "2025-01-22T18:55:34Z")

</div>

Looks like you are on the right track. `SetNumberOfIsodoseLevels` returns `None` because it just sets the value. You should be able to call `SetNumberOfIsodoseLevels` or something similar to confirm that it was set.

On the more general topic, yes, reusing the Logic classes from other modules is definitely the right way of doing things. Also, several modules expose widgets that can be reused in other modules although not all do. You can also include buttons that take you directly to another module, perhaps with some parameters pre-selected, which is sometimes useful.

---

<div class="post-metadata">

**Author:** ![shahrokh](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/shahrokh/32/1499_2.png) [@shahrokh](https://discourse.slicer.org/u/shahrokh)\
**Post date:** [February 16, 2025, 11:56am UTC](https://discourse.slicer.org/t/is-it-better-to-integrate-settings-from-module-b-into-module-a-for-improved-user-workflow-or-user-convenience/41189/4 "2025-02-16T11:56:02Z")

</div>

Thank you for your helpful response! I appreciate the guidance you’ve provided.

Regarding my progress, I believe I have successfully set up the Isodose module settings through the Python Interactor with the following commands:

```auto
object_vtkMRMLIsodoseNode = slicer.vtkMRMLIsodoseNode().CreateNodeInstance()
object_vtkMRMLIsodoseNode.SetReferenceDoseValue(47)
object_vtkMRMLIsodoseNode.GetReferenceDoseValue()
object_vtkMRMLIsodoseNode = slicer.vtkMRMLIsodoseNode().CreateNodeInstance()
object_vtkMRMLIsodoseNode.SetDoseUnits(slicer.vtkMRMLIsodoseNode.Gy)
object_vtkMRMLIsodoseNode.SetShowDoseVolumesOnly(1)

```

Now, I want to apply the `object_vtkMRMLIsodoseNode` settings to a node of type `RTDose`. I am using the following command to retrieve the node:

```auto
doseNode = slicer.util.getFirstNodeByClassByName('vtkMRMLScalarVolumeNode', '2: RTDOSE: DOSIsoft:RTDOSE:Phase #1 Dosi Dosi 1: Beam setup 1 (GY) [11]: Beam setup 1')

```

However, I have not been able to find a method within `object_vtkMRMLIsodoseNode` that can perform the “Generate Isodose” operation. Could you please help me on the method to use for this?

Best regards.  
Shahrokh.

---

<div class="post-metadata">

**Author:** ![shahrokh](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/shahrokh/32/1499_2.png) [@shahrokh](https://discourse.slicer.org/u/shahrokh)\
**Post date:** [February 17, 2025, 12:43pm UTC](https://discourse.slicer.org/t/is-it-better-to-integrate-settings-from-module-b-into-module-a-for-improved-user-workflow-or-user-convenience/41189/5 "2025-02-17T12:43:19Z")

</div>

I used the following commands to solve this problem:

```auto
# Get the dose node
doseVolmeNode = slicer.util.getFirstNodeByClassByName('vtkMRMLScalarVolumeNode', '2: RTDOSE: DOSIsoft:RTDOSE:Phase #1 Dosi Dosi 1: Beam setup 1 (GY) [11]: Beam setup 1')

# Create the isodose node
object_vtkMRMLIsodoseNode = slicer.vtkMRMLIsodoseNode().CreateNodeInstance()

# Initial isodose settings (Similar to the settings of the Isodose module)
object_vtkMRMLIsodoseNode.SetReferenceDoseValue(47)
object_vtkMRMLIsodoseNode.SetDoseUnits(slicer.vtkMRMLIsodoseNode.Gy)
object_vtkMRMLIsodoseNode.SetShowDoseVolumesOnly(1)
object_vtkMRMLIsodoseNode.SetAndObserveDoseVolumeNode(doseVolmeNode)

# Create isodose surface
isodose_logic = slicer.modules.isodose.logic()
modelDose47 = isodose_logic.CreateIsodoseSurfaces(object_vtkMRMLIsodoseNode)

```

However, I still cannot get the two results below:

1. The model that is seen in the 3D window with the `Isodose` module, as shown in the image below.  

2. In the Data module, a node named IsodoseLevel\_47Gy has been created. The image below:  

Please guide me.  
Best regards.  
Shahrokh

---

<div class="post-metadata">

**Author:** ![shahrokh](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/shahrokh/32/1499_2.png) [@shahrokh](https://discourse.slicer.org/u/shahrokh)\
**Post date:** [February 18, 2025, 6:09am UTC](https://discourse.slicer.org/t/is-it-better-to-integrate-settings-from-module-b-into-module-a-for-improved-user-workflow-or-user-convenience/41189/6 "2025-02-18T06:09:28Z")

</div>

Sorry… As I mentioned in the previous message, I first set the parameters of the Isodose module in the object named object\_vtkMRMLIsodoseNode from the vtkMRMLIsodoseNode class. Then, I applied it to a dose volume node named doseVolumeNode. Today, I realized (in the error log display) that the issue seems to be in this last step. The image below shows this error.

 ![Screenshot from 2025-02-18 09-12-11](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/8/2/82004207a99d014cb51f15914968613e49aa6564.png)

As can be seen, after running this command:  
`object_vtkMRMLIsodoseNode.SetAndObserveDoseVolumeNode(doseVolumeNode)`  
I get this error message:

```auto
Python console user input: object_vtkMRMLIsodoseNode.SetAndObserveDoseVolumeNode(doseVolumeNode)
Cannot set reference: the referenced and referencing node are not in the same scene

```

Sorry, I don’t understand the meaning of the phrase **Cannot set reference: the referenced and referencing node are not in the same scene.**.

Best regards.  
Shahrokh

---

<div class="post-metadata">

**Author:** ![shahrokh](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/shahrokh/32/1499_2.png) [@shahrokh](https://discourse.slicer.org/u/shahrokh)\
**Post date:** [February 18, 2025, 11:10am UTC](https://discourse.slicer.org/t/is-it-better-to-integrate-settings-from-module-b-into-module-a-for-improved-user-workflow-or-user-convenience/41189/7 "2025-02-18T11:10:29Z")

</div>

Excuse me…  
I was able to move one more step forward. Instead of using the command

```auto
myIsodoseSurface = slicer.vtkSlicerIsodoseModuleLogic().CreateIsodoseSurfaces(object_vtkMRMLIsodoseNode)

```

I executed the following command (as mentioned in the guidance provided in question of [Call SlicerRT Isodose (or create isodoses) from python](https://discourse.slicer.org/t/call-slicerrt-isodose-or-create-isodoses-from-python/4506/7)):

```auto
myIsodoseSurface = slicer.modules.isodose.logic().CreateIsodoseSurfaces(object_vtkMRMLIsodoseNode)

```

Therefore, the full commands executed are as follows:

```auto
doseVolumeNode = slicer.util.getFirstNodeByClassByName('vtkMRMLScalarVolumeNode', '2: RTDOSE: DOSIsoft:RTDOSE:Phase #1 Dosi Dosi 1: Beam setup 1 (GY) [11]: Beam setup 1')
object_vtkMRMLIsodoseNode = slicer.vtkMRMLIsodoseNode().CreateNodeInstance()
object_vtkMRMLIsodoseNode.SetScene(doseVolumeNode.GetScene())
object_vtkMRMLIsodoseNode.SetReferenceDoseValue(47)
object_vtkMRMLIsodoseNode.SetDoseUnits(slicer.vtkMRMLIsodoseNode.Gy)
object_vtkMRMLIsodoseNode.SetAndObserveDoseVolumeNode(doseVolumeNode)
#myIsodoseSurface = slicer.vtkSlicerIsodoseModuleLogic().CreateIsodoseSurfaces(object_vtkMRMLIsodoseNode)
myIsodoseSurface = slicer.modules.isodose.logic().CreateIsodoseSurfaces(object_vtkMRMLIsodoseNode)

```

As you can see in the image below,

 ![Screenshot from 2025-02-18 14-27-29](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/4/5/453addf9589426cf63cc73ecc726d138afd0bb3e.png)

similar to the `Isodose` module execution, which produces a model output placed in a folder, when running the command of:

```auto
myIsodoseSurface = slicer.modules.isodose.logic().CreateIsodoseSurfaces(object_vtkMRMLIsodoseNode)

```

this folder is also created, but it is empty, and the 3DSlicer environment completely freezes, to the point where none of the icons in the red, yellow, or green windows are selectable. In the end, I have to close 3DSlicer.

I think I am getting closer to my answer.  
Please guide me.  
Best regards.  
Shahrokh.

---

<div class="post-metadata">

**Author:** ![shahrokh](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/shahrokh/32/1499_2.png) [@shahrokh](https://discourse.slicer.org/u/shahrokh)\
**Post date:** [February 19, 2025, 12:06pm UTC](https://discourse.slicer.org/t/is-it-better-to-integrate-settings-from-module-b-into-module-a-for-improved-user-workflow-or-user-convenience/41189/8 "2025-02-19T12:06:31Z")

</div>

I think I was mostly successful. The problem I mentioned in my previous message (the freezing of the 3DSlicer display environment, such as 3D view) was because I hadn’t set up its color table. Based on this, the commands became as follows.

```auto
# Get the dose volume node by class and name
doseVolumeNode = slicer.util.getFirstNodeByClassByName('vtkMRMLScalarVolumeNode', '2: RTDOSE: DOSIsoft:RTDOSE:Phase #1 Dosi Dosi 1: Beam setup 1 (GY) [11]: Beam setup 1')

# Create a new Isodose node instance for displaying isodose surfaces
object_vtkMRMLIsodoseNode = slicer.vtkMRMLIsodoseNode().CreateNodeInstance()

# Set the scene for the isodose node to match the dose volume node's scene
object_vtkMRMLIsodoseNode.SetScene(doseVolumeNode.GetScene())

# Set the dose units to Gray (Gy)
object_vtkMRMLIsodoseNode.SetDoseUnits(slicer.vtkMRMLIsodoseNode.Gy)

# Set the reference dose value (in Gy) for isodose levels
object_vtkMRMLIsodoseNode.SetReferenceDoseValue(47.00)

# Observe the dose volume node to track its changes
object_vtkMRMLIsodoseNode.SetAndObserveDoseVolumeNode(doseVolumeNode)

# Setup the color table for the isodose node based on the dose volume
slicer.modules.isodose.logic().SetupColorTableNodeForDoseVolumeNode(doseVolumeNode)

# Create isodose surfaces based on the configured isodose node
slicer.modules.isodose.logic().CreateIsodoseSurfaces(object_vtkMRMLIsodoseNode)

```

As can be seen in the commands above, I want the number of iso levels to be **one** , and the isodose surface to be generated for a dose of **47.00 Gy**. When I run these commands, the following result occurs.

 ![Screenshot from 2025-02-19 15-29-40](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/a/a/aaa61b2cafb975aa0b6d85ba8355f194e50043cb.png)

as shown above, This result is exactly the same as the default settings of the Isodoses module, meaning the number of iso levels is 6, and the dose values are 5, 10, 15, 20, 25, and 30 Gy. In other words, the value I set with the above commands (47.00 Gy) has essentially had no effect here.

I don’t know where the problem is from. I hope you can guide me, and until then, I will continue with my efforts.  
Please guide me.  
Best regards.  
Shahrokh
