Difference between revisions of "AnyWave:WriteMatlabScripted"

From WikiMEG
Jump to: navigation, search
(M)
(main.m)
 
(75 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
=Introduction=
 
=Introduction=
 
This section targets people who have a good knowledge and practice of the MATLAB programming language.<br/>
 
This section targets people who have a good knowledge and practice of the MATLAB programming language.<br/>
The purpose is to explain how to write a MATLAB function that will be the heart of the plug-in.<br/>
+
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.<br/>
 
We will also explain how to create a text file to describe our plug-in to AnyWave<br/>
 
We will also explain how to create a text file to describe our plug-in to AnyWave<br/>
 +
The AnyWave-MATLAB API consists in a set of MATLAB functions. They will be described in details in a dedicated section.<br/>
  
The AnyWave-MATLAB API (Application Programming Interface) which is a set a MATLAB functions, will be described in details, with examples to illustrate their use.
+
=Setup the plugin folder=
 +
The first thing to do is to create the basic structure for a plug-in.<br/>
 +
A MATLAB Scripted plug-in is very simple: it is a folder containing at least two files.<br/>
  
=Where to start?=
+
Let's begin by creating a folder (called MyPlugin) somewhere on the computer.<br/>
The first thing to do is to create the basic structure for a plug-in.<br/>
+
A Matlab Scripted plug-in is very simple, it is a folder containing at least two files.<br/>
+
<br/>
+
Let's begin by creating a folder somewhere on the computer, called '''MyPlugin'''.<br/>
+
 
This can be done in MATLAB: create a folder and create a new function called '''main''' in that folder.<br/>
 
This can be done in MATLAB: create a folder and create a new function called '''main''' in that folder.<br/>
 
The main function is '''MANDATORY'''. It will be the main function AnyWave will call to execute our plugin.<br/>
 
The main function is '''MANDATORY'''. It will be the main function AnyWave will call to execute our plugin.<br/>
Line 29: Line 28:
 
name = My Matlab Plugin
 
name = My Matlab Plugin
 
description = I am a plug-in written in Matlab
 
description = I am a plug-in written in Matlab
 +
category = Process:MATLAB:My MATLAB Plugin
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
The syntax is to set keywords and values.<br /><br />
  
That's enough to make our plugin visible and usable by AnyWave.
+
Here we have three keywords (name, description, category).<br />
 
+
Two keywords are mandatory : name and description. Other keywords are optional.<br />
=Copy the plug-in to the right location=
+
==desc.txt keywords==
We are ready to add the plug-in to AnyWave.
+
Some keywords may have several values. Separate the values by the colon character ''':''' <br/>
 
+
The table below shows all the keywords handled by AnyWave and their functions.<br/>
Copy the folder MyPlugin to your user's AnyWave plugins directory. Remember to place it in the Matlab subfolder.
+
For example on Windows:
+
[[File:Matlab3.png|center]]
+
 
+
As you can see MyPlugin in 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.
+
[[File:Matlab4.png|center]]
+
 
+
=AnyWave-MATLAB functions=
+
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.
+
 
+
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! Function !! Short description
+
! keyword !! description !! type
 
|-
 
|-
| '''AwGetInputChannels'''() || Get current input channels set by AnyWave for the plug-in.
+
| name || the name of your plugin. Must be unique.|| MANDATORY
 
|-
 
|-
| '''AwGetData'''(start, duration, <filtering>, <filteringOptions>) || Get the data of the current input channels.
+
| description || short description || MANDATORY
 
|-
 
|-
| '''AwGetWorkingDir'''() || Get the full path to a temporary directory created by AnyWave for the plug-in.
+
| category || Where to link the plugin in AnyWave menus || OPTIONAL
 
|-
 
|-
| '''AwGetFilePath'''() || Get the full path of the current open data file in AnyWave.
+
| input_flags || what is required for input || OPTIONAL
 
|-
 
|-
| '''AwGetMarkers'''(<keyword>, <value>) || Get markers from AnyWave.
+
| flags || The plugin special flags || OPTIONAL
|-
+
| '''AwAddMarker'''(label, position, <value>, <duration>, <targeted channels>) || Add a marker in AnyWave.
+
|-
+
| '''AwSendMessage'''(message) || Send a message to AnyWave. The message will be added to the plug-in's log.
+
|-
+
| '''AwIsProcessTerminated'''() || Returns true if the process has been aborted by the user in AnyWave.
+
 
|}
 
|}
  
==AwGetInputChannels()==
+
===category===
AnyWave uses channels to represent signals on screen but also as its internal data set.<br/>
+
'''category:''' It tells AnyWave where the plug-in will appear in the menus. Here, we decided to make it appear under the Python sub-menu in the Processes main menu.<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 category feature is usefull to separate plug-ins by theme.<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/>
+
Three category keywords are recognized:<br/>
<br/>
+
* Process :  The plug-in will be set in the Processes menu with a subcategory and a name, for example 'Process:Correlation:Compute correlation'
'''AwGetInputChannels()''' will request the list of input channels for the plug-in. No parameters are required.<br/>
+
* File: The plug-in will be set in the File Menu under the Export sub-menu. Example : 'File:Export to file.'
AnyWave will send back a structure array containing MATLAB structures which match the structure defined by the '''AwChannel()''' function.<br/>
+
* View: The plug-in will be set in the View Menu. Example : 'View:Launch 3D viewer'
'''AwChannel()''' is provided by AnyWave to easily create a MATLAB structure which will be compatible with AnyWave's channels objects.<br/>
+
If no category is specified, AnyWave will set the plug-in in the Processes menu using the name defined in the file.<br/>
 
<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/>
+
===input_flags===
<syntaxhighlight lang="matlab">
+
'''input_flags:''' a list a ":" separated strings that set the input flags for the plugin.<br/>
function main()
+
%MAIN Summary of this function goes here
+
%  Detailed explanation goes here
+
 
+
channels = AwGetInputChannels();
+
disp('Input channels:');
+
for i=1:numel(channels)
+
    fprintf('name: %s', channels(i).name);
+
    fprintf('ref: %s', channels(i).ref);
+
    fprintf('sampling rate: %g Hz', channels(i).samplingRate);
+
end
+
 
+
end
+
</syntaxhighlight>
+
 
+
As explained above, the channels variable is a MATLAB array of structs filled by AnyWave.<br/>
+
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/>
+
 
+
==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"
 
{| class="wikitable"
 
|-
 
|-
! Parameter!! Description
+
! input_flag !! description
 
|-
 
|-
| 1. start || The position in file in seconds.
+
| GetAllMarkers || AnyWave will copy all the markers and set them as input for the plugin. This will impact aw_getmarkers() function.
 
|-
 
|-
| 2. duration || Duration in seconds of the data or -1 to get ALL data in the file. (could be memory consuming).
+
| GetDurationMarkers || AnyWave will copy markers with a duration and set them as input. This will impact aw_getmarkers() function
 
|-
 
|-
| 3. filtering keyword : optional || A string representing filtering options to apply on data.
+
| ProcessIgnoresChannelSelection || The plugin will be run without using the selected channels as input by default.
 
|-
 
|-
| filtering keyword:'No Filtering' || Request data with no filtering: AnyWave will send data as they are in the file.
+
| ProcessRequiresChannelSelection || The plugin will only run if the user has selected channels.
 
|-
 
|-
| filtering keyword:'User Filtering Options' || Apply specific filtering options on data. That implies the use of the fourth parameter.
+
| GetAsRecordedChannels || AnyWave will copy all the as recorded channels found in the current file as input for the plugin. This will impact aw_getdata() function.
|-
+
|-  
| 4. filtering options : optional || optional if no filtering keyword is set or if the fileting keyword is 'No Filtering'.
+
| GetCurrentMontage || AnyWave will copy the current montaged channels and set them as input for the plugin. This will impact aw_getdata() function.
 
|}
 
|}
 
+
Example of desct.txt with input_flags:<br/>
filtering options must be a structure that matches the one generated by the AwFilteringOptions() MATLAB function:<br/>
+
<syntaxhighlight lang="text">
<syntaxhighlight lang="matlab">
+
name = MyPlugin
function [ foptions ] = AwFilteringOptions()
+
description = do something in MATLAB
foptions.meg_high = 0.;
+
category = Process:Test:MyPlugin
foptions.meg_low = 0.;
+
input_flags = ProcessIgnoresChannelSelection:GetAllMarkers
foptions.eeg_high = 0.;
+
foptions.eeg_low = 0.;
+
foptions.emg_high = 0.;
+
foptions.emg_low = 0.;
+
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/>
+
===flags===
The structure can then be modified to specify custom filtering options.<br/>
+
flags are used to configure the plugin capabilities.<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/>
+
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">
+
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.
+
channels = AwGetData(0, 20);
+
% plot only the first channel.
+
plot(channels(1).data);
+
% Wait for the user to close the figure.
+
uiwait();
+
 
+
end
+
</syntaxhighlight>
+
 
+
Like in the AwGetInputChannels() example above, channels will be an array of structures containing informations about input channels.<br/>
+
The difference here is that the data are provided by AnyWave. The data vector for a channel is available in the field named '''data'''.
+
 
+
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
+
</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>
+
==AwGetFilePath()==
+
This function returns the complete path to the current data file open by AnyWave. That could be usefull, for example, if we want to copy and rename the data file.
+
==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/>
+
A marker must have a name or label and a position in the file.<br/>
+
A marker could also have an integer value, a duration in seconds (a selection of samples) and can target one or several particular channels.<br/>
+
 
+
===Parameters===
+
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! Parameter!! Description
+
! flag !! 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.
+
| NoDataRequired or ProcessDoesntRequireData || indicates the plugin doesn't need a file to be open in AnyWave to run.
 
|-
 
|-
| 5. target channels : optional || A cell array of strings. This parameter is optional.
+
| CanRunFromCommandLine || indicates that the plugin can also run in batch mode and using the command line.
 
|}
 
|}
  
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.
+
=main.m=
 
+
This is the entry point function called by AnyWave.<br/>
Let see an example of adding markers:
+
Depending on the type of plugin you are writing, you may have to setup some variables in this file as an initialisation:<br>
 +
Indeed, you may decide to compile your plugin to distribute it as a standalone software. In this case, use the following code in your main.m:<br/>
 
<syntaxhighlight lang="matlab">
 
<syntaxhighlight lang="matlab">
function main()
+
function main(varargin)
  % ..
+
global args;
   % Add a simple marker:
+
if isdeployed
   AwAddMarker('My Marker', 2.0);  % this will add a marker named My Marker at position 2s in AnyWave.
+
% STANDALONE AnyWave Plugin code
  % Add a marker with a duration:
+
   global host;
   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
+
   global port;
  % Add a marker with a value:
+
  global pid;
  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
+
  if (nargin < 3)
  AwAddMarker('My Marker 3', 4, -1, 0, {'A12'});
+
      error('missing arguments.');
   % add a marker named My Marker 3, at position 4s, with no value (-1), no duration (0) but which targets channel A12
+
  end
 +
  host = varargin{1};
 +
  port = str2num(varargin{2});
 +
   pid = str2num(varargin{3});
 +
  if (nargin > 3)
 +
    args = varargin{4};
 +
  end
 +
    
 +
  assignin('base', 'host', host);
 +
  assignin('base', 'port', port);
 +
  assignin('base', 'pid', pid);
 +
   assignin('base', 'args', args);
 +
% end of STANDALONE AnyWave Plugin code
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
'''Note:''' Markers can have similar labels and can overlap.
+
=Copy the plug-in to the right location=
 +
We are ready to add the plug-in to AnyWave.
  
==AwGetMarkers(<keyword>, <keyword parameter>)==
+
Copy the folder MyPlugin to your user's AnyWave plugins directory. Remember to place it in the Matlab subfolder.
This function will return Markers currently present in AnyWave. If no parameters are specified, the function returns all the markers handle by AnyWave.
+
For example on Windows:
 +
[[File:Matlab3.png|center]]
  
The Markers are returned as an array of structures. Let see the format of a marker structure:
+
As you can see MyPlugin is located in the user's AnyWave path for Matlab Scripted plug-ins.
<syntaxhighlight lang="matlab">
+
 
marker.label = 'Marker Label';
+
=Use the plug-in in AnyWave=
marker.position = 0.; % position in seconds from the beginning of the file.
+
Launch AnyWave: the plug-in should be shown as available.
marker.duration = 0.; % duration in seconds. If 0. then the marker is a single marker which marks an event in time.
+
[[File:Matlab4.png|center]]
marker.value = -1; % Associated value. The value is an integer (INT16). -1 indicates that no value is currently associated with the marker.
+
marker.targets = {'A1', 'A2'}; % a Cell array of strings indicating the channels that are target by the marker. Can be empty if the marker is global to all channels.
+
</syntaxhighlight>
+

Latest revision as of 14:17, 30 March 2020

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 consists in a set of MATLAB functions. They will be described in details in a dedicated section.

Setup the plugin folder

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 syntax is to set keywords and values.

Here we have three keywords (name, description, category).
Two keywords are mandatory : name and description. Other keywords are optional.

desc.txt keywords

Some keywords may have several values. Separate the values by the colon character :
The table below shows all the keywords handled by AnyWave and their functions.

keyword description type
name the name of your plugin. Must be unique. MANDATORY
description short description MANDATORY
category Where to link the plugin in AnyWave menus OPTIONAL
input_flags what is required for input OPTIONAL
flags The plugin special flags OPTIONAL

category

category: It tells AnyWave where the plug-in will appear in the menus. Here, we decided to make it appear under the Python sub-menu in the Processes main menu.
The category feature is usefull to separate plug-ins by theme.
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 file.'
  • 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.

input_flags

input_flags: a list a ":" separated strings that set the input flags for the plugin.

input_flag description
GetAllMarkers AnyWave will copy all the markers and set them as input for the plugin. This will impact aw_getmarkers() function.
GetDurationMarkers AnyWave will copy markers with a duration and set them as input. This will impact aw_getmarkers() function
ProcessIgnoresChannelSelection The plugin will be run without using the selected channels as input by default.
ProcessRequiresChannelSelection The plugin will only run if the user has selected channels.
GetAsRecordedChannels AnyWave will copy all the as recorded channels found in the current file as input for the plugin. This will impact aw_getdata() function.
GetCurrentMontage AnyWave will copy the current montaged channels and set them as input for the plugin. This will impact aw_getdata() function.

Example of desct.txt with input_flags:

name = MyPlugin
description = do something in MATLAB
category = Process:Test:MyPlugin
input_flags = ProcessIgnoresChannelSelection:GetAllMarkers

flags

flags are used to configure the plugin capabilities.

flag description
NoDataRequired or ProcessDoesntRequireData indicates the plugin doesn't need a file to be open in AnyWave to run.
CanRunFromCommandLine indicates that the plugin can also run in batch mode and using the command line.

main.m

This is the entry point function called by AnyWave.
Depending on the type of plugin you are writing, you may have to setup some variables in this file as an initialisation:
Indeed, you may decide to compile your plugin to distribute it as a standalone software. In this case, use the following code in your main.m:

function main(varargin)
global args;
if isdeployed
% STANDALONE AnyWave Plugin code
   global host;
   global port;
   global pid;
 
   if (nargin < 3)
       error('missing arguments.');
  end
  host = varargin{1};
  port = str2num(varargin{2});
  pid = str2num(varargin{3});
  if (nargin > 3)
    args = varargin{4};
  end
 
  assignin('base', 'host',  host);
  assignin('base', 'port', port);
  assignin('base', 'pid', pid);
  assignin('base', 'args', args);
% end of STANDALONE AnyWave Plugin code
end

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