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