function ft_defaults

% FT_DEFAULTS (ending with "s") sets some general settings in the global variable
% ft_default (without the "s") and takes care of the required path settings. You can
% call this function in your startup.m script. This function is also called at the
% begin of all FieldTrip functions.
%
% The global configuration defaults are stored in the global "ft_default" structure.
% The ft_checkconfig function that is called by many FieldTrip functions will merge
% these global configuration defaults with the cfg ctructure that you pass to
% the FieldTrip function that you are calling.
%
% The global options and their default values are
%   ft_default.checkconfig       = string, can be 'pedantic', 'loose', 'silent' (default = 'loose')
%   ft_default.checkpath         = string, can be 'pedantic', 'once', 'no' (default = 'pedantic')
%   ft_default.checksize         = number in bytes, can be inf (default = 1e5)
%   ft_default.checkstring       = string, can be 'yes' or 'no' (default = 'yes'), convert "strings" in cfg to 'chars'
%   ft_default.showlogo          = string, can be 'yes' or 'no' (default = 'yes')
%   ft_default.showcallinfo      = string, can be 'yes' or 'no' (default = 'yes')
%   ft_default.trackcallinfo     = string, can be 'yes' or 'no' (default = 'yes')
%   ft_default.trackusage        = false, or string with salt for one-way encryption of identifying information (by default this is enabled and an automatic salt is created)
%   ft_default.trackdatainfo     = string, can be 'yes' or 'no' (default = 'no')
%   ft_default.keepprevious      = string, can be 'yes' or 'no' (default = 'yes')
%   ft_default.outputfilepresent = string, can be 'keep', 'overwrite', 'error' (default = 'overwrite')
%   ft_default.debug             = string, can be 'display', 'displayonerror', 'displayonsuccess', 'save', 'saveonerror', saveonsuccess' or 'no' (default = 'no')
%   ft_default.toolbox.signal    = string, can be 'compat' or 'matlab' (default is automatic, see below)
%   ft_default.toolbox.stats     = string, can be 'compat' or 'matlab' (default is automatic, see below)
%   ft_default.toolbox.images    = string, can be 'compat' or 'matlab' (default is automatic, see below)
%   ft_default.reproducescript   = string, directory to which the script and intermediate data are written (default = [])
%
% If you want to overrule these default settings, you can add something like this in your startup.m script
%   ft_defaults
%   global ft_default
%   ft_default.option1 = value1
%   ft_default.option2 = value2
%
% The toolbox option for signal, stats and images allows you to specify whether you
% want to use the original version from MathWorks or a compatible drop-in to be used.
% When you use the Radboud University license server, i.e. at the Donders, the
% default is 'compat'. This has the advantage that you do not need a license for
% these toolboxes; we do not have that many licenses and parallel computations on our
% Donders compute cluster would otherwise use all licenses. In all other cases, the
% default is 'matlab' when the toolbox is available, and 'compat' when it is not
% available.
%
% See also FT_HASTOOLBOX, FT_CHECKCONFIG, FT_TRACKUSAGE, LICENSE

% undocumented options
%   ft_default.siunits        = 'yes' or 'no'

% Copyright (C) 2009-2022, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

global ft_default

persistent initialized
persistent checkpath

if isempty(initialized)
  initialized = false;
end

if isempty(checkpath)
  checkpath = false;
end

% ft_warning is located in fieldtrip/utilities, which may not be on the path yet
if ~initialized && ~exist('ft_warning', 'file')
  ft_warning = @warning;
end

% locate the file with the persistent FieldTrip preferences
fieldtripprefs = fullfile(prefdir, 'fieldtripprefs.mat');
if ~initialized && exist(fieldtripprefs, 'file')
  prefs       = load(fieldtripprefs); % the file contains multiple fields
  ft_default  = mergestruct(ft_default, prefs);
end

% Set the defaults in a global variable, ft_checkconfig will copy these over into the local configuration.
% NOTE ft_getopt might not be available on the path at this moment and can therefore not yet be used.
% NOTE all options here should be explicitly listed as allowed in ft_checkconfig

