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


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 % http://neuroimage.usc.edu/brainstorm 83 % 84 % Copyright (c)2000-2017 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 % http://neuroimage.usc.edu/brainstorm 10 % 11 % Copyright (c)2000-2017 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 [2016] 634 sFilesSrcDeviant01 = bst_process('CallProcess', 'process_inverse_2016', 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 [2016] 677 sFilesSrcUnconst = bst_process('CallProcess', 'process_inverse_2016', 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_2016', 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 [2016] 758 sFilesAvgSrc = bst_process('CallProcess', 'process_inverse_2016', 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_single.m - Report: report_TutorialVisual_sub001.html

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

Additional documentation








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


Tutorials/Scripting (last edited 2016-11-01 22:18:13 by FrancoisTadel)