Advanced Tutorial Macro Macro modules Global Macro Python Scripting

Example 3: Creating a simple application

Introduction

In the previous examples, you already learned how to create macro modules, user interfaces and how to interact with your UI via Python scripting.

In this example, you will learn how to create a simple Prototype application in MeVisLab including a User Interface with 2D and 3D viewer. You will learn how to implement field listeners and react on events.

Steps to do

Create your network

Start with an empty network and add the Module ImageLoad to your workspace. Then add a View2D and View3D to your workspace and connect the modules as seen below.

Loading and viewing images

Loading and viewing images

Load an image

Now double-click Left Mouse Button on the ImageLoad module and open any image. You can use the included file ./MeVisLab/Resources/DemoData/MRI_Head.dcm.

Opening your viewers should now show the images in 2D and 3D.

Show images in 2D and 3D

Show images in 2D and 3D

Save your network

Now, save your network as *.mlab file and remember the location.

Create a macro module

Open the Project Wizard via [ File → Run Project Wizard ] and run Wizard for a macro module. Name your module MyViewerApplication, enter your details and click Next >.

Module Properties

Module Properties

On the next screen, make sure to add a Python file and use the existing network you previously saved. Click Next >.

Macro module Properties

Macro module Properties

You can leave all fields empty for now and just click Create.

Module Field Interface

Module Field Interface

MeVisLab reloads its internal database and you can open a new Tab. Search for your newly created module, in our case it was MyViewerApplication.

MyViewerApplication

MyViewerApplication

In case you double-click Left Mouse Button your module now, you will see the Automatic Panel only showing the name of your module, because we did not add any own Window until now.

Develop your User Interface

Before adding your own UI, open internal network of your macro module via right-click Right Mouse Button and [ Show Internal Network ]. Open the panel of your ImageLoad module and set filename to an empty string (clear). This is necessary for later.

Now, right-click on your MyViewerApplication and select [ Related Files → MyViewerApplication.script ]

MATE opens showing your script file. You already learned how to create simple UI elements in Example 2.4. Now we will create a little more complex UI including your View2D and View3D.

First we need a new Field in your Parameters section. Name the field filepath and set internalName to ImageLoad.filename.

MyViewerApplication.script

Interface {
  Inputs {}
  Outputs {}
  Parameters {
    Field filepath {
      internalName = ImageLoad.filename
    }
  }
}

We now re-use the filepath field from the ImageLoad module for our interface. Add a Window and a Vertical to the bottom of your *.script file. Add the just created parameter field filepath inside your Vertical as seen below.

MyViewerApplication.script

Interface {
  Inputs {}
  Outputs {}
  Parameters {
    Field filepath {
      internalName = ImageLoad.filename
    }
  }
}

Commands {
  source = $(LOCAL)/MyViewerApplication.py
}

Window {
  Vertical {
    Field filepath {}
  }
}

If you now double-click Left Mouse Button on your module, you can see your just created filepath field.

Filepath field in UI

Filepath field in UI

Next, we will add your 2D and 3D Viewers and a Button to your Window. Change your *.script file as seen below:

MyViewerApplication.script

Window {
  Vertical {
    Horizontal {
      Field filepath {}
      Button {
        title = "Reset"
        
      }
    }
    Horizontal {
      Viewer View2D.self {
        type    = SoRenderArea
        pw      = 400 ph = 400
        expandX = yes
        expandY = yes
      }
      Viewer View3D.self {
        pw      = 400 ph = 400
        expandX = yes
        expandY = yes
      }
    }
  }
}

We have a vertical Layout having 2 items placed horizontally next to each other. The new Button gets the title Reset but does nothing, yet because we did not add a Python function to a command.

Additionally we added the View2D and the View3D to our Window and defined the height, width and the expandX/Y property to yes. This leads our viewers to resize together with our Window.

You can now play around with your module in MeVisLab SDK. Open the Window and select a file. You can see the 2 viewers showing the 2D and 3D images. You can interact with your viewers the same way as in your MeVisLab network. All functionalities are taken from the modules and transferred to your user interface.

2D and 3D viewers in our application

2D and 3D viewers in our application

Develop a python function for your Button

Next we want to reset the filepath to an empty string on clicking our Reset button. Add the reset command to your Button.

MyViewerApplication.script

...
Button {
  title = "Reset"
  command = reset
}
...

Right-click Left Mouse Button on reset and select [ Create Python function 'reset' ]. MATE opens the Python file of your module and automatically adds the function definition. Set the filename of the ImageLoad module to an empty string.

MyViewerApplication.py

from mevis import *

def reset():
  ctx.field("filepath").value = ""

Clicking on Reset in your module now clears the filename field and the viewers do not show any images anymore.

Field listeners

A field listener watches a given field in your network and reacts on any changes of the field value. You can define Python functions to execute in case a change has been detected.

In order to define such a listener, you need to add it to the Commands section in your *.script file.

Example:

MyViewerApplication.script

Commands {
    source = $(LOCAL)/MyViewerApplication.py

    FieldListener View2D.startSlice {
        command = printCurrentSliceNumber
    }
}

In the above example, we react on changes of the field startSlice of the module View2D. Whenever the field value (currently displayed slice) changes, the Python function printCurrentSliceNumber is executed.

In your Python file Filter.py you can now add the following:

Filter.py

def printCurrentSliceNumber(field):
    MLAB.log(field.value)

Scrolling through slices in the View2D module now logs a message containing the slice number currently visible to the MeVisLab Debug Output.

Summary

  • You can add any Viewers to your application UI by reusing them in MDL.
  • Parameter Fields using the internalName of an existing field in your network allows re-using this UI element in your own UI. Changes in your UI are applied to the field in the module.
  • Field Listeners allow reacting on changes of a field value in Python.