Tutorial 28: Scripting

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

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.

Warning: Never call clear, clear functions, clear classes or clear all while Brainstorm is running. It will clear variables, functions and classes that are needed by Brainstorm..

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).

% bst_report('Email', ReportFile, username, to, subject, isFullReport);

Sends the report by email, as explained in this later section: Send report by email.

% gui_brainstorm('EmptyTempFolder');

Delete all the files in the Brainstorm temporary folder.

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 name 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 names with tag: low
sAvgData = bst_process('CallProcess', 'process_select_tag', sAvgData, [], ...
    'tag',    'low', ...
    'search', 2, ...  % Search the file names
    '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 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 name.

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

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


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 % - bst_set('Pipelines') Saved Pipelines stored 89 % 90 % SEE ALSO bst_get 91 92 % @============================================================================= 93 % This function is part of the Brainstorm software: 94 % https://neuroimage.usc.edu/brainstorm 95 % 96 % Copyright (c) University of Southern California & McGill University 97 % This software is distributed under the terms of the GNU General Public License 98 % as published by the Free Software Foundation. Further details on the GPLv3 99 % license can be found at http://www.gnu.org/copyleft/gpl.html. 100 % 101 % FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE 102 % UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY 103 % WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF 104 % MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY 105 % LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE. 106 % 107 % For more information type "brainstorm license" at command prompt. 108 % =============================================================================@ 109 % 110 % Authors: Francois Tadel, 2008-2021 111 % Martin Cousineau, 2017 112 113 global GlobalData; 114 115 %% ==== PARSE INPUTS ==== 116 if ((nargin >= 1) && ischar(varargin{1})) 117 contextName = varargin{1}; 118 if (nargin >= 2) 119 contextValue = varargin{2}; 120 else 121 contextValue = []; 122 end 123 else 124 error('Usage : bst_set(contextName, contextValue)'); 125 end 126 127 % Get required context structure 128 switch contextName 129 %% ==== BRAINSTORM CONFIGURATION ==== 130 case 'Version' 131 GlobalData.Program.Version = contextValue; 132 case 'BrainstormHomeDir' 133 GlobalData.Program.BrainstormHomeDir = contextValue; 134 case 'BrainstormDbDir' 135 GlobalData.DataBase.BrainstormDbDir = contextValue; 136 case 'BrainstormTmpDir' 137 GlobalData.Preferences.BrainstormTmpDir = contextValue; 138 case 'Pipelines' 139 GlobalData.Processes.Pipelines = contextValue; 140 141 %% ==== PROTOCOL ==== 142 case 'iProtocol' 143 if isnumeric(contextValue) 144 GlobalData.DataBase.iProtocol = contextValue; 145 else 146 error('iProtocol should be a number.'); 147 end 148 case {'ProtocolSubjects', 'ProtocolStudies'} 149 for structField = fieldnames(contextValue)' 150 GlobalData.DataBase.(contextName)(GlobalData.DataBase.iProtocol).(structField{1}) = contextValue.(structField{1}); 151 end 152 GlobalData.DataBase.isProtocolModified(GlobalData.DataBase.iProtocol) = 1; 153 case 'ProtocolInfo' 154 for structField = fieldnames(contextValue)' 155 GlobalData.DataBase.(contextName)(GlobalData.DataBase.iProtocol).(structField{1}) = contextValue.(structField{1}); 156 end 157 case 'isProtocolLoaded' 158 GlobalData.DataBase.isProtocolLoaded(GlobalData.DataBase.iProtocol) = contextValue; 159 case 'isProtocolModified' 160 GlobalData.DataBase.isProtocolModified(GlobalData.DataBase.iProtocol) = contextValue; 161 162 %% ==== SUBJECT ==== 163 case 'Subject' 164 % Get subjects list 165 ProtocolSubjects = bst_get('ProtocolSubjects'); 166 iSubject = varargin{2}; 167 sSubject = varargin{3}; 168 % If default subject 169 if (iSubject == 0) 170 ProtocolSubjects.DefaultSubject = sSubject; 171 else 172 ProtocolSubjects.Subject(iSubject) = sSubject; 173 end 174 % Update DataBase 175 bst_set('ProtocolSubjects', ProtocolSubjects); 176 177 178 %% ==== STUDY ==== 179 case 'Study' 180 % Get studies list 181 ProtocolStudies = bst_get('ProtocolStudies'); 182 iStudies = varargin{2}; 183 sStudies = varargin{3}; 184 iAnalysisStudy = -2; 185 iDefaultStudy = -3; 186 for i = 1:length(iStudies) 187 % Normal study 188 if (iStudies(i) > 0) 189 ProtocolStudies.Study(iStudies(i)) = sStudies(i); 190 % Inter-subject analysis study 191 elseif (iStudies(i) == iAnalysisStudy) 192 ProtocolStudies.AnalysisStudy = sStudies(i); 193 % Default study 194 elseif (iStudies(i) == iDefaultStudy) 195 ProtocolStudies.DefaultStudy = sStudies(i); 196 end 197 end 198 % Update DataBase 199 bst_set('ProtocolStudies', ProtocolStudies); 200 201 202 %% ==== GUI ==== 203 % USAGE: bst_set('Layout', sLayout) 204 % bst_set('Layout', PropName, PropValue) 205 case 'Layout' 206 if (nargin == 2) && isstruct(contextValue) 207 GlobalData.Preferences.Layout = contextValue; 208 isUpdateScreens = 0; 209 elseif (nargin == 3) && ischar(contextValue) && isfield(GlobalData.Preferences, 'Layout') && isfield(GlobalData.Preferences.Layout, contextValue) 210 GlobalData.Preferences.Layout.(contextValue) = varargin{3}; 211 isUpdateScreens = strcmpi(contextValue, 'DoubleScreen'); 212 else 213 error('Invalid call to bst_set.'); 214 end 215 % Update screen configuration 216 GlobalData.Program.ScreenDef = gui_layout('GetScreenClientArea'); 217 % Update layout right now 218 gui_layout('Update'); 219 % If the number of screen was changed: update the maximum size of the Brainstorm window 220 if isUpdateScreens 221 gui_layout('UpdateMaxBstSize'); 222 end 223 224 % USAGE: bst_set('FixedScaleY', []) 225 % bst_set('FixedScaleY', Modality, Value) 226 case 'FixedScaleY' 227 if (nargin == 3) && ~isempty(contextValue) && ~isempty(varargin{3}) 228 GlobalData.Preferences.FixedScaleY.(contextValue) = varargin{3}; 229 elseif (nargin == 2) && isempty(contextValue) 230 GlobalData.Preferences.FixedScaleY = struct(); 231 end 232 233 case 'ByteOrder' 234 switch(contextValue) 235 case {'b','ieee-le','n'} 236 GlobalData.Preferences.ByteOrder = 'b'; 237 case {'l','ieee-be'} 238 GlobalData.Preferences.ByteOrder = 'l'; 239 otherwise 240 error('Invalid byte order.'); 241 end 242 243 case 'Clipboard' 244 if (length(varargin) >= 3) 245 isCut = varargin{3}; 246 else 247 isCut = 0; 248 end 249 GlobalData.Program.Clipboard.Nodes = contextValue; 250 GlobalData.Program.Clipboard.isCut = isCut; 251 252 case 'ElectrodeConfig' 253 Modality = varargin{2}; 254 ElectrodeConf = varargin{3}; 255 if isequal(Modality, 'ECOG+SEEG') 256 Modality = 'ECOG_SEEG'; 257 elseif ~ismember(Modality, {'EEG','SEEG','ECOG','MEG'}) 258 error(['Invalid modality: ' Modality]); 259 end 260 GlobalData.Preferences.(contextName).(Modality) = ElectrodeConf; 261 262 case 'ElecInterpDist' 263 Modality = varargin{2}; 264 ElecInterpDist = varargin{3}; 265 if isequal(Modality, 'ECOG+SEEG') 266 Modality = 'ECOG_SEEG'; 267 elseif ~ismember(Modality, {'EEG','SEEG','ECOG','MEG'}) 268 error(['Invalid modality: ' Modality]); 269 end 270 GlobalData.Preferences.(contextName).(Modality) = ElecInterpDist; 271 272 case {'UniformizeTimeSeriesScales', 'XScale', 'YScale', 'FlipYAxis', 'AutoScaleY', 'ShowXGrid', 'ShowYGrid', 'ShowZeroLines', 'ShowEventsMode', ... 273 'Resolution', 'AutoUpdates', 'ExpertMode', 'DisplayGFP', 'ForceMatCompression', 'GraphicsSmoothing', 'DownsampleTimeSeries', ... 274 'DisableOpenGL', 'InterfaceScaling', 'TSDisplayMode', 'UseSigProcToolbox', 'LastUsedDirs', 'DefaultFormats', ... 275 'BFSProperties', 'ImportDataOptions', 'ImportEegRawOptions', 'RawViewerOptions', 'MontageOptions', 'TopoLayoutOptions', ... 276 'StatThreshOptions', 'ContactSheetOptions', 'ProcessOptions', 'BugReportOptions', 'DefaultSurfaceDisplay', ... 277 'MagneticExtrapOptions', 'MriOptions', 'ConnectGraphOptions', 'NodelistOptions', 'IgnoreMemoryWarnings', 'SystemCopy', ... 278 'TimefreqOptions_morlet', 'TimefreqOptions_hilbert', 'TimefreqOptions_fft', 'TimefreqOptions_psd', 'TimefreqOptions_stft', 'TimefreqOptions_plv', ... 279 'OpenMEEGOptions', 'DuneuroOptions', 'DigitizeOptions', 'PcaOptions', 'CustomColormaps', 'PluginCustomPath', 'BrainSuiteDir', 'PythonExe', ... 280 'GridOptions_headmodel', 'GridOptions_dipfit', 'LastPsdDisplayFunction', 'KlustersExecutable', 'ExportBidsOptions', 'ShowHiddenFiles'} 281 GlobalData.Preferences.(contextName) = contextValue; 282 283 case 'ReadOnly' 284 GlobalData.DataBase.isReadOnly = contextValue; 285 286 case 'PlotlyCredentials' 287 if length(varargin) ~= 4 288 error('Invalid call to bst_set.'); 289 end 290 [username, apiKey, domain] = varargin{2:4}; 291 % Default domain: plot.ly 292 if isempty(domain) 293 domain = 'https://plot.ly'; 294 end 295 % Plotly needs a URL with HTTP and no trailing slash. 296 if strfind(domain, 'https://') 297 domain = strrep(domain, 'https://', 'http://'); 298 elseif isempty(strfind(domain, 'http://')) 299 domain = ['http://', domain]; 300 end 301 if domain(end) == '/' 302 domain = domain(1:end-1); 303 end 304 % Save credentials 305 saveplotlycredentials(username, apiKey); 306 saveplotlyconfig(domain); 307 308 %% ==== ERROR ==== 309 otherwise 310 error('Invalid context : ''%s''', contextName); 311 312 313 end 314 315 316 317

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

Matlab

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.

Files

In addtion to export to Matlab, files in the database explorer can be exported as files. Right-click on the Deviant average in the database explorer > File > Export to File. Indicate the filename of the file format for the destination folder. The available file formats depend on the type of file to export.

Also, 'data' (raw and imported/trial recordings), 'results' (sources), 'timefreq' (time-frequency, spectrum and connectivity), or 'matrix' (any time series extracted from other files) files can be also exported to files using the process: File > Export to file .

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
    times
    reactTimes
    select
    channels
    notes

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. If you add or remove events, you must adjust the size of the other fields: epochs (always 1 for most file formats), channels and notes (cell array of empty matrices in most cases).

% 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).times = sRaw.F.events(iEvtNew).times + 0.03
% Round new time values to the nearest sample
sRaw.F.events(iEvtNew).times = ...
    round(sRaw.F.events(iEvtNew).times .* sRaw.F.prop.sfreq) ./ sRaw.F.prop.sfreq;
