images/v_36.pngVINCI 4.24.0
Docu Home

Matlab Interface

Table of Contents

see also: Index

Overview

This is a tutorial which describes how to use the Matlab interface provided by Vinci.

The reason why we implemented this interface is to combine the advantages of Matlab and Vinci to make both even more useful than they are on their own.

Vinci is a tool designed to visualize and analyse medical tomographic images. It’s emphasis is on interactive exploration and evaluation. For the purpose of automation, Vinci provides only some level of scriptability through a Python interface, as well as the ability to record and replay macros.

Matlab, on the other hand, is a programming language well suited for scientific programming, prototyping of ideas and automation of repetitive tasks. Writing interactive, user-interface driven applications with Matlab, however, is not an easy task.

The Matlab interface of Vinci allows you to write scripts and applications in Matlab, which use Vinci for the interactive parts of your program while you can write custom algorithms and analysis steps with the help of Matlab’s toolboxes and libraries.

Here is an incomplete list of things, you can do with the Vinci interface for Matlab:

  • Remotely control Vinci from Matlab.
  • Automate repetitive tasks in Vinci.
  • Load images in Vinci and access the image data within Matlab.
  • Generate new images in Matlab and visualize them using Vinci.
  • Create rois, measures and profiles and evaluate them from within Matlab.
  • A combination of all of these possibilities.

Getting Started

If you want to learn more about how to use the Matlab Interface for Vinci, we suggest you start by running some of the example scripts provided with each Vinci release. In principle, this works very similar on all platforms: you open Matlab and change into the examples directory which is part of every recent Vinci release. Traditionally, software is installed (“deployed”) slightly differently depending on the platform you use - so on Mac OS X, Linux and Windows you will typically find Vinci installations in different locations. The only important distinction here is the path to the examples directory.

In order to run the example scripts, you need to make sure that the Matlab session is using the right directory. Start Matlab, go to the Matlab “Command Window” and use the cd command to change to the examples directory. Everything else should work “out of the box”. The following platform specific recipes assume that you have installed Vinci 3.83 or newer (replace “383” if you are using another version).

MacOS
if you use the installer script, you can use the default path, otherwise you need to change “VINCI.app” to “VINCI-383.app”:
cd '/Applications/VINCI.app/Contents/external/matlab/'
Windows
the default path on the Windows platform is C:\Program Files\MPIfSF\vinci_383\external\matlab, so type
cd 'C:\Program Files\MPIfSF\vinci_383\external\matlab\'
Linux
the path to the examples directory depends on where you installed Vinci on your Linux machine and which platform id you specified. For example, if you chose /usr/local/ as the installation directory on a 64 bit Linux, you may have to type
cd '/usr/local/vinci_383-linux-x64/external/matlab/'

in the Matlab shell.

Once your Matlab session is located within the right directory, you should be able to see a number of files named test_*.m in the “Current Folder” window in Matlab. To run an example, open one of the files named test_*.m in the Matlab text editor and press F5 or select “Run” from the “Debug” menu.

Writing Your Own Scripts

Writing your own scripts for Vinci does not require a lot of initial work. The only step required is to tell Matlab where to find the Vinci interface package. The path to the package is the same that we used in the previous section to switch to the examples directory. You can use the following snippet of Matlab code as a starting point for your own scripts.

clear all
clc

addpath('/path/to/vinci/external/matlab');

c = Vinci.Constants();

%% open a vinci instance and open a new project
connection = Vinci.Connect();
commands = Vinci.Commands(connection);
commands.newProject();

You have to adjust the path used as an argument to the addpath command. Once you have done this, you can run the script. If everything works correctly, a new instance of Vinci with an empty project will appear. Starting from here, you can add additional code to remote control Vinci.

Adding The Vinci Interface to Your Matlab Path

If you plan to write several Matlab scripts for Vinci, you can permanently add the Vinci Matlab package to your Matlab path. Open a new instance of Matlab and type

addpath('/path/to/vinci/external/matlab');
savepath();

Adding the Vinci package to the Matlab path has the advantage, that it is not neccessary any more to specify the path in every single Matlab script. Moreover, you can run your scripts on different machines without the need to adjust the path in the script on every system. When a new version of Vinci is released, switching to the new version of Vinci requires that you adjust the path to the Vinci package only once in your pathdef.m file.

In the following sections, we except that you have already added the Vinci Matlab package to your Matlab path (by hand or permanently).

Starting Vinci from Matlab

To start a new instance of Vinci from within Matlab, type

