Difference between revisions of "AnyWave:WriteMatlabScripted"

From WikiMEG
Jump to: navigation, search
(Optional parameters)
(AnyWave-MATLAB functions)
Line 67: Line 67:
 
=AnyWave-MATLAB functions=
 
=AnyWave-MATLAB functions=
 
The table below shows a summary of all MATLAB functions available when writing a MATLAB Scripted plug-in:<br/>
 
The table below shows a summary of all MATLAB functions available when writing a MATLAB Scripted plug-in:<br/>
Function parameters placed between <> are optional.<br/>
+
 
'''Note:''' All AnyWave MATLAB functions begin with Aw. That will avoid confusion and clearly indicates the purpose of these functions.
+
'''Note:''' All AnyWave MATLAB functions start with 'aw_' to avoid confusions with other MATLAB functions.
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 74: Line 74:
 
! Function !! Short description
 
! Function !! Short description
 
|-
 
|-
| '''[[#AwGetInputChannels()|AwGetInputChannels]]'''() || Get current input channels set by AnyWave for the plug-in.
+
| '''[[#aw_getplugininfo()|aw_getplugininfo]]''' || Returns useful information about the plugin.
 
|-
 
|-
| '''[["AwGetDataInfo()|AwGetDataInfo]]'''() || Get informations about the data file.
+
| '''[[#aw_getdata()|aw_getdata]]''' || Returns data from AnyWave.
 
|-
 
|-
| '''[[#AwGetData(start, duration, <filtering keyword>, <filtering options>)|AwGetData]]'''(start, duration, <filtering>, <filteringOptions>) || Get the data of the current input channels.
+
| '''[[#aw_getmarkers()|aw_getmarkers]]''' || Returns markers from AnyWave.
 
|-
 
|-
| '''[[#AwGetWorkingDir()|AwGetWorkingDir]]'''() || Get the full path to a temporary directory created by AnyWave for the plug-in.
+
| '''[[#aw_addmarkers()|aw_addmarkers]]''' || Sends markers to AnyWave.
|-
+
| '''[[#AwGetMarkers(<keyword>, <value>)|AwGetMarkers]]'''(<keyword>, <value>) || Get markers from AnyWave.
+
|-
+
| '''[[#AwAddMarker(label, position, <value>, <duration>, <targeted channels>)|AwAddMarker]]'''(label, position, <value>, <duration>, <targeted channels>) || Add a marker in AnyWave.
+
|-
+
| '''[[#AwSendMessage(message)|AwSendMessage]]'''(message) || Send a message to AnyWave. The message will be added to the plug-in's log.
+
|-
+
| '''[[#AwIsProcessTerminated|AwIsProcessTerminated]]'''() || Returns true if the process has been aborted by the user in AnyWave.
+
 
|}
 
|}
  
==AwGetInputChannels()==
+
==aw_getplugininfo==
AnyWave uses channels to represent signals on screen but also as its internal data set.<br/>
+
When a plug-in is launched by AnyWave, a set of input and/or output parameters is defined accordingly to the specific settings for the plug-in.<br/>
+
The default behavior is to set as input channels the current selected channels in AnyWave. If there is no selection, then AnyWave will set all the channels in the current montage as input channels.<br/>
+
<br/>
+
'''AwGetInputChannels()''' will request the list of input channels for the plug-in. No parameters are required.<br/>
+
AnyWave will send back a structure array containing MATLAB structures which match the structure defined by the '''AwChannel()''' function.<br/>
+
'''AwChannel()''' is provided by AnyWave to easily create a MATLAB structure which will be compatible with AnyWave's channels objects.<br/>
+
<br/>
+
This function is usefull if you want to get input the channels' informations without requesting for data.<br/>
+
 
+
Let's try it in our main function for our plug-in:<br/>
+
 
<syntaxhighlight lang="matlab">
 
<syntaxhighlight lang="matlab">
function main()
+
function [ infos ] = aw_getplugininfo()
%MAIN Summary of this function goes here
+
%aw_getplugininfo returns information about the input set for the plugin.
Detailed explanation goes here
+
infos = aw_getplugininfo();
 
