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