% Re-generate an epochs field with only ones, and empty notes and channels fields
% (optional here, as we didn't change the number of evt)
nTimes = size(sRaw.F.events(iEvtNew).times, 2);
sRaw.F.events(iEvtNew).epochs = ones(1, nTimes);
sRaw.F.events(iEvtNew).channels = cell(1, nTimes);
sRaw.F.events(iEvtNew).notes = cell(1, nTimes);
% 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]
         times: [1x40 double]
    reactTimes: []
        select: 1
      channels: {1x40 cell}
         notes: {1x40 cell}

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 Matlab's 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

Find interface callback functions

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

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

Temporary files

Some processes need to create temporary files on the hard drive. For example, when epoching MEG/EEG recordings, Brainstorm would first create a temporary folder import_yymmdd_hhmmss, store all the epochs in it, then move them to the database when the epoching process is completed. The name of the temporary folder indicates its creation time (year/month/day_hour_minutes_seconds).

The default folder where Brainstorm stores its temporary files is located in the user folder ($HOME/.brainstorm/tmp/). This can be changed as explained in the introduction tutorial Create protocol.

At the end of each process, all the temporary files should be deleted automatically. However, in some cases, the process crashes or is killed before it can delete its temporary files. When starting the Brainstorm interface, users gets offered to delete the remaining temporary files. However, when running Brainstorm only from scripts, these files may never be deleted or made explicitly visible. To avoid these leftover temporary files to pile up indefinitely, it can be useful to add an explicit call to the function below, which deletes all of them.