+
%
channels = AwGetInputChannels();
+
%  returns a structure with the following fields:
disp('Input channels:');
+
%   .labels
for i=1:numel(channels)
+
%      labels of channels set as input for the plugin.
    fprintf('name: %s', channels(i).name);
+
%   .refs
    fprintf('ref: %s', channels(i).ref);
+
%      references of channels: Empty strings for monopolar channels.
    fprintf('sampling rate: %g Hz', channels(i).samplingRate);
+
%  .max_sr
end
+
%      maximum sampling rate in Hz.
 
+
%  .total_duration
 +
%      the total duration in seconds of the data.
 +
%  .temp_dir
 +
%      the path to a temporary directory created by AnyWave for the
 +
%      plugin.
 +
%
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
As explained above, the channels variable is a MATLAB array of structs filled by AnyWave.<br/>
+
==aw_getdata==
The function will then enumerate the contents of the array.<br/>
+
The structure contains 4 fields but only three are usefull in our case:<br/>
+
1. '''name''' is a string and contains the name associated with the channel by AnyWave.<br/>
+
Note that if a reference has been set in AnyWave the name will contain the name of the reference channel (for example: A1 - A2 in a bipolar montage).<br/>
+
 
+
2. '''ref''' is a string and contains the reference channel set for the current channel. The string is empty if no reference is set.<br/>
+
 
+
3. '''samplingRate''' is a double value containing the data sampling rate in Hertz.<br/>
+
 
+
Note that the messages that usually go to the Matlab Command Window, like those coming from disp() or fprintf() will be available in AnyWave.<br/>
+
AnyWave will get the content of all text outputs from the MATLAB script and put it in the process's log.<br/>
+
 
+
==AwGetDataInfo()==
+
<syntaxhighlight lang="matlab">
+
% get info about data file
+
infos = AwGetDataInfo();
+
 
+
% current path to data file
+
fprintf('data path: %s', infos.data_path);
+
 
+
% total file duration in seconds
+
fprintf('data duration : %g', infos.total_duration);
+
 
+
</syntaxhighlight>
+
 
+
==AwGetData(start, duration, <filtering keyword>, <filtering options>)==
+
As explained in AwGetInputChannels(), AnyWave will set some channels as input for the plug-in. AwGetData() will request data for these channels.
+
 
+
===Parameters===
+
{| class="wikitable"
+
|-
+
! Parameter!! Description
+
|-
+
| 1. start || The position in file in seconds.
+
|-
+
| 2. duration || Duration in seconds of the data or -1 to get ALL data in the file. (could be memory consuming).
+
|-
+
| 3. filtering keyword : optional || A string representing filtering options to apply on data.
+
|-
+
| filtering keyword:'No Filtering' || Request data with no filtering: AnyWave will send data as they are in the file.
+
|-
+
| filtering keyword:'User Filtering Options' || Apply specific filtering options on data. That implies the use of the fourth parameter.
+
|-
+
| 4. filtering options : optional || optional if no filtering keyword is set or if the fileting keyword is 'No Filtering'.
+
|}
+
 
+
filtering options must be a structure that matches the one generated by the AwFilteringOptions() MATLAB function:<br/>
+
 
<syntaxhighlight lang="matlab">
 
<syntaxhighlight lang="matlab">
function [ foptions ] = AwFilteringOptions()
+
function [ channels ] = aw_getdata(cfg )
foptions.meg_high = 0.;
+
%aw_getdata request data from AnyWave
foptions.meg_low = 0.;
+
%  channels = aw_getdata(cfg)
foptions.eeg_high = 0.;
+
%  returns channels' data according to the settings defined in cfg structure.
foptions.eeg_low = 0.;
+
%
foptions.emg_high = 0.;
+
%  cfg may contain the following fields:
foptions.emg_low = 0.;
+
 +
%  cfg.start = 10.;
 +
%      starting position in seconds of requested data.
 +
%      if this field is not specified, AnyWave will return data starting
 +
%      at position 0s.
 +
%  cfg.duration = 20.;
 +
%      duration of requested data in seconds.
 +
%      if this field is not specified, AnyWave will return ALL the
 +
%      available data.
 +
%  cfg.labels = {'A1', 'A2'};
 +
%      cell array of strings to identify the required channel labels.
 +
%      if no labels are specified, AnyWave will return the current selected
 +
%      channels set as input for the plugin.
 +
