Tutorial 28: Scripting

Authors: Francois Tadel, Elizabeth Bock, 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.

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

Starting a new script

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

Line by line: Header

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

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

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

These lines define the script inputs:

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

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

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

Line by line: Body

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

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

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

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

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

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

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

bst_report('Open', ReportFile);

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

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

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

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

Simplify the calls

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

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

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

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

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

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

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

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

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

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

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

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

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

Evaluate in Matlab

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

edit1.gif

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

Undefined variable "SubjectNames" or class "SubjectNames".

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

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

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

Naming conventions

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

Running the script

The simplified script looks like this:

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

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

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

You have three ways to execute it:

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

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

Running the script again

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

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

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

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

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

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

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

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

Starting Brainstorm

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

brainstorm: Start Brainstorm with the regular GUI.

brainstorm nogui: Start in silent mode, without the GUI, without progress bar, without user interactions.

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

if ~brainstorm('status')
    brainstorm nogui
end

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

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

To delete the protocol and start over:

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

Additional command line options:

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

Database requests

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

Let's start with a few simple examples:

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

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

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

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

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

db_indices.gif

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

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

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

Example: Getting the data structure.

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

Example: Getting the subject structure.

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

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

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

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

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

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


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

File structures

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

Custom processing

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

Process: Run Matlab command

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

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

The corresponding script looks like this:

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

Export/Import with the database explorer

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

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

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

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

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

import_matlab.gif

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

Reference: File manipulation

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

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

Saving files:

Registering new files in the database:

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

Other useful database functions:

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

Convert Brainstorm structures to FieldTrip structures:

Reference: Display functions

Create new visualization figures:

Configure time-series figures:

Configure 3D figures:

Configure time-frequency figures:

Configure colormaps:

Configure statistical thresholding:

Export the contents of a figure to a file:

Example: Creating a new file

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

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

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

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

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

Option #1: db_add

OutputFile = db_add(iStudy, sMat);

Option #2: bst_save / db_reload_studies

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

Option #3: bst_save / db_add_data

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

Example: Editing events

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

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

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

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

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

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

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

>> iEvtButton
iEvtButton =
     3

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

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

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

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

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

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

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

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

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

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

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

Find examples in the code

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

find_files.gif

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

find_files2.gif

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

debugger.gif

Additional quality control

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

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

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

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

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

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

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

Report generated with the code above:

Loop over subjects

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

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

