Contour Example 7: Using the CSOListContainer
Introduction
In this example, we are using the module CSOListContainer instead of the CSOManager. The CSOManager is a heavyweight, UI driven module. You can use it to see all of your CSOs and CSOGroups in the module panel. The CSOListContainer is a lightweight module with focus on Python scripting. We recommend to use this module for final application development, because Python provides much more flexibility in handling CSO objects.
We will create multiple CSOs by using the SoCSOEllipseEditor and dynamically add these CSOs to different groups via Python scripting depending on their area. CSOs larger than a configurable threshold will be drawn in red, smaller CSOs will be drawn in green. The colors will also be adapted if we manually resize the contours.
Steps to Do
Develop Your Network
Add a LocalImage and a View2D module to your workspace and connect them as shown below. Load the file ProbandT1.dcm from MeVisLab demo data. In order to create contours (CSOs), we need a SoView2DCSOExtensibleEditor module. It manages attached CSO editors, renderers, and offers an optional default renderer for all types of CSOs.
Add a SoCSOEllipseEditor and a CSOListContainer to the SoView2DCSOExtensibleEditor
You are now able to draw CSOs.
Create a separate directory for this tutorial and save your network in this empty directory. This makes the final structure easier to read.
Create a Local Macro Module
Select the module CSOListContainer and open menu [
File
→
Create Local Macro
]. Enter some details about your new local macro module and click
The appearance of the CSOListContainer module changes, because it is a macro module named csoList now.

The behavior of your network does not change. You can still draw the same CSOs and they are still managed by the CSOListContainer module. The reason why we created a local macro with a single module inside is that we want to add Python scripting to the module. Python scripts can only be added to macro modules.
Open the context menu of your csoList module
and select [
Related Files
→
csoList.script
].
The MeVisLab text editor MATE opens, showing your .script file. You can see the output of your module as CSOListContainer.outCSOList. We want to define a threshold for the color of our CSOs. For this, add another field to the Parameters section of your script file named
In order to call Python functions, we also need a Python file. Add a Commands section and define the source of the Python file as $(LOCAL)/csoList.py. Also add an
csoList.script
Interface {
Inputs {}
Outputs {
Field baseOut0 {
internalName = CSOListContainer.outCSOList
}
}
Parameters {
Field areaThreshold { type = Float value = 2000.0 }
}
}
Commands {
source = $(LOCAL)/csoList.py
initCommand = initCSOList
}
Right-click
on the
Back in MeVisLab, the new field
Write Python Script
Whenever the local macro module is added to the workspace or reloaded, new CSOLists shall be created and we need a possibility to update the lists whenever a new CSO has been created or existing contours changed.
Define a function
csoList.py
def setupCSOList():
csoList = _getCSOList()
csoList.removeAll()
csoGroupSmall = csoList.addGroup("small")
csoGroupLarge = csoList.addGroup("large")
csoGroupSmall.setUsePathPointColor(True)
csoGroupSmall.setPathPointColor((0, 1, 0))
csoGroupLarge.setUsePathPointColor(True)
csoGroupLarge.setPathPointColor((1, 0, 0))
def _getCSOList():
return ctx.field("CSOListContainer.outCSOList").object()
The function gets the current CSOList from the output field of the CSOListContainer. Initially, it should be empty. If not, we want to start with an empty list; therefore, we remove all existing CSOs.
We also create two new CSOGroups: one list for small contours, one list for larger contours, depending on the defined
Additionally, we also want to define different colors for the CSOs in the lists. Small contours shall be drawn in green, large contours shall be drawn in red.
In order to listen for changes on the contours, we need to register for notifications. Create a new function
csoList.py
def registerForNotification():
csoList = _getCSOList()
csoList.registerForNotification(csoList.NOTIFICATION_CSO_FINISHED, ctx, "csoFinished")
def csoFinished(_arg):
csoList = _getCSOList()
for cso in csoList.getCSOs():
cso.removeFromAllGroups()
csoArea = cso.getArea()
csoGroup = csoList.getGroupByLabel("large")
if csoArea <= _getAreaThreshold():
csoGroup = csoList.getGroupByLabel("small")
csoGroup.addCSO(cso.getId())
def _getAreaThreshold():
return ctx.field("areaThreshold").value
The function gets all currently existing CSOs from the CSOListContainer. Then, we register for notifications on this list. Whenever the notification NOTIFICATION_CSO_FINISHED is sent in the current context, we call the function
The
The function
Now, we can call our functions in the
csoList.py
def initCSOList():
setupCSOList()
registerForNotification()
def setupCSOList():
csoList = _getCSOList()
csoList.removeAll()
csoGroupSmall = csoList.addGroup("small")
csoGroupLarge = csoList.addGroup("large")
csoGroupSmall.setUsePathPointColor(True)
csoGroupSmall.setPathPointColor((0, 1, 0))
csoGroupLarge.setUsePathPointColor(True)
csoGroupLarge.setPathPointColor((1, 0, 0))
def registerForNotification():
csoList = _getCSOList()
csoList.registerForNotification(csoList.NOTIFICATION_CSO_FINISHED, ctx, "csoFinished")
def csoFinished(_arg):
csoList = _getCSOList()
for cso in csoList.getCSOs():
cso.removeFromAllGroups()
csoArea = cso.getArea()
csoGroup = csoList.getGroupByLabel("large")
if csoArea <= _getAreaThreshold():
csoGroup = csoList.getGroupByLabel("small")
csoGroup.addCSO(cso.getId())
def _getAreaThreshold():
return ctx.field("areaThreshold").value
def _getCSOList():
return ctx.field("CSOListContainer.outCSOList").object()
If you now draw contours, they are automatically colored depending on their area. You can also edit existing contours and the color is adapted.
Summary
- The module
CSOListContainerprovides a lightweight container to manage contours. - It makes sense to encapsulate a single module into a macro module to provide additional functionalities via Python scripting.
- Notifications can be used to react on events.
Download Archive here.







