function spp_params = spp_load_pooling_params(spp_params_def)
% spp_params = spp_load_pooling_params(spp_params_def)
%   spp_params -- parameters for spatial pyramid pooling for spatial model
%
% AUTORIGHTS
% ---------------------------------------------------------
% Copyright (c) 2014, Shaoqing Ren
%
% This file is part of the SPP code and is available
% under the terms of the Simplified BSD License provided in
% LICENSE. Please retain this notice and LICENSE if you use
% this file (or any portion of it) in your project.
% ---------------------------------------------------------

[~, ~, ext] = fileparts(spp_params_def);
if isempty(ext)
    spp_params_def = [spp_params_def, '.m'];
end
assert(exist(spp_params_def, 'file') ~= 0);

% change folder to avoid too long path for eval()
cur_dir = pwd;
[spp_def_dir, spp_def_file] = fileparts(spp_params_def);

cd(spp_def_dir);
spp_params = eval(spp_def_file);
cd(cur_dir);

spp_params.expected_scale = @spm_expected_scale;
spp_params.response_boxes = @spm_response_boxes;

end


%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% /**
%  * Copyright (C) 2016 CoDyCo
%  * @author: Daniele Pucci, Gabriele Nava
%  * Permission is granted to copy, distribute, and/or modify this program
%  * under the terms of the GNU General Public License, version 2 or any
%  * later version published by the Free Software Foundation.
%  *
%  * A copy of the license can be found at
%  * http://www.robotcub.org/icub/license/gpl.txt
%  *
%  * This program 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
%  */
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% NOTE: THIS SCRIPT IS RUN AUTOMATICALLY WHEN THE USER STARTS THE ASSOCIATED
% SIMULINK MODEL. NO NEED TO RUN THIS SCRIPT EVERY TIME.
clearvars -except sl_synch_handles simulinkStaticGUI
clc

%% GENERAL SIMULATION INFO
%
% If you are simulating the robot with Gazebo, remember that it is required
% to launch Gazebo as follows:
%
%     gazebo -slibgazebo_yarp_clock.so
%
% and properly set the environmental variable YARP_ROBOT_NAME in the .bashrc.

% Simulation time in seconds. For long simulations, put an high number
% (not inf) for allowing automatic code generation
Config.SIMULATION_TIME = 600000;

% Controller period [s]
Config.tStep           = 0.01;

% If Config.SAVE_WORKSPACE = True, every time the simulink model is run the
% workspace is saved after stopping the simulation
Config.SAVE_WORKSPACE  = false;

% if TRUE, the controller will STOP if the joints hit the joints limits
% and/or if the (unsigned) difference between two consecutive joints
% encoders measurements is greater than a given threshold.
Config.EMERGENCY_STOP_WITH_JOINTS_LIMITS  = false;
Config.EMERGENCY_STOP_WITH_ENCODER_SPIKES = true;

% Verify that the integration time has been respected during the simulation
Config.CHECK_INTEGRATION_TIME = true;
Config.PLOT_INTEGRATION_TIME  = false;

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% CONFIGURATIONS COMPLETED: loading gains and parameters for the specific robot
run(strcat('app/robots/',getenv('YARP_ROBOT_NAME'),'/configRobot.m'));
run(strcat('app/robots/',getenv('YARP_ROBOT_NAME'),'/configJointsControl.m'));
run(strcat('app/robots/',getenv('YARP_ROBOT_NAME'),'/gainsAndReferences.m'));


function [net,stats] = cnn_train_dag_modified(net, imdb, getBatch, varargin)
%CNN_TRAIN_DAG Demonstrates training a CNN using the DagNN wrapper
%    CNN_TRAIN_DAG() is similar to CNN_TRAIN(), but works with
%    the DagNN wrapper instead of the SimpleNN wrapper.

% Copyright (C) 2014-16 Andrea Vedaldi.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

opts.expDir = fullfile('data','exp') ;
opts.continue = true ;
opts.batchSize = 256 ;
opts.numSubBatches = 1 ;
opts.train = [] ;
opts.val = [] ;
opts.gpus = [] ;
opts.prefetch = false ;
opts.numEpochs = 300 ;
opts.learningRate = 0.001 ;
opts.weightDecay = 0.0005 ;
opts.momentum = 0.9 ;
opts.saveMomentum = true ;
opts.nesterovUpdate = false ;
opts.randomSeed = 0 ;
opts.profile = false ;
opts.parameterServer.method = 'mmap' ;
opts.parameterServer.prefix = 'mcn' ;

opts.derOutputs = {'objective', 1} ;
opts.extractStatsFn = @extractStats ;
opts.plotStatistics = true;
opts = vl_argparse(opts, varargin) ;

if ~exist(opts.expDir, 'dir'), mkdir(opts.expDir) ; end
if isempty(opts.train), opts.train = find(imdb.images.set==1) ; end
if isempty(opts.val), opts.val = find(imdb.images.set==2) ; end
if isnan(opts.train), opts.train = [] ; end
if isnan(opts.val), opts.val = [] ; end

% -------------------------------------------------------------------------
%                                                            Initialization
% -------------------------------------------------------------------------

evaluateMode = isempty(opts.train) ;
if ~evaluateMode
  if isempty(opts.derOutputs)
    error('DEROUTPUTS must be specified when training.\n') ;
  end
end

% -------------------------------------------------------------------------
%                                                        Train and validate
% -------------------------------------------------------------------------

modelPath = @(ep) fullfile(opts.expDir, sprintf('net-epoch-%d.mat', ep));
modelFigPath = fullfile(opts.expDir, 'net-train.pdf') ;

start = opts.continue * findLastCheckpoint(opts.expDir) ;
if start >= 1
  fprintf('%s: resuming by loading epoch %d\n', mfilename, start) ;
  [net, state, stats] = loadState(modelPath(start)) ;
else
  state = [] ;
end

for epoch=start+1:opts.numEpochs

  % Set the random seed based on the epoch and opts.randomSeed.
  % This is important for reproducibility, including when training
  % is restarted from a checkpoint.

  rng(epoch + opts.randomSeed) ;
%   prepareGPUs(opts, epoch == start+1) ;

  % Train for one epoch.
  params = opts ;
  params.epoch = epoch ;
  params.learningRate = opts.learningRate(min(epoch, numel(opts.learningRate))) ;
  params.train = opts.train(randperm(numel(opts.train))) ; % shuffle
  params.val = opts.val(randperm(numel(opts.val))) ;
  params.imdb = imdb ;
  params.getBatch = getBatch ;

  if numel(opts.gpus) <= 1
    [net, state] = processEpoch(net, state, params, 'train') ;
    [net, state] = processEpoch(net, state, params, 'val') ;

    if size(imdb.images.labels,1) > 1
        [net.meta.svm_model1,net.meta.svm_err1] = training_SVR(net,params);
    end

    if ~evaluateMode
      saveState(modelPath(epoch), net, state) ;
    end
    lastStats = state.stats ;
  else
    spmd
      [net, state] = processEpoch(net, state, params, 'train') ;
      [net, state] = processEpoch(net, state, params, 'val') ;
      if labindex == 1 && ~evaluateMode
        saveState(modelPath(epoch), net, state) ;
      end
      lastStats = state.stats ;
    end
    lastStats = accumulateStats(lastStats) ;
  end

  stats.train(epoch) = lastStats.train ;
  stats.val(epoch) = lastStats.val ;
  clear lastStats ;
  saveStats(modelPath(epoch), stats) ;