connection = Vinci.Connect();

This call will start Vinci and return a connection object of the type Vinci.Connect:

connection = Vinci.Connect();
whos connection

% returns
%  Name            Size            Bytes  Class            Attributes
%
%  connection      1x1               112  Vinci.Connect

This connection object is the central component of the Vinci interface. Every other object which communicates with Vinci will do this through the connection object.

You can call Vinci.Connect() several times to start multiple instances of Vinci. Each call returns a new connection object and the different Vinci instances are independent of each other.

Connecting to a Running Instance of Vinci

You can connect to an already running instance of Vinci. This feature requires that you start Vinci with the commandline option -S (uppercase s). In this mode, Vinci will not open the default project, but instead show an empty window and wait for connection requests. When started with -S, Vinci’s log view will contain a line similar to

opened TCPServer (port: 42456)

The number in this line is the network port, on which Vinci awaits Matlab’s connection request. To connect to Vinci from Matlab, supply this number as a parameter to the Vinci.Connect call:

connection = Vinci.Connect(42456);

The Vinci Package

All functions and classes used by the Vinci Matlab interface are stored within a Matlab package with the name Vinci. When you use components from this package, you always have to prefix the component with Vinci.. For example, if you want to refer to the Image class within the package, you have to type Vinci.Image. Using packages prevents name clashes between several different functions or classes with identical names.

If you use a class or function often, you can import it. This way, it is not neccessary to specify the package name any more:

import Vinci.Connect
connection = Connect();

To import all classes and functions, execute

import Vinci.*

Importing all components of a package can cause subtle bugs when a function or class in the path is hid by another function or class with the same name inside the module. Therefore, it is usually not a good idea to import all components of a package.

The Documentation

Our goal is to document all classes, properties, methods and functions of the Vinci Matlab interface. We have not succeeded so far, as some parts of the interface are still undocumented. Large parts, however, already contain documentation describing the functionality of classes and methods. To access this documentation from within Matlab, type either help <component> or doc <component> in Vinci’s command prompt. To access the documentation of the image class, type

help Vinci.Image

To see the documentation of the sendMessage method of class Connect, type

help Vinci.Connect.sendMessage

If you prefer an html version of the documentation, have a look at the Matlab API Documentation.

Optional Arguments

Many methods and functions provided by the Vinci interface have a list of optional arguments. You can specify these arguments as key-value pairs at the end of the function’s argument list. For example, the method Vinci.Image.createRoiPolygon() has the optional arguments =’Color’= and =’Rotation’= to initialize the color and rotation of the roi to specific values. You can supply these arguments as

Vinci.Image.createRoiPolygon('Color', [255 0 0], 'Rotation', pi/2);

The order, in which you supply the arguments is not important, therefore, you can also write

Vinci.Image.createRoiPolygon('Rotation', pi/2, 'Color', [255 0 0]);

If you do not supply an additional argument, Vinci will either set this argument to a default value or behave in a different way. For example, if you do not specify the number of the =’ImageBuffer’= when loading an image, Vinci will automatically choose a free image buffer for you. The default behaviour of optional arguments is documented in the documentation of the corresponding function or method.

Filepaths

There are several situations, in which you have to supply the path to a file. Often, Vinci - not Matlab - will try to read from or write to this file. Vinci’s current directory, however, does not neccessarily correspond to Matlab’s current directory. Therefore, it is dangerous to supply a filename using a relative path as Vinci might misinterpret the path.

Instead, convert relative paths to absolute paths using the function Vinci.getAbsolutePath(relpath). This function can also resolve the ~ character at the beginning of a path to the user’s home directory, just like it is done in the unix shell. This feature will work on all platforms, including Windows. So if the project file, you want to open is located in the user’s home directory in a directory data, you can write

myProjectFile = Vinci.getAbsolutePath('~/data/project.vpx');

On linux, the home directory is located at /home/<username>/. On Mac OS X, it is /Users/<username>/. On Windows, it will be either C:\Documents and Settings\<username> or C:\Users\<username>\.

Creating a new Project or Loading an Existing One

When Matlab starts a new instance of Vinci, Vinci does not load a project. Instead, Vinci just shows an empty window. This allows you to either create a new, empty project or load an existing project, which initializes Vinci the way you like.

The following snippet starts a new Vinci instance and opens a new empty project:

connection = Vinci.Connect();
commands = Vinci.Commands(connection);

commands.newProject();

To load an existing project file, type:

connection = Vinci.Connect();
commands = Vinci.Commands(connection);