%
 +
%  cfg.filtering = 'no';
 +
%      specifies that we don't want AnyWave to filter the data.
 +
%  cfg.filtering = 'yes';
 +
%      specifies that we want data to be filtered.
 +
%  Note:
 +
%      if the filtering field is not specified, the data will be filtered by
 +
%      AnyWave using the current user defined settings.
 +
%
 +
%  cfg.eeg_lp = 10.; requires filtering = 'yes'.
 +
%      specifies that we want EEG data with low pass filter of 10Hz.
 +
%  cfg.eeg_hp = 1.; requires filtering = 'yes'.
 +
%      specifies that we want EEG data with high pass filter of 1Hz.
 +
%  cfg.meg_lp = 10.; requires filtering = 'yes'.
 +
%      specifies that we want MEG data with low pass filter of 10Hz.
 +
%  cfg.meg_hp = 1.;  requires filtering = 'yes'.
 +
%      specifies that we want MEG data with high pass filter of 1Hz.
 +
%
 +
%  cfg.decimate = 8;
 +
%      specifies that we only take 1 sample of data every 8 samples.
 +
%
 +
%Output:
 +
%  channels is an array of strucrures with the following fields:
 +
%  .label;
 +
%      a string representing the channel's label.
 +
%  .ref;
 +
%      a string representing the reference channel. Can be empty.
 +
%  .data;
 +
%      a data vector containing the samples.
 +
%  .sr;
 +
%      the sampling rate of data.
 +
%  .hpf; 
 +
%      the High Pass filter set.
 +
%  .lpf;
 +
%      the Low Pass filter set.
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
As you can see above, the AwFilteringOptions function will create a structure with all fields set to zero, which means no filtering on data of all types of channels.<br/>
 
The structure can then be modified to specify custom filtering options.<br/>
 
  
Note: If no filtering options are specified using the filtering keyword parameter, then the data coming from AnyWave will be filtered as it is defined in AnyWave.<br/>
+
'''Example:'''<br />
In other words, if you have set filtering options in AnyWave, that filtering options will be applied when requesting for data in the MATLAB plug-in.
+
 
+
===Examples===
+
==== Requesting data with AnyWave's current filtering options ====
+
 
<syntaxhighlight lang="matlab">
 
<syntaxhighlight lang="matlab">
function main()
+
function main
%MAIN Summary of this function goes here
+
%  Detailed explanation goes here
+
  
% ask for data, at position 0 and for a duration of 20 seconds.
+
% request 10 seconds of data starting at 2.5s
channels = AwGetData(0, 20);
+
cfg = [];
% plot only the first channel.
+
cfg.start = 2.5;
plot(channels(1).data);
+
cfg.duration = 10;
% Wait for the user to close the figure.
+
channels = aw_getdata(cfg);
uiwait();
+
  
end
+
% request raw data (with no filtering)
</syntaxhighlight>
+
cfg = [];
 +
cfg.start = 2.5;
 +
cfg.duration = 10;
 +
cfg.filtering = 'no';
 +
channels = aw_getdata(cfg);
  
Like in the AwGetInputChannels() example above, channels will be an array of structures containing informations about input channels.<br/>
+
% request data with low pass filter of 25Hz on EEG channels
The difference here is that the data are provided by AnyWave. The data vector for a channel is available in the field named '''data'''.
+
cfg = [];
 +
cfg.start = 2.5;
 +
cfg.duration = 10;
 +
cfg.filtering = 'yes';
 +
cfg.eeg_lp = 25;
 +
channels = aw_getdata(cfg);
  
In the script above we will get 20 seconds of data from the begining of file, using the current filtering options of AnyWave.
 
 
We then plot the data contained in the first channel and wait for the user to close the figure.
 
 
'''Note:''' ''uiwait()'' is mandatory here if you want to see something on the screen when the plug-in will be executed by AnyWave.<br/>
 
This is due to the fact that the MATLAB code will not run in the normal context (with a Command Window and a workspace) but is executed and terminated.
 
 
====Requesting data using filtering options====
 
<syntaxhighlight lang="matlab">
 