1 function tutorial_visual_full_single(tutorial_dir, reports_dir) 2 % TUTORIAL_VISUAL_FULL_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 % - tutorial_dir: Directory containing the folder ds000117_R1.0.0 (https://openfmri.org/dataset/ds000117/, version 1.0.0) 8 % |- ds000117_R1.0.0 9 % |- derivatives/freesurfer/sub-XX : Segmentation folders generated with FreeSurfer 10 % |- derivatives/meg_derivatives/sub-XX/ses-meg/meg/*.fif : MEG+EEG recordings (processed with MaxFilter's tSSS) 11 % |- sub-emptyroom/ses-meg/meg/090707_raw_st.fif : Empty room measurements 12 % - reports_dir: If defined, exports all the reports as HTML to this folder 13 14 % @============================================================================= 15 % This function is part of the Brainstorm software: 16 % https://neuroimage.usc.edu/brainstorm 17 % 18 % Copyright (c)2000-2018 University of Southern California & McGill University 19 % This software is distributed under the terms of the GNU General Public License 20 % as published by the Free Software Foundation. Further details on the GPLv3 21 % license can be found at http://www.gnu.org/copyleft/gpl.html. 22 % 23 % FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE 24 % UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY 25 % WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF 26 % MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY 27 % LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE. 28 % 29 % For more information type "brainstorm license" at command prompt. 30 % =============================================================================@ 31 % 32 % Author: Francois Tadel, Elizabeth Bock, 2016-2018 33 34 35 %% ===== SCRIPT VARIABLES ===== 36 % Full list of subjects to process 37 SubjectNames = {'sub-01', 'sub-02', 'sub-03', 'sub-04', 'sub-05', 'sub-06', 'sub-07', 'sub-08', 'sub-09', 'sub-10', ... 38 'sub-11', 'sub-12', 'sub-13', 'sub-14', 'sub-15', 'sub-16'}; 39 SubjectNoise = 'sub-emptyroom'; 40 % Bad channels {iSubj} = {Run01, Run02, Run03, Run04, Run05, Run06} 41 BadChannels{1} = {'EEG016', 'EEG070', 'EEG050',{'EEG008','EEG050'}, [], []}; 42 BadChannels{2} = {{'EEG027', 'EEG030', 'EEG038'}, 'EEG010', 'EEG010', 'EEG010', 'EEG010', 'EEG010'}; 43 BadChannels{3} = {{'EEG008','EEG017'}, {'EEG008','EEG017'}, {'EEG008','EEG017'}, {'EEG008','EEG017'}, {'EEG008','EEG017','EEG001'}, {'EEG008','EEG017','EEG020'}}; 44 BadChannels{4} = {{'EEG038'}, {'EEG038','EEG001','EEG016'}, {'EEG038','EEG001','EEG016'}, {'EEG038','EEG001'}, {'EEG038','EEG001','EEG016'}, {'EEG038','EEG001','EEG016'}}; 45 BadChannels{5} = {'EEG001', 'EEG001', [], [], [], []}; 46 BadChannels{6} = {'EEG068', [], 'EEG004', [], [], []}; 47 BadChannels{7} = {[], [], {'EEG004','EEG008'}, {'EEG004','EEG008'},{'EEG004','EEG008','EEG043','EEG045','EEG047'}, {'EEG004','EEG008'}}; 48 BadChannels{8} = {[], [], [], [], [], []}; 49 BadChannels{9} = {[], 'EEG004', 'EEG004', [], 'EEG004', 'EEG004'}; 50 BadChannels{10} = {[], [], [], [], [], []}; 51 BadChannels{11} = {{'EEG010','EEG050'}, 'EEG050', 'EEG050', 'EEG050', 'EEG050', 'EEG050'}; 52 BadChannels{12} = {{'EEG024','EEG057'}, {'EEG024','EEG057'}, {'EEG024','EEG057'}, {'EEG024','EEG057','EEG070'}, {'EEG024','EEG057'}, {'EEG024','EEG057','EEG070'}}; 53 BadChannels{13} = {'EEG009', 'EEG009', {'EEG009','EEG057','EEG69'}, 'EEG009', {'EEG009','EEG044'}, {'EEG009','EEG044'}}; 54 BadChannels{14} = {'EEG029', 'EEG029', 'EEG029', {'EEG004','EEG008','EEG016','EEG029'}, {'EEG004','EEG008','EEG016','EEG029'}, {'EEG004','EEG008','EEG016','EEG029'}}; 55 BadChannels{15} = {'EEG038', 'EEG038', 'EEG038', 'EEG038', {'EEG054','EEG038'}, 'EEG038'}; 56 BadChannels{16} = {'EEG008', 'EEG008', 'EEG008', 'EEG008', 'EEG008', 'EEG008'}; 57 % SSP components to remove {iSubj} = {sRun01, sRun02, sRun03, sRun03, sRun04, sRun05, sRun06}, sRun0X={ECG_GRAD,ECG_MAG} 58 SspSelect{1} = {{1,1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 59 SspSelect{2} = {{1,1}, {1,1}, {1,1}, {1,1}, {3,1}, {1,1}}; 60 SspSelect{3} = {{[],1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 61 SspSelect{4} = {{[],1}, {[],1}, {[],1}, {[],1}, {[],1}, {[],1}}; 62 SspSelect{5} = {{2,1}, {1,1}, {1,1}, {[],1}, {1,1}, {1,1}}; 63 SspSelect{6} = {{2,1}, {2,1}, {1,1}, {2,1}, {1,1}, {2,1}}; 64 SspSelect{7} = {{1,1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 65 SspSelect{8} = {{1,1}, {1,1}, {[],1}, {2,1}, {1,1}, {2,1}}; 66 SspSelect{9} = {{1,1}, {1,1}, {[],1}, {[],1}, {1,1}, {1,1}}; 67 SspSelect{10} = {{1,1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 68 SspSelect{11} = {{[],1}, {[],1}, {[],1}, {[],1}, {[],[]}, {[],[]}}; 69 SspSelect{12} = {{[1,2],[1,2]}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 70 SspSelect{13} = {{[],[]}, {[],[]}, {[],[]}, {[],[]}, {[],[]}, {[],[]}}; 71 SspSelect{14} = {{1,1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 72 SspSelect{15} = {{1,1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}}; 73 SspSelect{16} = {{1,1}, {1,1}, {1,1}, {2,1}, {1,1}, {1,1}}; 74 75 76 %% ===== CREATE PROTOCOL ===== 77 % Start brainstorm without the GUI 78 if ~brainstorm('status') 79 brainstorm nogui 80 end 81 % Output folder for reports 82 if (nargin < 2) || isempty(reports_dir) || ~isdir(reports_dir) 83 reports_dir = []; 84 end 85 % You have to specify the folder in which the tutorial dataset is unzipped 86 BidsDir = bst_fullfile(tutorial_dir, 'ds000117_R1.0.0'); 87 if (nargin < 1) || isempty(tutorial_dir) || ~file_exist(tutorial_dir) || ~file_exist(BidsDir) 88 error('The first argument must be the full path to the tutorial folder.'); 89 end 90 % The protocol name has to be a valid folder name (no spaces, no weird characters...) 91 ProtocolName = 'TutorialVisual'; 92 % Delete existing protocol 93 gui_brainstorm('DeleteProtocol', ProtocolName); 94 % Create new protocol 95 gui_brainstorm('CreateProtocol', ProtocolName, 0, 0); 96 % Set visualization filters: 40Hz low-pass, no high-pass 97 panel_filter('SetFilters', 1, 40, 0, [], 0, [], 0, 0); 98 % Set colormap: local color scale 99 bst_colormaps('SetMaxMode', 'meg', 'local'); 100 bst_colormaps('SetMaxMode', 'eeg', 'local'); 101 102 103 %% ===== PRE-PROCESS AND IMPORT ===== 104 for iSubj = 1:16 105 % Start a new report (one report per subject) 106 bst_report('Start'); 107 108 % If subject already exists: delete it 109 [sSubject, iSubject] = bst_get('Subject', SubjectNames{iSubj}); 110 if ~isempty(sSubject) 111 db_delete_subjects(iSubject); 112 end 113 114 % ===== FILES TO IMPORT ===== 115 % Build the path of the files to import 116 AnatDir = fullfile(BidsDir, 'derivatives', 'freesurfer', SubjectNames{iSubj}, 'ses-mri', 'anat'); 117 DataDir = fullfile(BidsDir, 'derivatives', 'meg_derivatives', SubjectNames{iSubj}, 'ses-meg', 'meg'); 118 % Check if the folder contains the required files 119 if ~file_exist(AnatDir) 120 error(['The folder "' AnatDir '" does not exist.']); 121 end 122 if ~file_exist(DataDir) 123 error(['The folder "' DataDir '" does not exist.']); 124 end 125 126 % ===== ANATOMY ===== 127 % Process: Import anatomy folder 128 bst_process('CallProcess', 'process_import_anatomy', [], [], ... 129 'subjectname', SubjectNames{iSubj}, ... 130 'mrifile', {AnatDir, 'FreeSurfer'}, ... 131 'nvertices', 15000); 132 133 % ===== PROCESS EACH RUN ===== 134 for iRun = 1:6 135 % Files to import 136 FifFile = bst_fullfile(DataDir, sprintf('%s_ses-meg_task-facerecognition_run-%02d_proc-tsss_meg.fif', SubjectNames{iSubj}, iRun)); 137 138 % ===== LINK CONTINUOUS FILE ===== 139 % Process: Create link to raw file 140 sFileRaw = bst_process('CallProcess', 'process_import_data_raw', [], [], ... 141 'subjectname', SubjectNames{iSubj}, ... 142 'datafile', {FifFile, 'FIF'}, ... 143 'channelreplace', 1, ... 144 'channelalign', 0); 145 146 % ===== PREPARE CHANNEL FILE ===== 147 % Process: Set channels type 148 bst_process('CallProcess', 'process_channel_settype', sFileRaw, [], ... 149 'sensortypes', 'EEG061, EEG064', ... 150 'newtype', 'NOSIG'); 151 bst_process('CallProcess', 'process_channel_settype', sFileRaw, [], ... 152 'sensortypes', 'EEG062', ... 153 'newtype', 'EOG'); 154 bst_process('CallProcess', 'process_channel_settype', sFileRaw, [], ... 155 'sensortypes', 'EEG063', ... 156 'newtype', 'ECG'); 157 158 % Process: Remove head points 159 sFileRaw = bst_process('CallProcess', 'process_headpoints_remove', sFileRaw, [], ... 160 'zlimit', 0); 161 % Process: Refine registration 162 sFileRaw = bst_process('CallProcess', 'process_headpoints_refine', sFileRaw, []); 163 % Process: Project electrodes on scalp 164 sFileRaw = bst_process('CallProcess', 'process_channel_project', sFileRaw, []); 165 166 % Process: Snapshot: Sensors/MRI registration 167 bst_process('CallProcess', 'process_snapshot', sFileRaw, [], ... 168 'target', 1, ... % Sensors/MRI registration 169 'modality', 1, ... % MEG (All) 170 'orient', 1, ... % left 171 'comment', sprintf('MEG/MRI Registration: Subject #%d, Run #%d', iSubj, iRun)); 172 bst_process('CallProcess', 'process_snapshot', sFileRaw, [], ... 173 'target', 1, ... % Sensors/MRI registration 174 'modality', 4, ... % EEG 175 'orient', 1, ... % left 176 'comment', sprintf('EEG/MRI Registration: Subject #%d, Run #%d', iSubj, iRun)); 177 178 % ===== IMPORT TRIGGERS ===== 179 % Process: Read from channel 180 bst_process('CallProcess', 'process_evt_read', sFileRaw, [], ... 181 'stimchan', 'STI101', ... 182 'trackmode', 2, ... % Bit: detect the changes for each bit independently 183 'zero', 0); 184 % Process: Group by name 185 bst_process('CallProcess', 'process_evt_groupname', sFileRaw, [], ... 186 'combine', 'Unfamiliar=3,4', ... 187 'dt', 0, ... 188 'delete', 1); 189 % Process: Rename event 190 bst_process('CallProcess', 'process_evt_rename', sFileRaw, [], ... 191 'src', '3', ... 192 'dest', 'Famous'); 193 % Process: Rename event 194 bst_process('CallProcess', 'process_evt_rename', sFileRaw, [], ... 195 'src', '5', ... 196 'dest', 'Scrambled'); 197 % Process: Add time offset 198 bst_process('CallProcess', 'process_evt_timeoffset', sFileRaw, [], ... 199 'info', [], ... 200 'eventname', 'Famous, Unfamiliar, Scrambled', ... 201 'offset', 0.0345); 202 % Process: Delete events 203 bst_process('CallProcess', 'process_evt_delete', sFileRaw, [], ... 204 'eventname', '1,2,6,7,8,9,10,11,12,13,14,15,16'); 205 % Process: Detect cHPI activity (Elekta):STI201 206 bst_process('CallProcess', 'process_evt_detect_chpi', sFileRaw, [], ... 207 'eventname', 'chpi_bad', ... 208 'channelname', 'STI201', ... 209 'method', 'off'); % Mark as bad when the HPI coils are OFF 210 211 % ===== FREQUENCY FILTERS ===== 212 % Process: Notch filter: 50Hz 100Hz 150Hz 200Hz 213 sFileClean = bst_process('CallProcess', 'process_notch', sFileRaw, [], ... 214 'freqlist', [50, 100, 150, 200], ... 215 'sensortypes', 'MEG, EEG', ... 216 'read_all', 0); 217 % Process: Power spectrum density (Welch) 218 sFilesPsd = bst_process('CallProcess', 'process_psd', [sFileRaw, sFileClean], [], ... 219 'timewindow', [], ... 220 'win_length', 4, ... 221 'win_overlap', 50, ... 222 'sensortypes', 'MEG, EEG', ... 223 'edit', struct(... 224 'Comment', 'Power', ... 225 'TimeBands', [], ... 226 'Freqs', [], ... 227 'ClusterFuncTime', 'none', ... 228 'Measure', 'power', ... 229 'Output', 'all', ... 230 'SaveKernel', 0)); 231 % Process: Snapshot: Frequency spectrum 232 bst_process('CallProcess', 'process_snapshot', sFilesPsd, [], ... 233 'target', 10, ... % Frequency spectrum 234 'comment', sprintf('Power spctrum: Subject #%d, Run #%d', iSubj, iRun)); 235 236 % ===== BAD CHANNELS ===== 237 if ~isempty(BadChannels{iSubj}{iRun}) 238 % Process: Set bad channels 239 bst_process('CallProcess', 'process_channel_setbad', sFileClean, [], ... 240 'sensortypes', BadChannels{iSubj}{iRun}); 241 end 242 243 % ===== EEG REFERENCE ===== 244 % Process: Re-reference EEG 245 bst_process('CallProcess', 'process_eegref', sFileClean, [], ... 246 'eegref', 'AVERAGE', ... 247 'sensortypes', 'EEG'); 248 249 % ===== DETECT ARTIFACTS ====== 250 % Process: Detect heartbeats 251 bst_process('CallProcess', 'process_evt_detect_ecg', sFileClean, [], ... 252 'channelname', 'EEG063', ... 253 'timewindow', [], ... 254 'eventname', 'cardiac'); 255 % Different amplitude thresholds for different subjects 256 if strcmpi(SubjectNames{iSubj}, 'sub-05') 257 thresholdMAX = 50; 258 else 259 thresholdMAX = 100; 260 end 261 % Process: Detect: blink_BAD - Detects all events where the amplitude exceeds 100uV 262 bst_process('CallProcess', 'process_evt_detect_threshold', sFileClean, [], ... 263 'eventname', 'blink_BAD', ... 264 'channelname', 'EEG062', ... 265 'timewindow', [], ... 266 'thresholdMAX', thresholdMAX, ... 267 'units', 3, ... % uV (10^-6) 268 'bandpass', [0.3, 20], ... 269 'isAbsolute', 1, ... 270 'isDCremove', 0); 271 272 % ===== SSP COMPUTATION ===== 273 % Process: SSP ECG: cardiac 274 bst_process('CallProcess', 'process_ssp_ecg', sFileClean, [], ... 275 'eventname', 'cardiac', ... 276 'sensortypes', 'MEG GRAD', ... 277 'usessp', 1, ... 278 'select', SspSelect{iSubj}{iRun}{1}); 279 bst_process('CallProcess', 'process_ssp_ecg', sFileClean, [], ... 280 'eventname', 'cardiac', ... 281 'sensortypes', 'MEG MAG', ... 282 'usessp', 1, ... 283 'select', SspSelect{iSubj}{iRun}{2}); 284 % Process: Snapshot: SSP projectors 285 bst_process('CallProcess', 'process_snapshot', sFileClean, [], ... 286 'target', 2, ... 287 'comment', sprintf('Subject #%d, Run #%d', iSubj, iRun)); % SSP projectors 288 289 % ===== IMPORT BAD EVENTS ===== 290 % Get bad segments: this is typically done manually, not from a script 291 BadSegments = GetBadSegments(iSubj, iRun); 292 % Process: Import from file 293 bst_process('CallProcess', 'process_evt_import', sFileClean, [], ... 294 'evtfile', {BadSegments, 'ARRAY-TIMES'}, ... 295 'evtname', 'BAD'); 296 297 % ===== IMPORT TRIALS ===== 298 % Process: Import MEG/EEG: Events 299 sFilesEpochs = bst_process('CallProcess', 'process_import_data_event', sFileClean, [], ... 300 'subjectname', SubjectNames{iSubj}, ... 301 'condition', '', ... 302 'eventname', 'Famous, Scrambled, Unfamiliar', ... 303 'timewindow', [], ... 304 'epochtime', [-0.5, 1.2], ... 305 'createcond', 0, ... 306 'ignoreshort', 1, ... 307 'usectfcomp', 1, ... 308 'usessp', 1, ... 309 'freq', [], ... 310 'baseline', [-0.5, -0.0009]); 311 312 % ===== AVERAGE: RUN ===== 313 % Process: Average: By trial group (folder average) 314 sFilesAvg = bst_process('CallProcess', 'process_average', sFilesEpochs, [], ... 315 'avgtype', 5, ... % By trial group (folder average) 316 'avg_func', 1, ... % Arithmetic average: mean(x) 317 'weighted', 0, ... 318 'keepevents', 0); 319 % Process: Snapshot: Recordings time series 320 bst_process('CallProcess', 'process_snapshot', sFilesAvg, [], ... 321 'target', 5, ... % Recordings time series 322 'modality', 4, ... % EEG 323 'time', 0.11, ... 324 'Comment', sprintf('Subject #%d, Run #%d', iSubj, iRun)); 325 % Process: Snapshot: Recordings time series 326 bst_process('CallProcess', 'process_snapshot', sFilesAvg, [], ... 327 'target', 6, ... % Recordings topography (one time) 328 'modality', 4, ... % EEG 329 'time', 0.11, ... 330 'Comment', sprintf('Subject #%d, Run #%d', iSubj, iRun)); 331 332 % ===== COMPUTE NOISECOV: EEG ===== 333 % Process: Compute covariance (noise or data) 334 bst_process('CallProcess', 'process_noisecov', sFilesEpochs, [], ... 335 'baseline', [-0.5, -0.0009], ... 336 'sensortypes', 'EEG', ... 337 'target', 1, ... % Noise covariance (covariance over baseline time window) 338 'dcoffset', 1, ... % Block by block, to avoid effects of slow shifts in data 339 'identity', 0, ... 340 'copycond', 0, ... 341 'copysubj', 0, ... 342 'replacefile', 1); % Replace 343 end 344 345 % Save report 346 ReportFile = bst_report('Save', []); 347 if ~isempty(reports_dir) && ~isempty(ReportFile) 348 bst_report('Export', ReportFile, bst_fullfile(reports_dir, ['report_' ProtocolName '_' SubjectNames{iSubj} '.html'])); 349 end 350 end 351 352 353 %% ===== EMPTY ROOM RECORDINGS ===== 354 % Loop on all the noise sessions 355 NoiseFiles = {}; 356 for ses = {'20090409', '20090506', '20090511', '20090515', '20090518', '20090601', '20091126', '20091208'} 357 NoiseFiles{end+1} = fullfile(BidsDir, 'derivatives', 'meg_derivatives', SubjectNoise, ['ses-' ses{1}], 'meg', ['sub-01_ses-' ses{1} '_task-noise_run-01_proc-tsss_meg.fif']); 358 end 359 % Process: Create link to raw file 360 sFilesNoise = bst_process('CallProcess', 'process_import_data_raw', [], [], ... 361 'subjectname', SubjectNoise, ... 362 'datafile', {NoiseFiles, 'FIF'}, ... 363 'channelreplace', 1, ... 364 'channelalign', 0); 365 % Process: Notch filter: 50Hz 100Hz 150Hz 200Hz 366 sFileNoiseClean = bst_process('CallProcess', 'process_notch', sFilesNoise, [], ... 367 'freqlist', [50, 100, 150, 200], ... 368 'sensortypes', 'MEG, EEG', ... 369 'read_all', 0); 370 % Process: Compute noise covariance 371 bst_process('CallProcess', 'process_noisecov', sFileNoiseClean, [], ... 372 'baseline', [], ... 373 'sensortypes', 'MEG', ... 374 'target', 1, ... % Noise covariance (covariance over baseline time window) 375 'dcoffset', 1, ... % Block by block, to avoid effects of slow shifts in data 376 'identity', 0, ... 377 'copycond', 1, ... 378 'copysubj', 1, ... 379 'copymatch', 1, ... 380 'replacefile', 2); % Merge 381 382 383 384 %% ===== SOURCE ESTIMATION ===== 385 % Start a new report (one report for the source estimation of all the subjects) 386 bst_report('Start'); 387 % Loop on the subjects: This loop is separated from the previous one, because we should 388 % compute the BEM surfaces after importing all the runs, so that the registration is done 389 % using the high resolution head surface, instead of the smooth scalp BEM layer. 390 for iSubj = 1:length(SubjectNames) 391 % ===== BEM SURFACES ===== 392 % Process: Generate BEM surfaces 393 bst_process('CallProcess', 'process_generate_bem', [], [], ... 394 'subjectname', SubjectNames{iSubj}, ... 395 'nscalp', 1082, ... 396 'nouter', 642, ... 397 'ninner', 642, ... 398 'thickness', 4); 399 400 % ===== SELECT ALL AVERAGES ===== 401 % Process: Select data files in: */* 402 sFilesAvg = bst_process('CallProcess', 'process_select_files_data', [], [], ... 403 'subjectname', SubjectNames{iSubj}); 404 % Process: Select file comments with tag: Avg 405 sFilesAvg = bst_process('CallProcess', 'process_select_tag', sFilesAvg, [], ... 406 'tag', 'Avg'); % Select only the files with the tag 407 408 % ===== COMPUTE HEAD MODELS ===== 409 % Process: Compute head model (only for the first run of the subject) 410 bst_process('CallProcess', 'process_headmodel', sFilesAvg(1), [], ... 411 'sourcespace', 1, ... % Cortex surface 412 'meg', 3, ... % Overlapping spheres 413 'eeg', 3, ... % OpenMEEG BEM 414 'ecog', 1, ... % 415 'seeg', 1, ... % 416 'openmeeg', struct(... 417 'BemSelect', [1, 1, 1], ... 418 'BemCond', [1, 0.0125, 1], ... 419 'BemNames', {{'Scalp', 'Skull', 'Brain'}}, ... 420 'BemFiles', {{}}, ... 421 'isAdjoint', 0, ... 422 'isAdaptative', 1, ... 423 'isSplit', 0, ... 424 'SplitLength', 4000)); 425 % Get all the runs for this subject (ie the list of the study indices) 426 iStudyOther = setdiff(unique([sFilesAvg.iStudy]), sFilesAvg(1).iStudy); 427 % Copy the forward model file to the other runs 428 sHeadmodel = bst_get('HeadModelForStudy', sFilesAvg(1).iStudy); 429 for iStudy = iStudyOther 430 db_add(iStudy, sHeadmodel.FileName); 431 end 432 433 % ===== COMPUTE SOURCES: MEG ===== 434 % Process: Compute sources [2018] 435 sAvgSrcMeg = bst_process('CallProcess', 'process_inverse_2018', sFilesAvg, [], ... 436 'output', 1, ... % Kernel only: shared 437 'inverse', struct(... 438 'Comment', 'MN: MEG ALL', ... 439 'InverseMethod', 'minnorm', ... 440 'InverseMeasure', 'amplitude', ... 441 'SourceOrient', {{'fixed'}}, ... 442 'Loose', 0.2, ... 443 'UseDepth', 1, ... 444 'WeightExp', 0.5, ... 445 'WeightLimit', 10, ... 446 'NoiseMethod', 'reg', ... 447 'NoiseReg', 0.1, ... 448 'SnrMethod', 'fixed', ... 449 'SnrRms', 1e-06, ... 450 'SnrFixed', 3, ... 451 'ComputeKernel', 1, ... 452 'DataTypes', {{'MEG GRAD', 'MEG MAG'}})); 453 % Process: Snapshot: Sources (one time) - Loop only to get a correct comment for the report 454 for i = 1:length(sAvgSrcMeg) 455 bst_process('CallProcess', 'process_snapshot', sAvgSrcMeg(i), [], ... 456 'target', 8, ... % Sources (one time) 457 'orient', 4, ... % bottom 458 'time', 0.11, ... 459 'threshold', 20, ... 460 'Comment', ['MEG sources: ' sFilesAvg(i).FileName]); 461 end 462 463 % ===== COMPUTE SOURCES: EEG ===== 464 % Process: Compute sources [2018] 465 sAvgSrcEeg = bst_process('CallProcess', 'process_inverse_2018', sFilesAvg, [], ... 466 'output', 1, ... % Kernel only: shared 467 'inverse', struct(... 468 'Comment', 'MN: EEG', ... 469 'InverseMethod', 'minnorm', ... 470 'InverseMeasure', 'amplitude', ... 471 'SourceOrient', {{'fixed'}}, ... 472 'Loose', 0.2, ... 473 'UseDepth', 1, ... 474 'WeightExp', 0.5, ... 475 'WeightLimit', 10, ... 476 'NoiseMethod', 'reg', ... 477 'NoiseReg', 0.1, ... 478 'SnrMethod', 'fixed', ... 479 'SnrRms', 1e-06, ... 480 'SnrFixed', 3, ... 481 'ComputeKernel', 1, ... 482 'DataTypes', {{'EEG'}})); 483 % Process: Snapshot: Sources (one time) - Loop only to get a correct comment for the report 484 for i = 1:length(sAvgSrcEeg) 485 bst_process('CallProcess', 'process_snapshot', sAvgSrcEeg(i), [], ... 486 'target', 8, ... % Sources (one time) 487 'orient', 4, ... % bottom 488 'time', 0.11, ... 489 'threshold', 10, ... 490 'Comment', ['EEG sources: ' sFilesAvg(i).FileName]); 491 end 492 end 493 % Save report 494 ReportFile = bst_report('Save', []); 495 if ~isempty(reports_dir) && ~isempty(ReportFile) 496 bst_report('Export', ReportFile, bst_fullfile(reports_dir, ['report_' ProtocolName '_sources.html'])); 497 end 498 499 500 %% ===== TIME-FREQUENCY ===== 501 % Start a new report (one report for the time-frequency of all the subjects) 502 bst_report('Start'); 503 % List of conditions to process separately 504 AllConditions = {'Famous', 'Scrambled', 'Unfamiliar'}; 505 % Channels to display in the screen capture, by order of preference (if the first channel is bad, use the following) 506 SelChannel = {'EEG070','EEG060','EEG065','EEG050','EEG003'}; 507 % Compute one separate time-frequency average for each subject/run/condition 508 for iSubj = 1:length(SubjectNames) 509 for iRun = 1:6 510 % Process: Select data files in: Subject/Run 511 sTrialsAll = bst_process('CallProcess', 'process_select_files_data', [], [], ... 512 'subjectname', SubjectNames{iSubj}, ... 513 'condition', sprintf('sub-%02d_ses-meg_task-facerecognition_run-%02d_proc-tsss_meg_notch', iSubj, iRun)); 514 % Loop on the conditions 515 for iCond = 1:length(AllConditions) 516 % Comment describing this average 517 strComment = [SubjectNames{iSubj}, ' / ', sprintf('run_%02d', iRun), ' / ', AllConditions{iCond}]; 518 disp(['BST> ' strComment]); 519 % Find the first good channel in the display list 520 if isempty(BadChannels{iSubj}{iRun}) 521 iSel = 1; 522 else 523 iSel = find(~ismember(SelChannel,BadChannels{iSubj}{iRun}), 1); 524 end 525 % Process: Select file comments with tag: Avg 526 sTrialsCond = bst_process('CallProcess', 'process_select_tag', sTrialsAll, [], ... 527 'tag', [AllConditions{iCond}, '_trial'], ... 528 'search', 1, ... % Search the file names 529 'select', 1); % Select only the files with the tag 530 % Process: Time-frequency (Morlet wavelets), averaged across trials 531 sTimefreq = bst_process('CallProcess', 'process_timefreq', sTrialsCond, [], ... 532 'sensortypes', 'MEG MAG, EEG', ... 533 'edit', struct(... 534 'Comment', ['Avg: ' AllConditions{iCond} ', Power, 6-60Hz'], ... 535 'TimeBands', [], ... 536 '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], ... 537 'MorletFc', 1, ... 538 'MorletFwhmTc', 3, ... 539 'ClusterFuncTime', 'none', ... 540 'Measure', 'power', ... 541 'Output', 'average', ... 542 'RemoveEvoked', 0, ... 543 'SaveKernel', 0), ... 544 'normalize', 'none'); % None: Save non-standardized time-frequency maps 545 % Process: Extract time: [-200ms,900ms] 546 sTimefreq = bst_process('CallProcess', 'process_extract_time', sTimefreq, [], ... 547 'timewindow', [-0.2, 0.9], ... 548 'overwrite', 1); 549 % Screen capture of one sensor 550 hFigTf = view_timefreq(sTimefreq.FileName, 'SingleSensor', SelChannel{iSel}); 551 bst_report('Snapshot', hFigTf, strComment, 'Time-frequency', [200, 200, 400, 250]); 552 close(hFigTf); 553 end 554 end 555 end 556 % Save report 557 ReportFile = bst_report('Save', []); 558 if ~isempty(reports_dir) && ~isempty(ReportFile) 559 bst_report('Export', ReportFile, bst_fullfile(reports_dir, ['report_' ProtocolName '_timefreq.html'])); 560 end 561 end 562 563 564 565 566 %% ===== SUPPORT FUNCTIONS ===== 567 function BadSeg = GetBadSegments(iSubj, iRun) 568 BadSegments{1} = {... 569 [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], ... 570 [84.791 85.166], ... 571 [79.183 80.167], ... 572 [64.309 65.185], ... 573 [90.958 91.167; 178.005 178.355; 293.282 295.919; 312.298 316.479; 353.835 357.716], ... 574 [60.292 66.802; 69.975 71.210; 105.233 107.586; 108.822 109.506; 376.225 376.325]}; 575 BadSegments{2} = {... 576 [223.806 224.199; 279.772 279.895; 453.241 455.108; 692.423 692.593], ... 577 [65.298 66.194; 304.727 306.178; 399.165 400.732], ... 578 [203.141 205.085; 281.579 287.883; 420.395 421.128], ... 579 [387.118 388.229; 440.318 441.900; 554.825 558.744], ... 580 [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], ... 581 [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]}; 582 BadSegments{3} = {... 583 [406.312 407.207; 727.055 728.714], ... 584 [84.894 85.156; 152.028 152.946; 297.835 298.915; 418.272 421.845; 554.084 554.794], ... 585 [73.758 74.159; 378.212 378.536; 406.065 407.099; 470.541 471.698; 488.900 491.168; 529.596 530.453], ... 586 [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], ... 587 [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], ... 588 [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]}; 589 BadSegments{4} = {... 590 [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], ... 591 [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], ... 592 [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], ... 593 [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], ... 594 [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], ... 595 [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]}; 596 BadSegments{5} = {... 597 [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], ... 598 [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], ... 599 [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], ... 600 [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], ... 601 [59.176 60.218; 74.854 75.317; 308.180 309.877; 380.705 381.059], ... 602 [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]}; 603 BadSegments{6} = {... 604 [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], ... 605 [64.898 65.161; 71.700 72.718; 226.185 226.740; 324.124 324.425; 329.062 329.301; 486.143 486.975], ... 606 [62.300 63.148; 266.254 266.639; 409.920 410.221], ... 607 [54.048 55.214; 330.893 331.255], ... 608 [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], ... 609 [44.720 45.167; 211.446 211.964; 368.955 369.172]}; 610 BadSegments{7} = {... 611 [154.966 155.144; 551.639 551.855], ... 612 [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], ... 613 [81.627 82.136; 377.953 381.046], ... 614 [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], ... 615 [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], ... 616 [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]}; 617 BadSegments{8} = {... 618 [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], ... 619 [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], ... 620 [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], ... 621 [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], ... 622 [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], ... 623 [135.997 137.232; 383.565 383.657; 418.763 418.955]}; 624 BadSegments{9} = {... 625 [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], ... 626 [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], ... 627 [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], ... 628 [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], ... 629 [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], ... 630 [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]}; 631 BadSegments{10} = {... 632 [235.104 236.184; 324.272 325.028; 330.799 331.401; 541.062 541.826; 564.747 565.072], ... 633 [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], ... 634 [41.266 41.675; 53.905 55.240; 159.159 159.345; 220.255 220.394], ... 635 [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], ... 636 [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], ... 637 [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]}; 638 BadSegments{11} = {... 639 [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], ... 640 [52.107 53.156; 521.077 521.155], ... 641 [65.331 66.156], ... 642 [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], ... 643 [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], ... 644 [50.195 51.145; 158.850 159.012]}; 645 BadSegments{12} = {... 646 [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], ... 647 [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], ... 648 [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], ... 649 [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], ... 650 [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], ... 651 [66.900 72.232; 75.510 78.688; 543.495 545.999]}; 652 BadSegments{13} = {... 653 [307.246 308.179; 627.881 628.089; 629.941 630.049], ... 654 [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], ... 655 [92.059 93.209], ... 656 [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], ... 657 [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], ... 658 [87.308 87.639; 107.039 108.189; 427.943 428.035; 437.965 438.027; 439.973 440.026; 491.275 492.571]}; 659 BadSegments{14} = {... 660 [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], ... 661 [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], ... 662 [89.285 90.187], ... 663 [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], ... 664 [71.132 72.227], ... 665 [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]}; 666 BadSegments{15} = {... 667 [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], ... 668 [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], ... 669 [53.557 54.175; 148.851 149.136], ... 670 [43.681 44.214; 361.255 361.587; 409.462 411.021], ... 671 [90.868 91.130; 410.935 411.044], ... 672 [64.786 65.141; 132.385 132.786; 177.735 178.252; 278.747 278.902; 313.959 314.028; 314.970 315.031]}; 673 BadSegments{16} = {... 674 [38.958 44.335; 305.280 312.826; 324.778 326.067; 393.183 398.367; 403.410 422.854], ... 675 [49.726 50.251; 58.675 65.465; 263.918 264.088; 321.795 322.195; 522.881 523.081], ... 676 [61.245 62.325; 65.628 65.905; 315.686 317.275; 335.184 336.449; 387.870 388.117; 389.892 390.062], ... 677 [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], ... 678 [71.665 72.513; 76.347 77.181; 127.134 128.862], ... 679 [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]}; 680 BadSeg = BadSegments{iSubj}{iRun}'; 681 end 682

Additional documentation








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


Tutorials/Scripting (last edited 2018-05-14 06:29:11 by FrancoisTadel)