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