The ApplicationController

Some more advanced features are only available through an imfusion.ApplicationController. It manages loaded data, can visualize data and records executed algorithms, among other things.

If you are using the embedded Python interpreter of the ImFusionSuite, a imfusion.ApplicationController is already instantiated. Otherwise we create a imfusion.ConsoleController which is a special controller that does not provide or require a GUI:

>>> if not imfusion.app:
...     imfusion.app = imfusion.ConsoleController()

All the previously introduced functions are independent of the imfusion.ApplicationController but some can also be called on the imfusion.ApplicationController instance with some additional side effects:

>>> imfusion.app.open('ct_image.png')
[imfusion.SharedImageSet(size: 1, [imfusion.SharedImage(USHORT width: 512 height: 512 spacing: 0.661813x0.661813x1 mm)])]

If you executed the previous code in the ImFusionSuite, you might have noted that the image is directly displayed in the main view area. This is because the data gets automatically added to the imfusion.DataModel. This is not the case if you load data with imfusion.io.open().

DataModel

The imfusion.DataModel stores all data that is managed by the imfusion.ApplicationController and you can retrieve, add or delete data from it:

>>> dm = imfusion.app.data_model
>>> len(dm)
1
>>> img = dm[0]
>>> img
imfusion.SharedImageSet(size: 1, [imfusion.SharedImage(USHORT width: 512 height: 512 spacing: 0.661813x0.661813x1 mm)])

Be careful when removing data: Since the data is owned by the underlying C++ framework, Python cannot track the lifetime of the data. This means that any variable still referring a deleted data might lead to a crash.

When adding data created in Python to the imfusion.DataModel it will get copied. The reference to the copy is returned:

>>> new_img = imfusion.SharedImageSet(np.zeros([1, 8, 8, 8, 1], dtype=np.uint8))
>>> new_img = dm.add(new_img)

Running algorithms

We can also execute algorithms directly on the imfusion.ApplicationController. Any output data will then be added automatically to the imfusion.DataModel:

>>> imfusion.app.execute_algorithm('Base.MorphologicalOperations', [img])
[imfusion.SharedImageSet(size: 1, [imfusion.SharedImage(USHORT width: 512 height: 512 spacing: 0.661813x0.661813x1 mm)])]
>>> len(dm)
2

The imfusion.ApplicationController will also keep track of all executed algorithms. You can save the algorithm history in the ImFusionSuite as a workspace (.iws) and replay the algorithms with the same settings. Check the C++ documentation for more details about workspaces.

Instead of executing the algorithm right away, we can also just open it:

>>> imfusion.app.add_algorithm('Base.MorphologicalOperations', [img])
<imfusion._bindings.BaseAlgorithm object at...>

This returns a reference to the algorithm instance and will open the corresponding UI element (which we call “Algorithm Controller”) in the ImFusionSuite.

Recommendations

If you are only writing simple scripts, you most likely don’t need the added complexity of the imfusion.ApplicationController and should use the functions that don’t require it like imfusion.execute_algorithm(). Also if you write custom algorithm, you should not rely on imfusion.app being available.

If, on the other hand, you are using Python in combination with the ImFusionSuite application, the imfusion.ApplicationController interface is much more convenient.