How to write your own process

Brainstorm offers a flexible plug-in structure. All the operations available when using the Process1 and Process2 tabs, which means most of the Brainstorm features, are in fact written as plug-ins.

This tutorial looks long and complicated, but don't let it scare you. Putting your code in a process is not so difficult. The first part in an exaustive reference manual that details all the possible options, you don't need to understand it completely. The second part explains how to copy an existing process and modify it to do what you want.

introPipeline.gif

Process folders

A Brainstorm plug-in, or "process", is a single Matlab .m script that is automatically identified and added to the menus in the pipeline editor. Two folders are parsed for plug-ins:

If you write a valid process function and place it in one of those folders, it will become automatically available in the pipeline editor menus, when you use the Process1 or Process2 tabs.

Send it to another Brainstorm user and your code will be automatically available into the other person's Brainstorm interface. It is a very efficient way solution for exchanging code without the nightmare of understanding what are the inputs of the functions (units of the values, dimensions of the matrices, etc.).

Structure of the process scripts

Sub-functions

A process function must be named "process_...m" and located in one of the two process folders in order to be recognized by the software. Let's call our example function "process_test.m". It contains at least 4 functions:

You are free to add as many sub-functions as needed to the process file. If your process needs some sub-functions to run, it is preferable to copy the full code directly into the "process_test.m" code, rather than leaving it in separate functions. This way it prevents from spreading subfunctions everywhere, which get later lost or forgotten in the distribution when the process is deleted. It might be incomfortable at the beginning if you are not used to work with scripts with over 100 lines, but you'll get used to it, the Matlab code editor offers many solution to make long scripts easy to edit (cells, code folding...). It makes your process easier to maintain and to exchange with other users, which is important in the long run.

Optional function: Compute()

Some processes can be designed to be called at the same time from the Brainstorm context, to work as a plug-in, and directly from the Matlab command line or a script, independently from the Brainstorm database and plug-in system.

In this case, we can leave what is specific to the Brainstorm structure in the Run() function, and move the real computation to additional sub-functions. In this case, we recommend that you respect the following convention: name the main external sub-function Compute().

Example: Z-score

Let's take the example of the process "Standardize > Z-score (static)", which is described in the function process_zscore.m. The function Run() reads and tests the options defined by the user and then calls Compute(), which is responsible from calculating the z-score normalization.

function sInput = Run(sProcess, sInput)
    % Get inputs
    iBaseline = panel_time('GetTimeIndices', sInput.TimeVector, sProcess.options.baseline.Value{1});
    [...]
    % Compute zscore
    sInput.A = Compute(sInput.A, iBaseline);
    [...]
end

The function Compute() calls another function ComputeStat():

function A = Compute(A, iBaseline)
    % Calculate mean and standard deviation
    [meanBaseline, stdBaseline] = ComputeStat(A(:, iBaseline,:));
    % Compute zscore
    A = bst_bsxfun(@minus, A, meanBaseline);
    A = bst_bsxfun(@rdivide, A, stdBaseline);
end

function [meanBaseline, stdBaseline] = ComputeStat(A)
    % Compute baseline statistics
    stdBaseline  = std(A, 0, 2);
    meanBaseline = mean(A, 2);
    % Remove null variance values
    stdBaseline(stdBaseline == 0) = 1e-12;
end

This mechanism allows us to access this z-score function at different levels. We can call it as a Brainstorm process that takes Brainstorm structures in input (this is usually not done manually, but by the pipeline editor or by bst_process):

sInput = process_zscore('Run', sProcess, sInput);

Or as regular functions that take standard Matlab matrices in input:

% Generate some random signal
F = rand(1,500);  ind = 1:100;

% Normalize the signal
F = process_zscore('Compute', F, ind);

% Or just calculate its average and standard deviation
[Favg, Fstd] = process_zscore('ComputeStat', F);

Process description

The function GetDescription() creates a structure sProcess that documents the process: its name, the way it is supposed to be used in the interface and all the options it needs. It contains the following fields:

Not all the fields have to be defined in the function GetDescription(). The missing ones will be set to their default values, as defined in db_template('ProcessDesc').

Definition of the options

Categories of process

There are three different types of processes: Filter, File, Custom. The category of the process is defined by the field sProcess.Category.

Filter

Brainstorm processes independently each file in the input list (the files that have been dropped in the Process1 or Process2 files lists) and is responsible for the following operations:

In the process, the function Run():

Advantages: All the complicated things are taken care of automatically, the functions can be very short.

Limitations: There is no control over the file names and locations, one file in input = one file in output, and the file type cannot be changed (InputTypes=OutputTypes).

For example, let's consider one of the simplest processes: process_absolute.m. It just calcuates the absolute value of the input data matrix. The Run() function is only one line long:

function sInput = Run(sProcess, sInput)
    sInput.A = abs(sInput.A);
end

The sInput structure

File

Brainstorm processes independently each file in the input list. It just creates a structure sInput , and directly transfers the fil

Custom

Input description

The structure sInput contains the following fields:

Running a process

A pipeline is an array of sProcess structures, that are exectuted one after the other.

Alternative

Run Matlab command

Tutorials/TutUserProcess (last edited 2013-10-11 19:26:42 by 69)