commands.loadProject('/path/to/project-file.vpx');

The path to the file must be either absolute or relative to Vinci’s working directory, as explained in Filepaths.

Loading Images

To load an image, type

img = Vinci.Image.loadImage(connection, filename);

As we already explained in Filepaths, the filename must be absolute as Vinci and not Matlab will try to load the image file. You can use Vinci.getAbsolutePath() to convert a path relative to Matlab’s working directory into an absolute path.

By default, Vinci tries to guess the file format of an image file. This feature most often works, however, Vinci will not always choose the correct plugin. Therefore, it is a good idea to specify the image format explicitly if you know the image format of the file.

c = Vinci.Constants;
img = Vinci.Image.loadImage(connection, filename, 'ImageFormat', c.ImageTypes.ECAT7Image);

You can find the names of all supported file formats in Vinci.Constants.ImageTypes.

Both the connection object and the filename are mandatory arguments to the loadImage function. Moreover, there are several optional arguments, you can use when loading an image. Type

doc Vinci.Image.loadImage

for a list of all arguments available.

Getting a Handle to an Image in Vinci

Sometimes, you want to get a handle to an image, which has already been loaded. This might be the case if you previously opened a project, which does already contain images or if the user of your script loaded images by hand into Vinci. If you know the number of the image buffer, you can create a Vinci.Image object and specify the image number in the constructor.

#begin_src matlab img = Vinci.Image(connection, 0); #end_src

You can find the number of the image buffer in the blue bar above the image in Vinci.

If you need a list of all images loaded in Vinci, you can type

#begin_src matlab images = Vinci.Image.getAllImages(connection); #end_src

This function returns a vector of Vinci.Image objects for all images defined in Vinci. If you need a list of all image buffers in Vinci (even the ones, which do not contain valid images), you can set the optional second parameter includeUndefined to true.

#begin_src matlab imgs = Vinci.Image.getAllImages(connection, true); #end_src

Reading Metadata From an Image

Vinci loads an stores meta-information about your images, such as the name of the patient, the date of the measure, the tracer used in a PET measurement and so on. You can access this meta-information from Matlab with the getMetaInformation() method of the image class.

image = Vinci.Image.loadImage(connection, filename);

metainformation = image.getMetaInformation();

The value returned by getMetaInformation() is a struct object containing a field for every element of meta-information.

metainfo = image.getMetaInformation();

fprintf('The patient''s name is %s', metainfo.PatientName);
fprintf('The patient''s date of birth is %s', metainfo.PatientDOB);

You can query a list of all fields in the struct by typing

fieldnames = fieldnames(metainfo);

For every field in the struct returned by getMetaInformation(), there is also a property with the same name in the image class. Therefore, you can also write

image = Vinci.Image.loadImage(connection, filename);

fprintf('The patient''s name is %s', image.PatientName);
fprintf('The patient''s date of birth is %s', image.PatientDOB);

This method is more convient to use then calling getMetaInformation(). It is, however, also slower when accessing multiple elements of meta-information, as Matlab has to request each element individually.

Loading an Image Volume into Matlab

One strength of Matlab is that you can perform almost arbitrary image processing tasks with it. You can combine this feature with Vinci’s large number of supported image formats to easily load and process images, as well as view and save the results back to disk. The link between Vinci and Matlab is the method Vinci.Image.getImageVolume. This function returns the image volume of any image in Vinci as a 3D array of float values.

image = Vinci.Image.loadImage(connection, filename);
volume = image.getImageVolume();
% pixelsize is stored in mm
pixelsize = image.PixelSize;

You can use the property PixelSize to get the voxel dimensions of the image.

Using the image volume and the pixel size, you can now manipulate the image in any way you like, i.e. segment it, apply filters or calculate statistics about the image.

Creating New Images and Cloning Images

When you modify the volume of an image, you usually want to display and save the modified image in Vinci. You can change the image volume of an existing image with the method Vinci.Image.setImageVolume(). Using this method, however, is discouraged. Changing an image volume modifies the original image. If you change the image and then save the project, you might accidentally overwrite the original file and lose important data. It is a much better idea to either create a new image or clone an existing image with modified settings.

Creating a new image is the appropriate way if there is no image which you could clone. For example, if you use Vinci just to display images, you will most often open a new instance of Vinci just to show one image.

If you modify an existing image or create a new image, which is derived from an existing image, you should clone the original image. The cloned image will inherit all meta information from the original image, as well as the reslicing parameters and the color scale.

To create a new image, write

