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