function main()
 
  % create the filteriong options struct
 
  foptions = AwFilteringOptions();
 
  % set specific filtering options
 
  % eeg channels only will be filtered.
 
  foptions.eeg_high = 45;  % High pass filter 45Hz
 
  foptions.eeg_low = 5;    % Low pass filter 5Hz
 
  % get data
 
  channels = AwGetData(0, 20, 'User Filtering Options', foptions);
 
  % plot only the first channel.
 
  plot(channels(1).data);
 
  % Wait for the user to close the figure.
 
  uiwait();
 
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
The example above shows how to ask AnyWave to filter data. Note that only the EEG channels will be filtered. That implies that some EEG channels are set as input for the plug-in.
 
  
====Requesting data with no filtering====
 
<syntaxhighlight lang="matlab">
 
function main()
 
  channels = AwGetData(0, 20, 'No Filtering');
 
  % plot only the first channel.
 
  plot(channels(1).data);
 
  % Wait for the user to close the figure.
 
  uiwait();
 
end
 
</syntaxhighlight>
 
 
Remember: No Filtering means that AnyWave will send data as they are stored in the file.
 
==AwGetWorkingDir()==
 
The function returns a string which is the full path to a temporary folder created by AnyWave for the plug-in.
 
 
This is particularly usefull to store temporary files or settings.
 
 
Example:
 
<syntaxhighlight lang="matlab">
 
function main()
 
  % get input channels
 
  channels = AwGetInputChannels();
 
  % save channels to a temporary file
 
  save(strcat(AwGetWorkingDir(), '/channels'), 'channels');
 
end
 
</syntaxhighlight>
 
 
==AwAddMarker(label, position, <value>, <duration>, <targeted channels>)==
 
==AwAddMarker(label, position, <value>, <duration>, <targeted channels>)==
 
AnyWave is able to receive markers as output parameter of a plug-in. This function will add a marker to the list of output parameters that will be handle by AnyWave when the plug-in has terminated.<br/>
 
AnyWave is able to receive markers as output parameter of a plug-in. This function will add a marker to the list of output parameters that will be handle by AnyWave when the plug-in has terminated.<br/>

Revision as of 16:01, 29 January 2016

Introduction

This section targets people who have a good knowledge and practice of the MATLAB programming language.
The purpose is to explain how to write a MATLAB function that will be the heart of a plug-in executed in MATLAB by AnyWave.
We will also explain how to create a text file to describe our plug-in to AnyWave

The AnyWave-MATLAB API (Application Programming Interface) which is a set of MATLAB functions, will be described in details, with examples to illustrate their use.

Requirements

MATLAB software must be installed on the computer. AnyWave should be able to detect the installation by itself. However, in some special cases, MATLAB could be installed on a custom path AnyWave may not check. In that case, the user must specify the path to MATLAB in AnyWave by changing options in the Preferences settings.

NB: on Linux, csh must be installed at /bin/csh, or the MATLAB Engine API used by AnyWave will not function, and AnyWave will report "Failed to connect to MATLAB!" in the corresponding Process log.

Where to start?

The first thing to do is to create the basic structure for a plug-in.
A MATLAB Scripted plug-in is very simple: it is a folder containing at least two files.

Let's begin by creating a folder (called MyPlugin) somewhere on the computer.
This can be done in MATLAB: create a folder and create a new function called main in that folder.
The main function is MANDATORY. It will be the main function AnyWave will call to execute our plugin.

Matlab1.png

As shown in the image above, a MyPlugin folder has been created and a main function was added.

We are now ready to write our first Matlab plug-in!!

Refer to the AnyWave-MATLAB functions section to learn how to program a plug-in that will communicate with AnyWave.

Writing the desc.txt file

We have written the MATLAB code and now all we have to do is to create a descriptive text file to inform AnyWave about our plug-in.
Let's dot it in Maltab:

Matlab2.png

The file must be named desc.txt and may looks like:

name = My Matlab Plugin
description = I am a plug-in written in Matlab
category = Process:MATLAB:My MATLAB Plugin

The category line is optional. It tells AnyWave where the plug-in will appear in the menus. Here we decided to caterogize it as a Process, with a sub category called MATLAB. Finally, the plug-in name will be My MATLAB Plugin.

The category feature is usefull to separate plug-in that won't really do some calculation but convert data to another format or launch external tools. It could also be useful to classify signal processing algorithms.

