Tutorial 28: Scripting

Authors: Francois Tadel, Elizabeth Bock, Sylvain Baillet, Matthias Sure

The previous tutorials explained how to use Brainstorm in an interactive way to process one subject with two acquisition runs. In the context of a typical neuroimaging study, you may have tens or hundreds of subjects to process in the same way, it is unrealistic to do everything manually. Some parts of the analysis can be processed in batches with no direct supervision, others require more attention. This tutorial introduces tools and tricks that will help you assemble an efficient analysis pipeline.

Requirements: You need a license for the Matlab environment in order to use these tools and execute custom scripts. If you are running the compiled version of Brainstorm with the MCR library, the only custom code you can run is through the menu "File > Matlab console" and the process "Run Matlab command".

Starting a new script

The easiest way to get started with a new Brainstorm script is to use the script generator, already introduced in the tutorial Select files and run processes. Select some files in the Process1 or Process2 tabs, select a list of processes, and use the menu Generate .m script. The example below should work with the protocol "TutorialIntroduction" created during the introduction tutorials.

Line by line: Header

% Script generated by Brainstorm (19-Jul-2016)

All the lines starting with a "%" are comments, they are never executed.

% Input files
sFiles = [];
SubjectNames = {...
    'Subject01'};

These lines define the script inputs:

% Start a new report
bst_report('Start', sFiles);

Starts a new report of activity: Clears all the previous logs and gets ready to record new messages. The report will collect all the messages that are generated during the execution of the script by the various processes. You can explicitly add screen captures and additional messages to the current report with the function bst_report. This report will remain open until the function bst_report('Start') is called again. To display the current report, use the menu File > Report viewer.

The syntax function_name('SubFunction', arguments) is used a lot in Brainstorm: it calls a subfunction available inside a .m file. This line above calls the function Start() in the file brainstorm3/toolbox/process/bst_report.m. This is made possible with the use of the short script "macro_method". Many of the Brainstorm .m files are actually libraries of functions, rather than simple "scripts" or "functions".

Line by line: Body

% Process: Select data files in: Subject01/*/Avg: deviant
sFiles = bst_process('CallProcess', 'process_select_files_data', sFiles, [], ...
    'subjectname',   SubjectNames{1}, ...
    'condition',     '', ...
    'tag',           'Avg: deviant', ...
    'includebad',    0, ...
    'includeintra',  0, ...
    'includecommon', 0);

% Process: Low-pass:30Hz
sFiles = bst_process('CallProcess', 'process_bandpass', sFiles, [], ...
    'sensortypes', 'MEG', ...
    'highpass',    0, ...
    'lowpass',     30, ...
    'attenuation', 'strict', ...  % 60dB
    'mirror',      0, ...
    'useold',      0, ...
    'overwrite',   0);

% Process: Snapshot: Recordings time series
sFiles = bst_process('CallProcess', 'process_snapshot', sFiles, [], ...
    'target',         5, ...  % Recordings time series
    'modality',       1, ...  % MEG (All)
    'orient',         4, ...  % bottom
    'time',           0.11, ...
    'contact_time',   [0, 0.1], ...
    'contact_nimage', 12, ...
    'threshold',      20, ...
    'Comment',        'Run');

You will find one block per process you selected in the pipeline editor. They all have the same syntax:
output_files = bst_process('CallProcess', process_name, input_files_A, input_files_B, options_list);

% Save and display report
ReportFile = bst_report('Save', sFiles);

Closes the current report and saves it in the user report folder ($HOME/.brainstorm/reports). These reports are in .mat format and contain all the information necessary to re-run the execution exactly in the same way, but they are not easy to read.

The parameter "sFiles" is optional, it indicates what are the files that are considered as the final results of the script. You can remove it without breaking your script: ReportFile = bst_report('Save');

bst_report('Open', ReportFile);

Opens the report viewer to display what happened during the execution. This is equivalent to using the menu File > Report viewer. You can comment this line (ie. add a "%" at the beginning of the line) if you don't want to show the report at the end of the execution.

% bst_report('Export', ReportFile, ExportDir);

This function exports the report in readable format, as an HTML file that includes all the screen captures embedded in it. It is disabled by default. If you want to use this feature: remove the "%" at the beginning of the line, and define the variable ExportDir.

ExportDir must be a string that defines where to save the HTML report. It can be either the absolute path to a HTML file (eg. 'C:\Users\myuser\Documents\report_example.html') or just a folder (eg. 'C:\Users\myuser\Documents'). If you enter only a path to a folder, a default file name including the protocol name and a date tag is generated (report_ProtocolName_YYMMDD_HHMMSS.html).

Simplify the calls

The script you generated is like any Matlab script: you can edit it, rename the variables, add tests and loops, etc. The first important thing to understand is how to edit the options and change the inputs/outputs. The script generator uses only one variable for all the file lists (sFiles) and the output process is always the input of the following process. This is usually too restrictive to write a full analysis script: we commonly need to have multiple lists of files or to run two different operations on the same file.

Let's consider the first process call, which selects the averages for the Deviant condition in both runs.

sFiles = bst_process('CallProcess', 'process_select_files_data', sFiles, [], ...
    'subjectname',   SubjectNames{1}, ...
    'condition',     '', ...
    'tag',           'Avg: deviant', ...
    'includebad',    0, ...
    'includeintra',  0, ...
    'includecommon', 0);

There is no need to set the parameter sFiles, because there is no input, you can replace it with an empty matrix []. You can therefore remove the line "sFiles = [];". We can also rename the output variable "sAvgData", to be more specific.

sAvgData = bst_process('CallProcess', 'process_select_files_data', [], [], ...

You can omit all the options that are not defined, not used, or kept to their default values:

sAvgData = bst_process('CallProcess', 'process_select_files_data', [], [], ...
    'subjectname',   SubjectNames{1}, ...
    'tag',           'Avg: deviant');

Edit the call to the low-pass filter: Change the input to sAvgData and the output to sAvgDataLow, this way you will be able to keep track of the two files if you need to use them independently later.

sAvgDataLow = bst_process('CallProcess', 'process_bandpass', sAvgData, [], ...
    'sensortypes', 'MEG', ...
    'highpass',    0, ...
    'lowpass',     30, ...
    'attenuation', 'strict');   % 60dB

Edit the call to the snapshot process: Change the input to sAvgDataLow, and remove the output parameter (we are not expecting any output file from it).

bst_process('CallProcess', 'process_snapshot', sAvgDataLow, [], ...
    'target',   5, ...  % Recordings time series
    'modality', 1);     % MEG (All)

Replace the last lines with the following code, in order to export the report instead of opening in the report viewer (edit the file path to point at your own user folder instead).

ReportFile = bst_report('Save');
bst_report('Export', ReportFile, 'C:\Users\myuser\Documents\report_test.html');

Evaluate in Matlab

Select the code for the first process in the Matlab editor, right-click > Evaluate selection (or press F9).

edit1.gif

If you haven't executed your script yet, you will get the following error in the Matlab command window:

Undefined variable "SubjectNames" or class "SubjectNames".

The variable SubjectNames is not defined yet: Execute the first lines "SubjectNames = {'Subject01'}", then try again. You should now have a new variable in your Matlab workspace, which points at the two average files. Type "sAvgData(1)" in your command window to display the first element:

>> sAvgData(1)
ans =
          iStudy: 6
           iItem: 1
        FileName: '..._01_600Hz_notch/data_deviant_average_160513_1329.mat'
        FileType: 'data'
         Comment: 'Avg: deviant (39 files)'
       Condition: 'S01_AEF_20131218_01_600Hz_notch'
     SubjectFile: 'Subject01/brainstormsubject.mat'
     SubjectName: 'Subject01'
        DataFile: ''
     ChannelFile: 'Subject01/S01_AEF_20131218_01_600Hz_notch/channel_ctf_acc1.mat'
    ChannelTypes: {'ADC A'  'ADC V'  'DAC'  'ECG'  'EOG'  'MEG'  'MEG REF' ...}

The field "sAvgData(1).FileName" contains the relative path to the to the Deviant average in the first run. This structure sAvgData contains also a lot of information that can be helpful in your script:

Naming conventions

To help you navigate in the Brainstorm code, here are some naming conventions:

Running the script

The simplified script looks like this:

% Input files
SubjectNames = {'Subject01'};
% Start a new report
bst_report('Start');

% Process: Select data files in: Subject01/*/Avg: deviant
sAvgData = bst_process('CallProcess', 'process_select_files_data', [], [], ...
    'subjectname',   SubjectNames{1}, ...
    'tag',           'Avg: deviant');
% Process: Low-pass:30Hz
sAvgDataLow = bst_process('CallProcess', 'process_bandpass', sAvgData, [], ...
    'sensortypes', 'MEG', ...
    'highpass',    0, ...
    'lowpass',     30, ...
    'attenuation', 'strict');  % 60dB
% Process: Snapshot: Recordings time series
bst_process('CallProcess', 'process_snapshot', sAvgDataLow, [], ...
    'target',   5, ...  % Recordings time series
    'modality', 1);     % MEG (All)

% Save and display report
ReportFile = bst_report('Save');
bst_report('Export', ReportFile, 'C:\Users\franc\Documents\report_test.html');

You have three ways to execute it:

At the end of the execution, nothing happens, because we indicated we wanted to export the report instead of opening it. To check out the report of execution: use the menu File > Report viewer from the Brainstorm window, or open the file report_test.html that was saved somewhere on your computer.

In this page, you can review everything that happened in the script: when it was executed, how long it took, what are the processes that were executed, some additional messages (two files were selected with the first process) and the screen captures taken by process_snapshot.

Running the script again

If you execute the script again, it will not behave as expected anymore. The selection process we used assumes that there is only one file per folder with a comment that includes "Avg: deviant". This is not the case anymore after the execution, because the low-pass filtered files also contain the same string. The execution of the first process of the script now returns 4 files.

>> sAvgData = bst_process('CallProcess', 'process_select_files_data', [], [], ...
    'subjectname',   SubjectNames{1}, ...
    'tag',           'Avg: deviant')

sAvgData =
1x4 struct array with fields:
    iStudy
    iItem
    ...

In order to exclude the low-pass filtered files from this selection, you can add another process that will refine the selection. Use the script generator again to create a template call for another process, then copy-paste it in your script.

Now the file selection part of your script should look like this, and should return only two files:

% Process: Select data files in: Subject01/*/Avg: Deviant
sAvgData = bst_process('CallProcess', 'process_select_files_data', [], [], ...
    'subjectname',   SubjectNames{1}, ...
    'tag',           'Avg: deviant');
% Process: Ignore file comments with tag: low
sAvgData = bst_process('CallProcess', 'process_select_tag', sAvgData, [], ...
    'tag',    'low', ...
    'search', 2, ...  % Search the file comments
    'select', 2);  % Ignore the files with the tag

With this last modification, your script is more robust. It can be executed multiple times without completely changing its behavior. When you are fetching files from the database using comment tags or file names, always pay attention to this aspect: the database grows and the further you go, the more specific your requests have to be.

A good practice can be to tag explicitly the output files your script generates if you need to fetch them later. You can use the process File > Add tag and File > Set comment.

Starting Brainstorm

Brainstorm must be running in the background for these scripts to run properly. The interface doesn't have to be visible on the screen, but the database engine must be running for processing requests. At the beginning of your script, you can explicitly start or restart Brainstorm.

If you want to start Brainstorm only if it is not already running, you can use the following code:

if ~brainstorm('status')
    brainstorm nogui
end

To select a specific protocol at the beginning of your script:

ProtocolName = 'TutorialIntroduction';
% Get the protocol index
iProtocol = bst_get('Protocol', ProtocolName);
if isempty(iProtocol)
    error(['Unknown protocol: ' ProtocolName]);
end
% Select the current procotol
gui_brainstorm('SetCurrentProtocol', iProtocol);

To delete the protocol and start over:

% Delete existing protocol
gui_brainstorm('DeleteProtocol', ProtocolName);
% Create new protocol
gui_brainstorm('CreateProtocol', ProtocolName, 0, 0);

Additional command line options:

brainstorm stop      % Quit Brainstorm
brainstorm update    % Download and install latest Brainstorm update (see bst_update)
brainstorm reset     % Re-initialize Brainstorm database and preferences
brainstorm digitize  % Digitize electrodes positions and head shape using a Polhemus
brainstorm setpath   % Add Brainstorm subdirectories to current path
brainstorm info      % Open Brainstorm website
brainstorm forum     % Open Brainstorm forum
brainstorm license   % Display license

Database requests

The functions bst_get and bst_set allow you to query the database, access the configuration of the software and modify some display parameters. The complete reference documentation of these functions is included directly in their code (brainstorm3/toolbox/core/bst_get.m and bst_set.m).

Let's start with a few simple examples:

>> ProtocolInfo = bst_get('ProtocolInfo')  % Configuration of the current protocol
ProtocolInfo =
              Comment: 'TutorialIntroduction'
              STUDIES: 'C:\Work\Protocols\TutorialIntroduction\data'
             SUBJECTS: 'C:\Work\Protocols\TutorialIntroduction\anat'
               iStudy: 6
       UseDefaultAnat: 0
    UseDefaultChannel: 0

>> isGUI = bst_get('isGUI')   % Is the Brainstorm interface displayed (0=no, 1=yes)

>> bst_set('FlipYAxis', 1)                 % New figures will have the Y axis flipped
>> bst_set('TSDisplayMode', 'butterfly')   % New figures will use a "butterfly" view
>> bst_set('FieldTripDir', FieldTripDir)   % Set path to the FieldTrip toolbox

To reference the files in the database, each protocol is subdivided in Subjects (the "anat" folder, containing the MRI, surfaces and atlases) and Studies (the "data" folder, including the recordings, channel files and all the analyses). Each Study corresponds to a sub-folder (eg. protocol/data/subject01/run01/), and is attached to only one subject.

Subjects and Studies are referenced in the protocol with a unique index, most of the time kept in variables named iSubject and iStudy. The files available in them are also referenced with indices, with variables such as iAnatomy, iSurface, iData, iHeadModel, iResults or iTimefreq. You can see the indices in the database explorer by hovering your mouse over the nodes files and folders:

db_indices.gif

Example: Getting the study structure from the variable sAvgData, defined in the script:

>> sAvgData(1)
ans =
          iStudy: 6
           iItem: 1
           ...

>> sStudy = bst_get('Study', sAvgData(1).iStudy)   % Get study struct with its index
sStudy =
                 Name: 'S01_AEF_20131218_01_600Hz_notch'
             FileName: 'Subject01/S01_AEF_20131218_01_600Hz_notch/brainstormstudy.mat'
          DateOfStudy: '13-May-2016'
    BrainStormSubject: 'Subject01/brainstormsubject.mat'   % Subject filename
            Condition: {'S01_AEF_20131218_01_600Hz_notch'} % Name of the folder
              Channel: [1x1 struct]       % Channel file
             iChannel: []                 % Not used anymore
                 Data: [1x242 struct]     % List of "data" files in the folder
            HeadModel: [1x1 struct]       % List of head models in the folder
           iHeadModel: 1                  % Default head model (file in green)
               Result: [1x244 struct]     % List of source files and links
                 Stat: [1x0 struct]       % List of statistical results
                Image: [0x0 struct]       % List of images
             NoiseCov: [1x2 struct]       % Noise(1) and data(2) covariance files
              Dipoles: [0x0 struct]       % List of dipole files in the folder
             Timefreq: [1x247 struct]     % List of time-frequency files
               Matrix: [0x0 struct]       % List of "matrix" files in the folder

Example: Getting the data structure.

% Get the structure representing the file from sStudy
>> sData = sStudy.Data(sAvgData(1).iItem)
sData =
    FileName: '..._01_600Hz_notch/data_deviant_average_160513_1329.mat'
     Comment: 'Avg: deviant (39 files)'    % File comment
    DataType: 'recordings'                 % Type of data in the file
    BadTrial: 0                            % If 1, the trial is marked as bad

Example: Getting the subject structure.

% Get subject structure from filename (lists the files in the subject folder)
>> sSubject = bst_get('Subject', sStudy.BrainStormSubject)
sSubject =
                 Name: 'Subject01'    % Subject name, same as folder name
             Comments: ''             % Not used much
             FileName: 'Subject01/brainstormsubject.mat'
    DateOfAcquisition: ''             % Not used anymore
              Anatomy: [1x1 struct]   % List of MRI volumes
              Surface: [1x9 struct]   % List of surfaces
             iAnatomy: 1              % Index of default MRI
               iScalp: 9              % Index of default head surface
              iCortex: 4              % Index of default cortex surface
          iInnerSkull: []             % Index of default inner skull surface
          iOuterSkull: []             % Index of default outer skull surface
               iOther: []             % Not used anymore
       UseDefaultAnat: 0        % If 1: Use the default anatomy
    UseDefaultChannel: 0        % 0=one/folder, 1=one/subject, 2=one global

Example: Getting the study structure and data index from a file name.

>> DataFile = sAvgData(1).FileName
DataFile =
Subject01/..._01_600Hz_notch/data_deviant_average_160513_1329.mat

>> [sStudy, iStudy, iData] = bst_get('DataFile', DataFile)
sStudy =
                 Name: 'S01_AEF_20131218_01_600Hz_notch'
             FileName: '..._01_600Hz_notch/brainstormstudy.mat'
          DateOfStudy: '13-May-2016'
    BrainStormSubject: 'Subject01/brainstormsubject.mat'
            Condition: {'S01_AEF_20131218_01_600Hz_notch'}
              Channel: [1x1 struct]
             iChannel: []
                 Data: [1x242 struct]
            HeadModel: [1x1 struct]
           iHeadModel: 1
               Result: [1x244 struct]
                 Stat: [1x0 struct]
                Image: [0x0 struct]
             NoiseCov: [1x2 struct]
              Dipoles: [0x0 struct]
             Timefreq: [1x247 struct]
               Matrix: [0x0 struct]
iStudy =
     6
iData =
     1

Many other options are available for searching files in the database with bst_get. We cannot list them all in this page, but you can refer to the code of bst_get.m for more information.

1 function [argout1, argout2, argout3, argout4, argout5] = bst_get( varargin ) 2 % BST_GET: Get a Brainstorm structure. 3 % This function is used to abstract the way that these structures are stored. 4 % 5 % USAGE : 6 % ====== DIRECTORIES ================================================================== 7 % - bst_get('UserDir') : User home directory 8 % - bst_get('BrainstormHomeDir') : Application directory of brainstorm 9 % - bst_get('BrainstormUserDir') : User home directory for brainstorm (<home>/.brainstorm/) 10 % - bst_get('BrainstormTmpDir') : User brainstorm temporary directory (Default: <home>/.brainstorm/tmp/) 11 % - bst_get('BrainstormTmpDir', isForcedDefault=0, SubDir=[]) : User DEFAULT brainstorm temporary directory (<home>/.brainstorm/tmp/SubDir) 12 % - bst_get('BrainstormDocDir') : Doc folder folder of the Brainstorm distribution (may vary in compiled versions) 13 % - bst_get('BrainstormDefaultsDir') : Defaults folder of the Brainstorm distribution (may vary in compiled versions) 14 % - bst_get('UserReportsDir') : User reports directory (<home>/.brainstorm/reports/) 15 % - bst_get('UserMexDir') : User temporary directory (<home>/.brainstorm/mex/) 16 % - bst_get('UserProcessDir') : User custom processes directory (<home>/.brainstorm/process/) 17 % - bst_get('UserDefaultsDir') : User defaults directory (<home>/.brainstorm/defaults/) 18 % - bst_get('UserPluginsDir') : User plugins directory (brainstorm3/plugins/ if it exists, otherwise <home>/.brainstorm/plugins/) 19 % - bst_get('BrainstormDbFile') : User brainstorm.mat file (<home>/.brainstorm/brainstorm.mat) 20 % - bst_get('BrainstormDbDir') : User database directory (contains all the brainstorm protocols) 21 % - bst_get('DirDefaultSubject') : Directory name of the default subject 22 % - bst_get('DirDefaultStudy') : Directory name of the default study for each subject 23 % - bst_get('DirAnalysisInter') : Directory name of the inter-subject analysis study 24 % - bst_get('DirAnalysisIntra') : Directory name of the intra-subject analysis study (for each subject) 25 % - bst_get('AnatomyDefaults') : Get the contents of directory bstDir/defaults/anatomy 26 % - bst_get('MniAtlasDefaults') : Get the contents of directory bstDir/defaults/mniatlas 27 % - bst_get('EegDefaults') : Get the contents of directory bstDir/defaults/eeg 28 % - bst_get('LastUsedDirs') : Structure with all the last used directories (last used) 29 % - bst_get('OsType', isMatlab=1) : Get a string that describes the operating system (if isMatlab=1 return the Matlab/JVM platform, else return the real host system) 30 % - bst_get('FileFilters', DataType) : Get the list of import filters for a specific data type 31 % - bst_get('PluginCustomPath') : Full custom path to all plugins 32 % - bst_get('BrainSuiteDir') : Full path to a local installation of BrainSuite 33 % - bst_get('SpmTpmAtlas') : Full path to the SPM atlas TPM.nii 34 % - bst_get('PythonExe') : Path to the python executable 35 % 36 % ====== PROTOCOLS ==================================================================== 37 % - bst_get('iProtocol') : Indice of current protocol 38 % - bst_get('Protocol', ProtocolName): Return the indice of the protocol ProtocolName, or [] if it doesn't exist 39 % - bst_get('ProtocolInfo') : Definition structure for current protocol 40 % - bst_get('ProtocolSubjects') : Subjects list for current protocol 41 % - bst_get('ProtocolStudies') : Studies list for current protocol 42 % - bst_get('isProtocolLoaded') : 1 if the protocol has been loaded, 0 else 43 % - bst_get('isProtocolModified') : 1 if the protocol has been modified, 0 else 44 % 45 % ====== STUDIES ====================================================================== 46 % - bst_get('Study', StudyFileName) : Get one study in current protocol with its file name 47 % - bst_get('Study', iStudies) : Get one or more studies 48 % - bst_get('Study') : Get current study in current protocol 49 % - bst_get('StudyCount') : Get number of studies in the current protocol 50 % - bst_get('StudyWithSubject', SubjectFile) : Find studies associated with a given subject file (WITHOUT the system studies ('intra_subject', 'default_study')) 51 % - bst_get('StudyWithSubject', ..., 'intra_subject') : Find studies ... INCLUDING 'intra_subject' study 52 % - bst_get('StudyWithSubject', ..., 'default_study') : Find studies ... INCLUDING 'default_study' study 53 % - bst_get('StudyWithCondition', ConditionPath) : Find studies for a given condition path 54 % - bst_get('ChannelStudiesWithSubject', iSubjects) : Get all the studies where there should be a channel file for a list of subjects 55 % - bst_get('AnalysisIntraStudy', iSubject) : Get the default analysis study for target subject 56 % - bst_get('AnalysisInterStudy') : Get the default analysis study for inter-subject analysis 57 % - bst_get('DefaultStudy', iSubject) : Get the default study for target subject (by subject indice) 58 % - bst_get('DefaultStudy') : Get the global default study (common to all subjects) 59 % - bst_get('DefaultStudy', SubjectFile) : Get the default study for target subject (by filename) 60 % - bst_get('ChannelFile', ChannelFile) : Find a channel file in current protocol 61 % - bst_get('ChannelFileForStudy', StudyFile/DataFile) : Find a channel file in current protocol 62 % - bst_get('ChannelForStudy', iStudies) : Return current Channel struct for target study 63 % - bst_get('ChannelModalities', ChannelFile) : Return displayable modalities for a Channel file 64 % - bst_get('ChannelModalities', DataFile) : Return displayable modalities for a Data/Results/Timefreq... file 65 % - bst_get('ChannelDevice', ChannelFile) : Return acquisistion device for a channel file 66 % - bst_get('TimefreqDisplayModalities', TfFile) : Get displayable modalities for a TF file based on recordings 67 % - bst_get('HeadModelForStudy', iStudy) : Return current HeadModel struct for target study 68 % - bst_get('HeadModelFile', HeadModelFile) : Find a HeadModel file in current protocol 69 % - bst_get('HeadModelFile', HeadModelFile, iStudies): Find a HeadModel file in current protocol 70 % - bst_get('NoiseCovFile', NoiseCovFile) : Find a noise covariance file file in current protocol 71 % - bst_get('NoiseCovFile', NoiseCovFile, iStudies) : Find a noise covariance file in current protocol 72 % - bst_get('NoiseCovFile', DataCovFile) : Find a data covariance file file in current protocol 73 % - bst_get('NoiseCovFile', DataCovFile, iStudies) : Find a data covariance file file in current protocol 74 % - bst_get('DataFile', DataFile) : Find a DataFile in current protocol 75 % - bst_get('DataFile', DataFile, iStudies) : Find a DataFile in current protocol 76 % - bst_get('DataForDataList', iStudy, DataListName) : Find all the DataFiles grouped by a data list 77 % - bst_get('DataForStudy', iStudy) : Find all the Data files that are dependent on the channel/headmodel of a given study 78 % - bst_get('DataForStudies', iStudies) 79 % - bst_get('DataForChannelFile', ChannelFile) : Find all the DataFiles that use the given ChannelFile 80 % - bst_get('ResultsFile', ResultsFile) : Find a ResultsFile in current protocol 81 % - bst_get('ResultsFile', ResultsFile, iStudies) : Find a ResultsFile in input studies 82 % - bst_get('ResultsForDataFile', DataFile, iStudies): Find all results computed based on DataFile 83 % - bst_get('StatFile', StatFile) : Find a StatFile in current protocol 84 % - bst_get('StatFile', StatFile, iStudies) : Find a StatFile in input studies 85 % - bst_get('StatForDataFile', DataFile, iStudies) 86 % - bst_get('StatForDataFile', DataFile) 87 % - bst_get('TimefreqFile', TimefreqFile) 88 % - bst_get('TimefreqFile', TimefreqFile, iStudies) 89 % - bst_get('TimefreqForFile', FileName, iStudies) : Find all timefreq files computed based on target file 90 % - bst_get('TimefreqForKernel', KernelFile) 91 % - bst_get('DipolesFile', DipolesFile) 92 % - bst_get('DipolesFile', DipolesFile, iStudies) 93 % - bst_get('DipolesForFile', FileName, iStudies) : Find all dipoles files computed based on target file 94 % - bst_get('DipolesForKernel', KernelFile) 95 % - bst_get('MatrixFile', MatrixFile) 96 % - bst_get('MatrixFile', MatrixFile, iStudies) 97 % - bst_get('MatrixForMatrixList', iStudy, MatrixListName) 98 % - bst_get('AnyFile', AnyFile) 99 % - bst_get('AnyFile', AnyFile, iStudies) 100 % - bst_get('RelatedDataFile', FileName) 101 % - bst_get('RelatedDataFile', FileName, iStudies) 102 % - bst_get('GetFilenames') 103 % 104 % ====== SUBJECTS ====================================================================== 105 % - bst_get('Subject', SubjectFileName, isRaw) : Find a subject in current protocol with its file name 106 % - bst_get('Subject', SubjectName, isRaw) : Find a subject in current protocol with its name 107 % - bst_get('Subject', iSubject) : Get a subject (normal or default if iSubject==0) 108 % - bst_get('Subject') : Get current subject in current protocol 109 % - bst_get('SubjectCount') : Get number of studies in the current protocol 110 % - bst_get('NormalizedSubjectName') : Name of the subject with a normalized anatomy 111 % - bst_get('NormalizedSubject') : Get group analysis subject for the current protocol 112 % - bst_get('ConditionsForSubject', SubjectFile) : Find all conditions for a given subject 113 % - bst_get('SurfaceFile', SurfaceFile) : Find a surface in current protocol 114 % - bst_get('SurfaceFileByType', iSubject, SurfaceType) : Find surfaces with given type for subject #i (default only) 115 % - bst_get('SurfaceFileByType', SubjectFile, SurfaceType) : Find surfaces with given type for subject SubjectFile (default only) 116 % - bst_get('SurfaceFileByType', SurfaceName, SurfaceType) : Find surfaces with given type for subject that also has surface SurfaceName (default only) 117 % - bst_get('SurfaceFileByType', MriName, SurfaceType) : Find surfaces with given type for subject that also has MRI MriName (default only) 118 % - bst_get('SurfaceFileByType', ..., ..., isDefaultOnly) : If 0, return all the surfaces of the given type, instead of only the default surface 119 % - bst_get('MriFile', MriFile) : Find a MRI in current protocol 120 % 121 % ====== GUI ================================================================= 122 % - bst_get('BstControls') : Return main Brainstorm GUI structure 123 % - bst_get('BstFrame') : Return main Brainstorm JFrame 124 % - bst_get('isGUI') : Return 1 if the Brainstorm interface is displayed 125 % - bst_get('GuiLevel') : Return GUI level: -1=server, 0=nogui, 1=normal, 2=autopilot 126 % - bst_get('ScreenDef') : Get screens configuration 127 % - bst_get('DecorationSize') : Get dimensions of the windows decorations 128 % - bst_get('Layout') : Configuration of the main Brainstorm window 129 % - bst_get('Layout', prop) : Get one property in the layout properties 130 % - bst_get('PanelContainer') : Display list of registered panel containers 131 % - bst_get('PanelContainer', ContainerName) : Get a panel container handle 132 % - bst_get('Panel') : Display list of registered panels 133 % - bst_get('Panel', PanelName) : Find a panel with its name 134 % - bst_get('PanelControls', PanelName) : Get the controls of a panel 135 % - bst_get('Clipboard') : Nodes that were copied from the interface 136 % - bst_get('FigFont') : Standard font size displayed in the figures 137 % - bst_get('Font') : Create a Java font, scaled for the operating system 138 % 139 % ====== CONFIGURATION ================================================================= 140 % - bst_get('Version') : Brainstorm version 141 % - bst_get('MatlabVersion') : Matlab version (version number * 100, eg. 801) 142 % - bst_get('MatlabReleaseName') : Matlab version (release name, eg. "R2014a") 143 % - bst_get('JavaVersion') : Java version 144 % - bst_get('isJavacomponent') : Returns 1 if javacomponent is available (Matlab < 2019b), 0 otherwise 145 % - bst_get('SystemMemory') : Amount of memory available, in Mb 146 % - bst_get('ByteOrder') : {'l','b'} - Byte order used to read and save binary files 147 % - bst_get('TSDisplayMode') : {'butterfly','column'} 148 % - bst_get('ElectrodeConfig', Modality) : Structure describing the display values for SEEG/ECOG/EEG contacts 149 % - bst_get('ElecInterpDist', Modality) : Structure describing the maximum distance for interpolating SEEG/ECOG/EEG values onto a surface 150 % - bst_get('AutoUpdates') : {0,1} - If 1, check automatically for updates at startup 151 % - bst_get('ForceMatCompression') : {0,1} - If 1, always save mat-files using the v7 format instead of v6 152 % - bst_get('IgnoreMemoryWarnings') : {0,1} - If 1, do not display memory warnings at the Brainstorm startup 153 % - bst_get('ExpertMode') : {0,1} - If 1, show advanced options that regular user do not see 154 % - bst_get('DisplayGFP') : {0,1} - If 1, the GFP is displayed on all the time series figures 155 % - bst_get('DownsampleTimeSeries') : {0,1,...} - If > 0, downsample dense time series for faster display 156 % - bst_get('DisableOpenGL') : {0,1,2} - If 1, do not use OpenGL renderer; if 2, use software OpenGL 157 % - bst_get('InterfaceScaling') : {100,125,150,...} - Scales the Brainstorm GUI by a fixed factor 158 % - bst_get('GraphicsSmoothing') : {0,1} - If 1, uses the graphics smoothing (Matlab >= 2014b) 159 % - bst_get('SystemCopy') : {0,1} - If 1, uses the system calls mv/cp instead of movefile/copyfile (Linux only) 160 % - bst_get('DefaultFormats') : Default formats for importing/exporting data, channels, ... (last used) 161 % - bst_get('BFSProperties') : Conductivities and thicknesses for 3-shell spherical forward model 162 % - bst_get('ImportDataOptions') : Import options for recordings 163 % - bst_get('ImportEegRawOptions') : Importation options for RAW EEG format 164 % - bst_get('BugReportOptions') : Bug reporter options 165 % - bst_get('DefaultSurfaceDisplay') : Default display options for surfaces (smooth, data threshold, sulci map) 166 % - bst_get('MagneticExtrapOptions') : Structure with the options for magnetic field extrapolation 167 % - bst_get('DefaultFreqBands') 168 % - bst_get('TimefreqOptions_morlet') 169 % - bst_get('TimefreqOptions_fft') 170 % - bst_get('TimefreqOptions_psd') 171 % - bst_get('TimefreqOptions_hilbert') 172 % - bst_get('OpenMEEGOptions') 173 % - bst_get('DuneuroOptions') 174 % - bst_get('GridOptions_headmodel') 175 % - bst_get('GridOptions_dipfit') 176 % - bst_get('UniformizeTimeSeriesScales') : {0,1} - If 1, the Y-axis of all the time series figures have the scale 177 % - bst_get('FlipYAxis') : {0,1} - If 1, the recordings are displayed with the negative values UP 178 % - bst_get('AutoScaleY') : {0,1} - If 1, the axis limits are updated when the figure is updated 179 % - bst_get('ShowXGrid') : {0,1} - If 1, show the XGrid in the time series figures 180 % - bst_get('ShowYGrid') : {0,1} - If 1, show the YGrid in the time series figures 181 % - bst_get('ShowZeroLines') : {0,1} - If 1, show the Y=0 lines in the columns view 182 % - bst_get('ShowEventsMode') : {'dot','line','none'} 183 % - bst_get('Resolution') : [resX,resY] fixed resolutions for X and Y axes 184 % - bst_get('FixedScaleY', Modality) : Struct with the scales to impose on the recordings for the selected modality 185 % - bst_get('XScale', XScale) : {'log', 'linear'} 186 % - bst_get('YScale', YScale) : {'log', 'linear'} 187 % - bst_get('UseSigProcToolbox') : Use Matlab's Signal Processing Toolbox when available 188 % - bst_get('RawViewerOptions', sFile) : Display options for RAW recordings, adapt for specific file 189 % - bst_get('RawViewerOptions') : Display options for RAW recordings 190 % - bst_get('TopoLayoutOptions') : Display options for 2DLayout display 191 % - bst_get('StatThreshOptions') : Options for online statistical thresholding 192 % - bst_get('ContactSheetOptions') : Display options for contact sheets 193 % - bst_get('ProcessOptions') : Options related with the data processing 194 % - bst_get('CustomColormaps') : Gets the list of user defined colormaps 195 % - bst_get('MriOptions') : Configuration for MRI display 196 % - bst_get('DigitizeOptions') : Digitizer options 197 % - bst_get('PcaOptions') : Options for PCA dimension reduction (xyz flattening or scout function) 198 % - bst_get('ReadOnly') : Read only interface 199 % - bst_get('NodelistOptions') : Structure with the options for file selection in the Process1 and Process2 panels 200 % - bst_get('ResizeFunction') : Get the appropriate resize function 201 % - bst_get('groot') : Get the root graphic object 202 % - bst_get('JFrame', hFig) : Get the underlying java frame for a Matlab figure 203 % - bst_get('LastPsdDisplayFunction') : Display option of measure for spectrum (log, power, magnitude, etc.) 204 % - bst_get('PlotlyCredentials') : Get the credentials and URL to connect to plot.ly server 205 % - bst_get('ExportBidsOptions') : Additional metadata for BIDS export 206 % 207 % SEE ALSO bst_set 208 209 % @============================================================================= 210 % This function is part of the Brainstorm software: 211 % https://neuroimage.usc.edu/brainstorm 212 % 213 % Copyright (c) University of Southern California & McGill University 214 % This software is distributed under the terms of the GNU General Public License 215 % as published by the Free Software Foundation. Further details on the GPLv3 216 % license can be found at http://www.gnu.org/copyleft/gpl.html. 217 % 218 % FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE 219 % UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY 220 % WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF 221 % MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY 222 % LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE. 223 % 224 % For more information type "brainstorm license" at command prompt. 225 % =============================================================================@ 226 % 227 % Authors: Francois Tadel, 2008-2023 228 % Martin Cousineau, 2017 229 % Raymundo Cassani, 2021-2023 230 231 %% ==== PARSE INPUTS ==== 232 global GlobalData; 233 if ((nargin >= 1) && ischar(varargin{1})) 234 contextName = varargin{1}; 235 else 236 return 237 end 238 % Initialize returned variable 239 argout1 = []; 240 argout2 = []; 241 argout3 = []; 242 argout4 = []; 243 argout5 = []; 244 245 % Get required context structure 246 switch contextName 247 %% ==== SUBFUNCTIONS ===== 248 case 'findFileInStudies' 249 [argout1, argout2, argout3] = findFileInStudies(varargin{2:end}); 250 251 %% ==== BRAINSTORM CONFIGURATION ==== 252 case 'Version' 253 argout1 = GlobalData.Program.Version; 254 255 case 'MatlabVersion' 256 if ~exist('version','builtin') 257 Version = 601; 258 else 259 % Get version number 260 str_vers = version(); 261 vers = sscanf(str_vers, '%d.%d%*s'); 262 if isempty(vers) || any(~isnumeric(vers)) || any(isnan(vers)) 263 vers = 0; 264 end 265 Version = 100 * vers(1) + vers(2); 266 % Get release name 267 ipar = [find(str_vers == '('), find(str_vers == ')')]; 268 end 269 argout1 = Version; 270 271 case 'MatlabReleaseName' 272 if ~exist('version','builtin') 273 Release = 'Matlab6'; 274 else 275 % Get version number 276 str_vers = version(); 277 % Get release name 278 ipar = [find(str_vers == '('), find(str_vers == ')')]; 279 Release = str_vers(ipar(1)+1:ipar(2)-1); 280 end 281 argout1 = Release; 282 283 case 'JavaVersion' 284 strver = char(java.lang.System.getProperty('java.version')); 285 iDot = find(strver == '.'); 286 if (length(iDot) < 2) 287 argout1 = str2num(strver); 288 else 289 argout1 = str2num(strver(1:iDot(2)-1)); 290 end 291 292 case 'isJavacomponent' 293 % After Matlab 2019b, javacomponent() and JavaFrame property have been deprecated 294 argout1 = (bst_get('MatlabVersion') <= 906); 295 296 case 'SystemMemory' 297 maxvar = []; 298 totalmem = []; 299 if ispc && (bst_get('MatlabVersion') >= 706) 300 try 301 % Get memory info 302 usermem = memory(); 303 maxvar = round(usermem.MaxPossibleArrayBytes / 1024 / 1024); 304 totalmem = round(usermem.MemAvailableAllArrays / 1024 / 1024); 305 catch 306 % Whatever... 307 end 308 end 309 argout1 = maxvar; 310 argout2 = totalmem; 311 312 case 'BrainstormHomeDir' 313 argout1 = GlobalData.Program.BrainstormHomeDir; 314 case 'BrainstormDbDir' 315 argout1 = GlobalData.DataBase.BrainstormDbDir; 316 case 'UserDir' 317 try 318 if ispc 319 userDir = getenv('USERPROFILE'); 320 else 321 userDir = char(java.lang.System.getProperty('user.home')); 322 end 323 catch 324 userDir = ''; 325 end 326 if isempty(userDir) 327 userDir = bst_get('BrainstormHomeDir'); 328 end 329 argout1 = userDir; 330 331 case 'BrainstormUserDir' 332 bstUserDir = bst_fullfile(bst_get('UserDir'), '.brainstorm'); 333 if ~isdir(bstUserDir) 334 res = mkdir(bstUserDir); 335 if ~res 336 error(['Cannot create Brainstorm user directory: "' bstUserDir '".']); 337 end 338 end 339 argout1 = bstUserDir; 340 341 case 'BrainstormTmpDir' 342 tmpDir = ''; 343 isForcedDefault = ((nargin >= 2) && ~isempty(varargin{2}) && varargin{2}); 344 % Subdirectory 345 if (nargin >= 3) && ~isempty(varargin{3}) 346 SubDir = varargin{3}; 347 348 % % Add PID of MATLAB process to the temporary folder 349 % try 350 % pid = feature('getpid'); 351 % catch 352 % pid = []; 353 % end 354 % if ~isempty(pid) 355 % SubDir = sprintf('%s_%d', SubDir, feature('getpid')); 356 % end 357 358 % Add date+time of MATLAB process to the temporary folder 359 c = clock; 360 SubDir = sprintf('%s_%02.0f%02.0f%02.0f_%02.0f%02.0f%02.0f', SubDir, c(1)-2000, c(2:6)); 361 else 362 SubDir = []; 363 end 364 % Default folder: userdir/tmp 365 defDir = bst_fullfile(bst_get('BrainstormUserDir'), 'tmp'); 366 % If temporary directory is set in the preferences 367 if ~isForcedDefault && isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'BrainstormTmpDir') 368 tmpDir = GlobalData.Preferences.BrainstormTmpDir; 369 end 370 % Else: use directory userdir/tmp 371 if isempty(tmpDir) 372 tmpDir = defDir; 373 end 374 % Create directory if it does not exist yet 375 if ~isdir(tmpDir) 376 res = mkdir(tmpDir); 377 if ~res && ~strcmp(tmpDir, defDir) 378 disp(['BST> Cannot create Brainstorm temporary directory: "' tmpDir '".']); 379 disp(['BST> Using default directory instead: "' defDir '".']); 380 % Create temporary folder 381 tmpDir = defDir; 382 if ~isdir(tmpDir) 383 res = mkdir(tmpDir); 384 else 385 res = 1; 386 end 387 end 388 % Error: cannot create any temporary folder 389 if ~res 390 error(['Cannot create Brainstorm temporary directory: "' tmpDir '".']); 391 end 392 end 393 % Add sub-directory 394 if ~isempty(SubDir) 395 tmpDir = bst_fullfile(tmpDir, SubDir); 396 % Create directory if it does not exist yet 397 if ~isdir(tmpDir) 398 res = mkdir(tmpDir); 399 if ~res 400 error(['Cannot create Brainstorm temporary directory: "' tmpDir '".']); 401 end 402 end 403 end 404 argout1 = tmpDir; 405 406 case 'BrainstormDocDir' 407 docDir = bst_fullfile(GlobalData.Program.BrainstormHomeDir, 'doc'); 408 if ~exist(docDir, 'file') 409 % Matlab compiler >= 2018b stores 'doc' under 'bst_javabuil' 410 docDir = bst_fullfile(GlobalData.Program.BrainstormHomeDir, 'bst_javabuil', 'doc'); 411 if ~exist(docDir, 'file') 412 docDir = ''; 413 disp('BST> Could not find "doc" folder.'); 414 disp(['BST> BrainstormHomeDir = ' GlobalData.Program.BrainstormHomeDir]); 415 end 416 end 417 argout1 = docDir; 418 419 case 'BrainstormDefaultsDir' 420 defaultsDir = bst_fullfile(GlobalData.Program.BrainstormHomeDir, 'defaults'); 421 if ~exist(defaultsDir, 'file') 422 % Matlab compiler >= 2018b stores 'defaults' under 'bst_javabuil' 423 defaultsDir = bst_fullfile(GlobalData.Program.BrainstormHomeDir, 'bst_javabuil', 'defaults'); 424 if ~exist(defaultsDir, 'file') 425 defaultsDir = ''; 426 disp('BST> Could not find "defaults" folder.'); 427 disp(['BST> BrainstormHomeDir = ' GlobalData.Program.BrainstormHomeDir]); 428 end 429 end 430 argout1 = defaultsDir; 431 432 case 'UserReportsDir' 433 reportDir = bst_fullfile(bst_get('BrainstormUserDir'), 'reports'); 434 if ~isdir(reportDir) 435 res = mkdir(reportDir); 436 if ~res 437 error(['Cannot create user reports directory: "' reportDir '".']); 438 end 439 end 440 argout1 = reportDir; 441 442 case 'UserMexDir' 443 mexDir = bst_fullfile(bst_get('BrainstormUserDir'), 'mex'); 444 if ~isdir(mexDir) 445 res = mkdir(mexDir); 446 if ~res 447 error(['Cannot create Brainstorm mex-files directory: "' mexDir '".']); 448 end 449 end 450 argout1 = mexDir; 451 452 case 'UserProcessDir' 453 processDir = bst_fullfile(bst_get('BrainstormUserDir'), 'process'); 454 if ~isdir(processDir) 455 res = mkdir(processDir); 456 if ~res 457 error(['Cannot create Brainstorm custom processes directory: "' processDir '".']); 458 end 459 end 460 argout1 = processDir; 461 462 case 'UserDefaultsDir' 463 defDir = bst_fullfile(bst_get('BrainstormUserDir'), 'defaults'); 464 defDirAnat = bst_fullfile(defDir, 'anatomy'); 465 defDirEeg = bst_fullfile(defDir, 'eeg'); 466 if ~isdir(defDir) 467 res = mkdir(defDir); 468 if ~res 469 error(['Cannot create user templates directory: "' defDir '".']); 470 end 471 end 472 if ~isdir(defDirAnat) 473 res = mkdir(defDirAnat); 474 if ~res 475 error(['Cannot create user templates directory: "' defDirAnat '".']); 476 end 477 end 478 if ~isdir(defDirEeg) 479 res = mkdir(defDirEeg); 480 if ~res 481 error(['Cannot create user templates directory: "' defDirEeg '".']); 482 end 483 end 484 argout1 = defDir; 485 486 case 'UserPluginsDir' 487 % If brainstorm/plugins exists, use it (case of an environment exported and reused) 488 pluginsDir = bst_fullfile(GlobalData.Program.BrainstormHomeDir, 'plugins'); 489 % Otherwise (standard case): <home>/.brainstorm/plugins/ 490 if ~exist(pluginsDir, 'file') 491 pluginsDir = bst_fullfile(bst_get('BrainstormUserDir'), 'plugins'); 492 if ~isdir(pluginsDir) 493 res = mkdir(pluginsDir); 494 if ~res 495 error(['Cannot create plugins directory: "' pluginsDir '".']); 496 end 497 end 498 end 499 argout1 = pluginsDir; 500 501 case 'BrainstormDbFile' 502 argout1 = bst_fullfile(bst_get('BrainstormUserDir'), 'brainstorm.mat'); 503 504 %% ==== PROTOCOL ==== 505 case 'iProtocol' 506 if isempty(GlobalData.DataBase.iProtocol) 507 argout1 = 0; 508 else 509 argout1 = GlobalData.DataBase.iProtocol; 510 end 511 512 case 'Protocol' 513 if ~isempty(GlobalData.DataBase.ProtocolInfo) 514 argout1 = find(strcmpi({GlobalData.DataBase.ProtocolInfo.Comment}, varargin{2})); 515 else 516 argout1 = []; 517 end 518 519 case {'ProtocolInfo', 'ProtocolSubjects', 'ProtocolStudies', 'isProtocolLoaded', 'isProtocolModified'} 520 argout2 = GlobalData.DataBase.iProtocol; 521 % No protocol: return empty matrix 522 if isempty(argout2) || ~isnumeric(argout2) || argout2 == 0 523 return; 524 end 525 % Check index integrity 526 if ((argout2 <= 0) || (argout2 > length(GlobalData.DataBase.ProtocolInfo))), warning('Brainstorm:InvalidIndex', 'Invalid index'), return, end 527 % Get requested protocol structure 528 argout1 = GlobalData.DataBase.(contextName)(argout2); 529 530 531 %% ==== STUDY ==== 532 % Usage: [sStudy, iStudy] = bst_get('Study', StudyFileName) 533 % [sStudy, iStudy] = bst_get('Study') 534 % [sStudy, iStudy] = bst_get('Study', iStudies) 535 case 'Study' 536 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 537 return; 538 end 539 % Get list of current protocols 540 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 541 ProtocolStudies = GlobalData.DataBase.ProtocolStudies(GlobalData.DataBase.iProtocol); 542 % Get list of current protocol studies 543 if isempty(ProtocolStudies) || isempty(ProtocolInfo) 544 return; 545 end 546 % ===== PARSE INPUTS ===== 547 if (nargin < 2) 548 % Call: bst_get('Study'); 549 iStudies = ProtocolInfo.iStudy; 550 StudyFileName = []; 551 elseif (isnumeric(varargin{2})) 552 iStudies = varargin{2}; 553 StudyFileName = []; 554 elseif (ischar(varargin{2})) 555 iStudies = []; 556 StudyFileName = strrep(varargin{2}, ProtocolInfo.STUDIES, ''); 557 end 558 % Indices 559 iAnalysisStudy = -2; % CANNOT USE -1 => DISABLES SEARCH FUNCTIONS 560 iDefaultStudy = -3; 561 % Indices > 0: normal studies indiced in ProtocolStudies.Study array 562 563 % ===== GET STUDY BY INDEX ===== 564 % Call: bst_get('Study', iStudies); 565 if ~isempty(iStudies) 566 argout1 = repmat(ProtocolStudies.DefaultStudy, 0); 567 % Get analysis study 568 iTargetAnalysis = find(iStudies == iAnalysisStudy); 569 if ~isempty(iTargetAnalysis) 570 argout1(iTargetAnalysis) = repmat(ProtocolStudies.AnalysisStudy, size(iTargetAnalysis)); 571 argout2(iTargetAnalysis) = repmat(iAnalysisStudy, size(iTargetAnalysis)); 572 end 573 % Get default study 574 iTargetDefault = find(iStudies == iDefaultStudy); 575 if ~isempty(iTargetDefault) 576 argout1(iTargetDefault) = repmat(ProtocolStudies.DefaultStudy, size(iTargetDefault)); 577 argout2(iTargetDefault) = repmat(iDefaultStudy, size(iTargetDefault)); 578 end 579 % Get normal studies 580 iTargetNormal = find((iStudies >= 1) & (iStudies <= length(ProtocolStudies.Study))); 581 if ~isempty(iTargetNormal) 582 argout1(iTargetNormal) = ProtocolStudies.Study(iStudies(iTargetNormal)); 583 argout2(iTargetNormal) = iStudies(iTargetNormal); 584 end 585 % Error 586 if isempty(argout1) 587 GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol).iStudy = []; 588 end 589 590 % ===== GET STUDY BY FILENAME ===== 591 % Call: bst_get('Study', StudyFileName); 592 elseif ~isempty(StudyFileName) 593 % NORMAL STUDY 594 iStudy = find(file_compare({ProtocolStudies.Study.FileName}, StudyFileName), 1); 595 % If a study is found : return it 596 if ~isempty(iStudy) 597 argout1 = ProtocolStudies.Study(iStudy); 598 argout2 = iStudy; 599 % DEFAULT STUDY 600 elseif ~isempty(ProtocolStudies.DefaultStudy) && file_compare({ProtocolStudies.DefaultStudy.FileName}, StudyFileName) 601 argout1 = ProtocolStudies.DefaultStudy; 602 argout2 = iDefaultStudy; 603 % ANALYSIS STUDY 604 elseif ~isempty(ProtocolStudies.AnalysisStudy) && file_compare({ProtocolStudies.AnalysisStudy.FileName}, StudyFileName) 605 argout1 = ProtocolStudies.AnalysisStudy; 606 argout2 = iAnalysisStudy; 607 end 608 else 609 return 610 end 611 612 613 %% ==== STUDY WITH SUBJECT FILE ==== 614 % Usage : [sStudies, iStudies] = bst_get('StudyWithSubject', SubjectFile) : WITHOUT the system studies ('intra_subject', 'default_study') 615 % [sStudies, iStudies] = bst_get(..., 'intra_subject', 'default_study') : WITH the system studies: 'intra_subject' | 'default_study' 616 case 'StudyWithSubject' 617 % Parse inputs 618 if (nargin < 2) || ~ischar(varargin{2}) 619 error('Invalid call to bst_get()'); 620 end 621 if (nargin > 2) 622 IntraStudies = any(strcmpi(varargin(3:end), 'intra_subject')); 623 DefaultStudies = any(strcmpi(varargin(3:end), 'default_study')); 624 else 625 IntraStudies = 0; 626 DefaultStudies = 0; 627 end 628 SubjectFile = {varargin{2}}; 629 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 630 return; 631 end 632 % Get list of current protocol description 633 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 634 ProtocolStudies = GlobalData.DataBase.ProtocolStudies(GlobalData.DataBase.iProtocol); 635 if isempty(ProtocolStudies) || isempty(ProtocolInfo) 636 return; 637 end 638 639 % Get default subject 640 sDefaultSubject = bst_get('Subject', 0); 641 % If SubjectFile is the default subject filename 642 if ~isempty(sDefaultSubject) && ~isempty(sDefaultSubject.FileName) && file_compare( SubjectFile{1}, sDefaultSubject.FileName) 643 % Get all the subjects files that use default anatomy 644 ProtocolSubjects = GlobalData.DataBase.ProtocolSubjects(GlobalData.DataBase.iProtocol); 645 iSubjectUseDefaultAnat = find([ProtocolSubjects.Subject.UseDefaultAnat]); 646 if isempty(iSubjectUseDefaultAnat) 647 return 648 end 649 SubjectFile = {ProtocolSubjects.Subject(iSubjectUseDefaultAnat).FileName}; 650 % Also updates inter-subject node 651 isInterSubject = 1; 652 else 653 isInterSubject = 0; 654 end 655 % Search all the current protocol's studies 656 iStudies = []; 657 for i=1:length(SubjectFile) 658 iStudies = [iStudies, find(file_compare({ProtocolStudies.Study.BrainStormSubject}, SubjectFile{i}))]; 659 end 660 % Return results 661 if ~isempty(iStudies) 662 % Remove "analysis_intra" and "default_study" studies from list 663 if ~IntraStudies 664 iStudies(strcmpi({ProtocolStudies.Study(iStudies).Name}, bst_get('DirAnalysisIntra'))) = []; 665 end 666 if ~DefaultStudies 667 iStudies(strcmpi({ProtocolStudies.Study(iStudies).Name}, bst_get('DirDefaultStudy'))) = []; 668 end 669 % Return studies 670 argout1 = ProtocolStudies.Study(iStudies); 671 argout2 = iStudies; 672 else 673 argout1 = repmat(db_template('Study'), 0); 674 argout2 = []; 675 end 676 % Add inter-subject node, if needed 677 if isInterSubject 678 [sInterStudy, iInterStudy] = bst_get('AnalysisInterStudy'); 679 argout1 = [argout1, sInterStudy]; 680 argout2 = [argout2, iInterStudy]; 681 end 682 683 684 %% ==== STUDY WITH CONDITION PATH ==== 685 % USAGE: [sStudies, iStudies] = bst_get('StudyWithCondition', ConditionPath) 686 % 687 % INPUT: ConditionPath 688 % - 'SubjectName/conditionName' : Target condition for the specified subject 689 % - 'SubjectName/@intra' : Intra-subject condition for the subject 690 % - 'SubjectName/@default_study' : Default condition for the subject (where the subject's shared files are stored) 691 % - '*/conditionName' : Target condition for all the subjects 692 % - '@inter' : Inter-subject condition 693 % - '@default_study' : Protocol's default condition (where the protocol's shared files are stored) 694 695 case 'StudyWithCondition' 696 % Parse inputs 697 if (nargin ~= 2) || ~ischar(varargin{2}) 698 error('Invalid call to bst_get()'); 699 end 700 ConditionPath = varargin{2}; 701 % Get list of current protocol description 702 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 703 ProtocolStudies = GlobalData.DataBase.ProtocolStudies(GlobalData.DataBase.iProtocol); 704 if isempty(ProtocolStudies) || isempty(ProtocolInfo) 705 return; 706 end 707 708 % ConditionPath = @inter 709 if strcmpi(ConditionPath, '@inter') 710 iStudy = -2; 711 argout2 = iStudy; 712 argout1 = bst_get('Study', iStudy); 713 % ConditionPath = @default_study 714 elseif strcmpi(ConditionPath, '@default_study') 715 iStudy = -3; 716 argout2 = iStudy; 717 argout1 = bst_get('Study', iStudy); 718 % ConditionPath = SubjectName/ConditionName 719 else 720 % Get subject and condition names 721 condSplit = str_split(ConditionPath); 722 if (length(condSplit) ~= 2) 723 error('Invalid condition path.'); 724 end 725 SubjectName = condSplit{1}; 726 ConditionName = condSplit{2}; 727 728 % If first element is '*', search for condition in all the studies 729 if (SubjectName(1) == '*') 730 iStudies = 1:length(ProtocolStudies.Study); 731 % Else : search for condition only in studies that are linked to the subject specified in the ConditionPath 732 else 733 % Get subject 734 sSubject = bst_get('Subject', SubjectName, 1); 735 if isempty(sSubject) 736 return; 737 end 738 iStudies = find(file_compare({ProtocolStudies.Study.BrainStormSubject}, sSubject.FileName)); 739 end 740 % Nothing to search 741 if isempty(iStudies) 742 return 743 end 744 745 % Search all the current protocol's studies 746 iStudies = iStudies(cellfun(@(c)isequal(ConditionName, c), [ProtocolStudies.Study(iStudies).Condition])); 747 % Return results 748 if ~isempty(iStudies) 749 % Remove "analysis_intra" and "default_study" studies from list 750 if ~strcmpi(ConditionName, '@intra') 751 iStudies(strcmpi({ProtocolStudies.Study(iStudies).Condition}, bst_get('DirAnalysisIntra'))) = []; 752 end 753 if ~strcmpi(ConditionName, '@default_study') 754 iStudies(strcmpi({ProtocolStudies.Study(iStudies).Condition}, bst_get('DirDefaultStudy'))) = []; 755 end 756 % Sort by subject 757 if (length(iStudies) > 1) 758 SubjNameList = cell(1,length(iStudies)); 759 % For each study, get subject name 760 for i = 1:length(iStudies) 761 sSubject = bst_get('Subject', ProtocolStudies.Study(iStudies(i)).BrainStormSubject); 762 SubjNameList{i} = sSubject.Name; 763 end 764 % Sort subjects names 765 [sortSubjList, iSort] = sort(SubjNameList); 766 % Apply same sorting to studies 767 iStudies = iStudies(iSort); 768 end 769 % Return studies 770 argout1 = ProtocolStudies.Study(iStudies); 771 argout2 = iStudies; 772 else 773 argout1 = repmat(db_template('Study'), 0); 774 argout2 = []; 775 end 776 end 777 778 %% ==== CHANNEL STUDIES WITH SUBJECT ==== 779 % Usage: iStudies = bst_get('ChannelStudiesWithSubject', iSubjects, 'NoIntra') 780 case 'ChannelStudiesWithSubject' 781 % Parse inputs 782 if (nargin >= 2) && isnumeric(varargin{2}) 783 iSubjects = varargin{2}; 784 else 785 error('Invalid call to bst_get()'); 786 end 787 if (nargin == 3) && strcmpi(varargin{3}, 'NoIntra') 788 NoIntra = 1; 789 else 790 NoIntra = 0; 791 end 792 % Process all subjects 793 iStudies = []; 794 for i=1:length(iSubjects) 795 iSubject = iSubjects(i); 796 sSubject = bst_get('Subject', iSubject, 1); 797 % No subject: error 798 if isempty(sSubject) 799 continue 800 % If subject uses default channel file 801 elseif (sSubject.UseDefaultChannel ~= 0) 802 % Get default study for this subject 803 [tmp___, iStudiesNew] = bst_get('DefaultStudy', iSubject); 804 iStudies = [iStudies, iStudiesNew]; 805 % Else: get all the studies belonging to this subject 806 else 807 if NoIntra 808 [tmp___, iStudiesNew] = bst_get('StudyWithSubject', sSubject.FileName); 809 else 810 [tmp___, iStudiesNew] = bst_get('StudyWithSubject', sSubject.FileName, 'intra_subject'); 811 end 812 iStudies = [iStudies, iStudiesNew]; 813 end 814 end 815 argout1 = iStudies; 816 817 818 %% ==== STUDIES COUNT ==== 819 % Usage: [nbStudies] = bst_get('StudyCount') 820 case 'StudyCount' 821 % Nothing 822 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 823 argout1 = 0; 824 return; 825 end 826 % Get list of current protocol studies 827 ProtocolStudies = GlobalData.DataBase.ProtocolStudies(GlobalData.DataBase.iProtocol); 828 argout1 = length(ProtocolStudies.Study); 829 830 %% ==== SUBJECTS COUNT ==== 831 % Usage: [nbSubjects] = bst_get('SubjectCount') 832 case 'SubjectCount' 833 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 834 argout1 = 0; 835 return; 836 end 837 % Get list of current protocol studies 838 ProtocolSubjects = GlobalData.DataBase.ProtocolSubjects(GlobalData.DataBase.iProtocol); 839 argout1 = length(ProtocolSubjects.Subject); 840 841 %% ==== NORMALIZED SUBJECT ==== 842 case 'NormalizedSubject' 843 % Get normalized subject name 844 normSubjName = 'Group_analysis'; 845 % Try to get normalized subject 846 [sNormSubj, iNormSubj] = bst_get('Subject', normSubjName, 0); 847 % If normalized subject does not exist: create it 848 if isempty(sNormSubj) 849 % Always use default anatomy 850 UseDefaultAnat = 1; 851 % If all the subjects use a global channel file: Use global default as well 852 if ~isempty(GlobalData.DataBase.ProtocolSubjects(GlobalData.DataBase.iProtocol).Subject) && ... 853 all([GlobalData.DataBase.ProtocolSubjects(GlobalData.DataBase.iProtocol).Subject.UseDefaultChannel] == 2) 854 UseDefaultChannel = 2; 855 else 856 UseDefaultChannel = 1; 857 end 858 % Create subject 859 [sNormSubj, iNormSubj] = db_add_subject(normSubjName, [], UseDefaultAnat, UseDefaultChannel); 860 % Get full subject structure 861 [sNormSubj, iNormSubj] = bst_get('Subject', normSubjName, 0); 862 end 863 argout1 = sNormSubj; 864 argout2 = iNormSubj; 865 866 867 %% ==== ANALYSIS STUDY (INTRA) ==== 868 % Usage: [sAnalStudy, iAnalStudy] = bst_get('AnalysisIntraStudy', iSubject) 869 case 'AnalysisIntraStudy' 870 % Parse inputs 871 if (nargin == 2) && isnumeric(varargin{2}) 872 iSubject = varargin{2}; 873 else 874 error('Invalid call to bst_get()'); 875 end 876 % Get subject 877 sSubject = bst_get('Subject', iSubject, 1); 878 % Get studies related to subject 879 [sSubjStudies, iSubjStudies] = bst_get('StudyWithSubject', sSubject.FileName, 'intra_subject'); 880 % Look for the 'AnalysisIntra' study 881 iFound = find(cellfun(@(c)ismember(bst_get('DirAnalysisIntra'), c), {sSubjStudies.Condition})); 882 iAnalStudy = iSubjStudies(iFound); 883 sAnalStudy = sSubjStudies(iFound); 884 % Return found structure 885 argout1 = sAnalStudy; 886 argout2 = iAnalStudy; 887 888 889 %% ==== ANALYSIS STUDY (INTER) ==== 890 % Usage: [sAnalStudyInter, iAnalStudyInter] = bst_get('AnalysisInterStudy') 891 case 'AnalysisInterStudy' 892 iAnalStudyInter = -2; 893 [argout1, argout2] = bst_get('Study', iAnalStudyInter); 894 895 896 %% ==== DEFAULT STUDY ==== 897 % Usage: [sDefaulStudy, iDefaultStudy] = bst_get('DefaultStudy', iSubject) 898 % [sDefaulStudy, iDefaultStudy] = bst_get('DefaultStudy') : iSubject=0 899 % [sDefaulStudy, iDefaultStudy] = bst_get('DefaultStudy', SubjectFile) 900 case 'DefaultStudy' 901 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 902 return; 903 end 904 % Parse inputs 905 if (nargin == 1) 906 iSubject = 0; 907 elseif (nargin == 2) && isnumeric(varargin{2}) 908 iSubject = varargin{2}; 909 elseif (nargin == 2) && ischar(varargin{2}) 910 SubjectFile = varargin{2}; 911 % Get subject attached to study 912 [sSubject, iSubject] = bst_get('Subject', SubjectFile, 1); 913 if isempty(sSubject) || ~sSubject.UseDefaultChannel 914 return; 915 end 916 else 917 error('Invalid call to bst_get()'); 918 end 919 % === DEFAULT SUBJECT === 920 % => Return global default study 921 if (iSubject == 0) 922 % Get protocol's studies 923 ProtocolStudies = GlobalData.DataBase.ProtocolStudies(GlobalData.DataBase.iProtocol); 924 % Return Global default study 925 argout1 = ProtocolStudies.DefaultStudy; 926 argout2 = -3; 927 % === NORMAL SUBJECT === 928 else 929 % Get subject 930 sSubject = bst_get('Subject', iSubject, 1); 931 % === GLOBAL DEFAULT STUDY === 932 if sSubject.UseDefaultChannel == 2 933 % Get protocol's studies 934 ProtocolStudies = GlobalData.DataBase.ProtocolStudies(GlobalData.DataBase.iProtocol); 935 % Return Global default study 936 argout1 = ProtocolStudies.DefaultStudy; 937 argout2 = -3; 938 % === SUBJECT'S DEFAULT STUDY === 939 elseif sSubject.UseDefaultChannel == 1 940 % Get studies related to subject 941 [sSubjStudies, iSubjStudies] = bst_get('StudyWithSubject', sSubject.FileName, 'default_study'); 942 % Look for the 'DefaultStudy' study 943 iFound = find(cellfun(@(c)ismember(bst_get('DirDefaultStudy'), c), {sSubjStudies.Condition})); 944 iDefaultStudy = iSubjStudies(iFound); 945 sDefaultStudy = sSubjStudies(iFound); 946 % Return found structure 947 argout1 = sDefaultStudy; 948 argout2 = iDefaultStudy; 949 end 950 end 951 952 953 954 %% ==== SUBJECT ==== 955 % Usage : [sSubject, iSubject] = bst_get('Subject', iSubject, isRaw) 956 % [sSubject, iSubject] = bst_get('Subject', SubjectFileName, isRaw); 957 % [sSubject, iSubject] = bst_get('Subject', SubjectName, isRaw); 958 % [sSubject, iSubject] = bst_get('Subject'); 959 % If isRaw is set: force to return the real brainstormsubject description 960 % (ignoring wether it uses protocol's default anatomy or not) 961 case 'Subject' 962 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 963 return; 964 end 965 % Get list of current protocol subjects 966 ProtocolSubjects = GlobalData.DataBase.ProtocolSubjects(GlobalData.DataBase.iProtocol); 967 sSubject = []; 968 SubjectName = []; 969 SubjectFileName = []; 970 % ISRAW parameter 971 if (nargin < 3) 972 isRaw = 0; 973 else 974 isRaw = varargin{3}; 975 end 976 % Call: bst_get('subject', iSubject, isRaw); 977 if (nargin >= 2) && isnumeric(varargin{2}) 978 iSubject = varargin{2}; 979 if (iSubject > length(ProtocolSubjects.Subject)) 980 error('Invalid subject indice.'); 981 end 982 % If required subject is default subject (iSubject = 0) 983 if (iSubject == 0) 984 % Default subject available 985 if ~isempty(ProtocolSubjects.DefaultSubject) 986 sSubject = ProtocolSubjects.DefaultSubject; 987 % Default subject not available 988 else 989 return 990 end 991 % Normal subject 992 else 993 sSubject = ProtocolSubjects.Subject(iSubject); 994 end 995 996 % Call: bst_get('subject', SubjectFileName, isRaw); 997 % Call: bst_get('subject', SubjectName, isRaw); 998 elseif (nargin >= 2) && isempty(varargin{2}) 999 % If study name is empty: use DefaultSubject 1000 SubjectFileName = ProtocolSubjects.DefaultSubject.FileName; 1001 elseif (nargin >= 2) && (ischar(varargin{2})) 1002 [fName, fBase, fExt] = bst_fileparts(varargin{2}); 1003 % Argument is a Matlab .mat filename 1004 if strcmpi(fExt, '.mat') 1005 SubjectFileName = varargin{2}; 1006 % Else : assume argument is a directory 1007 else 1008 SubjectName = file_standardize(varargin{2}); 1009 end 1010 1011 % Call: bst_get('subject'); => looking for current subject 1012 elseif (nargin < 2) 1013 % Get current subject filename in current study 1014 sStudy = bst_get('Study'); 1015 if isempty(sStudy) 1016 return 1017 end 1018 SubjectFileName = sStudy.BrainStormSubject; 1019 % If study's subject is not defined, get DefaultSubject 1020 if isempty(SubjectFileName) && ~isempty(ProtocolSubjects.DefaultSubject) 1021 SubjectFileName = ProtocolSubjects.DefaultSubject.FileName; 1022 end 1023 else 1024 error('Invalid call to bst_get()'); 1025 end 1026 1027 % If Subject is defined by its filename/name 1028 if isempty(sSubject) 1029 % Look in Default Subject 1030 if ~isempty(ProtocolSubjects.DefaultSubject) && (file_compare(ProtocolSubjects.DefaultSubject.FileName, SubjectFileName) ... 1031 || strcmpi(ProtocolSubjects.DefaultSubject.Name, SubjectName)) 1032 sSubject = ProtocolSubjects.DefaultSubject; 1033 iSubject = 0; 1034 % If not found : find target subject file name in normal subjects 1035 elseif ~isempty(SubjectFileName) 1036 iSubject = find(file_compare({ProtocolSubjects.Subject.FileName}, SubjectFileName), 1); 1037 sSubject = ProtocolSubjects.Subject(iSubject); 1038 elseif ~isempty(SubjectName) 1039 iSubject = find(file_compare({ProtocolSubjects.Subject.Name}, SubjectName), 1); 1040 sSubject = ProtocolSubjects.Subject(iSubject); 1041 else 1042 error('Subject name not specified.'); 1043 end 1044 end 1045 1046 % Return found subject 1047 if ~isempty(iSubject) && ~isempty(sSubject) 1048 % If subject uses default subject 1049 if sSubject.UseDefaultAnat && ~isRaw && ~isempty(ProtocolSubjects.DefaultSubject) && ~isempty(ProtocolSubjects.DefaultSubject.FileName) 1050 % Return default subject (WITH REAL SUBJECT'S NAME) 1051 argout1 = ProtocolSubjects.DefaultSubject; 1052 argout1.Name = sSubject.Name; 1053 argout1.UseDefaultAnat = sSubject.UseDefaultAnat; 1054 argout1.UseDefaultChannel = sSubject.UseDefaultChannel; 1055 argout2 = iSubject; 1056 % Else, return found subject 1057 else 1058 argout1 = sSubject; 1059 argout2 = iSubject; 1060 end 1061 end 1062 1063 1064 %% ==== SURFACE FILE ==== 1065 % Usage : [sSubject, iSubject, iSurface] = bst_get('SurfaceFile', SurfaceFile) 1066 case 'SurfaceFile' 1067 % No protocol in database 1068 if isempty(GlobalData) || isempty(GlobalData.DataBase) || isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1069 return; 1070 end 1071 % Get list of current protocol subjects 1072 ProtocolSubjects = GlobalData.DataBase.ProtocolSubjects(GlobalData.DataBase.iProtocol); 1073 if isempty(ProtocolSubjects) 1074 return 1075 end; 1076 1077 % Parse inputs 1078 if (nargin == 2) 1079 SurfaceFile = varargin{2}; 1080 else 1081 error('Invalid call to bst_get().'); 1082 end 1083 1084 % Remove SUBJECTS path from SurfaceFile 1085 SurfaceFile = file_short(SurfaceFile); 1086 % Look for surface file in DefaultSubject 1087 if ~isempty(ProtocolSubjects.DefaultSubject) 1088 % Find the first surface that matches the SurfaceFile 1089 iSurface = find(file_compare(SurfaceFile, {ProtocolSubjects.DefaultSubject.Surface.FileName}), 1); 1090 % If a surface was found in default subject : return it 1091 if ~isempty(iSurface) 1092 argout1 = ProtocolSubjects.DefaultSubject; 1093 argout2 = 0; 1094 argout3 = iSurface; 1095 return 1096 end 1097 end 1098 % Look for surface file in all the surfaces of all subjects 1099 for iSubj = 1:length(ProtocolSubjects.Subject) 1100 % Find the first surface that matches the SurfaceFile 1101 iSurface = find(file_compare(SurfaceFile, {ProtocolSubjects.Subject(iSubj).Surface.FileName}), 1); 1102 % If a surface was found in current subject : return it 1103 if ~isempty(iSurface) 1104 argout1 = ProtocolSubjects.Subject(iSubj); 1105 argout2 = iSubj; 1106 argout3 = iSurface; 1107 return 1108 end 1109 end 1110 1111 1112 %% ==== SURFACE FILE BY TYPE ==== 1113 % Usage : [sSurface, iSurface] = bst_get('SurfaceFileByType', iSubject, SurfaceType) 1114 % [sSurface, iSurface] = bst_get('SurfaceFileByType', SubjectFile, SurfaceType) 1115 % [sSurface, iSurface] = bst_get('SurfaceFileByType', SurfaceFile, SurfaceType) 1116 % [sSurface, iSurface] = bst_get('SurfaceFileByType', MriFile, SurfaceType) 1117 % [sSurface, iSurface] = bst_get('SurfaceFileByType', ..., SurfaceType, isDefaultOnly) 1118 case 'SurfaceFileByType' 1119 % By default: return only the default surfaces of the category 1120 if (nargin < 4) 1121 isDefaultOnly = 1; 1122 else 1123 isDefaultOnly = varargin{4}; 1124 end 1125 % Get subject 1126 if isempty(varargin{2}) 1127 % Get default subject 1128 sSubject = bst_get('Subject', 0); 1129 elseif ischar(varargin{2}) 1130 FileName = varargin{2}; 1131 sSubject = bst_get('AnyFile', FileName); 1132 else 1133 iSubject = varargin{2}; 1134 sSubject = bst_get('Subject', iSubject); 1135 end 1136 % Error handling 1137 if isempty(sSubject) 1138 disp('BST> Warning: Subject not found.'); 1139 return; 1140 elseif isempty(sSubject.Surface) 1141 return; 1142 end 1143 SurfaceType = varargin{3}; 1144 1145 % === RETURN ONLY DEFAULTS === 1146 if isDefaultOnly 1147 % Look for required surface type 1148 field = ['i' SurfaceType]; 1149 if ~isfield(sSubject, field) || isempty(sSubject.(field)) 1150 return 1151 end 1152 argout1 = sSubject.Surface(sSubject.(field)); 1153 argout2 = sSubject.(field); 1154 % === RETURN ALL THE SURFACES === 1155 else 1156 % Build the list of tagged surfaces 1157 fileTag = ['_' lower(SurfaceType)]; 1158 iTargetList = find(cellfun(@(c)~isempty(strfind(c, fileTag)), {sSubject.Surface.FileName})); 1159 % Put the default cortex on top of the list 1160 iDefaults = intersect([sSubject.iCortex, sSubject.iScalp, sSubject.iInnerSkull, sSubject.iOuterSkull, sSubject.iFibers, sSubject.iFEM], iTargetList); 1161 if ~isempty(iDefaults) 1162 iTargetList = [iDefaults, setdiff(iTargetList, iDefaults)]; 1163 end 1164 % Return all cortex surfaces 1165 argout1 = sSubject.Surface(iTargetList); 1166 argout2 = iTargetList; 1167 end 1168 1169 1170 %% ==== MRI FILE ==== 1171 % Usage : [sSubject, iSubject, iMri] = bst_get('MriFile', MriFile) 1172 case 'MriFile' 1173 % No protocol in database 1174 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1175 return; 1176 end 1177 % Get list of current protocol subjects 1178 ProtocolSubjects = GlobalData.DataBase.ProtocolSubjects(GlobalData.DataBase.iProtocol); 1179 if isempty(ProtocolSubjects) 1180 return 1181 end 1182 1183 % Parse inputs 1184 if (nargin == 2) 1185 MriFile = varargin{2}; 1186 else 1187 error('Invalid call to bst_get().'); 1188 end 1189 1190 % Remove SUBJECTS path from MriFile 1191 MriFile = file_short(MriFile); 1192 % Look for MRI file in DefaultSubject 1193 if ~isempty(ProtocolSubjects.DefaultSubject) 1194 % Find the first MRI that matches the MriFile 1195 iMri = find(file_compare(MriFile, {ProtocolSubjects.DefaultSubject.Anatomy.FileName}), 1); 1196 % If a MRI was found in default subject : return it 1197 if ~isempty(iMri) 1198 argout1 = ProtocolSubjects.DefaultSubject; 1199 argout2 = 0; 1200 argout3 = iMri; 1201 return 1202 end 1203 end 1204 % Look for MRI file in all the MRIs of all subjects 1205 for iSubj = 1:length(ProtocolSubjects.Subject) 1206 % Find the first MRI that matches the MriFile 1207 iMri = find(file_compare(MriFile, {ProtocolSubjects.Subject(iSubj).Anatomy.FileName}), 1); 1208 % If a MRI was found in current subject : return it 1209 if ~isempty(iMri) 1210 argout1 = ProtocolSubjects.Subject(iSubj); 1211 argout2 = iSubj; 1212 argout3 = iMri; 1213 return 1214 end 1215 end 1216 1217 1218 %% ==== CHANNEL FILE ==== 1219 % Usage: [sStudy, iStudy, iChannel] = bst_get('ChannelFile', ChannelFile) 1220 case 'ChannelFile' 1221 % No protocol in database 1222 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1223 return; 1224 end 1225 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1226 % Parse inputs 1227 if (nargin == 2) 1228 ChannelFile = varargin{2}; 1229 ChannelFile = strrep(ChannelFile, ProtocolInfo.STUDIES, ''); 1230 else 1231 error('Invalid call to bst_get().'); 1232 end 1233 % Look for Channel file in all the surfaces of all subjects 1234 [argout1, argout2, argout3] = findFileInStudies('Channel', 'FileName', ChannelFile); 1235 1236 1237 %% ==== CHANNEL FILE FOR STUDY ==== 1238 % Usage: [ChannelFile, sStudy, iStudy] = bst_get('ChannelFileForStudy', StudyFile/DataFile) 1239 case 'ChannelFileForStudy' 1240 % Parse inputs 1241 if (nargin == 2) 1242 StudyFile = varargin{2}; 1243 else 1244 error('Invalid call to bst_get().'); 1245 end 1246 % Get study in database 1247 [sStudy, iStudy] = bst_get('Study', StudyFile); 1248 % If data file instead of Study file 1249 if isempty(sStudy) 1250 [sStudy, iStudy] = bst_get('AnyFile', StudyFile); 1251 end 1252 sChannel = bst_get('ChannelForStudy', iStudy); 1253 if ~isempty(sChannel) 1254 argout1 = sChannel.FileName; 1255 argout2 = sStudy; 1256 argout3 = iStudy; 1257 else 1258 argout1 = []; 1259 end 1260 1261 1262 %% ==== CHANNEL STRUCT FOR STUDY ==== 1263 % Usage: [sChannel, iChanStudy] = bst_get('ChannelForStudy', iStudies) 1264 case 'ChannelForStudy' 1265 % Parse inputs 1266 if (nargin == 2) 1267 iStudies = varargin{2}; 1268 else 1269 error('Invalid call to bst_get().'); 1270 end 1271 iChanStudies = []; 1272 sListChannel = []; 1273 for i = 1:length(iStudies) 1274 % Get study 1275 iStudy = iStudies(i); 1276 sStudy = bst_get('Study', iStudy); 1277 if isempty(sStudy) 1278 continue; 1279 end 1280 iChanStudy = iStudy; 1281 % === Analysis-Inter node === 1282 iAnalysisInter = -2; 1283 iGlobalDefaultStudy = -3; 1284 if (iStudy == iAnalysisInter) 1285 % If no channel file is defined in 'Analysis-intra' node: look in 1286 if isempty(sStudy.Channel) 1287 % Get global default study 1288 sStudy = bst_get('Study', iGlobalDefaultStudy); 1289 iChanStudy = iGlobalDefaultStudy; 1290 end 1291 % === All other nodes === 1292 else 1293 % Get subject attached to study 1294 [sSubject, iSubject] = bst_get('Subject', sStudy.BrainStormSubject, 1); 1295 if isempty(sSubject) 1296 return; 1297 end 1298 % Subject uses default channel/headmodel 1299 if (sSubject.UseDefaultChannel ~= 0) 1300 [sStudy, iChanStudy] = bst_get('DefaultStudy', iSubject); 1301 if isempty(sStudy) 1302 return 1303 end 1304 end 1305 end 1306 iChanStudies = [iChanStudies, iChanStudy]; 1307 sListChannel = [sListChannel, sStudy.Channel]; 1308 end 1309 % Return Channel structure 1310 argout1 = sListChannel; 1311 argout2 = iChanStudies; 1312 1313 %% ==== CHANNEL MODALITIES ===== 1314 % Usage: [Modalities, DispMod, DefMod] = bst_get('ChannelModalities', ChannelFile) 1315 % [Modalities, DispMod, DefMod] = bst_get('ChannelModalities', DataFile/ResultsFile/TimefreqFile...) 1316 case 'ChannelModalities' 1317 % Get input file 1318 [sStudy, iStudy, iItem, DataType, sItem] = bst_get('AnyFile', varargin{2}); 1319 % If channel file 1320 if strcmpi(DataType, 'channel') 1321 sChannel = sItem; 1322 else 1323 sChannel = bst_get('ChannelForStudy', iStudy); 1324 end 1325 % Return modalities 1326 if ~isempty(sChannel) 1327 % Get all modalities 1328 if ~isempty(sChannel.DisplayableSensorTypes) 1329 % Return the displayable sensors on top of the list 1330 argout1 = cat(2, sChannel.DisplayableSensorTypes, setdiff(sChannel.Modalities, sChannel.DisplayableSensorTypes)); 1331 else 1332 argout1 = sChannel.Modalities; 1333 end 1334 % Get only sensors that have spatial representation 1335 argout2 = sChannel.DisplayableSensorTypes; 1336 % Default candidates 1337 if ~isempty(argout2) 1338 defList = argout2; 1339 else 1340 defList = argout1; 1341 end 1342 if isempty(defList) 1343 return; 1344 end 1345 % Remove EDF and BDF from the default list 1346 defList = setdiff(defList, {'EDF','BDF','KDF'}); 1347 % Get default modality 1348 if ismember('SEEG', defList) 1349 argout3 = 'SEEG'; 1350 elseif ismember('ECOG', defList) 1351 argout3 = 'ECOG'; 1352 elseif any(ismember({'MEG','MEG GRAD','MEG MAG'}, defList)) 1353 argout3 = 'MEG'; 1354 elseif ismember('EEG', defList) 1355 argout3 = 'EEG'; 1356 elseif ismember('NIRS', defList) 1357 argout3 = 'NIRS'; 1358 else 1359 argout3 = defList{1}; 1360 end 1361 % Place the default on top of the lists 1362 if ismember(argout3, argout1) 1363 argout1(strcmpi(argout1, argout3)) = []; 1364 argout1 = cat(2, argout3, argout1); 1365 end 1366 if ismember(argout3, argout2) 1367 argout2(strcmpi(argout2, argout3)) = []; 1368 argout2 = cat(2, argout3, argout2); 1369 end 1370 else 1371 argout1 = []; 1372 end 1373 1374 1375 %% ==== TIMEFREQ DISPLAY MODALITIES ==== 1376 % Usage: DisplayMod = bst_get('TimefreqDisplayModalities', TimefreqFile) 1377 case 'TimefreqDisplayModalities' 1378 TimefreqFile = varargin{2}; 1379 % Load sensor names from file 1380 TimefreqMat = in_bst_timefreq(TimefreqFile, 0, 'RowNames'); 1381 % Get channel file 1382 ChannelFile = bst_get('ChannelFileForStudy', TimefreqFile); 1383 if isempty(ChannelFile) 1384 return; 1385 end 1386 % Load channel file 1387 ChannelMat = load(file_fullpath(ChannelFile), 'Channel'); 1388 % Get channels that are present in the file 1389 [tmp__,I,J] = intersect({ChannelMat.Channel.Name}, TimefreqMat.RowNames); 1390 FileMod = unique({ChannelMat.Channel(I).Type}); 1391 % Check if only one type of gradiometer is selected 1392 if isequal(FileMod, {'MEG GRAD'}) && all(cellfun(@(c)(c(end)=='2'), {ChannelMat.Channel(I).Name})) 1393 argout1 = {'MEG GRAD2'}; 1394 elseif isequal(FileMod, {'MEG GRAD'}) && all(cellfun(@(c)(c(end)=='3'), {ChannelMat.Channel(I).Name})) 1395 argout1 = {'MEG GRAD3'}; 1396 % Keep only the modalities that can be displayed (as topography) 1397 else 1398 argout1 = intersect(FileMod, {'MEG','MEG GRAD','MEG MAG','EEG','ECOG','SEEG','NIRS'}); 1399 end 1400 1401 1402 %% ==== CHANNEL DEVICE ==== 1403 % Usage: Device = bst_get('ChannelDevice', ChannelFile) 1404 case 'ChannelDevice' 1405 ChannelFile = varargin{2}; 1406 if ~isempty(strfind(ChannelFile, 'vectorview306')) 1407 Device = 'Vectorview306'; 1408 elseif ~isempty(strfind(ChannelFile, 'ctf_acc1')) 1409 Device = 'CTF'; 1410 elseif ~isempty(strfind(ChannelFile, '4d_acc1')) 1411 Device = '4D'; 1412 elseif ~isempty(strfind(ChannelFile, 'babysquid')) 1413 Device = 'BabySQUID'; 1414 elseif ~isempty(strfind(ChannelFile, 'babymeg')) 1415 Device = 'BabyMEG'; 1416 elseif ~isempty(strfind(ChannelFile, 'kit')) 1417 Device = 'KIT'; 1418 elseif ~isempty(strfind(ChannelFile, 'ricoh')) 1419 Device = 'RICOH'; 1420 elseif ~isempty(strfind(ChannelFile, 'kriss')) 1421 Device = 'KRISS'; 1422 elseif ~isempty(strfind(ChannelFile, 'nirsbrs')) 1423 Device = 'NIRS-BRS'; 1424 else 1425 Device = ''; 1426 end 1427 argout1 = Device; 1428 1429 1430 %% ==== HEADMODEL STRUCT FOR STUDY ==== 1431 % Usage: [sHeadModel] = bst_get('HeadModelForStudy', iStudy) 1432 case 'HeadModelForStudy' 1433 % Parse inputs 1434 if (nargin == 2) 1435 iStudy = varargin{2}; 1436 else 1437 error('Invalid call to bst_get().'); 1438 end 1439 % Get study 1440 sStudy = bst_get('Study', iStudy); 1441 % === Analysis-Inter node === 1442 iAnalysisInter = -2; 1443 iGlobalDefaultStudy = -3; 1444 if (iStudy == iAnalysisInter) 1445 % If no channel file is defined in 'Analysis-intra' node: look in 1446 if isempty(sStudy.iHeadModel) 1447 % Get global default study 1448 sStudy = bst_get('Study', iGlobalDefaultStudy); 1449 end 1450 % === All other nodes === 1451 else 1452 % Get subject attached to study 1453 [sSubject, iSubject] = bst_get('Subject', sStudy.BrainStormSubject, 1); 1454 if isempty(sSubject) 1455 return; 1456 end 1457 % Subject uses default channel/headmodel 1458 if (sSubject.UseDefaultChannel ~= 0) 1459 sStudy = bst_get('DefaultStudy', iSubject); 1460 if isempty(sStudy) 1461 return 1462 end 1463 end 1464 end 1465 % Return HeadModel structure 1466 if ~isempty(sStudy.iHeadModel) 1467 argout1 = sStudy.HeadModel(sStudy.iHeadModel(1)); 1468 else 1469 argout1 = []; 1470 end 1471 1472 1473 %% ==== HEADMODEL FILE ==== 1474 % Usage: [sStudy, iStudy, iHeadModel] = bst_get('HeadModelFile', HeadModelFile, iStudies) 1475 % [sStudy, iStudy, iHeadModel] = bst_get('HeadModelFile', HeadModelFile) 1476 case 'HeadModelFile' 1477 % No protocol in database 1478 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1479 return; 1480 end 1481 % Input #2: HeadModelFile 1482 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1483 HeadModelFile = varargin{2}; 1484 HeadModelFile = strrep(HeadModelFile, ProtocolInfo.STUDIES, ''); 1485 % Input #3: iStudies 1486 if (nargin < 3) 1487 iStudies = []; 1488 else 1489 iStudies = varargin{3}; 1490 end 1491 % Look for surface file in all the surfaces of all subjects 1492 [argout1, argout2, argout3] = findFileInStudies('HeadModel', 'FileName', HeadModelFile, iStudies); 1493 1494 %% ==== NOISECOV FILE ==== 1495 % Usage: [sStudy, iStudy, iNoiseCov] = bst_get('NoiseCovFile', NoiseCovFile, iStudies) 1496 % [sStudy, iStudy, iNoiseCov] = bst_get('NoiseCovFile', NoiseCovFile) 1497 % Usage: [sStudy, iStudy, iNoiseCov] = bst_get('DataCovFile', NoiseCovFile, iStudies) 1498 % [sStudy, iStudy, iNoiseCov] = bst_get('DataCovFile', NoiseCovFile) 1499 case {'NoiseCovFile', 'DataCovFile'} 1500 % No protocol in database 1501 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1502 return; 1503 end 1504 % Input #2: NoiseCovFile 1505 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1506 NoiseCovFile = varargin{2}; 1507 NoiseCovFile = strrep(NoiseCovFile, ProtocolInfo.STUDIES, ''); 1508 % Input #3: iStudies 1509 if (nargin < 3) 1510 iStudies = []; 1511 else 1512 iStudies = varargin{3}; 1513 end 1514 % Look for surface file in all the surfaces of all subjects 1515 [argout1, argout2, argout3] = findFileInStudies('NoiseCov', 'FileName', NoiseCovFile, iStudies); 1516 1517 1518 %% ==== DATA FILE ==== 1519 % Usage: [sStudy, iStudy, iData] = bst_get('DataFile', DataFile, iStudies) 1520 % [sStudy, iStudy, iData] = bst_get('DataFile', DataFile) 1521 case 'DataFile' 1522 % No protocol in database 1523 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1524 return; 1525 end 1526 % Input #2: DataFile 1527 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1528 DataFile = varargin{2}; 1529 DataFile = strrep(DataFile, ProtocolInfo.STUDIES, ''); 1530 % Input #3: iStudies 1531 if (nargin < 3) 1532 iStudies = []; 1533 else 1534 iStudies = varargin{3}; 1535 end 1536 % Look for file in all the studies 1537 [argout1, argout2, argout3] = findFileInStudies('Data', 'FileName', DataFile, iStudies); 1538 1539 1540 %% ==== DATA FOR DATA LIST ==== 1541 % Usage: [iFoundData] = bst_get('DataForDataList', iStudy, DataListName) 1542 case 'DataForDataList' 1543 iStudy = varargin{2}; 1544 DataListName = varargin{3}; 1545 % Get study structure 1546 sStudy = bst_get('Study', iStudy); 1547 % Get all the data files held by this datalist 1548 listComments = cellfun(@(c)deblank(str_remove_parenth(c)), {sStudy.Data.Comment}, 'UniformOutput', 0); 1549 iFoundData = find(strcmp(listComments, DataListName)); 1550 % Return found data files 1551 argout1 = iFoundData; 1552 1553 %% ==== MATRIX FOR MATRIX LIST ==== 1554 % Usage: [iFoundMatrix] = bst_get('MatrixForMatrixList', iStudy, MatrixListName) 1555 case 'MatrixForMatrixList' 1556 iStudy = varargin{2}; 1557 MatrixListName = varargin{3}; 1558 % Get study structure 1559 sStudy = bst_get('Study', iStudy); 1560 % Get all the matrix files held by this datalist 1561 listComments = cellfun(@(c)deblank(str_remove_parenth(c)), {sStudy.Matrix.Comment}, 'UniformOutput', 0); 1562 iFoundMatrix = find(strcmp(listComments, MatrixListName)); 1563 % Return found matrix files 1564 argout1 = iFoundMatrix; 1565 1566 1567 %% ==== DATA FOR STUDY (INCLUDING SHARED STUDIES) ==== 1568 % Usage: [iStudies, iDatas] = bst_get('DataForStudy', iStudy) 1569 case 'DataForStudy' 1570 % Get target study 1571 iStudy = varargin{2}; 1572 sStudy = bst_get('Study', iStudy); 1573 isDefaultStudy = strcmpi(sStudy.Name, bst_get('DirDefaultStudy')); 1574 isGlobalDefault = (iStudy == -3); 1575 1576 % If study is the global default study 1577 sStudies = []; 1578 iStudies = []; 1579 if isGlobalDefault 1580 % Get all the subjects of the protocol 1581 nbSubjects = bst_get('SubjectCount'); 1582 for iSubject = 1:nbSubjects 1583 sSubject = bst_get('Subject', iSubject, 1); 1584 if sSubject.UseDefaultChannel 1585 [tmp_sStudies, tmp_iStudies] = bst_get('StudyWithSubject', sSubject.FileName); 1586 sStudies = [sStudies, tmp_sStudies]; 1587 iStudies = [iStudies, tmp_iStudies]; 1588 end 1589 end 1590 % Else, if study is a subject's default study (ie. channel file is shared by all studies of one subject) 1591 elseif isDefaultStudy 1592 % Get all the subject's studies 1593 [sStudies, iStudies] = bst_get('StudyWithSubject', sStudy.BrainStormSubject, 'intra_subject', 'default_study'); 1594 else 1595 % Normal: one channel per condition 1596 sStudies = sStudy; 1597 iStudies = iStudy; 1598 end 1599 % Get all the DataFiles for all these studies 1600 for i = 1:length(sStudies) 1601 nData = length(sStudies(i).Data); 1602 argout1 = [argout1, repmat(iStudies(i), [1,nData])]; 1603 argout2 = [argout2, 1:nData]; 1604 end 1605 1606 1607 %% ==== DATA FOR STUDIES (INCLUDING SHARED STUDIES) ==== 1608 % Usage: [iStudies, iDatas] = bst_get('DataForStudies', iStudies) 1609 case 'DataForStudies' 1610 iStudies = varargin{2}; 1611 for i = 1:length(iStudies) 1612 [tmp_iStudies, tmp_iDatas] = bst_get('DataForStudy', iStudies(i)); 1613 argout1 = [argout1, tmp_iStudies]; 1614 argout2 = [argout2, tmp_iDatas]; 1615 end 1616 1617 %% ==== DATA FILE FOR CHANNEL FILE ==== 1618 % Usage: DataFiles = bst_get('DataForChannelFile', ChannelFile) 1619 case 'DataForChannelFile' 1620 ChannelFile = varargin{2}; 1621 DataFiles = {}; 1622 % Get study for the given channel file 1623 [sStudy, iStudy] = bst_get('ChannelFile', ChannelFile); 1624 if isempty(sStudy) 1625 return; 1626 end 1627 % Get dependent data files 1628 [iStudies, iDatas] = bst_get('DataForStudy', iStudy); 1629 % Get all the Data filenames 1630 for i = 1:length(iStudies) 1631 sStudy = bst_get('Study', iStudies(i)); 1632 DataFiles = cat(2, DataFiles, {sStudy.Data(iDatas(i)).FileName}); 1633 end 1634 argout1 = DataFiles; 1635 1636 1637 %% ==== RESULTS FILE ==== 1638 % Usage: [sStudy, iStudy, iResult] = bst_get('ResultsFile', ResultsFile, iStudies) 1639 % [sStudy, iStudy, iResult] = bst_get('ResultsFile', ResultsFile) 1640 case 'ResultsFile' 1641 % No protocol in database 1642 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1643 return; 1644 end 1645 % Input #2: ResultsFile 1646 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1647 ResultsFile = varargin{2}; 1648 ResultsFile = strrep(ResultsFile, ProtocolInfo.STUDIES, ''); 1649 % Input #3: iStudies 1650 if (nargin < 3) 1651 iStudies = []; 1652 else 1653 iStudies = varargin{3}; 1654 end 1655 % Look for surface file in all the surfaces of all subjects 1656 [argout1, argout2, argout3] = findFileInStudies('Result', 'FileName', ResultsFile, iStudies); 1657 1658 1659 %% ==== RESULTS FOR DATA FILE ==== 1660 % Usage: [sStudy, iStudy, iResults] = bst_get('ResultsForDataFile', DataFile) : search the whole protocol 1661 % Usage: [sStudy, iStudy, iResults] = bst_get('ResultsForDataFile', DataFile, iStudies) : search only the specified studies 1662 case 'ResultsForDataFile' 1663 % No protocol in database 1664 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1665 return; 1666 end 1667 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1668 % Input #2: DataFile 1669 DataFile = varargin{2}; 1670 DataFile = strrep(DataFile, ProtocolInfo.STUDIES, ''); 1671 % Determine in which studies to search for ResultsFile 1672 if (nargin >= 3) 1673 % Studies specified in argument 1674 iStudy = varargin{3}; 1675 else 1676 % Get study in which DataFile is located 1677 [sStudy, iStudy] = bst_get('DataFile', DataFile); 1678 if isempty(iStudy) 1679 return; 1680 end 1681 end 1682 % Search selected studies 1683 [argout1, argout2, argout3] = findFileInStudies('Result', 'DataFile', DataFile, iStudy); 1684 1685 1686 %% ==== STAT FILE ==== 1687 % Usage: [sStudy, iStudy, iData] = bst_get('StatFile', StatFile, iStudies) 1688 % [sStudy, iStudy, iData] = bst_get('StatFile', StatFile) 1689 case 'StatFile' 1690 % No protocol in database 1691 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1692 return; 1693 end 1694 % Input #2: SataFile 1695 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1696 StatFile = varargin{2}; 1697 StatFile = strrep(StatFile, ProtocolInfo.STUDIES, ''); 1698 % Input #3: iStudies 1699 if (nargin < 3) 1700 iStudies = []; 1701 else 1702 iStudies = varargin{3}; 1703 end 1704 % Look for surface file in all the surfaces of all subjects 1705 [argout1, argout2, argout3] = findFileInStudies('Stat', 'FileName', StatFile, iStudies); 1706 1707 1708 %% ==== STAT FOR DATA FILE ==== 1709 % Usage: [sStudy, iStudy, iResults] = bst_get('StatForDataFile', DataFile) : search the whole protocol 1710 % Usage: [sStudy, iStudy, iResults] = bst_get('StatForDataFile', DataFile, iStudies) : search only the specified studies 1711 case 'StatForDataFile' 1712 % No protocol in database 1713 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1714 return; 1715 end 1716 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1717 % Parse inputs 1718 if (nargin >= 2) 1719 DataFile = varargin{2}; 1720 DataFile = strrep(DataFile, ProtocolInfo.STUDIES, ''); 1721 else 1722 error('Invalid call to bst_get().'); 1723 end 1724 % Determine in which studies to search for ResultsFile 1725 if (nargin >= 3) 1726 % Studies specified in argument 1727 iStudies = varargin{3}; 1728 else 1729 % Get study in which DataFile is located 1730 [sStudies, iStudies] = bst_get('DataFile', DataFile); 1731 if isempty(iStudies) 1732 return; 1733 end 1734 end 1735 % Search selected studies 1736 [argout1, argout2, argout3] = findFileInStudies('Stat', 'DataFile', DataFile, iStudies); 1737 1738 %% ==== TIMEFREQ FILE ==== 1739 % Usage: [sStudy, iStudy, iTimefreq] = bst_get('TimefreqFile', TimefreqFile, iStudies) 1740 % [sStudy, iStudy, iTimefreq] = bst_get('TimefreqFile', TimefreqFile) 1741 case 'TimefreqFile' 1742 % No protocol in database 1743 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1744 return; 1745 end 1746 % Input #2: TimefreqFile 1747 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1748 TimefreqFile = varargin{2}; 1749 TimefreqFile = strrep(TimefreqFile, ProtocolInfo.STUDIES, ''); 1750 % Remove optional RefRowName 1751 iPipe = find(TimefreqFile == '|', 1); 1752 if ~isempty(iPipe) 1753 TimefreqFile = TimefreqFile(1:iPipe-1); 1754 end 1755 % Input #3: iStudies 1756 if (nargin < 3) 1757 iStudies = []; 1758 else 1759 iStudies = varargin{3}; 1760 end 1761 % Look for surface file in all the surfaces of all subjects 1762 [argout1, argout2, argout3] = findFileInStudies('Timefreq', 'FileName', TimefreqFile, iStudies); 1763 1764 %% ==== TIMEFREQ FOR FILE ==== 1765 % Usage: [sStudy, iStudy, iTimefreq] = bst_get('TimefreqForFile', FileName, iStudies) : search only the specified studies 1766 % [sStudy, iStudy, iTimefreq] = bst_get('TimefreqForFile', FileName) : search the whole protocol 1767 case 'TimefreqForFile' 1768 % No protocol in database 1769 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1770 return; 1771 end 1772 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1773 % Parse inputs 1774 if (nargin >= 2) 1775 FileName = varargin{2}; 1776 FileName = strrep(FileName, ProtocolInfo.STUDIES, ''); 1777 else 1778 error('Invalid call to bst_get().'); 1779 end 1780 % Get study in which file is located 1781 if (nargin >= 3) 1782 iStudies = varargin{3}; 1783 [sStudy, iStudy, iFile, DataType] = bst_get('AnyFile', FileName, iStudies); 1784 else 1785 [sStudy, iStudy, iFile, DataType] = bst_get('AnyFile', FileName); 1786 end 1787 % If file was not found 1788 if isempty(iStudy) 1789 return; 1790 end 1791 % Search direct dependent files 1792 [tmp, tmp, iTf] = findFileInStudies('Timefreq', 'DataFile', FileName, iStudy); 1793 % Data files: get all the depending results, and then all the timefreq for those results 1794 if strcmpi(DataType, 'data') 1795 [tmp, tmp, iResults] = bst_get('ResultsForDataFile', FileName, iStudy); 1796 for i = 1:length(iResults); 1797 % Search selected studies 1798 [tmp, tmp, iTfRes] = findFileInStudies('Timefreq', 'DataFile', sStudy.Result(iResults(i)).FileName, iStudy); 1799 if ~isempty(iTfRes) 1800 iTf = [iTf iTfRes]; 1801 end 1802 end 1803 end 1804 % Return results 1805 if ~isempty(iTf) 1806 argout1 = sStudy; 1807 argout2 = iStudy; 1808 argout3 = iTf; 1809 end 1810 1811 1812 %% ==== DIPOLES FOR FILE ==== 1813 % Usage: [sStudy, iStudy, iDipoles] = bst_get('DipolesForFile', FileName, iStudies) : search only the specified studies 1814 % [sStudy, iStudy, iDipoles] = bst_get('DipolesForFile', FileName) : search the whole protocol 1815 case 'DipolesForFile' 1816 % No protocol in database 1817 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1818 return; 1819 end 1820 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1821 % Parse inputs 1822 if (nargin >= 2) 1823 FileName = varargin{2}; 1824 FileName = strrep(FileName, ProtocolInfo.STUDIES, ''); 1825 else 1826 error('Invalid call to bst_get().'); 1827 end 1828 % Get study in which file is located 1829 if (nargin >= 3) 1830 iStudies = varargin{3}; 1831 [sStudy, iStudy, iFile, DataType] = bst_get('AnyFile', FileName, iStudies); 1832 else 1833 [sStudy, iStudy, iFile, DataType] = bst_get('AnyFile', FileName); 1834 end 1835 % If file was not found 1836 if isempty(iStudy) 1837 return; 1838 end 1839 % Search direct dependent files 1840 [tmp, tmp, iDip] = findFileInStudies('Dipoles', 'DataFile', FileName, iStudy); 1841 % Data files: get all the depending results, and then all the timefreq for those results 1842 if strcmpi(DataType, 'data') 1843 [tmp, tmp, iResults] = bst_get('ResultsForDataFile', FileName, iStudy); 1844 for i = 1:length(iResults); 1845 % Search selected studies 1846 [tmp, tmp, iDipRes] = findFileInStudies('Dipoles', 'DataFile', sStudy.Result(iResults(i)).FileName, iStudy); 1847 if ~isempty(iDipRes) 1848 iDip = [iDip, iDipRes]; 1849 end 1850 end 1851 end 1852 % Return results 1853 if ~isempty(iDip) 1854 argout1 = sStudy; 1855 argout2 = iStudy; 1856 argout3 = iDip; 1857 end 1858 1859 1860 %% ==== TIMEFREQ FOR KERNEL ==== 1861 % Find all the timefreq files dependent from links due to a given kernel 1862 % Usage: [sStudy, iStudy, iTimefreq] = bst_get('TimefreqForKernel', KernelFile) 1863 case 'TimefreqForKernel' 1864 sFoundStudy = []; 1865 iFoundStudy = []; 1866 iFoundTimefreq = []; 1867 % No protocol in database 1868 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1869 return; 1870 end 1871 % Get study in which file is located 1872 KernelFile = varargin{2}; 1873 [sStudy, iStudy, iFile, DataType] = bst_get('ResultsFile', KernelFile); 1874 if isempty(iStudy) 1875 return; 1876 end 1877 % Get all the data files relative with this kernel 1878 [iDepStudies, iDepDatas] = bst_get('DataForStudy', iStudy); 1879 % Keep only once each study 1880 iDepStudies = unique(iDepStudies); 1881 % Process all the dependent studies 1882 for iSt = 1:length(iDepStudies) 1883 % Get the study structure 1884 sDepStudy = bst_get('Study', iDepStudies(iSt)); 1885 % Process each timefreq file separately 1886 for iTf = 1:length(sDepStudy.Timefreq) 1887 DataFile = sDepStudy.Timefreq(iTf).DataFile; 1888 % Keep only the files that are linked to LINKS 1889 if isempty(DataFile) || (length(DataFile) < 5) || ~isequal(DataFile(1:5), 'link|') 1890 continue; 1891 end 1892 % Split link 1893 splitFile = str_split(DataFile, '|'); 1894 % If the kernel is found: add it to the found list 1895 if file_compare(splitFile{2}, KernelFile) 1896 sFoundStudy = [sFoundStudy sDepStudy]; 1897 iFoundStudy = [iFoundStudy, iDepStudies(iSt)]; 1898 iFoundTimefreq = [iFoundTimefreq, iTf]; 1899 end 1900 end 1901 end 1902 % Return findings 1903 argout1 = sFoundStudy; 1904 argout2 = iFoundStudy; 1905 argout3 = iFoundTimefreq; 1906 1907 1908 %% ==== DIPOLES FOR KERNEL ==== 1909 % Find all the dipoles files dependent from links due to a given kernel 1910 % Usage: [sStudy, iStudy, iDipoles] = bst_get('TimefreqForKernel', KernelFile) 1911 case 'DipolesForKernel' 1912 sFoundStudy = []; 1913 iFoundStudy = []; 1914 iFoundDipoles = []; 1915 % No protocol in database 1916 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1917 return; 1918 end 1919 % Get study in which file is located 1920 KernelFile = varargin{2}; 1921 [sStudy, iStudy, iFile, DataType] = bst_get('ResultsFile', KernelFile); 1922 if isempty(iStudy) 1923 return; 1924 end 1925 % Get all the data files relative with this kernel 1926 [iDepStudies, iDepDatas] = bst_get('DataForStudy', iStudy); 1927 % Keep only once each study 1928 iDepStudies = unique(iDepStudies); 1929 % Process all the dependent studies 1930 for iSt = 1:length(iDepStudies) 1931 % Get the study structure 1932 sDepStudy = bst_get('Study', iDepStudies(iSt)); 1933 % Process each timefreq file separately 1934 for iDip = 1:length(sDepStudy.Dipoles) 1935 DataFile = sDepStudy.Dipoles(iDip).DataFile; 1936 % Keep only the files that are linked to LINKS 1937 if isempty(DataFile) || (length(DataFile) < 5) || ~isequal(DataFile(1:5), 'link|') 1938 continue; 1939 end 1940 % Split link 1941 splitFile = str_split(DataFile, '|'); 1942 % If the kernel is found: add it to the found list 1943 if file_compare(splitFile{2}, KernelFile) 1944 sFoundStudy = [sFoundStudy sDepStudy]; 1945 iFoundStudy = [iFoundStudy, iDepStudies(iSt)]; 1946 iFoundDipoles = [iFoundDipoles, iDip]; 1947 end 1948 end 1949 end 1950 % Return findings 1951 argout1 = sFoundStudy; 1952 argout2 = iFoundStudy; 1953 argout3 = iFoundDipoles; 1954 1955 1956 %% ==== DIPOLES FILE ==== 1957 % Usage: [sStudy, iStudy, iDipole] = bst_get('DipolesFile', DipolesFile, iStudies) 1958 % [sStudy, iStudy, iDipole] = bst_get('DipolesFile', DipolesFile) 1959 case 'DipolesFile' 1960 % No protocol in database 1961 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1962 return; 1963 end 1964 % Input #2: DipolesFile 1965 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1966 DipolesFile = varargin{2}; 1967 DipolesFile = strrep(DipolesFile, ProtocolInfo.STUDIES, ''); 1968 % Input #3: iStudies 1969 if (nargin < 3) 1970 iStudies = []; 1971 else 1972 iStudies = varargin{3}; 1973 end 1974 % Look for surface file in all the surfaces of all subjects 1975 [argout1, argout2, argout3] = findFileInStudies('Dipoles', 'FileName', DipolesFile, iStudies); 1976 1977 1978 %% ==== MATRIX FILE ==== 1979 % Usage: [sStudy, iStudy, iDipole] = bst_get('MatrixFile', MatrixFile, iStudies) 1980 % [sStudy, iStudy, iDipole] = bst_get('MatrixFile', MatrixFile) 1981 case 'MatrixFile' 1982 % No protocol in database 1983 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 1984 return; 1985 end 1986 % Input #2: MatrixFile 1987 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 1988 MatrixFile = varargin{2}; 1989 MatrixFile = strrep(MatrixFile, ProtocolInfo.STUDIES, ''); 1990 % Input #3: iStudies 1991 if (nargin < 3) 1992 iStudies = []; 1993 else 1994 iStudies = varargin{3}; 1995 end 1996 % Look for surface file in all the surfaces of all subjects 1997 [argout1, argout2, argout3] = findFileInStudies('Matrix', 'FileName', MatrixFile, iStudies); 1998 1999 %% ==== IMAGE FILE ==== 2000 % Usage: [sStudy, iStudy, iDipole] = bst_get('ImageFile', ImageFile, iStudies) 2001 % [sStudy, iStudy, iDipole] = bst_get('ImageFile', ImageFile) 2002 case 'ImageFile' 2003 % No protocol in database 2004 if isempty(GlobalData.DataBase.iProtocol) || (GlobalData.DataBase.iProtocol == 0) 2005 return; 2006 end 2007 % Input #2: ImageFile 2008 ProtocolInfo = GlobalData.DataBase.ProtocolInfo(GlobalData.DataBase.iProtocol); 2009 ImageFile = varargin{2}; 2010 ImageFile = strrep(ImageFile, ProtocolInfo.STUDIES, ''); 2011 % Input #3: iStudies 2012 if (nargin < 3) 2013 iStudies = []; 2014 else 2015 iStudies = varargin{3}; 2016 end 2017 % Look for surface file in all the surfaces of all subjects 2018 [argout1, argout2, argout3] = findFileInStudies('Image', 'FileName', ImageFile, iStudies); 2019 2020 2021 %% ==== ANY FILE ==== 2022 % Usage: [sStudy, iStudy, iFile, DataType, sItem] = bst_get('AnyFile', FileName, iStudies) 2023 % [sStudy, iStudy, iFile, DataType, sItem] = bst_get('AnyFile', FileName) 2024 case 'AnyFile' 2025 % Input #2: FileName 2026 FileName = varargin{2}; 2027 if isempty(FileName) 2028 return 2029 end 2030 % Input #3: iStudies 2031 if (nargin < 3) 2032 iStudies = []; 2033 else 2034 iStudies = varargin{3}; 2035 end 2036 % Get data format 2037 fileType = file_gettype(FileName); 2038 if isempty(fileType) 2039 error('File type is not recognized.'); 2040 end 2041 sItem = []; 2042 % Get information related with this file 2043 switch (fileType) 2044 % ===== FUNCTIONAL ===== 2045 case 'channel' 2046 [sStudy, iStudy] = bst_get('ChannelFile', FileName); 2047 iItem = 1; 2048 if (nargout >= 5) && ~isempty(sStudy) 2049 sItem = sStudy.Channel; 2050 end 2051 case 'headmodel' 2052 [sStudy, iStudy, iItem] = bst_get('HeadModelFile', FileName); 2053 if (nargout >= 5) && ~isempty(sStudy) 2054 sItem = sStudy.HeadModel(iItem); 2055 end 2056 case 'noisecov' 2057 [sStudy, iStudy, iItem] = bst_get('NoiseCovFile', FileName); 2058 if (nargout >= 5) && ~isempty(sStudy) 2059 sItem = sStudy.NoiseCov(iItem); 2060 end 2061 case 'ndatacov' 2062 [sStudy, iStudy, iItem] = bst_get('DataCovFile', FileName); 2063 if (nargout >= 5) && ~isempty(sStudy) 2064 sItem = sStudy.NoiseCov(iItem); 2065 end 2066 case {'data', 'spike'} 2067 [sStudy, iStudy, iItem] = bst_get('DataFile', FileName, iStudies); 2068 if (nargout >= 5) && ~isempty(sStudy) 2069 sItem = sStudy.Data(iItem); 2070 end 2071 case {'results', 'link'} 2072 [sStudy, iStudy, iItem] = bst_get('ResultsFile', FileName, iStudies); 2073 if (nargout >= 5) && ~isempty(sStudy) 2074 sItem = sStudy.Result(iItem); 2075 end 2076 case {'presults', 'pdata','ptimefreq','pmatrix'} 2077 [sStudy, iStudy, iItem] = bst_get('StatFile', FileName, iStudies); 2078 if (nargout >= 5) && ~isempty(sStudy) 2079 sItem = sStudy.Stat(iItem); 2080 end 2081 case 'dipoles' 2082 [sStudy, iStudy, iItem] = bst_get('DipolesFile', FileName, iStudies); 2083 if (nargout >= 5) && ~isempty(sStudy) 2084 sItem = sStudy.Dipoles(iItem); 2085 end 2086 case 'timefreq' 2087 % Remove optional RefRowName 2088 iPipe = find(FileName == '|', 1); 2089 if ~isempty(iPipe) 2090 FileName = FileName(1:iPipe-1); 2091 end 2092 [sStudy, iStudy, iItem] = bst_get('TimefreqFile', FileName, iStudies); 2093 if (nargout >= 5) && ~isempty(sStudy) 2094 sItem = sStudy.Timefreq(iItem); 2095 end 2096 case 'matrix' 2097 [sStudy, iStudy, iItem] = bst_get('MatrixFile', FileName, iStudies); 2098 if (nargout >= 5) && ~isempty(sStudy) 2099 sItem = sStudy.Matrix(iItem); 2100 end 2101 case 'brainstormstudy' 2102 [sStudy, iStudy] = bst_get('Study', FileName); 2103 iItem = 0; 2104 if (nargout >= 5) && ~isempty(sStudy) 2105 sItem = sStudy; 2106 end 2107 case {'image', 'video', 'videolink'} 2108 [sStudy, iStudy, iItem] = bst_get('ImageFile', FileName, iStudies); 2109 if (nargout >= 5) && ~isempty(sStudy) 2110 sItem = sStudy.Image(iItem); 2111 end 2112 % ===== ANATOMY ===== 2113 case {'cortex','scalp','innerskull','outerskull','tess','fibers','fem'} 2114 [sStudy, iStudy, iItem] = bst_get('SurfaceFile', FileName); 2115 if (nargout >= 5) && ~isempty(sStudy) 2116 sItem = sStudy.Surface(iItem); 2117 end 2118 case 'subjectimage' 2119 [sStudy, iStudy, iItem] = bst_get('MriFile', FileName); 2120 if (nargout >= 5) && ~isempty(sStudy) 2121 sItem = sStudy.Anatomy(iItem); 2122 end 2123 case 'brainstormsubject' 2124 [sStudy, iStudy] = bst_get('Subject', FileName); 2125 iItem = 0; 2126 if (nargout >= 5) && ~isempty(sStudy) 2127 sItem = sStudy; 2128 end 2129 otherwise 2130 error('File type is not recognized.'); 2131 end 2132 argout1 = sStudy; 2133 argout2 = iStudy; 2134 argout3 = iItem; 2135 argout4 = fileType; 2136 if (nargout >= 5) 2137 argout5 = sItem; 2138 end 2139 2140 2141 %% ==== GET RELATED DATA FILE ==== 2142 % Usage: DataFile = bst_get('RelatedDataFile', FileName, iStudies) 2143 % DataFile = bst_get('RelatedDataFile', FileName) 2144 case 'RelatedDataFile' 2145 % Input #2: FileName 2146 FileName = varargin{2}; 2147 % Input #3: iStudies 2148 if (nargin < 3) 2149 iStudies = []; 2150 else 2151 iStudies = varargin{3}; 2152 end 2153 % Get file in database 2154 [sStudy, iStudy, iFile, fileType] = bst_get('AnyFile', FileName, iStudies); 2155 % If this data file does not belong to any study 2156 if isempty(sStudy) 2157 return; 2158 end 2159 % Get associated data file 2160 switch (fileType) 2161 case 'data' 2162 RelatedDataFile = sStudy.Data(iFile).FileName; 2163 case {'pdata','presults','ptimefreq','pmatrix'} 2164 RelatedDataFile = sStudy.Stat(iFile).DataFile; 2165 case {'results', 'link'} 2166 RelatedDataFile = sStudy.Result(iFile).DataFile; 2167 case 'dipoles' 2168 RelatedDataFile = sStudy.Dipoles(iFile).DataFile; 2169 case 'timefreq' 2170 RelatedDataFile = sStudy.Timefreq(iFile).DataFile; 2171 otherwise 2172 RelatedDataFile = ''; 2173 end 2174 % If related file is results: get related data file 2175 if ~isempty(RelatedDataFile) 2176 relFileType = file_gettype(RelatedDataFile); 2177 if ismember(relFileType, {'link','results'}) 2178 RelatedDataFile = bst_get('RelatedDataFile', RelatedDataFile, iStudy); 2179 end 2180 end 2181 % Return file 2182 argout1 = RelatedDataFile; 2183 2184 %% ==== ALL CONDITIONS FOR ONE SUBJECT ==== 2185 % Usage: [Conditions] = bst_get('ConditionsForSubject', SubjectFile) 2186 case 'ConditionsForSubject' 2187 % Parse inputs 2188 if (nargin == 2) 2189 SubjectFile = varargin{2}; 2190 else 2191 error('Invalid call to bst_get().'); 2192 end 2193 % Get list of studies associated with subject 2194 sStudies = bst_get('StudyWithSubject', SubjectFile); 2195 % Get Conditions for each study 2196 Conditions = {}; 2197 for i = 1:length(sStudies) 2198 % Test if the condition of this study was not added previously 2199 isNewCondition = 1; 2200 for iCond = 1:length(Conditions) 2201 % If new condition is found 2202 % (and excludes DirAnalysisIntra and DirDefaultSubject from list) 2203 if isempty(sStudies(i).Condition) || ... 2204 isequal(sStudies(i).Condition, Conditions(iCond)) || ... 2205 strcmpi(sStudies(i).Condition{1}, bst_get('DirAnalysisIntra')) || ... 2206 strcmpi(sStudies(i).Condition{1}, bst_get('DirDefaultSubject')) 2207 isNewCondition = 0; 2208 break; 2209 end 2210 end 2211 % If Condition is not added yet : add it to the list 2212 if isNewCondition && ~isempty(sStudies(i).Condition) 2213 Conditions{end+1} = sStudies(i).Condition{1}; 2214 end 2215 end 2216 % Return conditions list 2217 argout1 = Conditions; 2218 2219 2220 %% ==== ANATOMY DEFAULTS ==== 2221 % Returns the list of all the anatomy defaults (distributed with the software + user defined) 2222 case 'AnatomyDefaults' 2223 % Parse inputs 2224 if (nargin == 2) 2225 AnatName = varargin{2}; 2226 else 2227 AnatName = []; 2228 end 2229 % Get templates from the brainstorm3 folder 2230 progDir = bst_fullfile(bst_get('BrainstormDefaultsDir'), 'anatomy'); 2231 progFiles = dir(progDir); 2232 % Get templates from the user folder 2233 userDir = bst_fullfile(bst_get('UserDefaultsDir'), 'anatomy'); 2234 userFiles = dir(userDir); 2235 % Combine the two lists 2236 AllProgNames = cat(2, {progFiles.name}, cellfun(@(c)cat(2,c,'.zip'), {progFiles.name}, 'UniformOutput', 0)); 2237 AllFiles = cat(2, cellfun(@(c)bst_fullfile(progDir,c), setdiff({progFiles.name}, {'.','..'}), 'UniformOutput', 0), ... 2238 cellfun(@(c)bst_fullfile(userDir,c), setdiff({userFiles.name}, AllProgNames), 'UniformOutput', 0)); 2239 % Initialize list of defaults 2240 sTemplates = repmat(struct('FilePath',[],'Name',[]), 0); 2241 % Find all the valid defaults (.zip files or subdirectory with a brainstormsubject.mat in it) 2242 for i = 1:length(AllFiles) 2243 % Decompose file name 2244 [fPath, fBase, fExt] = bst_fileparts(AllFiles{i}); 2245 % Entry is a directory W/ a name that does not start with a '.' 2246 if isempty(fBase) || strcmpi(fBase(1),'.') || (~isempty(fExt) && ~strcmpi(fExt, '.zip')) 2247 continue; 2248 end 2249 % If it's a folder: check for a brainstormsubject file 2250 if isdir(AllFiles{i}) 2251 bstFiles = dir(bst_fullfile(AllFiles{i}, 'brainstormsubject*.mat')); 2252 if (length(bstFiles) == 1) 2253 sTemplates(end+1).FilePath = AllFiles{i}; 2254 sTemplates(end).Name = fBase; 2255 end 2256 % If it's a zip file 2257 elseif isequal(fExt, '.zip') 2258 sTemplates(end+1).FilePath = AllFiles{i}; 2259 sTemplates(end).Name = fBase; 2260 end 2261 end 2262 % Get defaults from internet 2263 if ~ismember('icbm152', lower({sTemplates.Name})) 2264 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=ICBM152_2023b'; 2265 sTemplates(end).Name = 'ICBM152'; 2266 end 2267 if ~ismember('icbm152_2022', lower({sTemplates.Name})) 2268 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=ICBM152_2022'; 2269 sTemplates(end).Name = 'ICBM152_2022'; 2270 end 2271 if ~ismember('icbm152_2023b', lower({sTemplates.Name})) 2272 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=ICBM152_2023b'; 2273 sTemplates(end).Name = 'ICBM152_2023b'; 2274 end 2275 if ~ismember('icbm152_2019', lower({sTemplates.Name})) 2276 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=ICBM152_2019'; 2277 sTemplates(end).Name = 'ICBM152_2019'; 2278 end 2279 if ~ismember('icbm152_brainsuite_2016', lower({sTemplates.Name})) 2280 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=ICBM152_BrainSuite_2016'; 2281 sTemplates(end).Name = 'ICBM152_BrainSuite_2016'; 2282 end 2283 if ~ismember('colin27_2016', lower({sTemplates.Name})) 2284 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Colin27_2016'; 2285 sTemplates(end).Name = 'Colin27_2016'; 2286 end 2287 if ~ismember('colin27_brainsuite_2016', lower({sTemplates.Name})) 2288 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Colin27_BrainSuite_2016'; 2289 sTemplates(end).Name = 'Colin27_BrainSuite_2016'; 2290 end 2291 if ~ismember('bci-dni_brainsuite_2020', lower({sTemplates.Name})) 2292 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=BCI-DNI_BrainSuite_2020'; 2293 sTemplates(end).Name = 'BCI-DNI_BrainSuite_2020'; 2294 end 2295 if ~ismember('uscbrain_brainsuite_2020', lower({sTemplates.Name})) 2296 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=USCBrain_BrainSuite_2020'; 2297 sTemplates(end).Name = 'USCBrain_BrainSuite_2020'; 2298 end 2299 if ~ismember('fsaverage_2020', lower({sTemplates.Name})) 2300 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=FSAverage_2020'; 2301 sTemplates(end).Name = 'FsAverage_2020'; 2302 end 2303 if ~ismember('kabdebon_7w', lower({sTemplates.Name})) 2304 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Kabdebon_7w'; 2305 sTemplates(end).Name = 'Kabdebon_7w'; 2306 end 2307 if ~ismember('oreilly_0.5m_2021', lower({sTemplates.Name})) 2308 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_0.5m_2021'; 2309 sTemplates(end).Name = 'Oreilly_0.5m_2021'; 2310 end 2311 if ~ismember('oreilly_1m_2021', lower({sTemplates.Name})) 2312 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_1m_2021'; 2313 sTemplates(end).Name = 'Oreilly_1m_2021'; 2314 end 2315 if ~ismember('oreilly_2m_2021', lower({sTemplates.Name})) 2316 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_2m_2021'; 2317 sTemplates(end).Name = 'Oreilly_2m_2021'; 2318 end 2319 if ~ismember(lower({sTemplates.Name}), 'oreilly_3m_2021') 2320 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_3m_2021'; 2321 sTemplates(end).Name = 'Oreilly_3m_2021'; 2322 end 2323 if ~ismember('oreilly_4.5m_2021', lower({sTemplates.Name})) 2324 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_4.5m_2021'; 2325 sTemplates(end).Name = 'Oreilly_4.5m_2021'; 2326 end 2327 if ~ismember('oreilly_6m_2021', lower({sTemplates.Name})) 2328 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_6m_2021'; 2329 sTemplates(end).Name = 'Oreilly_6m_2021'; 2330 end 2331 if ~ismember('oreilly_7.5m_2021', lower({sTemplates.Name})) 2332 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_7.5m_2021'; 2333 sTemplates(end).Name = 'Oreilly_7.5m_2021'; 2334 end 2335 if ~ismember('oreilly_9m_2021', lower({sTemplates.Name})) 2336 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_9m_2021'; 2337 sTemplates(end).Name = 'Oreilly_9m_2021'; 2338 end 2339 if ~ismember('oreilly_10.5m_2021', lower({sTemplates.Name})) 2340 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_10.5m_2021'; 2341 sTemplates(end).Name = 'Oreilly_10.5m_2021'; 2342 end 2343 if ~ismember('oreilly_12m_2021', lower({sTemplates.Name})) 2344 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_12m_2021'; 2345 sTemplates(end).Name = 'Oreilly_12m_2021'; 2346 end 2347 if ~ismember('oreilly_15m_2021', lower({sTemplates.Name})) 2348 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_15m_2021'; 2349 sTemplates(end).Name = 'Oreilly_15m_2021'; 2350 end 2351 if ~ismember('oreilly_18m_2021', lower({sTemplates.Name})) 2352 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_18m_2021'; 2353 sTemplates(end).Name = 'Oreilly_18m_2021'; 2354 end 2355 if ~ismember('oreilly_24m_2021', lower({sTemplates.Name})) 2356 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=Oreilly_24m_2021'; 2357 sTemplates(end).Name = 'Oreilly_24m_2021'; 2358 end 2359 % If a specific template was requested 2360 if ~isempty(AnatName) 2361 iAnat = find(strcmpi({sTemplates.Name}, AnatName)); 2362 sTemplates = sTemplates(iAnat); 2363 end 2364 % Sort in alphabetical order 2365 if ~isempty(sTemplates) 2366 [tmp__, I] = sort_nat({sTemplates(2:end).Name}); 2367 sTemplates = sTemplates([1, I+1]); 2368 end 2369 % Return defaults list 2370 argout1 = sTemplates; 2371 2372 2373 %% ==== MNI ATLASES ==== 2374 % Returns the list of all the available MNI atlases 2375 case 'MniAtlasDefaults' 2376 % Get templates from the brainstorm3 folder 2377 mniDir = bst_fullfile(bst_get('UserDefaultsDir'), 'mniatlas'); 2378 mniFiles = dir(bst_fullfile(mniDir, '*.nii.gz')); 2379 mniFiles = cellfun(@(c)bst_fullfile(mniDir,c), {mniFiles.name}, 'UniformOutput', 0); 2380 % Initialize list of defaults 2381 sTemplates = repmat(struct('FilePath',[],'Name',[],'Info',[]), 0); 2382 % Find all the valid defaults (.zip files or subdirectory with a brainstormsubject.mat in it) 2383 for i = 1:length(mniFiles) 2384 % Decompose file name 2385 [fPath, fBase, fExt] = bst_fileparts(mniFiles{i}); 2386 % Keep only files with .nii and .nii.gz extensions 2387 if ~isempty(fBase) && (fBase(1) ~= '.') && ~isempty(fExt) && strcmpi(fExt, '.gz') 2388 sTemplates(end+1).FilePath = mniFiles{i}; 2389 sTemplates(end).Name = strrep(fBase, '.nii', ''); 2390 sTemplates(end).Info = ''; 2391 end 2392 end 2393 % Sort in alphabetical order 2394 if ~isempty(sTemplates) 2395 [tmp__, I] = sort_nat(lower({sTemplates.Name})); 2396 sTemplates = sTemplates(I); 2397 end 2398 2399 % Get defaults from internet 2400 if ~ismember('aal2', lower({sTemplates.Name})) 2401 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=mni_AAL2'; 2402 sTemplates(end).Name = 'AAL2'; 2403 sTemplates(end).Info = 'https://www.gin.cnrs.fr/en/tools/aal/'; 2404 end 2405 if ~ismember('aal3', lower({sTemplates.Name})) 2406 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=mni_AAL3'; 2407 sTemplates(end).Name = 'AAL3'; 2408 sTemplates(end).Info = 'https://www.gin.cnrs.fr/en/tools/aal/'; 2409 end 2410 if ~ismember('aicha', lower({sTemplates.Name})) 2411 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=mni_AICHA'; 2412 sTemplates(end).Name = 'AICHA'; 2413 sTemplates(end).Info = 'https://www.gin.cnrs.fr/en/tools/aicha'; 2414 end 2415 if ~ismember('brainnetome', lower({sTemplates.Name})) 2416 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=mni_Brainnetome'; 2417 sTemplates(end).Name = 'Brainnetome'; 2418 sTemplates(end).Info = 'http://atlas.brainnetome.org/'; 2419 end 2420 if ~ismember('brainnetome_leaddbs', lower({sTemplates.Name})) 2421 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=mni_Brainnetome_leaddbs'; 2422 sTemplates(end).Name = 'Brainnetome_leaddbs'; 2423 sTemplates(end).Info = 'http://atlas.brainnetome.org/'; 2424 end 2425 if ~ismember('brodmann', lower({sTemplates.Name})) 2426 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=mni_Brodmann'; 2427 sTemplates(end).Name = 'Brodmann'; 2428 sTemplates(end).Info = 'https://people.cas.sc.edu/rorden/mricro/lesion.html#brod'; 2429 end 2430 if ~ismember('hammers83', lower({sTemplates.Name})) 2431 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=mni_Hammers'; 2432 sTemplates(end).Name = 'Hammers'; 2433 sTemplates(end).Info = 'http://brain-development.org/brain-atlases/adult-brain-atlases/'; 2434 end 2435 if ~ismember('neuromorphometrics', lower({sTemplates.Name})) 2436 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=mni_Neuromorphometrics'; 2437 sTemplates(end).Name = 'Neuromorphometrics'; 2438 sTemplates(end).Info = 'https://search.kg.ebrains.eu/instances/Dataset/ef48c5e9-6b3c-4d5a-a9a9-e678fe10bdf6'; 2439 end 2440 if ~ismember('julich-brain-v25', lower({sTemplates.Name})) 2441 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=mni_Julich-Brain-v25'; 2442 sTemplates(end).Name = 'Julich-Brain-v25'; 2443 sTemplates(end).Info = 'https://search.kg.ebrains.eu/instances/Dataset/ef48c5e9-6b3c-4d5a-a9a9-e678fe10bdf6'; 2444 end 2445 if ~ismember('schaefer2018_100_7net', lower({sTemplates.Name})) 2446 sTemplates(end+1).FilePath = 'http://neuroimage.usc.edu/bst/getupdate.php?t=mni_Schaefer2018'; 2447 sTemplates(end).Name = 'Schaefer2018'; 2448 sTemplates(end).Info = 'https://github.com/ThomasYeoLab/CBIG/tree/master/stable_projects/brain_parcellation/Schaefer2018_LocalGlobal'; 2449 end 2450 % Return defaults list 2451 argout1 = sTemplates; 2452 2453 2454 %% ==== EEG DEFAULTS ==== 2455 % Returns an array of struct(fullpath, name) of all the Brainstorm eeg nets defaults 2456 % Usage: EegDefaults = bst_get('EegDefaults') 2457 % EegDefaults = bst_get('EegDefaults', TemplateName=[], SetupName=[]) 2458 case 'EegDefaults' 2459 % Parse inputs 2460 if (nargin >= 3) 2461 SetupName = varargin{3}; 2462 else 2463 SetupName = []; 2464 end 2465 if (nargin >= 2) 2466 TemplateName = varargin{2}; 2467 else 2468 TemplateName = []; 2469 end 2470 % Get templates from the brainstorm3 folder 2471 progDir = bst_fullfile(bst_get('BrainstormDefaultsDir'), 'eeg'); 2472 progFiles = dir(bst_fullfile(progDir, '*')); 2473 % Get templates from the user folder 2474 userDir = bst_fullfile(bst_get('UserDefaultsDir'), 'eeg'); 2475 userFiles = dir(bst_fullfile(userDir, '*')); 2476 % Combine the two lists 2477 dirList = cat(2, cellfun(@(c)bst_fullfile(progDir,c), {progFiles.name}, 'UniformOutput', 0), ... 2478 cellfun(@(c)bst_fullfile(userDir,c), setdiff({userFiles.name}, {progFiles.name}), 'UniformOutput', 0)); 2479 % Initialize list of folders 2480 fullDefaultsList = repmat(struct('contents','', 'name',''), 0); 2481 % For each template directory 2482 for iDir = 1:length(dirList) 2483 % Decompose file name 2484 [fPath, fBase, fExt] = bst_fileparts(dirList{iDir}); 2485 % Entry is a not a folder, or starts with a "." 2486 if ~isdir(dirList{iDir}) || isempty(fBase) || strcmpi(fBase(1),'.') 2487 continue; 2488 end 2489 % Skip if it is not the requested template 2490 if ~isempty(TemplateName) && ~strcmpi(fBase, TemplateName) 2491 continue; 2492 end 2493 % Get files list 2494 fileList = dir(bst_fullfile(dirList{iDir}, 'channel*.mat')); 2495 defaultsList = repmat(struct('fullpath','', 'name',''), 0); 2496 % Find all the valid defaults (channel files) 2497 for iFile = 1:length(fileList) 2498 [tmp__, baseName] = bst_fileparts(fileList(iFile).name); 2499 baseName = strrep(baseName, 'channel_', ''); 2500 baseName = strrep(baseName, '_channel', ''); 2501 baseName = strrep(baseName, '_', ' '); 2502 % Skip if it is not the requested template 2503 if ~isempty(SetupName) && ~strcmpi(baseName, SetupName) 2504 continue; 2505 end 2506 % Add to list of templates 2507 iNewDefault = length(defaultsList) + 1; 2508 defaultsList(iNewDefault).fullpath = bst_fullfile(dirList{iDir}, fileList(iFile).name); 2509 defaultsList(iNewDefault).name = baseName; 2510 end 2511 % Add files list to defaults list 2512 if ~isempty(defaultsList) 2513 fullDefaultsList(end + 1) = struct('contents', defaultsList, ... 2514 'name', fBase); 2515 end 2516 end 2517 % Return defaults list 2518 argout1 = fullDefaultsList; 2519 2520 2521 %% ==== GET FILENAMES ==== 2522 case 'GetFilenames' 2523 iStudies = varargin{2}; 2524 iItems = varargin{3}; 2525 DataType = varargin{4}; 2526 FileNames = cell(1, length(iStudies)); 2527 argout1 = {}; 2528 for i = 1:length(iStudies) 2529 % Get study definition 2530 sStudy = bst_get('Study', iStudies(i)); 2531 if isempty(sStudy) 2532 continue; 2533 end 2534 % Recordings or sources 2535 switch (DataType) 2536 case 'data' 2537 if (iItems(i) > length(sStudy.Data)) 2538 return; 2539 end 2540 FileNames{i} = sStudy.Data(iItems(i)).FileName; 2541 case 'results' 2542 if (iItems(i) > length(sStudy.Result)) 2543 return; 2544 end 2545 FileNames{i} = sStudy.Result(iItems(i)).FileName; 2546 case 'timefreq' 2547 if (iItems(i) > length(sStudy.Timefreq)) 2548 return; 2549 end 2550 FileNames{i} = sStudy.Timefreq(iItems(i)).FileName; 2551 case 'matrix' 2552 if (iItems(i) > length(sStudy.Matrix)) 2553 return; 2554 end 2555 FileNames{i} = sStudy.Matrix(iItems(i)).FileName; 2556 case {'pdata','presults','ptimfreq'} 2557 if (iItems(i) > length(sStudy.Stat)) 2558 return; 2559 end 2560 FileNames{i} = sStudy.Stat(iItems(i)).FileName; 2561 end 2562 end 2563 argout1 = FileNames; 2564 2565 2566 %% ==== GUI ==== 2567 case 'BstFrame' 2568 if isempty(GlobalData) || isempty(GlobalData.Program.GUI) || isempty(GlobalData.Program.GUI.mainWindow) 2569 argout1 = []; 2570 else 2571 argout1 = GlobalData.Program.GUI.mainWindow.jBstFrame; 2572 end 2573 case 'BstControls' 2574 if isempty(GlobalData) || isempty(GlobalData.Program) || isempty(GlobalData.Program.GUI) || isempty(GlobalData.Program.GUI.mainWindow) 2575 argout1 = []; 2576 else 2577 argout1 = GlobalData.Program.GUI.mainWindow; 2578 end 2579 case 'isGUI' 2580 if isempty(GlobalData) || isempty(GlobalData.Program) || ~isfield(GlobalData.Program, 'GuiLevel') 2581 argout1 = []; 2582 else 2583 argout1 = (GlobalData.Program.GuiLevel >= 1); 2584 end 2585 case 'GuiLevel' 2586 if isempty(GlobalData) || isempty(GlobalData.Program) || ~isfield(GlobalData.Program, 'GuiLevel') 2587 argout1 = []; 2588 else 2589 argout1 = GlobalData.Program.GuiLevel; 2590 end 2591 case 'ScreenDef' 2592 if isempty(GlobalData) || isempty(GlobalData.Program) || ~isfield(GlobalData.Program, 'ScreenDef') 2593 argout1 = []; 2594 else 2595 argout1 = GlobalData.Program.ScreenDef; 2596 end 2597 case 'DecorationSize' 2598 if isempty(GlobalData) || isempty(GlobalData.Program) || ~isfield(GlobalData.Program, 'DecorationSize') 2599 argout1 = []; 2600 else 2601 argout1 = GlobalData.Program.DecorationSize; 2602 end 2603 case 'Layout' 2604 % Default or current layout structure 2605 if ~isfield(GlobalData, 'Preferences') || ~isfield(GlobalData.Preferences, 'Layout') || ~((nargin == 1) || isfield(GlobalData.Preferences.Layout, varargin{2})) || ~isfield(GlobalData.Preferences.Layout, 'MainWindowPos') 2606 GlobalData.Preferences.Layout = db_template('Layout'); 2607 end 2608 % Structure or property call 2609 if (nargin == 2) && ischar(varargin{2}) && isfield(GlobalData.Preferences.Layout, varargin{2}) 2610 argout1 = GlobalData.Preferences.Layout.(varargin{2}); 2611 elseif (nargin == 1) 2612 argout1 = GlobalData.Preferences.Layout; 2613 else 2614 error('Invalid call to bst_get.'); 2615 end 2616 2617 case 'ByteOrder' 2618 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'ByteOrder') 2619 argout1 = GlobalData.Preferences.ByteOrder; 2620 else 2621 argout1 = 'l'; 2622 end 2623 2624 case 'UniformizeTimeSeriesScales' 2625 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'UniformizeTimeSeriesScales') 2626 argout1 = GlobalData.Preferences.UniformizeTimeSeriesScales; 2627 else 2628 argout1 = 1; 2629 end 2630 2631 case 'FlipYAxis' 2632 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'FlipYAxis') 2633 argout1 = GlobalData.Preferences.FlipYAxis; 2634 else 2635 argout1 = 0; 2636 end 2637 2638 case 'AutoScaleY' 2639 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'AutoScaleY') 2640 argout1 = GlobalData.Preferences.AutoScaleY; 2641 else 2642 argout1 = 1; 2643 end 2644 2645 case 'ShowXGrid' 2646 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'ShowXGrid') 2647 argout1 = GlobalData.Preferences.ShowXGrid; 2648 else 2649 argout1 = 0; 2650 end 2651 2652 case 'ShowYGrid' 2653 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'ShowYGrid') 2654 argout1 = GlobalData.Preferences.ShowYGrid; 2655 else 2656 argout1 = 0; 2657 end 2658 2659 case 'ShowZeroLines' 2660 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'ShowZeroLines') 2661 argout1 = GlobalData.Preferences.ShowZeroLines; 2662 else 2663 argout1 = 1; 2664 end 2665 2666 case 'Resolution' 2667 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'Resolution') 2668 argout1 = GlobalData.Preferences.Resolution; 2669 else 2670 argout1 = [0 0]; 2671 end 2672 2673 case 'FixedScaleY' 2674 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'FixedScaleY') && isfield(GlobalData.Preferences.FixedScaleY, varargin{2}) && ~isempty(GlobalData.Preferences.FixedScaleY.(varargin{2})) 2675 argout1 = GlobalData.Preferences.FixedScaleY.(varargin{2}); 2676 else 2677 argout1 = []; 2678 end 2679 2680 case 'XScale' 2681 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'XScale') 2682 argout1 = GlobalData.Preferences.XScale; 2683 else 2684 argout1 = 'linear'; 2685 end 2686 2687 case 'YScale' 2688 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'YScale') 2689 argout1 = GlobalData.Preferences.YScale; 2690 else 2691 argout1 = 'linear'; 2692 end 2693 2694 case 'ShowEventsMode' 2695 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'ShowEventsMode') 2696 argout1 = GlobalData.Preferences.ShowEventsMode; 2697 else 2698 argout1 = 'dot'; 2699 end 2700 2701 case 'AutoUpdates' 2702 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'AutoUpdates') 2703 argout1 = GlobalData.Preferences.AutoUpdates; 2704 else 2705 argout1 = 1; 2706 end 2707 2708 case 'ForceMatCompression' 2709 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'ForceMatCompression') 2710 argout1 = GlobalData.Preferences.ForceMatCompression; 2711 else 2712 argout1 = 0; 2713 end 2714 2715 case 'IgnoreMemoryWarnings' 2716 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'IgnoreMemoryWarnings') 2717 argout1 = GlobalData.Preferences.IgnoreMemoryWarnings; 2718 else 2719 argout1 = 0; 2720 end 2721 2722 case 'SystemCopy' 2723 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'SystemCopy') 2724 argout1 = GlobalData.Preferences.SystemCopy; 2725 else 2726 argout1 = 0; 2727 end 2728 2729 case 'ExpertMode' 2730 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'ExpertMode') 2731 argout1 = GlobalData.Preferences.ExpertMode; 2732 else 2733 argout1 = 0; 2734 end 2735 2736 case 'DisplayGFP' 2737 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'DisplayGFP') 2738 argout1 = GlobalData.Preferences.DisplayGFP; 2739 else 2740 argout1 = 1; 2741 end 2742 2743 case 'DownsampleTimeSeries' 2744 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'DownsampleTimeSeries') 2745 if (GlobalData.Preferences.DownsampleTimeSeries == 1) 2746 GlobalData.Preferences.DownsampleTimeSeries = 5; 2747 end 2748 argout1 = GlobalData.Preferences.DownsampleTimeSeries; 2749 else 2750 argout1 = 5; 2751 end 2752 2753 case 'GraphicsSmoothing' 2754 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'GraphicsSmoothing') 2755 argout1 = GlobalData.Preferences.GraphicsSmoothing; 2756 else 2757 argout1 = 5; 2758 end 2759 2760 case 'DisableOpenGL' 2761 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'DisableOpenGL') 2762 argout1 = GlobalData.Preferences.DisableOpenGL; 2763 else 2764 argout1 = 0; 2765 end 2766 2767 case 'InterfaceScaling' 2768 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'InterfaceScaling') 2769 argout1 = GlobalData.Preferences.InterfaceScaling; 2770 else 2771 % Get screen resolution 2772 if isfield(GlobalData, 'Program') && isfield(GlobalData.Program, 'ScreenDef') && isfield(GlobalData.Program.ScreenDef, 'javaPos') && ~isempty(GlobalData.Program.ScreenDef(1).javaPos) 2773 AvailableRes = [100 125 150 200 250 300 400]; 2774 iRes = bst_closest(GlobalData.Program.ScreenDef(1).javaPos.width * 100 / 1920, AvailableRes); 2775 argout1 = AvailableRes(iRes); 2776 else 2777 argout1 = 100; 2778 end 2779 end 2780 2781 case 'TSDisplayMode' 2782 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'TSDisplayMode') 2783 argout1 = GlobalData.Preferences.TSDisplayMode; 2784 else 2785 argout1 = 'butterfly'; 2786 end 2787 2788 case 'PluginCustomPath' 2789 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'PluginCustomPath') && ~isempty(GlobalData.Preferences.PluginCustomPath) 2790 argout1 = GlobalData.Preferences.PluginCustomPath; 2791 else 2792 argout1 = []; 2793 end 2794 2795 case 'BrainSuiteDir' 2796 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'BrainSuiteDir') && ~isempty(GlobalData.Preferences.BrainSuiteDir) 2797 if isdir(GlobalData.Preferences.BrainSuiteDir) && file_exist(bst_fullfile(GlobalData.Preferences.BrainSuiteDir, 'bdp')) 2798 argout1 = GlobalData.Preferences.BrainSuiteDir; 2799 else 2800 argout1 = []; 2801 end 2802 else 2803 argout1 = []; 2804 end 2805 2806 case 'SpmTpmAtlas' 2807 preferSpm = 0; 2808 % CALL: bst_get('SpmTpmAtlas', 'SPM') 2809 if (nargin >= 2) && strcmpi(varargin{2}, 'SPM') 2810 preferSpm = 1; 2811 end 2812 2813 % Get template file 2814 tpmUser = bst_fullfile(bst_get('BrainstormUserDir'), 'defaults', 'spm', 'TPM.nii'); 2815 if file_exist(tpmUser) && ~preferSpm 2816 argout1 = tpmUser; 2817 disp(['BST> SPM12 template found: ' tpmUser]); 2818 return; 2819 end 2820 % If it does not exist: check in brainstorm3 folder 2821 tpmDistrib = bst_fullfile(bst_get('BrainstormHomeDir'), 'defaults', 'spm', 'TPM.nii'); 2822 if file_exist(tpmDistrib) && ~preferSpm 2823 argout1 = tpmDistrib; 2824 disp(['BST> SPM12 template found: ' tpmDistrib]); 2825 return; 2826 end 2827 % If it does not exist: check in spm12 folder 2828 PlugSpm = bst_plugin('GetInstalled', 'spm12'); 2829 if ~isempty(PlugSpm) 2830 tpmSpm = bst_fullfile(PlugSpm.Path, PlugSpm.SubFolder, 'tpm', 'TPM.nii'); 2831 if file_exist(tpmSpm) 2832 argout1 = tpmSpm; 2833 disp(['BST> SPM12 template found: ' tpmSpm]); 2834 return; 2835 elseif preferSpm 2836 argout1 = bst_get('SpmTpmAtlas'); 2837 return 2838 end 2839 else 2840 tpmSpm = ''; 2841 end 2842 % Not found... 2843 disp('SPM12 template not found in any of the following folders:'); 2844 disp([' - ' tpmUser]); 2845 disp([' - ' tpmDistrib]); 2846 if ~isempty(tpmSpm) 2847 disp([' - ' tpmSpm]); 2848 end 2849 argout1 = []; 2850 2851 case 'PythonExe' 2852 % Get saved value 2853 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'PythonExe') && ~isempty(GlobalData.Preferences.PythonExe) 2854 if file_exist(GlobalData.Preferences.PythonExe) 2855 argout1 = GlobalData.Preferences.PythonExe; 2856 else 2857 disp(['BST> Error: Python executable not found: ' GlobalData.Preferences.PythonExe]); 2858 argout1 = []; 2859 end 2860 else 2861 argout1 = []; 2862 end 2863 % If not defined in Brainstorm, but set in Matlab 2864 if isempty(argout1) 2865 [pyVer, PythonExe] = bst_python_ver(); 2866 if ~isempty(PythonExe) && file_exist(PythonExe) 2867 disp(['BST> Found Python executable: ' PythonExe]); 2868 argout1 = PythonExe; 2869 bst_set('PythonExe', PythonExe); 2870 end 2871 end 2872 2873 case 'ElectrodeConfig' 2874 % Get modality 2875 Modality = varargin{2}; 2876 if isequal(Modality, 'ECOG+SEEG') 2877 Modality = 'ECOG_SEEG'; 2878 elseif isempty(Modality) || ~ismember(Modality, {'EEG','ECOG','SEEG'}) 2879 error(['Invalid modality: ' Modality]); 2880 end 2881 % Value was saved previously 2882 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'ElectrodeConfig') && isfield(GlobalData.Preferences.ElectrodeConfig, Modality) && isfield(GlobalData.Preferences.ElectrodeConfig.(Modality), 'ContactDiameter') 2883 argout1 = GlobalData.Preferences.ElectrodeConfig.(Modality); 2884 % Get default value 2885 else 2886 switch (Modality) 2887 case 'EEG' 2888 ElectrodeConfig.Type = 'eeg'; 2889 ElectrodeConfig.ContactDiameter = 0.010; 2890 ElectrodeConfig.ContactLength = 0.002; 2891 ElectrodeConfig.ElecDiameter = []; 2892 ElectrodeConfig.ElecLength = []; 2893 case 'ECOG' 2894 ElectrodeConfig.Type = 'ecog'; 2895 ElectrodeConfig.ContactDiameter = 0.004; 2896 ElectrodeConfig.ContactLength = 0.001; 2897 ElectrodeConfig.ElecDiameter = 0.0005; 2898 ElectrodeConfig.ElecLength = []; 2899 case {'SEEG','ECOG_SEEG'} 2900 ElectrodeConfig.Type = 'seeg'; 2901 ElectrodeConfig.ContactDiameter = 0.0008; 2902 ElectrodeConfig.ContactLength = 0.002; 2903 ElectrodeConfig.ElecDiameter = 0.0007; 2904 ElectrodeConfig.ElecLength = 0.070; 2905 end 2906 argout1 = ElectrodeConfig; 2907 end 2908 2909 case 'ElecInterpDist' 2910 % Get modality 2911 Modality = varargin{2}; 2912 if isequal(Modality, 'ECOG+SEEG') 2913 Modality = 'ECOG_SEEG'; 2914 elseif isempty(Modality) || ~ismember(Modality, {'EEG','ECOG','SEEG','MEG'}) 2915 error(['Invalid modality: ' Modality]); 2916 end 2917 % Value was saved previously 2918 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'ElecInterpDist') && isfield(GlobalData.Preferences.ElecInterpDist, Modality) 2919 argout1 = GlobalData.Preferences.ElecInterpDist.(Modality); 2920 % Get default value 2921 else 2922 switch (Modality) 2923 case 'EEG', argout1 = .3; 2924 case 'ECOG', argout1 = .015; 2925 case 'SEEG', argout1 = .015; 2926 case 'ECOG_SEEG', argout1 = .015; 2927 case 'MEG', argout1 = .5; 2928 end 2929 end 2930 2931 case 'UseSigProcToolbox' 2932 % In a parfor loop: GlobalData is empty => Check only if the toolbox is installed (ignore user preferences) 2933 if isempty(GlobalData) || ~isfield(GlobalData, 'Program') || ~isfield(GlobalData.Program, 'HasSigProcToolbox') 2934 argout1 = exist('kaiserord', 'file'); 2935 else 2936 % Save the result of the check for the SigProc tb 2937 if isempty(GlobalData.Program.HasSigProcToolbox) 2938 % Check if Signal Processing Toolbox is installed 2939 GlobalData.Program.HasSigProcToolbox = (exist('kaiserord', 'file') == 2); 2940 end 2941 % Return user preferences 2942 if ~GlobalData.Program.HasSigProcToolbox 2943 argout1 = 0; 2944 elseif isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'UseSigProcToolbox') 2945 argout1 = GlobalData.Preferences.UseSigProcToolbox; 2946 else 2947 argout1 = 1; 2948 end 2949 end 2950 2951 case 'CustomColormaps' 2952 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'CustomColormaps') && ~isempty(GlobalData.Preferences.CustomColormaps) 2953 argout1 = GlobalData.Preferences.CustomColormaps; 2954 else 2955 argout1 = repmat(struct('Name', '', 'CMap', []), 0); 2956 end 2957 2958 case 'BFSProperties' 2959 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'BFSProperties') && ~isempty(GlobalData.Preferences.BFSProperties) 2960 argout1 = GlobalData.Preferences.BFSProperties; 2961 else 2962 argout1 = [.33 .0042 .33 .88 .93]; 2963 end 2964 2965 case 'LastUsedDirs' 2966 defPref = struct(... 2967 'ImportData', '', ... 2968 'ImportChannel', '', ... 2969 'ImportAnat', '', ... 2970 'ImportMontage', '', ... 2971 'ExportChannel', '', ... 2972 'ExportData', '', ... 2973 'ExportAnat', '', ... 2974 'ExportProtocol', '', ... 2975 'ExportImage', '', ... 2976 'ExportScript', '', ... 2977 'ExportMontage', ''); 2978 argout1 = FillMissingFields(contextName, defPref); 2979 % Check that all folders are valid 2980 fields = fieldnames(argout1); 2981 for i = 1:length(fields) 2982 if ~ischar(argout1.(fields{i})) || ~file_exist(argout1.(fields{i})) 2983 argout1.(fields{i}) = ''; 2984 end 2985 end 2986 2987 case 'DefaultFormats' 2988 defPref = struct(... 2989 'AnatIn', 'FreeSurfer', ... 2990 'ChannelIn', '', ... 2991 'ChannelOut', '', ... 2992 'DataIn', 'CTF', ... 2993 'DataOut', '', ... 2994 'DipolesIn', '', ... 2995 'DipolesOut', '', ... 2996 'ImageOut', '', ... 2997 'EventsIn', '', ... 2998 'EventsOut', '', ... 2999 'MriIn', '', ... 3000 'MriOut', 'Nifti1', ... 3001 'NoiseCovIn', '', ... 3002 'NoiseCovOut', '', ... 3003 'ResultsIn', '', ... 3004 'ResultsOut', '', ... 3005 'SpmOut', '', ... 3006 'SspIn', '', ... 3007 'SspOut', '', ... 3008 'SurfaceIn', '', ... 3009 'SurfaceOut', '', ... 3010 'LabelIn', '', ... 3011 'LabelOut', '', ... 3012 'TimefreqIn', '', ... 3013 'TimefreqOut', '', ... 3014 'MatrixIn', '', ... 3015 'MatrixOut', '', ... 3016 'MontageIn', '', ... 3017 'MontageOut', '', ... 3018 'FibersIn', ''); 3019 argout1 = FillMissingFields(contextName, defPref); 3020 3021 case 'OsType' 3022 switch (mexext) 3023 case 'mexglx', argout1 = 'linux32'; 3024 case 'mexa64', argout1 = 'linux64'; 3025 case 'mexmaci', argout1 = 'mac32'; 3026 case 'mexmaci64', argout1 = 'mac64'; 3027 case 'mexmaca64', argout1 = 'mac64arm'; 3028 case 'mexs64', argout1 = 'sol64'; 3029 case 'mexw32', argout1 = 'win32'; 3030 case 'mexw64', argout1 = 'win64'; 3031 otherwise, error('Unsupported extension.'); 3032 end 3033 % CALL: bst_get('OsType', isMatlab=0) 3034 if (nargin >= 2) && isequal(varargin{2}, 0) 3035 if strcmpi(argout1, 'win32') && (~isempty(strfind(java.lang.System.getProperty('java.home'), '(x86)')) || ~isempty(strfind(java.lang.System.getenv('ProgramFiles(x86)'), '(x86)'))) 3036 argout1 = 'win64'; 3037 end 3038 end 3039 3040 case 'ImportDataOptions' 3041 defPref = db_template('ImportOptions'); 3042 argout1 = FillMissingFields(contextName, defPref); 3043 3044 case 'RawViewerOptions' 3045 defPref = struct(... 3046 'PageDuration', 3, ... 3047 'RemoveBaseline', 'all', ... 3048 'UseCtfComp', 1, ... 3049 'Shortcuts', []); 3050 defPref.Shortcuts = {... 3051 '1', 'event1', 'simple', []; ... % Key, event name, event type (simple,extended,page), epoch time 3052 '2', 'event2', 'simple', []; ... 3053 '3', 'event3', 'simple', []; ... 3054 '4', 'event4', 'simple', []; ... 3055 '5', 'event5', 'simple', []; ... 3056 '6', 'event6', 'simple', []; ... 3057 '7', 'event7', 'simple', []; ... 3058 '8', 'event8', 'simple', []; ... 3059 '9', 'event9', 'simple', []}; 3060 argout1 = FillMissingFields(contextName, defPref); 3061 % If invalid PageDuration: reset to default 3062 if (argout1.PageDuration <= 0.1) 3063 argout1.PageDuration = defPref.PageDuration; 3064 end 3065 % If old shortcuts: reset to defaults 3066 if any(size(argout1.Shortcuts) ~= size(defPref.Shortcuts)) 3067 disp('BST> Warning: Reset keyboard shortcuts to include new options.'); 3068 argout1.Shortcuts = defPref.Shortcuts; 3069 bst_set('RawViewerOptions', argout1); 3070 end 3071 3072 case 'MontageOptions' 3073 defPref = struct('Shortcuts', []); 3074 defPref.Shortcuts = { 3075 %'a', []; ... Note: A is reserved for All channels 3076 'b', []; ... 3077 'c', []; ... 3078 'd', []; ... 3079 'e', []; ... 3080 'f', []; ... 3081 'g', []; ... 3082 'h', []; ... 3083 'i', []; ... 3084 'j', []; ... 3085 'k', []; ... 3086 'l', []; ... 3087 'm', []; ... 3088 'n', []; ... 3089 'o', []; ... 3090 'p', []; ... 3091 'q', []; ... 3092 'r', []; ... 3093 's', []; ... 3094 't', []; ... 3095 'u', []; ... 3096 'v', []; ... 3097 'w', []; ... 3098 'x', []; ... 3099 'y', []; ... 3100 'z', []; ... 3101 }; 3102 argout1 = FillMissingFields(contextName, defPref); 3103 3104 case 'TopoLayoutOptions' 3105 defPref = struct(... 3106 'TimeWindow', [], ... 3107 'WhiteBackground', 0, ... 3108 'ShowRefLines', 1, ... 3109 'ShowLegend', 1, ... 3110 'FlipYAxis', 0, ... 3111 'ContourLines', 10); 3112 argout1 = FillMissingFields(contextName, defPref); 3113 3114 case 'StatThreshOptions' 3115 defPref = struct(... 3116 'pThreshold', .05, ... 3117 'durThreshold', 0, ... 3118 'Correction', 'fdr', ... 3119 'Control', [1 2 3]); 3120 argout1 = FillMissingFields(contextName, defPref); 3121 % Make sure that Control is not a string (previous brainstorm version) 3122 if ischar(argout1.Control) 3123 argout1.Control = defPref.Control; 3124 end 3125 % Make sure that 'no' is used instead of 'none' (previous brainstorm version) 3126 if strcmpi(argout1.Correction, 'none') 3127 argout1.Correction = 'no'; 3128 end 3129 3130 case 'ContactSheetOptions' 3131 defPref = struct(... 3132 'nImages', 20, ... 3133 'TimeRange', [], ... 3134 'SkipVolume', 0.2); 3135 argout1 = FillMissingFields(contextName, defPref); 3136 3137 case 'ProcessOptions' 3138 defPref = struct(... 3139 'SavedParam', struct(), ... 3140 'MaxBlockSize', 100 / 8 * 1024 * 1024, ... % 100Mb 3141 'LastMaxBlockSize', 100 / 8 * 1024 * 1024); % 100Mb 3142 argout1 = FillMissingFields(contextName, defPref); 3143 3144 case 'ImportEegRawOptions' 3145 defPref = struct(... 3146 'isCanceled', 0, ... 3147 'BaselineDuration', 0, ... 3148 'SamplingRate', 1000, ... 3149 'MatrixOrientation', 'channelXtime', ... % {'channelXtime', 'timeXchannel'} 3150 'VoltageUnits', 'V', ... % {'\muV', 'mV', 'V'} 3151 'SkipLines', 0, ... 3152 'nAvg', 1, ... 3153 'isChannelName', 0); % 1 if the first entry contains the channel name 3154 argout1 = FillMissingFields(contextName, defPref); 3155 3156 case 'BugReportOptions' 3157 defPref = struct(... 3158 'isEnabled', 0, ... 3159 'SmtpServer', 'mailhost.chups.jussieu.fr', ... 3160 'UserEmail', ''); 3161 argout1 = FillMissingFields(contextName, defPref); 3162 3163 case 'DefaultSurfaceDisplay' 3164 defPref = struct(... 3165 'SurfShowSulci', 1, ... 3166 'SurfSmoothValue', 0, ... 3167 'DataThreshold', 0.5, ... 3168 'SizeThreshold', 1, ... 3169 'DataAlpha', 0); 3170 argout1 = FillMissingFields(contextName, defPref); 3171 3172 case 'MagneticExtrapOptions' 3173 defPref = struct(... 3174 'ForceWhitening', 0, ... 3175 'EpsilonValue', 0.0001); 3176 argout1 = FillMissingFields(contextName, defPref); 3177 3178 case 'DefaultFreqBands' 3179 argout1 = {... 3180 'delta', '2, 4', 'mean'; ... 3181 'theta', '5, 7', 'mean'; ... 3182 'alpha', '8, 12', 'mean'; ... 3183 'beta', '15, 29', 'mean'; ... 3184 'gamma1', '30, 59', 'mean'; ... 3185 'gamma2', '60, 90', 'mean'}; 3186 3187 case 'TimefreqOptions_morlet' 3188 defPref.isTimeBands = 0; 3189 defPref.isFreqBands = 0; 3190 defPref.isFreqLog = 0; 3191 defPref.TimeBands = {}; 3192 defPref.Freqs = '1:1:60'; 3193 defPref.FreqsLog = '1:40:150'; 3194 defPref.FreqBands = bst_get('DefaultFreqBands'); 3195 defPref.Measure = 'power'; 3196 defPref.SaveKernel = 0; 3197 defPref.Output = 'all'; 3198 defPref.RemoveEvoked = 0; 3199 defPref.ClusterFuncTime = 'after'; 3200 defPref.MorletFc = 1; 3201 defPref.MorletFwhmTc = 3; 3202 argout1 = FillMissingFields(contextName, defPref); 3203 if isempty(argout1.Freqs) 3204 argout1.Freqs = defPref.Freqs; 3205 end 3206 if ~isempty(argout1.FreqBands) && ((size(argout1.FreqBands,2) ~= 3) || ~all(cellfun(@ischar, argout1.FreqBands(:))) || any(cellfun(@(c)isempty(strtrim(c)), argout1.FreqBands(:)))) 3207 argout1.FreqBands = defPref.FreqBands; 3208 end 3209 3210 case 'TimefreqOptions_hilbert' 3211 defPref.isTimeBands = 0; 3212 defPref.isFreqBands = 1; 3213 defPref.isFreqLog = 0; 3214 defPref.TimeBands = {}; 3215 defPref.Freqs = []; 3216 defPref.FreqsLog = []; 3217 defPref.FreqBands = bst_get('DefaultFreqBands'); 3218 defPref.Measure = 'power'; 3219 defPref.SaveKernel = 0; 3220 defPref.Output = 'all'; 3221 defPref.RemoveEvoked = 0; 3222 defPref.ClusterFuncTime = 'after'; 3223 argout1 = FillMissingFields(contextName, defPref); 3224 if isempty(argout1.Freqs) 3225 argout1.Freqs = defPref.Freqs; 3226 end 3227 if ~isempty(argout1.FreqBands) && (size(argout1.FreqBands,2) == 3) && ~ischar(argout1.FreqBands{1,2}) 3228 argout1.FreqBands = defPref.FreqBands; 3229 end 3230 3231 case 'TimefreqOptions_plv' % not used 3232 defPref.isTimeBands = 0; 3233 defPref.isFreqBands = 1; 3234 defPref.isFreqLog = 0; 3235 defPref.TimeBands = {}; 3236 defPref.Freqs = []; 3237 defPref.FreqsLog = []; 3238 defPref.FreqBands = bst_get('DefaultFreqBands'); 3239 defPref.Measure = 'other'; 3240 defPref.SaveKernel = 0; 3241 defPref.Output = 'all'; 3242 defPref.ClusterFuncTime = 'after'; 3243 argout1 = FillMissingFields(contextName, defPref); 3244 if isempty(argout1.Freqs) 3245 argout1.Freqs = defPref.Freqs; 3246 end 3247 if ~isempty(argout1.FreqBands) && ~ischar(argout1.FreqBands{1,2}) 3248 argout1.FreqBands = defPref.FreqBands; 3249 end 3250 3251 case 'TimefreqOptions_fft' 3252 defPref.isTimeBands = 0; 3253 defPref.isFreqBands = 0; 3254 defPref.isFreqLog = 0; 3255 defPref.TimeBands = {}; 3256 defPref.Freqs = []; 3257 defPref.FreqsLog = []; 3258 defPref.FreqBands = bst_get('DefaultFreqBands'); 3259 defPref.Measure = 'power'; 3260 defPref.Output = 'all'; 3261 defPref.ClusterFuncTime = 'after'; 3262 argout1 = FillMissingFields(contextName, defPref); 3263 if isempty(argout1.Freqs) 3264 argout1.Freqs = defPref.Freqs; 3265 end 3266 if ~isempty(argout1.FreqBands) && ~ischar(argout1.FreqBands{1,2}) 3267 argout1.FreqBands = defPref.FreqBands; 3268 end 3269 3270 case 'TimefreqOptions_psd' 3271 defPref.isTimeBands = 0; 3272 defPref.isFreqBands = 0; 3273 defPref.isFreqLog = 0; 3274 defPref.TimeBands = {}; 3275 defPref.Freqs = []; 3276 defPref.FreqsLog = []; 3277 defPref.FreqBands = bst_get('DefaultFreqBands'); 3278 defPref.Measure = 'power'; 3279 defPref.Output = 'all'; 3280 defPref.ClusterFuncTime = 'after'; 3281 argout1 = FillMissingFields(contextName, defPref); 3282 if isempty(argout1.Freqs) 3283 argout1.Freqs = defPref.Freqs; 3284 end 3285 if ~isempty(argout1.FreqBands) && ~ischar(argout1.FreqBands{1,2}) 3286 argout1.FreqBands = defPref.FreqBands; 3287 end 3288 3289 case 'TimefreqOptions_stft' 3290 defPref.isTimeBands = 0; 3291 defPref.isFreqBands = 0; 3292 defPref.isFreqLog = 0; 3293 defPref.TimeBands = {}; 3294 defPref.Freqs = []; 3295 defPref.FreqsLog = []; 3296 defPref.FreqBands = bst_get('DefaultFreqBands'); 3297 defPref.Measure = 'power'; 3298 defPref.Output = 'all'; 3299 defPref.ClusterFuncTime = 'after'; 3300 defPref.StftWinLen = 1; 3301 defPref.StftWinOvr = 0; 3302 defPref.StftFrqMax = 0; 3303 argout1 = FillMissingFields(contextName, defPref); 3304 if isempty(argout1.Freqs) 3305 argout1.Freqs = defPref.Freqs; 3306 end 3307 if ~isempty(argout1.FreqBands) && ~ischar(argout1.FreqBands{1,2}) 3308 argout1.FreqBands = defPref.FreqBands; 3309 end 3310 3311 case 'ExportBidsOptions' 3312 defPref.ProjName = []; 3313 defPref.ProjID = []; 3314 defPref.ProjDesc = []; 3315 defPref.Categories = []; 3316 defPref.JsonDataset = ['{' 10 ' "License": "PD"' 10 '}']; 3317 defPref.JsonMeg = ['{' 10 ' "TaskDescription": "My task"' 10 '}']; 3318 argout1 = FillMissingFields(contextName, defPref); 3319 3320 case 'OpenMEEGOptions' 3321 defPref.BemFiles = {}; 3322 defPref.BemNames = {'Scalp', 'Skull', 'Brain'}; 3323 defPref.BemCond = [1, 0.0125, 1]; 3324 defPref.BemSelect = [1 1 1]; 3325 defPref.isAdjoint = 0; 3326 defPref.isAdaptative = 1; 3327 defPref.isSplit = 0; 3328 defPref.SplitLength = 4000; 3329 argout1 = FillMissingFields(contextName, defPref); 3330 3331 case 'DuneuroOptions' 3332 defPref = duneuro_defaults(); 3333 argout1 = FillMissingFields(contextName, defPref); 3334 3335 case 'GridOptions_dipfit' 3336 defPref = struct(... 3337 'Method', 'isotropic', ... 3338 'nLayers', 17, ... 3339 'Reduction', 3, ... 3340 'nVerticesInit', 4000, ... 3341 'Resolution', 0.020, ... 3342 'FileName', ''); 3343 argout1 = FillMissingFields(contextName, defPref); 3344 3345 case 'GridOptions_headmodel' 3346 defPref = struct(... 3347 'Method', 'isotropic', ... 3348 'nLayers', 17, ... 3349 'Reduction', 3, ... 3350 'nVerticesInit', 4000, ... 3351 'Resolution', 0.005, ... 3352 'FileName', ''); 3353 argout1 = FillMissingFields(contextName, defPref); 3354 3355 case 'MriOptions' 3356 defPref = struct(... 3357 'isRadioOrient', 0, ... 3358 'isMipAnatomy', 0, ... 3359 'isMipFunctional', 0, ... 3360 'OverlaySmooth', 0, ... 3361 'InterpDownsample', 3, ... 3362 'DistanceThresh', 6, ... 3363 'UpsampleImage', 0, ... 3364 'DefaultAtlas', []); 3365 argout1 = FillMissingFields(contextName, defPref); 3366 3367 case 'DigitizeOptions' 3368 defPref = struct(... 3369 'ComPort', 'COM1', ... 3370 'ComRate', 9600, ... 3371 'ComByteCount', 94, ... % 47 bytes * 2 receivers 3372 'UnitType', 'fastrak', ... 3373 'PatientId', 'S001', ... 3374 'nFidSets', 2, ... 3375 'isBeep', 1, ... 3376 'isMEG', 1, ... 3377 'isSimulate', 0, ... 3378 'Montages', [... 3379 struct('Name', 'No EEG', ... 3380 'Labels', []), ... 3381 struct('Name', 'Default', ... 3382 'Labels', [])], ... 3383 'iMontage', 1); 3384 argout1 = FillMissingFields(contextName, defPref); 3385 3386 case 'PcaOptions' 3387 defPref.Method = 'pca'; % deprecated legacy per-file with sign inconsistencies, but kept as default for reproducibility 3388 defPref.Baseline = [-.1, 0]; % not used for 'pca': full window instead 3389 defPref.DataTimeWindow = [0, 1]; % not used for 'pca': full window instead 3390 defPref.RemoveDcOffset = 'file'; 3391 argout1 = FillMissingFields(contextName, defPref); 3392 3393 case 'ConnectGraphOptions' 3394 % Get interface scaling factor 3395 InterfaceScaling = bst_get('InterfaceScaling'); 3396 % Get default values 3397 defPref = struct(... 3398 'LobeFullLabel', 1, ... 3399 'TextDisplayMode', [1 2], ... 3400 'LabelSize', 7 .* InterfaceScaling ./ 100, ... 3401 'NodeSize', 5 .* InterfaceScaling ./ 100, ... 3402 'LinkSize', 1.5 .* InterfaceScaling ./ 100, ... 3403 'BgColor', [0 0 0], ... 3404 'HierarchyNodeIsVisible', 1); 3405 % If we have an additional argument, get the default values 3406 if nargin > 1 3407 argout1 = defPref; 3408 % Otherwise, get the saved values 3409 else 3410 savedValues = FillMissingFields(contextName, defPref); 3411 3412 % if any of the fields are [], replace by default value 3413 % do it here to avoid touching the common FillMissingFields 3414 % function, as other tools may actually want to set [] as desired property 3415 fields = fieldnames(savedValues); 3416 for i=1:numel(fields) 3417 if(isempty(savedValues.(fields{i}))) 3418 savedValues.(fields{i}) = defPref.(fields{i}); 3419 end 3420 end 3421 argout1 = savedValues; 3422 end 3423 3424 case 'NodelistOptions' 3425 defPref = struct(... 3426 'String', '', ... % What to search for 3427 'Target', 'Comment', ... % What field to search for: {'FileName', 'Comment'} 3428 'Action', 'Select'); % What to do with the filtered files: {'Select', 'Exclude'} 3429 argout1 = FillMissingFields(contextName, defPref); 3430 3431 case 'ReadOnly' 3432 if isfield(GlobalData.DataBase, 'isReadOnly') 3433 argout1 = GlobalData.DataBase.isReadOnly; 3434 else 3435 argout1 = 0; 3436 end 3437 3438 case 'LastPsdDisplayFunction' 3439 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'LastPsdDisplayFunction') 3440 argout1 = GlobalData.Preferences.LastPsdDisplayFunction; 3441 else 3442 argout1 = []; 3443 end 3444 3445 case 'PlotlyCredentials' 3446 % Get saved username and API key 3447 try 3448 creds = loadplotlycredentials(); 3449 argout1 = creds.username; 3450 argout2 = creds.api_key; 3451 catch 3452 argout1 = ''; 3453 argout2 = ''; 3454 end 3455 % Get saved domain 3456 try 3457 config = loadplotlyconfig(); 3458 argout3 = config.plotly_domain; 3459 catch 3460 argout3 = ''; 3461 end 3462 3463 case 'KlustersExecutable' 3464 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, 'KlustersExecutable') 3465 argout1 = GlobalData.Preferences.KlustersExecutable; 3466 else 3467 argout1 = []; 3468 end 3469 3470 3471 %% ===== FILE FILTERS ===== 3472 case 'FileFilters' 3473 switch lower(varargin{2}) 3474 case 'mri' 3475 argout1 = {... 3476 {'.img'}, 'MRI: Analyze (*.img/*.hdr)', 'Analyze'; ... 3477 {'.ima'}, 'MRI: BrainVISA GIS (*.ima/*.dim)', 'GIS'; ... 3478 {'.ima'}, 'MRI: BrainVISA GIS (*.ima/*.dim)', 'GIS'; ... 3479 {'.mri'}, 'MRI: CTF (*.mri)', 'CTF'; ... 3480 {'.mat'}, 'MRI: FieldTrip (*.mat)', 'FT-MRI'; ... 3481 {'.mgh','.mgz'}, 'MRI: MGH (*.mgh,*.mgz)', 'MGH'; ... 3482 {'.mnc', '.mni'}, 'MRI: MNI (*.mnc,*.mni)', 'MINC'; ... 3483 {'.nii','.gz'}, 'MRI: NIfTI-1 (*.nii;*.nii.gz)', 'Nifti1'; ... 3484 {'_subjectimage'}, 'MRI: Brainstorm (*subjectimage*.mat)', 'BST'; ... 3485 {'*'}, 'MRI: DICOM (SPM converter)', 'DICOM-SPM'; ... 3486 {'.mri', '.fif', '.img', '.ima', '.nii', '.mgh', '.mgz', '.mnc', '.mni', '.gz', '_subjectimage'}, 'All MRI files (subject space)', 'ALL'; ... 3487 {'.mri', '.fif', '.img', '.ima', '.nii', '.mgh', '.mgz', '.mnc', '.mni', '.gz', '_subjectimage'}, 'All MRI files (MNI space)', 'ALL-MNI'; ... 3488 {'.mri', '.fif', '.img', '.ima', '.nii', '.mgh', '.mgz', '.mnc', '.mni', '.gz', '_subjectimage'}, 'Volume atlas (subject space)', 'ALL-ATLAS'; ... 3489 {'.mri', '.fif', '.img', '.ima', '.nii', '.mgh', '.mgz', '.mnc', '.mni', '.gz', '_subjectimage'}, 'Volume atlas (MNI space)', 'ALL-MNI-ATLAS'; ... 3490 }; 3491 case 'mriout' 3492 argout1 = {... 3493 {'.img'}, 'MRI: Analyze (*.img/*.hdr)', 'Analyze'; ... 3494 {'.ima'}, 'MRI: BrainVISA GIS (*.ima/*.dim)', 'GIS'; ... 3495 {'.mri'}, 'MRI: CTF (*.mri)', 'CTF'; ... 3496 {'.mat'}, 'MRI: FieldTrip (*.mat)', 'FT-MRI'; ... 3497 {'.nii'}, 'MRI: NIfTI-1 (*.nii)', 'Nifti1'... 3498 }; 3499 case 'anatin' 3500 argout1 = {... 3501 {'.folder'}, 'FreeSurfer', 'FreeSurfer-fast'; ... 3502 {'.folder'}, 'FreeSurfer + Volume atlases', 'FreeSurfer'; ... 3503 {'.folder'}, 'FreeSurfer + Volume atlases + Thickness', 'FreeSurfer+Thick'; ... 3504 {'.folder'}, 'BrainSuite', 'BrainSuite-fast'; ... 3505 {'.folder'}, 'BrainSuite + Volume atlases', 'BrainSuite'; ... 3506 {'.folder'}, 'BrainVISA', 'BrainVISA'; ... 3507 {'.folder'}, 'CAT12', 'CAT12'; ... 3508 {'.folder'}, 'CAT12 + Thickness', 'CAT12+Thick'; ... 3509 {'.folder'}, 'CIVET', 'CIVET'; ... 3510 {'.folder'}, 'CIVET + Thickness', 'CIVET+Thick'; ... 3511 {'.folder'}, 'HCP MEG/anatomy (pipeline v3)', 'HCPv3'; ... 3512 {'.folder'}, 'SimNIBS', 'SimNIBS'; ... 3513 }; 3514 case 'source4d' 3515 argout1 = {... 3516 {'.folder'}, 'NIfTI-1 (*.nii)', 'Nifti1';... 3517 {'.folder'}, 'Analyze (*.img/*.hdr)', 'Analyze'; ... 3518 {'.folder'}, 'Matlab 4D matrix (*voltime*.mat)', 'BST'; ... 3519 }; 3520 3521 case 'surface' 3522 argout1 = {... 3523 {'.mesh'}, 'BrainVISA (*.mesh)', 'MESH'; ... 3524 {'_tess', '_head', '_scalp', '_brain', '_cortex', '_innerskull', '_outerskull'}, 'Brainstorm (*.mat)', 'BST'; ... 3525 {'.dfs'}, 'BrainSuite (*.dfs)', 'DFS'; ... 3526 {'.dsgl'}, 'BrainSuite old (*.dsgl)', 'DSGL'; ... 3527 {'.bd0','.bd1','.bd2','.bd3','.bd4','.bd5','.bd6','.bd7','.bd8','.bd9', ... 3528 '.s00','.s01','.s02','.s03','.s04','.s05','.s06','.s07','.s08','.s09'}, ... 3529 'Curry BEM (*.db*;*.s0*)', 'CURRY-BEM'; 3530 {'.vtk'}, 'FSL: VTK (*.vtk)', 'VTK'; ... 3531 {'*'}, 'FreeSurfer (*.*)', 'FS'; 3532 {'.off'}, 'Geomview OFF (*.off)', 'OFF'; ... 3533 {'.gii'}, 'GIfTI / MRI coordinates (*.gii)', 'GII'; ... 3534 {'.gii'}, 'GIfTI / MNI coordinates (*.gii)', 'GII-MNI'; ... 3535 {'.gii'}, 'GIfTI / World coordinates (*.gii)', 'GII-WORLD'; ... 3536 {'.fif'}, 'MNE (*.fif)', 'FIF'; ... 3537 {'.obj'}, 'MNI OBJ (*.obj)', 'MNIOBJ'; ... 3538 {'.msh'}, 'SimNIBS3/headreco Gmsh4 (*.msh)', 'SIMNIBS3'; ... 3539 {'.msh'}, 'SimNIBS4/charm Gmsh4 (*.msh)', 'SIMNIBS4'; ... 3540 {'.tri'}, 'TRI (*.tri)', 'TRI'; ... 3541 {'.mri', '.fif', '.img', '.ima', '.nii', '.mgh', '.mgz', '.mnc', '.mni', '.gz', '_subjectimage'}, 'Volume mask or atlas (subject space)', 'MRI-MASK'; ... 3542 {'.mri', '.fif', '.img', '.ima', '.nii', '.mgh', '.mgz', '.mnc', '.mni', '.gz'}, 'Volume mask or atlas (MNI space)', 'MRI-MASK-MNI'; ... 3543 {'.nwbaux'}, 'Neurodata Without Borders (*.nwbaux)', 'NWB'; ... 3544 {'*'}, 'All surface files (*.*)', 'ALL'; ... 3545 }; 3546 3547 case 'surfaceout' 3548 argout1 = {... 3549 {'.mesh'}, 'BrainVISA (*.mesh)', 'MESH'; ... 3550 {'.dfs'}, 'BrainSuite (*.dfs)', 'DFS'; ... 3551 {'.fs'}, 'FreeSurfer (*.fs)', 'FS'; ... 3552 {'.obj'}, 'Wavefront OBJ (*.obj)', 'OBJ'; ... 3553 {'.off'}, 'Geomview OFF (*.off)', 'OFF'; ... 3554 {'.gii'}, 'GIfTI (*.gii)', 'GII'; ... 3555 {'.tri'}, 'TRI (*.tri)', 'TRI'; ... 3556 }; 3557 3558 case 'data' 3559 argout1 = {... 3560 {'.*'}, 'MEG/EEG: 4D-Neuroimaging/BTi (*.*)', '4D'; ... 3561 {'.meg4','.res4'}, 'MEG/EEG: CTF (*.ds;*.meg4;*.res4)', 'CTF'; ... 3562 {'.fif'}, 'MEG/EEG: Elekta-Neuromag (*.fif)', 'FIF'; ... 3563 {'.mat'}, 'MEG/EEG: FieldTrip (*.mat)', 'FT-TIMELOCK'; ... 3564 {'.raw'}, 'MEG/EEG: ITAB (*.raw)', 'ITAB'; ... 3565 {'.kdf'}, 'MEG/EEG: KRISS MEG (*.kdf)', 'KDF'; ... 3566 {'.mrk','.sqd','.con','.raw','.ave'}, 'MEG/EEG: Ricoh (*.sqd;*.con;*.raw;*.ave;*.mrk)', 'RICOH'; ... 3567 {'.mat'}, 'MEG/EEG: SPM (*.mat/.dat)', 'SPM-DAT'; ... 3568 {'.mrk','.sqd','.con','.raw','.ave'}, 'MEG/EEG: Yokogawa/KIT (*.sqd;*.con;*.raw;*.ave;*.mrk)', 'KIT'; ... 3569 {'.meghdf5'}, 'MEG/EEG: York Instruments MEGSCAN (.meghdf5)', 'MEGSCAN-HDF5'; ... 3570 {'.bst'}, 'MEG/EEG: Brainstorm binary (*.bst)', 'BST-BIN'; ... 3571 {'.adicht'}, 'EEG: ADInstruments LabChart (*.adicht)', 'EEG-ADICHT'; ... 3572 {'.msr'}, 'EEG: ANT ASA (*.msr)', 'EEG-ANT-MSR'; ... 3573 {'.cnt','.avr'}, 'EEG: ANT EEProbe (*.cnt;*.avr)', 'EEG-ANT-CNT'; ... 3574 {'*'}, 'EEG: ASCII text (*.*)', 'EEG-ASCII'; ... 3575 {'.raw'}, 'EEG: Axion AxIS (*.raw)', 'EEG-AXION'; ... 3576 {'.dat'}, 'EEG: BCI2000 (*.dat)', 'EEG-BCI2000'; ... 3577 {'.bdf'}, 'EEG: BDF (*.bdf)', 'EEG-BDF'; ... 3578 {'.avr','.mux','.mul'}, 'EEG: BESA exports (*.avr;*.mul;*.mux)', 'EEG-BESA'; ... 3579 {'.acq'}, 'EEG: BIOPAC AcqKnowledge (*.acq)', 'EEG-BIOPAC'; ... 3580 {'.ns1','.ns2','.ns3','.ns4','.ns5','.ns6'}, 'EEG: Blackrock NeuroPort (*.nsX/*.nev)', 'EEG-BLACKROCK'; 3581 {'.eeg','.dat'}, 'EEG: BrainVision BrainAmp (*.eeg;*.dat)', 'EEG-BRAINAMP'; ... 3582 {'.txt'}, 'EEG: BrainVision Analyzer (*.txt)', 'EEG-BRAINVISION'; ... 3583 {'.sef','.ep','.eph'}, 'EEG: Cartool (*.sef;*.ep;*.eph)', 'EEG-CARTOOL'; ... 3584 {'.dat','.cdt'}, 'EEG: Curry (*.dat;*.cdt)', 'EEG-CURRY'; ... 3585 {'.smr','.son'}, 'EEG: CED Spike2 old 32bit (*.smr;*.son)', 'EEG-SMR'; ... 3586 {'.smr','.smrx'}, 'EEG: CED Spike2 new 64bit (*.smr;*.smrx)', 'EEG-SMRX'; ... 3587 {'.rda'}, 'EEG: Compumedics ProFusion Sleep (*.rda)', 'EEG-COMPUMEDICS-PFS'; ... 3588 {'.bin'}, 'EEG: Deltamed Coherence-Neurofile (*.bin)', 'EEG-DELTAMED'; ... 3589 {'.edf','.rec'}, 'EEG: EDF / EDF+ (*.rec;*.edf)', 'EEG-EDF'; ... 3590 {'.set'}, 'EEG: EEGLAB (*.set)', 'EEG-EEGLAB'; ... 3591 {'.raw'}, 'EEG: EGI Netstation RAW (*.raw)', 'EEG-EGI-RAW'; ... 3592 {'.mff','.bin'}, 'EEG: EGI-Philips (*.mff)', 'EEG-EGI-MFF'; ... 3593 {'.edf'}, 'EEG: EmotivPRO (*.edf)', 'EEG-EMOTIV'; ... 3594 {'.erp','.hdr'}, 'EEG: ERPCenter (*.hdr;*.erp)', 'EEG-ERPCENTER'; ... 3595 {'.erp'}, 'EEG: ERPLab (*.erp)', 'EEG-ERPLAB'; ... 3596 {'.mat','.hdf5'}, 'EEG: g.tec Matlab (*.mat,*.hdf5)', 'EEG-GTEC'; ... 3597 {'.rhd','.rhs'}, 'EEG: Intan (*.rhd,*.rhs)', 'EEG-INTAN'; ... 3598 {'.mb2'}, 'EEG: MANSCAN (*.mb2)', 'EEG-MANSCAN'; ... 3599 {'.trc'}, 'EEG: Micromed (*.trc)', 'EEG-MICROMED'; ... 3600 {'.mat'}, 'EEG: Matlab matrix (*.mat)', 'EEG-MAT'; ... 3601 {'.csv'}, 'EEG: Muse (*.csv)', 'EEG-MUSE-CSV'; ... 3602 {'.ncs'}, 'EEG: Neuralynx (*.ncs)', 'EEG-NEURALYNX'; ... 3603 {'.nwb'}, 'EEG: Neurodata Without Borders (*.nwb)','NWB'; ... 3604 {'.nedf','.easy'}, 'EEG: Neuroelectrics (*.nedf;*.easy)', 'EEG-NEUROELECTRICS'; ... 3605 {'.bin'}, 'EEG: NeurOne session folder', 'EEG-NEURONE'; ... 3606 {'.cnt','.avg','.eeg','.dat'}, 'EEG: Neuroscan (*.cnt;*.eeg;*.avg;*.dat)', 'EEG-NEUROSCAN'; ... 3607 {'.eeg','.dat'}, 'EEG: NeuroScope (*.eeg;*.dat)', 'EEG-NEUROSCOPE'; ... 3608 {'.e'}, 'EEG: Nicolet (*.e)', 'EEG-NICOLET'; ... 3609 {'.eeg'}, 'EEG: Nihon Kohden (*.eeg)', 'EEG-NK'; ... 3610 {'.dat'}, 'EEG: Open Ephys flat binary (*.dat)', 'EEG-OEBIN'; ... 3611 {'.plx','.pl2'}, 'EEG: Plexon (*.plx;*.pl2)', 'EEG-PLEXON'; ... 3612 {'.ns1','.ns2','.ns3','.ns4','.ns5','.ns6'}, 'EEG: Ripple Trellis (*.nsX/*.nev)', 'EEG-RIPPLE'; ... 3613 {'.h5'}, 'EEG: The Virtual Brain (*_TimeSeriesEEG.h5)', 'EEG-TVB'; ... 3614 {'.csv'}, 'EEG: Wearable Sensing (*.csv)', 'EEG-WS-CSV'; ... 3615 {'.xdf'}, 'EEG: XDF (*.xdf)', 'EEG-XDF'; ... 3616 {'.nirs'}, 'NIRS: Brainsight (*.nirs)', 'NIRS-BRS'; ... 3617 {'.bnirs','.jnirs','.snirf'}, 'NIRS: SNIRF (*.snirf)', 'NIRS-SNIRF'; ... 3618 {'.edf'}, 'Eye tracker: EyeLink (*.edf)', 'EYELINK'; ... 3619 {'.tsv'}, 'Eye tracker: Tobii glasses (*.tsv)', 'EYE-TOBII-TSV'; ... 3620 }; 3621 case 'raw' 3622 argout1 = {... 3623 {'.*'}, 'MEG/EEG: 4D-Neuroimaging/BTi (*.*)', '4D'; ... 3624 {'.meg4','.res4'}, 'MEG/EEG: CTF (*.ds;*.meg4;*.res4)', 'CTF'; ... 3625 {'.fif'}, 'MEG/EEG: Elekta-Neuromag (*.fif)', 'FIF'; ... 3626 {'.mat'}, 'MEG/EEG: FieldTrip (*.mat)', 'FT-TIMELOCK'; ... 3627 {'.raw'}, 'MEG/EEG: ITAB (*.raw)', 'ITAB'; ... 3628 {'.kdf'}, 'MEG/EEG: KRISS MEG (*.kdf)', 'KDF'; ... 3629 {'.mrk','.sqd','.con','.raw','.ave'}, 'MEG/EEG: Ricoh (*.sqd;*.con;*.raw;*.ave;*.mrk)', 'RICOH'; ... 3630 {'.mat'}, 'MEG/EEG: SPM (*.mat/.dat)', 'SPM-DAT'; ... 3631 {'.mrk','.sqd','.con','.raw','.ave'}, 'MEG/EEG: Yokogawa/KIT (*.sqd;*.con;*.raw;*.ave;*.mrk)', 'KIT'; ... 3632 {'.meghdf5'}, 'MEG/EEG: York Instruments MEGSCAN (.meghdf5)', 'MEGSCAN-HDF5'; ... 3633 {'.bst'}, 'MEG/EEG: Brainstorm binary (*.bst)', 'BST-BIN'; ... 3634 {'.adicht'}, 'EEG: ADInstruments LabChart (*.adicht)', 'EEG-ADICHT'; ... 3635 {'.msr'}, 'EEG: ANT ASA (*.msr)', 'EEG-ANT-MSR'; ... 3636 {'.cnt','.avr'}, 'EEG: ANT EEProbe (*.cnt;*.avr)', 'EEG-ANT-CNT'; ... 3637 {'*'}, 'EEG: ASCII text (*.*)', 'EEG-ASCII'; ... 3638 {'.raw'}, 'EEG: Axion AxIS (*.raw)', 'EEG-AXION'; ... 3639 {'.dat'}, 'EEG: BCI2000 (*.dat)', 'EEG-BCI2000'; ... 3640 {'.bdf'}, 'EEG: BDF (*.bdf)', 'EEG-BDF'; ... 3641 {'.avr','.mux','.mul'}, 'EEG: BESA exports (*.avr;*.mul;*.mux)', 'EEG-BESA'; ... 3642 {'.acq'}, 'EEG: BIOPAC AcqKnowledge (*.acq)', 'EEG-BIOPAC'; ... 3643 {'.ns1','.ns2','.ns3','.ns4','.ns5','.ns6'}, 'EEG: Blackrock NeuroPort (*.nsX/*.nev)', 'EEG-BLACKROCK'; 3644 {'.eeg','.dat'}, 'EEG: BrainVision BrainAmp (*.eeg;*.dat)', 'EEG-BRAINAMP'; ... 3645 {'.txt'}, 'EEG: BrainVision Analyzer (*.txt)', 'EEG-BRAINVISION'; ... 3646 {'.sef','.ep','.eph'}, 'EEG: Cartool (*.sef;*.ep;*.eph)', 'EEG-CARTOOL'; ... 3647 {'.smr','.son'}, 'EEG: CED Spike2 old 32bit (*.smr;*.son)', 'EEG-SMR'; ... 3648 {'.smr','.smrx'}, 'EEG: CED Spike2 new 64bit (*.smr;*.smrx)', 'EEG-SMRX'; ... 3649 {'.rda'}, 'EEG: Compumedics ProFusion Sleep (*.rda)', 'EEG-COMPUMEDICS-PFS'; ... 3650 {'.dat','.cdt'}, 'EEG: Curry (*.dat;*.cdt)', 'EEG-CURRY'; ... 3651 {'.bin'}, 'EEG: Deltamed Coherence-Neurofile (*.bin)', 'EEG-DELTAMED'; ... 3652 {'.edf','.rec'}, 'EEG: EDF / EDF+ (*.rec;*.edf)', 'EEG-EDF'; ... 3653 {'.set'}, 'EEG: EEGLAB (*.set)', 'EEG-EEGLAB'; ... 3654 {'.raw'}, 'EEG: EGI Netstation RAW (*.raw)', 'EEG-EGI-RAW'; ... 3655 {'.mff','.bin'}, 'EEG: EGI-Philips (*.mff)', 'EEG-EGI-MFF'; ... 3656 {'.edf'}, 'EEG: EmotivPRO (*.edf)', 'EEG-EMOTIV'; ... 3657 {'.mat','.hdf5'}, 'EEG: g.tec Matlab (*.mat,*.hdf5)', 'EEG-GTEC'; ... 3658 {'.rhd','.rhs'}, 'EEG: Intan (*.rhd,*.rhs)', 'EEG-INTAN'; ... 3659 {'.mb2'}, 'EEG: MANSCAN (*.mb2)', 'EEG-MANSCAN'; ... 3660 {'.mat'}, 'EEG: Matlab matrix (*.mat)', 'EEG-MAT'; ... 3661 {'.csv'}, 'EEG: Muse (*.csv)', 'EEG-MUSE-CSV'; ... 3662 {'.trc'}, 'EEG: Micromed (*.trc)', 'EEG-MICROMED'; ... 3663 {'.ncs'}, 'EEG: Neuralynx (*.ncs)', 'EEG-NEURALYNX'; ... 3664 {'.nwb'}, 'EEG: Neurodata Without Borders (*.nwb)','NWB'; ... 3665 {'.nedf','.easy'}, 'EEG: Neuroelectrics (*.nedf;*.easy)', 'EEG-NEUROELECTRICS'; ... 3666 {'.bin'}, 'EEG: NeurOne session folder', 'EEG-NEURONE'; ... 3667 {'.cnt','.avg','.eeg','.dat'}, 'EEG: Neuroscan (*.cnt;*.eeg;*.avg;*.dat)', 'EEG-NEUROSCAN'; ... 3668 {'.eeg','.dat'}, 'EEG: NeuroScope (*.eeg;*.dat)', 'EEG-NEUROSCOPE'; ... 3669 {'.e'}, 'EEG: Nicolet (*.e)', 'EEG-NICOLET'; ... 3670 {'.eeg'}, 'EEG: Nihon Kohden (*.eeg)', 'EEG-NK'; ... 3671 {'.dat'}, 'EEG: Open Ephys flat binary (*.dat)', 'EEG-OEBIN'; ... 3672 {'.plx','.pl2'}, 'EEG: Plexon (*.plx;.pl2)' 'EEG-PLEXON'; ... 3673 {'.ns1','.ns2','.ns3','.ns4','.ns5','.ns6'}, 'EEG: Ripple Trellis (*.nsX/*.nev)', 'EEG-RIPPLE'; ... 3674 {'.h5'}, 'EEG: The Virtual Brain (*_TimeSeriesEEG.h5)', 'EEG-TVB'; ... 3675 {'.tbk'}, 'EEG: Tucker Davis Technologies (*.tbk)', 'EEG-TDT'; ... 3676 {'.csv'}, 'EEG: Wearable Sensing (*.csv)', 'EEG-WS-CSV'; ... 3677 {'.xdf'}, 'EEG: XDF (*.xdf)', 'EEG-XDF'; ... 3678 {'.trc','.eeg','.e','.bin','.rda','.edf','.bdf'}, 'SEEG: Deltamed/Micromed/NK/Nicolet/BrainVision/EDF', 'SEEG-ALL'; ... 3679 {'.trc','.eeg','.e','.bin','.rda','.edf','.bdf'}, 'ECOG: Deltamed/Micromed/NK/Nicolet/BrainVision/EDF', 'ECOG-ALL'; ... 3680 {'.nirs'}, 'NIRS: Brainsight (*.nirs)', 'NIRS-BRS'; ... 3681 {'.bnirs','.jnirs','.snirf'}, 'NIRS: SNIRF (*.snirf)', 'NIRS-SNIRF'; ... 3682 {'.edf'}, 'Eye tracker: EyeLink (*.edf)', 'EYELINK'; ... 3683 {'.tsv'}, 'Eye tracker: Tobii glasses (*.tsv)', 'EYE-TOBII-TSV'; ... 3684 }; 3685 3686 case 'dataout' 3687 argout1 = {... 3688 {'.bst'}, 'MEG/EEG: Brainstorm binary (*.bst)', 'BST-BIN'; ... 3689 {'.mat'}, 'MEG/EEG: FieldTrip timelock (*.mat)', 'FT-TIMELOCK'; ... 3690 {'.mat'}, 'MEG/EEG: SPM (*.mat/.dat)', 'SPM-DAT'; ... 3691 {'.eeg'}, 'EEG: BrainVision BrainAmp (*.eeg)', 'EEG-BRAINAMP'; ... 3692 {'.eph'}, 'EEG: Cartool EPH (*.eph)', 'EEG-CARTOOL-EPH'; ... 3693 {'.edf'}, 'EEG: EDF+ (*.edf)', 'EEG-EDF'; ... 3694 {'.raw'}, 'EEG: EGI NetStation RAW (*.raw)', 'EEG-EGI-RAW'; ... 3695 {'.snirf'}, 'NIRS: SNIRF (*.snirf)', 'NIRS-SNIRF'; ... 3696 {'.txt'}, 'ASCII: Space-separated, fixed column size (*.txt)', 'ASCII-SPC'; ... 3697 {'.txt'}, 'ASCII: Space-separated with header, fixed column size (*.txt)', 'ASCII-SPC-HDR'; ... 3698 {'.tsv'}, 'ASCII: Tab-separated (*.tsv)', 'ASCII-TSV'; ... 3699 {'.tsv'}, 'ASCII: Tab-separated with header (*.tsv)', 'ASCII-TSV-HDR'; ... 3700 {'.tsv'}, 'ASCII: Tab-separated with header transposed (*.tsv)', 'ASCII-TSV-HDR-TR'; ... 3701 {'.csv'}, 'ASCII: Comma-separated (*.csv)', 'ASCII-CSV'; ... 3702 {'.csv'}, 'ASCII: Comma-separated with header (*.csv)', 'ASCII-CSV-HDR'; ... 3703 {'.csv'}, 'ASCII: Comma-separated with header transposed (*.csv)', 'ASCII-CSV-HDR-TR'; ... 3704 {'.xlsx'}, 'Microsoft Excel (*.xlsx)', 'EXCEL'; ... 3705 {'.xlsx'}, 'Microsoft Excel transposed (*.xlsx)', 'EXCEL-TR'; ... 3706 {'_timeseries'}, 'Brainstorm matrix (*timeseries*.mat)', 'BST'; ... 3707 }; 3708 case 'rawout' 3709 argout1 = {... 3710 {'.bst'}, 'MEG/EEG: Brainstorm binary (*.bst)', 'BST-BIN'; ... 3711 {'.mat'}, 'MEG/EEG: SPM (*.mat/.dat)', 'SPM-DAT'; ... 3712 {'.eeg'}, 'EEG: BrainVision BrainAmp (*.eeg)', 'EEG-BRAINAMP'; ... 3713 {'.edf'}, 'EEG: EDF+ (*.edf)', 'EEG-EDF'; ... 3714 {'.raw'}, 'EEG: EGI NetStation RAW (*.raw)', 'EEG-EGI-RAW'; ... 3715 {'.snirf'}, 'NIRS: SNIRF (*.snirf)', 'NIRS-SNIRF'; ... 3716 }; 3717 case 'events' 3718 argout1 = {... 3719 {'.trg'}, 'ANT EEProbe (*.trg)', 'ANT'; ... 3720 {'.mrk'}, 'AnyWave (*.mrk)', 'ANYWAVE'; ... 3721 {'.evt'}, 'BESA (*.evt)', 'BESA'; ... 3722 {'.tsv'}, 'BIDS events: onset, duration, trial_type, channel (*.tsv)', 'BIDS'; ... 3723 {'.vmrk'}, 'BrainVision BrainAmp (*.vmrk)', 'BRAINAMP'; ... 3724 {'_events'}, 'Brainstorm (events*.mat)', 'BST'; ... 3725 {'.mrk'}, 'Cartool (*.mrk)', 'CARTOOL'; ... 3726 {'.mrk'}, 'CTF MarkerFile (*.mrk)', 'CTF'; ... 3727 {'.cef'}, 'Curry (*.cef)', 'CURRY'; ... 3728 {'.eve','.fif'}, 'Elekta-Neuromag MNE (*.eve;*.fif)', 'FIF'; ... 3729 {'.evl','.txt'}, 'Elekta-Neuromag Graph (*.evl;*.txt)', 'GRAPH'; ... 3730 {'.txt','.mat'}, 'FieldTrip trial definition (*.txt;*.mat)', 'TRL'; ... 3731 {'.trg'}, 'KRISS MEG (*.trg)', 'KDF'; ... 3732 {'.evt'}, 'Micromed (*.evt)', 'MICROMED'; ... 3733 {'.ev2'}, 'Neuroscan (*.ev2)', 'NEUROSCAN'; ... 3734 {'.txt'}, 'Nicolet export (*.txt)', 'NICOLET'; ... 3735 {'timestamps.npy'},'Open Ephys (timestamps.npy)', 'OEBIN'; ... 3736 {'.log'}, 'Presentation (*.log)', 'PRESENTATION'; ... 3737 {'.mrk','.sqd','.con','.raw','.ave'}, 'Ricoh (*.mrk;*.sqd;*.con;*.raw;*.ave)', 'RICOH'; ... 3738 {'.txt'}, 'XLTEK export (*.txt)', 'XLTEK'; ... 3739 {'.mrk','.sqd','.con','.raw','.ave'}, 'Yokogawa/KIT (*.mrk;*.sqd;*.con;*.raw;*.ave)', 'KIT'; ... 3740 {'.*'}, 'Array of times (*.mat;*.*)', 'ARRAY-TIMES'; ... 3741 {'.*'}, 'Array of samples (*.mat;*.*)', 'ARRAY-SAMPLES'; ... 3742 {'.txt','.csv'}, 'CSV text file: label, time, duration (*.txt;*.csv)', 'CSV-TIME'; ... 3743 {'.*'}, 'CTF Video Times (.txt)', 'CTFVIDEO'; ... 3744 }; 3745 case 'eventsout' 3746 argout1 = {... 3747 {'.mrk'}, 'AnyWave (*.mrk)', 'ANYWAVE'; ... 3748 {'_events'}, 'Brainstorm (events*.mat)', 'BST'; ... 3749 {'.vmrk'}, 'BrainVision BrainAmp (*.vmrk)', 'BRAINAMP'; ... 3750 {'.mrk'}, 'CTF MarkerFile (*.mrk)', 'CTF'; ... 3751 {'.eve','.fif'}, 'Elekta-Neuromag/MNE (*.eve)', 'FIF'; ... 3752 {'.evl'}, 'Elekta-Neuromag Graph (Alternative Style) (*.evl)', 'GRAPH_ALT'; ... 3753 {'.txt'}, 'Array of times (*.txt)', 'ARRAY-TIMES'; ... 3754 {'.txt'}, 'Array of samples (*.txt)', 'ARRAY-SAMPLES'; ... 3755 {'.txt','.csv'}, 'CSV text file: label, time, duration (*.txt;*.csv)', 'CSV-TIME'; ... 3756 {'.txt'}, 'CTF Video Times (*.txt)', 'CTFVIDEO'; ... 3757 {'.tsv'}, 'BIDS events: onset, duration, trial_type (*.tsv)', 'BIDS'; ... 3758 }; 3759 case 'channel' 3760 argout1 = {... 3761 {'.*'}, 'MEG/EEG: 4D-Neuroimaging/BTi (*.*)', '4D'; ... 3762 {'.meg4','.res4'}, 'MEG/EEG: CTF (*.ds;*.meg4;*.res4)', 'CTF' ; ... 3763 {'.fif'}, 'MEG/EEG: Elekta-Neuromag (*.fif)', 'FIF'; ... 3764 {'.kdf'}, 'MEG/EEG: KRISS MEG (*.kdf)', 'KDF'; ... 3765 {'.raw'}, 'MEG/EEG: ITAB (*.raw)', 'ITAB'; ... 3766 {'.mrk','.sqd','.con','.raw','.ave'}, 'MEG/EEG: Ricoh (*.sqd;*.con;*.raw;*.ave;*.mrk)', 'RICOH'; ... 3767 {'.mrk','.sqd','.con','.raw','.ave'}, 'MEG/EEG: Yokogawa/KIT (*.sqd;*.con;*.raw;*.ave;*.mrk)', 'KIT'; ... 3768 {'.meghdf5'}, 'MEG/EEG: York Instruments MEGSCAN (.meghdf5)', 'MEGSCAN-HDF5'; ... 3769 {'.bst'}, 'MEG/EEG: Brainstorm binary (*.bst)', 'BST-BIN'; ... 3770 {'_channel'}, 'MEG/EEG: Brainstorm (channel*.mat)', 'BST'; ... 3771 {'.elc'}, 'EEG: ANT ASA/Xensor (*.elc)', 'XENSOR'; ... 3772 {'.sfp','.elp','.ela','.eps'}, 'EEG: BESA (*.sfp;*.elp;*.eps/*.ela)', 'BESA'; ... 3773 {'.bvef','.bvct','.txt'}, 'EEG: BrainVision electrode file (*.bvef,*.bvct,*.txt)', 'BRAINVISION'; ... 3774 {'.tsv'}, 'EEG: BIDS electrodes.tsv, subject space mm (*.tsv)', 'BIDS-SCANRAS-MM'; ... 3775 {'.tsv'}, 'EEG: BIDS electrodes.tsv, MNI space mm (*.tsv)', 'BIDS-MNI-MM'; ... 3776 {'.tsv'}, 'EEG: BIDS electrodes.tsv, ACPC space mm (*.tsv)', 'BIDS-ACPC-MM'; ... 3777 {'.tsv'}, 'EEG: BIDS electrodes.tsv, ALS/SCS/CTF space mm (*.tsv)','BIDS-ALS-MM'; ... 3778 {'.tsv'}, 'EEG: BIDS electrodes.tsv, CapTrak space mm (*.tsv)', 'BIDS-CAPTRAK-MM'; ... 3779 {'.els','.xyz'}, 'EEG: Cartool (*.els;*.xyz)', 'CARTOOL'; ... 3780 {'.eeg'}, 'EEG: MegDraw (*.eeg)', 'MEGDRAW'; ... 3781 {'.res','.rs3','.pom'}, 'EEG: Curry (*.res;*.rs3;*.pom)', 'CURRY'; ... 3782 {'.ced','.xyz','.set'}, 'EEG: EEGLAB (*.ced;*.xyz;*.set)', 'EEGLAB'; ... 3783 {'.elc'}, 'EEG: EETrak (*.elc)', 'EETRAK'; ... 3784 {'.sfp'}, 'EEG: EGI (*.sfp)', 'EGI'; ... 3785 {'coordinates.xml'}, 'EEG: EGI-Philips (coordinates.xml)', 'MFF'; ... 3786 {'.elp'}, 'EEG: EMSE (*.elp)', 'EMSE'; ... 3787 {'.pts','.csv'}, 'EEG: IntrAnat, subject space (*.pts;*.csv)', 'INTRANAT'; ... 3788 {'.pts','.csv'}, 'EEG: IntrAnat, MNI space (*.pts;*.csv)', 'INTRANAT_MNI'; ... 3789 {'.csv'}, 'EEG: Localite (*.csv)', 'LOCALITE'; ... 3790 {'.dat','.tri','.txt','.asc'}, 'EEG: Neuroscan (*.dat;*.tri;*.txt;*.asc)', 'NEUROSCAN'; ... 3791 {'.pos','.pol','.elp','.txt'}, 'EEG: Polhemus (*.pos;*.pol;*.elp;*.txt)', 'POLHEMUS'; ... 3792 {'.csv'}, 'EEG: SimNIBS (*.csv)', 'SIMNIBS'; ... 3793 {'.h5'}, 'EEG: The Virtual Brain (*_SensorsEEG.h5)', 'TVB'; ... 3794 {'*'}, 'EEG: ASCII: Name,XYZ (*.*)', 'ASCII_NXYZ'; ... 3795 {'*'}, 'EEG: ASCII: Name,XYZ_MNI (*.*)', 'ASCII_NXYZ_MNI'; ... 3796 {'*'}, 'EEG: ASCII: Name,XYZ_World (*.*)', 'ASCII_NXYZ_WORLD'; ... 3797 {'*'}, 'EEG: ASCII: Name,XY (*.*)', 'ASCII_NXY'; ... 3798 {'*'}, 'EEG: ASCII: XYZ (*.*)', 'ASCII_XYZ'; ... 3799 {'*'}, 'EEG: ASCII: XYZ_MNI (*.*)', 'ASCII_XYZ_MNI'; ... 3800 {'*'}, 'EEG: ASCII: XYZ_World (*.*)', 'ASCII_XYZ_WORLD'; ... 3801 {'*'}, 'EEG: ASCII: XY (*.*)', 'ASCII_XY'; ... 3802 {'*'}, 'EEG: ASCII: XYZ,Name (*.*)', 'ASCII_XYZN'; ... 3803 {'*'}, 'EEG: ASCII: XYZ_MNI,Name (*.*)', 'ASCII_XYZN_MNI'; ... 3804 {'*'}, 'EEG: ASCII: XYZ_World,Name (*.*)', 'ASCII_XYZN_WORLD'; ... 3805 {'*'}, 'EEG: ASCII: Name,Theta,Phi (*.*)', 'ASCII_NTP'; ... 3806 {'*'}, 'EEG: ASCII: Theta,Phi (*.*)', 'ASCII_TP'; ... 3807 }; 3808 case 'channelout' 3809 argout1 = {... 3810 {'.pos'}, 'EEG+Headshape: Polhemus (*.pos)', 'POLHEMUS'; ... 3811 {'.eeg'}, 'Headshape: MegDraw (*.eeg)', 'MEGDRAW'; ... 3812 {'.pos'}, 'Headshape: Polhemus (*.pos)', 'POLHEMUS-HS'; ... 3813 {'.txt'}, 'Headshape: ASCII: XYZ (*.txt)', 'ASCII_XYZ-HS'; ... 3814 {'.txt'}, 'Headshape: ASCII: XYZ_World (*.txt)', 'ASCII_XYZ_WORLD-HS'; ... 3815 {'.txt'}, 'Headshape: ASCII: Name,XYZ (*.txt)', 'ASCII_NXYZ-HS'; ... 3816 {'.txt'}, 'Headshape: ASCII: Name,XYZ_World (*.txt)', 'ASCII_NXYZ_WORLD-HS'; ... 3817 {'.txt'}, 'Headshape: ASCII: XYZ,Name (*.txt)', 'ASCII_XYZN-HS'; ... 3818 {'.txt'}, 'Headshape: ASCII: XYZ_World,Name (*.txt)', 'ASCII_XYZN_WORLD-HS'; ... 3819 {'.sfp'}, 'EEG: BESA (*.sfp)', 'BESA-SFP'; ... 3820 {'.elp'}, 'EEG: BESA (*.elp)', 'BESA-ELP'; ... 3821 {'.tsv'}, 'EEG: BIDS electrodes.tsv, subject space mm (*.tsv)', 'BIDS-SCANRAS-MM'; ... 3822 {'.tsv'}, 'EEG: BIDS electrodes.tsv, MNI space mm (*.tsv)', 'BIDS-MNI-MM'; ... 3823 {'.tsv'}, 'EEG: BIDS electrodes.tsv, ALS/SCS/CTF space mm (*.tsv)', 'BIDS-ALS-MM'; ... 3824 {'.xyz'}, 'EEG: Cartool (*.xyz)', 'CARTOOL-XYZ'; ... 3825 {'.res'}, 'EEG: Curry (*.res)', 'CURRY-RES'; ... 3826 {'.xyz'}, 'EEG: EEGLAB (*.xyz)', 'EEGLAB-XYZ'; ... 3827 {'.sfp'}, 'EEG: EGI (*.sfp)', 'EGI'; ... 3828 {'.txt'}, 'EEG/NIRS: ASCII: XYZ (*.txt)', 'ASCII_XYZ-EEG'; ... 3829 {'.txt'}, 'EEG/NIRS: ASCII: XYZ_MNI (*.txt)', 'ASCII_XYZ_MNI-EEG'; ... 3830 {'.txt'}, 'EEG/NIRS: ASCII: XYZ_World (*.txt)', 'ASCII_XYZ_WORLD-EEG'; ... 3831 {'.txt'}, 'EEG/NIRS: ASCII: Name,XYZ (*.txt)', 'ASCII_NXYZ-EEG'; ... 3832 {'.txt'}, 'EEG/NIRS: ASCII: Name,XYZ_MNI (*.txt)', 'ASCII_NXYZ_MNI-EEG'; ... 3833 {'.txt'}, 'EEG/NIRS: ASCII: Name,XYZ_World (*.txt)', 'ASCII_NXYZ_WORLD-EEG'; ... 3834 {'.txt'}, 'EEG/NIRS: ASCII: XYZ,Name (*.txt)', 'ASCII_XYZN-EEG'; ... 3835 {'.txt'}, 'EEG/NIRS: ASCII: XYZ_MNI,Name (*.txt)', 'ASCII_XYZN_MNI-EEG'; ... 3836 {'.txt'}, 'EEG/NIRS: ASCII: XYZ_World,Name (*.txt)', 'ASCII_XYZN_WORLD-EEG'; ... 3837 {'.txt'}, 'EEG/NIRS: Brainsight (*.txt)', 'BRAINSIGHT-TXT'; ... 3838 {'.tsv'}, 'NIRS: BIDS optrodes.tsv, subject space mm (*.tsv)', 'BIDS-NIRS-SCANRAS-MM'; ... 3839 {'.tsv'}, 'NIRS: BIDS optrodes.tsv, MNI space mm (*.tsv)', 'BIDS-NIRS-MNI-MM'; ... 3840 {'.tsv'}, 'NIRS: BIDS optrodes.tsv, ALS/SCS/CTF space mm (*.tsv)', 'BIDS-NIRS-ALS-MM'; ... 3841 }; 3842 case 'labelin' 3843 argout1 = {... 3844 {'.dfs'}, 'BrainSuite atlas (*.dfs)', 'DFS'; ... 3845 {'.annot'}, 'FreeSurfer atlas (*.annot)', 'FS-ANNOT'; ... 3846 {'.label'}, 'FreeSurfer ROI, single scout (*.label)', 'FS-LABEL-SINGLE'; ... 3847 {'.label'}, 'FreeSurfer ROI, probability map (*.label)', 'FS-LABEL'; ... 3848 {'.gii'}, 'GIfTI texture (*.gii)', 'GII-TEX'; ... 3849 {'.dset'}, 'SUMA atlas (*.dset)', 'DSET'; ... 3850 {'_scout'}, 'Brainstorm scouts (*scout*.mat)', 'BST'; ... 3851 {'.mri', '.fif', '.img', '.ima', '.nii', '.mgh', '.mgz', '.mnc', '.mni', '.gz', '_subjectimage'}, 'Volume mask or atlas (dilated, subject space)', 'MRI-MASK'; ... 3852 {'.mri', '.fif', '.img', '.ima', '.nii', '.mgh', '.mgz', '.mnc', '.mni', '.gz'}, 'Volume mask or atlas (dilated, MNI space)', 'MRI-MASK-MNI'; ... 3853 {'.mri', '.fif', '.img', '.ima', '.nii', '.mgh', '.mgz', '.mnc', '.mni', '.gz', '_subjectimage'}, 'Volume mask or atlas (no overlap, subject space)', 'MRI-MASK-NOOVERLAP'; ... 3854 {'.mri', '.fif', '.img', '.ima', '.nii', '.mgh', '.mgz', '.mnc', '.mni', '.gz'}, 'Volume mask or atlas (no overlap, MNI space)', 'MRI-MASK-NOOVERLAP-MNI'; ... 3855 }; 3856 case 'resultsout' 3857 argout1 = {... 3858 {'_sources'}, 'Brainstorm sources (*sources*.mat)', 'BST'; ... 3859 {'.mat'}, 'FieldTrip sources (*.mat)', 'FT-SOURCES'; ... 3860 {'.txt'}, 'ASCII: Space-separated, fixed columns size (*.txt)', 'ASCII-SPC'; ... 3861 {'.txt'}, 'ASCII: Space-separated with header, fixed column size (*.txt)', 'ASCII-SPC-HDR'; ... 3862 {'.tsv'}, 'ASCII: Tab-separated (*.tsv)', 'ASCII-TSV'; ... 3863 {'.tsv'}, 'ASCII: Tab-separated with header (*.tsv)', 'ASCII-TSV-HDR'; ... 3864 {'.tsv'}, 'ASCII: Tab-separated with header transposed (*.tsv)', 'ASCII-TSV-HDR-TR'; ... 3865 {'.csv'}, 'ASCII: Comma-separated (*.csv)', 'ASCII-CSV'; ... 3866 {'.csv'}, 'ASCII: Comma-separated with header (*.csv)', 'ASCII-CSV-HDR'; ... 3867 {'.csv'}, 'ASCII: Comma-separated with header transposed (*.csv)', 'ASCII-CSV-HDR-TR'; ... 3868 {'.xlsx'}, 'Microsoft Excel (*.xlsx)', 'EXCEL'; ... 3869 {'.xlsx'}, 'Microsoft Excel transposed (*.xlsx)', 'EXCEL-TR'; ... 3870 }; 3871 case 'timefreqout' 3872 argout1 = {... 3873 {'_timefreq'}, 'Brainstorm structure (*timefreq*.mat)', 'BST'; ... 3874 {'.mat'}, 'FieldTrip freq (*.mat)', 'FT-FREQ'; ... 3875 {'.txt'}, 'ASCII: Space-separated, fixed columns size (*.txt)', 'ASCII-SPC'; ... 3876 {'.txt'}, 'ASCII: Space-separated with header, fixed column size (*.txt)', 'ASCII-SPC-HDR'; ... 3877 {'.tsv'}, 'ASCII: Tab-separated (*.tsv)', 'ASCII-TSV'; ... 3878 {'.tsv'}, 'ASCII: Tab-separated with header (*.tsv)', 'ASCII-TSV-HDR'; ... 3879 {'.tsv'}, 'ASCII: Tab-separated with header transposed (*.tsv)', 'ASCII-TSV-HDR-TR'; ... 3880 {'.csv'}, 'ASCII: Comma-separated (*.csv)', 'ASCII-CSV'; ... 3881 {'.csv'}, 'ASCII: Comma-separated with header (*.csv)', 'ASCII-CSV-HDR'; ... 3882 {'.csv'}, 'ASCII: Comma-separated with header transposed (*.csv)', 'ASCII-CSV-HDR-TR'; ... 3883 {'.xlsx'}, 'Microsoft Excel (*.xlsx)', 'EXCEL'; ... 3884 {'.xlsx'}, 'Microsoft Excel transposed (*.xlsx)', 'EXCEL-TR'; ... 3885 }; 3886 case 'matrixout' 3887 argout1 = {... 3888 {'_matrix'}, 'Brainstorm structure (*matrix*.mat)', 'BST'; ... 3889 {'.bst'}, 'MEG/EEG: Brainstorm binary (*.bst)', 'BST-BIN'; ... 3890 {'.mat'}, 'FieldTrip timelock (*.mat)', 'FT-TIMELOCK'; ... 3891 {'.edf'}, 'EEG: EDF+ (*.edf)', 'EEG-EDF'; ... 3892 {'.txt'}, 'ASCII: Space-separated, fixed columns size (*.txt)', 'ASCII-SPC'; ... 3893 {'.txt'}, 'ASCII: Space-separated with header, fixed column size (*.txt)', 'ASCII-SPC-HDR'; ... 3894 {'.tsv'}, 'ASCII: Tab-separated (*.tsv)', 'ASCII-TSV'; ... 3895 {'.tsv'}, 'ASCII: Tab-separated with header (*.tsv)', 'ASCII-TSV-HDR'; ... 3896 {'.tsv'}, 'ASCII: Tab-separated with header transposed (*.tsv)', 'ASCII-TSV-HDR-TR'; ... 3897 {'.csv'}, 'ASCII: Comma-separated (*.csv)', 'ASCII-CSV'; ... 3898 {'.csv'}, 'ASCII: Comma-separated with header (*.csv)', 'ASCII-CSV-HDR'; ... 3899 {'.csv'}, 'ASCII: Comma-separated with header transposed (*.csv)', 'ASCII-CSV-HDR-TR'; ... 3900 {'.xlsx'}, 'Microsoft Excel (*.xlsx)', 'EXCEL'; ... 3901 {'.xlsx'}, 'Microsoft Excel transposed (*.xlsx)', 'EXCEL-TR'; ... 3902 }; 3903 case 'montagein' 3904 argout1 = {... 3905 {'.sel'}, 'MNE selection files (*.sel)', 'MNE'; ... 3906 {'.mon'}, 'Text montage files (*.mon)', 'MON'; ... 3907 {'_montage'}, 'Brainstorm montage files (montage_*.mat)', 'BST'; 3908 {'.csv'}, 'Comma-separated montage files (*.csv)', 'CSV'}; 3909 case 'montageout' 3910 argout1 = {... 3911 {'.sel'}, 'MNE selection files (*.sel)', 'MNE'; ... 3912 {'.mon'}, 'Text montage files (*.mon)', 'MON'; ... 3913 {'_montage'}, 'Brainstorm montage files (montage_*.mat)', 'BST'}; 3914 case 'clusterin' 3915 argout1 = {... 3916 {'_cluster'}, 'Brainstorm clusters file (*cluster*.mat)', 'BST'; ... 3917 {'.sel'}, 'MNE selection files (*.sel)', 'MNE'}; 3918 case 'fibers' 3919 argout1 = {... 3920 {'.trk'}, 'TrackVis (*.trk)', 'TRK'; ... 3921 {'_fibers'}, 'Brainstorm fibers files (fibers_*.mat)', 'BST'}; 3922 end 3923 3924 3925 %% ===== FONTS ===== 3926 case 'FigFont' 3927 if ispc 3928 argout1 = 8; 3929 else 3930 argout1 = 9; 3931 end 3932 InterfaceScaling = bst_get('InterfaceScaling'); 3933 if (InterfaceScaling ~= 100) 3934 argout1 = argout1 * InterfaceScaling / 100; 3935 end 3936 3937 case 'Font' 3938 % Default font size 3939 if (nargin < 2) 3940 if strncmp(computer,'MAC',3) 3941 fontSize = 12; 3942 else 3943 fontSize = 11; 3944 end 3945 % Font size in input 3946 else 3947 fontSize = varargin{2}; 3948 end 3949 % Adjust for interface scaling 3950 fontSize = fontSize * bst_get('InterfaceScaling') / 100; 3951 3952 % Font types 3953 fontTypes = {}; 3954 if (nargin >= 3) 3955 if ischar(varargin{3}) 3956 fontTypes = varargin(3); 3957 else 3958 fontTypes = varargin{3}; 3959 end 3960 else 3961 fontTypes{end + 1} = 'Arial'; % Default font 3962 fontTypes{end + 1} = 'Liberation Sans'; % Free Arial substitute 3963 end 3964 % Check for cached font 3965 foundFont = 0; 3966 for iFont = 1 : length(fontTypes) 3967 strCache = strrep(sprintf('%s%d', fontTypes{iFont}, round(fontSize*100)), ' ', '_'); 3968 if ~isempty(GlobalData) && isfield(GlobalData, 'Program') && isfield(GlobalData.Program, 'FontCache') && isfield(GlobalData.Program.FontCache, strCache) 3969 argout1 = GlobalData.Program.FontCache.(strCache); 3970 foundFont = 1; 3971 break; 3972 end 3973 end 3974 3975 % If font not cached, find first supported font 3976 if ~foundFont 3977 ge = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(); 3978 allFonts = cell(ge.getAvailableFontFamilyNames()); 3979 3980 for iFont = 1 : length(fontTypes) 3981 if any(strcmp(fontTypes{iFont}, allFonts)) 3982 fontType = fontTypes{iFont}; 3983 foundFont = 1; 3984 break; 3985 end 3986 end 3987 3988 if ~foundFont 3989 fontType = 'SansSerif'; % If nothing else works. 3990 end 3991 3992 strCache = strrep(sprintf('%s%d', fontType, round(fontSize*100)), ' ', '_'); 3993 argout1 = java.awt.Font(fontType, java.awt.Font.PLAIN, fontSize); 3994 GlobalData.Program.FontCache.(strCache) = argout1; 3995 end 3996 3997 %% ==== PANEL CONTAINERS ==== 3998 case 'PanelContainer' 3999 % Get Brainstorm GUI context structure 4000 bst_GUI = GlobalData.Program.GUI; 4001 if (isempty(bst_GUI) || ~isfield(bst_GUI, 'panelContainers')) 4002 error('Brainstorm GUI is not yet initialized'); 4003 end 4004 4005 % Get ContainerName in argument 4006 if ((nargin >= 2) && (ischar(varargin{2}))) 4007 ContainerName = varargin{2}; 4008 % If no container name in argument : just display all the container names 4009 else 4010 disp('Registered panel containers :'); 4011 for iContainer = 1:length(bst_GUI.panelContainers) 4012 disp([' - ' bst_GUI.panelContainers(iContainer).name]); 4013 end 4014 return 4015 end 4016 4017 % Look for containerName in all the registered panel containers 4018 iContainer = 1; 4019 found = 0; 4020 while (~found (iContainer <= length(bst_GUI.panelContainers))) 4021 if (strcmpi(ContainerName, bst_GUI.panelContainers(iContainer).name)) 4022 found = 1; 4023 else 4024 iContainer = iContainer + 1; 4025 end 4026 end 4027 % If container is found : return it 4028 if (found) 4029 argout1 = bst_GUI.panelContainers(iContainer).jHandle; 4030 else 4031 % warning('Brainstorm:InvalidContainer', 'Container ''%s'' could not be found.', ContainerName); 4032 end 4033 4034 4035 %% ==== PANELS ==== 4036 case 'Panel' 4037 % Get Brainstorm GUI context structure 4038 if (isempty(GlobalData) || isempty(GlobalData.Program.GUI) || ~isfield(GlobalData.Program.GUI, 'panels')) 4039 return 4040 end 4041 listPanels = GlobalData.Program.GUI.panels; 4042 % Get Panel in argument 4043 if ((nargin >= 2) && (ischar(varargin{2}))) 4044 PanelName = varargin{2}; 4045 % If no panel name in argument : just display all the panels names 4046 else 4047 disp('Registered panels :'); 4048 for iContainer = 1:length(listPanels) 4049 disp([' - ' get(listPanels(iContainer), 'name')]); 4050 end 4051 return 4052 end 4053 % Look for panelName in all the registered panels 4054 iPanel = find(strcmpi(PanelName, get(listPanels, 'name')), 1); 4055 if ~isempty(iPanel) 4056 argout1 = listPanels(iPanel); 4057 argout2 = iPanel; 4058 end 4059 4060 4061 %% ==== PANEL CONTROLS ==== 4062 % Calls : bst_get('PanelControls', PanelName) 4063 case 'PanelControls' 4064 % Get Panel name in argument 4065 if ((nargin >= 2) && (ischar(varargin{2}))) 4066 PanelName = varargin{2}; 4067 else 4068 error('Invalid call to bst_get()'); 4069 end 4070 % Find BstPanel with this name 4071 bstPanel = bst_get('Panel', PanelName); 4072 % If panel was found : return its controls 4073 if ~isempty(bstPanel) 4074 argout1 = get(bstPanel, 'sControls'); 4075 end 4076 4077 %% ===== NODES COPY ===== 4078 % Calls : bst_get('Clipboard') 4079 case 'Clipboard' 4080 argout1 = GlobalData.Program.Clipboard.Nodes; 4081 argout2 = GlobalData.Program.Clipboard.isCut; 4082 4083 %% ==== DIRECTORIES ==== 4084 case 'DirDefaultSubject' 4085 argout1 = '@default_subject'; 4086 case 'DirDefaultStudy' 4087 argout1 = '@default_study'; 4088 case 'DirAnalysisIntra' 4089 argout1 = '@intra'; 4090 case 'DirAnalysisInter' 4091 argout1 = '@inter'; 4092 case 'NormalizedSubjectName' 4093 argout1 = 'Group_analysis'; 4094 4095 %% ==== OTHER ==== 4096 case 'ResizeFunction' 4097 if (bst_get('MatlabVersion') <= 803) 4098 argout1 = 'ResizeFcn'; 4099 else 4100 argout1 = 'SizeChangedFcn'; 4101 end 4102 case 'groot' 4103 if (bst_get('MatlabVersion') <= 803) 4104 argout1 = 0; 4105 else 4106 argout1 = groot; 4107 end 4108 case 'JFrame' 4109 hFig = varargin{2}; 4110 MatlabVersion = bst_get('MatlabVersion'); 4111 jFrame = []; 4112 try 4113 if (MatlabVersion <= 705) 4114 jf = get(hFig, 'javaframe'); 4115 jFrame = jf.fFigureClient.getWindow(); 4116 elseif (MatlabVersion <= 712) 4117 jf = get(handle(hFig), 'javaframe'); 4118 jFrame = jf.fFigureClient.getWindow(); 4119 elseif (MatlabVersion <= 803) 4120 jf = get(handle(hFig), 'javaframe'); 4121 jFrame = jf.fHG1Client.getWindow(); 4122 elseif (MatlabVersion < 907) % Matlab >= 2019b deprecated the JavaFrame property 4123 warning('off', 'MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); 4124 jf = get(hFig, 'javaframe'); 4125 warning('on', 'MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); 4126 jFrame = jf.fHG2Client.getWindow(); 4127 else 4128 disp('BST> Error: Matlab 2019b deprecated the JavaFrame property.'); 4129 end 4130 catch 4131 disp('BST> Warning: Cannot get the JavaFrame property for the selected figure.'); 4132 end 4133 argout1 = jFrame; 4134 4135 %% ==== ERROR ==== 4136 otherwise 4137 error(sprintf('Invalid context : "%s"', contextName)); 4138 end 4139 end 4140 4141 4142 4143 4144 %% ==== HELPERS ==== 4145 % Return all the protocol studies that have a given file in its structures 4146 % Possible field names: Result.DataFile, Result.FileName, Data.FileName, Channel.FileName 4147 % 4148 % USAGE: [sFoundStudy, iFoundStudy, iItem] = findFileInStudies(fieldGroup, fieldName, fieldFile, iStudiesList) 4149 % [sFoundStudy, iFoundStudy, iItem] = findFileInStudies(fieldGroup, fieldName, fieldFile) 4150 function [sFoundStudy, iFoundStudy, iItem] = findFileInStudies(fieldGroup, fieldName, fieldFile, iStudiesList) 4151 global GlobalData; 4152 sFoundStudy = []; 4153 iFoundStudy = []; 4154 iItem = []; 4155 % If no file provided, return 4156 if isempty(fieldFile) 4157 return; 4158 end 4159 % Extract folder(s) of the file(s) we're looking for 4160 fieldParts = strfind(fieldFile, '|'); 4161 if ~isempty(fieldParts) 4162 fieldParts(end+1) = length(fieldFile); 4163 fieldFolders = {}; 4164 iLast = 1; 4165 for iPart = 1:length(fieldParts) 4166 folder = fileparts(fieldFile(iLast:fieldParts(iPart)-1)); 4167 if ~isempty(folder) 4168 fieldFolders{end + 1} = folder; 4169 end 4170 iLast = fieldParts(iPart) + 1; 4171 end 4172 else 4173 fieldFolders = {fileparts(fieldFile)}; 4174 end 4175 % Get protocol information 4176 ProtocolStudies = GlobalData.DataBase.ProtocolStudies(GlobalData.DataBase.iProtocol); 4177 % List studies to process 4178 if (nargin < 4) || isempty(iStudiesList) 4179 iStudiesList = [-2, -3, 1:length(ProtocolStudies.Study)]; 4180 end 4181 4182 % NORMAL STUDIES: Look for surface file in all the surfaces of all subjects 4183 for iStudy = iStudiesList 4184 % Get study 4185 switch (iStudy) 4186 case -2, sStudy = ProtocolStudies.AnalysisStudy; 4187 case -3, sStudy = ProtocolStudies.DefaultStudy; 4188 otherwise, sStudy = ProtocolStudies.Study(iStudy); 4189 end 4190 % Check if field is available for the study 4191 if isempty(sStudy.(fieldGroup)) 4192 continue; 4193 end 4194 % Check we are in the correct folder 4195 if ~any(file_compare(fieldFolders, fileparts(sStudy.FileName))) 4196 continue; 4197 end 4198 % Get list of files from study 4199 filesList = {sStudy.(fieldGroup).(fieldName)}; 4200 if isempty(filesList) 4201 continue; 4202 end 4203 % Replace empty cells with empty strings 4204 iValidFiles = find(cellfun(@ischar, filesList)); 4205 if isempty(iValidFiles) 4206 continue; 4207 end 4208 % Find target in this list 4209 iItem = find(file_compare(filesList(iValidFiles), fieldFile)); 4210 if ~isempty(iItem) 4211 sFoundStudy = sStudy; 4212 iFoundStudy = iStudy; 4213 iItem = iValidFiles(iItem); 4214 return 4215 end 4216 end 4217 end 4218 4219 4220 %% ===== FILL MISSING FIELDS ===== 4221 function bstPref = FillMissingFields(PrefName, defPref) 4222 global GlobalData; 4223 if isfield(GlobalData, 'Preferences') && isfield(GlobalData.Preferences, PrefName) && isstruct(GlobalData.Preferences.(PrefName)) 4224 bstPref = GlobalData.Preferences.(PrefName); 4225 bstPref = struct_copy_fields(bstPref, defPref, 0); 4226 else 4227 bstPref = defPref; 4228 end 4229 end 4230 4231 4232 4233 4234 4235 4236


To change parameters or database structures: bst_set.m.

1 function bst_set( varargin ) 2 % BST_SET: Set a Brainstorm structure. 3 % 4 % DESCRIPTION: This function is used to abstract the way that these structures are stored. 5 % 6 % USAGE: 7 % ====== DIRECTORIES ================================================================== 8 % - bst_set('BrainstormHomeDir', BrainstormHomeDir) 9 % - bst_set('BrainstormTmpDir', BrainstormTmpDir) 10 % - bst_set('BrainstormDbDir', BrainstormDbDir) 11 % - bst_set('LastUsedDirs', sDirectories) 12 % - bst_set('BrainSuiteDir', BrainSuiteDir) 13 % - bst_set('PythonExe', PythonExe) 14 % - bst_set('PluginCustomPath', PluginCustomPath) 15 % 16 % ====== PROTOCOLS ==================================================================== 17 % - bst_set('iProtocol', iProtocol) 18 % - bst_set('ProtocolInfo', sProtocolInfo) 19 % - bst_set('ProtocolSubjects', ProtocolSubjects) 20 % - bst_set('isProtocolLoaded', isProtocolLoaded) 21 % - bst_set('isProtocolModified',isProtocolModified) 22 % - bst_set('ProtocolStudies', ProtocolStudies) 23 % - bst_set('Study', iStudy, sStudy) : Set a study in current protocol 24 % - bst_set('Subject', iSubject, sSubject) : Set a subject in current protocol 25 % 26 % ====== GUI ================================================================= 27 % - bst_set('Layout', sLayout) 28 % - bst_set('Layout', PropName, PropValue) 29 % - bst_set('Clipboard', Nodes, isCut) : Copy operation from the tree 30 % 31 % ====== CONFIGURATION ================================================================= 32 % - bst_set('Version', Version) 33 % - bst_set('ByteOrder', value) : 'b' for big endian, 'l' for little endian 34 % - bst_set('AutoUpdates', isAutoUpdates) 35 % - bst_set('ExpertMode', isExpertMode) 36 % - bst_set('DisplayGFP', isDisplayGFP) 37 % - bst_set('DownsampleTimeSeries', isDownsampleTimeSeries) 38 % - bst_set('GraphicsSmoothing', isGraphicsSmoothing) 39 % - bst_set('ForceMatCompression', isForceCompression) 40 % - bst_set('IgnoreMemoryWarnings', isIgnoreMemoryWarnings) 41 % - bst_set('SystemCopy', isSystemCopy) 42 % - bst_set('DisableOpenGL', isDisableOpenGL) 43 % - bst_set('InterfaceScaling', InterfaceScaling) 44 % - bst_set('TSDisplayMode', TSDisplayMode) : {'butterfly','column'} 45 % - bst_set('ElectrodeConfig', ElectrodeConfig, Modality) 46 % - bst_set('ElecInterpDist', ElecInterpDist, Modality) 47 % - bst_set('DefaultFormats' defaultFormats) 48 % - bst_set('BFSProperties', [scalpCond,skullCond,brainCond,scalpThick,skullThick]) 49 % - bst_set('ImportEegRawOptions', ImportEegRawOptions) 50 % - bst_set('BugReportOptions', BugReportOptions) 51 % - bst_set('DefaultSurfaceDisplay', displayStruct) 52 % - bst_set('MagneticExtrapOptions', extrapStruct) 53 % - bst_set('TimefreqOptions_morlet', Options) 54 % - bst_set('TimefreqOptions_fft', Options) 55 % - bst_set('TimefreqOptions_psd', Options) 56 % - bst_set('TimefreqOptions_hilbert', Options) 57 % - bst_set('TimefreqOptions_plv', Options) 58 % - bst_set('OpenMEEGOptions', Options) 59 % - bst_set('DuneuroOptions', Options) 60 % - bst_set('GridOptions_headmodel', Options) 61 % - bst_set('GridOptions_dipfit', Options) 62 % - bst_set('UniformizeTimeSeriesScales', isUniform) 63 % - bst_set('FlipYAxis', isFlipY) 64 % - bst_set('AutoScaleY', isAutoScaleY) 65 % - bst_set('FixedScaleY', Modality, Value) 66 % - bst_set('XScale', XScale) 67 % - bst_set('YScale', YScale) 68 % - bst_set('ShowXGrid', isShowXGrid) 69 % - bst_set('ShowYGrid', isShowYGrid) 70 % - bst_set('ShowZeroLines', isShowZeroLines) 71 % - bst_set('ShowEventsMode', ShowEventsMode) 72 % - bst_set('Resolution', [resX,resY]) 73 % - bst_set('UseSigProcToolbox', UseSigProcToolbox) 74 % - bst_set('RawViewerOptions', RawViewerOptions) 75 % - bst_set('TopoLayoutOptions', TopoLayoutOptions) 76 % - bst_set('StatThreshOptions', StatThreshOptions) 77 % - bst_set('ContactSheetOptions', ContactSheetOptions) 78 % - bst_set('ProcessOptions', ProcessOptions) 79 % - bst_set('MriOptions', MriOptions) 80 % - bst_set('CustomColormaps', CustomColormaps) 81 % - bst_set('DigitizeOptions', DigitizeOptions) 82 % - bst_set('PcaOptions', PcaOptions) 83 % - bst_set('ReadOnly', ReadOnly) 84 % - bst_set('LastPsdDisplayFunction', LastPsdDisplayFunction) 85 % - bst_set('PlotlyCredentials', Username, ApiKey, Domain) 86 % - bst_set('KlustersExecutable', ExecutablePath) 87 % - bst_set('ExportBidsOptions'), ExportBidsOptions) 88 % 89 % SEE ALSO bst_get 90 91 % @============================================================================= 92 % This function is part of the Brainstorm software: 93 % https://neuroimage.usc.edu/brainstorm 94 % 95 % Copyright (c) University of Southern California & McGill University 96 % This software is distributed under the terms of the GNU General Public License 97 % as published by the Free Software Foundation. Further details on the GPLv3 98 % license can be found at http://www.gnu.org/copyleft/gpl.html. 99 % 100 % FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE 101 % UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY 102 % WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF 103 % MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY 104 % LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE. 105 % 106 % For more information type "brainstorm license" at command prompt. 107 % =============================================================================@ 108 % 109 % Authors: Francois Tadel, 2008-2021 110 % Martin Cousineau, 2017 111 112 global GlobalData; 113 114 %% ==== PARSE INPUTS ==== 115 if ((nargin >= 1) && ischar(varargin{1})) 116 contextName = varargin{1}; 117 if (nargin >= 2) 118 contextValue = varargin{2}; 119 else 120 contextValue = []; 121 end 122 else 123 error('Usage : bst_set(contextName, contextValue)'); 124 end 125 126 % Get required context structure 127 switch contextName 128 %% ==== BRAINSTORM CONFIGURATION ==== 129 case 'Version' 130 GlobalData.Program.Version = contextValue; 131 case 'BrainstormHomeDir' 132 GlobalData.Program.BrainstormHomeDir = contextValue; 133 case 'BrainstormDbDir' 134 GlobalData.DataBase.BrainstormDbDir = contextValue; 135 case 'BrainstormTmpDir' 136 GlobalData.Preferences.BrainstormTmpDir = contextValue; 137 138 %% ==== PROTOCOL ==== 139 case 'iProtocol' 140 if isnumeric(contextValue) 141 GlobalData.DataBase.iProtocol = contextValue; 142 else 143 error('iProtocol should be a number.'); 144 end 145 case {'ProtocolSubjects', 'ProtocolStudies'} 146 for structField = fieldnames(contextValue)' 147 GlobalData.DataBase.(contextName)(GlobalData.DataBase.iProtocol).(structField{1}) = contextValue.(structField{1}); 148 end 149 GlobalData.DataBase.isProtocolModified(GlobalData.DataBase.iProtocol) = 1; 150 case 'ProtocolInfo' 151 for structField = fieldnames(contextValue)' 152 GlobalData.DataBase.(contextName)(GlobalData.DataBase.iProtocol).(structField{1}) = contextValue.(structField{1}); 153 end 154 case 'isProtocolLoaded' 155 GlobalData.DataBase.isProtocolLoaded(GlobalData.DataBase.iProtocol) = contextValue; 156 case 'isProtocolModified' 157 GlobalData.DataBase.isProtocolModified(GlobalData.DataBase.iProtocol) = contextValue; 158 159 %% ==== SUBJECT ==== 160 case 'Subject' 161 % Get subjects list 162 ProtocolSubjects = bst_get('ProtocolSubjects'); 163 iSubject = varargin{2}; 164 sSubject = varargin{3}; 165 % If default subject 166 if (iSubject == 0) 167 ProtocolSubjects.DefaultSubject = sSubject; 168 else 169 ProtocolSubjects.Subject(iSubject) = sSubject; 170 end 171 % Update DataBase 172 bst_set('ProtocolSubjects', ProtocolSubjects); 173 174 175 %% ==== STUDY ==== 176 case 'Study' 177 % Get studies list 178 ProtocolStudies = bst_get('ProtocolStudies'); 179 iStudies = varargin{2}; 180 sStudies = varargin{3}; 181 iAnalysisStudy = -2; 182 iDefaultStudy = -3; 183 for i = 1:length(iStudies) 184 % Normal study 185 if (iStudies(i) > 0) 186 ProtocolStudies.Study(iStudies(i)) = sStudies(i); 187 % Inter-subject analysis study 188 elseif (iStudies(i) == iAnalysisStudy) 189 ProtocolStudies.AnalysisStudy = sStudies(i); 190 % Default study 191 elseif (iStudies(i) == iDefaultStudy) 192 ProtocolStudies.DefaultStudy = sStudies(i); 193 end 194 end 195 % Update DataBase 196 bst_set('ProtocolStudies', ProtocolStudies); 197 198 199 %% ==== GUI ==== 200 % USAGE: bst_set('Layout', sLayout) 201 % bst_set('Layout', PropName, PropValue) 202 case 'Layout' 203 if (nargin == 2) && isstruct(contextValue) 204 GlobalData.Preferences.Layout = contextValue; 205 isUpdateScreens = 0; 206 elseif (nargin == 3) && ischar(contextValue) && isfield(GlobalData.Preferences, 'Layout') && isfield(GlobalData.Preferences.Layout, contextValue) 207 GlobalData.Preferences.Layout.(contextValue) = varargin{3}; 208 isUpdateScreens = strcmpi(contextValue, 'DoubleScreen'); 209 else 210 error('Invalid call to bst_set.'); 211 end 212 % Update screen configuration 213 GlobalData.Program.ScreenDef = gui_layout('GetScreenClientArea'); 214 % Update layout right now 215 gui_layout('Update'); 216 % If the number of screen was changed: update the maximum size of the Brainstorm window 217 if isUpdateScreens 218 gui_layout('UpdateMaxBstSize'); 219 end 220 221 % USAGE: bst_set('FixedScaleY', []) 222 % bst_set('FixedScaleY', Modality, Value) 223 case 'FixedScaleY' 224 if (nargin == 3) && ~isempty(contextValue) && ~isempty(varargin{3}) 225 GlobalData.Preferences.FixedScaleY.(contextValue) = varargin{3}; 226 elseif (nargin == 2) && isempty(contextValue) 227 GlobalData.Preferences.FixedScaleY = struct(); 228 end 229 230 case 'ByteOrder' 231 switch(contextValue) 232 case {'b','ieee-le','n'} 233 GlobalData.Preferences.ByteOrder = 'b'; 234 case {'l','ieee-be'} 235 GlobalData.Preferences.ByteOrder = 'l'; 236 otherwise 237 error('Invalid byte order.'); 238 end 239 240 case 'Clipboard' 241 if (length(varargin) >= 3) 242 isCut = varargin{3}; 243 else 244 isCut = 0; 245 end 246 GlobalData.Program.Clipboard.Nodes = contextValue; 247 GlobalData.Program.Clipboard.isCut = isCut; 248 249 case 'ElectrodeConfig' 250 Modality = varargin{2}; 251 ElectrodeConf = varargin{3}; 252 if isequal(Modality, 'ECOG+SEEG') 253 Modality = 'ECOG_SEEG'; 254 elseif ~ismember(Modality, {'EEG','SEEG','ECOG','MEG'}) 255 error(['Invalid modality: ' Modality]); 256 end 257 GlobalData.Preferences.(contextName).(Modality) = ElectrodeConf; 258 259 case 'ElecInterpDist' 260 Modality = varargin{2}; 261 ElecInterpDist = varargin{3}; 262 if isequal(Modality, 'ECOG+SEEG') 263 Modality = 'ECOG_SEEG'; 264 elseif ~ismember(Modality, {'EEG','SEEG','ECOG','MEG'}) 265 error(['Invalid modality: ' Modality]); 266 end 267 GlobalData.Preferences.(contextName).(Modality) = ElecInterpDist; 268 269 case {'UniformizeTimeSeriesScales', 'XScale', 'YScale', 'FlipYAxis', 'AutoScaleY', 'ShowXGrid', 'ShowYGrid', 'ShowZeroLines', 'ShowEventsMode', ... 270 'Resolution', 'AutoUpdates', 'ExpertMode', 'DisplayGFP', 'ForceMatCompression', 'GraphicsSmoothing', 'DownsampleTimeSeries', ... 271 'DisableOpenGL', 'InterfaceScaling', 'TSDisplayMode', 'UseSigProcToolbox', 'LastUsedDirs', 'DefaultFormats', ... 272 'BFSProperties', 'ImportDataOptions', 'ImportEegRawOptions', 'RawViewerOptions', 'MontageOptions', 'TopoLayoutOptions', ... 273 'StatThreshOptions', 'ContactSheetOptions', 'ProcessOptions', 'BugReportOptions', 'DefaultSurfaceDisplay', ... 274 'MagneticExtrapOptions', 'MriOptions', 'ConnectGraphOptions', 'NodelistOptions', 'IgnoreMemoryWarnings', 'SystemCopy', ... 275 'TimefreqOptions_morlet', 'TimefreqOptions_hilbert', 'TimefreqOptions_fft', 'TimefreqOptions_psd', 'TimefreqOptions_stft', 'TimefreqOptions_plv', ... 276 'OpenMEEGOptions', 'DuneuroOptions', 'DigitizeOptions', 'PcaOptions', 'CustomColormaps', 'PluginCustomPath', 'BrainSuiteDir', 'PythonExe', ... 277 'GridOptions_headmodel', 'GridOptions_dipfit', 'LastPsdDisplayFunction', 'KlustersExecutable', 'ExportBidsOptions'} 278 GlobalData.Preferences.(contextName) = contextValue; 279 280 case 'ReadOnly' 281 GlobalData.DataBase.isReadOnly = contextValue; 282 283 case 'PlotlyCredentials' 284 if length(varargin) ~= 4 285 error('Invalid call to bst_set.'); 286 end 287 [username, apiKey, domain] = varargin{2:4}; 288 % Default domain: plot.ly 289 if isempty(domain) 290 domain = 'https://plot.ly'; 291 end 292 % Plotly needs a URL with HTTP and no trailing slash. 293 if strfind(domain, 'https://') 294 domain = strrep(domain, 'https://', 'http://'); 295 elseif isempty(strfind(domain, 'http://')) 296 domain = ['http://', domain]; 297 end 298 if domain(end) == '/' 299 domain = domain(1:end-1); 300 end 301 % Save credentials 302 saveplotlycredentials(username, apiKey); 303 saveplotlyconfig(domain); 304 305 %% ==== ERROR ==== 306 otherwise 307 error('Invalid context : ''%s''', contextName); 308 309 310 end 311 312 313 314

File structures

The structures of the different types of files were described in the sections "On the hard drive" of the introduction tutorials. Here is a summary of all these sections:

Custom processing

In many situations, you will find useful to read the files available in the database, and maybe modify them. The easiest approaches do not require any scripting, we will start by reviewing them quickly.

Process: Run Matlab command

If you want to modify the values saved in a file (eg. the field "F" from a "data" file), the easiest way is probably to use the process1 File > Run Matlab command. It is also available from Process2 in the category "Other".

It loads the files in input and run them through a piece of Matlab code that you can edit freely. It can extend a lot the flexibility of the Brainstorm pipeline manager, providing an easy access to any Matlab function or script.

The corresponding script looks like this:

sFiles = bst_process('CallProcess', 'process_matlab_eval', sFiles, [], ...
    'matlab',      'Data = Data.^2;', ...
    'sensortypes', 'MEG', ...
    'overwrite',   0);

Export/Import with the database explorer

Right-click on the Deviant average in the database explorer > File > Export to Matlab > "DataMat".

Data exported as "DataMat"
>> DataMat
DataMat =
     ChannelFlag: [340x1 double]
    ColormapType: []
         Comment: 'Avg: deviant (39 files)'
        DataType: 'recordings'
          Device: 'CTF'
    DisplayUnits: []
               F: [340x361 double]
         History: {45x3 cell}
             Std: []
            Time: [1x361 double]
            nAvg: 39
          Events: [1x1 struct]

DataMat is the exact content of the corresponding .mat file, as loaded with Matlab's load() function. Edit some of the fields of this structure from the Matlab command window:

>> DataMat.Comment = 'Test square';
>> DataMat.F = DataMat.F .^ 2;

Now right-click on the folder containing the original file > File > Import from Matlab > DataMat:

import_matlab.gif

If instead, you right-click on the original file and select the menu File > Import from Matlab, it overwrites the selected file instead of creating a new one with the selected structure.

Reference: File manipulation

Useful functions for manipulating file names and paths (read the code of the functions for help):

Reading files from a script (all the functions take relative paths in input):

Saving files:

Registering new files in the database:

Reload folders (if you saved or deleted files without registering correctly the modification in the database):

Other useful database functions:

Export a file from the database to other file formats (read the comments in the functions for help):

Convert Brainstorm structures to FieldTrip structures:

Reference: Display functions

Create new visualization figures:

Configure time-series figures:

Configure 3D figures:

Configure time-frequency figures:

Configure colormaps:

Configure statistical thresholding:

Export the contents of a figure to a file:

Example: Creating a new file

This section illustrates how to add new files to the database. We will create a sinusoidal signal and save it in a "matrix" file, in a new folder of the subject "Test".

% Time: 1 second with a sampling frequency of 1000Hz
t = 0:0.001:1;
% Generate two sinsuoidal signals (20Hz,30Hz)
F = [sin(20*2*pi*t); 0.5*sin(30*2*pi*t)];

% Initialize an empty "matrix" structure
sMat = db_template('matrixmat');
% Fill the required fields of the structure
sMat.Value       = F;
sMat.Comment     = 'Test sinusoids';
sMat.Description = {'Signal #1: 20Hz'; 'Signal #2: 30Hz'};
sMat.Time        = t;

% Create a new folder "Script" in subject "Test"
iStudy = db_add_condition('Test', 'Script');
% Get the corresponding study structure
sStudy = bst_get('Study', iStudy);

There are many options to add a new file to the database, with various levels of requirements. You can call the db_add function (reloads the destination folder, therefore slow if you save many files), save the file in the corresponding folder and reload the protocol (slow as well), or register the file in the database manually (more complicated but faster).

Option #1: db_add

OutputFile = db_add(iStudy, sMat);

Option #2: bst_save / db_reload_studies

% Get the full path to the new folder
% (same folder as the brainstormstudy.mat file for this study)
OutputFolder = bst_fileparts(file_fullpath(sStudy.FileName));
% Get a new unique filename (including a timestamp)
MatrixFile = bst_process('GetNewFilename', OutputFolder, 'matrix_test');
% Save file
bst_save(MatrixFile, sMat, 'v6');
% Reload the folder in which the new file was saved
db_reload_studies(iStudy);

Option #3: bst_save / db_add_data

% Another way to generate a unique filename (without a timestamp)
MatrixFile = file_unique(bst_fullfile(OutputFolder, 'matrix_test.mat'));
% Save file
bst_save(MatrixFile, sMat, 'v6');
% Reference saved file in the database
db_add_data(iStudy, MatrixFile, sMat);
% Update the database explorer display
panel_protocols('UpdateNode', 'Study', iStudy);

Example: Editing events

A step that commonly requires manual changes is the definition of the event markers. For example, we have to combine external triggers or behavioral information with the existing events. This example illustrates how to load the events, modify them and save them back.

For the continuous recordings, the events are saved in the .mat file corresponding to the "Link to raw file". These structures contain only meta-data and information created with Brainstorm, the EEG/MEG recordings are available in a separate binary file. First, we need to load this link.

% Right-click on a "Link to raw file" in the database explorer
%  > File > Copy file path to clipboard
RawFile = '/.../@rawS01.../data_0raw_S01_..._01_600Hz_notch.mat'

% Load the "sFile" structure, contained in the .F structure
% of the link file (data_0raw...mat)
sRaw = in_bst_data(RawFile, 'F');

>> sRaw.F.events
ans =
1x7 struct array with fields:
    label
    color
    epochs
    samples
    times
    reactTimes
    select

For example, let's say we want to add 30ms to all the events in the category "button" in order to compensate for some hardware delay, and create a new event category with the modified timing. We need first to identify what is the index of the category "button", in this array of 7 event structures.

% Find the index of the event category "button"
iEvtButton = find(strcmpi({sRaw.F.events.label}, 'button'));

>> iEvtButton
iEvtButton =
     3

In the code above, note this special Matlab syntax that allows the concatenation of the values of one field across multiple structures, in an array of structures:

>> {sRaw.F.events.label}
ans =
    'standard'    'deviant'    'button'    'cardiac'
    'blink'    'bad_1-7Hz'    'bad_40-240Hz'

If you want to search instead all the events containing a specific tag, for example "bad", you can use the cellfun function (applies the same function sequentially to all the elements in a cell array and concatenates the results) in combination with the strfind function (search for a substring). The final call to the find function returns at which indices the list of tags found in the event label is not empty.

>> iEvtBad = find( ~cellfun( @(c)isempty(strfind(c,'bad')), ...
                             {sRaw.F.events.label}))
iEvtBad =
     6     7

The code below copies the existing event category "button", renames it and add a 30ms offset. Note that the times and samples field must always match. If you modify one, you must modify the others as well (times = samples/sfreq). If you add or remove events, you must adjust the size of the epochs field (always 1 for most file formats).

% Copy the event category "button" to a new category
iEvtNew = length(sRaw.F.events) + 1;
sRaw.F.events(iEvtNew) = sRaw.F.events(iEvtButton);
% Rename the new event to "button_offset"
sRaw.F.events(iEvtNew).label = 'button_offset';

% How many samples in 30ms (0.030s * 600Hz = 18 samples)
offsetSample = round(0.030 .* sRaw.F.prop.sfreq);
% Apply offset to the events in the "button_offset" category
sRaw.F.events(iEvtNew).samples = ...
    sRaw.F.events(iEvtNew).samples + offsetSample;
% Re-compute the corresponding times
sRaw.F.events(iEvtNew).times = ...
    sRaw.F.events(iEvtNew).samples ./ sRaw.F.prop.sfreq;
% Re-generate an epochs field with only ones
% (optional here, as we didn't change the number of evt)
sRaw.F.events(iEvtNew).epochs = ...
    ones(1, size(sRaw.F.events(iEvtNew).times, 2));
% Change the event color to yellow (red=1, green=1, blue=0)
sRaw.F.events(iEvtNew).color = [1 1 0];

>> sRaw.F.events(iEvtNew)
ans =
         label: 'button_offset'
         color: [1 1 0]
        epochs: [1x40 double]
       samples: [1x40 double]
         times: [1x40 double]
    reactTimes: []
        select: 1

The last step is to save the modifications back to the "Link to raw file". Here the call to file_fullpath is optional because the variable RawFile already contains the absolute path to the file.

% Update the sRaw structure to the RawFile file (the last parameter appends to the existing struct)
bst_save(file_fullpath(RawFile), sRaw, 'v6', 1);

Open the recordings to make sure your transformation worked the way you expected.

Find examples in the code

The easier way to understand how to use a function is to search the code with the "Find files" interface in Matlab. Go to the brainstorm3 folder, click on "Find files" (or Ctrl+Shift+F), enter the name of a function in "Find files containing text", Include subfolders, Match case. It will return all the lines that include the string you entered across all the files in the Brainstorm distribution. Just double-click on a line to jump to the code in the Matlab editor.

find_files.gif

You can use the same interface to find what function is called when you click on a button or menu in the interface. Search for the label or the tooltip of the interface element in the same way. The example below shows how to track what happens when you click on the headmodel popup menu "Check spheres".

find_files2.gif

If you have trouble understanding how to set some input parameters, you can use the debugger to explore a real use case. Place a breakpoint at the begging of your function of interest (watch this tutorial if you don't know how to do this), for example in view_timeseries.m. Then click on the corresponding menus in the Brainstorm interface (eg. double-click on a data file). When the execution reaches the line you selected, it stops and gives you back the commands. You can explore the values in all the variables, modify them, and execute the code step by step (many options available in the Editor tab of Matlab).

debugger.gif

Additional quality control

You can add in the reports all the information that may help you control the quality of the analysis, or figures you want to include in publications or clinical reports. The process "File > Save snapshot" lets you save some predefined views, but you can also custom screen captures. The example below shows how to add a "raster plot" for all the deviant trials from Run#01 in the report.

% Get all the deviant trials in Run#01  (the list includes the deviant average)
sDeviant = bst_process('CallProcess', 'process_select_files_data', [], [], ...
    'subjectname',   'Subject01', ...
    'condition',     'S01_AEF_20131218_01_600Hz_notch', ...
    'tag',           'deviant');

% Open raster plot
hFig = view_erpimage({sDeviant.FileName}, 'erpimage', 'MEG');
% Select the channel MRT34
sOptions = panel_display('GetDisplayOptions');
sOptions.RowName = 'MRT34';
panel_display('SetDisplayOptions', sOptions);

% Screen capture of this figure
% bst_report('Snapshot', hFig, FileName, Comment, WindowPosition);
bst_report('Snapshot', hFig, [], 'ERP image: MRT34', [300 100 600 400]);
% Close figure
close(hFig);

You can also add messages in the reports (information, warning or errors).

% Function call: bst_report(MsgType, sProcess, sInputs, Message)
bst_report('Info',    [], sDeviant, 'This is an information message.');
bst_report('Warning', [], sDeviant, 'This is a warning.');
bst_report('Error',   [], sDeviant, 'This is an error.');

% Open the report viewer to show the current report (not saved yet)
bst_report('Open', 'Current');

Report generated with the code above:

Loop over subjects

Creating loops is not supported yet by the script generator, but relatively easy to do from a script without knowing too much about Matlab programming. The example below shows how to create a loop over subjects to import their anatomy. The dataset used here is from the tutorial MEG visual: single subject.

With the Process1 box empty, select the process "Import > Import anatomy > Import anatomy folder" and generate a script. Simplify if using the guidelines presented in the previous sections:

% Input files
SubjectNames = {'sub001'};
RawFiles = {...
    '/.../Tutorials/sample_group/freesurfer/sub001'};

% Process: Import anatomy folder
bst_process('CallProcess', 'process_import_anatomy', [], [], ...
    'subjectname', SubjectNames{1}, ...
    'mrifile',     {RawFiles{1}, 'FreeSurfer'}, ...
    'nvertices',   15000);

Add the other subject names and corresponding FreeSurfer folders in the script header:

SubjectNames = {'sub001', 'sub002', 'sub003', 'sub004'};
RawFiles = {...
    '/.../Tutorials/sample_group/freesurfer/sub001', ...
    '/.../Tutorials/sample_group/freesurfer/sub002', ...
    '/.../Tutorials/sample_group/freesurfer/sub003', ...
    '/.../Tutorials/sample_group/freesurfer/sub004'};

Add a for loop around all the steps to repeat on each subject ("for" before, and "end" after the code), and replace the indices "1" with the loop variable:

% Loop on subjects
for iSubject = 1:length(SubjectNames)
    % Process: Import anatomy folder
    bst_process('CallProcess', 'process_import_anatomy', [], [], ...
        'subjectname', SubjectNames{iSubject}, ...
        'mrifile',     {RawFiles{iSubject}, 'FreeSurfer'}, ...
        'nvertices',   15000);
end

Loop over acquisition runs

If you have multiple subjects for which the anatomy is already imported, and multiple runs to process for each subject, you can add two nested for loops to link all the runs to the database in the same script. The dataset used here is from the tutorial MEG visual: single subject.

With the Process1 box empty, select the process "Import > Import recordings > Create link to raw file" and generate a script. Simplify if using the guidelines presented in the previous sections:

% Input files
SubjectNames = {'sub001'};
RawFiles = {...
    '/.../sample_group/ds117/sub001/MEG/run_01_sss.fif'};

% Process: Create link to raw file
sFileRaw = bst_process('CallProcess', 'process_import_data_raw', [], [], ...
    'subjectname',    SubjectNames{1}, ...
    'datafile',       {RawFiles{1}, 'FIF'}, ...
    'channelreplace', 0, ...
    'channelalign',   0, ...
    'evtmode',        'value');

Add the other subject names and all the runs for all the subjects (array of cell arrays) in the script header:

SubjectNames = {'sub001', 'sub002'};
RawFiles = {...
    {'/.../sample_group/ds117/sub001/MEG/run_01_sss.fif', ...
     '/.../sample_group/ds117/sub001/MEG/run_02_sss.fif', ...
     '/.../sample_group/ds117/sub001/MEG/run_03_sss.fif'}, ...
    {'/.../sample_group/ds117/sub002/MEG/run_01_sss.fif', ...
     '/.../sample_group/ds117/sub002/MEG/run_02_sss.fif', ...
     '/.../sample_group/ds117/sub002/MEG/run_03_sss.fif'}};

Add two for loops around the code to repeat on all the runs:

% Loop on subjects
for iSubject = 1:length(SubjectNames)
  % Loop on runs for each subject
  for iRun = 1:length(RawFiles{iSubject})
    % Process: Create link to raw file
    sFileRaw = bst_process('CallProcess', 'process_import_data_raw', [], [], ...
        'subjectname',    SubjectNames{iSubject}, ...
        'datafile',       {RawFiles{iSubjects}{iRun}, 'FIF'}, ...
        'channelreplace', 0, ...
        'channelalign',   0, ...
        'evtmode',        'value');
  end
end

How to process an entire study

This section proposes a standard workflow for processing a full group study with Brainstorm. It contains the same steps of analysis as the introduction tutorials, but separating what can be done automatically from what should be done manually. This workflow can be adapted to most ERP studies (stimulus-based).

Final scripts

The following script from the Brainstorm distribution reproduces the introduction tutorials ("Get started"): brainstorm3/toolbox/script/tutorial_introduction.m - Report: report_TutorialIntroduction.html

1 function tutorial_introduction(tutorial_dir, reports_dir) 2 % TUTORIAL_INTRODUCTION: Script that runs all the Brainstorm introduction tutorials. 3 % 4 % INPUTS: 5 % - tutorial_dir : Directory where the sample_introduction.zip file has been unzipped 6 % - reports_dir : Directory where to save the execution report (instead of displaying it) 7 8 % @============================================================================= 9 % This function is part of the Brainstorm software: 10 % https://neuroimage.usc.edu/brainstorm 11 % 12 % Copyright (c) University of Southern California & McGill University 13 % This software is distributed under the terms of the GNU General Public License 14 % as published by the Free Software Foundation. Further details on the GPLv3 15 % license can be found at http://www.gnu.org/copyleft/gpl.html. 16 % 17 % FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE 18 % UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY 19 % WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF 20 % MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY 21 % LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE. 22 % 23 % For more information type "brainstorm license" at command prompt. 24 % =============================================================================@ 25 % 26 % Author: Francois Tadel, 2016-2017 27 28 29 % ===== FILES TO IMPORT ===== 30 % Output folder for reports 31 if (nargin < 2) || isempty(reports_dir) || ~isdir(reports_dir) 32 reports_dir = []; 33 end 34 % You have to specify the folder in which the tutorial dataset is unzipped 35 if (nargin == 0) || isempty(tutorial_dir) || ~file_exist(tutorial_dir) 36 error('The first argument must be the full path to the dataset folder.'); 37 end 38 % Subject name 39 SubjectName = 'Subject01'; 40 % Build the path of the files to import 41 AnatDir = fullfile(tutorial_dir, 'sample_introduction', 'anatomy'); 42 Run1File = fullfile(tutorial_dir, 'sample_introduction', 'data', 'S01_AEF_20131218_01_600Hz.ds'); 43 Run2File = fullfile(tutorial_dir, 'sample_introduction', 'data', 'S01_AEF_20131218_02_600Hz.ds'); 44 NoiseFile = fullfile(tutorial_dir, 'sample_introduction', 'data', 'S01_Noise_20131218_02_600Hz.ds'); 45 % Check if the folder contains the required files 46 if ~file_exist(Run1File) 47 error(['The folder ' tutorial_dir ' does not contain the folder from the file sample_introduction.zip.']); 48 end 49 % Re-inialize random number generator 50 if (bst_get('MatlabVersion') >= 712) 51 rng('default'); 52 end 53 54 55 %% ===== TUTORIAL #1: CREATE PROTOCOL ================================================ 56 % =================================================================================== 57 disp([10 'DEMO> Tutorial #1: Create protocol' 10]); 58 % The protocol name has to be a valid folder name (no spaces, no weird characters...) 59 ProtocolName = 'TutorialIntroduction'; 60 % Start brainstorm without the GUI 61 if ~brainstorm('status') 62 brainstorm nogui 63 end 64 % Delete existing protocol 65 gui_brainstorm('DeleteProtocol', ProtocolName); 66 % Create new protocol 67 gui_brainstorm('CreateProtocol', ProtocolName, 0, 0); 68 % Start a new report 69 bst_report('Start'); 70 % Reset colormaps 71 bst_colormaps('RestoreDefaults', 'meg'); 72 % Set the current display mode to 'butterfly' 73 bst_set('TSDisplayMode', 'butterfly'); 74 75 76 %% ===== TUTORIAL #2: IMPORT ANATOMY ================================================= 77 % =================================================================================== 78 disp([10 'DEMO> Tutorial #2: Import anatomy' 10]); 79 % Process: Import FreeSurfer folder 80 bst_process('CallProcess', 'process_import_anatomy', [], [], ... 81 'subjectname', SubjectName, ... 82 'mrifile', {AnatDir, 'FreeSurfer'}, ... 83 'nvertices', 15000, ... 84 'nas', [127, 213, 139], ... 85 'lpa', [ 52, 113, 96], ... 86 'rpa', [202, 113, 91]); 87 % This automatically calls the SPM registration procedure because the AC/PC/IH points are not defined 88 89 90 91 %% ===== TUTORIAL #3: EXPLORE ANATOMY ================================================ 92 % =================================================================================== 93 disp([10 'DEMO> Tutorial #3: Explore anatomy' 10]); 94 % Get subject definition 95 sSubject = bst_get('Subject', SubjectName); 96 % Get MRI file and surface files 97 MriFile = sSubject.Anatomy(sSubject.iAnatomy).FileName; 98 CortexFile = sSubject.Surface(sSubject.iCortex).FileName; 99 HeadFile = sSubject.Surface(sSubject.iScalp).FileName; 100 % Display MRI 101 hFigMri1 = view_mri(MriFile); 102 hFigMri3 = view_mri_3d(MriFile, [], [], 'NewFigure'); 103 hFigMri2 = view_mri_slices(MriFile, 'x', 20); 104 pause(0.5); 105 % Close figures 106 close([hFigMri1 hFigMri2 hFigMri3]); 107 % Display scalp and cortex 108 hFigSurf = view_surface(HeadFile); 109 hFigSurf = view_surface(CortexFile, [], [], hFigSurf); 110 hFigMriSurf = view_mri(MriFile, CortexFile); 111 % Figure configuration 112 iTess = 2; 113 panel_surface('SetShowSulci', hFigSurf, iTess, 1); 114 panel_surface('SetSurfaceColor', hFigSurf, iTess, [1 0 0]); 115 panel_surface('SetSurfaceSmooth', hFigSurf, iTess, 0.5, 0); 116 panel_surface('SetSurfaceTransparency', hFigSurf, iTess, 0.8); 117 figure_3d('SetStandardView', hFigSurf, 'left'); 118 pause(0.5); 119 % Close figures 120 close([hFigSurf hFigMriSurf]); 121 122 123 124 %% ===== TUTORIAL #4: CHANNEL FILE =================================================== 125 % =================================================================================== 126 disp([10 'DEMO> Tutorial #4: Channel file' 10]); 127 % Process: Create link to raw files 128 sFilesRun1 = bst_process('CallProcess', 'process_import_data_raw', [], [], ... 129 'subjectname', SubjectName, ... 130 'datafile', {Run1File, 'CTF'}, ... 131 'channelalign', 1); 132 sFilesRun2 = bst_process('CallProcess', 'process_import_data_raw', [], [], ... 133 'subjectname', SubjectName, ... 134 'datafile', {Run2File, 'CTF'}, ... 135 'channelalign', 1); 136 sFilesNoise = bst_process('CallProcess', 'process_import_data_raw', [], [], ... 137 'subjectname', SubjectName, ... 138 'datafile', {NoiseFile, 'CTF'}, ... 139 'channelalign', 0); 140 sFilesRaw = [sFilesRun1, sFilesRun2, sFilesNoise]; 141 % Process: Snapshot: Sensors/MRI registration 142 bst_process('CallProcess', 'process_snapshot', [sFilesRun1, sFilesRun2], [], ... 143 'target', 1, ... % Sensors/MRI registration 144 'modality', 1, ... % MEG (All) 145 'orient', 1, ... % left 146 'Comment', 'MEG/MRI Registration'); 147 148 % View sensors 149 hFig = view_surface(HeadFile); 150 hFig = view_channels(sFilesRun1.ChannelFile, 'MEG', 1, 1, hFig); 151 % Hide sensors 152 pause(0.5); 153 hFig = view_channels(sFilesRun1.ChannelFile, 'MEG', 0, 0, hFig); 154 % View coils 155 hFig = view_channels(sFilesRun1.ChannelFile, 'CTF', 1, 1, hFig); 156 % View helmet 157 pause(0.5); 158 hFig = view_helmet(sFilesRun1.ChannelFile, hFig); 159 pause(0.5); 160 close(hFig); 161 % Edit good/bad channel for current file 162 gui_edit_channel(sFilesRun1.ChannelFile); 163 pause(0.5); 164 % Unload everything 165 bst_memory('UnloadAll', 'Forced'); 166 167 168 169 %% ===== TUTORIAL #5: REVIEW RAW ===================================================== 170 % =================================================================================== 171 disp([10 'DEMO> Tutorial #5: Review raw' 10]); 172 % Process: Convert to continuous (CTF): Continuous 173 bst_process('CallProcess', 'process_ctf_convert', sFilesRaw, [], ... 174 'rectype', 2); % Continuous 175 176 % View recordings 177 hFigMeg = view_timeseries(sFilesRun1.FileName, 'MEG'); 178 hFigEeg = view_timeseries(sFilesRun1.FileName, 'Misc'); 179 hFigSel = view_timeseries(sFilesRun1.FileName, 'MEG', {'MLT11','MLT12','MLT13'}); 180 % Figure configuration 181 pause(0.5); 182 panel_record('SetTimeLength', 3); 183 panel_record('SetStartTime', 100); 184 panel_record('SetDisplayMode', hFigMeg, 'column'); 185 panel_montage('SetCurrentMontage', hFigMeg, 'CTF LT'); 186 % Set filters: panel_filter('SetFilters', LowPassEnabled, LowPassValue, HighPassEnabled, HighPassValue, SinRemovalEnabled, SinRemovalValue, MirrorEnabled, FullSourcesEnabled) 187 panel_filter('SetFilters', 1, 100, 1, 1, 0, [], 0, 0); 188 pause(0.5); 189 panel_record('SetDisplayMode', hFigMeg, 'butterfly'); 190 panel_montage('SetCurrentMontage', hFigMeg, ''); 191 % Close figures 192 close([hFigMeg hFigEeg hFigSel]); 193 194 195 196 %% ===== TUTORIAL #8: STIM DELAYS ==================================================== 197 % =================================================================================== 198 disp([10 'DEMO> Tutorial #8: Stim delays' 10]); 199 % Process: Detect: standard_fix 200 bst_process('CallProcess', 'process_evt_detect_analog', [sFilesRun1, sFilesRun2], [], ... 201 'eventname', 'standard_fix', ... 202 'channelname', 'UADC001', ... 203 'timewindow', [], ... 204 'threshold', 1.2, ... 205 'blanking', 0.2, ... 206 'highpass', 0, ... 207 'lowpass', 0, ... 208 'refevent', 'standard', ... 209 'isfalling', 0, ... 210 'ispullup', 0, ... 211 'isclassify', 0); 212 % Process: Detect: deviant_fix 213 bst_process('CallProcess', 'process_evt_detect_analog', [sFilesRun1, sFilesRun2], [], ... 214 'eventname', 'deviant_fix', ... 215 'channelname', 'UADC001', ... 216 'timewindow', [], ... 217 'threshold', 1.2, ... 218 'blanking', 0.2, ... 219 'highpass', 0, ... 220 'lowpass', 0, ... 221 'refevent', 'deviant', ... 222 'isfalling', 0, ... 223 'ispullup', 0, ... 224 'isclassify', 0); 225 % Process: Read from channel 226 bst_process('CallProcess', 'process_evt_read', [sFilesRun1, sFilesRun2], [], ... 227 'stimchan', 'UDIO001', ... 228 'trackmode', 1, ... % Value: detect the changes of channel value 229 'zero', 0); 230 231 % Process: Delete events 232 bst_process('CallProcess', 'process_evt_delete', [sFilesRun1, sFilesRun2], [], ... 233 'eventname', 'standard, deviant, button'); 234 % Process: Rename event (standard_fix>standard) 235 bst_process('CallProcess', 'process_evt_rename', [sFilesRun1, sFilesRun2], [], ... 236 'src', 'standard_fix', ... 237 'dest', 'standard'); 238 % Process: Rename event (deviant_fix>deviant) 239 bst_process('CallProcess', 'process_evt_rename', [sFilesRun1, sFilesRun2], [], ... 240 'src', 'deviant_fix', ... 241 'dest', 'deviant'); 242 % Process: Rename event (64>button) 243 bst_process('CallProcess', 'process_evt_rename', [sFilesRun1, sFilesRun2], [], ... 244 'src', '64', ... 245 'dest', 'button'); 246 247 248 249 %% ===== TUTORIAL #10: FREQUENCY FILTERS ============================================= 250 % =================================================================================== 251 disp([10 'DEMO> Tutorial #10: Frequency filters' 10]); 252 % Process: Sinusoid removal: 60Hz 120Hz 180Hz 300Hz 253 sFilesNotch = bst_process('CallProcess', 'process_notch', sFilesRaw, [], ... 254 'freqlist', [60, 120, 180], ... 255 'sensortypes', 'MEG', ... 256 'read_all', 0); 257 % Process: Power spectrum density (Welch) 258 sFilesPsd = bst_process('CallProcess', 'process_psd', [sFilesRaw, sFilesNotch], [], ... 259 'timewindow', [], ... 260 'win_length', 4, ... 261 'win_overlap', 50, ... 262 'clusters', {}, ... 263 'sensortypes', 'MEG', ... 264 'edit', struct(... 265 'Comment', 'Power', ... 266 'TimeBands', [], ... 267 'Freqs', [], ... 268 'ClusterFuncTime', 'none', ... 269 'Measure', 'power', ... 270 'Output', 'all', ... 271 'SaveKernel', 0)); 272 % Process: Snapshot: Frequency spectrum 273 bst_process('CallProcess', 'process_snapshot', sFilesPsd, [], ... 274 'target', 10, ... % Frequency spectrum 275 'modality', 1, ... % MEG (All) 276 'Comment', 'Power spectrum density'); 277 % Process: Delete folders 278 bst_process('CallProcess', 'process_delete', sFilesRaw, [], ... 279 'target', 2); % Delete folders 280 % Separate the three outputs 281 sFilesRun1 = {sFilesNotch(1).FileName}; 282 sFilesRun2 = {sFilesNotch(2).FileName}; 283 sFilesNoise = {sFilesNotch(3).FileName}; 284 285 286 287 %% ===== TUTORIAL #11: BAD CHANNELS ================================================== 288 % =================================================================================== 289 % % Process: Set bad channels 290 % sFiles = bst_process('CallProcess', 'process_channel_setbad', sFilesRun2, [], ... 291 % 'sensortypes', 'MRT51, MLO52, MLO42, MLO43'); 292 293 294 295 %% ===== TUTORIAL #12: ARTIFACTS DETECTION =========================================== 296 % =================================================================================== 297 disp([10 'DEMO> Tutorial #12: Artifacts detection' 10]); 298 % Process: Detect heartbeats 299 bst_process('CallProcess', 'process_evt_detect_ecg', [sFilesRun1, sFilesRun2], [], ... 300 'channelname', 'ECG', ... 301 'timewindow', [], ... 302 'eventname', 'cardiac'); 303 % Process: Detect eye blinks 304 bst_process('CallProcess', 'process_evt_detect_eog', [sFilesRun1, sFilesRun2], [], ... 305 'channelname', 'VEOG', ... 306 'timewindow', [], ... 307 'eventname', 'blink'); 308 % Process: Remove simultaneous 309 bst_process('CallProcess', 'process_evt_remove_simult', [sFilesRun1, sFilesRun2], [], ... 310 'remove', 'cardiac', ... 311 'target', 'blink', ... 312 'dt', 0.25, ... 313 'rename', 0); 314 315 316 317 %% ===== TUTORIAL #13: SSP =========================================================== 318 % =================================================================================== 319 disp([10 'DEMO> Tutorial #13: SSP' 10]); 320 % Process: SSP ECG: cardiac 321 bst_process('CallProcess', 'process_ssp_ecg', [sFilesRun1, sFilesRun2], [], ... 322 'eventname', 'cardiac', ... 323 'sensortypes', 'MEG', ... 324 'usessp', 0, ... 325 'select', 1); 326 % Process: SSP EOG: blink 327 bst_process('CallProcess', 'process_ssp_eog', sFilesRun1, [], ... 328 'eventname', 'blink', ... 329 'sensortypes', 'MEG', ... 330 'usessp', 0, ... 331 'select', [1 2]); 332 bst_process('CallProcess', 'process_ssp_eog', sFilesRun2, [], ... 333 'eventname', 'blink', ... 334 'sensortypes', 'MEG', ... 335 'usessp', 0, ... 336 'select', 1); 337 338 339 %% ===== TUTORIAL #14: BAD SEGMENTS ================================================== 340 % =================================================================================== 341 disp([10 'DEMO> Tutorial #14: Bad segments' 10]); 342 % Process: Detect other artifacts 343 bst_process('CallProcess', 'process_evt_detect_badsegment', [sFilesRun1, sFilesRun2], [], ... 344 'timewindow', [], ... 345 'sensortypes', 'MEG', ... 346 'threshold', 3, ... % 3 347 'isLowFreq', 1, ... 348 'isHighFreq', 1); 349 350 % Process: Rename event (1-7Hz > saccade) (Run02 only) 351 bst_process('CallProcess', 'process_evt_rename', sFilesRun2, [], ... 352 'src', '1-7Hz', ... 353 'dest', 'saccade'); 354 355 % Manual selection of saccades (cannot be done from the pipeline editor: manual edition of the structures) 356 sMatRun2 = in_bst_data(sFilesRun2{1}, 'F'); 357 iEvtSaccade = find(strcmpi({sMatRun2.F.events.label}, 'saccade')); 358 sMatRun2.F.events(iEvtSaccade).times = [30, 81.5, 104, 142.5, 167, 187.5, 246.5, 319; 31, 83, 105, 144, 168, 188.5, 248, 320]; 359 sMatRun2.F.events(iEvtSaccade).epochs = ones(1, size(sMatRun2.F.events(iEvtSaccade).times, 2)); 360 sMatRun2.F.events(iEvtSaccade).channels = []; 361 sMatRun2.F.events(iEvtSaccade).notes = []; 362 bst_save(file_fullpath(sFilesRun2{1}), sMatRun2, 'v6', 1); 363 364 % Process: SSP: saccade (Run02 only) 365 bst_process('CallProcess', 'process_ssp', sFilesRun2, [], ... 366 'timewindow', [], ... 367 'eventname', 'saccade', ... 368 'eventtime', [-0.2, 0.2], ... 369 'bandpass', [1.5, 7], ... 370 'sensortypes', 'MEG', ... 371 'usessp', 1, ... 372 'saveerp', 0, ... 373 'method', 1, ... 374 'select', 1); 375 % Process: Detect other artifacts (Run02 only) 376 bst_process('CallProcess', 'process_evt_detect_badsegment', sFilesRun2, [], ... 377 'timewindow', [], ... 378 'sensortypes', 'MEG', ... 379 'threshold', 3, ... % 3 380 'isLowFreq', 1, ... 381 'isHighFreq', 1); 382 383 % Process: Rename event (1-7Hz > bad_1-7Hz) 384 bst_process('CallProcess', 'process_evt_rename', [sFilesRun1, sFilesRun2], [], ... 385 'src', '1-7Hz', ... 386 'dest', 'bad_1-7Hz'); 387 % Process: Rename event (40-240Hz > bad_40-240Hz) 388 bst_process('CallProcess', 'process_evt_rename', [sFilesRun1, sFilesRun2], [], ... 389 'src', '40-240Hz', ... 390 'dest', 'bad_40-240Hz'); 391 % Process: Snapshot: SSP projectors 392 bst_process('CallProcess', 'process_snapshot', [sFilesRun1, sFilesRun2], [], ... 393 'target', 2, ... % SSP projectors 394 'Comment', 'SSP projectors'); 395 396 397 398 %% ===== TUTORIAL #15: IMPORT EVENTS ================================================= 399 % =================================================================================== 400 disp([10 'DEMO> Tutorial #15: Import events' 10]); 401 % Process: Import MEG/EEG: Events (Run01) 402 sFilesEpochs1 = bst_process('CallProcess', 'process_import_data_event', sFilesRun1, [], ... 403 'subjectname', SubjectName, ... 404 'condition', '', ... 405 'eventname', 'standard, deviant', ... 406 'timewindow', [], ... 407 'epochtime', [-0.100, 0.500], ... 408 'createcond', 0, ... 409 'ignoreshort', 1, ... 410 'usectfcomp', 1, ... 411 'usessp', 1, ... 412 'freq', [], ... 413 'baseline', [-0.1, -0.0017]); 414 % Process: Import MEG/EEG: Events (Run02) 415 sFilesEpochs2 = bst_process('CallProcess', 'process_import_data_event', sFilesRun2, [], ... 416 'subjectname', SubjectName, ... 417 'condition', '', ... 418 'eventname', 'standard, deviant', ... 419 'timewindow', [], ... 420 'epochtime', [-0.100, 0.500], ... 421 'createcond', 0, ... 422 'ignoreshort', 1, ... 423 'usectfcomp', 1, ... 424 'usessp', 1, ... 425 'freq', [], ... 426 'baseline', [-0.1, -0.0017]); 427 % Display raster plot 428 hFigRaster = view_erpimage({sFilesEpochs1.FileName}, 'erpimage', 'MEG'); 429 panel_display(); 430 bst_report('Snapshot', hFigRaster, sFilesEpochs1(1).FileName, 'ERP image'); 431 close(hFigRaster); 432 433 434 %% ===== TUTORIAL #16: AVERAGE ======================================================= 435 % =================================================================================== 436 disp([10 'DEMO> Tutorial #16: Average' 10]); 437 % Process: Average: By trial group (folder average) 438 sFilesAvg = bst_process('CallProcess', 'process_average', [sFilesEpochs1, sFilesEpochs2], [], ... 439 'avgtype', 5, ... % By trial groups (folder average) 440 'avg_func', 1, ... % Arithmetic average: mean(x) 441 'weighted', 0, ... 442 'keepevents', 1); 443 % Process: Delete events 'cardiac' 444 bst_process('CallProcess', 'process_evt_delete', sFilesAvg, [], ... 445 'eventname', 'cardiac'); 446 % Process: Snapshot: Recordings time series 447 bst_process('CallProcess', 'process_snapshot', sFilesAvg, [], ... 448 'target', 5, ... % Recordings time series 449 'modality', 1, ... % MEG (All) 450 'Comment', 'Evoked response'); 451 % Set colormap: global color scale 452 bst_colormaps('SetMaxMode', 'meg', 'global'); 453 % Process: Snapshot: Recordings topography (contact sheet) 454 bst_process('CallProcess', 'process_snapshot', sFilesAvg, [], ... 455 'target', 7, ... % Recordings topography (contact sheet) 456 'modality', 1, ... % MEG 457 'contact_time', [0, 0.350], ... 458 'contact_nimage', 15, ... 459 'Comment', 'Evoked response'); 460 461 % Process: Average+Stderr: By trial group (subject average) 462 sFilesAvgAll = bst_process('CallProcess', 'process_average', [sFilesEpochs1, sFilesEpochs2], [], ... 463 'avgtype', 6, ... % By trial group (subject average) 464 'avg_func', 7, ... % Arithmetic average + Standard error 465 'weighted', 0, ... 466 'keepevents', 1); 467 % Process: Delete events 'cardiac' 468 bst_process('CallProcess', 'process_evt_delete', sFilesAvgAll, [], ... 469 'eventname', 'cardiac'); 470 % Process: Delete events 'saccade' 471 bst_process('CallProcess', 'process_evt_delete', sFilesAvgAll, [], ... 472 'eventname', 'saccade'); 473 % Process: Snapshot: Recordings time series 474 bst_process('CallProcess', 'process_snapshot', sFilesAvgAll, [], ... 475 'target', 5, ... % Recordings time series 476 'modality', 1, ... % MEG (All) 477 'Comment', 'Evoked response'); 478 479 480 %% ===== TUTORIAL #17: EXPLORATION =================================================== 481 % =================================================================================== 482 disp([10 'DEMO> Tutorial #17: Bad segments' 10]); 483 % View averages 484 hFigMeg1 = view_timeseries(sFilesAvg(1).FileName, 'MEG'); 485 hFigMeg2 = view_timeseries(sFilesAvg(2).FileName, 'MEG'); 486 hFigEeg1 = view_timeseries(sFilesAvg(1).FileName, 'Misc'); 487 hFigEeg2 = view_timeseries(sFilesAvg(2).FileName, 'Misc'); 488 hFigTopo1 = view_topography(sFilesAvg(1).FileName, 'MEG', '2DSensorCap'); 489 hFigTopo2 = view_topography(sFilesAvg(2).FileName, 'MEG', '2DSensorCap'); 490 hFigTp2 = view_topography(sFilesAvg(3).FileName, 'MEG', '3DSensorCap'); 491 hFigTp3 = view_topography(sFilesAvg(3).FileName, 'MEG', '2DDisc'); 492 hFigTp4 = view_topography(sFilesAvg(3).FileName, 'MEG', '2DLayout'); 493 % Set time: 90ms 494 panel_time('SetCurrentTime', 0.090); 495 % Set filters: 40Hz low-pass, no high-pass 496 panel_filter('SetFilters', 1, 40, 0, [], 0, [], 0, 0); 497 % View selected sensors 498 SelectedChannels = {'MLC31', 'MLC32'}; 499 bst_figures('SetSelectedRows', SelectedChannels); 500 view_timeseries(sFilesAvg(4).FileName, [], SelectedChannels); 501 % Select time window 502 figure_timeseries('SetTimeSelectionManual', hFigMeg1, [0.070, 0.130]); 503 % Show sensors on 2DSensorCap topography 504 isMarkers = 1; 505 isLabels = 0; 506 figure_3d('ViewSensors', hFigTopo1, isMarkers, isLabels); 507 % Display time contact sheet for a figure 508 pause(0.5); 509 hContactFig = view_contactsheet( hFigTopo2, 'time', 'fig', [], 12, [0 0.120] ); 510 pause(0.5); 511 close(hContactFig); 512 513 514 515 %% ===== TUTORIAL #18: COLORMAPS ===================================================== 516 % =================================================================================== 517 disp([10 'DEMO> Tutorial #18: Colormaps' 10]); 518 % Set 'Meg' colormap to 'jet' 519 bst_colormaps('SetColormapName', 'meg', 'jet'); 520 pause(0.5); 521 % Set 'Meg' colormap to 'rwb' 522 bst_colormaps('SetColormapName', 'meg', 'cmap_rbw'); 523 % Set colormap to display absolute values 524 bst_colormaps('SetColormapAbsolute', 'meg', 1); 525 % Normalize colormap for each time frame 526 bst_colormaps('SetMaxMode', 'meg', 'local'); 527 % Hide colorbar 528 bst_colormaps('SetDisplayColorbar', 'meg', 0); 529 pause(0.5); 530 % Restore colormap to default values 531 bst_colormaps('RestoreDefaults', 'meg'); 532 % Edit good/bad channel for current file 533 gui_edit_channelflag(sFilesAvg(1).FileName); 534 % Close figures 535 pause(0.5); 536 bst_memory('UnloadAll', 'Forced'); 537 538 539 540 %% ===== TUTORIAL #20: HEAD MODEL ==================================================== 541 % =================================================================================== 542 disp([10 'DEMO> Tutorial #20: Head model' 10]); 543 % Process: Compute head model 544 bst_process('CallProcess', 'process_headmodel', sFilesAvg, [], ... 545 'comment', '', ... 546 'sourcespace', 1, ... 547 'meg', 3); % Overlapping spheres 548 % Get study structure 549 sStudy = bst_get('Study', sFilesAvg(1).iStudy); 550 % Show spheres 551 hFig = view_spheres(sStudy.HeadModel(sStudy.iHeadModel).FileName, sStudy.Channel.FileName, sSubject); 552 pause(0.5); 553 close(hFig); 554 555 556 557 %% ===== TUTORIAL #21: NOISE COVARIANCE ============================================== 558 % =================================================================================== 559 disp([10 'DEMO> Tutorial #21: Noise covariance' 10]); 560 % Process: Compute covariance (noise or data) 561 bst_process('CallProcess', 'process_noisecov', sFilesNoise, [], ... 562 'baseline', [], ... 563 'sensortypes', 'MEG, EEG, SEEG, ECOG', ... 564 'target', 1, ... % Noise covariance (covariance over baseline time window) 565 'dcoffset', 1, ... % Block by block, to avoid effects of slow shifts in data 566 'identity', 0, ... 567 'copycond', 1, ... 568 'copysubj', 0, ... 569 'replacefile', 1); % Replace 570 % Process: Snapshot: Noise covariance 571 bst_process('CallProcess', 'process_snapshot', sFilesNoise, [], ... 572 'target', 3, ... % Noise covariance 573 'Comment', 'Noise covariance'); 574 575 % Process: Compute covariance (noise or data) [Run01] 576 bst_process('CallProcess', 'process_noisecov', sFilesEpochs1, [], ... 577 'baseline', [-0.1, -0.0017], ... 578 'datatimewindow', [0, 0.5], ... 579 'sensortypes', 'MEG, EEG, SEEG, ECOG', ... 580 'target', 2, ... % Data covariance (covariance over data time window) 581 'dcoffset', 1, ... % Block by block, to avoid effects of slow shifts in data 582 'identity', 0, ... 583 'copycond', 0, ... 584 'copysubj', 0, ... 585 'replacefile', 1); % Replace 586 % Process: Compute covariance (noise or data) [Run02] 587 bst_process('CallProcess', 'process_noisecov', sFilesEpochs2, [], ... 588 'baseline', [-0.1, -0.0017], ... 589 'datatimewindow', [0, 0.5], ... 590 'sensortypes', 'MEG, EEG, SEEG, ECOG', ... 591 'target', 2, ... % Data covariance (covariance over data time window) 592 'dcoffset', 1, ... % Block by block, to avoid effects of slow shifts in data 593 'identity', 0, ... 594 'copycond', 0, ... 595 'copysubj', 0, ... 596 'replacefile', 1); % Replace 597 % Process: Snapshot: Data covariance 598 bst_process('CallProcess', 'process_snapshot', [sFilesEpochs1(1), sFilesEpochs2(1)], [], ... 599 'target', 12, ... % Data covariance 600 'Comment', 'Data covariance'); 601 602 603 604 %% ===== TUTORIAL #22: SOURCE ESTIMATION ============================================= 605 % =================================================================================== 606 disp([10 'DEMO> Tutorial #22: Source estimation' 10]); 607 % === GET DEVIANT AVERAGE RUN01 === 608 % Process: Select recordings in: Subject01/S01_AEF_20131218_01_600Hz_notch 609 sFiles01 = bst_process('CallProcess', 'process_select_files_data', [], [], ... 610 'subjectname', SubjectName, ... 611 'condition', 'S01_AEF_20131218_01_600Hz_notch', ... 612 'includebad', 0); 613 % Process: Select file comments with tag: deviant 614 sFilesAvgDeviant01 = bst_process('CallProcess', 'process_select_tag', sFiles01, [], ... 615 'tag', 'Avg: deviant', ... 616 'search', 2, ... % Search the file comments 617 'select', 1); % Select only the files with the tag 618 619 % === CONSTRAINED EXAMPLE === 620 % Minimum norm options 621 InverseOptions = struct(... 622 'Comment', 'MN: MEG', ... 623 'InverseMethod', 'minnorm', ... 624 'InverseMeasure', 'amplitude', ... 625 'SourceOrient', {{'fixed'}}, ... 626 'Loose', 0.2, ... 627 'UseDepth', 1, ... 628 'WeightExp', 0.5, ... 629 'WeightLimit', 10, ... 630 'NoiseMethod', 'reg', ... 631 'NoiseReg', 0.1, ... 632 'SnrMethod', 'fixed', ... 633 'SnrRms', 0.001, ... 634 'SnrFixed', 3, ... 635 'ComputeKernel', 1, ... 636 'DataTypes', {{'MEG'}}); 637 % Process: Compute sources [2018] 638 sFilesSrcDeviant01 = bst_process('CallProcess', 'process_inverse_2018', sFilesAvgDeviant01, [], ... 639 'output', 2, ... % Kernel only: one per file 640 'inverse', InverseOptions); 641 642 % === DISPLAY SOURCES MANUALLY === 643 % View time series 644 hFigSrc1 = view_timeseries(sFilesAvgDeviant01(1).FileName, 'MEG'); 645 % View on the cortex surface 646 hFigSrc2 = script_view_sources(sFilesSrcDeviant01.FileName, 'cortex'); 647 % Set current time to 90ms 648 panel_time('SetCurrentTime', 0.090); 649 % Set orientation 650 figure_3d('SetStandardView', hFigSrc2, 'left'); 651 % Set surface threshold 652 iSurf = 1; 653 thresh = .30; 654 panel_surface('SetDataThreshold', hFigSrc2, iSurf, thresh); 655 % Set surface smoothing 656 panel_surface('SetSurfaceSmooth', hFigSrc2, iSurf, .6, 0); 657 % Show sulci 658 panel_surface('SetShowSulci', hFigSrc2, iSurf, 1); 659 660 % View sources on MRI (3D orthogonal slices) 661 hFigSrc3 = script_view_sources(sFilesSrcDeviant01.FileName, 'mri3d'); 662 panel_surface('SetDataThreshold', hFigSrc3, iSurf, thresh); 663 % Set the position of the cuts in the 3D figure 664 cutsPosVox = [74 93 159]; 665 panel_surface('PlotMri', hFigSrc3, cutsPosVox); 666 667 % View sources with MRI Viewer 668 hFigSrc4 = script_view_sources(sFilesSrcDeviant01.FileName, 'mriviewer'); 669 panel_surface('SetDataThreshold', hFigSrc4, iSurf, thresh); 670 % Set the position of the cuts in the MRI Viewer (values in millimeters) 671 figure_mri('SetLocation', 'voxel', hFigSrc4, [], cutsPosVox); 672 % Close figures 673 close([hFigSrc1 hFigSrc2 hFigSrc3 hFigSrc4]); 674 675 % === UNCONSTRAINED EXAMPLE === 676 % Unconstrained minnorm 677 InverseOptions.Comment = 'MN: MEG'; 678 InverseOptions.InverseMeasure = 'amplitude'; 679 InverseOptions.SourceOrient = {'free'}; 680 % Process: Compute sources [2018] 681 sFilesSrcUnconst = bst_process('CallProcess', 'process_inverse_2018', sFilesAvgDeviant01, [], ... 682 'output', 2, ... % Kernel only: one per file 683 'inverse', InverseOptions); 684 685 686 % === NORMALIZED SOURCES === 687 % dSPM 688 InverseOptions.Comment = 'dSPM: MEG'; 689 InverseOptions.InverseMeasure = 'dspm2018'; 690 InverseOptions.SourceOrient = {'fixed'}; 691 sFilesSrcDspm = bst_process('CallProcess', 'process_inverse_2018', sFilesAvgDeviant01, [], ... 692 'output', 2, ... % Kernel only: one per file 693 'inverse', InverseOptions); 694 % sLORETA (old function) 695 sFilesSrcSloreta = bst_process('CallProcess', 'process_inverse', sFilesAvgDeviant01, [], ... 696 'comment', '', ... 697 'method', 3, ... % sLORETA 698 'wmne', struct(... 699 'SourceOrient', {{'fixed'}}, ... 700 'loose', 0.2, ... 701 'SNR', 3, ... 702 'pca', 1, ... 703 'diagnoise', 0, ... 704 'regnoise', 1, ... 705 'magreg', 0.1, ... 706 'gradreg', 0.1, ... 707 'depth', 1, ... 708 'weightexp', 0.5, ... 709 'weightlimit', 10), ... 710 'sensortypes', 'MEG, MEG MAG, MEG GRAD, EEG', ... 711 'output', 2); % Kernel only: one per file 712 % Process: Z-score normalization: [-100ms,-2ms] 713 sFilesSrcZscore = bst_process('CallProcess', 'process_baseline_norm', sFilesSrcDeviant01, [], ... 714 'baseline', [-0.100, -0.002], ... 715 'source_abs', 0, ... 716 'method', 'zscore'); % Z-score transformation: x_std = (x - μ) / σ 717 718 % Process: Snapshot: Sources (one time) 719 bst_process('CallProcess', 'process_snapshot', sFilesSrcDeviant01, [], ... 720 'target', 8, ... % Sources (one time) 721 'orient', 1, ... % left 722 'time', 0.09, ... 723 'threshold', 30, ... 724 'Comment', 'Current density map (Constrained)'); 725 bst_process('CallProcess', 'process_snapshot', sFilesSrcDspm, [], ... 726 'target', 8, ... % Sources (one time) 727 'orient', 1, ... % left 728 'time', 0.09, ... 729 'threshold', 60, ... 730 'Comment', 'dSPM'); 731 bst_process('CallProcess', 'process_snapshot', sFilesSrcSloreta, [], ... 732 'target', 8, ... % Sources (one time) 733 'orient', 1, ... % left 734 'time', 0.09, ... 735 'threshold', 60, ... 736 'Comment', 'sLORETA'); 737 bst_process('CallProcess', 'process_snapshot', sFilesSrcZscore, [], ... 738 'target', 8, ... % Sources (one time) 739 'orient', 1, ... % left 740 'time', 0.09, ... 741 'threshold', 60, ... 742 'Comment', 'Z-score'); 743 bst_process('CallProcess', 'process_snapshot', sFilesSrcUnconst, [], ... 744 'target', 8, ... % Sources (one time) 745 'orient', 1, ... % left 746 'time', 0.0917, ... 747 'threshold', 0, ... 748 'Comment', 'Current density map (Unconstrained)'); 749 750 % === DELETE EXPERIMENTS === 751 % Process: Delete constrained example 752 bst_process('CallProcess', 'process_delete', [sFilesSrcDeviant01, sFilesSrcDspm, sFilesSrcSloreta, sFilesSrcZscore, sFilesSrcUnconst], [], ... 753 'target', 1); % Delete selected files 754 755 756 % === SHARED KERNEL === 757 % Constrained minnorm 758 InverseOptions.Comment = 'MN: MEG'; 759 InverseOptions.InverseMeasure = 'amplitude'; 760 InverseOptions.SourceOrient = {'fixed'}; 761 % Process: Compute sources [2018] 762 sFilesAvgSrc = bst_process('CallProcess', 'process_inverse_2018', sFilesAvg, [], ... 763 'output', 1, ... % Kernel only: shared 764 'inverse', InverseOptions); 765 766 767 % === AVERAGE SOURCES ACROSS RUNS === 768 % Process: Average: By trial group (subject average) 769 sFilesIntraSrc = bst_process('CallProcess', 'process_average', sFilesAvgSrc, [], ... 770 'avgtype', 6, ... % By trial group (subject average) 771 'avg_func', 1, ... % Arithmetic average: mean(x) 772 'weighted', 1, ... 773 'scalenormalized', 0); 774 % Process: Low-pass:40Hz 775 sFilesIntraSrcLow = bst_process('CallProcess', 'process_bandpass', sFilesIntraSrc, [], ... 776 'highpass', 0, ... 777 'lowpass', 40, ... 778 'attenuation', 'strict', ... % 60dB 779 'mirror', 0, ... 780 'overwrite', 0); 781 % Process: Z-score normalization: [-100ms,-2ms] 782 sFilesIntraZscore = bst_process('CallProcess', 'process_baseline_norm', sFilesIntraSrcLow, [], ... 783 'baseline', [-0.100, -0.0017], ... 784 'source_abs', 0, ... 785 'method', 'zscore'); % Z-score transformation: x_std = (x - μ) / σ 786 787 % Process: Delete intermediate results 788 bst_process('CallProcess', 'process_delete', sFilesIntraSrcLow, [], ... 789 'target', 1); % Delete selected files 790 % Screen captures 791 bst_process('CallProcess', 'process_snapshot', sFilesIntraZscore, [], ... 792 'target', 8, ... % Sources (one time) 793 'orient', 1, ... % left 794 'time', 0.09, ... 795 'threshold', 40, ... 796 'Comment', 'Average across runs (left)'); 797 bst_process('CallProcess', 'process_snapshot', sFilesIntraZscore, [], ... 798 'target', 8, ... % Sources (one time) 799 'orient', 2, ... % right 800 'time', 0.09, ... 801 'threshold', 40, ... 802 'Comment', 'Average across runs (right)'); 803 bst_process('CallProcess', 'process_snapshot', sFilesIntraZscore(1), [], ... 804 'target', 9, ... % Sources (contact sheet) 805 'orient', 1, ... % left 806 'contact_time', [0, 0.35], ... 807 'contact_nimage', 15, ... 808 'threshold', 20, ... 809 'Comment', 'Average across runs'); 810 811 812 %% ===== TUTORIAL #23: SCOUTS ======================================================== 813 % =================================================================================== 814 disp([10 'DEMO> Tutorial #23: Scouts' 10]); 815 % Load surface file 816 sCortex = in_tess_bst(CortexFile); 817 % Add new scouts in first atlas 818 sCortex.iAtlas = find(strcmpi({sCortex.Atlas.Name}, 'Destrieux')); 819 % Save file 820 bst_save(file_fullpath(CortexFile), sCortex, 'v7'); 821 % Unload everything 822 bst_memory('UnloadAll', 'Forced'); 823 % Find scouts indices to display: {'A1L', 'A1R', 'IFGL', 'M1L'} 824 [tmp,iScouts,tmp] = intersect({sCortex.Atlas(sCortex.iAtlas).Scouts.Label}, {'G_temp_sup-G_T_transv L', 'G_temp_sup-G_T_transv R', 'G_front_inf-Opercular L', 'G_precentral L'}); 825 826 % View cortex 827 hFigSurf1 = view_surface(CortexFile, [], [], 'NewFigure'); 828 hFigSurf2 = view_surface(CortexFile, [], [], 'NewFigure'); 829 figure_3d('SetStandardView', hFigSurf1, 'left'); 830 figure_3d('SetStandardView', hFigSurf2, 'right'); 831 panel_surface('SetSurfaceSmooth', hFigSurf1, 1, .6, 0); 832 panel_surface('SetSurfaceSmooth', hFigSurf2, 1, .6, 0); 833 panel_surface('SetShowSulci', hFigSurf1, 1, 1); 834 panel_surface('SetShowSulci', hFigSurf2, 1, 1); 835 % Configure scouts display 836 panel_scout('SetScoutsOptions', 0, 1, 1, 'all', 0.7, 1, 1, 0); 837 % View scouts 838 hFigScouts = view_scouts({sFilesIntraZscore.FileName}, iScouts); 839 hLegend = findobj(hFigScouts, 'Type', 'legend'); 840 if ~isempty(hLegend) && ishandle(hLegend(1)) 841 set(hLegend(1), 'Units', 'pixels'); 842 pos = get(hLegend(1), 'Position'); 843 set(hLegend(1), 'Position', [1, 1, pos(3), pos(4)]); 844 end 845 % Save figures 846 bst_report('Snapshot', hFigScouts, sFilesIntraZscore(1).FileName, 'Scouts', [100 100 670 250]); 847 % Close all 848 pause(1); 849 bst_memory('UnloadAll', 'Forced'); 850 851 852 853 %% ===== TUTORIAL #24: TIME-FREQUENCY ================================================ 854 % =================================================================================== 855 disp([10 'DEMO> Tutorial #24: Time-frequency' 10]); 856 % Process: Simulate generic signals 857 sSim = bst_process('CallProcess', 'process_simulate_matrix', [], [], ... 858 'subjectname', 'Test', ... 859 'condition', 'Simulation', ... 860 'samples', 6000, ... 861 'srate', 1000, ... 862 'matlab', ['f1 = 2; f2 = 20; f3 = 50;' 10 'i =2000:6000;' 10 'Data(1,i) = sin(f1*2*pi*t(i)) + 0.4 * cos(f2*2*pi*t(i));' 10 'Data = Data + 0.2 * sin(f3*2*pi*t) + 0.4 * rand(1,6000);']); 863 864 % Time-frequency options 865 TfOptions = struct(... 866 'Comment', 'Power,1-60Hz', ... 867 'TimeBands', [], ... 868 'Freqs', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60], ... 869 'MorletFc', 1, ... 870 'MorletFwhmTc', 3, ... 871 'ClusterFuncTime', 'none', ... 872 'Measure', 'power', ... 873 'Output', 'average', ... 874 'SaveKernel', 0); 875 % Process: Time-frequency (Morlet wavelets) 876 sSimTf1 = bst_process('CallProcess', 'process_timefreq', sSim, [], ... 877 'edit', TfOptions, ... 878 'normalize', 'multiply'); % 1/f compensation: Multiply output values by frequency 879 880 % === NORMALIZATION === 881 % Process: Time-frequency (Morlet wavelets) 882 sSimTf2 = bst_process('CallProcess', 'process_timefreq', sSim, [], ... 883 'edit', TfOptions, ... 884 'normalize', 'none'); % None: Save non-standardized time-frequency maps 885 % Process: Spectral flattening 886 sSimTf2Multi = bst_process('CallProcess', 'process_tf_norm', sSimTf2, [], ... 887 'normalize', 'multiply', ... % 1/f compensation (multiple by frequency) 888 'overwrite', 0); 889 % Process: Event-related perturbation (ERS/ERD): [750ms,1250ms] 890 sSimTf2Ersd = bst_process('CallProcess', 'process_baseline_norm', sSimTf2, [], ... 891 'baseline', [0.75, 1.25], ... 892 'method', 'ersd', ... % Event-related perturbation (ERS/ERD): x_std = (x - μ) / μ * 100 893 'overwrite', 0); 894 895 % Process: Snapshot: Time-frequency maps 896 bst_process('CallProcess', 'process_snapshot', sSimTf2, [], ... 897 'target', 14, ... % Time-frequency maps 898 'Comment', 'Not normalized'); 899 % Process: Snapshot: Time-frequency maps 900 bst_process('CallProcess', 'process_snapshot', sSimTf2Multi, [], ... 901 'target', 14, ... % Time-frequency maps 902 'Comment', 'Spectral flattening: 1/f compensation'); 903 % Process: Snapshot: Time-frequency maps 904 bst_process('CallProcess', 'process_snapshot', sSimTf2Ersd, [], ... 905 'target', 14, ... % Time-frequency maps 906 'Comment', 'ERS/ERD'); 907 % Spectrum/Time series 908 hFigTf1 = view_spectrum(sSimTf2.FileName, 'Spectrum'); 909 hFigTf2 = view_spectrum(sSimTf2.FileName, 'TimeSeries'); 910 panel_time('SetCurrentTime', 0.5); 911 panel_freq('SetCurrentFreq', 2, 0); 912 bst_report('Snapshot', [hFigTf1 hFigTf2], sSimTf2.FileName, 'Not normalized: 2s/20Hz', [200, 200, 400, 250]); 913 panel_time('SetCurrentTime', 2.02); 914 panel_freq('SetCurrentFreq', 20, 0); 915 bst_report('Snapshot', [hFigTf1 hFigTf2], sSimTf2.FileName, 'Not normalized: 2s/20Hz', [200, 200, 400, 250]); 916 bst_memory('UnloadAll', 'Forced'); 917 918 919 % === HILBERT TRANSFORM === 920 % Process: Hilbert transform 921 sSimHilbert = bst_process('CallProcess', 'process_hilbert', sSim, [], ... 922 'edit', struct(... 923 'Comment', 'Power', ... 924 'TimeBands', [], ... 925 'Freqs', {{'delta', '2, 4', 'mean'; 'theta', '5, 7', 'mean'; 'alpha', '8, 12', 'mean'; 'beta', '15, 29', 'mean'; 'gamma1', '30, 59', 'mean'; 'gamma2', '60, 90', 'mean'}}, ... 926 'ClusterFuncTime', 'none', ... 927 'Measure', 'power', ... 928 'Output', 'all', ... 929 'SaveKernel', 0), ... 930 'normalize', 'none', ... % None: Save non-standardized time-frequency maps 931 'mirror', 0); 932 % Process: Spectral flattening 933 sSimHilbertMulti = bst_process('CallProcess', 'process_tf_norm', sSimHilbert, [], ... 934 'normalize', 'multiply', ... % 1/f compensation (multiple by frequency) 935 'overwrite', 0); 936 % Process: Event-related perturbation (ERS/ERD): [750ms,1250ms] 937 sSimHilbertErsd = bst_process('CallProcess', 'process_baseline_norm', sSimHilbert, [], ... 938 'baseline', [0.75, 1.25], ... 939 'method', 'ersd', ... % Event-related perturbation (ERS/ERD): x_std = (x - μ) / μ * 100 940 'overwrite', 0); 941 942 % Process: Snapshot: Time-frequency maps 943 bst_process('CallProcess', 'process_snapshot', sSimHilbert, [], ... 944 'target', 14, ... % Time-frequency maps 945 'Comment', 'Not normalized'); 946 % Process: Snapshot: Time-frequency maps 947 bst_process('CallProcess', 'process_snapshot', sSimHilbertMulti, [], ... 948 'target', 14, ... % Time-frequency maps 949 'Comment', 'Spectral flattening: 1/f compensation'); 950 % Process: Snapshot: Time-frequency maps 951 bst_process('CallProcess', 'process_snapshot', sSimHilbertErsd, [], ... 952 'target', 14, ... % Time-frequency maps 953 'Comment', 'ERS/ERD'); 954 955 % === SINGLE TRIALS === 956 TfOptions.Comment = 'Avg,Power,1-150Hz'; 957 TfOptions.Freqs = [1, 2, 3.1, 4.2, 5.4, 6.7, 8, 9.5, 11, 12.6, 14.3, 16.1, 18.1, 20.1, 22.3, 24.6, 27, 29.6, 32.4, 35.3, 38.4, 41.6, 45.1, 48.8, 52.7, 56.9, 61.3, 66, 70.9, 76.2, 81.8, 87.7, 94, 100.6, 107.7, 115.2, 123.1, 131.6, 140.5, 150]; 958 % Process: Time-frequency (Morlet wavelets) 959 sEpochsAvgTf = bst_process('CallProcess', 'process_timefreq', sFilesEpochs1, [], ... 960 'sensortypes', 'MEG, EEG', ... 961 'edit', TfOptions, ... 962 'normalize', 'none'); % None: Save non-standardized time-frequency maps 963 % Process: Event-related perturbation (ERS/ERD): [-75ms,0ms] 964 sEpochsAvgTfErsd = bst_process('CallProcess', 'process_baseline_norm', sEpochsAvgTf, [], ... 965 'baseline', [-0.075, 0], ... 966 'method', 'ersd', ... % Event-related perturbation (ERS/ERD): x_std = (x - μ) / μ * 100 967 'overwrite', 0); 968 969 % === DISPLAY === 970 % View time-frequency file 971 hFigTf1 = view_timefreq(sEpochsAvgTfErsd.FileName, 'SingleSensor'); 972 % Configure display 973 sOptions = panel_display('GetDisplayOptions'); 974 sOptions.HideEdgeEffects = 1; 975 sOptions.HighResolution = 1; 976 panel_display('SetDisplayOptions', sOptions); 977 % Other display modes 978 hFigTf2 = view_timefreq(sEpochsAvgTfErsd.FileName, 'AllSensors'); 979 hFigTf3 = view_timefreq(sEpochsAvgTfErsd.FileName, '2DLayout'); 980 hFigTf4 = view_timefreq(sEpochsAvgTfErsd.FileName, '2DLayoutOpt'); 981 bst_colormaps('SetColormapName', 'stat2', 'jet'); 982 bst_colormaps('SetColormapAbsolute', 'stat2', 1); 983 bst_report('Snapshot', hFigTf1, sEpochsAvgTfErsd.FileName, 'Time-frequency', [200, 200, 400, 250]); 984 bst_report('Snapshot', [hFigTf2 hFigTf3 hFigTf4], sEpochsAvgTfErsd.FileName, 'Time-frequency', [200, 200, 750, 400]); 985 close([hFigTf1 hFigTf2 hFigTf3 hFigTf4]); 986 % Image [channel x time] 987 hFigTf5 = view_erpimage(sEpochsAvgTfErsd.FileName, 'trialimage'); 988 % Topographies 989 hFigTf6 = view_topography(sEpochsAvgTfErsd.FileName, 'MEG', '3DSensorCap'); 990 hFigTf7 = view_topography(sEpochsAvgTfErsd.FileName, 'MEG', '2DDisc'); 991 hFigTf8 = view_topography(sEpochsAvgTfErsd.FileName, 'MEG', '2DSensorCap'); 992 hFigTf9 = view_topography(sEpochsAvgTfErsd.FileName, 'MEG', '2DLayout'); 993 panel_time('SetCurrentTime', 0.175); 994 panel_freq('SetCurrentFreq', 8, 0); 995 bst_report('Snapshot', [hFigTf5 hFigTf6 hFigTf7 hFigTf8 hFigTf9], sEpochsAvgTfErsd.FileName, 'Time-frequency: 8Hz', [200, 200, 400, 250]); 996 close([hFigTf5 hFigTf6 hFigTf7 hFigTf8 hFigTf9]); 997 998 999 % === AVERAGE FOR SCOUTS === 1000 % Select all sources for the single deviant epochs 1001 sFilesEpochDeviantSrc = bst_process('CallProcess', 'process_select_files_results', [], [], ... 1002 'subjectname', SubjectName, ... 1003 'condition', '', ... 1004 'includebad', 0); 1005 sFilesEpochDeviantSrc = bst_process('CallProcess', 'process_select_tag', sFilesEpochDeviantSrc, [], ... 1006 'tag', 'deviant', ... 1007 'search', 1, ... % Search the file names 1008 'select', 1); % Select only the files with the tag 1009 sFilesEpochDeviantSrc = bst_process('CallProcess', 'process_select_tag', sFilesEpochDeviantSrc, [], ... 1010 'tag', 'average', ... 1011 'search', 1, ... % Search the file names 1012 'select', 2); % Exclude the files with the tag 1013 1014 % Process: Time-frequency (Morlet wavelets) 1015 sFilesTfScout = bst_process('CallProcess', 'process_timefreq', sFilesEpochDeviantSrc, [], ... 1016 'clusters', {'Destrieux', {'G_temp_sup-G_T_transv L', 'G_temp_sup-G_T_transv R', 'G_front_inf-Opercular L', 'G_precentral L'}}, ... 1017 'scoutfunc', 1, ... % Mean 1018 'edit', struct(... 1019 'Comment', 'Deviant: Scouts,Avg,Power,1-150Hz', ... 1020 'TimeBands', [], ... 1021 'Freqs', [1, 2, 3.1, 4.2, 5.4, 6.7, 8, 9.5, 11, 12.6, 14.3, 16.1, 18.1, 20.1, 22.3, 24.6, 27, 29.6, 32.4, 35.3, 38.4, 41.6, 45.1, 48.8, 52.7, 56.9, 61.3, 66, 70.9, 76.2, 81.8, 87.7, 94, 100.6, 107.7, 115.2, 123.1, 131.6, 140.5, 150], ... 1022 'MorletFc', 1, ... 1023 'MorletFwhmTc', 3, ... 1024 'ClusterFuncTime', 'after', ... 1025 'Measure', 'power', ... 1026 'Output', 'average', ... 1027 'SaveKernel', 0), ... 1028 'normalize', 'none'); % None: Save non-standardized time-frequency maps) 1029 % Process: Event-related perturbation (ERS/ERD): [-75ms,0ms] 1030 sFilesTfScoutErsd = bst_process('CallProcess', 'process_baseline_norm', sFilesTfScout, [], ... 1031 'baseline', [-0.075, 0], ... 1032 'method', 'ersd', ... % Event-related perturbation (ERS/ERD): x_std = (x - μ) / μ * 100 1033 'overwrite', 0); 1034 % Process: Snapshot: Time-frequency maps 1035 bst_process('CallProcess', 'process_snapshot', sFilesTfScoutErsd, [], ... 1036 'target', 14, ... % Time-frequency maps 1037 'Comment', 'ERS/ERD'); 1038 1039 1040 % === FULL CORTEX / HILBERT === 1041 % Process: Hilbert transform 1042 sFilesHilbertCortex = bst_process('CallProcess', 'process_hilbert', sFilesEpochDeviantSrc, [], ... 1043 'clusters', {}, ... 1044 'scoutfunc', 1, ... % Mean 1045 'edit', struct(... 1046 'Comment', 'Deviant: Avg,Magnitude', ... 1047 'TimeBands', [], ... 1048 'Freqs', {{'delta', '2, 4', 'mean'; 'theta', '5, 7', 'mean'; 'alpha', '8, 12', 'mean'; 'beta', '15, 29', 'mean'; 'gamma1', '30, 59', 'mean'; 'gamma2', '60, 90', 'mean'}}, ... 1049 'ClusterFuncTime', 'none', ... 1050 'Measure', 'power', ... 1051 'Output', 'average', ... 1052 'RemoveEvoked', 0, ... 1053 'SaveKernel', 0), ... 1054 'normalize', 'none', ... % None: Save non-standardized time-frequency maps 1055 'mirror', 0); 1056 % Process: Event-related perturbation (ERS/ERD): [-75ms,0ms] 1057 sFilesHilbertCortexErsd = bst_process('CallProcess', 'process_baseline_norm', sFilesHilbertCortex, [], ... 1058 'baseline', [-0.075, 0], ... 1059 'method', 'ersd', ... % Event-related perturbation (ERS/ERD): x_std = (x - μ) / μ * 100 1060 'overwrite', 0); 1061 1062 % View results 1063 hFigTf1 = view_surface_data([], sFilesHilbertCortexErsd.FileName); 1064 hFigTf2 = view_timefreq(sFilesHilbertCortexErsd.FileName, 'SingleSensor', 362); 1065 figure_3d('SetStandardView', hFigTf1, 'left'); 1066 panel_surface('SetDataThreshold', hFigTf1, 1, 0.5); 1067 panel_time('SetCurrentTime', 0.175); 1068 panel_freq('SetCurrentFreq', 3); 1069 bst_colormaps('RestoreDefaults', 'stat2'); 1070 bst_report('Snapshot', [hFigTf1 hFigTf2], sFilesHilbertCortexErsd.FileName, 'Hilbert transform: Alpha band', [200, 200, 400, 250]); 1071 bst_memory('UnloadAll', 'Forced'); 1072 1073 1074 %% ===== TUTORIAL #25: DIFFRERENCE =================================================== 1075 % =================================================================================== 1076 disp([10 'DEMO> Tutorial #25: Difference' 10]); 1077 1078 % ===== SELECT TRIALS (DATA) ===== 1079 % Process: Select recordings in: Subject01/* 1080 sFilesAll = bst_process('CallProcess', 'process_select_files_data', [], [], ... 1081 'subjectname', SubjectName, ... 1082 'condition', '', ... 1083 'includebad', 0); 1084 % Process: Select file names with tag: deviant_trial 1085 sEpochDeviant = bst_process('CallProcess', 'process_select_tag', sFilesAll, [], ... 1086 'tag', 'deviant_trial', ... 1087 'search', 1, ... % Search the file names 1088 'select', 1); % Select only the files with the tag 1089 % Process: Select file names with tag: standard_trial 1090 sEpochStandard = bst_process('CallProcess', 'process_select_tag', sFilesAll, [], ... 1091 'tag', 'standard_trial', ... 1092 'search', 1, ... % Search the file names 1093 'select', 1); % Select only the files with the tag 1094 1095 % ===== SELECT TRIALS (SOURCE) ===== 1096 % Process: Select recordings in: Subject01/* 1097 sFilesAllSrc = bst_process('CallProcess', 'process_select_files_results', [], [], ... 1098 'subjectname', SubjectName, ... 1099 'condition', '', ... 1100 'includebad', 0); 1101 % Process: Select file names with tag: deviant_trial 1102 sEpochDeviantSrc = bst_process('CallProcess', 'process_select_tag', sFilesAllSrc, [], ... 1103 'tag', 'deviant_trial', ... 1104 'search', 1, ... % Search the file names 1105 'select', 1); % Select only the files with the tag 1106 % Process: Select file names with tag: standard_trial 1107 sEpochStandardSrc = bst_process('CallProcess', 'process_select_tag', sFilesAllSrc, [], ... 1108 'tag', 'standard_trial', ... 1109 'search', 1, ... % Search the file names 1110 'select', 1); % Select only the files with the tag 1111 1112 % ===== ABSOLUTE DIFFERENCE ====== 1113 % Process: Difference: A-B, abs 1114 sDiffSrc = bst_process('CallProcess', 'process_diff_ab', sFilesIntraSrc(1).FileName, sFilesIntraSrc(2).FileName, ... 1115 'source_abs', 1); 1116 % Process: Set comment: deviant|abs - standard|abs 1117 sDiffSrc = bst_process('CallProcess', 'process_set_comment', sDiffSrc, [], ... 1118 'tag', 'deviant|abs - standard|abs', ... 1119 'isindex', 1); 1120 % Process: Low-pass:40Hz 1121 sDiffSrcZscore = bst_process('CallProcess', 'process_bandpass', sDiffSrc, [], ... 1122 'highpass', 0, ... 1123 'lowpass', 40, ... 1124 'attenuation', 'strict', ... % 60dB 1125 'mirror', 0, ... 1126 'overwrite', 1); 1127 % Process: Z-score transformation: [-100ms,-2ms] 1128 sDiffSrcZscore = bst_process('CallProcess', 'process_baseline_norm', sDiffSrcZscore, [], ... 1129 'baseline', [-0.1, -0.002], ... 1130 'source_abs', 0, ... 1131 'method', 'zscore', ... % Z-score transformation: x_std = (x - μ) / σ 1132 'overwrite', 0); 1133 % Process: Snapshot: Sources (contact sheet) 1134 bst_process('CallProcess', 'process_snapshot', sDiffSrcZscore, [], ... 1135 'target', 9, ... % Sources (contact sheet) 1136 'modality', 1, ... % MEG (All) 1137 'orient', 1, ... % left 1138 'contact_time', [0, 0.35], ... 1139 'contact_nimage', 15, ... 1140 'threshold', 30, ... 1141 'Comment', 'Difference deviant - standard (absolute)'); 1142 1143 % ===== RELATIVE DIFFERENCE ===== 1144 % Process: Difference: A-B 1145 sDiffSrcRel = bst_process('CallProcess', 'process_diff_ab', sFilesIntraSrc(1).FileName, sFilesIntraSrc(2).FileName, ... 1146 'source_abs', 0); 1147 % Process: Set comment: deviant - standard 1148 sDiffSrcRel = bst_process('CallProcess', 'process_set_comment', sDiffSrcRel, [], ... 1149 'tag', 'deviant - standard', ... 1150 'isindex', 1); 1151 % Process: Low-pass:40Hz 1152 sDiffSrcRelZscore = bst_process('CallProcess', 'process_bandpass', sDiffSrcRel, [], ... 1153 'highpass', 0, ... 1154 'lowpass', 40, ... 1155 'attenuation', 'strict', ... % 60dB 1156 'mirror', 0, ... 1157 'overwrite', 1); 1158 % Process: Z-score transformation: [-100ms,-2ms] 1159 sDiffSrcRelZscore = bst_process('CallProcess', 'process_baseline_norm', sDiffSrcRelZscore, [], ... 1160 'baseline', [-0.1, -0.002], ... 1161 'source_abs', 0, ... 1162 'method', 'zscore', ... % Z-score transformation: x_std = (x - μ) / σ 1163 'overwrite', 0); 1164 % Configure colormap: hot/absolute 1165 bst_colormaps('SetColormapName', 'stat2', 'hot'); 1166 bst_colormaps('SetColormapAbsolute', 'stat2', 1); 1167 % Process: Snapshot: Sources (contact sheet) 1168 bst_process('CallProcess', 'process_snapshot', sDiffSrcRelZscore, [], ... 1169 'target', 9, ... % Sources (contact sheet) 1170 'modality', 1, ... % MEG (All) 1171 'orient', 1, ... % left 1172 'contact_time', [0, 0.35], ... 1173 'contact_nimage', 15, ... 1174 'threshold', 30, ... 1175 'Comment', 'Difference deviant - standard (relative)'); 1176 % Restore colormap: rwb/relative 1177 bst_colormaps('SetColormapName', 'stat2', 'cmap_rbw'); 1178 bst_colormaps('SetColormapAbsolute', 'stat2', 0); 1179 1180 % ===== DIFFERENCE OF MEANS ===== 1181 % Process: Select uniform number of files [uniform] 1182 [sEpochDeviantUni, sEpochStandardUni] = bst_process('CallProcess', 'process_select_uniform2', sEpochDeviant, sEpochStandard, ... 1183 'nfiles', 0, ... 1184 'method', 4); % Uniformly distributed 1185 % Process: Difference of means [mean] 1186 sDiffMean = bst_process('CallProcess', 'process_diff_mean', sEpochDeviantUni, sEpochStandardUni, ... 1187 'avg_func', 1, ... % Arithmetic average mean(A) - mean(B) 1188 'weighted', 0); 1189 % Process: Snapshot: Recordings time series 1190 bst_process('CallProcess', 'process_snapshot', sDiffMean, [], ... 1191 'target', 5, ... % Recordings time series 1192 'modality', 1, ... % MEG (All) 1193 'Comment', 'Difference of means'); 1194 1195 1196 1197 %% ===== TUTORIAL #26: STATISTICS ==================================================== 1198 % =================================================================================== 1199 disp([10 'DEMO> Tutorial #26: Statistics' 10]); 1200 % ===== HISTOGRAMS ===== 1201 % Process: Extract values: [160ms] MLP57 1202 sHistoDeviant = bst_process('CallProcess', 'process_extract_values', sEpochDeviant, [], ... 1203 'timewindow', [0.16, 0.16], ... 1204 'sensortypes', 'MLP57', ... 1205 'isabs', 0, ... 1206 'avgtime', 0, ... 1207 'avgrow', 0, ... 1208 'dim', 2, ... % Concatenate time (dimension 2) 1209 'Comment', ''); 1210 % Process: Extract values: [160ms] MLP57 1211 sHistoStandard = bst_process('CallProcess', 'process_extract_values', sEpochStandard, [], ... 1212 'timewindow', [0.16, 0.16], ... 1213 'sensortypes', 'MLP57', ... 1214 'isabs', 0, ... 1215 'avgtime', 0, ... 1216 'avgrow', 0, ... 1217 'dim', 2, ... % Concatenate time (dimension 2) 1218 'Comment', ''); 1219 % Display histograms 1220 hFigHisto = view_histogram({sHistoDeviant.FileName, sHistoStandard.FileName}); 1221 bst_report('Snapshot', hFigHisto, sHistoDeviant.FileName, 'Histograms for MLP57/160ms'); 1222 close(hFigHisto); 1223 1224 % ===== EXEMPLE #1: PARAMETRIC/DATA ===== 1225 % Process: t-test [equal] [-100ms,500ms] H0:(A-B = 0) 1226 sTestParamData = bst_process('CallProcess', 'process_test_parametric2', sEpochDeviant, sEpochStandard, ... 1227 'timewindow', [-0.1, 0.5], ... 1228 'sensortypes', '', ... 1229 'isabs', 0, ... 1230 'avgtime', 0, ... 1231 'avgrow', 0, ... 1232 'Comment', '', ... 1233 'test_type', 'ttest_equal', ... % Student's t-test (equal variance) t = (mean(A)-mean(B)) / (Sx * sqrt(1/nA + 1/nB))Sx = sqrt(((nA-1)*var(A) + (nB-1)*var(B)) / (nA+nB-2)) df = nA + nB - 2 1234 'tail', 'two'); % Two-tailed 1235 % Set display properties 1236 StatThreshOptions = bst_get('StatThreshOptions'); 1237 StatThreshOptions.pThreshold = 0.05; 1238 StatThreshOptions.Correction = 'fdr'; 1239 StatThreshOptions.Control = [1 2 3]; 1240 bst_set('StatThreshOptions', StatThreshOptions); 1241 % Process: Snapshot: Recordings time series 1242 bst_process('CallProcess', 'process_snapshot', sTestParamData, [], ... 1243 'target', 5, ... % Recordings time series 1244 'modality', 1, ... % MEG (All) 1245 'time', 0.16, ... 1246 'Comment', 'Parametric t-test (p<0.05, FDR)'); 1247 % Process: Snapshot: Recordings topography (one time) 1248 bst_process('CallProcess', 'process_snapshot', sTestParamData, [], ... 1249 'target', 6, ... % Recordings topography (one time) 1250 'modality', 1, ... % MEG (All) 1251 'time', 0.16, ... 1252 'Comment', 'Parametric t-test (p<0.05, FDR)'); 1253 1254 % ===== EXEMPLE #2: NON-PARAMETRIC/DATA ===== 1255 % Process: Perm t-test equal [-100ms,500ms MEG] H0:(A=B), H1:(A<>B) 1256 sTestPermData = bst_process('CallProcess', 'process_test_permutation2', sEpochDeviant, sEpochStandard, ... 1257 'timewindow', [-0.1, 0.5], ... 1258 'sensortypes', 'MEG', ... 1259 'isabs', 0, ... 1260 'avgtime', 0, ... 1261 'avgrow', 0, ... 1262 'iszerobad', 1, ... 1263 'Comment', '', ... 1264 'test_type', 'ttest_equal', ... % Student's t-test (equal variance) t = (mean(A)-mean(B)) / (Sx * sqrt(1/nA + 1/nB))Sx = sqrt(((nA-1)*var(A) + (nB-1)*var(B)) / (nA+nB-2)) 1265 'randomizations', 1000, ... 1266 'tail', 'two'); % Two-tailed 1267 % Process: Snapshot: Recordings time series 1268 bst_process('CallProcess', 'process_snapshot', sTestPermData, [], ... 1269 'target', 5, ... % Recordings time series 1270 'modality', 1, ... % MEG (All) 1271 'time', 0.16, ... 1272 'Comment', 'Non-parametric t-test (p<0.05, FDR)'); 1273 % Process: Snapshot: Recordings topography (one time) 1274 bst_process('CallProcess', 'process_snapshot', sTestPermData, [], ... 1275 'target', 6, ... % Recordings topography (one time) 1276 'modality', 1, ... % MEG (All) 1277 'time', 0.16, ... 1278 'Comment', 'Non-parametric t-test (p<0.05, FDR)'); 1279 1280 % ===== EXEMPLE #3: CLUSTER/DATA ===== 1281 % Process: FT t-test unequal cluster [-100ms,500ms MEG] H0:(A=B), H1:(A<>B) 1282 sTestClustData = bst_process('CallProcess', 'process_ft_timelockstatistics', sEpochDeviant, sEpochStandard, ... 1283 'sensortypes', 'MEG', ... 1284 'timewindow', [-0.1, 0.5], ... 1285 'isabs', 0, ... 1286 'avgtime', 0, ... 1287 'avgchan', 0, ... 1288 'randomizations', 1000, ... 1289 'statistictype', 1, ... % Independent t-test 1290 'tail', 'two', ... % Two-tailed 1291 'correctiontype', 2, ... % cluster 1292 'minnbchan', 0, ... 1293 'clusteralpha', 0.05); 1294 % Process: Snapshot: Recordings time series 1295 bst_process('CallProcess', 'process_snapshot', sTestClustData, [], ... 1296 'target', 5, ... % Recordings time series 1297 'time', 0.16, ... 1298 'modality', 1, ... % MEG (All) 1299 'Comment', 'Cluster-based permutation test'); 1300 % Process: Snapshot: Recordings topography (one time) 1301 bst_process('CallProcess', 'process_snapshot', sTestClustData, [], ... 1302 'target', 6, ... % Recordings topography (one time) 1303 'modality', 1, ... % MEG (All) 1304 'time', 0.16, ... 1305 'Comment', 'Cluster-based permutation test'); 1306 1307 % ===== EXAMPLE #4: PARAMETRIC/SOURCES ===== 1308 % Process: t-test [equal] [-100ms,500ms] H0:(A-B = 0) 1309 sTestParamSrc = bst_process('CallProcess', 'process_test_parametric2', sEpochDeviantSrc, sEpochStandardSrc, ... 1310 'timewindow', [-0.1, 0.5], ... 1311 'scoutsel', {}, ... 1312 'scoutfunc', 1, ... % Mean 1313 'isnorm', 0, ... 1314 'avgtime', 0, ... 1315 'Comment', '', ... 1316 'test_type', 'ttest_equal', ... % Student's t-test (equal variance) t = (mean(A)-mean(B)) / (Sx * sqrt(1/nA + 1/nB))Sx = sqrt(((nA-1)*var(A) + (nB-1)*var(B)) / (nA+nB-2)) df = nA + nB - 2 1317 'tail', 'two'); % Two-tailed 1318 % Process: Difference of means [abs(mean)] 1319 sDiffMeanSrc = bst_process('CallProcess', 'process_diff_mean', sEpochDeviantSrc, sEpochStandardSrc, ... 1320 'avg_func', 2, ... % Absolute value of average abs(mean(A)) - abs(mean(B)) 1321 'weighted', 0); 1322 % Process: Apply statistic threshold: p<0.05 (FDR:1,2,3) 1323 sDiffMeanSrcThresh = bst_process('CallProcess', 'process_extract_pthresh2', sTestParamSrc, sDiffMeanSrc, ... 1324 'pthresh', 0.05, ... 1325 'correction', 3, ... % False discovery rate (FDR) 1326 'control1', 1, ... 1327 'control2', 1, ... 1328 'control3', 1); 1329 % Process: Snapshot: Sources (one time) 1330 bst_process('CallProcess', 'process_snapshot', sTestParamSrc, [], ... 1331 'target', 8, ... % Sources (one time) 1332 'orient', 1, ... % left 1333 'time', 0.148, ... 1334 'threshold', 40, ... 1335 'Comment', 'Parametric t-test (p<0.05, FDR)'); 1336 % Process: Snapshot: Sources (one time) 1337 bst_process('CallProcess', 'process_snapshot', sDiffMeanSrc, [], ... 1338 'target', 8, ... % Sources (one time) 1339 'orient', 1, ... % left 1340 'time', 0.148, ... 1341 'threshold', 40, ... 1342 'Comment', 'abs(average(deviant)) - abs(average(standard))'); 1343 % Process: Snapshot: Sources (one time) 1344 bst_process('CallProcess', 'process_snapshot', sDiffMeanSrcThresh, [], ... 1345 'target', 8, ... % Sources (one time) 1346 'orient', 1, ... % left 1347 'time', 0.148, ... 1348 'threshold', 0, ... 1349 'Comment', 'Different of mean thresholded with t-test results'); 1350 1351 % ===== EXAMPLE #5: PARAMETRIC/SCOUTS ===== 1352 % Process: t-test equal [-100ms,500ms] H0:(A=B), H1:(A<>B) 1353 sTestParamScout = bst_process('CallProcess', 'process_test_parametric2', sEpochDeviantSrc, sEpochStandardSrc, ... 1354 'timewindow', [-0.1, 0.5], ... 1355 'scoutsel', {'Destrieux', {'G_front_inf-Opercular L', 'G_precentral L', 'G_temp_sup-G_T_transv L'}}, ... 1356 'scoutfunc', 1, ... % Mean 1357 'isnorm', 0, ... 1358 'avgtime', 0, ... 1359 'Comment', '', ... 1360 'test_type', 'ttest_equal', ... % Student's t-test (equal variance) t = (mean(A)-mean(B)) / (Sx * sqrt(1/nA + 1/nB))Sx = sqrt(((nA-1)*var(A) + (nB-1)*var(B)) / (nA+nB-2)) df = nA + nB - 2 1361 'tail', 'two'); % Two-tailed 1362 % Process: Apply statistic threshold: p<0.05 (FDR:1,2,3) 1363 sTestParamScoutThresh = bst_process('CallProcess', 'process_extract_pthresh', sTestParamScout, [], ... 1364 'pthresh', 0.05, ... 1365 'correction', 3, ... % False discovery rate (FDR) 1366 'control1', 1, ... 1367 'control2', 1, ... 1368 'control3', 1); 1369 % Process: Compute head model 1370 bst_process('CallProcess', 'process_headmodel', sTestParamScoutThresh, [], ... 1371 'sourcespace', 1, ... % Cortex surface 1372 'meg', 3); % Overlapping spheres 1373 % Process: Simulate recordings from scouts 1374 sSimulData = bst_process('CallProcess', 'process_simulate_recordings', sTestParamScoutThresh, [], ... 1375 'scouts', {'Destrieux', {'G_front_inf-Opercular L', 'G_precentral L', 'G_temp_sup-G_T_transv L'}}, ... 1376 'savesources', 1); 1377 1378 % Get corresponding source file 1379 [sStudy,iStudy,iRes] = bst_get('ResultsForDataFile', sSimulData.FileName); 1380 sSimulSrc = sStudy.Result(iRes).FileName; 1381 % Reset visualization filters 1382 panel_filter('SetFilters', 0, [], 0, [], 0, [], 0, 0); 1383 % Process: Snapshot: Recordings time series 1384 bst_process('CallProcess', 'process_snapshot', sTestParamScout, [], ... 1385 'target', 5, ... % Recordings time series 1386 'time', 0.148, ... 1387 'Comment', 'Parametric t-test (p<0.05, FDR)'); 1388 % Process: Snapshot: Sources (one time) 1389 bst_process('CallProcess', 'process_snapshot', sSimulSrc, [], ... 1390 'target', 8, ... % Sources (one time) 1391 'orient', 1, ... % left 1392 'time', 0.148, ... 1393 'threshold', 0, ... 1394 'Comment', 'Simulated sources'); 1395 % Process: Snapshot: Recordings time series 1396 bst_process('CallProcess', 'process_snapshot', sSimulData, [], ... 1397 'target', 5, ... % Recordings time series 1398 'modality', 1, ... % MEG (All) 1399 'time', 0.148, ... 1400 'Comment', 'Simulated MEG recordings'); 1401 1402 1403 % ===== EXAMPLE #6: NON-PARAMETRIC/TIMEFREQ ===== 1404 TfOptions.Output = 'all'; 1405 % Process: Time-frequency (Morlet wavelets) / DEVIANT 1406 sEpochDeviantTf = bst_process('CallProcess', 'process_timefreq', sEpochDeviant, [], ... 1407 'sensortypes', 'MLP57', ... 1408 'edit', TfOptions, ... 1409 'normalize', 'none'); % None: Save non-standardized time-frequency maps 1410 % Process: Time-frequency (Morlet wavelets) / STANDARD 1411 sEpochStandardTf = bst_process('CallProcess', 'process_timefreq', sEpochStandard, [], ... 1412 'sensortypes', 'MLP57', ... 1413 'edit', TfOptions, ... 1414 'normalize', 'none'); % None: Save non-standardized time-frequency maps 1415 % Process: Perm t-test equal [-100ms,500ms 1-150Hz] H0:(A=B), H1:(A<>B) 1416 sTestTf = bst_process('CallProcess', 'process_test_permutation2', sEpochDeviantTf, sEpochStandardTf, ... 1417 'timewindow', [-0.1, 0.5], ... 1418 'freqrange', [1, 150], ... 1419 'rows', '', ... 1420 'isabs', 0, ... 1421 'avgtime', 0, ... 1422 'avgrow', 0, ... 1423 'avgfreq', 0, ... 1424 'matchrows', 0, ... 1425 'iszerobad', 1, ... 1426 'Comment', '', ... 1427 'test_type', 'ttest_equal', ... % Student's t-test (equal variance) t = (mean(A)-mean(B)) / (Sx * sqrt(1/nA + 1/nB))Sx = sqrt(((nA-1)*var(A) + (nB-1)*var(B)) / (nA+nB-2)) 1428 'randomizations', 1000, ... 1429 'tail', 'two'); % Two-tailed 1430 % Set stat threshold 1431 StatThreshOptions.pThreshold = 0.05; 1432 StatThreshOptions.Correction = 'none'; 1433 bst_set('StatThreshOptions', StatThreshOptions); 1434 % Process: Snapshot: Time-frequency maps 1435 bst_process('CallProcess', 'process_snapshot', sTestTf, [], ... 1436 'target', 14, ... % Time-frequency maps 1437 'Comment', 'Non-parametric t-test (p<0.05, Uncorrected)'); 1438 % Process: Delete intermediate results 1439 bst_process('CallProcess', 'process_delete', [sEpochDeviantTf, sEpochStandardTf], [], ... 1440 'target', 1); % Delete selected files 1441 1442 1443 1444 %% ===== SAVE REPORT ===== 1445 % Save and display report 1446 ReportFile = bst_report('Save', []); 1447 if ~isempty(reports_dir) && ~isempty(ReportFile) 1448 bst_report('Export', ReportFile, reports_dir); 1449 else 1450 bst_report('Open', ReportFile); 1451 end 1452 1453 disp([10 'DEMO> Done.' 10]);


For an example of a script illustrating how to create loops, look at the tutorial MEG visual: single subject. brainstorm3/toolbox/script/tutorial_visual_single.m - Report: report_TutorialVisual_sub001.html

1 function tutorial_visual_single(bids_dir, reports_dir) 2 % TUTORIAL_VISUAL_SINGLE: Runs the Brainstorm/SPM group analysis pipeline (single subject, BIDS version). 3 % 4 % ONLINE TUTORIALS: https://neuroimage.usc.edu/brainstorm/Tutorials/VisualSingle 5 % 6 % INPUTS: 7 % - bids_dir: Path to folder ds000117 (https://openneuro.org/datasets/ds000117) 8 % |- derivatives/freesurfer/sub-XX : Segmentation folders generated with FreeSurfer 9 % |- derivatives/meg_derivatives/sub-XX/ses-meg/meg/*.fif : MEG+EEG recordings (processed with MaxFilter's SSS) 10 % |- derivatives/meg_derivatives/sub-emptyroom/ses-meg/meg/*.fif : Empty room measurements 11 % - reports_dir: If defined, exports all the reports as HTML to this folder 12 13 % @============================================================================= 14 % This function is part of the Brainstorm software: 15 % https://neuroimage.usc.edu/brainstorm 16 % 17 % Copyright (c) University of Southern California & McGill University 18 % This software is distributed under the terms of the GNU General Public License 19 % as published by the Free Software Foundation. Further details on the GPLv3 20 % license can be found at http://www.gnu.org/copyleft/gpl.html. 21 % 22 % FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE 23 % UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY 24 % WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF 25 % MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY 26 % LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE. 27 % 28 % For more information type "brainstorm license" at command prompt. 29 % =============================================================================@ 30 % 31 % Author: Francois Tadel, Elizabeth Bock, 2016-2018 32 33 34 %% ===== SCRIPT VARIABLES ===== 35 % Full list of subjects to process 36 SubjectNames = {'sub-01', 'sub-02', 'sub-03', 'sub-04', 'sub-05', 'sub-06', 'sub-07', 'sub-08', ... 37 'sub-09', 'sub-10', 'sub-11', 'sub-12', 'sub-13', 'sub-14', 'sub-15', 'sub-16'}; 38 % Empty-room dates for each subject (so that we can match automatically recordings with empty-room) 39 EmptyRoomSubj = 'sub-emptyroom'; 40 AcquisitionDates = {'09-Apr-2009', '06-May-2009', '11-May-2009', '18-May-2009', '15-May-2009', '15-May-2009', '15-May-2009', '15-May-2009', ... 41 '15-May-2009', '15-May-2009', '01-Jun-2009', '01-Jun-2009', '01-Jun-2009', '26-Nov-2009', '08-Dec-2009', '08-Dec-2009'}; 42 % Bad channels {iSubj} = {Run01, Run02, Run03, Run04, Run05, Run06} 43 BadChannels{1} = {'EEG016', 'EEG070', 'EEG050',{'EEG008','EEG050'}, [], []}; 44 BadChannels{2} = {{'EEG027', 'EEG030', 'EEG038'}, 'EEG010', 'EEG010', 'EEG010', 'EEG010', 'EEG010'}; 45 BadChannels{3} = {{'EEG008','EEG017'}, {'EEG008','EEG017'}, {'EEG008','EEG017'}, {'EEG008','EEG017'}, {'EEG008','EEG017','EEG001'}, {'EEG008','EEG017','EEG020'}}; 46 BadChannels{4} = {{'EEG038'}, {'EEG038','EEG001','EEG016'}, {'EEG038','EEG001','EEG016'}, {'EEG038','EEG001'}, {'EEG038','EEG001','EEG016'}, {'EEG038','EEG001','EEG016'}}; 47 BadChannels{5} = {'EEG001', 'EEG001', [], [], [], []}; 48 BadChannels{6} = {'EEG068', [], 'EEG004', [], [], []}; 49 BadChannels{7} = {[], [], {'EEG004','EEG008'}, {'EEG004','EEG008'},{'EEG004','EEG008','EEG043','EEG045','EEG047'}, {'EEG004','EEG008'}}; 50 BadChannels{8} = {[], [], [], [], [], []}; 51 BadChannels{9} = {[], 'EEG004', 'EEG004', [], 'EEG004', 'EEG004'}; 52 BadChannels{10} = {[], [], [], [], [], []}; 53 BadChannels{11} = {{'EEG010','EEG050'}, 'EEG050', 'EEG050', 'EEG050', 'EEG050', 'EEG050'}; 54 BadChannels{12} = {{'EEG024','EEG057'}, {'EEG024','EEG057'}, {'EEG024','EEG057'}, {'EEG024','EEG057','EEG070'}, {'EEG024','EEG057'}, {'EEG024','EEG057','EEG070'}}; 55 BadChannels{13} = {'EEG009', 'EEG009', {'EEG009','EEG057','EEG69'}, 'EEG009', {'EEG009','EEG044'}, {'EEG009','EEG044'}}; 56 BadChannels{14} = {'EEG029', 'EEG029', 'EEG029', {'EEG004','EEG008','EEG016','EEG029'}, {'EEG004','EEG008','EEG016','EEG029'}, {'EEG004','EEG008','EEG016','EEG029'}}; 57 BadChannels{15} = {'EEG038', 'EEG038', 'EEG038', 'EEG038', {'EEG054','EEG038'}, 'EEG038'}; 58 BadChannels{16} = {'EEG008', 'EEG008', 'EEG008', 'EEG008', 'EEG008', 'EEG008'}; 59 % SSP components to remove {iSubj} = {sRun01, sRun02, sRun03, sRun03, sRun04, sRun05, sRun06}, sRun0X={ECG_GRAD,ECG_MAG} 60 SspSelect{1} = {{1,1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 61 SspSelect{2} = {{1,1}, {1,1}, {1,1}, {1,1}, {3,1}, {1,1}}; 62 SspSelect{3} = {{[],1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 63 SspSelect{4} = {{[],1}, {[],1}, {[],1}, {[],1}, {[],1}, {[],1}}; 64 SspSelect{5} = {{2,1}, {1,1}, {1,1}, {[],1}, {1,1}, {1,1}}; 65 SspSelect{6} = {{2,1}, {2,1}, {1,1}, {2,1}, {1,1}, {2,1}}; 66 SspSelect{7} = {{1,1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 67 SspSelect{8} = {{1,1}, {1,1}, {[],1}, {2,1}, {1,1}, {2,1}}; 68 SspSelect{9} = {{1,1}, {1,1}, {[],1}, {[],1}, {1,1}, {1,1}}; 69 SspSelect{10} = {{1,1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 70 SspSelect{11} = {{[],1}, {[],1}, {[],1}, {[],1}, {[],[]}, {[],[]}}; 71 SspSelect{12} = {{[1,2],[1,2]}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 72 SspSelect{13} = {{[],[]}, {[],[]}, {[],[]}, {[],[]}, {[],[]}, {[],[]}}; 73 SspSelect{14} = {{1,1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 74 SspSelect{15} = {{1,1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 75 SspSelect{16} = {{1,1}, {1,1}, {1,1}, {2,1}, {1,1}, {1,1}}; 76 77 78 %% ===== CREATE PROTOCOL ===== 79 % Start brainstorm without the GUI 80 if ~brainstorm('status') 81 brainstorm nogui 82 end 83 % Output folder for reports 84 if (nargin < 2) || isempty(reports_dir) || ~isdir(reports_dir) 85 reports_dir = []; 86 end 87 % You have to specify the folder in which the tutorial dataset is unzipped 88 if (nargin < 1) || isempty(bids_dir) || ~file_exist(bids_dir) || ~file_exist(bst_fullfile(bids_dir, 'derivatives')) || ~file_exist(bst_fullfile(bids_dir, 'dataset_description.json')) 89 error('The first argument must be the full path to the tutorial folder.'); 90 end 91 % The protocol name has to be a valid folder name (no spaces, no weird characters...) 92 ProtocolName = 'TutorialVisual'; 93 % Delete existing protocol 94 gui_brainstorm('DeleteProtocol', ProtocolName); 95 % Create new protocol 96 gui_brainstorm('CreateProtocol', ProtocolName, 0, 0); 97 % Set visualization filters: 40Hz low-pass, no high-pass 98 panel_filter('SetFilters', 1, 40, 0, [], 0, [], 0, 0); 99 % Set colormap: local color scale 100 bst_colormaps('SetMaxMode', 'meg', 'local'); 101 bst_colormaps('SetMaxMode', 'eeg', 'local'); 102 103 104 %% ===== PRE-PROCESS AND IMPORT ===== 105 for iSubj = 1:16 106 % Start a new report (one report per subject) 107 bst_report('Start'); 108 disp(sprintf('\n===== IMPORT: SUBJECT #%d =====\n', iSubj)); 109 110 % If subject already exists: delete it 111 [sSubject, iSubject] = bst_get('Subject', SubjectNames{iSubj}); 112 if ~isempty(sSubject) 113 db_delete_subjects(iSubject); 114 end 115 116 % ===== FILES TO IMPORT ===== 117 % Build the path of the files to import 118 AnatDir = fullfile(bids_dir, 'derivatives', 'freesurfer', SubjectNames{iSubj}, 'ses-mri', 'anat'); 119 DataDir = fullfile(bids_dir, 'derivatives', 'meg_derivatives', SubjectNames{iSubj}, 'ses-meg', 'meg'); 120 % Check if the folder contains the required files 121 if ~file_exist(AnatDir) 122 error(['The folder "' AnatDir '" does not exist.']); 123 end 124 if ~file_exist(DataDir) 125 error(['The folder "' DataDir '" does not exist.']); 126 end 127 128 % ===== ANATOMY ===== 129 % Process: Import anatomy folder 130 bst_process('CallProcess', 'process_import_anatomy', [], [], ... 131 'subjectname', SubjectNames{iSubj}, ... 132 'mrifile', {AnatDir, 'FreeSurfer'}, ... 133 'nvertices', 15000); 134 135 % ===== PROCESS EACH RUN ===== 136 for iRun = 1:6 137 % Files to import 138 FifFile = bst_fullfile(DataDir, sprintf('%s_ses-meg_task-facerecognition_run-%02d_proc-sss_meg.fif', SubjectNames{iSubj}, iRun)); 139 140 % ===== LINK CONTINUOUS FILE ===== 141 % Process: Create link to raw file 142 sFileRaw = bst_process('CallProcess', 'process_import_data_raw', [], [], ... 143 'subjectname', SubjectNames{iSubj}, ... 144 'datafile', {FifFile, 'FIF'}, ... 145 'channelreplace', 1, ... 146 'channelalign', 0); 147 % Set acquisition date 148 panel_record('SetAcquisitionDate', sFileRaw.iStudy, AcquisitionDates{iSubj}); 149 150 % ===== PREPARE CHANNEL FILE ===== 151 % Process: Set channels type 152 bst_process('CallProcess', 'process_channel_settype', sFileRaw, [], ... 153 'sensortypes', 'EEG061, EEG064', ... 154 'newtype', 'NOSIG'); 155 bst_process('CallProcess', 'process_channel_settype', sFileRaw, [], ... 156 'sensortypes', 'EEG062', ... 157 'newtype', 'EOG'); 158 bst_process('CallProcess', 'process_channel_settype', sFileRaw, [], ... 159 'sensortypes', 'EEG063', ... 160 'newtype', 'ECG'); 161 162 % Process: Remove head points 163 sFileRaw = bst_process('CallProcess', 'process_headpoints_remove', sFileRaw, [], ... 164 'zlimit', 0); 165 % Process: Refine registration 166 sFileRaw = bst_process('CallProcess', 'process_headpoints_refine', sFileRaw, []); 167 % Process: Project electrodes on scalp 168 sFileRaw = bst_process('CallProcess', 'process_channel_project', sFileRaw, []); 169 170 % Process: Snapshot: Sensors/MRI registration 171 bst_process('CallProcess', 'process_snapshot', sFileRaw, [], ... 172 'target', 1, ... % Sensors/MRI registration 173 'modality', 1, ... % MEG (All) 174 'orient', 1, ... % left 175 'Comment', sprintf('MEG/MRI Registration: Subject #%d, Run #%d', iSubj, iRun)); 176 bst_process('CallProcess', 'process_snapshot', sFileRaw, [], ... 177 'target', 1, ... % Sensors/MRI registration 178 'modality', 4, ... % EEG 179 'orient', 1, ... % left 180 'Comment', sprintf('EEG/MRI Registration: Subject #%d, Run #%d', iSubj, iRun)); 181 182 % ===== IMPORT TRIGGERS ===== 183 % Process: Read from channel 184 bst_process('CallProcess', 'process_evt_read', sFileRaw, [], ... 185 'stimchan', 'STI101', ... 186 'trackmode', 2, ... % Bit: detect the changes for each bit independently 187 'zero', 0); 188 % Process: Group by name 189 bst_process('CallProcess', 'process_evt_groupname', sFileRaw, [], ... 190 'combine', 'Unfamiliar=3,4', ... 191 'dt', 0, ... 192 'delete', 1); 193 % Process: Rename event 194 bst_process('CallProcess', 'process_evt_rename', sFileRaw, [], ... 195 'src', '3', ... 196 'dest', 'Famous'); 197 % Process: Rename event 198 bst_process('CallProcess', 'process_evt_rename', sFileRaw, [], ... 199 'src', '5', ... 200 'dest', 'Scrambled'); 201 % Process: Add time offset 202 bst_process('CallProcess', 'process_evt_timeoffset', sFileRaw, [], ... 203 'info', [], ... 204 'eventname', 'Famous, Unfamiliar, Scrambled', ... 205 'offset', 0.0345); 206 % Process: Delete events 207 bst_process('CallProcess', 'process_evt_delete', sFileRaw, [], ... 208 'eventname', '1,2,6,7,8,9,10,11,12,13,14,15,16'); 209 % Process: Detect cHPI activity (Elekta):STI201 210 bst_process('CallProcess', 'process_evt_detect_chpi', sFileRaw, [], ... 211 'eventname', 'chpi_bad', ... 212 'channelname', 'STI201', ... 213 'method', 'off'); % Mark as bad when the HPI coils are OFF 214 215 % ===== FREQUENCY FILTERS ===== 216 % Process: Notch filter: 50Hz 100Hz 150Hz 200Hz 217 sFileClean = bst_process('CallProcess', 'process_notch', sFileRaw, [], ... 218 'freqlist', [50, 100, 150, 200], ... 219 'sensortypes', 'MEG, EEG', ... 220 'read_all', 0); 221 % Process: Power spectrum density (Welch) 222 sFilesPsd = bst_process('CallProcess', 'process_psd', [sFileRaw, sFileClean], [], ... 223 'timewindow', [], ... 224 'win_length', 4, ... 225 'win_overlap', 50, ... 226 'sensortypes', 'MEG, EEG', ... 227 'edit', struct(... 228 'Comment', 'Power', ... 229 'TimeBands', [], ... 230 'Freqs', [], ... 231 'ClusterFuncTime', 'none', ... 232 'Measure', 'power', ... 233 'Output', 'all', ... 234 'SaveKernel', 0)); 235 % Process: Snapshot: Frequency spectrum 236 bst_process('CallProcess', 'process_snapshot', sFilesPsd, [], ... 237 'target', 10, ... % Frequency spectrum 238 'Comment', sprintf('Power spctrum: Subject #%d, Run #%d', iSubj, iRun)); 239 240 % ===== BAD CHANNELS ===== 241 if ~isempty(BadChannels{iSubj}{iRun}) 242 % Process: Set bad channels 243 bst_process('CallProcess', 'process_channel_setbad', sFileClean, [], ... 244 'sensortypes', BadChannels{iSubj}{iRun}); 245 end 246 247 % ===== EEG REFERENCE ===== 248 % Process: Re-reference EEG 249 bst_process('CallProcess', 'process_eegref', sFileClean, [], ... 250 'eegref', 'AVERAGE', ... 251 'sensortypes', 'EEG'); 252 253 % ===== DETECT ARTIFACTS ====== 254 % Process: Detect heartbeats 255 bst_process('CallProcess', 'process_evt_detect_ecg', sFileClean, [], ... 256 'channelname', 'EEG063', ... 257 'timewindow', [], ... 258 'eventname', 'cardiac'); 259 % Different amplitude thresholds for different subjects 260 if strcmpi(SubjectNames{iSubj}, 'sub-05') 261 thresholdMAX = 50; 262 else 263 thresholdMAX = 100; 264 end 265 % Process: Detect: blink_BAD - Detects all events where the amplitude exceeds 100uV 266 bst_process('CallProcess', 'process_evt_detect_threshold', sFileClean, [], ... 267 'eventname', 'blink_BAD', ... 268 'channelname', 'EEG062', ... 269 'timewindow', [], ... 270 'thresholdMAX', thresholdMAX, ... 271 'units', 3, ... % uV (10^-6) 272 'bandpass', [0.3, 20], ... 273 'isAbsolute', 1, ... 274 'isDCremove', 0); 275 276 % ===== SSP COMPUTATION ===== 277 % Process: SSP ECG: cardiac 278 bst_process('CallProcess', 'process_ssp_ecg', sFileClean, [], ... 279 'eventname', 'cardiac', ... 280 'sensortypes', 'MEG GRAD', ... 281 'usessp', 1, ... 282 'select', SspSelect{iSubj}{iRun}{1}); 283 bst_process('CallProcess', 'process_ssp_ecg', sFileClean, [], ... 284 'eventname', 'cardiac', ... 285 'sensortypes', 'MEG MAG', ... 286 'usessp', 1, ... 287 'select', SspSelect{iSubj}{iRun}{2}); 288 % Process: Snapshot: SSP projectors 289 bst_process('CallProcess', 'process_snapshot', sFileClean, [], ... 290 'target', 2, ... 291 'Comment', sprintf('Subject #%d, Run #%d', iSubj, iRun)); % SSP projectors 292 293 % ===== IMPORT BAD EVENTS ===== 294 % Get bad segments: this is typically done manually, not from a script 295 BadSegments = GetBadSegments(iSubj, iRun); 296 % Process: Import from file 297 bst_process('CallProcess', 'process_evt_import', sFileClean, [], ... 298 'evtfile', {BadSegments, 'ARRAY-TIMES'}, ... 299 'evtname', 'BAD'); 300 301 % ===== IMPORT TRIALS ===== 302 % Process: Import MEG/EEG: Events 303 sFilesEpochs = bst_process('CallProcess', 'process_import_data_event', sFileClean, [], ... 304 'subjectname', SubjectNames{iSubj}, ... 305 'condition', '', ... 306 'eventname', 'Famous, Scrambled, Unfamiliar', ... 307 'timewindow', [], ... 308 'epochtime', [-0.5, 1.2], ... 309 'createcond', 0, ... 310 'ignoreshort', 1, ... 311 'usectfcomp', 1, ... 312 'usessp', 1, ... 313 'freq', [], ... 314 'baseline', [-0.5, -0.0009]); 315 316 % ===== AVERAGE: RUN ===== 317 % Process: Average: By trial group (folder average) 318 sFilesAvg = bst_process('CallProcess', 'process_average', sFilesEpochs, [], ... 319 'avgtype', 5, ... % By trial group (folder average) 320 'avg_func', 1, ... % Arithmetic average: mean(x) 321 'weighted', 0, ... 322 'keepevents', 0); 323 % Process: Snapshot: Recordings time series 324 bst_process('CallProcess', 'process_snapshot', sFilesAvg, [], ... 325 'target', 5, ... % Recordings time series 326 'modality', 4, ... % EEG 327 'time', 0.11, ... 328 'Comment', sprintf('Subject #%d, Run #%d', iSubj, iRun)); 329 % Process: Snapshot: Recordings topography 330 bst_process('CallProcess', 'process_snapshot', sFilesAvg, [], ... 331 'target', 6, ... % Recordings topography (one time) 332 'modality', 4, ... % EEG 333 'time', 0.11, ... 334 'Comment', sprintf('Subject #%d, Run #%d', iSubj, iRun)); 335 336 % ===== COMPUTE NOISECOV: EEG ===== 337 % Process: Compute covariance (noise or data) 338 bst_process('CallProcess', 'process_noisecov', sFilesEpochs, [], ... 339 'baseline', [-0.5, -0.0009], ... 340 'sensortypes', 'EEG', ... 341 'target', 1, ... % Noise covariance (covariance over baseline time window) 342 'dcoffset', 1, ... % Block by block, to avoid effects of slow shifts in data 343 'identity', 0, ... 344 'copycond', 0, ... 345 'copysubj', 0, ... 346 'replacefile', 1); % Replace 347 end 348 349 % Save report 350 ReportFile = bst_report('Save', []); 351 if ~isempty(reports_dir) && ~isempty(ReportFile) 352 bst_report('Export', ReportFile, bst_fullfile(reports_dir, ['report_' ProtocolName '_' SubjectNames{iSubj} '.html'])); 353 end 354 end 355 356 357 %% ===== EMPTY ROOM RECORDINGS ===== 358 disp(sprintf('\n===== IMPORT: EMPTY-ROOM =====\n')); 359 % Loop on all the noise sessions 360 NoiseFiles = {}; 361 for ses = {'20090409', '20090506', '20090511', '20090515', '20090518', '20090601', '20091126', '20091208'} 362 NoiseFiles{end+1} = fullfile(bids_dir, 'derivatives', 'meg_derivatives', EmptyRoomSubj, ['ses-' ses{1}], 'meg', ['sub-emptyroom_ses-' ses{1} '_task-noise_proc-sss_meg.fif']); 363 end 364 % Process: Create link to raw file 365 sFilesNoise = bst_process('CallProcess', 'process_import_data_raw', [], [], ... 366 'subjectname', EmptyRoomSubj, ... 367 'datafile', {NoiseFiles, 'FIF'}, ... 368 'channelreplace', 1, ... 369 'channelalign', 0); 370 % Process: Notch filter: 50Hz 100Hz 150Hz 200Hz 371 sFileNoiseClean = bst_process('CallProcess', 'process_notch', sFilesNoise, [], ... 372 'freqlist', [50, 100, 150, 200], ... 373 'sensortypes', 'MEG, EEG', ... 374 'read_all', 0); 375 % Process: Compute noise covariance 376 bst_process('CallProcess', 'process_noisecov', sFileNoiseClean, [], ... 377 'baseline', [], ... 378 'sensortypes', 'MEG', ... 379 'target', 1, ... % Noise covariance (covariance over baseline time window) 380 'dcoffset', 1, ... % Block by block, to avoid effects of slow shifts in data 381 'identity', 0, ... 382 'copycond', 1, ... 383 'copysubj', 1, ... 384 'copymatch', 1, ... 385 'replacefile', 2); % Merge 386 387 388 %% ===== SOURCE ESTIMATION ===== 389 % Start a new report (one report for the source estimation of all the subjects) 390 bst_report('Start'); 391 % Loop on the subjects: This loop is separated from the previous one, because we should 392 % compute the BEM surfaces after importing all the runs, so that the registration is done 393 % using the high resolution head surface, instead of the smooth scalp BEM layer. 394 for iSubj = 1:length(SubjectNames) 395 disp(sprintf('\n===== SOURCES: SUBJECT #%d =====\n', iSubj)); 396 397 % ===== BEM SURFACES ===== 398 % Process: Generate BEM surfaces 399 bst_process('CallProcess', 'process_generate_bem', [], [], ... 400 'subjectname', SubjectNames{iSubj}, ... 401 'nscalp', 1082, ... 402 'nouter', 642, ... 403 'ninner', 642, ... 404 'thickness', 4, ... 405 'method', 'brainstorm'); 406 407 % ===== SELECT ALL AVERAGES ===== 408 % Process: Select data files in: */* 409 sFilesAvg = bst_process('CallProcess', 'process_select_files_data', [], [], ... 410 'subjectname', SubjectNames{iSubj}); 411 % Process: Select file comments with tag: Avg 412 sFilesAvg = bst_process('CallProcess', 'process_select_tag', sFilesAvg, [], ... 413 'tag', 'Avg'); % Select only the files with the tag 414 415 % ===== COMPUTE HEAD MODELS ===== 416 % Process: Compute head model (only for the first run of the subject) 417 bst_process('CallProcess', 'process_headmodel', sFilesAvg(1), [], ... 418 'sourcespace', 1, ... % Cortex surface 419 'meg', 3, ... % Overlapping spheres 420 'eeg', 3, ... % OpenMEEG BEM 421 'ecog', 1, ... % 422 'seeg', 1, ... % 423 'openmeeg', struct(... 424 'BemSelect', [1, 1, 1], ... 425 'BemCond', [1, 0.0125, 1], ... 426 'BemNames', {{'Scalp', 'Skull', 'Brain'}}, ... 427 'BemFiles', {{}}, ... 428 'isAdjoint', 0, ... 429 'isAdaptative', 1, ... 430 'isSplit', 0, ... 431 'SplitLength', 4000)); 432 % Get all the runs for this subject (ie the list of the study indices) 433 iStudyOther = setdiff(unique([sFilesAvg.iStudy]), sFilesAvg(1).iStudy); 434 % Copy the forward model file to the other runs 435 sHeadmodel = bst_get('HeadModelForStudy', sFilesAvg(1).iStudy); 436 for iStudy = iStudyOther 437 db_add(iStudy, sHeadmodel.FileName); 438 end 439 440 % ===== COMPUTE SOURCES: MEG ===== 441 % Process: Compute sources [2018] 442 sAvgSrcMeg = bst_process('CallProcess', 'process_inverse_2018', sFilesAvg, [], ... 443 'output', 1, ... % Kernel only: shared 444 'inverse', struct(... 445 'Comment', 'MN: MEG ALL', ... 446 'InverseMethod', 'minnorm', ... 447 'InverseMeasure', 'amplitude', ... 448 'SourceOrient', {{'fixed'}}, ... 449 'Loose', 0.2, ... 450 'UseDepth', 1, ... 451 'WeightExp', 0.5, ... 452 'WeightLimit', 10, ... 453 'NoiseMethod', 'reg', ... 454 'NoiseReg', 0.1, ... 455 'SnrMethod', 'fixed', ... 456 'SnrRms', 1e-06, ... 457 'SnrFixed', 3, ... 458 'ComputeKernel', 1, ... 459 'DataTypes', {{'MEG GRAD', 'MEG MAG'}})); 460 % Process: Snapshot: Sources (one time) - Loop only to get a correct comment for the report 461 for i = 1:length(sAvgSrcMeg) 462 bst_process('CallProcess', 'process_snapshot', sAvgSrcMeg(i), [], ... 463 'target', 8, ... % Sources (one time) 464 'orient', 4, ... % bottom 465 'time', 0.11, ... 466 'threshold', 20, ... 467 'Comment', ['MEG sources: ' sFilesAvg(i).FileName]); 468 end 469 470 % ===== COMPUTE SOURCES: EEG ===== 471 % Process: Compute sources [2018] 472 sAvgSrcEeg = bst_process('CallProcess', 'process_inverse_2018', sFilesAvg, [], ... 473 'output', 1, ... % Kernel only: shared 474 'inverse', struct(... 475 'Comment', 'MN: EEG', ... 476 'InverseMethod', 'minnorm', ... 477 'InverseMeasure', 'amplitude', ... 478 'SourceOrient', {{'fixed'}}, ... 479 'Loose', 0.2, ... 480 'UseDepth', 1, ... 481 'WeightExp', 0.5, ... 482 'WeightLimit', 10, ... 483 'NoiseMethod', 'reg', ... 484 'NoiseReg', 0.1, ... 485 'SnrMethod', 'fixed', ... 486 'SnrRms', 1e-06, ... 487 'SnrFixed', 3, ... 488 'ComputeKernel', 1, ... 489 'DataTypes', {{'EEG'}})); 490 % Process: Snapshot: Sources (one time) - Loop only to get a correct comment for the report 491 for i = 1:length(sAvgSrcEeg) 492 bst_process('CallProcess', 'process_snapshot', sAvgSrcEeg(i), [], ... 493 'target', 8, ... % Sources (one time) 494 'orient', 4, ... % bottom 495 'time', 0.11, ... 496 'threshold', 10, ... 497 'Comment', ['EEG sources: ' sFilesAvg(i).FileName]); 498 end 499 end 500 % Save report 501 ReportFile = bst_report('Save', []); 502 if ~isempty(reports_dir) && ~isempty(ReportFile) 503 bst_report('Export', ReportFile, bst_fullfile(reports_dir, ['report_' ProtocolName '_sources.html'])); 504 end 505 506 507 %% ===== TIME-FREQUENCY ===== 508 % Start a new report (one report for the time-frequency of all the subjects) 509 bst_report('Start'); 510 % List of conditions to process separately 511 AllConditions = {'Famous', 'Scrambled', 'Unfamiliar'}; 512 % Channels to display in the screen capture, by order of preference (if the first channel is bad, use the following) 513 SelChannel = {'EEG070','EEG060','EEG065','EEG050','EEG003'}; 514 % Compute one separate time-frequency average for each subject/run/condition 515 for iSubj = 1:length(SubjectNames) 516 disp(sprintf('\n===== TIME-FREQUENCY: SUBJECT #%d =====\n', iSubj)); 517 for iRun = 1:6 518 % Process: Select data files in: Subject/Run 519 sTrialsAll = bst_process('CallProcess', 'process_select_files_data', [], [], ... 520 'subjectname', SubjectNames{iSubj}, ... 521 'condition', sprintf('sub-%02d_ses-meg_task-facerecognition_run-%02d_proc-sss_meg_notch', iSubj, iRun)); 522 % Loop on the conditions 523 for iCond = 1:length(AllConditions) 524 % Comment describing this average 525 strComment = [SubjectNames{iSubj}, ' / ', sprintf('run_%02d', iRun), ' / ', AllConditions{iCond}]; 526 disp(['BST> ' strComment]); 527 % Find the first good channel in the display list 528 if isempty(BadChannels{iSubj}{iRun}) 529 iSel = 1; 530 else 531 iSel = find(~ismember(SelChannel,BadChannels{iSubj}{iRun}), 1); 532 end 533 % Process: Select file comments with tag: Avg 534 sTrialsCond = bst_process('CallProcess', 'process_select_tag', sTrialsAll, [], ... 535 'tag', [AllConditions{iCond}, '_trial'], ... 536 'search', 1, ... % Search the file names 537 'select', 1); % Select only the files with the tag 538 % Process: Time-frequency (Morlet wavelets), averaged across trials 539 sTimefreq = bst_process('CallProcess', 'process_timefreq', sTrialsCond, [], ... 540 'sensortypes', 'MEG MAG, EEG', ... 541 'edit', struct(... 542 'Comment', ['Avg: ' AllConditions{iCond} ', Power, 6-60Hz'], ... 543 'TimeBands', [], ... 544 'Freqs', [6, 6.8, 7.6, 8.6, 9.7, 11, 12.4, 14, 15.8, 17.9, 20.2, 22.8, 25.7, 29, 32.7, 37, 41.7, 47.1, 53.2, 60], ... 545 'MorletFc', 1, ... 546 'MorletFwhmTc', 3, ... 547 'ClusterFuncTime', 'none', ... 548 'Measure', 'power', ... 549 'Output', 'average', ... 550 'RemoveEvoked', 0, ... 551 'SaveKernel', 0), ... 552 'normalize', 'none'); % None: Save non-standardized time-frequency maps 553 % Process: Extract time: [-200ms,900ms] 554 sTimefreq = bst_process('CallProcess', 'process_extract_time', sTimefreq, [], ... 555 'timewindow', [-0.2, 0.9], ... 556 'overwrite', 1); 557 % Screen capture of one sensor 558 hFigTf = view_timefreq(sTimefreq.FileName, 'SingleSensor', SelChannel{iSel}); 559 bst_report('Snapshot', hFigTf, strComment, 'Time-frequency', [200, 200, 400, 250]); 560 close(hFigTf); 561 end 562 end 563 end 564 % Save report 565 ReportFile = bst_report('Save', []); 566 if ~isempty(reports_dir) && ~isempty(ReportFile) 567 bst_report('Export', ReportFile, bst_fullfile(reports_dir, ['report_' ProtocolName '_timefreq.html'])); 568 end 569 end 570 571 572 573 574 %% ===== SUPPORT FUNCTIONS ===== 575 function BadSeg = GetBadSegments(iSubj, iRun) 576 BadSegments{1} = {... 577 [247.867 248.185; 598.999 598.999; 598.999 598.999; 611.999 611.999; 612.999 612.999; 613.999 613.999; 616.999 616.999; 617.999 617.999; 623.999 623.999; 715.209 715.467], ... 578 [84.791 85.166], ... 579 [79.183 80.167], ... 580 [64.309 65.185], ... 581 [90.958 91.167; 178.005 178.355; 293.282 295.919; 312.298 316.479; 353.835 357.716], ... 582 [60.292 66.802; 69.975 71.210; 105.233 107.586; 108.822 109.506; 376.225 376.325]}; 583 BadSegments{2} = {... 584 [223.806 224.199; 279.772 279.895; 453.241 455.108; 692.423 692.593], ... 585 [65.298 66.194; 304.727 306.178; 399.165 400.732], ... 586 [203.141 205.085; 281.579 287.883; 420.395 421.128], ... 587 [387.118 388.229; 440.318 441.900; 554.825 558.744], ... 588 [71.000 80.999; 82.750 87.367; 149.528 149.667; 264.747 267.995; 368.415 371.973; 376.263 378.763; 398.334 401.551; 537.410 541.645], ... 589 [38.000 47.999; 47.825 50.046; 61.298 61.384; 249.653 253.379; 282.917 283.820; 286.135 287.616; 298.167 300.196; 328.254 329.511; 335.957 337.817; 478.277 480.707]}; 590 BadSegments{3} = {... 591 [406.312 407.207; 727.055 728.714], ... 592 [84.894 85.156; 152.028 152.946; 297.835 298.915; 418.272 421.845; 554.084 554.794], ... 593 [73.758 74.159; 378.212 378.536; 406.065 407.099; 470.541 471.698; 488.900 491.168; 529.596 530.453], ... 594 [94.874 95.152; 317.385 321.374; 325.696 327.055; 439.220 439.829; 454.473 455.175; 486.196 486.829; 518.660 522.015; 524.400 525.249; 562.417 570.325], ... 595 [96.208 97.181; 98.942 99.096; 135.005 135.754; 143.990 144.599; 250.139 250.247; 300.459 300.559; 338.265 339.322; 545.913 546.067], ... 596 [91.415 92.156; 284.843 286.525; 297.886 298.404; 317.046 317.163; 332.698 332.791; 358.946 359.402; 428.405 428.775; 478.374 478.690; 549.866 550.128]}; 597 BadSegments{4} = {... 598 [22.967 22.967; 50.036 50.098; 52.058 52.058; 156.653 156.653; 171.565 173.386; 239.544 242.105; 268.162 270.175; 268.992 268.992; 316.032 316.032; 338.283 339.000; 357.959 361.909; 370.871 370.871; 381.579 383.677; 437.731 437.731; 463.482 468.505; 476.135 479.838; 486.652 488.272; 504.860 508.999], ... 599 [309.493 311.707; 342.681 344.525; 354.019 357.321; 390.023 391.225; 393.926 395.855; 404.221 405.069; 432.522 435.932; 459.048 460.715; 471.763 478.529; 549.387 551.999; 591.087 594.143; 608.541 611.079; 624.847 626.615; 649.648 651.570], ... 600 [57.411 58.198; 88.346 88.955; 200.761 202.335; 227.016 227.688; 257.726 258.054; 356.798 359.005; 404.260 411.003], ... 601 [46.000 54.823; 61.000 70.332; 203.005 207.125; 275.875 278.121; 313.500 314.824; 337.973 338.636; 422.505 426.239], ... 602 [58.000 62.479; 78.250 85.166; 89.955 91.360; 116.322 117.888; 130.013 131.987; 149.509 150.489; 174.650 175.823; 182.030 183.334; 196.758 197.384; 204.458 204.697; 205.236 208.663; 311.028 316.383; 320.700 327.181; 332.437 335.354; 344.205 346.133; 374.208 374.865; 385.519 386.214; 441.942 444.241; 453.957 456.997; 486.039 487.004; 501.238 504.185; 512.962 514.675; 553.398 556.215], ... 603 [41.406 45.743; 58.681 59.144; 108.086 108.896; 140.633 143.750; 196.110 199.474; 210.778 210.971; 234.649 235.143; 258.081 259.632; 339.101 340.805; 390.277 390.609; 438.935 442.122; 528.221 534.031]}; 604 BadSegments{5} = {... 605 [265.539 265.778; 266.334 266.495; 268.479 268.965; 367.428 367.636; 439.655 442.779; 453.497 453.853; 504.997 505.329; 519.513 519.683; 595.674 595.982; 602.000 602.463], ... 606 [121.113 121.499; 124.971 126.213; 253.735 254.075; 272.232 272.464; 272.895 273.104; 346.368 346.645; 368.812 369.052; 406.382 406.605; 452.920 453.113; 454.903 455.112; 507.655 507.840; 508.766 509.013; 584.853 585.030; 594.831 595.656; 597.261 602.249], ... 607 [37.251 37.497; 38.825 39.056; 40.615 41.849; 43.624 44.758; 53.333 53.641; 54.698 55.076; 57.668 59.196; 79.129 79.360; 81.475 81.714; 122.658 123.375; 284.787 285.296; 288.754 288.993; 345.790 346.022; 421.212 421.459; 481.428 482.207; 503.408 503.685; 504.272 504.449; 524.451 524.714; 526.913 531.499], ... 608 [87.322 88.178; 91.085 91.325; 95.121 95.491; 114.174 114.397; 129.874 130.113; 151.220 151.544; 281.689 281.959; 532.966 533.345], ... 609 [59.176 60.218; 74.854 75.317; 308.180 309.877; 380.705 381.059], ... 610 [182.382 183.245; 196.220 196.736; 276.018 276.327; 292.490 294.086; 370.755 370.847; 435.644 436.624; 467.535 468.460; 522.838 525.847]}; 611 BadSegments{6} = {... 612 [141.690 142.424; 157.070 157.417; 355.138 356.025; 423.999 423.999; 424.999 424.999; 426.999 426.999; 427.999 427.999; 486.430 488.151; 493.999 493.999; 501.511 501.619; 501.549 501.549; 501.585 501.585; 502.999 502.999; 503.999 503.999; 540.999 540.999; 541.999 541.999; 555.999 555.999; 556.999 556.999; 561.999 561.999; 563.999 563.999; 564.999 564.999; 565.999 565.999; 567.999 567.999], ... 613 [64.898 65.161; 71.700 72.718; 226.185 226.740; 324.124 324.425; 329.062 329.301; 486.143 486.975], ... 614 [62.300 63.148; 266.254 266.639; 409.920 410.221], ... 615 [54.048 55.214; 330.893 331.255], ... 616 [185.616 186.495; 331.411 331.796; 386.843 387.028; 387.999 387.999; 389.999 389.999; 434.575 434.875; 519.802 519.995], ... 617 [44.720 45.167; 211.446 211.964; 368.955 369.172]}; 618 BadSegments{7} = {... 619 [154.966 155.144; 551.639 551.855], ... 620 [88.774 89.167; 107.999 107.999; 109.999 109.999; 110.999 110.999; 112.999 112.999; 113.999 113.999; 114.999 114.999; 119.999 119.999; 121.999 121.999; 124.223 125.465; 137.011 138.871], ... 621 [81.627 82.136; 377.953 381.046], ... 622 [241.136 242.171; 543.849 544.196; 596.639 598.553; 600.227 601.075; 603.999 603.999; 605.999 605.999; 609.999 609.999; 611.305 612.809; 614.999 614.999; 615.803 616.937; 623.694 625.877; 653.999 653.999; 655.055 655.756; 663.999 663.999], ... 623 [68.852 69.481; 74.034 75.200; 78.426 78.600; 104.497 105.963; 253.951 254.034; 256.964 257.038; 257.915 258.048; 323.254 324.156; 365.880 368.131; 369.952 370.060; 371.728 372.999; 430.931 431.965; 535.521 542.999], ... 624 [70.271 71.205; 94.441 96.445; 98.613 99.126; 112.318 112.749; 131.686 132.265; 148.935 150.615; 161.120 161.600; 205.325 208.214; 215.035 215.863; 217.403 218.818; 286.178 287.171; 399.075 404.853]}; 625 BadSegments{8} = {... 626 [238.505 238.546; 256.354 257.224; 316.116 316.167; 341.519 341.558; 356.493 356.566; 380.095 380.170; 391.906 392.048; 448.457 448.562; 469.931 470.028; 530.488 530.575; 555.180 558.136; 562.152 562.245; 588.403 588.502; 625.205 625.662; 638.019 638.438; 649.982 650.008; 650.691 651.357; 651.925 652.061; 665.445 665.472; 695.923 696.015; 706.528 706.720; 729.706 732.534], ... 627 [99.546 106.114; 113.245 114.199; 150.885 154.989; 277.486 278.075; 333.645 335.574; 339.358 340.646; 371.860 375.394; 497.459 499.156], ... 628 [49.008 50.205; 231.446 233.406; 329.590 329.659; 355.101 356.019; 360.733 360.973; 372.955 374.891; 389.283 392.068; 453.610 455.431; 464.632 465.265; 489.209 489.996; 514.777 515.295], ... 629 [178.368 179.232; 293.865 294.521; 418.252 418.314; 450.124 450.209; 480.236 480.445; 492.725 493.975; 495.170 497.624; 500.382 500.459; 504.247 504.402; 628.017 628.079; 628.827 628.905; 630.209 630.332], ... 630 [100.616 101.172; 107.691 108.539; 188.814 188.875; 193.119 193.281; 207.964 208.033; 432.254 432.385; 489.834 489.911; 517.960 518.037; 518.955 519.040; 520.938 521.062; 521.945 522.037; 523.959 524.052; 525.942 526.057; 526.945 527.015; 528.958 529.059; 531.138 531.192; 531.979 532.048; 532.951 533.028; 533.962 534.024], ... 631 [135.997 137.232; 383.565 383.657; 418.763 418.955]}; 632 BadSegments{9} = {... 633 [215.107 216.187; 262.388 262.388; 287.519 287.635; 289.895 290.135; 311.999 311.999; 350.161 351.179; 526.154 527.033; 564.999 564.999; 584.935 585.059; 587.999 587.999; 601.999 601.999; 603.999 603.999; 608.999 608.999; 612.999 612.999], ... 634 [47.667 47.775; 49.172 54.681; 67.195 70.805; 78.988 80.477; 138.701 138.948; 138.727 138.727; 138.728 138.728; 138.728 138.728; 138.734 138.734; 138.734 138.734; 138.881 138.881; 138.881 138.881; 138.907 138.907; 140.993 141.093; 141.037 141.037; 141.045 141.045; 155.795 155.864; 155.822 155.822; 155.849 155.849; 168.999 168.999; 206.999 206.999; 219.999 219.999; 225.999 225.999; 226.999 226.999; 228.999 228.999; 236.999 236.999; 242.463 242.463; 242.463 242.463; 242.487 242.487; 247.999 247.999; 251.999 251.999; 252.483 252.483; 253.315 254.163; 265.999 265.999; 267.999 267.999; 272.358 272.358; 272.410 272.410; 298.999 298.999; 300.999 300.999; 314.037 314.037; 314.047 314.047; 321.813 321.813; 321.813 321.813; 321.833 321.833; 329.117 329.117; 329.117 329.117; 329.156 329.156; 346.999 346.999; 347.999 347.999; 349.320 349.320; 349.329 349.329; 352.528 355.869; 364.040 364.040; 396.278 397.420; 404.865 404.865; 407.905 407.905; 407.905 407.905; 407.954 407.954; 418.454 418.454; 418.454 418.454; 418.486 418.486; 441.999 441.999; 444.999 444.999; 447.999 447.999; 453.550 453.650; 454.931 455.055; 457.999 457.999; 479.964 480.079; 481.999 481.999; 482.949 483.073; 488.948 489.064; 511.999 511.999; 520.999 520.999; 523.999 523.999; 526.954 527.069; 533.999 533.999; 537.999 537.999], ... 635 [82.889 83.198; 206.143 207.424; 403.873 404.096; 406.790 407.485; 413.936 414.075; 415.912 416.112; 536.621 537.532], ... 636 [182.999 182.999; 182.999 182.999; 183.999 183.999; 195.999 195.999; 208.999 208.999; 209.999 209.999; 278.601 278.955; 413.913 414.067; 415.250 417.792; 419.940 420.087; 420.999 420.999; 512.999 512.999; 514.363 516.254; 521.917 522.134; 522.999 522.999; 523.915 524.101; 533.999 533.999; 538.999 538.999; 539.892 540.062; 543.999 543.999; 548.874 549.089; 549.900 550.062; 552.755 554.075; 585.999 585.999; 587.957 588.073; 588.999 588.999; 594.999 594.999; 603.971 604.056; 604.928 605.097; 615.986 618.495; 623.999 623.999], ... 637 [53.215 54.203; 164.227 168.965; 201.433 202.775; 292.973 295.889; 303.961 304.817; 309.354 311.236; 313.123 313.639; 322.547 323.017; 331.141 334.852; 356.637 356.985; 367.855 368.079; 369.995 373.459; 377.849 378.142; 406.072 407.306; 436.164 436.665; 458.033 458.905; 516.889 518.656; 517.812 518.684], ... 638 [113.945 115.225; 198.570 198.863; 264.162 264.795; 383.705 385.641; 396.477 397.064; 399.706 406.457; 452.261 453.179; 486.338 487.102; 498.869 499.579; 507.968 508.925; 546.266 547.285; 558.825 560.128]}; 639 BadSegments{10} = {... 640 [235.104 236.184; 324.272 325.028; 330.799 331.401; 541.062 541.826; 564.747 565.072], ... 641 [100.581 101.229; 285.644 285.644; 285.644 285.644; 297.979 298.033; 298.999 298.999; 300.949 301.026; 301.999 301.999; 303.999 303.999; 304.999 304.999; 306.999 306.999; 307.999 307.999; 310.999 310.999; 311.999 311.999; 313.971 314.025; 314.999 314.999; 316.995 317.035; 317.999 317.999; 319.999 319.999; 320.923 321.046; 326.971 327.048; 327.999 327.999; 329.999 329.999; 330.999 330.999; 332.974 333.028; 333.999 333.999; 335.971 336.025; 336.999 336.999; 338.973 339.035; 339.999 339.999; 341.951 342.044; 343.999 343.999; 344.964 345.033; 346.999 346.999; 347.999 347.999; 452.015 453.411; 458.735 459.776; 467.974 468.089], ... 642 [41.266 41.675; 53.905 55.240; 159.159 159.345; 220.255 220.394], ... 643 [66.751 67.190; 201.674 201.812; 294.119 295.168; 303.188 303.528; 316.992 317.037; 317.999 317.999; 317.999 317.999; 319.999 319.999; 320.980 321.042; 322.999 322.999; 325.999 325.999; 326.955 327.048; 328.999 328.999; 333.999 333.999; 334.999 334.999; 342.999 342.999; 343.999 343.999; 351.915 352.038; 352.999 352.999; 407.979 408.056; 409.999 409.999; 411.999 411.999; 415.405 416.154; 435.999 435.999; 436.962 437.046; 468.885 469.100; 469.999 469.999; 470.999 470.999; 516.210 516.357], ... 644 [105.369 106.172; 141.468 142.178; 199.008 199.818; 201.269 201.716; 352.851 353.083; 449.865 452.041; 459.508 459.802], ... 645 [229.948 230.033; 230.999 230.999; 230.999 230.999; 259.588 259.990; 343.970 345.798; 361.999 361.999; 362.970 363.046; 364.999 364.999; 366.999 366.999; 367.962 368.031; 372.521 374.179; 405.999 405.999; 409.999 409.999; 411.999 411.999; 412.999 412.999; 434.999 434.999; 435.970 436.031; 516.999 516.999; 519.999 519.999]}; 646 BadSegments{11} = {... 647 [179.045 180.225; 323.999 323.999; 323.999 323.999; 324.999 324.999; 327.978 328.025; 328.966 329.028; 330.999 330.999; 365.999 365.999; 367.999 367.999; 370.999 370.999; 371.999 371.999; 373.999 373.999; 375.965 376.042; 377.999 377.999], ... 648 [52.107 53.156; 521.077 521.155], ... 649 [65.331 66.156], ... 650 [81.579 82.143; 108.565 108.565; 108.566 108.566; 112.176 112.176; 122.377 122.377; 122.565 122.565; 213.882 213.882; 215.305 215.305; 224.851 224.851; 224.919 224.919; 255.815 255.815; 257.893 257.893; 359.952 359.952; 361.630 361.754; 370.285 370.285; 376.853 376.853; 511.600 511.600; 513.631 513.631; 513.988 513.988; 518.215 518.215], ... 651 [63.205 64.154; 170.951 171.036; 176.841 176.841; 176.842 176.842; 177.282 177.282; 223.886 223.971; 259.963 259.963; 261.547 261.547; 341.185 341.302; 368.999 368.999; 370.999 370.999; 374.999 374.999; 382.971 383.033; 383.999 383.999; 386.999 386.999; 388.958 389.035; 390.999 390.999; 391.955 392.031; 394.955 395.040; 396.999 396.999; 398.999 398.999; 400.999 400.999; 402.999 402.999; 404.963 405.033; 406.999 406.999; 429.829 429.829; 430.346 430.346; 465.184 465.184; 470.290 470.290], ... 652 [50.195 51.145; 158.850 159.012]}; 653 BadSegments{12} = {... 654 [193.435 194.175; 500.000 501.000; 08.988 509.868; 528.999 528.999; 528.999 528.999; 529.999 529.999; 531.999 531.999; 547.999 547.999], ... 655 [133.484 134.185; 134.911 135.065; 553.999 553.999; 553.999 553.999; 554.999 554.999; 557.999 557.999; 558.999 558.999; 564.999 564.999; 565.977 566.046; 568.999 568.999; 569.951 570.028; 571.999 571.999; 579.959 580.028; 580.977 581.055; 583.971 584.033; 583.999 583.999; 585.999 585.999; 586.999 586.999; 588.980 589.026; 590.999 590.999; 591.958 592.044; 595.999 595.999], ... 656 [46.028 47.216; 129.557 130.236; 200.999 200.999; 200.999 200.999; 201.975 202.075; 203.999 203.999; 204.967 205.053; 213.627 214.515; 218.958 219.044; 222.959 228.252; 309.999 309.999; 311.897 317.537; 311.999 311.999; 351.968 353.234; 399.999 399.999; 446.508 451.454; 487.999 487.999; 512.278 512.926], ... 657 [82.535 84.062; 102.247 102.355; 134.999 134.999; 134.999 134.999; 136.999 136.999; 138.973 139.042; 147.999 147.999; 148.999 148.999; 149.999 149.999; 193.999 193.999; 194.999 194.999; 224.984 226.095; 241.954 242.077; 243.948 244.087; 280.999 280.999; 281.999 281.999; 305.000 305.451; 310.945 311.068; 328.999 328.999; 352.999 352.999; 353.999 353.999; 397.025 397.411; 415.944 418.096; 415.999 415.999; 470.999 470.999; 477.971 478.041; 483.997 484.737; 492.958 493.089; 493.999 493.999; 494.999 494.999; 522.999 522.999; 523.999 523.999; 524.955 525.039], ... 658 [175.183 176.155; 246.112 246.991; 412.005 413.340; 483.915 484.061; 485.959 486.028; 497.360 498.880; 594.457 594.944; 596.641 598.006; 615.277 618.710], ... 659 [66.900 72.232; 75.510 78.688; 543.495 545.999]}; 660 BadSegments{13} = {... 661 [307.246 308.179; 627.881 628.089; 629.941 630.049], ... 662 [171.506 172.301; 172.999 172.999; 430.999 430.999; 432.999 432.999; 434.999 434.999; 448.999 448.999; 479.999 479.999; 489.999 489.999; 490.999 490.999; 491.999 491.999], ... 663 [92.059 93.209], ... 664 [52.791 53.231; 54.999 54.999; 65.985 68.138; 91.240 91.386; 92.137 92.207; 105.346 105.493; 121.120 121.398; 146.546 146.955; 194.025 197.652; 242.985 243.571; 247.101 247.556; 269.889 270.083; 270.946 271.070; 274.408 275.866; 294.565 295.267; 319.370 319.879; 365.999 365.999; 375.913 376.044; 376.869 377.055; 377.999 377.999; 390.130 393.225; 403.965 404.035; 404.953 405.075; 419.265 419.565; 427.015 427.154; 427.879 428.118; 427.999 427.999; 428.913 429.067; 480.945 482.095; 484.285 484.571; 516.929 517.099; 517.963 518.079], ... 665 [115.921 116.060; 117.999 117.999; 120.999 120.999; 126.896 127.058; 130.955 131.039; 131.957 132.043; 132.961 133.015; 134.999 134.999; 135.950 136.043; 139.999 139.999; 143.999 143.999; 144.850 145.066; 145.999 145.999; 146.999 146.999; 160.929 161.045; 161.999 161.999; 189.086 189.310; 193.939 194.063; 195.975 196.045; 199.961 200.045; 201.952 202.059; 202.939 205.084; 210.999 210.999; 211.738 213.629; 217.954 218.061; 218.987 219.049; 219.975 220.028; 258.953 259.037; 259.952 260.045; 260.963 261.032; 261.958 262.043; 262.954 263.054; 262.999 262.999; 288.999 288.999; 295.477 295.655; 298.976 299.054; 299.979 300.018; 300.975 301.005; 336.952 337.044; 337.977 338.032; 338.988 339.027; 338.999 338.999; 339.991 340.045; 340.975 341.029; 341.978 342.016; 343.976 344.054; 361.961 362.045; 365.942 366.050; 370.999 370.999; 384.961 385.045; 409.977 410.047; 415.984 416.030; 426.944 427.059; 430.999 430.999; 436.999 436.999; 448.999 448.999; 449.500 452.131; 481.962 482.055; 482.973 483.027; 484.975 485.060; 503.999 503.999; 504.999 504.999; 507.967 508.028; 508.955 509.032; 510.999 510.999; 512.999 512.999; 518.865 520.292; 522.958 523.043; 523.999 523.999; 524.948 525.034; 525.959 526.044; 526.946 527.055; 527.942 528.027; 528.961 529.053; 529.945 530.022; 535.999 535.999; 536.957 537.058; 538.967 539.036; 539.963 540.040; 541.976 542.045; 543.999 543.999; 551.956 552.034; 552.990 553.028; 553.977 554.024; 555.968 556.022; 556.204 557.454; 557.963 558.032; 559.969 560.023; 563.973 564.035; 563.999 563.999], ... 666 [87.308 87.639; 107.039 108.189; 427.943 428.035; 437.965 438.027; 439.973 440.026; 491.275 492.571]}; 667 BadSegments{14} = {... 668 [365.982 367.194; 368.999 368.999; 368.999 368.999; 369.999 369.999; 371.999 371.999; 373.999 373.999; 375.942 376.050; 376.999 376.999; 378.999 378.999; 380.999 380.999; 382.999 382.999; 383.999 383.999; 386.999 386.999; 387.999 387.999; 418.999 418.999; 444.999 444.999; 690.178 693.218], ... 669 [101.796 102.183; 218.999 218.999; 219.999 219.999; 221.999 221.999; 222.999 222.999; 227.999 227.999; 229.999 229.999; 230.999 230.999; 232.999 232.999; 233.999 233.999; 235.999 235.999; 237.999 237.999; 238.985 239.031; 240.999 240.999; 242.999 242.999; 243.999 243.999; 246.999 246.999; 247.999 247.999; 253.999 253.999; 258.999 258.999; 259.999 259.999; 260.227 261.123; 264.999 264.999; 265.999 265.999; 268.999 268.999; 269.999 269.999; 274.999 274.999; 276.999 276.999; 277.999 277.999; 280.999 280.999; 282.966 283.021; 284.999 284.999; 285.999 285.999; 360.999 360.999; 362.973 363.026; 364.999 364.999; 365.999 365.999; 367.999 367.999; 368.985 369.024; 370.999 370.999; 371.999 371.999; 378.999 378.999; 379.999 379.999; 381.999 381.999; 383.999 383.999; 385.999 385.999; 387.999 387.999; 388.999 388.999; 398.999 398.999; 415.999 415.999; 417.999 417.999; 418.999 418.999; 421.999 421.999; 422.999 422.999], ... 670 [89.285 90.187], ... 671 [85.991 87.179; 88.999 88.999; 89.999 89.999; 92.966 93.027; 93.999 93.999; 107.999 107.999; 110.999 110.999; 111.971 112.025; 118.999 118.999; 121.999 121.999; 122.999 122.999; 166.999 166.999; 168.957 169.035; 173.999 173.999; 174.999 174.999; 175.957 176.035; 198.999 198.999; 199.999 199.999; 202.999 202.999; 203.999 203.999; 205.999 205.999; 207.999 207.999; 208.999 208.999; 210.974 211.044; 211.999 211.999; 212.999 212.999; 232.984 233.023; 234.999 234.999; 235.999 235.999; 236.999 236.999; 239.958 240.044; 240.999 240.999], ... 672 [71.132 72.227], ... 673 [98.134 98.827; 110.497 110.814; 114.000 117.272; 279.999 279.999; 279.999 279.999; 280.999 280.999; 282.999 282.999; 283.999 283.999; 284.999 284.999; 286.999 286.999; 287.999 287.999; 288.999 288.999; 289.999 289.999; 291.966 292.044; 292.999 292.999; 346.999 346.999; 437.608 437.646; 518.988 519.104; 522.969 523.015; 534.999 534.999; 536.967 537.029; 562.725 563.426]}; 674 BadSegments{15} = {... 675 [66.755 67.172; 257.988 258.042; 258.714 259.385; 260.958 261.044; 265.931 266.062; 267.968 268.022; 268.978 269.033; 270.992 271.031; 272.964 273.017; 273.968 274.030; 275.975 276.059; 276.970 277.046; 288.976 289.038; 289.984 290.015; 295.994 296.025; 296.982 297.013; 300.966 301.152; 364.730 364.800], ... 676 [46.531 46.555; 65.156 66.148; 87.535 87.642; 183.896 183.934; 294.342 294.375; 330.004 330.528; 333.785 333.815; 345.177 345.203; 399.544 399.573; 480.964 480.980], ... 677 [53.557 54.175; 148.851 149.136], ... 678 [43.681 44.214; 361.255 361.587; 409.462 411.021], ... 679 [90.868 91.130; 410.935 411.044], ... 680 [64.786 65.141; 132.385 132.786; 177.735 178.252; 278.747 278.902; 313.959 314.028; 314.970 315.031]}; 681 BadSegments{16} = {... 682 [38.958 44.335; 305.280 312.826; 324.778 326.067; 393.183 398.367; 403.410 422.854], ... 683 [49.726 50.251; 58.675 65.465; 263.918 264.088; 321.795 322.195; 522.881 523.081], ... 684 [61.245 62.325; 65.628 65.905; 315.686 317.275; 335.184 336.449; 387.870 388.117; 389.892 390.062], ... 685 [56.020 57.255; 60.711 61.096; 64.353 64.924; 73.202 73.757; 76.134 76.844; 95.625 96.859; 171.436 172.625; 178.359 178.715; 212.828 213.415; 352.425 352.617; 367.755 369.097; 488.400 489.426], ... 686 [71.665 72.513; 76.347 77.181; 127.134 128.862], ... 687 [46.190 47.209; 53.461 55.752; 194.317 194.510; 213.101 213.240; 216.356 216.442; 225.962 226.286; 245.163 245.464; 252.041 253.422; 254.648 254.856; 292.966 294.340; 340.928 341.067; 346.298 346.452]}; 688 BadSeg = BadSegments{iSubj}{iRun}'; 689 end 690

Running scripts on a cluster

Like mentioned above Brainstorm can be started in different ways. To use Brainstorm on a distant server the starting command "brainstorm server" needs to be used.

Before using Brainstorm on a distant server a few adjustments need to be done.

At first Matlab (including the Signal Processing Toolbox --- depending on the used functions) needs to be installed on the server and a Brainstorm version needs to be located on the server. For the Brainstorm database, the folder "brainstorm_db" needs to be created. Regarding the file structure on the server, the path for the brainstorm folders could look like this:

/home/user/brainstorm3

/home/user/brainstorm_db/anat

/home/user/brainstorm_db/data

In the "brainstorm_db" folder all the files you want to process need to be included. To not miss any files, the easiest solution would be to upload the whole "brainstorm_db" folder from your computer to the server. On the local computer Brainstorm might create missing files, e.g. "protocol.m", on its own. On the server it might not be able to do so and will crash.

To run a script using Brainstorm on a distant server also the script needs to be prepared. The following lines should be included:

% Set up the Brainstorm files
pathStr = '/home/user/brainstorm3/';
addpath(genpath(pathStr));
BrainstormDbDir = '/home/user/brainstorm_db';
% Start Brainstorm
if ~brainstorm('status')
    brainstorm server
end
bst_set('BrainstormDbDir',BrainstormDbDir)
% Select the correct protocol
ProtocolName = 'Study'; % Enter the name of your protocol
sProtocol.Comment = ProtocolName;
sProtocol.SUBJECTS = [home 'anat'];
sProtocol.STUDIES = [home 'data'];
db_edit_protocol('load',sProtocol);
% Get the protocol index
iProtocol = bst_get('Protocol', ProtocolName);
if isempty(iProtocol)
    error(['Unknown protocol: ' ProtocolName]);
end
% Select the current procotol
gui_brainstorm('SetCurrentProtocol', iProtocol);

Afterwards, you might add your analysis script. For example, you may create a script using the Brainstorm pipeline and add these lines to the top of your script and run it on the server.

To run a script using Brainstorm on a server you should check that there is a free matlab license on the server and RAM/Quota is big enough for the data you will create while processing. Also the Matlab version might differ from the version installed on your local computer. The lines above were tested using Matlab 2015b on a server.

A Brainstorm script can be executed either directly (it needs to start Brainstorm itself), or started using the syntax brainstorm <script.m> <parameters> (starts Brainstorm in server mode, executes the script and quit Brainstorm).

Brainstorm scripts can also be executed from the compiled version of Brainstorm, therefore not requiring a Matlab license, only the installation of the free MCR library (see the Installation page). Add the full path to the script to execute and the script parameters to the start script:
brainstorm3.bat <script.m> or brainstorm3.command <script.m>.

Finding interface callback functions

If you are looking for the function called by a menu or a button in the interface:

Additional documentation








Feedback: Comments, bug reports, suggestions, questions
Email address (if you expect an answer):


Tutorials/Scripting (last edited 2019-05-01 12:40:46 by FrancoisTadel)