if ~isfield(ft_default, 'checkconfig'),       ft_default.checkconfig    = 'loose';    end % pedantic, loose, silent
if ~isfield(ft_default, 'checkpath'),         ft_default.checkpath      = 'pedantic'; end % pedantic, once, no
if ~isfield(ft_default, 'checksize'),         ft_default.checksize      = 1e5;        end % number in bytes, can be inf
if ~isfield(ft_default, 'checkstring'),       ft_default.checkstring    = 'yes';      end % yes or no
if ~isfield(ft_default, 'showlogo'),          ft_default.showlogo       = 'yes';      end % yes or no, this is relevant for SPM and EEGLAB
if ~isfield(ft_default, 'showcallinfo'),      ft_default.showcallinfo   = 'yes';      end % yes or no, this is used in ft_pre/postamble_provenance
if ~isfield(ft_default, 'keepprevious'),      ft_default.keepprevious   = 'yes';      end % yes, no, this is used in ft_postamble_previous
if ~isfield(ft_default, 'keepcfg'),           ft_default.keepcfg        = 'yes';      end % yes, no, this is used in ft_postamble_history
if ~isfield(ft_default, 'debug'),             ft_default.debug          = 'no';       end % no, save, saveonerror, display, displayonerror, this is used in ft_pre/postamble_debug
if ~isfield(ft_default, 'outputfilepresent'), ft_default.outputfilepresent = 'overwrite'; end % can be keep, overwrite, error

% These options allow to disable parts of the provenance
if ~isfield(ft_default, 'trackcallinfo'),  ft_default.trackcallinfo  = 'yes';    end % yes or no
if ~isfield(ft_default, 'trackdatainfo'),  ft_default.trackdatainfo  = 'no';     end % yes or no
if ~isfield(ft_default, 'tracktimeinfo'),  ft_default.tracktimeinfo  = 'yes';    end % yes or no
if ~isfield(ft_default, 'trackmeminfo')
  if ispc()
    % don't track memory usage info under Windows; this does not work (yet)
    ft_default.trackmeminfo   = 'no';
  else
    ft_default.trackmeminfo   = 'yes';
  end
end

if strcmp(license(), '38957')
  % within the Donders and Radboud University the default is compat, since we do not have that many licenses
  default_images = 'compat';
  default_stats  = 'compat';
  default_signal = 'compat';
else
  % in this case it will still check whether the Mathworks toolbox is available and if not, the compatible version will be added
  default_images = 'matlab';
  default_stats  = 'matlab';
  default_signal = 'matlab';
end

% These options allow to prefer the MATLAB toolbox implementations ('matlab') over the drop-in replacements ('compat').
if ~isfield(ft_default, 'toolbox'), ft_default.toolbox  = []; end
if ~isfield(ft_default.toolbox, 'images'), ft_default.toolbox.images  = default_images; end % matlab or compat
if ~isfield(ft_default.toolbox, 'stats') , ft_default.toolbox.stats   = default_stats;  end % matlab or compat
if ~isfield(ft_default.toolbox, 'signal'), ft_default.toolbox.signal  = default_signal; end % matlab or compat

% Some people mess up their path settings and then have stuff on the path that should not be there.
% The following will issue a warning
switch ft_default.checkpath
  case 'pedantic'
    % check every time
    checkIncorrectPath();
  case 'once'
    % check only once
    if ~checkpath
      checkIncorrectPath();
      checkpath = true;
    end
  case 'no'
    % do not check
end % case

% Check whether this ft_defaults function has already been executed. Note that we
% should not use ft_default itself directly, because the user might have set stuff
% in that struct already prior to ft_defaults being called for the first time.
if initialized && exist('ft_hastoolbox', 'file')
  return;
end

if isfield(ft_default, 'toolbox') && isfield(ft_default.toolbox, 'cleanup')
  prevcleanup = ft_default.toolbox.cleanup;
else
  prevcleanup = {};
end