gui_brainstorm('EmptyTempFolder');

Warning: Do not call this function in scripts that are supposed to be executed in parallel from the same user, as it might delete the temporary files from another session of Brainstorm.

Parallel processing

At the moment, Brainstorm is not capable of safely handling multiple sessions executed on the same computer, from the same user or on the same database folder. We are working on a new version of the databasing system that will support concurrent accesses. Until this is released, you should not have multiple people working at the same time with the same database, or multiple Matlab/Brainstorm instances running in parallel.

In some specific cases, however, it is possible to start multiple long processes simultaneously without much risk. For example, starting the BrainSuite MRI segmentation for multiple subjects within the same protocol can make sense. Some recommendations to run this safely:

Note that parallel processing does not always improve global performances. Many Matlab functions are already optimized to distribute their computation load over multiple CPUs. Running these in parallel from multiple instances of Matlab could be slower and less efficient in terms of memory usage, than running them sequentially from the same instance. Before deciding on running tasks in parallel, unless they are clearly not optimized to work on multiple cores (e.g. FreeSurfer segmentation), you should always run some tests to make sure it improves the global computation time.

Running scripts on a cluster

With Matlab

Matlab, including the toolboxes you need, needs to be installed on the server and a Brainstorm version needs to be located on the server. Start Brainstorm with the command "brainstorm server".