% compute an image volume
volume = ones(128, 128, 64);
pixelsize = [1 1 2];

newImage = Vinci.Image.createImageFromMemory(connection, volume, 'PixelSize', pixelsize);

To clone an existing image, type

volume = img1.getImageVolume();
pixelsize = img1.PixelSize;

% compute a new volume
[newVolume, newPixelSize] = someComputation(volume, pixelsize);

newImg = img1.cloneImage(newVolume, 'PixelSize', newPixelSize);

Both functions, createImageFromMemory and cloneImage, have a number of additional arguments. You can find out about these arguments by typing

help Vinci.Image.createImageFromMemory
help Vinci.Image.cloneImage

in the command window.

Display Objects

Vinci provides a set of objects, which you can place on top of a displayed image and use for the evaluation of images or for the creation of illustrations

  • regions of interest (rois), text annotations, profiles and measures. These

objects are called display objects.

You can both access display objects created in Vinci from within Matlab and create new display objects inside Matlab. Each display object is associated with exactly one image.

Creating Display Objects

To create a display object, write

displayObject = image.create*();

Here, image must be an object of type Vinci.Image and you must replace the asterisk (*) with the name of the display object, you want to create. The following table gives a list of all the display objects and their associated creation methods:

Method Created Type Description
createAnnotation() Vinci.Annotation Creates a new text annotation on top of the image.
createProfile() Vinci.Profile Creates a new profile on top of the image.
createMeasure() Vinci.Measure Creates a new distance measure tool on top of the image.
createRoiRect() Vinci.RoiRect Creates a new rectangular roi on top of the image.
createRoiEllipse() Vinci.RoiEllipse Creates a new ellipic roi on top of the image.
createRoiPolygon() Vinci.RoiPolygon Creates a new polygonal roi on top of the image.
createDisplayGroup() Vinci.DisplayGroup Creates a new display group on top of the image.

You can call all display object creation methods without any arguments. In this case, Vinci will set all properties of the created display object to some default value. You can, however, also supply a number of optional arguments in the form of key-value pairs to the create* method. The following options are supported by all display object types:

Property Description
‘Name’ The name of the display object. The name is not required to be unique.
‘OrthoPart’ The name of the ortho part (transaxial, coronal, sagittal), on which the display object should be displayed. Use the values in Vinci.Constants.OrthoParts when setting this options.
‘Color’ The color, which is used to display the display object. Colors are specified as triples [r, g, b] of integers between 0 and 255.
‘Rotation’ The rotation angle of the display objects. You must specify the angle in radians. The display object is rotated around it’s center.
image = Vinci.Image.loadImage(connection, filename);
orthoParts = Vinci.Constants.OrthoParts;

roi1 = image.createRoiRect();
roi2 = image.createRoiEllipse('OrthoPart', orthoParts.Coronal);
roi3 = image.createRoiPolygon('Color', [200 30 0], 'Rotation', pi/4);

annotation = image.createAnnotation('Name', 'AnAnnotation');
measure = image.createMeasure('OrthoPart', orthoParts.Sagittal);

Querying Existing Display Objects

Each display object belongs to one image in Vinci. You can query all display objects using the getDObjects() method of the Vinci.Image class:

image = Vinci.Image.loadImage(connection, filename);
dobjects = image.getDObjects();

The most commonly used object type in Vinci is the roi. This is why a method Vinci.Image.getRois() exists, which only returns the rois belonging to an image:

image = Vinci.Image.loadImage(connection, filename);
rois = image.getRois();

Display Coordinates

The position and size of a display object is given in display coordinates. An ortho view consists of several ortho displays, one for each displayed image. Each ortho display has one or several ortho parts. Usually, three ortho parts are shown - transaxial, coronal and sagittal. In the case of a zoomed view, however, only one ortho part is visible. The bottom left corner of such an ortho part has the coordinate (0,0). The upper-right corner is located at the coordinate (1,1). The positive x-axis runs from the left-hand side to the right-hand side of the display. The positive y-axis extends from the bottom to the top of the display. Values outside the range [0, 1] are valid, however, they lie outside the visible display. See figure XYZ for an illustration of the display coordinate system.

display-coordinates-annotated.png

Defining Geometry

All display objects provide a way to specify the geometry of the display object. Since the nature of the geometry differs from display object type to display object type, there is not one way to specify the geometry for all display object types. The following subsections describe how to define the geometry of different display objects.

RoiRect and RoiEllipse

