Automated FLIM

The software package LI-FLIM comes with a variety of automated features such as timelapse measurements and multi-frequency recording. Automated processing is not limited to just these features. LI-FLIM has its own ActiveX interface, which can be accessed with basically every programming language (e.g. C, Java, Visual Basic) or scripting language (e.g. MATLAB, Perl, Python). The extensive set of ActiveX controls in combination with LI-FLIM makes it easy to partially or fully automate a FLIM measurement.

 

Researchers at the University of Amsterdam developed a multi-position fluorescence lifetime imaging (FLIM) screening method to screen for bright FPs. However, this method can be applied to any experiment in which the fluorescence lifetime is an important parameter.
 

Introduction

In this tutorial you will get a quick introduction in automated FLIM using MATLAB. At the end of the article you will largely understand the steps to perform automated flim measurements as in the MATLAB example below.

% Records a lifetime image (a valid reference is assumed to
% have been recorded already). This script extracts the lifetime data and
% displays the lifetime calculated from modulation and phase in an image.
% The difference between these lifetimes is also diplayed as well as the
% intensity image.
function [im] = lifetime()
liflim = actxserver('LIFLIM.App');% Set up events
tm = timer('TimerFcn', @eventTimer, 'StartDelay', 10.0);
evnt = {'Lifetime', @(ObjectName, EventID, EventStruct, EventName)...
eventSnapshot(ObjectName, EventID, EventStruct, EventName, tm)};
liflim.registerevent(evnt);
% Take sample
start(tm);
liflim.Sample();
wait(tm);% Retreive data
dims = liflim.GetLifetimeDataDims();
data = liflim.GetLifetimeData(0);
im = permute(reshape(data, dims(1:end-1)), [2, 3, 4, 1, 5, 6]);
% Clean up
delete(tm);
delete(liflim);

function eventTimer(varargin)
disp('*** Timer Event ***');

function eventLifetime(ObjectName, EventID, EventStruct, EventName, tm)
stop(tm); 

 

Listing all connected devices

After a succesfull installation of LI-FLIM you can easily communicate with LI-FLIM using the ActiveX interface. Make a connection by using the following command:

liflim = actxserver('LIFLIM.App');

Where

liflim

(on the left hand side) can be any variable name, liflim will be used in this document. And the command on the right hand side will start up LI-FLIM automatically. We are now going to write some code to display all the devices connected to LI-FLIM.

devices = liflim.GetDevices();
disp(devices);

The first line of code calls a function in LI-FLIM, the GetDevices() function. This function returns a list (as a cell array) with all the devices connected to LI-FLIM. The second line of code is a matlab code to display data in the matlab command window. When nothing is displayed check if there are any devices connected to LI-FLIM. If there aren’t, make sure all devices are switched on. Go to LI-FLIM, select 'Devices' from the menubar and select 'Find available devices'. We will now end the script by closing the ActiveX connection to LI-FLIM.

delete(liflim);

We have now finished our MATLAB script. It is good practice to close an ActiveX connection when they are not needed anymore. The full code with comments can be downloaded below.

 

Listing all set parameters

Again we start by making a connection with LI-FLIM:

liflim = actxserver('LIFLIM.App');

Now we will save a list of all set parameters in LI-FLIM to a variable and display the results.

parameters = liflim.GetParameters();
disp(parameters);

Again the results are saved to the variable 'parameters' as a cell array. The results are displayed with the MATLAB function disp(parameters). Again we close the connection to LI-FLIM.

delete(liflim);

 

Setting a device parameter

Let's assume that the function GetDevices() returns a list with a LIFA system and a TRiCAM.

'LIFA 10000'
'LI2CAM 10000'

We now know that these two devices are connected to LI-FLIM. To set a device parameter we use the function SetDeviceParameter(device, parameter, value). Ofcourse we have to make a connection to LI-FLIM first:

liflim = actxserver('LIFLIM.App');

Now we will set the exposure time of the camera to 100 ms:

liflim.SetDeviceParameter('LI2CAM 10000', 'ExposureTime', 100);

And we close the connection to LI-FLIM.

delete(liflim);

 

Make and import a snapshot

Make an ActiveX connection to LI-FLIM.

liflim = actxserver('LIFLIM.App');

Now we send the snapshot command to LI-FLIM. This is the same as clicking the 'Snapshot' button in the 'Acquisition' box in the 'Acquisition Settings' toolbox. A snapshot will be made and the 'Camera' tab will become the active tab in LI-FLIM.

liflim.Snapshot();

The acquisition of a snapshot will take LI-FLIM some time, at least the amount of time set as exposure time. MATLAB does not automatically know whether or not LI-FLIM is finished with its tasks. We therefore have to wait a certain amount of time to let LI-FLIM do its work and introduce a break of two seconds.

pause(2);

After the break MATLAB can import the snapshot image data LI-FLIM. But first we import the information about the dimensions of the data.

dims = liflim.GetCameraDataDims();

GetCameraDataDims() returns 1x7 matrix with information about the cameradata in the following order: channel, x-co-ordinate, y-co-ordinate, z-co-ordinate, phase, frequency, time. We use this information to reshape and permute the imported data. Now we will import the raw data.

data = liflim.GetCameraData(0);

Where the number 0 denotes the timeframe, in this case the first (and only) timeframe. GetCameraData() will return all the acquired snapshot data for a given timeframe. The data obtained is stored as an array of values. We want to reshape the data to get a six dimensional matrix (with all dimensional information corresponding to the GetCameraDataDims() function). And we want to permute this matrix to better suit for use in MATLAB.

snapshot = permute(reshape(data, sz(1:end-1)), [2, 3, 4, 1, 5, 6]);

The reshape command makes a multidimensional matrix of the raw data, according to the dimension information acquired by GetCameraDataDims(). The time dimension is dropped because the time information is not in the raw data. The permute command makes a matrix with dimensions in the following order: x-co-ordinate, y-co-ordinate, z-co-ordinate, channel, phase, frequency. The snapshot information is now processed for use in MATLAB. We can show the image with the MATLAB command imshow().

imshow(snapshot,[]);

The variable 'snapshot' is the final snapshot information and the brackets are to linearly scale the intensities of the image to the whole 8-bit range. We now close the connection to LI-FLIM.

delete(liflim);

 

Importing a snapshot safely

Pausing after sending a Snapshot command is one way to wait for LI-FLIM to finish its tasks. Pausing however, could lead to erroneous results. When importing data while a measurement is somewhat slower than average (read: acquisition time is more than pause time). MATLAB could import unfinished acquisition data. Or when doing multiple acquisitions, MATLAB could get a new task before finishing its current task. This throws an error, and the script will be exited.

To overcome these problems we have to make use of the events LI-FLIM will fire after a specific task. LI-FLIM has pre-determined events (listed in the LI-FLIM user manual), these events can be seen by MATLAB when you listen to them in the correct way. In this paragraph the snapshot event will be used to check when a snapshot is taken and ready to be imported. To make use of the event functionality we have to introduce functions to our script. Functions are very powerfull and makes (parts of) your script re-usable. The plan is to make two files. A file with the function makeSnapshot that returns the imagedata, and a file that connects to LI-FLIM, calls the function, displays its result and closes the connection to LI-FLIM. First we have to define a main function, type:

function[snapshot] = makeSnapshot(liflim)

The term 'function', the brackets , the equals sign and parenthesis are obligatory in defining a function. The variable 'snapshot' will be returned when calling the function (this will be the image data imported from LI-FLIM), 'makeSnapshot' is the name of the function. The .m file has to have the same name: 'makeSnapshot.m'. The variable between parenthesis (liflim) is the variable you have to enter when calling the function (the ActiveX handle).

Now we will create some variables needed to listen to the snapshot event. We will create a timer to never let MATLAB wait for more than 10 seconds. A snapshot should never take longer than a couple of seconds, if the snapshot event doesn’t fire a timer event will fire. It is not necessary to fully understand the code, just copy:

