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