Three category keywords are recognized:

  • Process : The plug-in will be set in the Processes menu with a subcategory and a name, for example 'Process:Correlation:Compute correlation'
  • File: The plug-in will be set in the File Menu under the Export sub-menu. Example : 'File:Export to MATLAB'
  • View: The plug-in will be set in the View Menu. Example : 'View:Launch 3D viewer'

If no category is specified, AnyWave will set the plug-in in the Processes menu using the name defined in the file.

Copy the plug-in to the right location

We are ready to add the plug-in to AnyWave.

Copy the folder MyPlugin to your user's AnyWave plugins directory. Remember to place it in the Matlab subfolder. For example on Windows:

Matlab3.png

As you can see MyPlugin is located in the user's AnyWave path for Matlab Scripted plug-ins.

Use the plug-in in AnyWave

Launch AnyWave: the plug-in should be shown as available.

Matlab4.png

AnyWave-MATLAB functions

The table below shows a summary of all MATLAB functions available when writing a MATLAB Scripted plug-in:

Note: All AnyWave MATLAB functions start with 'aw_' to avoid confusions with other MATLAB functions.

Function Short description
aw_getplugininfo Returns useful information about the plugin.
aw_getdata Returns data from AnyWave.
aw_getmarkers Returns markers from AnyWave.
aw_addmarkers Sends markers to AnyWave.

aw_getplugininfo

function [ infos ] = aw_getplugininfo()
%aw_getplugininfo returns information about the input set for the plugin.
%   infos = aw_getplugininfo();
%
%   returns a structure with the following fields:
%   .labels
%       labels of channels set as input for the plugin.
%   .refs
%       references of channels: Empty strings for monopolar channels.
%   .max_sr
%       maximum sampling rate in Hz.
%   .total_duration
%       the total duration in seconds of the data.
%   .temp_dir
%       the path to a temporary directory created by AnyWave for the
%       plugin.
%
end

aw_getdata

function [ channels ] = aw_getdata(cfg )
%aw_getdata request data from AnyWave
%   channels = aw_getdata(cfg) 
%   returns channels' data according to the settings defined in cfg structure.
%
%   cfg may contain the following fields: 
%   
%   cfg.start = 10.;
%       starting position in seconds of requested data.
%       if this field is not specified, AnyWave will return data starting
%       at position 0s.
%   cfg.duration = 20.;
%       duration of requested data in seconds.
%       if this field is not specified, AnyWave will return ALL the
%       available data.
%   cfg.labels = {'A1', 'A2'};
%       cell array of strings to identify the required channel labels.
%       if no labels are specified, AnyWave will return the current selected
%       channels set as input for the plugin.
%
%   cfg.filtering = 'no';
%       specifies that we don't want AnyWave to filter the data.
%   cfg.filtering = 'yes';
%       specifies that we want data to be filtered.
%   Note:
%       if the filtering field is not specified, the data will be filtered by
%       AnyWave using the current user defined settings.
%
%   cfg.eeg_lp = 10.;  requires filtering = 'yes'.
%       specifies that we want EEG data with low pass filter of 10Hz.
%   cfg.eeg_hp = 1.;  requires filtering = 'yes'.
%       specifies that we want EEG data with high pass filter of 1Hz.
%   cfg.meg_lp = 10.;  requires filtering = 'yes'.
%       specifies that we want MEG data with low pass filter of 10Hz.
%   cfg.meg_hp = 1.;  requires filtering = 'yes'.
%       specifies that we want MEG data with high pass filter of 1Hz.
%
%   cfg.decimate = 8;
%       specifies that we only take 1 sample of data every 8 samples.
%
%Output:
%   channels is an array of strucrures with the following fields:
%   .label; 
%       a string representing the channel's label.
%   .ref;
%       a string representing the reference channel. Can be empty.
%   .data;
%       a data vector containing the samples.
%   .sr;
%       the sampling rate of data. 
%   .hpf;  
%       the High Pass filter set.
%   .lpf;
%       the Low Pass filter set.
end

Example:

function main
 
% request 10 seconds of data starting at 2.5s
cfg = [];
cfg.start = 2.5;
cfg.duration = 10;
channels = aw_getdata(cfg);
 
