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
>> bst_set('FieldTripDir', FieldTripDir)   % Set path to the FieldTrip toolbox

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

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

db_indices.gif

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

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

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

Example: Getting the data structure.

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

Example: Getting the subject structure.

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

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

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

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

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

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


To change parameters or database structures: bst_set.m.

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

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


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

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

Running scripts on a cluster

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:

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

% Load a new uploaded database (sets BrainstormDbDir and load the protocols it contains)
BrainstormDbDir = '/home/user/brainstorm_db';
db_import(BrainstormDbDir);

% Alternative: Set up the Brainstorm DB folder (defines where the protocols are created)
bst_set('BrainstormDbDir', BrainstormDbDir);

% Get the protocol index of an existing protocol (already registered or loaded previously)
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

% Select the current procotol
gui_brainstorm('SetCurrentProtocol', iProtocol);

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:

To avoid being asked for "brainstorm_db", add the command: local

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-03-19 08:14:32 by FrancoisTadel)