if strcmp(ft_default.showlogo, 'yes')
  % show a welcome message
  fprintf([
    '-------------------------------------------------------------------------------------------' ...
    '\nFieldTrip is developed by members and collaborators of the Donders Institute for Brain,' ...
    '\nCognition and Behaviour at Radboud University, Nijmegen, the Netherlands.' ...
    '\n'...
    '\n                          --------------------------'...
    '\n                        /                            \\'...
    '\n                     ------------------------------------'...
    '\n                    /                                    \\'...
    '\n          -------------------------------------------------'...
    '\n         /                            /\\/\\/\\/\\/\\ '...
    '\n         ---------------------------------------------------'...
    '\n                  |        F  i  e  l  d  T  r  i  p       |'...
    '\n                  ------------------------------------------'...
    '\n                   \\                                      /'...
    '\n                     ------------------------------------'...
    '\n                          \\            /'...
    '\n                            ----------'...
    '\n' ...
    '\nPlease cite the FieldTrip reference paper when you have used FieldTrip in your study.' ...
    '\nRobert Oostenveld, Pascal Fries, Eric Maris, and Jan-Mathijs Schoffelen. FieldTrip: Open' ...
    '\nSource Software for Advanced Analysis of MEG, EEG, and Invasive Electrophysiological Data.' ...
    '\nComputational Intelligence and Neuroscience, vol. 2011, Article ID 156869, 9 pages, 2011.' ...
    '\ndoi:10.1155/2011/156869.' ...
    '\n-------------------------------------------------------------------------------------------\n'
    ]);
end % if showlogo