% request raw data (with no filtering)
cfg = [];
cfg.start = 2.5;
cfg.duration = 10;
cfg.filtering = 'no';
channels = aw_getdata(cfg);
 
% request data with low pass filter of 25Hz on EEG channels
cfg = [];
cfg.start = 2.5;
cfg.duration = 10;
cfg.filtering = 'yes';
cfg.eeg_lp = 25;
channels = aw_getdata(cfg);
 
end


AwAddMarker(label, position, <value>, <duration>, <targeted channels>)

AnyWave is able to receive markers as output parameter of a plug-in. This function will add a marker to the list of output parameters that will be handle by AnyWave when the plug-in has terminated.
A marker must have a name or label and a position in the file.
A marker could also have an integer value, a duration in seconds (a selection of samples) and can target one or several particular channels.

Parameters

Parameter Description
1. label A string to set the marker's label.
2. position Real scalar value to set the psition in seconds of the marker in the file.
3. value : optional Integer value (INT16 if possible) associated to the marker.
4. duration : optional Real scalar value to set the duration of the marker. Could be zero.
5. target channels : optional A cell array of strings. This parameter is optional.

Only the first two parameters are mandatory. However, if the marker must target some channels, then you will have to specify parameter 3 and 4 as well.

Let see an example of adding markers:

function main()
   % .. 
   % Add a simple marker:
   AwAddMarker('My Marker', 2.0);   % this will add a marker named My Marker at position 2s in AnyWave.
   % Add a marker with a duration:
   AwAddMarker('My selection', 3.0, -1, 5); % this will add a marker named My selection at position 3s, with a value of -1 and a duration of 5s
   % Add a marker with a value:
   AwAddMarker('My Marker 2', 1, 12); % this will add a marker named My Marker 2, at position 1s with a value of 12
   % Add a marker which targets a particular channel
   AwAddMarker('My Marker 3', 4, -1, 0, {'A12'});
  % add a marker named My Marker 3, at position 4s, with no value (-1), no duration (0) but which targets channel A12
end

Note: Markers can have similar labels and can overlap.

AwGetMarkers(<keyword>, <keyword parameter>)

This function will return Markers currently present in AnyWave. If no parameters are specified, the function returns all the markers handle by AnyWave.

The Markers are returned as an array of structures. Let see the format of a marker structure:

marker.label = 'Marker Label';
marker.start = 0.; % position in seconds from the beginning of the file.
marker.duration = 0.; % duration in seconds. If 0. then the marker is a single marker which marks an event in time.
marker.value = -1; % Associated value. 
% The value is an integer (INT16). -1 indicates that no value is currently associated with the marker.
marker.channels = {'A1', 'A2'}; % a Cell array of strings indicating the channels that are targeted by the marker.
% Can be empty if the marker is global to all channels.

Optional parameters

It is possible to only ask for a subset of the markers currently active in AnyWave. The keyword parameter permits to ask for markers references by their values or by theirs labels.


keyword = 'By Value'
This indicates that we want markers which have a specified value. The second parameter must be the value.
Example:

markers = AwGetMarkers('By Value', 10);
 
% markers will contain structures corresponding to markers with a value 10
% ATTENTION : markers can be an empty array if no markers matches the request.

keyword = 'By Label'
This indicates that we want markers which have a specified label. The second parameter must be the label.
Example:

markers = AwGetMarkers('By Label', 'Stimulus 1');
 
% markers will contain structures corresponding to markers with a label set to Stimulus 1
% ATTENTION : markers can be an empty array if no markers matches the request.

AwSendMessage(message)

This function sends a text message to AnyWave. The message will appear in the Processes console in AnyWave and also in the plugin's log.

Example:

channels = AwGetData(0, -1); % get all data
 
for (i=1:numel(channels)
   AwSendMessage(sprintf('Processing channel %d', i));
   % do something
end

AwIsProcessTerminated

This function will return true or false depending on the action of the user about the currently running plug-in.

This function is usefull when processing heavy and long calculations. If the user want to cancel the current processing, it may be suitable to cancel the current calculation running in MATLAB as well.

Example:

channels = AwGetData(0, -1); % get all data
 
% 
for (i=1:numel(channels)
    if (~AwProcessIsTerminated())
         % do some heavy calculation on a data contained in channel
   end
end