tm = timer('TimerFcn', @eventTimer, 'StartDelay', 10.0);
evnt = {'Snapshot', @(ObjectName, EventID, EventStruct, EventName)...
eventSnapshot(ObjectName, EventID, EventStruct, EventName, tm)};

The following code will let MATLAB to listen to the event we have just defined.

liflim.registerevent(evnt);

And we can start the timer, successively send the snapshot command and we will wait for the timer:

start(tm);
liflim.Snapshot();
wait(tm);

The function will wait until the time-out of ten seconds is reached, or when the ‘snapshot’ event is fired. The following code is unchanged with respect to the former paragraph:

dims = liflim.GetCameraDataDims();
data = liflim.GetCameraData(0);
snapshot = permute(reshape(data, dims(1:end-1)), [2, 3, 4, 1, 5, 6]);

This is the end of the makeSnapshot() function, but not the end of the file. We have to create two more functions. A timer event function and a snapshot event function, to run some code when any of these two events occur. At first create the eventTimer() function:

functioneventTimer(varargin)
disp('*** Timer Event ***');

The timer event fires every time the timer reaches ten seconds. It does not need to do anything, but it could display something when the event occurs, as in this case. You also could throw an error and quit the script. Now create the eventSnapshot() function:

functioneventSnapshot(ObjectName, EventID, EventStruct, EventName, tm)
stop(tm);

This function will be called when the snapshot event occurs. The code stop(tm) will stop the timer, wait(tm) sees this and the function will continue. To stop listening to the snapshot event and to delete the timer, type:

liflim.unregisterevent(evnt);
delete(tm);

The function makeSnaphot() is complete and ready to be saved. We now will write a short script to call the function:

liflim = actxserver('LIFLIM.App'); % Make an ActiveX connection to LI-FLIM
snapshot = makeSnapshot(liflim); % Call the function makeSnapshot
imshow(snapshot,[]); % Show snapshot as an image. 
% The empty brackets '[]' are to linearly scale the intensities
delete(liflim); % Close the connection to LI-FLIM 

Make sure you save the full code to the function makeSnapshot() to 'makeSnapshot.m'.

 

Retrieving Lifetime Data

To perform a FLIM measurement and retrieve its lifetime data, only a few adjustments have to be made with respect to the makeSnapshot script. With this function we will expect that a reference material already has been taken and loaded in LI-FLIM. At first the name of the function will change. And we will name the returned image data 'im'.

function [im] = lifetime( liflim )

The timer will not change, but the event will. We will be 'listening' to the Lifetime-event. This event will fire when LI-FLIM finishes its lifetime calculations.

tm = timer('TimerFcn', @eventTimer, 'StartDelay', 10.0);
evnt = {'Lifetime', @(ObjectName, EventID, EventStruct, EventName)...
eventSnapshot(ObjectName, EventID, EventStruct, EventName, tm)};
liflim.registerevent(evnt);

The command we will send to LI-FLIM will be the Sample() command, this is equal to pressing the Sample-button in LI-FLIM. The command will be enclosed, as in the 'makeSnaphot' function by the 'start' and the 'wait' functions of the timer:

start(tm);
liflim.Sample();
wait(tm);

Now the data can be retrieved, the following commands are equivalent to the cameradata function used in the makeSnapshot script.

dims = liflim.GetLifetimeDataDims();
data = liflim.GetLifetimeData(0);
im = permute(reshape(data, dims(1:end-1)), [2, 3, 4, 1, 5, 6]);

We delete the timer when its no longer needed.

delete(tm);

The data is stored in the 'im' variable and this will be returned by the function. We finish by copying the same function used in the makeSnapshot function:

function eventTimer(varargin)
disp('*** Timer Event ***');
function eventLifetime(ObjectName, EventID, EventStruct, EventName, tm)
stop(tm);

Make sure that you save this to lifetime.m.