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