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

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


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)2000-2020 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 275 if isempty(domain) 276 % Default Plot.ly server 277 domain = 'http://plot.ly'; 278 end 279 280 % Plotly needs a URL with HTTP and no trailing slash. 281 if strfind(domain, 'https://') 282 domain = strrep(domain, 'https://', 'http://'); 283 elseif isempty(strfind(domain, 'http://')) 284 domain = ['http://', domain]; 285 end 286 if domain(end) == '/' 287 domain = domain(1:end-1); 288 end 289 290 saveplotlycredentials(username, apiKey); 291 saveplotlyconfig(domain); 292 293 %% ==== ERROR ==== 294 otherwise 295 error('Invalid context : ''%s''', contextName); 296 297 298 end 299 300 301 302

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

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

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.

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:

Finding interface callback functions

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

Additional documentation








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


Tutorials/Scripting (last edited 2021-09-23 13:27:06 by FrancoisTadel)