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