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.

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.

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


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

File structures

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

Custom processing

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

Process: Run Matlab command

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

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

The corresponding script looks like this:

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

Export/Import with the database explorer

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

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

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

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

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

import_matlab.gif

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

Reference: File manipulation

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

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

Saving files:

Registering new files in the database:

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

Other useful database functions:

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

Convert Brainstorm structures to FieldTrip structures:

Reference: Display functions

Create new visualization figures:

Configure time-series figures:

Configure 3D figures:

Configure time-frequency figures:

Configure colormaps:

Configure statistical thresholding:

Export the contents of a figure to a file:

Example: Creating a new file

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

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

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

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

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

Option #1: db_add

OutputFile = db_add(iStudy, sMat);

Option #2: bst_save / db_reload_studies

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

Option #3: bst_save / db_add_data

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

Example: Editing events

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

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

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

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

>> sRaw.F.events
ans =
1x7 struct array with fields:
    label
    color
    epochs
    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 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 = cell(1, size(sMatRun2.F.events(iEvtSaccade).times, 2)); 361 sMatRun2.F.events(iEvtSaccade).notes = cell(1, size(sMatRun2.F.events(iEvtSaccade).times, 2)); 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 406 % ===== SELECT ALL AVERAGES ===== 407 % Process: Select data files in: */* 408 sFilesAvg = bst_process('CallProcess', 'process_select_files_data', [], [], ... 409 'subjectname', SubjectNames{iSubj}); 410 % Process: Select file comments with tag: Avg 411 sFilesAvg = bst_process('CallProcess', 'process_select_tag', sFilesAvg, [], ... 412 'tag', 'Avg'); % Select only the files with the tag 413 414 % ===== COMPUTE HEAD MODELS ===== 415 % Process: Compute head model (only for the first run of the subject) 416 bst_process('CallProcess', 'process_headmodel', sFilesAvg(1), [], ... 417 'sourcespace', 1, ... % Cortex surface 418 'meg', 3, ... % Overlapping spheres 419 'eeg', 3, ... % OpenMEEG BEM 420 'ecog', 1, ... % 421 'seeg', 1, ... % 422 'openmeeg', struct(... 423 'BemSelect', [1, 1, 1], ... 424 'BemCond', [1, 0.0125, 1], ... 425 'BemNames', {{'Scalp', 'Skull', 'Brain'}}, ... 426 'BemFiles', {{}}, ... 427 'isAdjoint', 0, ... 428 'isAdaptative', 1, ... 429 'isSplit', 0, ... 430 'SplitLength', 4000)); 431 % Get all the runs for this subject (ie the list of the study indices) 432 iStudyOther = setdiff(unique([sFilesAvg.iStudy]), sFilesAvg(1).iStudy); 433 % Copy the forward model file to the other runs 434 sHeadmodel = bst_get('HeadModelForStudy', sFilesAvg(1).iStudy); 435 for iStudy = iStudyOther 436 db_add(iStudy, sHeadmodel.FileName); 437 end 438 439 % ===== COMPUTE SOURCES: MEG ===== 440 % Process: Compute sources [2018] 441 sAvgSrcMeg = bst_process('CallProcess', 'process_inverse_2018', sFilesAvg, [], ... 442 'output', 1, ... % Kernel only: shared 443 'inverse', struct(... 444 'Comment', 'MN: MEG ALL', ... 445 'InverseMethod', 'minnorm', ... 446 'InverseMeasure', 'amplitude', ... 447 'SourceOrient', {{'fixed'}}, ... 448 'Loose', 0.2, ... 449 'UseDepth', 1, ... 450 'WeightExp', 0.5, ... 451 'WeightLimit', 10, ... 452 'NoiseMethod', 'reg', ... 453 'NoiseReg', 0.1, ... 454 'SnrMethod', 'fixed', ... 455 'SnrRms', 1e-06, ... 456 'SnrFixed', 3, ... 457 'ComputeKernel', 1, ... 458 'DataTypes', {{'MEG GRAD', 'MEG MAG'}})); 459 % Process: Snapshot: Sources (one time) - Loop only to get a correct comment for the report 460 for i = 1:length(sAvgSrcMeg) 461 bst_process('CallProcess', 'process_snapshot', sAvgSrcMeg(i), [], ... 462 'target', 8, ... % Sources (one time) 463 'orient', 4, ... % bottom 464 'time', 0.11, ... 465 'threshold', 20, ... 466 'Comment', ['MEG sources: ' sFilesAvg(i).FileName]); 467 end 468 469 % ===== COMPUTE SOURCES: EEG ===== 470 % Process: Compute sources [2018] 471 sAvgSrcEeg = bst_process('CallProcess', 'process_inverse_2018', sFilesAvg, [], ... 472 'output', 1, ... % Kernel only: shared 473 'inverse', struct(... 474 'Comment', 'MN: EEG', ... 475 'InverseMethod', 'minnorm', ... 476 'InverseMeasure', 'amplitude', ... 477 'SourceOrient', {{'fixed'}}, ... 478 'Loose', 0.2, ... 479 'UseDepth', 1, ... 480 'WeightExp', 0.5, ... 481 'WeightLimit', 10, ... 482 'NoiseMethod', 'reg', ... 483 'NoiseReg', 0.1, ... 484 'SnrMethod', 'fixed', ... 485 'SnrRms', 1e-06, ... 486 'SnrFixed', 3, ... 487 'ComputeKernel', 1, ... 488 'DataTypes', {{'EEG'}})); 489 % Process: Snapshot: Sources (one time) - Loop only to get a correct comment for the report 490 for i = 1:length(sAvgSrcEeg) 491 bst_process('CallProcess', 'process_snapshot', sAvgSrcEeg(i), [], ... 492 'target', 8, ... % Sources (one time) 493 'orient', 4, ... % bottom 494 'time', 0.11, ... 495 'threshold', 10, ... 496 'Comment', ['EEG sources: ' sFilesAvg(i).FileName]); 497 end 498 end 499 % Save report 500 ReportFile = bst_report('Save', []); 501 if ~isempty(reports_dir) && ~isempty(ReportFile) 502 bst_report('Export', ReportFile, bst_fullfile(reports_dir, ['report_' ProtocolName '_sources.html'])); 503 end 504 505 506 %% ===== TIME-FREQUENCY ===== 507 % Start a new report (one report for the time-frequency of all the subjects) 508 bst_report('Start'); 509 % List of conditions to process separately 510 AllConditions = {'Famous', 'Scrambled', 'Unfamiliar'}; 511 % Channels to display in the screen capture, by order of preference (if the first channel is bad, use the following) 512 SelChannel = {'EEG070','EEG060','EEG065','EEG050','EEG003'}; 513 % Compute one separate time-frequency average for each subject/run/condition 514 for iSubj = 1:length(SubjectNames) 515 disp(sprintf('\n===== TIME-FREQUENCY: SUBJECT #%d =====\n', iSubj)); 516 for iRun = 1:6 517 % Process: Select data files in: Subject/Run 518 sTrialsAll = bst_process('CallProcess', 'process_select_files_data', [], [], ... 519 'subjectname', SubjectNames{iSubj}, ... 520 'condition', sprintf('sub-%02d_ses-meg_task-facerecognition_run-%02d_proc-sss_meg_notch', iSubj, iRun)); 521 % Loop on the conditions 522 for iCond = 1:length(AllConditions) 523 % Comment describing this average 524 strComment = [SubjectNames{iSubj}, ' / ', sprintf('run_%02d', iRun), ' / ', AllConditions{iCond}]; 525 disp(['BST> ' strComment]); 526 % Find the first good channel in the display list 527 if isempty(BadChannels{iSubj}{iRun}) 528 iSel = 1; 529 else 530 iSel = find(~ismember(SelChannel,BadChannels{iSubj}{iRun}), 1); 531 end 532 % Process: Select file comments with tag: Avg 533 sTrialsCond = bst_process('CallProcess', 'process_select_tag', sTrialsAll, [], ... 534 'tag', [AllConditions{iCond}, '_trial'], ... 535 'search', 1, ... % Search the file names 536 'select', 1); % Select only the files with the tag 537 % Process: Time-frequency (Morlet wavelets), averaged across trials 538 sTimefreq = bst_process('CallProcess', 'process_timefreq', sTrialsCond, [], ... 539 'sensortypes', 'MEG MAG, EEG', ... 540 'edit', struct(... 541 'Comment', ['Avg: ' AllConditions{iCond} ', Power, 6-60Hz'], ... 542 'TimeBands', [], ... 543 '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], ... 544 'MorletFc', 1, ... 545 'MorletFwhmTc', 3, ... 546 'ClusterFuncTime', 'none', ... 547 'Measure', 'power', ... 548 'Output', 'average', ... 549 'RemoveEvoked', 0, ... 550 'SaveKernel', 0), ... 551 'normalize', 'none'); % None: Save non-standardized time-frequency maps 552 % Process: Extract time: [-200ms,900ms] 553 sTimefreq = bst_process('CallProcess', 'process_extract_time', sTimefreq, [], ... 554 'timewindow', [-0.2, 0.9], ... 555 'overwrite', 1); 556 % Screen capture of one sensor 557 hFigTf = view_timefreq(sTimefreq.FileName, 'SingleSensor', SelChannel{iSel}); 558 bst_report('Snapshot', hFigTf, strComment, 'Time-frequency', [200, 200, 400, 250]); 559 close(hFigTf); 560 end 561 end 562 end 563 % Save report 564 ReportFile = bst_report('Save', []); 565 if ~isempty(reports_dir) && ~isempty(ReportFile) 566 bst_report('Export', ReportFile, bst_fullfile(reports_dir, ['report_' ProtocolName '_timefreq.html'])); 567 end 568 end 569 570 571 572 573 %% ===== SUPPORT FUNCTIONS ===== 574 function BadSeg = GetBadSegments(iSubj, iRun) 575 BadSegments{1} = {... 576 [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], ... 577 [84.791 85.166], ... 578 [79.183 80.167], ... 579 [64.309 65.185], ... 580 [90.958 91.167; 178.005 178.355; 293.282 295.919; 312.298 316.479; 353.835 357.716], ... 581 [60.292 66.802; 69.975 71.210; 105.233 107.586; 108.822 109.506; 376.225 376.325]}; 582 BadSegments{2} = {... 583 [223.806 224.199; 279.772 279.895; 453.241 455.108; 692.423 692.593], ... 584 [65.298 66.194; 304.727 306.178; 399.165 400.732], ... 585 [203.141 205.085; 281.579 287.883; 420.395 421.128], ... 586 [387.118 388.229; 440.318 441.900; 554.825 558.744], ... 587 [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], ... 588 [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]}; 589 BadSegments{3} = {... 590 [406.312 407.207; 727.055 728.714], ... 591 [84.894 85.156; 152.028 152.946; 297.835 298.915; 418.272 421.845; 554.084 554.794], ... 592 [73.758 74.159; 378.212 378.536; 406.065 407.099; 470.541 471.698; 488.900 491.168; 529.596 530.453], ... 593 [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], ... 594 [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], ... 595 [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]}; 596 BadSegments{4} = {... 597 [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], ... 598 [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], ... 599 [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], ... 600 [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], ... 601 [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], ... 602 [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]}; 603 BadSegments{5} = {... 604 [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], ... 605 [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], ... 606 [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], ... 607 [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], ... 608 [59.176 60.218; 74.854 75.317; 308.180 309.877; 380.705 381.059], ... 609 [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]}; 610 BadSegments{6} = {... 611 [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], ... 612 [64.898 65.161; 71.700 72.718; 226.185 226.740; 324.124 324.425; 329.062 329.301; 486.143 486.975], ... 613 [62.300 63.148; 266.254 266.639; 409.920 410.221], ... 614 [54.048 55.214; 330.893 331.255], ... 615 [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], ... 616 [44.720 45.167; 211.446 211.964; 368.955 369.172]}; 617 BadSegments{7} = {... 618 [154.966 155.144; 551.639 551.855], ... 619 [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], ... 620 [81.627 82.136; 377.953 381.046], ... 621 [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], ... 622 [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], ... 623 [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]}; 624 BadSegments{8} = {... 625 [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], ... 626 [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], ... 627 [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], ... 628 [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], ... 629 [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], ... 630 [135.997 137.232; 383.565 383.657; 418.763 418.955]}; 631 BadSegments{9} = {... 632 [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], ... 633 [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], ... 634 [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], ... 635 [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], ... 636 [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], ... 637 [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]}; 638 BadSegments{10} = {... 639 [235.104 236.184; 324.272 325.028; 330.799 331.401; 541.062 541.826; 564.747 565.072], ... 640 [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], ... 641 [41.266 41.675; 53.905 55.240; 159.159 159.345; 220.255 220.394], ... 642 [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], ... 643 [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], ... 644 [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]}; 645 BadSegments{11} = {... 646 [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], ... 647 [52.107 53.156; 521.077 521.155], ... 648 [65.331 66.156], ... 649 [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], ... 650 [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], ... 651 [50.195 51.145; 158.850 159.012]}; 652 BadSegments{12} = {... 653 [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], ... 654 [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], ... 655 [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], ... 656 [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], ... 657 [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], ... 658 [66.900 72.232; 75.510 78.688; 543.495 545.999]}; 659 BadSegments{13} = {... 660 [307.246 308.179; 627.881 628.089; 629.941 630.049], ... 661 [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], ... 662 [92.059 93.209], ... 663 [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], ... 664 [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], ... 665 [87.308 87.639; 107.039 108.189; 427.943 428.035; 437.965 438.027; 439.973 440.026; 491.275 492.571]}; 666 BadSegments{14} = {... 667 [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], ... 668 [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], ... 669 [89.285 90.187], ... 670 [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], ... 671 [71.132 72.227], ... 672 [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]}; 673 BadSegments{15} = {... 674 [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], ... 675 [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], ... 676 [53.557 54.175; 148.851 149.136], ... 677 [43.681 44.214; 361.255 361.587; 409.462 411.021], ... 678 [90.868 91.130; 410.935 411.044], ... 679 [64.786 65.141; 132.385 132.786; 177.735 178.252; 278.747 278.902; 313.959 314.028; 314.970 315.031]}; 680 BadSegments{16} = {... 681 [38.958 44.335; 305.280 312.826; 324.778 326.067; 393.183 398.367; 403.410 422.854], ... 682 [49.726 50.251; 58.675 65.465; 263.918 264.088; 321.795 322.195; 522.881 523.081], ... 683 [61.245 62.325; 65.628 65.905; 315.686 317.275; 335.184 336.449; 387.870 388.117; 389.892 390.062], ... 684 [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], ... 685 [71.665 72.513; 76.347 77.181; 127.134 128.862], ... 686 [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]}; 687 BadSeg = BadSegments{iSubj}{iRun}'; 688 end 689

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 2022-06-24 10:19:40 by FrancoisTadel)