%   if opts.plotStatistics
%     switchFigure(1) ; clf ;
%     plots = setdiff(...
%       cat(2,...
%       fieldnames(stats.train)', ...
%       fieldnames(stats.val)'), {'num', 'time'}) ;
%     for p = plots
%       p = char(p) ;
%       values = zeros(0, epoch) ;
%       leg = {} ;
%       for f = {'train', 'val'}
%         f = char(f) ;
%         if isfield(stats.(f), p)
%           tmp = [stats.(f).(p)] ;
%           values(end+1,:) = tmp(1,:)' ;
%           leg{end+1} = f ;
%         end
%       end
%       subplot(1,numel(plots),find(strcmp(p,plots))) ;
%       plot(1:epoch, values','o-') ;
%       xlabel('epoch') ;
%       title(p) ;
%       legend(leg{:}) ;
%       grid on ;
%     end
%     drawnow ;
%     print(1, modelFigPath, '-dpdf') ;
%   end
end

% With multiple GPUs, return one copy
if isa(net, 'Composite'), net = net{1} ; end

% -------------------------------------------------------------------------
function [net, state] = processEpoch(net, state, params, mode)
% -------------------------------------------------------------------------
% Note that net is not strictly needed as an output argument as net
% is a handle class. However, this fixes some aliasing issue in the
% spmd caller.

% initialize with momentum 0
if isempty(state) || isempty(state.momentum)
  state.momentum = num2cell(zeros(1, numel(net.params))) ;
end

% move CNN  to GPU as needed
numGpus = numel(params.gpus) ;
if numGpus >= 1
  net.move('gpu') ;
  state.momentum = cellfun(@gpuArray, state.momentum, 'uniformoutput', false) ;
end
if numGpus > 1
  parserv = ParameterServer(params.parameterServer) ;
  net.setParameterServer(parserv) ;
else
  parserv = [] ;
end

% profile
if params.profile
  if numGpus <= 1
    profile clear ;
    profile on ;
  else
    mpiprofile reset ;
    mpiprofile on ;
  end
end

num = 0 ;
epoch = params.epoch ;
subset = params.(mode) ;
adjustTime = 0 ;

stats.num = 0 ; % return something even if subset = []
stats.time = 0 ;

start = tic ;
for t=1:params.batchSize:numel(subset)
  fprintf('%s: epoch %02d: %3d/%3d:', mode, epoch, ...
          fix((t-1)/params.batchSize)+1, ceil(numel(subset)/params.batchSize)) ;
  batchSize = min(params.batchSize, numel(subset) - t + 1) ;

  for s=1:params.numSubBatches
    % get this image batch and prefetch the next
    batchStart = t + (labindex-1) + (s-1) * numlabs ;
    batchEnd = min(t+params.batchSize-1, numel(subset)) ;
    batch = subset(batchStart : params.numSubBatches * numlabs : batchEnd) ;
    num = num + numel(batch) ;
    if numel(batch) == 0, continue ; end

    inputs = params.getBatch(params.imdb, batch) ;

    if params.prefetch
      if s == params.numSubBatches
        batchStart = t + (labindex-1) + params.batchSize ;
        batchEnd = min(t+2*params.batchSize-1, numel(subset)) ;
      else
        batchStart = batchStart + numlabs ;
      end
      nextBatch = subset(batchStart : params.numSubBatches * numlabs : batchEnd) ;
      params.getBatch(params.imdb, nextBatch) ;
    end

    if strcmp(mode, 'train')
      net.mode = 'normal' ;
      net.accumulateParamDers = (s ~= 1) ;
      net.eval(inputs, params.derOutputs, 'holdOn', s < params.numSubBatches) ;
    else
      net.mode = 'test' ;
      net.eval(inputs) ;
    end
  end

  % Accumulate gradient.
  if strcmp(mode, 'train')
    if ~isempty(parserv), parserv.sync() ; end
    state = accumulateGradients(net, state, params, batchSize, parserv) ;
  end

  % Get statistics.
  time = toc(start) + adjustTime ;
  batchTime = time - stats.time ;
  stats.num = num ;
  stats.time = time ;
  stats = params.extractStatsFn(stats,net) ;
  currentSpeed = batchSize / batchTime ;
  averageSpeed = (t + batchSize - 1) / time ;
  if t == 3*params.batchSize + 1
    % compensate for the first three iterations, which are outliers
    adjustTime = 4*batchTime - time ;
    stats.time = time + adjustTime ;
  end

  fprintf(' %.1f (%.1f) Hz', averageSpeed, currentSpeed) ;
  for f = setdiff(fieldnames(stats)', {'num', 'time'})
    f = char(f) ;
    fprintf(' %s: %.4f', f, stats.(f)) ;
  end
  fprintf('\n') ;
end

% Save back to state.
state.stats.(mode) = stats ;
if params.profile
  if numGpus <= 1
    state.prof.(mode) = profile('info') ;
    profile off ;
  else
    state.prof.(mode) = mpiprofile('info');
    mpiprofile off ;
  end
end
if ~params.saveMomentum
  state.momentum = [] ;
else
  state.momentum = cellfun(@gather, state.momentum, 'uniformoutput', false) ;
end

net.reset() ;
net.move('cpu') ;

% -------------------------------------------------------------------------
function state = accumulateGradients(net, state, params, batchSize, parserv)
% -------------------------------------------------------------------------
numGpus = numel(params.gpus) ;
otherGpus = setdiff(1:numGpus, labindex) ;

for p=1:numel(net.params)

  if ~isempty(parserv)
    parDer = parserv.pullWithIndex(p) ;
  else
    parDer = net.params(p).der ;
  end

  switch net.params(p).trainMethod

    case 'average' % mainly for batch normalization
      thisLR = net.params(p).learningRate ;
      net.params(p).value = vl_taccum(...
          1 - thisLR, net.params(p).value, ...
          (thisLR/batchSize/net.params(p).fanout),  parDer) ;

    case 'gradient'
      thisDecay = params.weightDecay * net.params(p).weightDecay ;
      thisLR = params.learningRate * net.params(p).learningRate ;

      if thisLR>0 || thisDecay>0
        % Normalize gradient and incorporate weight decay.
        parDer = vl_taccum(1/batchSize, parDer, ...
                           thisDecay, net.params(p).value) ;

        % Update momentum.
        state.momentum{p} = vl_taccum(...
          params.momentum, state.momentum{p}, ...
          -1, parDer) ;

        % Nesterov update (aka one step ahead).
        if params.nesterovUpdate
          delta = vl_taccum(...
            params.momentum, state.momentum{p}, ...
            -1, parDer) ;
        else
          delta = state.momentum{p} ;
        end

        % Update parameters.
        net.params(p).value = vl_taccum(...
          1,  net.params(p).value, thisLR, delta) ;
      end
    otherwise
      error('Unknown training method ''%s'' for parameter ''%s''.', ...
        net.params(p).trainMethod, ...
        net.params(p).name) ;
  end
end

% -------------------------------------------------------------------------
function stats = accumulateStats(stats_)
% -------------------------------------------------------------------------

for s = {'train', 'val'}
  s = char(s) ;
  total = 0 ;

  % initialize stats stucture with same fields and same order as
  % stats_{1}
  stats__ = stats_{1} ;
  names = fieldnames(stats__.(s))' ;
  values = zeros(1, numel(names)) ;
  fields = cat(1, names, num2cell(values)) ;
  stats.(s) = struct(fields{:}) ;

  for g = 1:numel(stats_)
    stats__ = stats_{g} ;
    num__ = stats__.(s).num ;
    total = total + num__ ;

    for f = setdiff(fieldnames(stats__.(s))', 'num')
      f = char(f) ;
      stats.(s).(f) = stats.(s).(f) + stats__.(s).(f) * num__ ;

      if g == numel(stats_)
        stats.(s).(f) = stats.(s).(f) / total ;
      end
    end
  end
  stats.(s).num = total ;
end

% -------------------------------------------------------------------------
function stats = extractStats(stats, net)
% -------------------------------------------------------------------------
sel = find(cellfun(@(x) isa(x,'dagnn.Loss'), {net.layers.block})) ;
for i = 1:numel(sel)
  stats.(net.layers(sel(i)).outputs{1}) = net.layers(sel(i)).block.average ;
end

% -------------------------------------------------------------------------
function saveState(fileName, net_, state)
% -------------------------------------------------------------------------
net = net_.saveobj() ;
% save(fileName, 'net', 'state') ;
save(fileName, 'net') ;

% -------------------------------------------------------------------------
function saveStats(fileName, stats)
% -------------------------------------------------------------------------
if exist(fileName)
  save(fileName, 'stats', '-append') ;
else
  save(fileName, 'stats') ;
end

% -------------------------------------------------------------------------
function [net, state, stats] = loadState(fileName)
% -------------------------------------------------------------------------
load(fileName, 'net', 'state', 'stats') ;
net = dagnn.DagNN.loadobj(net) ;
if isempty(whos('stats'))
  error('Epoch ''%s'' was only partially saved. Delete this file and try again.', ...
        fileName) ;
end

% -------------------------------------------------------------------------
function epoch = findLastCheckpoint(modelDir)
% -------------------------------------------------------------------------
list = dir(fullfile(modelDir, 'net-epoch-*.mat')) ;
tokens = regexp({list.name}, 'net-epoch-([\d]+).mat', 'tokens') ;
epoch = cellfun(@(x) sscanf(x{1}{1}, '%d'), tokens) ;
epoch = max([epoch 0]) ;

% -------------------------------------------------------------------------
function switchFigure(n)
% -------------------------------------------------------------------------
if get(0,'CurrentFigure') ~= n
  try
    set(0,'CurrentFigure',n) ;
  catch
    figure(n) ;
  end
end

% -------------------------------------------------------------------------
function clearMex()
% -------------------------------------------------------------------------
clear vl_tmove vl_imreadjpeg ;

% -------------------------------------------------------------------------
function prepareGPUs(opts, cold)
% -------------------------------------------------------------------------
numGpus = numel(opts.gpus) ;
if numGpus > 1
  % check parallel pool integrity as it could have timed out
  pool = gcp('nocreate') ;
  if ~isempty(pool) && pool.NumWorkers ~= numGpus
    delete(pool) ;
  end
  pool = gcp('nocreate') ;
  if isempty(pool)
    parpool('local', numGpus) ;
    cold = true ;
  end

end
if numGpus >= 1 && cold
  fprintf('%s: resetting GPU\n', mfilename)
  clearMex() ;
  if numGpus == 1
    gpuDevice(opts.gpus)
  else
    spmd
      clearMex() ;
      gpuDevice(opts.gpus(labindex))
    end
  end
end

function [svm_model,svm_err] = training_SVR(net,params)

move(net, 'gpu')
net.mode = 'test';
batch = 64;
sampling = floor(length(params.train) / 5000);
scores_train = params.imdb.images.score(1:sampling:end);
data = params.imdb.images.data(:,:,:,1:sampling:end);
num_batch = floor(length(scores_train) / batch);
index = find(arrayfun(@(a) strcmp(a.name, 'myLoss'), net.layers)==1);
tlayerName = net.layers(index).inputs{1};
for i = 1:num_batch
    images = gpuArray(data(:,:,:,(i-1)*batch+1:i*batch));
    images = bsxfun(@minus, single(images), net.meta.normalization.averageImage) ;
    net.eval({'data', images});
    if strcmp(net.layers(end).block.lossType,'CE')
        feats(:,(i-1)*batch+1:i*batch) = squeeze(gather(vl_nnsoftmax(net.vars(net.getVarIndex(tlayerName)).value))) ;
    else
        feats(:,(i-1)*batch+1:i*batch) = squeeze(gather(net.vars(net.getVarIndex(tlayerName)).value)) ;
    end
end
if num_batch*batch < length(scores_train)
    images = gpuArray(data(:,:,:,num_batch*batch+1:length(scores_train)));
    images = bsxfun(@minus, single(images), net.meta.normalization.averageImage) ;
    net.eval({'data', images}) ;
    if strcmp(net.layers(end).block.lossType,'CE')
        feats(:,num_batch*batch+1:length(scores_train)) = squeeze(gather(vl_nnsoftmax(net.vars(net.getVarIndex(tlayerName)).value)));
    else
        feats(:,num_batch*batch+1:length(scores_train)) = squeeze(gather(net.vars(net.getVarIndex(tlayerName)).value));
    end
end
svm_model = svmtrain(scores_train', double(feats'), '-s 4 -t 0');
[scores_pred, ~,~] = svmpredict(scores_train', double(feats'), svm_model,'-q');
svm_err = (sum(abs(scores_pred - scores_train'))) / length(scores_train);


%EVALSFUN Shape function evaluation driver subroutine.
%
%   [ VBASE, NLDOF, XLDOF, SFUN ] = EVALSFUN( SFUN, I_EVAL, N_SDIM, N_VERT, I_DOF, XI, AINVJAC, VBASE )
%   Evaluates local basis function I_DOF in point XI for shape function SFUN on all
%   cells corresponding to AINVJAC. Returns the evaluated values in VBASE and
%   the local number of degrees of freedom on vertices, edges, faces, and cell
%   interiors in NLDOF and XLDOF as well as the low level function name in SFUN.
%
%   See also EVALDVAR, EVALEXPR

% Copyright 2013-2022 Precise Simulation, Ltd.


function [results_table_pos, results_table_neg, r, excluded_region_table, r_excluded, region_list] = table_of_atlas_regions_covered(obj, varargin)
% Make a table of which atlas parcels are covered by a set of regions or map identified in a study
%
% [results_table_pos, results_table_neg, r, excluded_region_table, r_excluded, region_list] = table_of_atlas_regions_covered(obj, [atlas_obj])
%
% fMRI activation maps often include large suprathreshold areas that span
% multiple brain regions.  Traditional tables divide areas by contiguous
% regions ("blobs"), but this type of division is not useful if blobs cannot
% be easily summarized by a single anatomical label. A complementary approach
% is to identify which areas defined in a standard brain atlas ("parcels")
% are covered by the activation map. Parcels can be defined based on anatomy
% (e.g., cytoarchitecture) or function (e.g., resting-state fMRI).
% For example, a large blob may span the insula, claustrum, and putamen.
% This can be described in a table that lists all of these regions, along with
% the percentage of each parcel covered by the activation map.
%
% This function uses the object method subdivide_by_atlas() to create such
% a table, which is dividided into two tables with positive and negative average
% statistic values (results_table_pos, results_table_neg). These are Matlab
% table-class objects.  It also returns a region-class object for reference
% and rendering the subdivided blobs on brain slices or surfaces.
%
% You can enter any atlas-class object as a 2nd argument. If you don't,
% a default atlas object will be used.
%
% Examples:
% -----------------------------------------------------------------
% % Load a thresholded map:
% % (Note: You must have Neuroimaging_Pattern_Masks repo with subfolders on your path)
% % This is a predictive map for drug craving (Koban et al. 2022, Nat Neurosci)
%
% ncsthr = fmri_data(which('NCS_multithr_001k5_005_05_pruned.nii'), 'noverbose');
%
% % Convert to region object:
% r = region(ncsthr);
%
% [results_table_pos, results_table_neg, r, excluded_region_table, table_legend_text] = table_of_atlas_regions_covered(r);
% montage(r, 'regioncenters', 'colormap');
%
% % Also see large blobs that didn't sufficiently cover any one atlas parcel:
% montage(r_excluded(cat(1, r_excluded.numVox) > 20), 'regioncenters', 'colormap');
%
% % You can use the image_vector method to apply this to a single-image
% % thresholded map:
% [results_table_pos, results_table_neg, r, excluded_region_table, r_excluded, region_labels] = table_of_atlas_regions_covered(ncsthr);
%
% Note: For a key to labels when using the Glasser 2016 Nature atlas, or the
% CANlab combined atlas (which uses Glasser), see GlasserTableS1.pdf in the
% original paper or CANlab github, or http://braininfo.rprc.washington.edu/
%
% see also region.table, for autolabeling of regions with an atlas and more
% detailed table output.
%
% Tor Wager, Feb 2023

if (size(obj.dat, 2) > 1)
    error('Use this function with fmri_data or image_vector objects containing only a single image. Use get_wh_image() to select one.')
end

r = region(obj);

[results_table_pos, results_table_neg, r, excluded_region_table, r_excluded, region_list] = table_of_atlas_regions_covered(r, varargin{:});

end


function test_bug2597

% WALLTIME 00:10:00
% MEM 2gb
% DEPENDENCY ft_selectdata

% this function tests the functionality of ft_selectdata to preserve the
% ordering of the channels according to the first input argument (thus
% overruling alphabetization, as well as any order in the cfg).

% make some data
data        = [];
data.label  = {'b';'a';'c'};
data.avg    = repmat([2 1 3]',[1 2]);
data.dimord = 'chan_time';
data.time   = [1 2];

datanew = ft_selectdata([], data);
assert(isequal(datanew.label,{'b';'a';'c'}));
assert(isequal(datanew.avg(:,1),[2 1 3]'));

data2        = [];
data2.label  = {'a';'b';'c'};
data2.avg    = repmat([1 2 3]',[1 2]);
data2.dimord = 'chan_time';
data2.time   = [1 2];

[datanew, datanew2] = ft_selectdata([], data, data2);
assert(isequal(datanew.label,{'b';'a';'c'}));
assert(isequal(datanew2.label,datanew.label));

data2        = [];
data2.label  = {'b';'c';'d'};
data2.avg    = repmat([2 3 4]',[1 2]);
data2.dimord = 'chan_time';
data2.time   = [1 2];
[datanew, datanew2] = ft_selectdata([], data, data2);
assert(isequal(datanew.label,{'b';'c'}));
assert(isequal(datanew2.label,{'b';'c'}));
assert(isequal(datanew.avg(:,1),[2 3]'));
assert(isequal(datanew2.avg(:,1),[2 3]'));

cfg.select = 'union';
[datanew, datanew2] = ft_selectdata(cfg, data, data2);
assert(isequal(datanew.label,{'b';'a';'c';'d'}));
assert(isequal(datanew2.label,{'b';'a';'c';'d'}));
assert(isequaln(datanew.avg(:,1),[2 1 3 nan]'));
assert(isequaln(datanew2.avg(:,1),[2 nan 3 4]'));

data2        = [];
data2.label  = {'b';'c';'e'};
data2.avg    = repmat([2 3 5]',[1 2]);
data2.dimord = 'chan_time';
data2.time   = [1 2];

data3        = [];
data3.label  = {'d';'a';'c'};
data3.avg    = repmat([4 1 3]',[1 2]);
data3.dimord = 'chan_time';
data3.time   = [1 2];

cfg.select = 'intersect';
[datanew, datanew2, datanew3] = ft_selectdata(cfg, data, data2, data3);
assert(isequal(datanew.label, {'c'}));
assert(isequal(datanew2.label, {'c'}));
assert(isequal(datanew3.label, {'c'}));
assert(isequaln(datanew.avg(:,1), 3));
assert(isequaln(datanew2.avg(:,1), 3));
assert(isequaln(datanew3.avg(:,1), 3));

cfg.select = 'union';
[datanew, datanew2, datanew3] = ft_selectdata(cfg, data, data2, data3);
assert(isequal(datanew.label, {'b';'a';'c';'e';'d'}));
assert(isequal(datanew2.label, {'b';'a';'c';'e';'d'}));
assert(isequal(datanew3.label, {'b';'a';'c';'e';'d'}));
assert(isequaln(datanew.avg(:,1), [2 1 3 nan nan]'));
assert(isequaln(datanew2.avg(:,1), [2 nan 3 5 nan]'));
assert(isequaln(datanew3.avg(:,1), [nan 1 3 nan 4]'));


%kkextract 'Extract Rectangular Region from Object'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros kextract.pane file
%
% Parameters:
% InputFile: i 'Input ', required: 'Input object'
% Integer: wsize 'Width ', default: 1: 'Specifies the region width'
% Integer: hsize 'Height ', default: 1: 'Specifies the region height'
% Integer: dsize 'Depth ', default: 1: 'Specifies the region depth'
% Integer: tsize 'Time ', default: 1: 'Specifies the region size on time dimension'
% Integer: esize 'Elements', default: 1: 'Specifies the region size on elements dimension'
% Integer: woff 'Width ', default: 0: 'Specifies origin of region on width dimension'
% Integer: hoff 'Height ', default: 0: 'Specifies origin of region on height dimension'
% Integer: doff 'Depth ', default: 0: 'Specifies origin of region on depth dimension'
% Integer: toff 'Time ', default: 0: 'Specifies origin of region on time dimension'
% Integer: eoff 'Elements', default: 0: 'Specifies origin of region on elements dimension'
% OutputFile: o 'Output', required: 'Resulting output region'
%
% Example: o = kkextract(i, {'i','';'wsize',1;'hsize',1;'dsize',1;'tsize',1;'esize',1;'woff',0;'hoff',0;'doff',0;'toff',0;'eoff',0;'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% kextract - Extract Rectangular Region from Object
%
%  DESCRIPTION
%
% The "Extract Region" operator (kextract) extracts a region of data
% from the source object "Input" (i) and places it in the destination
% object "Output" (o).  The region size is specified by the Width (wsize),
% Height (hsize), Depth (dsize), Time (tsize), and Elements (esize) Region
% Size parameters.  The region will be extracted starting at the point defined
% by the Region Origin parameters, Width (woff), Height (hoff), Depth (doff),
% Time (toff), and Elements (eoff).  The datum at this starting point will be
% placed at the origin (0,0,0,0,0) in the destination object.
%
% The output data object size for each dimension is determined first by the
% Region Size parameters "if" they are specified, and then by the Region
% Origin parameters in combination with the original source data size.  In other
% words, if the size for a dimension is not selected on the graphical user
% interface (or explicitly specified when running kextract from the command
% line), all data on that dimension will be extracted, starting at the specified
% origin.   This will ensure the following behavior.  Given an input data file
% with dimensions (width=100, height=100, depth=10, time=1, elements = 1),
% and the following "specified" parameters:
%
% 	Region Size:  Width = 50, Height = 50
% 	Region Origin:  Width = 2, Height = 2, Depth = 2
%
% the output object size will be (width=50, height=50, depth=8, time=1,
% elements = 1).
%
% The extract operation is based on implicit indexing.  This means that if
% location or time data exist, the extract operation is not done in terms
% an interpretation of the location/time data values, but in terms of the
% implicit indexing of these data (which is specified by the width, height,
% depth, time, elements indices of the polymorphic data model).  This program
% can operate on any combination of value, mask, location and/or time data
% in the input object.  Map data is unaffected by the extract operation.
%
% If the "Region Origin" and/or the \fIRegion Size\fP fall outside of
% the size of the input object, destination object value, location, and time
% data will be padded with zero, and mask data will be padded with one.
%
% The subobject position attribute of a data object defines the coordinates
% at which that subobject is located in its parent data object.
% The "Record Region Origin" option (subpos) allows the extract operator to
% set the sub-object position attribute in the output object to the Region
% origin.  If this option is set to "Yes", the subobject position of the
% output object will be set to (woff, hoff, doff, toff, eoff).  If "Record
% Region Origin" is set to "No", the output subobject position is set to
% (0,0,0,0,0).  Programs like the insert operator (kinsert) can use this
% attribute for automatically inserting the subregion back into the original
% after processing.
%
% The subobject position attribute can also be explicitly set by using the
% Set Data Attributes operator (ksetdattr), and can be printed using the
% Print File Information operator (kfileinfo).
%
% The destination object data types are the same as the source object
% data types.
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
%
%  RESTRICTIONS
% This program has not yet been updated to completely support the
% polymorphic data model.
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kkextract(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kkextract(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'wsize', 1;'hsize', 1;'dsize', 1;'tsize', 1;'esize', 1;'woff', 0;'hoff', 0;'doff', 0;'toff', 0;'eoff', 0;'o', '__output'};
maxval={0,2,2,2,2,2,0,0,0,0,0,0};
minval={0,2,2,2,2,2,0,0,0,0,0,0};
istoggle=[0,1,1,1,1,1,1,1,1,1,1,0];
was_set=istoggle * 0;
paramtype={'InputFile','Integer','Integer','Integer','Integer','Integer','Integer','Integer','Integer','Integer','Integer','OutputFile'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in')
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = '';
        end;
        narglist{jj,2} = '';
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = '';
          narglist{jj,2} = '';
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs))
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']);
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs))
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1)
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']);
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs)
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(1,1);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
[varargout{:}]=callKhoros([w 'kextract"  '],Inputs,narglist);


function [boutmat,line_names] = ethogram_plot_core(hfig,labels,T0,T1,expdirs,behaviornames,jabfiles,varargin)
% [boutmat,line_names] = ethogram_plot_core(hfig,labels,expdirs,T0,T1,behaviornames,jabfiles,p1,v1,...)
%
% labels: nexps x nsamps x nbehs label array. 0s and 1s are plotted as
% none and behavior-present, respectively. -1's may also be supplied, which
% are plotted as negative-behavior (faded color).
%
% Optional PVs:
%
% Input arg jabfiles are used only to enable click-on-bout-to-open-in-JAABA.

[trialdividers,pulldownselect,behaviorcolorslines] = ...
  myparse(varargin,...
  'trialdividers',false,...
  'pulldownselect',false,...
  'behaviorcolorslines',false);

figure(hfig);
clf;
ax = axes;

nexps = numel(expdirs);
nT = T1-T0+1;
nbehaviors = numel(behaviornames);
assert(size(labels,1)==nexps);
assert(size(labels,2)==nT);
assert(size(labels,3)==nbehaviors);
assert(numel(jabfiles)==nbehaviors,...
  'Input arg ''jabfiles'' must be a cellstr specifying the containing jab for each behavior');

if behaviorcolorslines || nbehaviors>7
  behaviorcolors = lines(nbehaviors);
else
  BEH_COLORS = [
         0         0    1.0000; ...
         0    0.5000         0; ...
    1.0000         0         0; ...
         0    0.7500    0.7500; ...
    0.7500         0    0.7500; ...
    0.7500    0.6000         0; ...
    0.2500    0.2500    0.2500];
  behaviorcolors = BEH_COLORS;
end
nobehaviorcolors = behaviorcolors + 0.67*(1-behaviorcolors); % gray transform
yrad = 1/nbehaviors;
xl = [T0-10,T1+10];

h = cell(nexps,nbehaviors); % patch handles; we keep track of these but ends up unused
hNo = cell(nexps,nbehaviors);
hlegend = nan(1,nbehaviors);
boutmat = cell(nexps,nbehaviors);
isfirst = true;
for j = 1:nbehaviors,
  behclr = behaviorcolors(j,:);
  nobehclr = nobehaviorcolors(j,:);
  for i = 1:nexps,

    if trialdividers && j==1
      % plot dividers for each exp
      plot(xl,repmat(i-yrad/2,1,2),'k:');
    end
    if isfirst,
      isfirst = false;
      hold on;
    end

    [starts,ends] = get_interval_ends(labels(i,:,j)>0);
    boutmat{i,j} = [starts(:) ends(:)];

    % pos behaviors
    if numel(starts)>0
      h{i,j} = hlpPatch(starts,ends,i,j,yrad,T0,behclr,{'FaceAlpha',0.4});
      if isnan(hlegend(j)),
        hlegend(j) = h{i,j}(1);
      end
    end

    % negative behaviors
    [starts,ends] = get_interval_ends(labels(i,:,j)<0);
    if numel(starts)>0
      hNo{i,j} = hlpPatch(starts,ends,i,j,yrad,T0,nobehclr,{'FaceAlpha',0.4});
    end

  end
end

line_names = cell(1,nexps);
for i = 1:nexps,
  [~,line_names{i}] = myfileparts(expdirs{i});
end
legend(hlegend(~isnan(hlegend)),behaviornames(~isnan(hlegend)));
yoffset = (nbehaviors-1)/nbehaviors/2;
set(ax,'YTick',yoffset+(1:nexps),'YTickLabel',line_names,'XLim',xl,'YLim',[1,nexps+1],'YDir','reverse','Box','off','TickDir','out');
if isprop(ax,'TickLabelInterpreter')
  ax.TickLabelInterpreter = 'none';
end

% set up axis guidata; data used in callbacks
gdata = struct();
gdata.T0 = T0;
gdata.T1 = T1;
gdata.labels = labels;
gdata.jabfiles = jabfiles;
gdata.expdirs = expdirs;
gdata.Nexp = numel(expdirs);
gdata.behaviornames = behaviornames;
gdata.Nbeh = numel(behaviornames);
gdata.behaviorcolors = behaviorcolors;
gdata.hAutoMarks = [];

% gdata.EXP_SELECTED_COLOR = [1 1 0];
% gdata.EXP_SELECTED_ALPHA = 1;
gdata.EXPZOOMPLUSMINUS = 1; % when zooming on exp, include +/- this many neighboring exps
% gdata.tfExpSelInProgress = false;
% gdata.tfExpIsUserSelected = false(numel(expdirs),1);
% gdata.hUserSelectionPatches = nan(numel(expdirs),1);
% gdata.customGroupVizInfo = cell(0,1); % customGroupVizInfo{i}.name % name of grp
% customGroupVizInfo{i}.tf  % indicator vec for ith viz group
% customGroupVizInfo{i}.h   % plot handles for ith viz group
% Note: due to arbitrary removal, customGroupVizInfo{i} may be [] for
% arbitrary i.
% gdata.CUSTOMGROUPMODN = 7; % this the "mod" for lines()

% gdata.axGroupStats = []; % second/overlay axis for group stats
guidata(ax,gdata);

if pulldownselect
  set(hfig,'units','pixels');
  set(hfig,'position',[100 100 1000 800],'toolbar','figure'); % adding uicontrols to figure below

  tmpunits = get(ax,'Units');
  set(ax,'Units','normalized');
  axpos = get(ax,'Position');
  set(ax,'Units',tmpunits);

  selections = [{'<all exps>'};expdirs(:)];
  uicontrol('style','popupmenu','String',selections,'fontsize',7,'units','normalized',...
    'position',[axpos(1) 0.955 axpos(3) 0.02],'callback',@(zS,zE)cbkExpZoom(zS,ax));
  uicontrol('style','text','String','Experiment zoom: ','fontweight','bold','horizontalalignment','right',...
    'units','normalized','position',[axpos(1)-0.2 0.95 0.2 0.02],'backgroundcolor',get(hfig,'color'));
end

set(ax,'ButtonDownFcn',@(src,evt)cbkAxBDF(src));

function hPatch = hlpPatch(starts,ends,i,j,yrad,T0,clr,patchArgs)
nbouts = numel(starts);
ends = ends-0.5;
starts = starts-0.5;
x = [starts;starts;ends;ends;starts]+T0-1;
y = i+yrad*[0;1;1;0;0]+yrad*(j-1);
xx = x;
yy = repmat(y,[1 nbouts]);
hPatch = patch(xx,yy,-1*ones(size(xx)),clr,...
  'MarkerFaceColor',clr,'HitTest','off','EdgeColor','none',patchArgs{:});

function cbkExpZoom(src,ax)
gdata = guidata(ax);

val = get(src,'value');
str = get(src,'String');
str = str{val};

expnum = find(strcmp(str,gdata.expdirs));
if isempty(expnum)
  ylim(ax,'auto');
else
  ylim(ax,[expnum-gdata.EXPZOOMPLUSMINUS expnum+gdata.EXPZOOMPLUSMINUS+1]);
end

function cbkAxBDF(ax)

gdata = guidata(ax);
ty = get(ancestor(ax,'figure'),'SelectionType');
switch ty
  case 'extend' % Shift-click
    yl = ylim(ax);
    if diff(yl)<=1.5
      % fully zoomed; zoom out
      ylim(ax,'auto');
    elseif diff(yl)<=gdata.EXPZOOMPLUSMINUS*2+1
      % medium zoom; go to full zoom (single exp)
      pt = get(ax,'currentpoint');
      expnum = floor(pt(1,2));
      ylim(ax,[expnum expnum+1]);
    else
      % go to medium zoom
      pt = get(ax,'currentpoint');
      expnum = floor(pt(1,2));
      ylim(ax,[expnum-gdata.EXPZOOMPLUSMINUS expnum+gdata.EXPZOOMPLUSMINUS+1]);
    end
  case 'alt' % Ctrl-click
%     pt = get(ax,'currentpoint');
%     expnum = floor(pt(1,2));
%     gdata = guidata(ax);
%     if expnum > gdata.Nexp % Can occur if ctrl-click slightly 'below' axis
%       warning('ethogram_plot:noSuchExp','Clicked point beyond range of experiments.');
%     else
%       gdata = lclToggleExpSelection(gdata,expnum);
%     end
%     gdata.tfExpSelInProgress = true;
%     guidata(ax,gdata);
  otherwise
    patchClickCallback(ax);
end

function patchClickCallback(h)
% Check for double click

% AL 20150113: This is not working

persistent chk

dothis = true;
if isempty(chk)
  chk = 1;
  pause(0.5); %Add a delay to distinguish single click from a double click
  if chk == 1
    chk = [];
    return;
  end
else
  dothis = false;
  chk = [];
end

if ~dothis, return; end
% Below executes only on double click

gdata = guidata(h);

% if gdata.scoresnotjabs
%   warning('ethogram_plot_core:nojabs','No jab files specified; clicking on bouts is disabled.');
%   return;
% end

pt = get(h,'currentpoint');
frameno = round(pt(1,1));
if frameno<0 || frameno>size(gdata.labels,2),
  return;
end
expnum = floor(pt(1,2));

% determine behavior number/index so we know which jab to open
behnum = find(gdata.labels(expnum,frameno,:));
if numel(behnum)==0, behnum = 1:numel(gdata.behaviornames); end
if numel(behnum)>1
  [sel,ok] = listdlg('ListSize',[650 220],'Name','Select a Behavior to see in JAABA',...
    'ListString',gdata.behaviornames(behnum),'SelectionMode','single','OKString','Select',...
    'InitialValue',1);
  if ok == 0, return; end
  behnum = behnum(sel);
end
assert(any(behnum==(1:gdata.Nbeh)));
selectedJab = gdata.jabfiles{behnum};

JLabelInterf.openJabExpFrame(selectedJab,gdata.expdirs{expnum},frameno);


function [ap_cascade, ap_dp, speedup] = compare_runtime(model, prec, suffix)

error('Read the README in this file and then remove this line.');

%                        !!! README FIRST !!!
%
% To perform experiments using the methodology in the paper you MUST
% compile the SINGLE-THREADED version of the convolution routine.
% Otherwise you will be comparing a multi-threaded, BLAS accelerated
% version of the DP algorithm to a single-threaded, non-BLAS accelerated
% version of the cascade algorithm.  To compile the single-threaded
% convolution routine simply run this command in matlab:
%
% >> mex -O fconv.cc -o fconv
%
% When you're done, you'll probably want to switch back to the multi-threaded,
% BLAS accelerated version.  You can do this by running the command:
%
% >> mex -O fconvblas.cc -lmwblas -o fconv

globals;
if nargin < 3
  suffix = num2str(prec);
end
[boxes, times] = ...
  dotest(model, 'test', model.year, [model.year '_CASCADE_' suffix], prec);

ap_cascade = pascal_eval(model.class, boxes{1}, 'test', model.year, ['2007_CASCADE_' suffix]);
ap_dp = pascal_eval(model.class, boxes{2}, 'test', model.year, ['2007_DP_' suffix]);
speedup = mean(times(:,2)./times(:,1));

function [boxes, times] = dotest(model, testset, year, suffix, prec)

setVOCyear = year;
globals;
pascal_init;

pca = 5;
cls = model.class;
ids = textread(sprintf(VOCopts.imgsetpath, testset), '%s');

[prec, recall, thresh] = cascade_thresh(model, year, prec);
model.thresh = thresh;
pca = 5;
cscmodel = cascade_model(model, model.year, pca, model.thresh);

times = zeros(length(ids), 3);
turns = round(rand(length(ids),1));

% run detector in each image
for i = 1:length(ids);
  if strcmp('inriaperson', cls)
    % INRIA uses a mixutre of PNGs and JPGs, so we need to use the annotation
    % to locate the image.  The annotation is not generally available for PASCAL
    % test data (e.g., 2009 test), so this method can fail for PASCAL.
    rec = PASreadrecord(sprintf(VOCopts.annopath, ids{i}));
    im = imread([VOCopts.datadir rec.imgname]);
  else
    im = imread(sprintf(VOCopts.imgpath, ids{i}));
  end

  % time feature computation
  th = tic();
  pyra = featpyramid(im, model);
  time_feat = toc(th);

  % randomize order to wash out who-went-first cache effects
  if turns(i)
    th = tic();
    [dets_CSC, boxes_CSC] = cascade_detect(pyra, cscmodel, cscmodel.thresh);
    time_CSC = toc(th);

    th = tic();
    [dets_DP, boxes_DP] = gdetect(pyra, model, model.thresh);
    time_DP = toc(th);
  else
    th = tic();
    [dets_DP, boxes_DP] = gdetect(pyra, model, model.thresh);
    time_DP = toc(th);

    th = tic();
    [dets_CSC, boxes_CSC] = cascade_detect(pyra, cscmodel, cscmodel.thresh);
    time_CSC = toc(th);
  end

  if ~isempty(boxes_CSC)
    [dets_CSC boxes_CSC] = clipboxes(im, dets_CSC, boxes_CSC);
    I = nms(dets_CSC, 0.5);
    boxes{1}{i} = dets_CSC(I,[1:4 end]);
    parts{1}{i} = boxes_CSC(I,:);
  else
    boxes{1}{i} = [];
    parts{1}{i} = [];
  end

  if ~isempty(boxes_DP)
    boxes_DP = reduceboxes(model, boxes_DP);
    [dets_DP boxes_DP] = clipboxes(im, dets_DP, boxes_DP);
    I = nms(dets_DP, 0.5);
    boxes{2}{i} = dets_DP(I,[1:4 end]);
    parts{2}{i} = boxes_DP(I,:);
  else
    boxes{2}{i} = [];
    parts{2}{i} = [];
  end

  times(i,:) = [time_CSC time_DP time_feat];
  ravg = mean(times(1:i,2)./times(1:i,1));
  fprintf('%s: testing: %s %s, %d/%d (%.3f)\n', ...
          cls, testset, VOCyear, i, length(ids), ravg);
end
save([cachedir cls '_boxes_' testset '_' suffix '.mat'], 'boxes', 'times');


function [dateNum, dateStr] = getCurrTime()
ds = char(datetime('now','TimeZone','local','Format','yyyy-MM-dd HH:mm:ss'));
[dateNum, dateStr] = datestr2datenum(ds);


report_this_filefun(mfilename('fullpath'));

av4 = [];
ni = 200
newt3 = newcat;
figure
fi = gcf;
for i = 2.0:0.1:3.1
    l = newt3(:,6) >= i;
    newt2 = newt3(l,:);
    bwithde
    drawnow
    figure_w_normalized_uicontrolunits(fi)
    hold on
    plot(av2(:,2),av2(:,1))
    drawnow

end


function trialmodels = single_trial_setup_models(EXPT, onsets, eventdesign, s, varargin)

    % trialmodels = single_trial_setup_models(EXPT, onsets, eventdesign, s, varargin)
    %Constructs a trial-level design matrix, estimates betas and writes them to
    %img files.
    %
    %USAGE: single_trial_analysis(EXPT,onsets,eventdesign,submat);
    %       e.g.,
    %       [onsets2 runlabels eventlabels rundesign eventdesign] = ...
    %       onsets2singletrial(subjects,EXPT.SPM.nscan,'TR',2,eventnames,'noadd');
    %
    %       single_trial_analysis(EXPT,onsets2,eventdesign,1,'gamma3',60);
    %
    %       single_trial_analysis(EXPT,onsets2,eventdesign,2,'gamma3',60, ...
    %       'ratings',ratings,'conditioncontrasts',[-3 -1 1 3], ...
    %       'conditionnames',{'warm' 'low' 'medium' 'hot'}, 'mvmt', ravols_movement_params);
    %
    %INPUTS:
    %   EXPT - EXPT object
    %       Required fields:
    %       subjects
    %       TR
    %       mask
    %       SPM.nscan
    %       FILES.im_files
    %
    %   onsets - 'cell' format onsets (see below)
    %       to convert from structure format, see onsets2singletrial
    %
    %   eventdesign - stick (delta) function indicating condition onsets;
    %                 returned as output of onsets2singletrial
    %
    %   submat - subject (or vector of subject) indices
    %   basistype (optional) - basis type (default: 'gamma3')
    %   hipass (optional) - high-pass filter (default: 60)
    %   startslice (optional) - starting slice
    %
    % Optional inputs:
    % conditioncontrasts: followed by contrasts across expt'l conditions
    % which are coded in eventdesign.  e.g., [-3 -1 1 3]';
    %
    % conditionnames: names for each condition in eventdesign: {'warm' 'low' 'medium' 'hot'};
    %
    % ratings : followed by behavioral data values
    % in same format as onsets
    % See onsets2singletrial for ways to do this.
    %
    %OUTPUTS:
    %   -saves a mat file with the suffix 'design' that contains the design mtx
    %
    %see trial_level_beta3.m for more information
    %
    %A NOTE ABOUT ONSETS:
    %The SCAN lab uses two different formats for its onsets. The
    %'structure' format contains a different field for each subject, and a
    %different sub-field for each run, with sub-fields for each condition that
    %contain the onsets. The 'cell' format is a cell vector, where each cell
    %contains 1 subject; within each subject-cell is another cell vector, where
    % each cell contains onsets for a particular run/condition. If, for example, you have 2
    %conditions and 2 runs, the cell array will be organized as follows:
    %The 1st cell will contain the onsets of all events from condition 1 in
    %run 1, the 2nd cell will contain the onsets of events from condition 2 in
    %run 1, the 3rd cell will contain onsets of events from condition 1 in run
    %2, etc. Specifically for single-trial analysis, the onsets must be in cell
    %format (and in TRs), with the added requirement that the onsets be adjusted
    %so that the first onset of each run is equal to the onset of the last scan
    %(*not event*) of the previous run. For example, if you have 100 scans in
    %each run, the first onset of the 1st run should be 0, the first onset of
    %the 2nd run should be 100, etc.
    %A useful function in this regard is 'onsets2singletrial',which converts
    %structure-format onsets to cell-format and adjusts the timing. The output of
    %onsets2singletrial can be fed directly into single_trial_analysis.
    %
    % Sam Gershman, 2006
    % Modified by Tor Wager, March 2007

    %-------- SOME PARAMETERS ---------------%
    TR = EXPT.TR;                   %TR
    nscans = EXPT.SPM.nscan;        %vector containing number of scans in each run
    nruns = length(nscans);         %number of runs
    %----------------------------------------%

    %----- SET DEFAULTS ---------------------%
    basistype = 'gamma3';
    hipass = 100;
    domvmt2 = 0;
    %----------------------------------------%

    disp(' '); fprintf('Building design matrix for %3.0f...\n',s);
    disp(['Name of this subject in EXPT.subjects : ' EXPT.subjects{s}]);

    ratings = []; conditioncontrasts = []; conditionnames = []; startslice = 1;

    for i = 1:length(varargin)
        if ischar(varargin{i})

            switch varargin{i}

                case 'ratings', ratings =  varargin{i+1};
                    disp('Found ratings. Will include in model.');

                case {'conditionnames'}, conditionnames = varargin{i+1};
                case {'conditioncontrasts'}, conditioncontrasts = varargin{i+1};

                case {'mvmt','movement'}, mvmt =  varargin{i+1}; disp('Found movement parameters.')

                case 'mvmt2', domvmt2 = 1; disp('Squared/lagged movement model is ON.');

                case {'basis','basisset','bases','basistype'} % name(s) of basis sets to use
                    disp('Found basistype.');
                    basistype = varargin{i+1}; varargin{i+1} = [];

                case 'whichbasis' % enter index in basis sets for each event
                    disp('Found whichbasis.');
                    whichbasis = varargin{i+1};

                case {'hipass','hplength','hp'}, hipass = varargin{i+1};
                    disp('Found high-pass filter length.')

                otherwise
                    disp('Unknown string input.')
            end
        end
    end

        % ---------------------------------------------------------------
        % set up images and onsets for this subject
        % ---------------------------------------------------------------

        ons = onsets{s};    %onsets for subj

        % Tor added this: we now need to enter ntrials to
        % whole_brain_filter
        ntrials = length(ons);

        % ---------------------------------------------------------------
        % CONSTRUCT TRIAL-LEVEL DESIGN MATRIX (models single trials)
        % ---------------------------------------------------------------

        disp('  Constructing design matrix...');

        if ~exist('whichbasis', 'var')
            fprintf('Using the same basis set for all events : %s\n', basistype);

            [trialX, trial_px, bf] = trial_level_beta3('onsets',ons,'output','design', ...
                'rows',sum(nscans),'basistype',basistype,'tr',TR);

            trialX = trialX(:, 1:end-1);    %remove 'experiment' intercept

        else
            fprintf('   Using basis sets indexed by whichbasis for each event\n');
            fprintf('   This will ONLY work if all basis sets have same # parameters.\n');

            trialX = [];

            for i = 1:length(ons)

                fprintf(1,'%3.0f ', i);

                if i == 1
                    [trialX_thistrial, trial_px, bf] = trial_level_beta3('onsets',ons(i),'output','design', ...
                    'rows',sum(nscans),'basistype',basistype{whichbasis(i)},'tr',TR);
                else
                    [trialX_thistrial] = trial_level_beta3('onsets',ons(i),'output','design', ...
                    'rows',sum(nscans),'basistype',basistype{whichbasis(i)},'tr',TR);
                end

                trialX_thistrial = trialX_thistrial(:,1:end-1); % get rid of intercept

                trialX = [trialX trialX_thistrial];

            end

            fprintf(1, '\n');
        end

        fprintf(1,'   Number of basis functions: %3.0f\n',size(bf,2))
        disp('NOTE: all basis sets for different event types MUST have same number of basis functions!')

        %CONSTRUCT HIGH-PASS FILTERING MATRIX
        % ---------------------------------------------------------------
        disp('  Adding high-pass filter to design matrix...');
        khstr = [];
        for r = 1:nruns

            [dummy,KL,KH{r}] = use_spm_filter(TR,nscans(r),'none','specify',hipass);
            if r==1; kh = ['KH{',num2str(r),'}']; else kh = [',KH{',num2str(r),'}']; end
            khstr = strcat(khstr,kh);

        end
        KH = eval(['blkdiag(',khstr,')']);

        % Add movement param stuff here
        % ---------------------------------------------------------------
        MV = [];
        if exist('mvmt', 'var')

            disp('  Adding movement parameters...');

            if size(mvmt, 1) ~= size(trialX, 1)
                error('mvmt params and trial design are different lengths.');
            end

            mvmt = scale(mvmt);

            if domvmt2
                disp('   Adding lagged and squared movement parameters...');
                m2 = [zeros(1, 6); mvmt(1:end-1,:)];
                %gradient(mvmt);
                MV = [mvmt mvmt .^ 2 m2 m2 .^ 2];

            else
                MV = mvmt;
            end

        end

        % Add intercepts and dummy covs for the first 2 trials
        % ---------------------------------------------------------------
        disp('  Adding intercepts and dummy covs for first 1 trials...');
        whremove = 1;  % could be 1:2, 1:3, etc.
        I = intercept_model(nscans, 1, whremove);

        % Put all regressors together
        % ---------------------------------------------------------------
        trialX_of_interest = trialX;

        trialX = [trialX KH MV I];
        trialpx = pinv(trialX);

        % save
        % ---------------------------------------------------------------
        disp(['  Saving to: ',EXPT.subjects{s},'_design.mat']);
        save([EXPT.subjects{s},'_design'], 'trialX', 'trialpx', 'trialX_of_interest');

        % ---------------------------------------------------------------
        % Get info for SUBJECT-LEVEL DESIGN MATRIX (models condition
        % effects across trials)
        % ---------------------------------------------------------------

        % Each row is a trial, each col. is a task condition
        % indicator matrix of 1/0, 1's in col. k where trials belong to condition k

        % Build subject-level design matrix, for analysis of condition
        % effects across trials
        % No intercept: interpret change from abs. baseline of zero

        subjlevelX = eventdesign{s};

        if size(subjlevelX, 1) ~= ntrials
            error('eventdesign is wrong size for ntrials.  Error in either onsets2singletrial or ons.');
        end

        subjlevelpx = pinv(subjlevelX);

        % contrasts should be in column vectors
        if isrow(conditioncontrasts), conditioncontrasts = conditioncontrasts'; end

        % stuff needed for whole_brain_filter trial-level models
        % ---------------------------------------------------------------

        trialmodels.trialX = trialX;
        trialmodels.bf = bf;
        trialmodels.ntrials = ntrials;
        trialmodels.trialpx = trialpx;
        trialmodels.subjlevelX = subjlevelX;
        trialmodels.subjlevelpx = subjlevelpx;
        trialmodels.conditioncontrasts = conditioncontrasts;
        trialmodels.conditionnames = conditionnames;

        if exist('ratings','var')
            disp('Found ratings and will include in trialmodels var, which is used in model fitting.');
            disp('So: will analyze by ratings in model fitting.');

            trialmodels.ratings = ratings{s};
        end

        % stuff to save even tho we don't need it in fitting.
        trialmodels.ons = ons;
        trialmodels.basistype = basistype;
        trialmodels.ntrials = ntrials;

        save([EXPT.subjects{s},'_design'],'-append','trialmodels');

        % tor added this to make image;
        figure; imagesc(trialX), colormap gray; drawnow

disp('Done setting up models.');

    end


%%
% Copyright (c) 2019-present, Mahmoud Afifi
%
% This source code is licensed under the license found in the
% LICENSE file in the root directory of this source tree.
%
% Please, cite the following paper if you use this code:
%
% Mahmoud Afifi and Michael S. Brown. What else can fool deep learning?
% Addressing color constancy errors on deep neural network performance.
% ICCV, 2019
%
% Email: mafifi@eecs.yorku.ca | m.3afifi@gmail.com
%%

%%
% This demo generates ten images from the given image. Each generated file
% will be in the following format: originalName_WB_CS.ext, where
% originalName is the original filename, WB refers to white balance (WB)
% settings, and CS is the camera style.
% WB settings are:
%   - T: Tungsten WB [2850 Kelvin (K)]
%   - F: Fluorescent WB [3800K]
%   - D: Daylight WB [5500K]
%   - C: Cloudy WB [6500K]
%   - S: Shade WB [7500K]
% Camera styes are:
%   - AS: Adobe Standard
%   - CS: Camera Standard
% The generated images and a copy of the input image (optional) will be
% saved in the output directory (output_dir)

%%
clear;
clc

imagename = fullfile('..','images','image1.jpg'); % image filename
output_dir = fullfile('..','results'); % output directory to save the
% generated images and a copy of input image
useGPU = false; %to use GPU
NumOfImgs = 10; % should be less than or equal 10
saveOrig = true; %to save a copy of the original image in output_dir

if NumOfImgs > 10
    error('Cannot generate more than 10 images for each input image');
end

if exist(output_dir,'dir') == 0
    mkdir(output_dir);
end

if useGPU
    load('synthWBmodel_GPU.mat'); % load WB_emulator GPU model
else
    load('synthWBmodel.mat'); % load WB_emulator CPU model
end

I_in = imread(imagename); % read the image
[~,name,ext] = fileparts(imagename);
if saveOrig == true % save a copy of the original image
    imwrite(I_in,fullfile(output_dir,sprintf('%s%s%s',name,'_original',ext)));
end

%%
disp('processing...');
tic
% generate images with synthetic WB effects
out = WB_emulator.generate_wb_srgb(I_in, NumOfImgs);
toc
if useGPU
    out = gather(out); % if GPU is used, convert images to a double tensor
end
disp('done!');
disp('saving...');
for i =1 : size(out,4)
    % save generated images
    imwrite(out(:,:,:,i),fullfile(output_dir,sprintf('%s%s%s',...
        name,WB_emulator.wb_photo_finishing{i},ext)));
end


function demnlab(action);
%DEMNLAB A front-end Graphical User Interface to the demos
%
%	Description
%	This function will start a user interface allowing the user to select
%	different demonstration functions to view. The demos are divided into
%	4 groups, with the demo being executed by selecting the desired
%	option from a pop-up menu.
%
%	See also
%

%	Copyright (c) Ian T Nabney (1996-2001)

% If run without parameters, initialise gui.
if nargin<1,
	action='initialise';
end;

if strcmp(action,'initialise'),

  % Create figure
  fig = figure( ...
    'Name', 'Netlab Demos', ...
    'NumberTitle', 'off', ...
    'Color', [0.7529 0.7529 0.7529], ...
    'Visible', 'on');

  % Create GROUPS
  % Bottom of demo buttons
  group1_bot = 0.20;
  group1_top = 0.75;
  uicontrol(fig, ...
    'Style', 'frame', ...
    'Units', 'normalized', ...
    'Position', [0.03 group1_bot 0.94 group1_top - group1_bot], ...
    'BackgroundColor', [0.5 0.5 0.5]);

  % Bottom of help and close buttons
  group2_bot = 0.04;
  uicontrol(fig, ...
    'Style', 'frame', ...
    'Units', 'normalized', ...
    'Position', [0.03 group2_bot 0.94 0.12], ...
    'BackgroundColor', [0.5 0.5 0.5]);

  % Draw title
  hLogoAxis = axes( ...
    'Units', 'normalized', ...
    'Position', [0.05 0.82 0.90 0.14], ...
    'Box', 'off', ...
    'XColor', [0 0 0], ...
    'YColor', [0 0 0], ...
    'Visible', 'on');

  load netlogo;			% load image and colour map
  colormap(netcmap(1:3,:));	% change colour map: don't need many entries
  image(nlogo);			% draw logo
  axis('image');		% ensures pixels on axis are square
  axis off;			% turn axes off

  % Create static text
  uicontrol(fig, ...
    'Style', 'text', ...
    'Units', 'normalized', ...
    'BackgroundColor', [0.5 0.5 0.5], ...
    'Position', [0.05 group1_top-0.1 0.90 0.08], ...
    'String', 'Select demo to run:');

  % First row text offset
  tRow1Offset = 0.14;
  % Offset between text and button
  TBoffset = 0.07;
  % First row button offset
  bRow1Offset = tRow1Offset+TBoffset;
  % ONE text
  uicontrol(fig, ...
    'Style', 'text', ...
    'Units', 'normalized', ...
    'BackgroundColor', [0.5 0.5 0.5], ...
    'Position', [0.08 group1_top-tRow1Offset 0.36 0.05], ...
    'String', 'Regression');

  popup1str(1) = {'Select Option'};
  popup1str(2) = {'Multi-Layer Perceptron'};
  popup1str(3) = {'Radial Basis Function'};
  popup1str(4) = {'Mixture Density Network'};
  % ONE popup
  hPop1 = uicontrol(fig, ...
    'Style','popup', ...
    'Units','normalized', ...
    'String', popup1str, ...
    'Position', [0.08 group1_top-bRow1Offset 0.36 0.08], ...
    'BackgroundColor', [0.7 0.7 0.7], ...
    'Callback', 'demnlab popup1');

  % TWO text
  uicontrol(fig, ...
    'Style', 'text', ...
    'Units', 'normalized', ...
    'BackgroundColor', [0.5 0.5 0.5], ...
    'Position', [0.56 group1_top-tRow1Offset 0.36 0.05], ...
    'String', 'Classification');

  popup2str(1) = popup1str(1);
  popup2str(2) = {'Generalised Linear Model (2 class)'};
  popup2str(3) = {'Generalised Linear Model (3 class)'};
  popup2str(4) = {'Multi-Layer Perceptron'};
  popup2str(5) = {'K nearest neighbour'};
  % TWO popup
  hPop2 = uicontrol(fig, ...
    'Style','popup', ...
    'Units','normalized', ...
    'String', popup2str, ...
    'Position', [0.56 group1_top-bRow1Offset 0.36 0.08], ...
    'BackgroundColor', [0.7 0.7 0.7], ...
    'Callback', 'demnlab popup2');

  tRow2Offset = 0.30;
  bRow2Offset = tRow2Offset+TBoffset;
  % THREE text
  uicontrol(fig, ...
    'Style', 'text', ...
    'Units', 'normalized', ...
    'BackgroundColor', [0.5 0.5 0.5], ...
    'Position', [0.08 group1_top - tRow2Offset 0.36 0.05], ...
    'String', 'Density Modelling and Clustering');

  popup3str(1) = popup1str(1);
  popup3str(2) = {'Gaussian Mixture (EM training)'};
  popup3str(3) = {'Gaussian Mixture (spherical)'};
  popup3str(4) = {'Gaussian Mixture (diagonal)'};
  popup3str(5) = {'Gaussian Mixture (full)'};
  popup3str(6) = {'Neuroscale'};
  popup3str(7) = {'GTM (EM training)'};
  popup3str(8) = {'GTM (visualisation)'};
  popup3str(9) = {'K-means clustering'};
  popup3str(10) = {'Self-Organising Map'};
  % TWO popup
  % THREE popup
  hPop3 = uicontrol(fig, ...
    'Style','popup', ...
    'Units','normalized', ...
    'String', popup3str, ...
    'Position', [0.08 group1_top - bRow2Offset 0.36 0.08], ...
    'BackgroundColor', [0.7 0.7 0.7], ...
    'Callback', 'demnlab popup3');

  % FOUR text
  uicontrol(fig, ...
    'Style', 'text', ...
    'Units', 'normalized', ...
    'BackgroundColor', [0.5 0.5 0.5], ...
    'Position', [0.56 group1_top - tRow2Offset 0.36 0.05], ...
    'String', 'Bayesian Methods');

  popup4str(1) = popup1str(1);
  popup4str(2) = {'Sampling the MLP Prior'};
  popup4str(3) = {'Evidence Approximation for MLP'};
  popup4str(4) = {'Evidence Approximation for RBF'};
  popup4str(5) = {'Evidence Approximation in Classification'};
  popup4str(6) = {'ARD for MLP'};
  popup4str(7) = {'Sampling the GP Prior'};
  popup4str(8) = {'GPs for Regression'};
  popup4str(9) = {'ARD for GP'};
  % FOUR popup
  hPop4 = uicontrol(fig, ...
    'Style','popup', ...
    'Units','normalized', ...
    'String', popup4str, ...
    'Position', [0.56 group1_top - bRow2Offset 0.36 0.08], ...
    'BackgroundColor', [0.7 0.7 0.7], ...
    'Callback', 'demnlab popup4');

  tRow3Offset = 0.45;
  bRow3Offset = tRow3Offset+TBoffset;
  % FIVE text
  uicontrol(fig, ...
    'Style', 'text', ...
    'Units', 'normalized', ...
    'BackgroundColor', [0.5 0.5 0.5], ...
    'Position', [0.08 group1_top - tRow3Offset 0.36 0.05], ...
    'String', 'Optimisation and Visualisation');

  popup5str(1) = popup1str(1);
  popup5str(2) = {'Algorithm Comparison'};
  popup5str(3) = {'On-line Gradient Descent'};
  popup5str(4) = {'Hinton Diagrams'};
  % FIVE popup
  hPop5 = uicontrol(fig, ...
    'Style','popup', ...
    'Units','normalized', ...
    'String',popup5str, ...
    'Position', [0.08 group1_top - bRow3Offset 0.36 0.08], ...
    'BackgroundColor', [0.7 0.7 0.7], ...
    'Callback', 'demnlab popup5');

  % SIX text
  uicontrol(fig, ...
    'Style', 'text', ...
    'Units', 'normalized', ...
    'BackgroundColor', [0.5 0.5 0.5], ...
    'Position', [0.56 group1_top - tRow3Offset 0.36 0.05], ...
    'String', 'Sampling');

  popup6str(1) = popup1str(1);
  popup6str(2) = {'Sampling a Gaussian'};
  popup6str(3) = {'MCMC sampling (Metropolis)'};
  popup6str(4) = {'Hybrid MC (Gaussian mixture)'};
  popup6str(5) = {'Hybrid MC for MLP I'};
  popup6str(6) = {'Hybrid MC for MLP II'};
  % SIX popup
  hPop6 = uicontrol(fig, ...
    'Style','popup', ...
    'Units','normalized', ...
    'String', popup6str, ...
    'Position', [0.56 group1_top - bRow3Offset 0.36 0.08], ...
    'BackgroundColor', [0.7 0.7 0.7], ...
    'Callback', 'demnlab popup6');

  % Create HELP button
  uicontrol(fig, ...
    'Units', 'normalized', ...
    'Position' , [0.05 group2_bot+0.02 0.40 0.08], ...
    'String', 'Help', ...
    'Callback', 'demnlab help');

  % Create CLOSE button
  uicontrol(fig, ...
    'Units', 'normalized', ...
    'Position' , [0.55 group2_bot+0.02 0.40 0.08], ...
    'String', 'Close', ...
    'Callback', 'close(gcf)');

  hndlList=[fig hPop1 hPop2 hPop3 hPop4 hPop5 hPop6];
  set(fig, 'UserData', hndlList);
  set(fig, 'HandleVisibility', 'callback');

elseif strcmp(action, 'popup1'),

  hndlList=get(gcf,'UserData');
  hPop = hndlList(2);

  selected = get(hPop, 'Val');
  set(hPop, 'Val', [1]);

  switch selected
    case 2
      demmlp1;
    case 3
      demrbf1;
    case 4
      demmdn1;
  end;

elseif strcmp(action,'popup2'),

  hndlList=get(gcf,'UserData');
  hPop = hndlList(3);

  selected = get(hPop, 'Val');
  set(hPop, 'Val', [1]);

  switch selected
    case 2
      demglm1;
    case 3
      demglm2;
    case 4
      demmlp2;
    case 5
      demknn1;
  end

elseif strcmp(action,'popup3'),

  hndlList=get(gcf,'UserData');
  hPop = hndlList(4);

  selected = get(hPop, 'Val');
  set(hPop, 'Val', [1]);

  switch selected
    case 2
      demgmm1;
    case 3
      demgmm2;
    case 4
      demgmm3;
    case 5
      demgmm4;
    case 6
      demns1;
    case 7
      demgtm1;
    case 8
      demgtm2;
    case 9
      demkmn1;
    case 10
      demsom1;
  end

elseif strcmp(action,'popup4'),

  hndlList=get(gcf,'UserData');
  hPop = hndlList(5);

  selected = get(hPop, 'Val');
  set(hPop, 'Val', [1]);

  switch selected
    case 2
      demprior;
    case 3
      demev1;
  case 4
      demev3;
  case 5
      demev2;
    case 6
      demard;
    case 7
      demprgp;
    case 8
      demgp;
    case 9
      demgpard;
  end

elseif strcmp(action,'popup5'),

  hndlList=get(gcf,'UserData');
  hPop = hndlList(6);

  selected = get(hPop, 'Val');
  set(hPop, 'Val', [1]);

  switch selected
    case 2
      demopt1;
    case 3
      demolgd1;
    case 4
      demhint;
  end

elseif strcmp(action,'popup6'),

  hndlList=get(gcf,'UserData');
  hPop = hndlList(7);

  selected = get(hPop, 'Val');
  set(hPop, 'Val', [1]);

  switch selected
    case 2
      demgauss;
    case 3
      demmet1;
    case 4
      demhmc1;
    case 5
      demhmc2;
    case 6
      demhmc3;
  end

elseif strcmp(action, 'help'),

  helpStr = {'To run a demo, press the appropriate button.'; ...
	'Instructions and information will appear in the Matlab';...
	'command window.'};

  hHelpDlg = helpdlg(helpStr, 'Netlab Demo Help');

end;


function varargout=lpcar2am(varargin)
%
% For calling details please see v_lpcar2am.m
%
% This dummy routine is included for backward compatibility only
% and will be removed in a future release of voicebox. Please use
% v_lpcar2am.m in future and/or update with v_voicebox_update.m
%
%      Copyright (C) Mike Brookes 2018
%      Version: $Id: lpcar2am.m 10863 2018-09-21 15:39:23Z dmb $
%
if nargout
    varargout=cell(1,nargout);
    [varargout{:}]=v_lpcar2am(varargin{:});
else
    v_lpcar2am(varargin{:});
end


function y = isreal( x )
y = isreal( cvxaff( x ) );

% Copyright 2005-2016 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


%% (Internal) Guess PPG/ABP signals indexes in a multimodal recording
%
%   [PPG_ABP_idx, ECG_header ] = get_PPG_ABP_idx_from_header(ECG_header)
%
% Arguments:
%
%      + ECG_header: header info
%
% Output:
%
%      + PPG_ABP_idx: indexes of the ECG signals in the multimodal matrix
%
%      + ECG_header: header of a ECG only recording
%
% Example:
%
% See also get_ECG_idx_from_header, ECGwrapper
%
% Author: Mariano Llamedo Soria llamedom@electron.frba.utn.edu.ar
% Version: 0.1 beta
% Last update: 14/5/2014
% Birthdate  : 21/4/2015
% Copyright 2008-2015
%
function [PPG_ABP_idx, ECG_header ] = get_PPG_ABP_idx_from_header(ECG_header)

    PPG_ABP_idx = [];

    str_12_leads_desc = { 'PPG' 'PLETH' 'ABP' 'ART' 'BP' 'PULSEWAVE' 'SPO2' };
    % add ECG patterns to be matched in ECG_header.desc
    PPG_ABP_pattern_desc = {'PLETH' 'ABP' 'ART' 'BP' 'PPG' };

    [~, ~, aux_idx ] = intersect(str_12_leads_desc, upper(strtrim(cellstr(ECG_header.desc))) );

    if( ECG_header.nsig ~= length(aux_idx) )

        PPG_ABP_idx = colvec(aux_idx);

        aux_idx = find(any(cell2mat(cellfun(@(b)(cell2mat(cellfun(@(a)(~isempty(strfind(a, b))), rowvec(upper(cellstr(ECG_header.desc))), 'UniformOutput', false))), colvec(PPG_ABP_pattern_desc), 'UniformOutput', false)),1));

        if( isempty(aux_idx) && isempty(PPG_ABP_idx) )
            if( isempty(PPG_ABP_idx) )
                cprintf('[1,0.5,0]', disp_option_enumeration('Could not find any PPG/ABP signal, check the lead description of the recording:', cellstr(ECG_header.desc) ) );
                fprintf(1, '\n')
            end
        else
            PPG_ABP_idx = unique([PPG_ABP_idx; colvec(aux_idx)]);
            Not_ECG_idx = setdiff(1:ECG_header.nsig, PPG_ABP_idx);
            if( ~isempty(Not_ECG_idx) )
%                 warning('get_ECG_idx_from_header:SignalsDiscarded', disp_option_enumeration('Some signal/s present are not ECG:', cellstr(ECG_header.desc(Not_ECG_idx,:)) ))
            end
        end

    else
        % all leads are standard ECG leads
        PPG_ABP_idx = 1:ECG_header.nsig;
    end

    if(length(PPG_ABP_idx) ~= ECG_header.nsig && nargout > 1)
       %trim the heasig if needed

        ECG_header = trim_ECG_header(ECG_header, PPG_ABP_idx);

    end


function chooseBestModels_HN_OldWithExp(pathExperimentsBinary,pathExperimentsTime,nExp,fSetNames,nameOutcomes,metric,maxOrder)
% -------------------------------------------------------------------------
% function chooseBestModels_HN(pathWORK,nExp,fSetName,nameOutcomes,maxOrder)
% -------------------------------------------------------------------------
% DESCRIPTION:
% This function requires user input to choose the set types and model orders
% providing the best parsimonious models for all outcomes analyzed in the
% HN study. See ref.[1] for more details.
% -------------------------------------------------------------------------
% REFERENCE:
% [1] Vallieres, M. et al. (2015). FDG-PET/CT radiomics models for the
%     early prediction of different tumour outcomes in head and neck cancer.
%     The Journal of Nuclear Medicine, aa(bb), xxx-yyy.
%     doi:
% -------------------------------------------------------------------------
% INPUTS:
% 1. pathExperiments: Full path to the directory containing all experiments.
%                     --> Ex: '/myProject/WORKSPACE/CV-BASED_RESULTS'
% 2. nExp: Numerical value specifying the number of experiments to analyze.
%          --> Ex: 10
% 3. fSetName: Cell of strings specifying the name of the type of feature
%              set analyzed.
%              --> Ex: {'PET','CT','SEPARATE','FUSED'}
% 4. nameOutcomes: Cell of strings specifying the outcome names to analyze.
%                  --> Ex: {'Failure','Locoregional','Distant','Death'}
% 5. maxOrder: Integer specifying the maximal multivariable model order.
%              --> Ex: 10
% -------------------------------------------------------------------------
% OUTPUTS: Final prediction models saved in a folder named 'FINAL_MODELS/nameOutcome/fSetName'
%          in the given experiment folder.
% -------------------------------------------------------------------------
% AUTHOR(S): Martin Vallieres <mart.vallieres@gmail.com>
% -------------------------------------------------------------------------
% HISTORY:
% - Creation: March 2016
%--------------------------------------------------------------------------
% STATEMENT:
% This file is part of <https://github.com/mvallieres/radiomics/>,
% a package providing MATLAB programming tools for radiomics analysis.
% --> Copyright (C) 2015  Martin Vallieres
%
%    This package 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.
%
%    This package 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 this package.  If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------

startpath = pwd;
cd(pathExperimentsBinary)
nOutcomes = length(nameOutcomes);
nType = length(fSetNames);

fprintf('\n')
for exp = 1:nExp
    cd(pathExperimentsTime), pathExperimentTime = fullfile(pathExperimentsTime,['Experiment',num2str(exp)]);
    cd(pathExperimentTime), mkdir('FINAL_MODELS'), cd('FINAL_MODELS'), pathFinalModelsTime = pwd;
    cd(pathExperimentsBinary), pathExperimentBinary = fullfile(pathExperimentsBinary,['Experiment',num2str(exp)]);
    cd(pathExperimentBinary), mkdir('FINAL_MODELS'), cd('FINAL_MODELS'), pathFinalModelsBinary = pwd;
    for o = 1:nOutcomes
        cd(pathFinalModelsTime), mkdir(nameOutcomes{o}), cd(fullfile(pathFinalModelsTime,nameOutcomes{o})), pathOutcomeTime = pwd;
        cd(pathFinalModelsBinary), mkdir(nameOutcomes{o}), cd(fullfile(pathFinalModelsBinary,nameOutcomes{o})), pathOutcomeBinary = pwd;
        plotPredictionResults_HN(fullfile(pathExperimentBinary,'RESULTS'),nameOutcomes{o},fSetNames,metric,maxOrder)
        fprintf('\n======== DISPLAYING PREDICTION RESULTS FOR "EXPERIMENT %u", "%s" OUTCOME, "%s" METRIC  ========\n',exp,nameOutcomes{o},metric)
        for f = 1:nType
            cd(pathOutcomeTime), mkdir(fSetNames{f}), cd(fullfile(pathOutcomeTime,fSetNames{f})), pathFinalTime = pwd;
            cd(pathOutcomeBinary), mkdir(fSetNames{f}), cd(fullfile(pathOutcomeBinary,fSetNames{f})), pathFinalBinary = pwd;
            while 1
                order = input(['Which model order of the ',fSetNames{f},' feature set provides the best parsimonious model? \n' ...
                               '--> Type a number between 1 to ',num2str(maxOrder),' and press ENTER \n' ...
                               'ANSWER: ']);
                fprintf('\n')
                if isnumeric(order) && order <= 10 && order >= 1
                    break
                end
            end
            cd(fullfile(pathExperimentBinary,'RESULTS'))
            results = load(['RESULTS_',fSetNames{f},'_',nameOutcomes{o}]); results = struct2cell(results); results = results{1};
            finalModel = results.(['Order',num2str(order)]);
            finalModel.Order = order;
            finalModel.outcome = nameOutcomes{o};
            cd(pathFinalBinary), save('finalModel','finalModel')
            cd(pathFinalTime), save('finalModel','finalModel')
        end
        close all
    end
end

cd(startpath)
end


%% Copyright (C) 2016-2019, 2022 Colin B. Macdonald
%% Copyright (C) 2022 Alex Vong
%%
%% This file is part of OctSymPy.
%%
%% OctSymPy 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.
%%
%% This software 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 this software; see the file COPYING.
%% If not, see <http://www.gnu.org/licenses/>.

%% -*- texinfo -*-
%% @defun  assert_have_python_and_sympy (pyexec)
%% @defunx assert_have_python_and_sympy (pyexec, verbose)
%% Check that Python and SymPy are installed and working.
%%
%% @seealso{sympref}
%% @end defun

function assert_have_python_and_sympy (pyexec, verbose)

  minsympyver = '1.4';

  if (nargin < 2)
    verbose = false;
  end

  if (verbose)
    disp ('')
    disp ('Symbolic package diagnostics')
    disp ('============================')
    disp ('')
    disp ('Python and SymPy are needed for most features of the Symbolic package.')
    disp ('')
    fprintf ('The Python interpreter is currently: "%s".\n', pyexec)
    disp ('')
    disp ('Computers may have more than one Python interpreter installed.  If you')
    disp ('need to, you can select a different one using the PYTHON environment')
    disp ('variable (see "help sympref").  For example, to use Python 3, try')
    disp ('    setenv PYTHON python3')
    disp ('    sympref reset')
    disp ('')
    fprintf ('Attempting to run %s -c "print(\\"Python says hello\\")"\n\n', pyexec);
  end

  [status, output] = system ([pyexec ' -c "print(\"Python says hello\")"']);
  if (verbose)
    status
    output
  end

  if ( (status ~= 0) || (~ strcmp(strtrim(output), 'Python says hello')) )
    if (~ verbose)
      error ('OctSymPy:nopython', ...
             ['Cannot run the Python executable "%s"\n' ...
              '    Try "sympref diagnose" for more information.'], ...
             pyexec)
    end
    disp ('')
    disp ('Unfortunately, that command failed!')
    disp ('We expected to see "status = 0" and "output = Python says hello".')
    disp ('')
    disp ('  * Is there an error message above?')
    disp ('')
    disp ('  * Do you have Python installed?')
    disp ('')
    disp ('  * Please try using "setenv" as described above.')
    disp ('')
    disp ('  * Most systems search the PATH environment when looking for commands.')
    disp ('    Your path seems to be:')
    disp ('')
    disp (getenv ('PATH'))

    # if (ispc () && (~isunix ()))
    #   disp ('')
    #   disp ('  * Did you install the Symbolic bundle for Windows that includes Python?')
    #   disp ('    Please refer to the installation notes for Windows users at')
    #   disp ('    <https://github.com/cbm755/octsympy/wiki/Notes-on-Windows-installation>')
    # end
    return
  end

  if (verbose)
    disp ('Good, Python ran correctly.')
    disp ('')
    disp ('')
    disp ('Python version')
    disp ('--------------')
    disp ('')
    disp ('Let''s check what version of Python we are calling...')
    disp ('')
    fprintf ('Attempting to run %s -c "import sys; print(sys.version)"\n', pyexec);
    [status, output] = system ([pyexec ' -c "import sys; print(sys.version)"']);
    status
    output
    fprintf ('Running %s -c "import sys; print(sys.executable)"\n', pyexec);
    [status, output] = system ([pyexec ' -c "import sys; print(sys.executable)"']);
    output
    fprintf ('Checking if %s is running in a Cygwin-like POSIX environment...', pyexec);
    if python_env_is_cygwin_like (pyexec)
      fprintf (' yes\n\n');
    else
      fprintf (' no\n\n');
    end
    disp ('');
    show_system_info ();
  end

  if (verbose)
    disp ('')
    disp ('SymPy Python Library')
    disp ('--------------------')
    disp ('')
    disp ('SymPy is a Python library used by Symbolic for almost all features.')
    disp ('')
    fprintf ('Attempting to run %s -c "import sympy; print(sympy.__version__)"\n\n', pyexec);
  end

  [status, output] = system([pyexec ' -c "import sympy; print(sympy.__version__)"']);
  if (verbose)
    status
    output
  end

  if (status ~= 0)
    if (~ verbose)
      error ('OctSymPy:nosympy', ...
            ['Python cannot import SymPy: have you installed SymPy?\n' ...
             '    Try "sympref diagnose" for more information.'])
    end
    disp ('')
    disp ('Unfortunately status was non-zero: probably Python cannot import sympy.')
    disp ('')
    disp ('  * Is there an error message above?')
    disp ('')
    disp ('  * Do you have SymPy installed?  If not, please try to install it and')
    disp ('    try again.')
    disp ('')
    disp ('  * If you do have SymPy installed, maybe it''s installed for a different')
    disp ('    Python interpreter than the one we found?  Please try "setenv" as')
    disp ('    described above to change your python interpreter.')
    return
  end

  spver = strtrim(output);

  if (verbose)
    fprintf ('SymPy must be at least version %s; you have version %s.\n', ...
             minsympyver, spver);
  end

  if (~ exist ('OCTAVE_VERSION', 'builtin'))
    % no compare_versions on matlab, just assume its ok (!)
    if (verbose)
      disp ('We cannot easily compare versions on your system: please verify the above.')
    end
  else
    if (compare_versions (spver, minsympyver, '<'))
      if (~ verbose)
        error('OctSymPy:oldsympy', ...
              ['SymPy version %s found but is too old (%s required)\n' ...
               '    Try "sympref diagnose" for more information.'], ...
              spver, minsympyver)
      end
      disp ('**** Your SymPy is too old! ****')
      disp ('Installed newer version already?  Perhaps it was for a different Python?')
      disp ('Try "setenv" as described above to change your python interpreter.')
      return
    end
  end

  if (verbose)
    disp ('')
    disp ('Good, a working version of SymPy is installed.')
    disp ('')
    disp ('')
    disp ('Python XML Parsing and DOM Support')
    disp ('----------------------------------')
    disp ('')
    disp ('The XML DOM library is used by Symbolic for passing values to and from Python.')
    disp ('Some older versions of Python formatted XML output differently.  As long as you')
    disp ('have any reasonably recent version of Python, this should pass.')
    disp ('')
  end

  script = ['import xml.dom.minidom as minidom; ' ...
            'doc = minidom.parseString(\"<item>value</item>\"); ' ...
            'print(doc.toprettyxml(indent=\"\"))'];

  if (verbose)
    fprintf ('Attempting to run %s -c "%s"\n\n', pyexec, script);
  end

  if (ispc () && (~isunix ()))
    script = strrep (script, '<', '^<');
    script = strrep (script, '>', '^>');
  end

  [status, output] = system([pyexec ' -c "' script '"']);
  if (verbose)
    status
    output
  end

  if (status ~= 0)
    if (~ verbose)
      error ('OctSymPy:noxmldom', ...
             ['Something wrong, perhaps with XML DOM: is this an unusual Python setup?\n' ...
              '    Try "sympref diagnose" for more information.'])
    end
    disp ('')
    disp ('Unfortunately status was non-zero: perhaps Python cannot import xml.dom?')
    disp ('')
    disp ('  * Is there an error message above?')
    disp ('')
    disp ('  * Are you using an unusual Python installation?  If not, please try to')
    disp ('    reinstall it and try again.')
    return
  end

  xmlout = strtrim (output);

  if (isempty (strfind (xmlout, '<item>value</item>')))
    if (~ verbose)
      error ('OctSymPy:oldxmldom', ...
             ['Python XML output is not compatible, probably an old version of Python?\n' ...
              '    Try "sympref diagnose" for more information.'])
    end
    disp ('**** Your Python is too old! ****')
    disp ('')
    disp ('The XML output shown above must have "<item>value</item>" all on one line.')
    disp ('If your Python interpreter is an older release, please try upgrading to a more')
    disp ('recent version.  Symbolic should work with Python 2 (version 2.7.3 or newer)')
    disp ('and Python 3 (version 3.2.3 or newer).')
    return
  end

  if (verbose)
    fprintf ('\nYour kit looks good for running the Symbolic package.  Happy hacking!\n\n')
  end
end


function y = cvxaff( x )
global cvx___
y = subsref( cvx___.problems( x.problem_ ).duals, x.name_ );

% Copyright 2005-2016 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


%% This function will generate the PDE function based on calculation result of the symbolic expression.
% This file has been modified to perform the parallel computing.
% Last Update: 2019/06/20
% Coded By: K

function Generate_PDE_RHS(Sindy_PDEs,Vars,name)
f_x=Sindy_PDEs;
matlabFunction(f_x,'File',name,'Optimize',true,'Vars',{Vars});


function sites = dbget_closest_sites(lon, lat, distkm, sitesdb, maxsta, snum, enum, chanmatch)
%DBGET_CLOSEST_SITES Get closest sites from an Antelop database to a given [lon, lat]
% sites = DBGET_CLOSEST_SITES(lon, lat, distkm, sitesdb, maxsta, snum, enum, chanmatch)
% load sites within distkm km of a given (LON, LAT)
% from site database sitesdb
%
% The sites structure returned has the followed fields:
%	channeltag - net.sta.loc.chan a ChannelTag object
%	longitude	- sites longitude
%	latitude	- sites latitude
%	elev	- sites elevation
%	distance	- distance (in km) from input (LON, LAT)
%
% Example: Get sites within 100km of (-150.0, 60.5) that were
% operational in 1990:
% sites = DBGET_CLOSEST_SITES(-150.0, 60.5, 100.0, '/avort/oprun/dbmaster/master_stations', 10, datenum(1990,1,1), datenum(1991,1,1));

% AUTHOR: Glenn Thompson, UAF-GI
% $Date: $
% $Revision: -1 $
debug.printfunctionstack('>')
warning(sprintf('%s assumes every station has a calibration - those without are missed',mfilename))
if ~exist('maxsta', 'var')
	maxsta = 999;
end
% if ~exist(sprintf('%s.site',sitesdb))
%     sitesdb = input('Please enter sites database path', 's')
% end
debug.print_debug(1,sprintf('sites db is %s',sitesdb))
dbptr = dbopen(sitesdb, 'r');

% Filter the site table
dbptr_site = dblookup_table(dbptr, 'site');
nrecs = dbquery(dbptr_site, 'dbRECORD_COUNT');
debug.print_debug(2,sprintf('Site table has %d records', nrecs));
dbptr_site = dbsubset(dbptr_site, sprintf('distance(lon, lat, %.4f, %.4f)<%.4f',lon,lat,km2deg(distkm)));
nrecs = dbquery(dbptr_site, 'dbRECORD_COUNT');
debug.print_debug(2,sprintf('After distance subset to lat %f and lon %f: %d records', lat, lon, nrecs));

if ~exist('snum', 'var')
    % No start time given, so assume we just want sites that exist today.
    % Remove any sites that have been decommissioned
    dbptr_site = dbsubset(dbptr_site, sprintf('offdate == NULL'));
else
    % Remove any sites that were decommissioned before the start time
    debug.print_debug(2,sprintf('offdate == NULL || offdate > %s',datenum2julday(snum)));
    dbptr_site = dbsubset(dbptr_site, sprintf('offdate == NULL || offdate > %s',datenum2julday(snum)));
end
% Remove any sites that were installed after the end time (this may remove
% some sites that exist today)
if exist('enum', 'var')
    debug.print_debug(2, sprintf('ondate  < %s',datenum2julday(enum)));
    dbptr_site = dbsubset(dbptr_site, sprintf('ondate  < %s',datenum2julday(enum)));
end
nrecs = dbquery(dbptr_site, 'dbRECORD_COUNT');
debug.print_debug(2,sprintf('After time subset: %d records', nrecs));
if nrecs==0
sites=struct();
return
end
dbgetv(dbptr_site, 'sta')

% Filter the sitechan table
dbptr_sitechan = dblookup_table(dbptr, 'sitechan');
nrecs = dbquery(dbptr_sitechan, 'dbRECORD_COUNT');
debug.print_debug(2,sprintf('sitechan has %d records', nrecs));

if exist('chanmatch','var')
    dbptr_sitechan = dbsubset(dbptr_sitechan, chanmatch);
    nrecs = dbquery(dbptr_sitechan, 'dbRECORD_COUNT');
    debug.print_debug(2,sprintf('After chan subset: %d records', nrecs));
end

if ~exist('snum', 'var')
    % No start time given, so assume we just want sites that exist today.
    % Remove any sites that have been decommissioned
    dbptr_sitechan = dbsubset(dbptr_sitechan, sprintf('offdate == NULL'));
else
    % Remove any sites that were decommissioned before the start time
    debug.print_debug(2,sprintf('offdate == NULL || offdate > %s',datenum2julday(snum)));
    dbptr_sitechan = dbsubset(dbptr_sitechan, sprintf('offdate == NULL || offdate > %s',datenum2julday(snum)));
end
% Remove any sites that were installed after the end time (this may remove
% some sites that exist today)
if exist('enum', 'var')
    debug.print_debug(2,sprintf('ondate  < %s',datenum2julday(enum)));
    dbptr_sitechan = dbsubset(dbptr_sitechan, sprintf('ondate  < %s',datenum2julday(enum)));
end
nrecs = dbquery(dbptr_sitechan, 'dbRECORD_COUNT');
debug.print_debug(2,sprintf('After time subset: %d records', nrecs));
dbgetv(dbptr_sitechan, 'sta')

% Join site and sitechan
dbptr_sitechan = dbjoin(dbptr_site, dbptr_sitechan);
nrecs = dbquery(dbptr_sitechan, 'dbRECORD_COUNT');
debug.print_debug(2,sprintf('After join site-sitechan %d records', nrecs));
dbgetv(dbptr_sitechan, 'sta')

% Read snetsta to get network code
dbptr_snetsta = dblookup_table(dbptr, 'snetsta');
nrecs = dbquery(dbptr_snetsta, 'dbRECORD_COUNT');
debug.print_debug(2,sprintf('snetsta has %d records', nrecs));
dbptr_snetsta = dbjoin(dbptr_sitechan, dbptr_snetsta);
nrecs = dbquery(dbptr_snetsta, 'dbRECORD_COUNT');
debug.print_debug(2,sprintf('After join site-sitechan-snetsta: %d records', nrecs));
snet = dbgetv(dbptr_snetsta, 'snet');
sta = dbgetv(dbptr_snetsta, 'sta');
stanetmap = containers.Map();
for c=1:numel(sta)
    stanetmap(sta{c}) = snet{c};
end

% If there is a calibration table, get the calib value and units
dbptr_calibration = dblookup_table(dbptr, 'calibration');
nrecs = dbquery(dbptr_calibration, 'dbRECORD_COUNT');
debug.print_debug(2,sprintf('calibration has %d records', nrecs));
%dbptr_calibration = dbjoin(dbptr_sitechan, dbptr_calibration,
%{'sta';'chan'}, {'sta';'chan'}); % danger with this is no subset on ondate/offdate
dbptr_calibration = dbjoin(dbptr_sitechan, dbptr_calibration);
dbptr_calibration = dbsubset(dbptr_calibration, 'sitechan.sta == calibration.sta && sitechan.chan == calibration.chan');
nrecs = dbquery(dbptr_calibration, 'dbRECORD_COUNT');
debug.print_debug(2,sprintf('After join site-sitechan-calibration: %d records', nrecs));

% Read data from final view
if nrecs == 0
    sites = [];
    return
end
% net = dbgetv(db4, 'snet');
% if ~iscell(net)
%     net = {net};
% end

latitude = dbgetv(dbptr_calibration, 'lat');
longitude = dbgetv(dbptr_calibration, 'lon');
elev = dbgetv(dbptr_calibration, 'elev');
staname = dbgetv(dbptr_calibration, 'sta');
if ~iscell(staname)
	staname = {staname};
end
channame = dbgetv(dbptr_calibration, 'chan');
if ~iscell(channame)
	channame = {channame};
end
ondate = dbgetv(dbptr_calibration, 'sitechan.ondate');
offdate = dbgetv(dbptr_calibration, 'sitechan.offdate');
calib = dbgetv(dbptr_calibration, 'calibration.calib');
units = dbgetv(dbptr_calibration, 'calibration.units');
dbclose(dbptr);

% Reformat data into sites return structure
numsites = numel(latitude);
for c=1:numsites
    yyyy = floor(ondate(c)/1000);
    if yyyy>1900
        jjj = ondate(c)-yyyy*1000;
        ondnum(c) = datenum(yyyy,1,jjj);
    else
        ondnum(c)=-Inf;
    end
end

for c=1:numsites
    yyyy = floor(offdate(c)/1000);
    if yyyy>1900
        jjj = offdate(c)-yyyy*1000;
        offdnum(c) = datenum(yyyy,1,jjj);
    else
       offdnum(c) = Inf;
    end
end

for c=1:numsites
    stadist(c) = deg2km(distance(lat, lon, latitude(c), longitude(c)));
end

% order the sites by distance
[y,i]=sort(stadist);
c=1;
while ((c<=numsites) && (stadist(i(c)) < distkm))
	%sites(c).name = staname{i(c)};
	%sites(c).channel = channame{i(c)};
	%sites(c).scnl = scnlobject(sites(c).name, sites(c).channel, net{i(c)});
    sta = staname{i(c)};
    chan = channame{i(c)};
    net = stanetmap(sta);
    sites(c).channeltag = ChannelTag(net, sta, '', chan);
    sites(c).string = string(sites(c).channeltag);
	sites(c).longitude = longitude(i(c));
	sites(c).latitude = latitude(i(c));
	sites(c).elev = elev(i(c));
	sites(c).distance = stadist(i(c));
    sites(c).ondnum = ondnum(i(c));
    sites(c).offdnum = offdnum(i(c));
    sites(c).calib = calib(i(c));
    sites(c).units = units(i(c));
	c = c + 1;
end

% remove any duplicate sites
[~,j]=unique({sites.string});
sites = sites(j);

% limit the number of sites
numsites = min([maxsta numel(sites)]);
sites = sites(1:numsites);

debug.printfunctionstack('<')


function [yes] = isfilextension(fname, extension)
% See also CHECK_FILE_EXTENSION, CLEAR_FILE_EXTENSION.
%
% File:      isfilextension.m
% Author:    Ioannis Filippidis, jfilippidis@gmail.com
% Date:      2012.06.22
% Language:  MATLAB R2012a
% Purpose:   check if file has the desired extension
% Copyright: Ioannis Filippidis, 2012-

% dot in extension ?
if ~strcmp(extension(1), '.')
    extension = ['.', extension];
end

[~, ~, ext] = fileparts(fname);

% extension = unwanted ?
if strcmp(ext, extension)
    yes = 1;
else
    yes = 0;
end


classdef DesignImagVariable < handle

   properties (Access = public)
      value
      valueOld
      valueOldOld
   end

   properties (GetAccess = public, SetAccess = private)
      xLength
   end

   properties (Access = private)

   end

   methods (Access = public)

       function obj = DesignImagVariable(cParams)
          obj.init(cParams)
       end

       function update(obj)
           obj.valueOldOld = obj.valueOld;
           obj.valueOld = obj.value;
       end

   end

   methods (Access = private)

       function init(obj,cParams)
          obj.xLength = cParams.xLength;
          obj.valueOldOld = zeros(obj.xLength,1);
          obj.valueOld    = zeros(obj.xLength,1);
          obj.value       = zeros(obj.xLength,1);
       end

   end

end