% Ensure that the path containing ft_defaults is on the path.
% This allows people to do "cd path_to_fieldtrip; ft_defaults"
ftPath = fileparts(mfilename('fullpath')); % get the full path to this function, strip away 'ft_defaults'
ftPath = strrep(ftPath, '\', '\\');
if isempty(regexp(path, [ftPath pathsep '|' ftPath '$'], 'once'))
  ft_warning('FieldTrip is not yet on your MATLAB path, adding %s', strrep(ftPath, '\\', '\'));
  addpath(ftPath);
end

if ~isdeployed

  if isempty(which('ft_hastoolbox')) || isempty(which('ft_warning'))
    % the fieldtrip/utilities directory contains the ft_hastoolbox and ft_warning
    % functions, which are required for the remainder of this script
    addpath(fullfile(fileparts(which('ft_defaults')), 'utilities'));
  end

  % Some people mess up their path settings and then have different versions of certain toolboxes on the path.
  % The following will issue a warning
  checkMultipleToolbox('FieldTrip',           'ft_defaults.m');
  checkMultipleToolbox('spm',                 'spm.m');
  checkMultipleToolbox('mne',                 'fiff_copy_tree.m');
  checkMultipleToolbox('eeglab',              'eeglab2fieldtrip.m');
  checkMultipleToolbox('dipoli',              'write_tri.m');
  checkMultipleToolbox('eeprobe',             'read_eep_avr.mexa64');
  checkMultipleToolbox('yokogawa',            'GetMeg160ChannelInfoM.p');
  checkMultipleToolbox('simbio',              'sb_compile_vista.m');
  checkMultipleToolbox('fns',                 'fns_region_read.m');
  checkMultipleToolbox('bemcp',               'bem_Cii_cst.mexa64');
  checkMultipleToolbox('bci2000',             'load_bcidat.m');
  checkMultipleToolbox('openmeeg',            'openmeeg_helper.m');
  checkMultipleToolbox('freesurfer',          'vox2ras_ksolve.m');
  checkMultipleToolbox('fastica',             'fastica.m');
  checkMultipleToolbox('besa',                'readBESAmul.m');
  checkMultipleToolbox('neuroshare',          'ns_GetAnalogData.m');
  checkMultipleToolbox('ctf',                 'setCTFDataBalance.m');
  checkMultipleToolbox('afni',                'WriteBrikHEAD.m');
  checkMultipleToolbox('gifti',               '@gifti/display.m');
  checkMultipleToolbox('sqdproject',          'sqdread.m');
  checkMultipleToolbox('xml4mat',             'xml2mat.m');
  checkMultipleToolbox('cca',                 'ccabss.m');
  checkMultipleToolbox('bsmart',              'armorf.m');
  checkMultipleToolbox('iso2mesh',            'iso2meshver.m');
  checkMultipleToolbox('bct',                 'degrees_und.m');
  checkMultipleToolbox('yokogawa_meg_reader', 'getYkgwHdrEvent.p');
  checkMultipleToolbox('biosig',              'sopen.m');
  checkMultipleToolbox('icasso',              'icassoEst.m');

  try
    % external/signal contains alternative implementations of some signal processing functions
    external_signal = fullfile(fileparts(which('ft_defaults')), 'external', 'signal');
    if ~ft_platform_supports('signal') || ~strcmp(ft_default.toolbox.signal, 'matlab') || ~ft_hastoolbox('signal')
      addpath(external_signal);
    elseif contains(path, external_signal)
      rmpath(external_signal);
    end
  end

  try
    % external/stats contains alternative implementations of some statistics functions
    external_stats = fullfile(fileparts(which('ft_defaults')), 'external', 'stats');
    if ~ft_platform_supports('stats') || ~strcmp(ft_default.toolbox.stats, 'matlab') || ~ft_hastoolbox('stats')
      addpath(external_stats);
    elseif contains(path, external_stats)
      rmpath(external_stats);
    end
  end

  try
    % external/images contains alternative implementations of some image processing functions
    external_images = fullfile(fileparts(which('ft_defaults')), 'external', 'images');
    if ~ft_platform_supports('images') || ~strcmp(ft_default.toolbox.images, 'matlab') || ~ft_hastoolbox('images')
      addpath(external_images);
    elseif contains(path, external_images)
      rmpath(external_images);
    end
  end

  try
    % this directory contains various functions that were obtained from elsewere, e.g. MATLAB file exchange
    ft_hastoolbox('fileexchange', 3, 1); % not required
  end

  try
    % these directories deal with compatibility with older MATLAB versions
    if ft_platform_supports('matlabversion', -inf, '2010a'), ft_hastoolbox('compat/matlablt2010b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2010b'), ft_hastoolbox('compat/matlablt2011a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2011a'), ft_hastoolbox('compat/matlablt2011b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2011b'), ft_hastoolbox('compat/matlablt2012a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2012a'), ft_hastoolbox('compat/matlablt2012b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2012b'), ft_hastoolbox('compat/matlablt2013a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2013a'), ft_hastoolbox('compat/matlablt2013b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2013b'), ft_hastoolbox('compat/matlablt2014a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2014a'), ft_hastoolbox('compat/matlablt2014b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2014b'), ft_hastoolbox('compat/matlablt2015a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2015a'), ft_hastoolbox('compat/matlablt2015b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2015b'), ft_hastoolbox('compat/matlablt2016a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2016a'), ft_hastoolbox('compat/matlablt2016b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2016b'), ft_hastoolbox('compat/matlablt2017a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2017a'), ft_hastoolbox('compat/matlablt2017b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2017b'), ft_hastoolbox('compat/matlablt2018a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2018a'), ft_hastoolbox('compat/matlablt2018b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2018b'), ft_hastoolbox('compat/matlablt2019a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2019a'), ft_hastoolbox('compat/matlablt2019b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2019b'), ft_hastoolbox('compat/matlablt2020a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2020a'), ft_hastoolbox('compat/matlablt2020b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2020b'), ft_hastoolbox('compat/matlablt2021a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2021a'), ft_hastoolbox('compat/matlablt2021b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2021b'), ft_hastoolbox('compat/matlablt2022a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2022a'), ft_hastoolbox('compat/matlablt2022b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2022b'), ft_hastoolbox('compat/matlablt2023a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2023a'), ft_hastoolbox('compat/matlablt2023b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2023b'), ft_hastoolbox('compat/matlablt2024a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2024a'), ft_hastoolbox('compat/matlablt2024b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2024b'), ft_hastoolbox('compat/matlablt2025a', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2025a'), ft_hastoolbox('compat/matlablt2025b', 3, 1); end
    if ft_platform_supports('matlabversion', -inf, '2025b'), ft_hastoolbox('compat/matlablt2026a', 3, 1); end
    % this deals with compatibility with all OCTAVE versions
    if ft_platform_supports('octaveversion', -inf, +inf),    ft_hastoolbox('compat/octave', 3, 1); end
  end

  try
    % these contains template layouts, neighbour structures, MRIs and cortical meshes
    ft_hastoolbox('template/layout',      1, 1);
    ft_hastoolbox('template/anatomy',     1, 1);
    ft_hastoolbox('template/headmodel',   1, 1);
    ft_hastoolbox('template/electrode',   1, 1);
    ft_hastoolbox('template/gradiometer', 1, 1);
    ft_hastoolbox('template/neighbours',  1, 1);
    ft_hastoolbox('template/sourcemodel', 1, 1);
  end

  try
    % this is used in ft_statistics
    ft_hastoolbox('statfun', 1, 1);
  end

  try
    % this is used in ft_definetrial
    ft_hastoolbox('trialfun', 1, 1);
  end

  try
    % this contains the low-level reading functions
    ft_hastoolbox('fileio', 1, 1);
  end

  try
    % this is for filtering etc. on time-series data
    ft_hastoolbox('preproc', 1, 1);
  end

  try
    % this contains forward models for the EEG and MEG volume conductor
    ft_hastoolbox('forward', 1, 1);
  end

  try
    % this contains inverse source estimation methods
    ft_hastoolbox('inverse', 1, 1);
  end

  try
    % this contains intermediate-level plotting functions, e.g. multiplots and 3-d objects
    ft_hastoolbox('plotting', 1, 1);
  end

  try
    % this contains intermediate-level functions for spectral analysis
    ft_hastoolbox('specest', 1, 1);
  end

  try
    % this contains the functions to compute connectivity metrics
    ft_hastoolbox('connectivity', 1, 1);
  end

  try
    % this contains test scripts
    ft_hastoolbox('test', 1, 1);
  end

  try
    % this contains the functions for spike and spike-field analysis
    ft_hastoolbox('contrib/spike', 1, 1);
  end

  try
    % this contains user contributed functions
    ft_hastoolbox('contrib/misc', 1, 1);
  end

  try
    % this contains specific code and examples for realtime processing
    ft_hastoolbox('realtime/example', 3, 1);    % not required
    ft_hastoolbox('realtime/online_mri', 3, 1); % not required
    ft_hastoolbox('realtime/online_meg', 3, 1); % not required
    ft_hastoolbox('realtime/online_eeg', 3, 1); % not required
  end

end

% the toolboxes added by this function should not be removed by FT_POSTAMBLE_HASTOOLBOX
ft_default.toolbox.cleanup = prevcleanup;

% track the usage of this function, this only happens once at startup
ft_trackusage('startup');

% remember that the function has executed in a persistent variable
initialized = true;

end % function ft_default


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SUBFUNCTION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function checkMultipleToolbox(toolbox, keyfile)

persistent warned
if isempty(warned)
  warned = false;
end

if ~ft_platform_supports('which-all')
  return;
end

list = which(keyfile, '-all');
if length(list)>1
  ft_warning('Multiple versions of %s on your path will confuse FieldTrip', toolbox);
  if ~warned % only throw the following warnings once
    warned = true;
    for i=1:length(list)
      ft_warning('one version of %s is found here: %s', toolbox, list{i});
    end
  end
  ft_warning('You probably used addpath(genpath(''path_to_fieldtrip'')), this can lead to unexpected behavior. See https://www.fieldtriptoolbox.org/faq/matlab/installation/');
end
end % function checkMultipleToolbox

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SUBFUNCTION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function checkIncorrectPath
p = fileparts(mfilename('fullpath'));
incorrect = fullfile(p, 'compat', 'incorrect');
if ~isempty(strfind(path, incorrect))
  ft_warning('Your path is set up incorrectly. You probably used addpath(genpath(''path_to_fieldtrip'')), this can lead to unexpected behavior. See https://www.fieldtriptoolbox.org/faq/matlab/installation/');
end
end % function checkIncorrectPath