For the database: the folder "brainstorm_db" needs to be registered at the beginning of the script. You can either upload a protocol folder from your local computer, or create an empty brainstorm_db folder and a new protocol on the distance server. At the end of this initialization phase, you need to have something like the structure below:

Your processing script could start with some of the elements below, depending on what you need:

% Start Brainstorm
cd /home/user/brainstorm3;
if ~brainstorm('status')
    brainstorm server
end

% Path to a Brainstorm database (= a folder that contains one or more Brainstorm protocols)
BrainstormDbDir = '/home/user/brainstorm_db';

% Load a new uploaded database (sets BrainstormDbDir and load all the protocols it contains)
db_import(BrainstormDbDir);

% Alternative: Set the Brainstorm DB folder
% (defines where the new protocols are going to be created, but does not load anything)
bst_set('BrainstormDbDir', BrainstormDbDir);

% Get the protocol index of an existing protocol (already loaded previously in Brainstorm)
iProtocol = bst_get('Protocol', ProtocolName);

% Create a new protocol if needed
if isempty(iProtocol)
    UseDefaultAnat = 0;
    UseDefaultChannel = 0;
    gui_brainstorm('CreateProtocol', ProtocolName, UseDefaultAnat, UseDefaultChannel);
end

% Delete an existing protocol
gui_brainstorm('DeleteProtocol', ProtocolName);

Execution: You should check that there is a Matlab license available on the server, and that RAM and disk quotas are large enough for the data you will create while processing. The Matlab version might differ from the version installed on your local computer or toolboxes might be missing, causing some errors.

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

External Matlab call

