Documentation/Nightly/Developers/OpenIGTLinkIF
For the latest Slicer documentation, visit the read-the-docs. |
This page provides developer's information for 3D Slicer's OpenIGTLink IF module.
Contents
Creating external OpenIGTLink server/client software
With the OpenIGTLink IF module, you can exchange various types of data (e.g. linear transforms and images) between 3D Slicer and external software over the local area network. We provide OpenIGTLink Library to support OpenIGTLink-compatible software. Please refer the Tutorial.
Controlling OpenIGTLink IF from Python module
You can use the OpenIGTLink IF module's features from 3D Slicer's Python interface. The features can be called from both Slicer Python Interactor (Python console) and Python module.
Requirements
- 3D Slicer 4.2 nightly build (November 10, 2012 or later) available at http://slicer.org/ (4.2.0 release version has an issue in initialization of the OpenIGTLinkIF module. If you use this version, you need to open the OpenIGTLinkIF module, before using the Python interface)
- OpenIGTLink Simulators available in NA-MIC wiki or the OpenIGTLink Library
Creating an OpenIGTLink connector node from Python Interactor
To establish an OpenIGTLink connection, first you need to create an OpenIGTLink connector node (vtkMRMLIGTLConnectorNode). From Python Interactor:
>>> cnode = slicer.vtkMRMLIGTLConnectorNode() >>> slicer.mrmlScene.AddNode(cnode) (vtkMRMLIGTLConnectorNode)0x125e6ce10
You may name the connector as follows:
>>> cnode.SetName('Connector1')
If the connector node is properly added to the scene, you could see it in the Connector list in the OpenIGTLink IF module.
Importing a linear transform to external software (3D Slicer as a client)
Suppose the downloaded simulator files are in <working directory>.
First, launch the "TrackerServer" simulator from a terminal (or a command prompt on Windows) and ask to wait for a connection from the 3D Slicer at port # 18944. The frame rate for sending linear transforms is set to 10 frames/sec
$ cd <working directory> $ ./TrackerServer 18944 10
Then open the Python Interactor and type in the following commands to configure the connector node as a client:
>>> cnode.SetTypeClient('localhost', 18944) 1
Make sure that cnode.SetTypeClient() function returns 1. Then, start the client by:
>>> cnode.Start() 1
If the connector node is successfully connected to the TrackerServer, you will start seeing 4x4 matrices printed on the terminal every 100 ms. You could also confirm in the Transform module that those matrices are imported to a linear transform node in the scene. Open "Transform" module and select "Tracker" from "Active Transform" menu.
Exporting a linear transform to external software (3D Slicer as a client)
Suppose the simulator files are in <working directory>.
First, launch the "ReceiveServer" simulator from the terminal (or the command prompt on Windows) and ask to wait for a connection from the 3D Slicer at port # 18944.
$ cd <working directory> $ ./ReceiveServer 18944
Then open the Python Interactor and type in the following command to configure the connector node as a client:
>>> cnode.SetTypeClient('localhost', 18944) 1
Make sure that cnode.SetTypeClient() function returns 1. Then, start the client by:
>>> cnode.Start() 1
Now the connector is connected to the ReceiveServer. You can confirm it from the Connector list in the OpenIGTLink IF module. If it is connected, the "Status" of the connector must be "ON".
The next step is to create a linear transform node to export. You can create it from "Transform" module, or from the Python Interactor:
>>> tnode = slicer.vtkMRMLLinearTransformNode() >>> slicer.mrmlScene.AddNode(tnode) (vtkMRMLLinearTransformNode)0x125e6cf70 >>>
If you created the transform node from the Transform module, you need to get the node object in the Python Interactor. To do so, open "Data" module, click the "Display MRML ID's" under the "Nodes" interface, and check the node ID written on the right end of the "Nodes" interface. If the transform node is the first node you created after launching 3D Slicer, the node ID is usually "vtkMRMLLinearTransformNode4". You can obtain the node object in the Python Interactor by using GetNodeByID() function:
>>> tnode = slicer.mrmlScene.GetNodeByID('vtkMRMLLinearTransformNode4')
Now it's ready for the connector node to observe the transform node. Register the transform node to the connector as an outgoing data:
>>> cnode.RegisterOutgoingMRMLNode(tnode) 1 >>>
You may check from "I/O Configuration" in the OpenIGTLinkIF module if the linear transform node is registered as a OUTGOING node. (The linear transform node should be under "OUT" branch of the connector node.)
Let's try updating the transform node. Open the "Transform" module, choose the linear transform node from "Active Transform" and drag any of translation/rotation sliders. While you are dragging those sliders, you will see 4x4 matrices are shown on the terminal that runs "ReceiveServer."
To close the connection, you may call:
>>> cnode.Stop()
Extended Interface for External Software (Ideas)
There has been discussion how to send extra data (data that are not defined as MRML nodes) to 3D Slicer through OpenIGTLink [1]. For example, some developers are interested in sending switch status for their tracking devices. Here are some notes and ideas
- Extra information in MRML scene
- Extra information can be stored in key/value array format as "attributes" in MRML nodes.
- Slicer developers use "ModuleName.attribute" as a key.
- With an MRML node, the OpenIGTLink IF module can notify other modules that the attribute has been updated through Event mechanism in 3D Slicer.
- Extra information in OpenIGTLink IF
- There is no mechanism to add any attribute information with existing data format. The challenge is to maintain the current rule (the message name and type corresponds to the MRML name and node type respectively), while handling the extra information using existing data types.
- The STRING type may be used to send key/attribute.
- PRO: Implementation is simple. It can be implemented without defining a new message type or changing the mechanism in the OpenIGTLinkIF module.
- CON: Cannot differentiate from STRING data, which will be stored in annotation node.
- Define COMMAND type in OpenIGTLink? A COMMAND message will not be converted to MRML node. It will be interpreted at the OpenIGTLinkIF module.
- PRO: This mechanism can be used for other purpose e.g. controlling 3D Slicer from external software by sending Python script.
- CON: The new message type is required.
- Use BIND message. The BIND message bundles multiple OpenIGTLink messages into one message. If the module receives a BIND message, it converts the first element to an MRML node, and then coverts other elements (must be STRING type) to key/value and set in the MRML node converted from the first element.
- PRO: Does not need any change in the protocol.
- CON: The API becomes a bit complicated.