Rectangular and elliptic rois are both defined by the coordinates of the lower-left corner of the roi and it’s width and height. You can query and set the geometry using the geometry property of both roi classes. The geometry must be specified as a struct with the fields x, y, width and height.

rectangle = image.createRoiRect();
ellipse = image.createRoiEllipse();

geo = struct('x', 0.3, 'y', 0.5, 'width', 0.2, 'height', 0.4);
rectangle.geometry = geo;
ellipse.geometry = geo;

RoiPolygon

The geometry of polygonal rois is given by a list of points, which define the corners of the polygon. You must specifiy the list as a 2xN matrix of float values. You can query and set the geometry using the geometry property.

polygon = image.createRoiPolygon();

geo = [0.3 0.4; 0.5 0.8, 0.8, 0.3]';
polygon.geometry = geo;

Profile and Measure

We define the geometry of profiles and measures by the position of the two endpoints, called head and tail. The value supplied to the geometry property must be a struct with two fields head and tail. Both fields must point to another struct with the fields x and y:

profile = image.createProfile();
measure = image.createMeasure();

head = struct('x', 0.3, 'y', 0.8);
tail = struct('x', 0.7, 'y', 0.1);
geo = struct('head', head, 'tail', tail);

profile.geometry = geo;
measure.geometry = geo;

Annotation

The geometry of a text annotation is defined by the position of the upper-left corner as well as the font size and font family. You can use the properties position, fontSize and font to set the geometry of an annotation:

annotation = image.createAnnotation();

annotation.geometry = [0.4 0.6];
annotation.fontSize = 14;
annotation.font = 'Arial';

Evaluating Rois

Vinci can calculate various statistics about the voxels inside a roi. You can access these statistics from Matlab with the evaluateRoi() method. This method is available for all roi types.

image = Vinci.Image.loadImage(connection, filename);

roi1 = image.createRoiRect();
roi2 = image.createRoiEllipse();
roi3 = image.createRoiPolygon();

statistics1 = roi1.evaluateRoi();
statistics2 = roi2.evaluateRoi();
statistics3 = roi3.evaluateRoi();

The value returned by evaluateRoi is a struct object with the fields Average, StdDev, Min, Max, Sum and Pixels.

statistics = roi.evalutateRoi();
fprintf('The mean of the values inside the roi is %f\n', statistics.Average);

Advanced Roi Statistics

Vinci can calculate the most commonly used statistics for rois. However, there may be situations, in which you need different statistics. For example, for noisy images, you may not want to use the minimum and maximum but instead the 5-th and 95-th percentile. In these situations, you can use the method getRoiValues() to query the individual pixel values inside the roi.

values = roi.getRoiValues();
percentile5 = quantile(values, 0.05);
percentile95 = quantile(values, 0.95);
fprintf('The 5-percentile is %f and the 95-percentile is %f\n', percentile5, percentile95);

getRoiValues() returns a vector of float values.

Coregistration

Vinci supports coregistration of images of the same or varying modalities via the MMM tool. Starting with Vinci 4.01.0, you can remote control the MMM tool with Matlab. To create a new MMM tool for an ortho display, write

ORTHODISPLAY_NUM = 0;
ortho = Vinci.OrthoView.getFirstOrthoView(connection);
mmm = Vinci.MMMTool.createNewMMMTool(connection, ortho, ORTHODISPLAY_NUM);

mmm is a handle to the MMM tool window. You can now start a co-registration using the following lines of code:

mmmScheme = Vinci.Constants.HumanSchemes.GoodQualityPetMrPrecise;
mmm.coregisterHuman(refImg, reslImg, 'SchemeName', mmmScheme);

refImg and reslImg must both be objects of the type Vinci.Image. The above code will coregister the reslicing image reslImg onto the reference image refImg. The additional argument ‘SchemeName’ selects the coregistration scheme, which should be used. You can find valid coregistration schemes in Vinci.Constants.HumanSchemes. Each coregistration scheme in this struct corresponds to one entry in the dropdown list at the top of the MMM tool window.

You can access the new transformation of the reslicing image with the getResliceParameters() method of the reslicing image:

parameters = reslImg.getResliceParameters();

Comments and further Development

We are excited about the new possibilities this Matlab interface offers for scripting Vinci. Please let us know if you have suggestions on how we can further improve it - it is generally possibly to remotely control most features of Vinci (we need this ability for our automated testing anyway) and the Matlab interface can be easily extended to cover more functionality. Mail: vinci@nf.mpg.de

(C) 2005-2014 Max Planck Institute for Neurological Research Cologne, Germany