To call a Brainstorm script directly from the command line of a terminal and avoid the graphical environment of Matlab to get started, on Linux or MacOS, you can use the syntax:

matlab -nosplash -nodesktop -r "run('/path/to/script.m');"

Without Matlab

Brainstorm scripts can also be executed from the compiled version of Brainstorm, therefore not requiring a Matlab license, only the installation of the free MATLAB Runtime (see installation instructions, section "without Matlab"). Add the full path to the script and the parameters to the command line:

In this configuration, Brainstorm is started using the command brainstorm server and then the script is executed. Therefore, your script should not start brainstorm again: remove the line "brainstorm server" from the example script in the section above.

In this configuration, the Matlab Runtime is not allowed to compile and execute .m scripts as a regular Matlab installation would. To work around this limitation, Brainstorm reads the script.m file and executes its contents with the Matlab eval function. Therefore this approach does not support the definition of functions or classes within the script.m. The compiled version of Brainstorm can only run code that can be executed from the Matlab Command Window. If you need more flexibility, you need to recompile a modified version of Brainstorm including your custom code (see below).

Parameters

The syntax of the script changes depending on the input parameters it accepts from the command line.

No extra parameters

The .m file must have the structure of a simple script, with no additional function definition.

Example script.m:

disp(['SCRIPT> Script start.']);
sStudy = bst_get('Study');
disp(['SCRIPT> Current study path: ' sStudy.FileName 10]);

Execution from the command line:

>> brainstorm 'C:\Users\franc\Downloads\GetStudyPath.m'

BST> Starting Brainstorm:
BST> =================================
BST> Version: 15-Jun-2022
BST> Deleting old process reports...
BST> Loading configuration file...
BST> Reading process folder...
BST> Loading current protocol...
BST> =================================

SCRIPT> Script start.
SCRIPT> Current study path: Subject01/S01_AEF_20131218_01_600Hz_notch/brainstormstudy.mat

BST> Emptying temporary directory...
BST> Brainstorm stopped.

Extra command line parameters

The .m file must declare a function on its first line. The number and names of parameters are parsed by Brainstorm from this first line, matched with the parameters passed from the command line, then the first line is removed and the rest of the code is executed with eval. Avoid including the "end" statement for the function, as it would result in more work to identify and remove it from the code. No other functions, sub-functions or classes can be declared in the same .m file.

Note that parameters are received as char arrays in the code: if you are expecting to pass numerical values, then the values must be parsed from the string (eg. with str2num).

Example script.m:

function GetStudyPath(iStudy)

disp([10 'SCRIPT> Script start.']);
sStudy = bst_get('Study', str2num(iStudy));
disp(['SCRIPT> Study path: ' sStudy.FileName 10]);

Execution from the command line:

>> brainstorm 'C:\Users\franc\Downloads\GetStudyPath.m' 1

BST> Starting Brainstorm:
BST> =================================
BST> Version: 15-Jun-2022
BST> Deleting old process reports...
BST> Loading configuration file...
BST> Reading process folder...
BST> Loading current protocol...
BST> =================================

WARNING: This file is a function, trying to convert to a script...

SCRIPT> Script start.
SCRIPT> Study path: Test/@default_study/brainstormstudy.mat

BST> Emptying temporary directory...
BST> Brainstorm stopped.

Send report by email

When running some long computation on a distant server, it can be convenient to receive an email when the processing is over. Two solutions for sending yourself an email from Brainstorm: from the pipeline editor, or directly from a script.

Use the process File > Send report by email to send the current execution report:

Alternatively, use one of the following options (isFullReport can be set to 0 or 1):

% At the end of your script
ReportFile = bst_report('Save', sFiles);
bst_report('Email', ReportFile, username, to, subject, isFullReport);

% Anywhere in your script
bst_report('Email', 'current', username, to, subject, isFullReport);

How to compile Brainstorm

Brainstorm can be compiled as a JAR application using the function bst_compile.m. You would need this in order to execute without Matlab a modified version of Brainstorm.

Software requirements:

To compile Brainstorm, run from the command line:

Additional documentation








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


Tutorials/Scripting (last edited 2024-06-17 21:59:30 by RaymundoCassani)