classdef PowerNetChargeRateTermCondition < AbstractEventTerminationCondition
    %PowerNetChargeRateTermCondition Summary of this class goes here
    %   Detailed explanation goes here

    properties
        netChargeRate(1,1) double = 0; %km
        initialStateLogEntry LaunchVehicleStateLogEntry
    end

    methods
        function obj = PowerNetChargeRateTermCondition(netChargeRate)
            obj.netChargeRate = netChargeRate;
        end

        function evtTermCondFcnHndl = getEventTermCondFuncHandle(obj)
            evtTermCondFcnHndl = @(t,y) obj.eventTermCond(t,y);
        end

        function initTermCondition(obj, initialStateLogEntry)
            obj.initialStateLogEntry = initialStateLogEntry;
        end

        function name = getName(obj)
            name = sprintf('Power Net Charge Rate (%.3f EC)', obj.netChargeRate);
        end

        function tf = shouldBeReinitOnRestart(obj)
            tf = true;
        end

        function params = getTermCondUiStruct(obj)
            params = struct();

            params.paramName = 'Net Charge Rate';
            params.paramUnit = 'EC/s';
            params.useParam = 'on';
            params.useStages = 'off';
            params.useTanks = 'off';
            params.useEngines = 'off';
            params.useStopwatches = 'off';

            params.value = obj.netChargeRate;
            params.refStage = LaunchVehicleStage.empty(1,0);
            params.refTank = LaunchVehicleEngine.empty(1,0);
            params.refEngine = LaunchVehicleEngine.empty(1,0);
            params.refStopwatch = LaunchVehicleStopwatch.empty(1,0);
        end

        function optVar = getNewOptVar(obj)
            optVar = NetChargeRateOptimizationVariable(obj);
        end

        function optVar = getExistingOptVar(obj)
            optVar = obj.optVar;
        end

        function tf = usesStage(obj, stage)
            tf = false;
        end

        function tf = usesEngine(obj, engine)
            tf = false;
        end

        function tf = usesTank(obj, tank)
            tf = false;
        end

        function tf = usesEngineToTankConn(obj, engineToTank)
            tf = false;
        end

        function tf = usesStopwatch(obj, stopwatch)
            tf = false;
        end
    end

    methods(Static)
        function termCond = getTermCondForParams(paramValue, stage, tank, engine, stopwatch)
            termCond = PowerNetChargeRateTermCondition(paramValue);
        end
    end

    methods(Access=private)
        function [value,isterminal,direction] = eventTermCond(obj, t,y)
            initStateLogEntry = obj.initialStateLogEntry;

            powerStorageStates = initStateLogEntry.getAllActivePwrStorageStates();

            numTankStates = initStateLogEntry.getNumActiveTankStates();
            numPwrStorageStates = initStateLogEntry.getNumActivePwrStorageStates();
            [~, ~, ~, ~, storageSoCs] = AbstractPropagator.decomposeIntegratorTandY(t,y, numTankStates, numPwrStorageStates);

            stgStates = initStateLogEntry.stageStates;

            ut = initStateLogEntry.time;
            rVect = initStateLogEntry.position(:);
            vVect = initStateLogEntry.velocity(:);
            bodyInfo = initStateLogEntry.centralBody;

            steeringModel = initStateLogEntry.steeringModel;

            storageRates = LaunchVehicleStateLogEntry.getStorageChargeRatesDueToSourcesSinks(storageSoCs, powerStorageStates, stgStates, ut, rVect, vVect, bodyInfo, steeringModel);
            actualNetStorageRate = sum(storageRates);

            value = actualNetStorageRate - obj.netChargeRate;
            isterminal = 1;
            direction = 0;
        end
    end
end


function [dat] =  test(algo,dat,lossType)
%
%               [res]=test(algo,data,loss)
%   An algorihm algo is trained on the training set data. If a loss
%   function is supplied, it will be calculated.
%   It returns a data object containing the results.
%   If no loss function is supplied, the data object will contain the loss
%   on the training set. If not, it usually contain the label estimates in
%   the X part and the true labels in the Y part of the data object.
%
%   It is also possible to call test(algo), where the emtpy data set is passed
%   into the algorithm to test it. This is useful for methods that generate their
%   own data.
%
%   Note:
%               test(algo) <=> test(algo,[]).

%% Programming note:
% It is used to call testing.m function which doesn't include loss
% function calculations in a child object

if nargin==1
    dat=[];% <--- data is optional
end;

if nargin<3
    lossType=[];
end;

if iscell(dat)
    dat=group(dat);
end;
%%<<----test data---->>
if ~isempty(dat)
    if ~am_i_data(dat)
        dat=test(dat); %% <--- i.e generate data
    end
end

%%%% SGE support (note sightly different behaviour from algorithm/train)
if isdeferred(algo)
	if submitted(algo.deferred)
		[algo jobfailed] = waitcollect(algo);
		if jobfailed, return, end
	else
		dat.deferred = qsub(algo.deferred, max(nargout,1), mfilename, algo, dat, lossType);
		return
	end
end
if ~isempty(dat)
if isdeferred(dat)
	[dat jobfailed] = waitcollect(dat);
	if jobfailed, return, end
end
end
%%%%

e=struct(dat);
%%<<------ if there are multiple datasets as input ---->>
if isa(dat,'group')  & strcmp(e.group,'separate')
  dat=e.child; % dat seen as @algorithm object => so it is not possible to access child directly
  dat=make_cell(dat);
  res=[];
  for i=1:length(dat)
      [r]=test(algo,dat{i},lossType);
      res{i}=r;
  end
  dat=group(res);  %% <--- return data/res as set of group
else
    [dat]=testing(algo,dat);
    if ~isempty(lossType)
      if isa(lossType,'loss')
	dat=train(lossType,dat);
      else
	dat=loss(dat,lossType);
      end
    end;
    if iscell(dat)
        dat=group(dat);
    end;  %%  <--- return data/res as set of group
end


function process_scores_Tex(conf, scores, nr)

fprintf('Writing results to Tex summary...\n');

valid_id = [2 3 4 5 6 7 8 9 11];
fprintf('\n');

    for j = 1:length(conf.desc)
        if sum(valid_id==j)==0
            continue;
        end;
        fprintf('& \\multicolumn{2}{|c|}{%s}', conf.desc{j});
    end
    fprintf('\\\\\n');

fprintf('image');
    for j = 1:length(conf.desc)
        if sum(valid_id==j)==0
            continue;
        end;
        fprintf('& PSNR & Time');
    end
    fprintf('\\\\\n');

for i =1:nr
    [p, f, x] = fileparts(conf.filenames{i});
    fprintf('%s',f);
    for j = 1:length(conf.desc)
        if sum(valid_id==j)==0
            continue;
        end;

        fprintf(' & %.1f & %.1f', scores(i,j), conf.countedtime(j-1,i));
    end
    fprintf('\\\\\n');
end

fprintf('average');
for j = 1:11
    if sum(valid_id==j)==0
       continue;
    end;

    fprintf(' & %.2f & %.2f', mean(scores(:,j)), mean(conf.countedtime(j-1,:)));
end
fprintf('\\\\\n\n\n');


function spp_demo()
clear mex;

spp_model_file = '.\data\spp_model\VOC2007\spp_model.mat';
if ~exist(spp_model_file, 'file')
  error('%s not exist ! \n', spp_model_file);
end
try
    load(spp_model_file);
catch err
    fprintf('load spp_model_file : %s\n', err.message);
end
caffe_net_file     = fullfile(pwd, 'data\cnn_model\Zeiler_conv5\Zeiler_conv5');
caffe_net_def_file = fullfile(pwd, 'data\cnn_model\Zeiler_conv5\Zeiler_spm_scale224_test_conv5.prototxt');

use_gpu = true;
gpu_id = 1;
if use_gpu
    gpuDevice(gpu_id);
end

caffe('init', caffe_net_def_file, caffe_net_file);
caffe('set_phase_test');
if use_gpu
    spp_model.cnn.layers = spp_layers_in_gpu(spp_model.cnn.layers);
    caffe('set_mode_gpu');
else
    caffe('set_mode_cpu');
end

spm_im_size = [480 576 688 874 1200];
% spm_im_size = [ 688 ];

im = imread('.\datasets\VOCdevkit2007\VOC2007\JPEGImages\000015.jpg');

dets = spp_detect(im, spp_model, spm_im_size, use_gpu);

classes = spp_model.classes;
boxes = cell(length(classes), 1);
thres = -0.5;
for i = 1:length(boxes)
    I = dets{i}(:, 5) >= thres;
    boxes{i} = dets{i}(I, :);
end
showboxes_new(im, boxes, classes);

caffe('release');

if use_gpu
    gpuDevice([]);
end


function [doseHandle,cMap,window] = matRad_plotDoseSlice3D(axesHandle,ct,doseCube,plane,slice,threshold,alpha,cMap,window)
% matRad function that generates a dose plot of a selected slice in 3D view
%
% call
%   [doseHandle,cMap,window] = matRad_plotDose3DSlice(axesHandle, doseCube,plane,slice,threshold)
%   [doseHandle,cMap,window] = matRad_plotDose3DSlice(axesHandle, doseCube,plane,slice,threshold,alpha)
%   [doseHandle,cMap,window] = matRad_plotDose3DSlice(axesHandle, doseCube,plane,slice,threshold,cMap)
%   [doseHandle,cMap,window] = matRad_plotDose3DSlice(axesHandle, doseCube,plane,slice,threshold,window)
%   [doseHandle,cMap,window] = matRad_plotDose3DSlice(axesHandle, doseCube,plane,slice,threshold,alpha,cMap)
%   [doseHandle,cMap,window] = matRad_plotDose3DSlice(axesHandle, doseCube,plane,slice,threshold,alpha,window)
%   [doseHandle,cMap,window] = matRad_plotDose3DSlice(axesHandle, doseCube,plane,slice,threshold,cMap,window)
%   [doseHandle,cMap,window] = matRad_plotDose3DSlice(axesHandle, doseCube,plane,slice,threshold,alpha,cMap,window)
%
% input
%   axesHandle  handle to axes the slice should be displayed in
%   ct          matRad CT struct which contains resolution
%   doseCube    3D array of the dose to select the slice from
%   plane       plane view (coronal=1,sagittal=2,axial=3)
%   slice       slice in the selected plane of the 3D cube
%   threshold   threshold above which the dose shall be displayed
%               for negative values (i.e. difference maps), also the values
%               smaller than the negative threshold will be displayed
%               if empty, no threshold will be applied
%   alpha       optional argument defining the alpha value, default is 0.6.
%               To use the default when providing a custom culormap, put in
%               an empty array by [].
%   cMap        optional argument defining the colormap, default is jet
%               if you want to use the default map with the window argument
%               you can use an empty array []
%   window      optional argument defining the displayed range. default is
%               [min(doseCube(:)) max(doseCube(:))]
%
% output
%   doseHandle: handle of the plotted dose axes
%   cMap        used colormap (same as input if set)
%   window      used window (same as input if set)
%
% References
%   -
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Copyright 2015 the matRad development team.
%
% This file is part of the matRad project. It is subject to the license
% terms in the LICENSE file found in the top-level directory of this
% distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part
% of the matRad project, including this file, may be copied, modified,
% propagated, or distributed except according to the terms contained in the
% LICENSE file.
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

matRad_cfg = MatRad_Config.instance();

%Use default colormap?
if nargin < 8 || isempty(cMap)
    cMap = jet(64);
end
if nargin < 7 || isempty(alpha)
    alpha = 0.6;
end
if nargin < 9 || isempty(window)
    window = [min(doseCube(:)) max(doseCube(:))];
end

cMapScale = size(cMap,1) - 1;
maxDose = max(doseCube(:));

%Create the coordinates
coords{1} = ct.resolution.x * (1:ct.cubeDim(2));
coords{2} = ct.resolution.y * (1:ct.cubeDim(1));
coords{3} = ct.resolution.z * (1:ct.cubeDim(3));

if plane == 1  % Coronal plane
    [xMesh,zMesh] = meshgrid(coords{2},coords{3});
    yMesh = slice*ct.resolution.x*ones(size(xMesh));
    %dose_slice = uint8(cMapScale*(squeeze(doseCube(slice,:,:)) - window(1))/(window(2)-window(1)));
    doseSlice = permute(squeeze(doseCube(slice,:,:)),[2 1]);
elseif plane == 2 % sagittal plane
    [yMesh,zMesh] = meshgrid(coords{1},coords{3});
    xMesh = slice*ct.resolution.y*ones(size(yMesh));
    %dose_slice = uint8(cMapScale*(squeeze(doseCube(:,slice,:)) - window(1))/(window(2)-window(1)));
    dose_slice = permute(squeeze(doseCube(:,slice,:)),[2 1]);
elseif plane == 3 % Axial plane
    [xMesh,yMesh] = meshgrid(coords{2},coords{1});
    zMesh = slice*ct.resolution.z*ones(size(xMesh));
    %dose_slice = uint8(cMapScale*(squeeze(doseCube(:,:,slice)) - window(1))/(window(2)-window(1)));
    dose_slice = squeeze(doseCube(:,:,slice));
end

if ~isempty(threshold)
    dose_mask = alpha * (dose_slice < window(2) & dose_slice > window(1) & dose_slice > threshold*maxDose);
else
    dose_mask = alpha * (dose_slice < window(2) & dose_slice > window(1));
end

dose_slice = uint8(cMapScale* (dose_slice - window(1))/(window(2)-window(1)));

%This circumenvents a bug in Octave when the index in the image hase the maximum value of uint8
if matRad_cfg.isOctave
	dose_slice(dose_slice == 255) = 254;
end

dose_rgb = ind2rgb(dose_slice,cMap);
% slice plot with surface(...), colormapping can be done by texture
% mapping, this is why we use surface instead of slice
doseHandle = surface('XData',xMesh, 'YData',yMesh, 'ZData',zMesh,'AlphaData',dose_mask, ...
        'CData',dose_rgb, 'CDataMapping','direct', ...
        'EdgeColor','none', 'FaceColor','texturemap', 'BackFaceLighting','unlit','FaceLighting','flat','FaceAlpha','texture','Parent',axesHandle);

end


classdef unimodalComponent
% This class is obsolet since MTEX 5.9. Use the class @SO3FunRBF instead.
% Anyway the class is preserved, so that saved @ODFs can be loaded.

methods (Static = true, Hidden=true)
  function odf = loadobj(s)
    psi = s.psi;
    if isempty(psi)
      psi = SO3DeLaValleePoussinKernel;
      warning(['MTEX is not able to load the SO3Kernel of the unimodalODF, ' ...
        'because its class has been deleted. A standard kernel is used instead.'])
    end
    odf = SO3FunRBF(s.center,psi,s.weights);
  end
end

end


function [imo,rois,labels,targets] = fast_rcnn_train_get_batch(images, imdb, batch, opts)
% FAST_RCNN_GET_BATCH_TRAIN  Generates mini-batches for Fast-RCNN train

% opts.numFgRoisPerImg = 128;
% opts.numRoisPerImg = 64;
% opts.maxScale = 1000;
% opts.bgLabel = 21;
% opts.visualize = 0;
% opts.scale = 600;
% opts.interpolation = 'bicubic';
% opts.averageImage = [];
% opts.numThreads = 2;
% opts.prefetch = true;
%
% Copyright (C) 2016 Hakan Bilen.
% 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).

if isempty(images)
  imo = [] ;
  rois = [] ;
  labels = [] ;
  targets = [] ;
  return ;
end

% fetch is true if images is a list of filenames (instead of
% a cell array of images)
fetch = ischar(images{1}) ;

% prefetch is used to load images in a separate thread
prefetch = fetch & opts.prefetch ;

if prefetch
  vl_imreadjpeg(images, 'numThreads',opts.numThreads,'prefetch') ;
  imo = [] ;
  rois = [] ;
  labels = [] ;
  targets = [] ;
  return ;
end

if fetch
  ims = vl_imreadjpeg(images,'numThreads',opts.numThreads) ;
else
  ims = images ;
end

maxW = 0;
maxH = 0;

% labels = imdb.images.label(:,batch);

pboxes   = cell(1,numel(batch));
plabels  = cell(1,numel(batch));
ptargets = cell(1,numel(batch));

% get fg and bg rois
for b=1:numel(batch)
  pbox   = imdb.boxes.pbox{batch(b)};
  plabel = imdb.boxes.plabel{batch(b)};
  ptarget = imdb.boxes.ptarget{batch(b)};

  if size(pbox,2)~=4
    error('wrong box size');
  end

  % get pos boxes
  pos = find((plabel~=opts.bgLabel) & (plabel > 0)) ;
  npos = numel(pos);
  % get neg boxes
  neg = find((plabel==opts.bgLabel)) ;
  nneg = numel(neg);

    bbox = [];
    label = [];
    target = [];

    opts.numFgRoisPerImg = min(npos,opts.numFgRoisPerImg);
    nBneg = min(nneg,opts.numRoisPerImg-opts.numFgRoisPerImg);

    if npos>0
      r = randperm(npos);
      p = pos(r(1:opts.numFgRoisPerImg));
      bbox = pbox(p,:);
      label = plabel(p);
      target = ptarget(p,:);
    end
    if nneg>0
      r = randperm(nneg);

      n = neg(r(1:nBneg));
      bbox = [bbox ; pbox(n,:)];
      label = [label ; plabel(n)];
      target = [target ; ones(size(ptarget(n,:)))];
    end
  pboxes{b} = bbox;
  plabels{b} = label;
  ptargets{b} = target;
end

if isempty(pboxes)
  warning('No gt box\n');
end

labels = vertcat(plabels{:});
targets = vertcat(ptargets{:});

% rescale images and rois
rois = [];
imre = cell(1,numel(batch));
for b=1:numel(batch)
  imSize = size(ims{b});

  h = imSize(1);
  w = imSize(2);

  factor = max(opts.scale(1)/h,opts.scale(1)/w);

  if any([h*factor,w*factor]>opts.maxScale)
    factor = min(opts.maxScale/h,opts.maxScale/w);
  end

  if abs(factor-1)>1e-3
    imre{b} = imresize(ims{b},factor,'Method',opts.interpolation);
  else
    imre{b} = ims{b};
  end

  if imdb.boxes.flip(batch(b))
    im = imre{b};
    imre{b} = im(:,end:-1:1,:);
  end

  imreSize = size(imre{b});

  maxH = max(imreSize(1),maxH);
  maxW = max(imreSize(2),maxW);

  % adapt bounding boxes into new coord
  bbox = pboxes{b};
  if any(bbox(:)<=0)
    error('bbox error');
  end

  nB = size(bbox,1);
  tbbox = bbox_scale(bbox,factor,[imreSize(2) imreSize(1)]);
  if any(tbbox(:)<=0)
    error('tbbox error');
  end

  rois = [rois [b*ones(1,nB) ; tbbox' ] ];
end

imo = zeros(maxH,maxW,size(imre{1},3),numel(batch),'single');
for b=1:numel(batch)
  % subtract mean
  if ~isempty(opts.averageImage)
    imre{b} = single(bsxfun(@minus,imre{b},opts.averageImage));
  end
  sz = size(imre{b});
  imo(1:sz(1),1:sz(2),:,b) = single(imre{b});
end


%--- help for dsge/bvar_dsge ---
%
%  INTERNAL FUNCTION: intermediary file for computing key elements for dsge-var
%
%  ::
%
%    [obj,retcode] = bvar_dsge(obj,varargin)
%
%  Args:
%
%     obj (rise | dsge): model object
%     varargin : ususal dsge options. The most important of which are:
%
%       - **dsgevar_lag** [integer|{4}]: number of lags in the VAR
%       - **dsgevar_constant** [false|{true}]: flag for having a constant in
%         the VAR
%       - **dsgevar_var_regime** [false|{true}]: use the VAR in simulations.
%         Otherwise use the DSGE
%       - **dsgevar_inner_param_uncertainty** [true|{false}]: make random draws
%         for the parameters around the mode for each simulation
%
%  Returns:
%     :
%
%     - **obj** [rise|dsge]: model object
%
%  Note:
%
%     - Because the BVAR-DSGE will have fewer variables than the DSGE, in
%       simulations, the missing variables will be stored as 0+1i in time series.
%       This is true for forecast, irf and simulate
%
%


function dispScanStats(scanBinsV, volHistV, name, nameVol, planC, indexS, opt)
%Command line display of basic scan statistics
%scanBinsV is a vector of the midpoint scanBin values.
%volHistV is either a histogram of volumes or surface areas.
%LM: 14 Oct 02, JOD.
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

% ESPEZI OCT 2014 added nameVol, changed order of printed items and added dose name

ud = get(findobj('Tag', 'IVHGui'),'userdata');
scanNum = get(ud.af.handles.scan,'value');
imageType = planC{indexS.scan}(scanNum).scanInfo(1).imageType;

if strcmpi(imageType,'CT')
    units = 'HU';
elseif strcmpi(imageType,'PET')
    units = 'SUV';
else
    units = '';
end

switch lower(opt)

  case 'standardscan'
    disp('-----------------------')
    disp('')
    disp(['Structure is:  ' name])

    totalVol = sum(volHistV);
    disp(['Total volume is:  ' num2str(totalVol) ' cubic cm.'])

    disp(['Scan name is:  ' nameVol])

    meanD = sum(scanBinsV.*volHistV)/sum(volHistV);
    disp(['Mean ' imageType ' ' units ' is:  ' num2str(meanD)])

    ind = max(find([volHistV~=0]));
    maxD = scanBinsV(ind);
    disp(['Max' imageType ' ' units ' is:  ' num2str(maxD)])

    ind = min(find([volHistV~=0]));
    minD = scanBinsV(ind);
    disp(['Min ' imageType ' ' units ' is:  ' num2str(minD)])
    disp('')
    disp('-----------------------')

  case 'dshscan'

    disp('-----------------------')
    disp('')
    disp(['Structure is:  ' name])

    areaV = volHistV;  %actually areas, not volumes.
    scansV = scanBinsV;

    totalArea = sum(areaV);
    disp(['Total surface area is:  ' num2str(totalArea) ' square cm.'])

    disp(['Scan name is:  ' nameVol])

    meanD = sum(scansV.*areaV)/sum(areaV);
    disp(['Mean surface ' imageType ' ' units ' is:  ' num2str(meanD)])

    maxScan = max(scansV);
    disp(['Max ' imageType ' ' units ' is:  ' num2str(maxScan)])

    minScan = min(scansV);
    disp(['Min ' imageType ' ' units ' is:  ' num2str(minScan)])
    disp('')
    disp('-----------------------')

end


function output = callsparsecolo(interfacedata)

% Retrieve needed data
options = interfacedata.options;
F_struc = interfacedata.F_struc;
c       = interfacedata.c;
K       = interfacedata.K;
x0      = interfacedata.x0;
ub      = interfacedata.ub;
lb      = interfacedata.lb;

% Bounded variables converted to constraints
if ~isempty(ub)
    [F_struc,K] = addStructureBounds(F_struc,K,ub,lb);
end

A = -F_struc(:,2:end)';
C = F_struc(:,1);
b = -c;

if options.savedebug
    ops = options.sparsecolo;
    save sparsecolodebug K A C b
end

ops = options.sparsecolo;
ops.SDPsolver = lower(interfacedata.solver.sdpsolver.tag);
ops.SDPAoptions = options.sdpa;
ops.sedumipar = options.sedumi;
ops.sdpt3OPTIONS = options.sdpt3;
ops.sdpt3OPTIONS.printlevel = options.verbose;
ops.printlevel = options.verbose;
if options.verbose==0
    ops.SDPAoptions.print = 'no';
else
    ops.SDPAoptions.print = 'display';
end

if options.savedebug
    save sparsecolodebug K A C b ops
end

if options.showprogress;showprogress(['Calling ' interfacedata.solver.tag],options.showprogress);end
solvertime = tic;
if options.verbose==0 % Sparsecolo does not run silent
    evalc('[x,y,infoCoLO,cliqueDomain,cliqueRange,LOP] = sparseCoLO(A,b,C,K,[],ops);');
else
    [x,y,infoCoLO,cliqueDomain,cliqueRange,LOP] = sparseCoLO(A,b,C,K,[],ops);
end
solvertime = toc(solvertime);

% Create YALMIP dual variable and slack
Dual = x;
Primal = y;

switch  lower(interfacedata.solver.sdpsolver.tag)
    case 'sdpt3'
        switch infoCoLO.SDPsolver.termcode
            case 0
                problem = 0; % No problems detected
            case {-1,-5}
                problem = 5; % Lack of progress
            case {-2,-3,-4,-7}
                problem = 4; % Numerical problems
            case -6
                problem = 3; % Maximum iterations exceeded
            case -10
                problem = 7; % YALMIP sent incorrect input to solver
            case 1
                problem = 2; % Dual feasibility
            case 2
                problem = 1; % Primal infeasibility
            otherwise
                problem = -1; % Unknown error
        end
    case 'sedumi'
        problem = sedumicode(infoCoLO.SDPsolver,options);

    case 'sdpa'
        switch (infoCoLO.SDPsolver.phasevalue)
            case 'pdOPT'
                problem = 0;
            case {'noINFO','pFEAS','dFEAS','pdFEAS'}
                problem = 3;
            case 'pFEAS_dINF'
                problem = 2;
            case 'pINF_dFEAS'
                problem = 1;
            case 'pUNBD'
                problem = 2;
            case 'dUNBD'
                problem = 1;
            case 'pdINF'
                problem = 12;
            otherwise
                problem = -1;
        end

end

if options.savesolveroutput
    solveroutput.obj = obj;
    solveroutput.X = X;
    solveroutput.y = y;
    solveroutput.Z = Z;
    solveroutput.info = info;
    solveroutput.runhist = runhist;
else
    solveroutput = [];
end

if options.savesolverinput
    solverinput.blk = blk;
    solverinput.A   = A;
    solverinput.C   = C;
    solverinput.b   = b;
    solverinput.X0   = [];
    solverinput.y0   = x0;
    solverinput.Z0   = [];
    solverinput.options   = options.sdpt3;
else
    solverinput = [];
end

% Standard interface
output = createOutputStructure(Primal,Dual,[],problem,interfacedata.solver.tag,solverinput,solveroutput,solvertime);

function problem = sedumicode(info,options)
temp = info.pinf;
pinf = info.dinf;
dinf = temp;

% Check for reported errors
if (pinf==0) &  (dinf==0)
    problem = 0; % No problems
end

% We can only report one error, use priorities
if (problem==0) & (pinf==1)
    problem = 1; % Primal infeasability
end

if (problem==0) & (dinf==1)
    problem = 2; % Dual infeasability
end

if (problem==0) & (info.numerr==1) | (info.numerr==2)
    problem = 4; %Numerical problems
end

if (problem==0) & (info.iter >= options.sedumi.maxiter)
    % Did we need exactly maxiter iterations to find optimum
    if (pinf==0) & (dinf==0) & (info.numerr==0)
        problem = 0; % Yes
    else
        problem = 3; % No, we are not optimal yet
    end
end

if (problem==0) & (info.feasratio<0.98)
    problem = 4;
end

% Fix for cases not really explained in documentation of sedumi?
if (abs(info.feasratio+1)<0.1) & (pinf==0) &  (dinf==0)
    problem = 1;
end
if (abs(info.feasratio+1)<0.1) & (pinf==0) &  (dinf==0) & (c'*y_s<-1e10)
    problem = 2;
end


function [ output ] = tapas_rdcm_store_parameters(DCM, mN_cut, sN, aN, bN, logF, logF_term, idx_x, z_cut, args)
% [ output ] = tapas_rdcm_store_parameters(DCM, mN_cut, sN, aN, bN, logF, logF_term, idx_x, z_cut, args)
%
% Wraps parameters to the output structure.
%
%   Input:
%   	DCM             - model structure
%       mN_cut          - posterior means of connectivity parameters
%       sN              - posterior covaraince of connectivity parameters
%       aN              - posterior shape parameter of measurement noise
%       bN              - posterior rate parameter of measurement noise
%       logF            - negative free energy
%       logF_term       - seperate terms of the negative free energy
%       idx_x           - regressor/parameter index
%       z_cut           - posterior binary indicators
%       args            - arguments
%
%   Output:
%       output          - output structure
%

% ----------------------------------------------------------------------
%
% Authors: Stefan Fraessle (stefanf@biomed.ee.ethz.ch), Ekaterina I. Lomakina
%
% Copyright (C) 2016-2022 Translational Neuromodeling Unit
%                         Institute for Biomedical Engineering
%                         University of Zurich & ETH Zurich
%
% This file is part of the TAPAS rDCM Toolbox, which is released under the
% terms of the GNU General Public License (GPL), version 3.0 or later. You
% can redistribute and/or modify the code under the terms of the GPL. For
% further see COPYING or <http://www.gnu.org/licenses/>.
%
% Please note that this toolbox is in an early stage of development. Changes
% are likely to occur in future releases.
%
% ----------------------------------------------------------------------

% remove confound regressors
Nc = size(DCM.U.X0,2);
DCM.b = DCM.b(:,:,1:end-Nc);
DCM.c = DCM.c(:,1:end-Nc);

% get number of regions and inputs
[nr, nu] = size(DCM.c);

% get the posterior parameter estimates
if min(size(idx_x)) == 1
    mN = zeros(nr,length(idx_x));
    mN(repmat(idx_x,nr,1)) = mN_cut;
else
    mN = mN_cut;
end

%% mean

% get mean for connectivity parameters
output.Ep          = tapas_rdcm_empty_par(DCM);
output.Ep.A        = mN(1:nr,1:nr);
output.Ep.B        = reshape(mN(1:nr,nr+1:nr+nr*nu),[nr nr nu]);
output.Ep.C        = mN(1:nr,end-Nc-nu+1:end-Nc);
output.Ep.baseline = mN(1:nr,end-Nc+1:end);

% modify driving inputs
if ( strcmp(args.type,'r') )
    output.Ep.C        = output.Ep.C*16;
end

%% variance

% get the number of potential connections
D = numel(output.Ep.A) + numel(output.Ep.C);

% create the covariance matrix (for computational reasons, only recommended for small DCMs)
if ( isempty(z_cut) && args.evalCp == 1 )

    % empty covariance matrix
    output.Cp = sparse(D,D);

    % get the number of entries
    nr_A    = numel(output.Ep.A);
    nr_C    = numel(output.Ep.C);
    nr_A_B  = numel(output.Ep.A(1,:))+numel(output.Ep.B(1,:,:))+numel(output.Ep.B(1,:,1));

    % define an index matrix for endogenous connections
    indexA = reshape(1:nr_A,nr,nr);

    % get the (co)variances of the endogenous connections
    for k = 1:nr
        for int = 1:nr
            for int2 = 1:nr
                output.Cp(indexA(k,int),indexA(k,int2)) = sN{k}(int,int2);
            end
        end
    end

    % define an index matrix for driving input parameters
    indexC = reshape(1:nr_C,nr,nu);

    % get the (co)variances of the driving input parameters
    for k = 1:nr
        for int = 1:nu
            for int2 = 1:nu
                output.Cp(nr_A+indexC(k,int),nr_A+indexC(k,int2)) = sN{k}(nr_A_B+int,nr_A_B+int2);
            end
        end
    end

    % get the covariances between endogeous and driving input parameters
    for k = 1:nr
        for int = 1:nr
            for int2 = 1:nu
                output.Cp(indexA(k,int),nr_A+indexC(k,int2)) = sN{k}(int,nr_A_B+int2);
                output.Cp(nr_A+indexC(k,int2),indexA(k,int)) = sN{k}(int,nr_A_B+int2);
            end
        end
    end
end

% store the regions-wise posterior covariance matrices
output.sN = sN;

%% precision

% store precision parameters
output.t  = aN./bN;
output.aN = aN;
output.bN = bN;

%% connection probabilities

% store connection probabilities
if ( ~isempty(z_cut) )
    if min(size(idx_x)) == 1
        z = zeros(nr,length(idx_x));
        z(repmat(idx_x,nr,1)) = z_cut;
    else
        z = z_cut;
    end

    output.Ip   = tapas_rdcm_empty_par(DCM);
    output.Ip.A = z(1:nr,1:nr);
    output.Ip.B = reshape(z(1:nr,nr+1:nr+nr*nu),[nr nr nu]);
    output.Ip.C = z(1:nr,end-nu:end-1);
else
    output.Ip   = tapas_rdcm_empty_par(DCM);
    output.Ip.A = DCM.a;
    output.Ip.B = DCM.b;
    output.Ip.C = DCM.c;
end

%% free energy

% store free energy
output.logF   = sum(logF);
output.logF_r = logF;

% store the components of the free energy
if ( ~isempty(logF_term) )
    output.logF_term.log_lik        = sum(logF_term.log_lik);
    output.logF_term.log_p_weight   = sum(logF_term.log_p_weight);
    output.logF_term.log_p_prec     = sum(logF_term.log_p_prec);
    output.logF_term.log_p_z        = sum(logF_term.log_p_z);
    output.logF_term.log_q_weight   = sum(logF_term.log_q_weight);
    output.logF_term.log_q_prec     = sum(logF_term.log_q_prec);
    output.logF_term.log_q_z        = sum(logF_term.log_q_z);
end

end


function test_tutorial_natmeg2014_preprocessing

% WALLTIME 00:20:00
% MEM 5gb
% DEPENDENCY

% this script executes the MATLAB content from
% http://www.fieldtriptoolbox.org/tutorial/natmeg2014/timefrequency
%
% it corresponds to the wiki version of 7 October 2014

clear all
close all

cd(dccnpath('/home/common/matlab/fieldtrip/data/ftp/workshop/natmeg2014'));

cfg = [];
cfg.dataset    = 'oddball1_mc_downsampled.fif';
cfg.continuous = 'yes';
cfg.channel    = 'MEG*1';
cfg.viewmode   = 'vertical';
cfg.blocksize  = 1; % Length of data to display, in seconds
ft_databrowser(cfg);

cfg = [];
cfg.dataset = 'oddball1_mc_downsampled.fif';
cfg.channel = {'MEG*2', 'MEG*3'};
cfg.viewmode = 'vertical';
cfg.blocksize = 1;                             % Length of data to display, in seconds
ft_databrowser(cfg);

cfg = [];
cfg.dataset = 'oddball1_mc_downsampled.fif';
cfg.channel = 'EEG';
cfg.viewmode = 'vertical';
cfg.blocksize = 1;                             % Length of data to display, in seconds
cfg.preproc.demean = 'yes';                    % Demean the data before display
cfg.ylim = [-4e-6 4e-6];
ft_databrowser(cfg);

cfg = [];
cfg.dataset = 'oddball1_mc_downsampled.fif';

cfg.trialdef.prestim        = 1;
cfg.trialdef.poststim       = 1;
cfg.trialdef.std_triggers   = 1;
cfg.trialdef.stim_triggers  = [1 2]; % 1 for standard, 2 for deviant
cfg.trialdef.odd_triggers   = 2;
cfg.trialdef.rsp_triggers   = [256 4096];
cfg.trialfun                = 'trialfun_oddball_stimlocked';
cfg                         = ft_definetrial(cfg);

cfg.continuous              = 'yes';
cfg.hpfilter                = 'no';
cfg.detrend                 = 'no';
cfg.continuous              = 'yes';
cfg.demean                  = 'yes';
cfg.dftfilter               = 'yes';
cfg.dftfreq                 = [50 100];
cfg.channel                 = 'MEG';
data_MEG                    = ft_preprocessing(cfg);

if false
  % skip the interactive section
  % separately for magnetometers
  cfg               = [];
  cfg.metric        = 'zvalue';
  cfg.layout        = 'neuromag306all.lay';
  cfg.channel       = 'MEG*1';
  cfg.keepchannel   = 'yes';  % This keeps those channels that are not displayed in the data
  data_MEG_clean    = ft_rejectvisual(cfg,data_MEG);
  % separately for gradiometers
  cfg.channel = {'MEG*2','MEG*3'};
  data_MEG_clean    = ft_rejectvisual(cfg,data_MEG_clean);
else
  % simply copy it over
  data_MEG_clean = data_MEG;
end

cfg = [];
cfg.lpfilter        = 'yes';
cfg.lpfreq          = 25;
cfg.demean          = 'yes';
cfg.baselinewindow  = [-0.5 0];
data_MEG_filt       = ft_preprocessing(cfg,data_MEG_clean);

cfg = [];
cfg.trials          = find(data_MEG_filt.trialinfo(:,1) == 1);
ERF_standard        = ft_timelockanalysis(cfg,data_MEG_filt);

cfg.trials          = find(data_MEG_filt.trialinfo(:,1) == 2);
ERF_oddball         = ft_timelockanalysis(cfg,data_MEG_filt);

cfg = [];
cfg.operation = 'x1 - x2';
cfg.parameter = 'avg';
ERF_diff = ft_math(cfg, ERF_oddball, ERF_standard);

cfg = [];
cfg.fontsize = 6;
cfg.layout = 'neuromag306mag.lay';
cfg.ylim = [-2.5e-13 2.5e-13];
cfg.xlim = [-0.2 0.6];

figure;
ft_multiplotER(cfg, ERF_standard, ERF_oddball, ERF_diff );
legend({'Standard';'Oddball';'Difference'});

cfg = [];
cfg.fontsize = 6;
cfg.layout   = 'neuromag306mag.lay';
cfg.xlim     = [-0.2 0.6];
cfg.ylim     = [-3e-13 3e-13];
cfg.channel  = 'MEG0211';

figure;
ft_singleplotER(cfg, ERF_standard, ERF_oddball, ERF_diff);
legend({'Standard';'Oddball';'Difference'});

cfg                 = [];
cfg.layout          = 'neuromag306mag.lay'; % name will change
cfg.zlim            = [-3e-13 3e-13];
cfg.xlim            = [0.08 0.15];
cfg.style           = 'straight';
cfg.comment         = 'no';
cfg.marker          = 'off';
cfg.colorbar        = 'southoutside';

figure;
subplot(1,3,1);
ft_topoplotER(cfg, ERF_standard);
title('Standard');
axis tight

subplot(1,3,2);
ft_topoplotER(cfg, ERF_oddball);
title('Oddball');
axis tight

subplot(1,3,3);
ft_topoplotER(cfg, ERF_diff);
title('Difference');
axis tight

% Combine planar
cfg = [];
ERF_standard_cmb    = ft_combineplanar(cfg, ERF_standard);
ERF_oddball_cmb     = ft_combineplanar(cfg, ERF_oddball);
ERF_diff_cmb        = ft_combineplanar(cfg, ERF_diff);

cfg = [];
cfg.fontsize = 6;
cfg.layout   = 'neuromag306cmb.lay';
cfg.ylim     = [0 8e-12];
cfg.xlim     = [-0.2 0.6];

figure;
ft_multiplotER(cfg, ERF_standard_cmb, ERF_oddball_cmb, ERF_diff_cmb);
legend({'Standard?, ?Oddball?, ?Difference'});

cfg = [];
cfg.showlabels = 'yes';
cfg.fontsize   = 6;
cfg.layout     = 'neuromag306cmb.lay';
cfg.xlim       = [-0.2 0.6];
cfg.ylim       = [0 8e-12];
cfg.channel    = 'MEG0222+0223';

figure;
ft_singleplotER(cfg, ERF_standard_cmb, ERF_oddball_cmb, ERF_diff_cmb);
legend({'Standard?, ?Oddball?, ?Difference'});

cfg                 = [];
cfg.layout          = 'neuromag306cmb.lay'; % name will change
cfg.zlim            = 'zeromax';
cfg.xlim            = [0.08 0.15];
cfg.style           = 'straight';
cfg.comment         = 'no';
cfg.marker          = 'off';
cfg.colorbar        = 'southoutside';

figure;
subplot(1,3,1);
ft_topoplotER(cfg, ERF_standard_cmb);
title('Standard');
axis tight

subplot(1,3,2);
ft_topoplotER(cfg, ERF_oddball_cmb);
title('Deviant');
axis tight

subplot(1,3,3);
ft_topoplotER(cfg, ERF_diff_cmb);
title('Difference');
axis tight

cfg = [];
cfg.dataset = 'oddball1_mc_downsampled.fif';

cfg.trialdef.prestim        = 1;
cfg.trialdef.poststim       = 1;
cfg.trialdef.std_triggers   = 1;
cfg.trialdef.stim_triggers  = [1 2];
cfg.trialdef.odd_triggers   = 2;
cfg.trialdef.rsp_triggers   = [256 4096];
cfg.trialfun                = 'trialfun_oddball_stimlocked';
cfg                         = ft_definetrial(cfg);

cfg.continuous              = 'yes';
cfg.hpfilter                = 'no';
cfg.detrend                 = 'no';
cfg.continuous              = 'yes';
cfg.demean                  = 'yes';
cfg.dftfilter               = 'yes';
cfg.dftfreq                 = [50 100];
cfg.channel                 = 'EEG';

cfg.reref                   = 'yes'; % recorded with left mastoid
cfg.refchannel              = 'all';
data_EEG                    = ft_preprocessing(cfg);

if false
  % skip the interactive section
  cfg               = [];
  cfg.metric        = 'zvalue';
  cfg.layout        = 'natmeg_customized_eeg1005.lay';
  data_EEG_clean    = ft_rejectvisual(cfg,data_EEG);
else
  % simply copy the data over
  data_EEG_clean = data_EEG;
end

cfg = [];
cfg.lpfilter        = 'yes';
cfg.lpfreq          = 25;
cfg.demean          = 'yes';
cfg.baselinewindow  = [-0.5 0];
data_EEG_filt       = ft_preprocessing(cfg,data_EEG_clean);

cfg = [];
cfg.trials          = find(data_EEG_filt.trialinfo(:,1) == 1);
ERP_standard        = ft_timelockanalysis(cfg, data_EEG_filt);
cfg.trials          = find(data_EEG_filt.trialinfo(:,1) == 2);
ERP_oddball         = ft_timelockanalysis(cfg, data_EEG_filt);

cfg = [];
cfg.operation = 'x1 - x2';
cfg.parameter = 'avg';
ERP_diff = ft_math(cfg, ERP_oddball, ERP_standard);

cfg          = [];
cfg.fontsize = 6;
cfg.layout   = 'natmeg_customized_eeg1005.lay';
cfg.ylim     = [-3e-6 3e-6];
cfg.xlim     = [-0.2 0.6];

figure;
ft_multiplotER(cfg, ERP_standard, ERP_oddball, ERP_diff);

cfg            = [];
cfg.showlabels = 'yes';
cfg.fontsize   = 6;
cfg.layout     = 'natmeg_customized_eeg1005.lay';
cfg.xlim       = [-0.2 0.6];
cfg.ylim       = [-8e-6 8e-6];
cfg.channel    = 'EEG020';

figure;
ft_singleplotER(cfg, ERP_standard, ERP_oddball, ERP_diff);
legend({'Standard';'Oddball';'Difference'});

% Topo
cfg                 = [];
cfg.layout          = 'natmeg_customized_eeg1005.lay';
cfg.zlim            = [-3e-6 3e-6];
cfg.xlim            = [0.08 0.15];
cfg.style           = 'straight';
cfg.comment         = 'no';
cfg.marker          = 'off';
cfg.colorbar        = 'southoutside';

figure;
subplot(1,3,1);
ft_topoplotER(cfg,ERP_standard);
title('Standard');
axis tight

subplot(1,3,2);
ft_topoplotER(cfg,ERP_oddball);
title('Deviant');
axis tight

subplot(1,3,3);
ft_topoplotER(cfg,ERP_diff);
title('Difference');
axis tight

cfg                 = [];
cfg.method          = 'finite';
cfg.elec            = ERP_standard.elec;

scd_ERP_standard    = ft_scalpcurrentdensity(cfg, ERP_standard);
scd_ERP_oddball     = ft_scalpcurrentdensity(cfg, ERP_oddball);
scd_ERP_diff        = ft_scalpcurrentdensity(cfg, ERP_diff);

cfg                 = [];
cfg.layout          = 'natmeg_customized_eeg1005.lay'; % name will change
cfg.zlim            = 'maxabs';
cfg.xlim            = [0.08 0.15];
cfg.style           = 'straight';
cfg.comment         = 'no';
cfg.marker          = 'off';
cfg.colorbar        = 'southoutside';

figure;
subplot(1,3,1);
ft_topoplotER(cfg,scd_ERP_standard);
title('Standard');
axis tight;

subplot(1,3,2);
ft_topoplotER(cfg,scd_ERP_oddball);
title('Oddball');
axis tight;

subplot(1,3,3);
ft_topoplotER(cfg,scd_ERP_diff);
title('Difference');
axis tight;

cfg      = [];
data_all = ft_appenddata(cfg, data_MEG, data_EEG);

if false
  % skip the interactive section
  cfg = [];
  cfg.channel    = 'EEG';
  cfg.metric     = 'zvalue';
  cfg.keepchannel= 'yes';
  cfg.layout     = 'neuromag306all.lay';
  data_all_clean = ft_rejectvisual(cfg, data_all);

  cfg.channel    = 'MEGMAG';
  data_all_clean = ft_rejectvisual(cfg, data_all_clean);

  cfg.channel    = 'MEGGRAD';
  data_all_clean = ft_rejectvisual(cfg, data_all_clean);
end


function [metrics, emphysema_mask] = PTKComputeEmphysemaFromMask(roi_data, mask)
    % PTKComputeEmphysemaFromMask. Computes emphysema percentage and percentile
    % density
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2013.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.

    emphysema_threshold_value_hu_1 = -950;
    emphysema_threshold_value_hu_2 = -910;

    emphysema_threshold_value_1 = roi_data.HounsfieldToGreyscale(emphysema_threshold_value_hu_1);
    emphysema_threshold_value_2 = roi_data.HounsfieldToGreyscale(emphysema_threshold_value_hu_2);
    emphysema_threshold_value_percentile = 15;
    lower_threshold = (roi_data.RawImage <= emphysema_threshold_value_1) & (mask.RawImage > 0);
    upper_threshold = (roi_data.RawImage <= emphysema_threshold_value_2) & (mask.RawImage > 0);
    emphysema_mask_raw = uint8(upper_threshold);
    emphysema_mask_raw(lower_threshold) = 3;
    emphysema_mask = mask.BlankCopy;
    emphysema_mask.ChangeRawImage(emphysema_mask_raw);

    number_of_voxels_in_mask = sum(mask.RawImage(:));
    emphysema_voxels_in_mask = sum(lower_threshold(:)); % We only count voxels in the lower threshold
    emphysema_percentage = 100*emphysema_voxels_in_mask/number_of_voxels_in_mask;

    if ~mask.ImageExists
        emphysema_percentile_density = NaN;
        emphysema_percentile_density_hu = NaN;
    else
        emphysema_percentile_density = prctile(roi_data.RawImage(mask.RawImage(:)), emphysema_threshold_value_percentile);
        emphysema_percentile_density_hu = roi_data.GreyscaleToHounsfield(emphysema_percentile_density);
    end

    metrics = PTKMetrics;
    metrics.AddMetric('EmphysemaPercentage', emphysema_percentage, '% of emphysema');
    metrics.AddMetric('EmphysemaPercentileDensityHU', emphysema_percentile_density_hu, 'Emphysema percentile density (HU)');
end


function [fx,dfdx,dfdp] = f_AR(x,theta,u,in)
% AR(1) evolution function
fx = x;
dfdx = eye(length(x));
dfdp = [];


function v = rotate_outer(m,rot,varargin)
% rotate crystal directions
%
% Input
%  m - @Miller
%  ori - @orientation
%
% Output
%  v - vector3d
%

% ensure that the rotations have the right reference frame
if isa(rot,'orientation') && nargin == 2
  rot = m.CS.ensureCS(rot);
end

v = rotate_outer@vector3d(m,rot);


function [im, im_scale] = prep_im_for_blob(im, im_means, target_size, max_size)
    im = single(im);
    if size(im,3) < 3
      im = im(:,:,[1 1 1]);
    end
    if ~isa(im, 'gpuArray')
        try
            im = bsxfun(@minus, im, im_means);
        catch
            im_means = imresize(im_means, [size(im, 1), size(im, 2)], 'bilinear', 'antialiasing', false);
            if  size(im,3)>3 && size(im,3) ~= size(im_means,3)
              im(:,:,1:3,:) = bsxfun(@minus, im(:,:,1:3,:), im_means);
            else
              im = bsxfun(@minus, im, im_means);
            end
        end
        im_scale = prep_im_for_blob_size(size(im), target_size, max_size);

        target_size = round([size(im, 1), size(im, 2)] * im_scale);
        im = imresize(im, target_size, 'bilinear', 'antialiasing', false);
    else
        % for im as gpuArray
        try
            im = bsxfun(@minus, im, im_means);
        catch
            im_means_scale = max(double(size(im, 1)) / size(im_means, 1), double(size(im, 2)) / size(im_means, 2));
            im_means = imresize(im_means, im_means_scale);
            y_start = floor((size(im_means, 1) - size(im, 1)) / 2) + 1;
            x_start = floor((size(im_means, 2) - size(im, 2)) / 2) + 1;
            im_means = im_means(y_start:(y_start+size(im, 1)-1), x_start:(x_start+size(im, 2)-1));
            im = bsxfun(@minus, im, im_means);
        end

        im_scale = prep_im_for_blob_size(size(im), target_size, max_size);
        im = imresize(im, im_scale);
    end
end


function out = times( a,b )
%TIMES (element-wise) for nested cells
%
% (c) Thomas Kuestner
% ---------------------------------------------------------------------

% determine input types
inType = {class(a), class(b)};
if(strcmp(inType{1},'TRAFO') && strcmp(inType{2},'TRAFO'))
    [outA, idx] = flattenCellMatrix(a.data);
    [outB, idxB] = flattenCellMatrix(b.data);
    meta = a.meta;
    meta_b = b.meta;
    clear 'a' 'b'

    if(~isempty(idx) && ~isempty(idxB) && ~all(cellfun(@(x,y) isequal(x,y), idx, idxB)))
        error('TRAFO::times: Nested cells must have the same size');
    end
    if (iscell(meta) && iscell(meta_b))
        if(~isempty(meta) && ~isempty(meta_b))
            if(iscell(meta{1}) && iscell(meta_b{1}))
                if(~all(cellfun(@(x,y) isequal(x,y), flattenCellMatrix(meta), flattenCellMatrix(meta_b))))
                    error('TRAFO::times: Unequal reconstruction information');
                end
            else
                if(~all(cellfun(@(x,y) isequal(x,y), meta, meta_b)))
                    % happens in kernelMult for kernel .* zpad(W) -> take kernel
                    % meta information (meta) => corrected
                    [ST, ~] = dbstack;
                    if(~strcmp(ST(2,1).name,'kernelMult'))
                        error('TRAFO::times: Unequal reconstruction information');
                    end
                end
            end
        end
    else
        if ~isequal(meta, meta_b)
            error('TRAFO::times: Unequal reconstruction information');
        end
    end

%     try
        out = cellfun(@(x,y) x.*y, outA, outB, 'UniformOutput', false);
%     catch msg
%         out = cell(size(outA));
%         for i=1:length(out)
%             out{i} = outA{i} .* outB{i};
%         end
%     end

elseif(strcmp(inType{1},'TRAFO')) % assume b is double/uint/int
    [out, idx] = flattenCellMatrix(a.data);
    meta = a.meta;
    clear 'a'

    out = cellfun(@(x) x .* b, out, 'UniformOutput', false);

elseif(strcmp(inType{2},'TRAFO'))
    [out, idx] = flattenCellMatrix(b.data);
    meta = b.meta;
    clear 'b'

    out = cellfun(@(x) a .* x, out, 'UniformOutput', false);

else
    error('TRAFO::times: Impossible constellation!');
end

out = reconFlatCellMatrix(out,idx);
out = TRAFO(out,meta); % return TRAFO object again without modifying input

end


function run_test_single_model
% Copyright (c) 2014-present University of Illinois at Urbana-Champaign
% All rights reserved.
%
% Developed by:     Po-Sen Huang, Paris Smaragdis
%                   Department of Electrical and Computer Engineering
%                   Department of Computer Science
%
% Given a model, evaluate the performance.
    baseDir = '../../../';
    addpath([baseDir, filesep, 'codes']);
    addpath([baseDir, filesep, 'tools', filesep, 'bss_eval']);
    addpath([baseDir, filesep, 'tools', filesep, 'bss_eval_3']);
    addpath([baseDir, filesep, 'tools', filesep, 'labrosa']);
    addpath([baseDir, filesep, 'codes', filesep, 'TSP']);

    ModelPath=[baseDir, filesep, 'codes',filesep, 'TSP', filesep, 'model_demo'];

    global SDR;
    SDR.deviter=0;   SDR.devmax=0;   SDR.testmax=0;
    SDR.devsar=0; SDR.devsir=0; SDR.testsar=0; SDR.testsir=0;

    j=7650;

    % Load model
    load model_RNN1_win1_h300_l2_r0_64ms_1000000_softabs_linearout_RELU_logmel_trn0_c1e-10_c0.001_bsz100000_miter10_bf50_c0_d0_7650.mat
    eI.writewav=1;
    eI.bss3=1;
    eI.DataPath=[baseDir, filesep, 'codes', filesep, 'TSP', ...
        filesep, 'Data', filesep];
    eI.saveDir = [baseDir, filesep, 'codes', filesep, 'TSP', ...
        filesep, 'demo', filesep, 'results', filesep];
    eI.CFGPath = [baseDir, filesep, 'tools', filesep, 'htk_features', filesep];
    test_TSP_general_kl_recurrent(eI.modelname, theta, eI, 'done', j);
end


background.marker_pos(:,1+mod(background.smax:background.smax+size(background_marker_pos,2)-1,background.buffer_len)) = background_marker_pos+logical(background_marker_pos)*background.mmax;
background.mmax = background.mmax + nnz(background_marker_pos);


function path=VMR2mrGray(VMRfile,mmPerPix);
% function path=VMR2mrGray(VMRfile,mmPerPix);
% Function to convert between Brainvoyager VMR file format and mrGray
% Last edited : $Date: 2007/07/05 19:51:58 $
% ARW 100300
if ~exist('mmPerPix','var')
   mmPerPix = [240/256 240/256 1.2];
   disp(['mmPerPix defaulting to [ ' num2str(mmPerPix,'%.4f ') ...
         	'].  I hope this is correct!']);
end

fid=fopen(VMRfile,'r');
header=fread(fid,3,'int16');
mainImg=fread(fid,'uchar');
fclose(fid);
mainImg=reshape(mainImg,[header(1),header(2),header(3)]);
disp('Flipping images...');

for thisIm=1:header(3)
   mainImg(:,:,thisIm)=rot90(fliplr(mainImg(:,:,thisIm)));
end

path = writeVolAnat(mainImg, mmPerPix);


function fns_elec_write(pnt, vsize, dimpos, elecfile)
%
% This function write the electrodes locations on disk and other
% information
%   1. pnt is the location of the electrodes [NX3]
%   3. voxel_sizes is the dimension of a voxel in the cartesian coordinates in mm [3X1]
%   4. nodes_sizes is the dimension of the dipoles grid [NX NY NZ]

% $Copyright (C) 2010 by Hung Dang$

hdf5write(elecfile, '/electrodes/locations', pnt);

hdf5write(elecfile, '/electrodes/gridlocs', int32(pnt), ...
          'WriteMode', 'append');       % Assume the electrodes
                                        % locations are mm and the
                                        % voxel sizes is 1mm x 1mm
                                        % x 1mm.

hdf5write(elecfile, '/electrodes/voxel_sizes', vsize, ...
          'WriteMode','append');

hdf5write(elecfile, '/electrodes/node_sizes', int32(dimpos), ...
          'WriteMode', 'append');


s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

hash = java.util.Hashtable;
C = {};
for i = 1:100
    key = randsample(s,20,true);
    value = randsample(s,40,true);
    hash.put(key, value);
    C{end+1} = {key, value};
end


function model = ivmOptimise(model, options);

% IVMOPTIMISE Optimise the IVM.
% FORMAT
% DESC optimises an IVM by iterating between selecting points and
% optimising kernel and noise parameters.
% ARG model : the model to be optimised.
% ARG options : options structure as returned by ivmOptions.
%
% SEEALSO : ivmOptimiseIvm, ivmOptimiseKernel, ivmOptimiseNoise
%
% COPYRIGHT : Neil D. Lawrence, 2005, 2006

% IVM

for i = 1:options.extIters
  if options.kernIters
    % Update the kernel if required.
    model = ivmOptimiseIvm(model, options.display);
    model = ivmOptimiseKernel(model, options.display, options.kernIters);
  end
  if options.noiseIters
    % Update the noise model if required.
    model = ivmOptimiseIvm(model, options.display);
    model = ivmOptimiseNoise(model, options.display, options.noiseIters);
  end
  if options.display
    ivmDisplay(model);
  end
end


function output = callbonmin(model)

model = yalmip2nonlinearsolver(model);
options = [];
try
    options.bonmin = optiRemoveDefaults(model.options.bonmin,bonminset());
catch
    options.bonmin = model.options.bonmin;
end
options.ipopt = model.options.ipopt;
options.display = model.options.verbose;

if ~model.derivative_available
    disp('Derivate-free call to bonmin/ipopt not yet implemented')
    error('Derivate-free call to bonmin/ipopt not yet implemented')
end

if model.options.savedebug
    save bonmindebug model
end

Fupp = [ repmat(0,length(model.bnonlinineq)+length(model.K.q)*(model.K.q(1)>0),1);
    repmat(0,length(model.bnonlineq),1);
    repmat(0,length(model.b),1);
    repmat(0,length(model.beq),1)];

Flow = [ repmat(-inf,length(model.bnonlinineq)+length(model.K.q)*(model.K.q(1)>0),1);
    repmat(0,length(model.bnonlineq),1);
    repmat(-inf,length(model.b),1);
    repmat(0,length(model.beq),1)];

if isempty(Flow)
    Flow = [];
    Fupp = [];
end

% Since ipopt react strangely on lb>ub, we should bail if that is detected
% (ipopt creates an exception)
if ~isempty(model.lb)
    if any(model.lb>model.ub)
        problem = 1;
        solverinput = [];
        solveroutput = [];
        output = createoutput(model.lb*0,[],[],problem,'BONMIN',solverinput,solveroutput,0);
        return
    end
end

% These are needed to avoid recomputation due to ipopts double call to get
% f and df, and g and dg
global latest_x_f
global latest_x_g
global latest_df
global latest_f
global latest_G
global latest_g
global latest_xevaled
global latest_x_xevaled
latest_G= [];
latest_g = [];
latest_x_f = [];
latest_x_g = [];
latest_xevaled = [];
latest_x_xevaled = [];

funcs.objective = @(x)ipopt_callback_f(x,model);
funcs.gradient = @(x)ipopt_callback_df(x,model);
if ~isempty(Fupp)
    funcs.constraints = @(x)ipopt_callback_g(x,model);
    funcs.jacobian  = @(x)ipopt_callback_dg(x,model);
end

options.lb = model.lb(:)';
options.ub = model.ub(:)';
if ~isempty(Fupp)
    options.cl = Flow;
    options.cu = Fupp;
end

if ~isempty(Fupp)
    m = length(model.lb);
    allA=[model.Anonlinineq];
    if size(model.F_struc,1) > 0
        % These are SOCP cones
        top = 1;
        for i = 1:length(model.K.q)
            rows = model.F_struc(top:top + model.K.q(i)-1,2:end)
            allA = [allA;any(rows,1)];
        end
    end
    allA = [allA;model.Anonlineq];
    jacobianstructure = spalloc(size(allA,1),m,0);
    depends = allA | allA;
    for i = 1:size(depends,1)
        vars = find(depends(i,:));
        [ii,vars] = find(model.deppattern(vars,:));
        vars = unique(vars);
        s = size(jacobianstructure,1);
        for j = 1:length(vars)
            jacobianstructure(i,find(vars(j) == model.linearindicies)) = 1;
        end
    end
    allA=[model.A; model.Aeq];
    depends = allA | allA;
    jacobianstructure = [jacobianstructure;depends];

    Z = sparse(jacobianstructure);
    funcs.jacobianstructure = @() Z;
end

if ~model.options.usex0
    model.x0 = (options.lb+options.ub)/2;
    model.x0(isinf(options.ub)) = options.lb(isinf(options.ub))+1;
    model.x0(isinf(options.lb)) = options.ub(isinf(options.lb))-1;
    model.x0(isinf(model.x0)) = 0;
end

if ~isempty(model.binary_variables) | ~isempty(model.integer_variables)
    options.var_type = zeros(length(model.linearindicies),1);
    options.var_type(model.binary_variables) = -1;
    options.var_type(model.integer_variables) = 1;
end

showprogress('Calling BONMIN',model.options.showprogress);
solvertime = tic;
[xout,info] = bonmin(model.x0,funcs,options);
solvertime = toc(solvertime);

x = RecoverNonlinearSolverSolution(model,xout);

switch info.status
    case {0,2}
        problem = 0;
    case 1
        problem = 1;
    case {-1}
        problem = 3;
    case {3}
        problem = 15;
    otherwise
        problem = -1;
end

% Duals currently not supported
D_struc = [];

% Save all data sent to solver?
if model.options.savesolverinput
    solverinput.x0 = model.x0;
    solverinput.model = model;
    solverinput.options = options;
else
    solverinput = [];
end

% Save all data from the solver?
if model.options.savesolveroutput
    solveroutput.x = xout;
    solveroutput.info = info;
else
    solveroutput = [];
end

% Standard interface
output = createoutput(x,D_struc,[],problem,'BONMIN',solverinput,solveroutput,solvertime);

% Code supplied by Jonatan Currie
function opts = removeDefaults(opts,defs)
oFn = fieldnames(opts);
for i = 1:length(oFn)
    label = oFn{i};
    if(isfield(defs,label))
        if(ischar(opts.(label)))
            if(strcmpi(defs.(label),opts.(label)))
                opts = rmfield(opts,label);
            end
        else
            if(defs.(label) == opts.(label))
                opts = rmfield(opts,label);
            end
        end
    end
end


function specific_vortal_plots(up)

save_name = up.paths.filenames.hr_rr_scatter;
savepath = [up.paths.plots_save_folder, up.paths.filenames.hr_rr_scatter, '.eps'];
if ~up.analysis.redo_stats
    exist_log = check_exists(savepath, save_name);
    if exist_log
        return
    end
end

%% Make plot of feature vs filter resp sigs
if ~isempty(strfind(up.paths.paper_figures_folder, 'pc13')) & ...
        isempty(strfind(up.paths.data_save_folder, 'REC')) & isempty(strfind(up.paths.data_save_folder, 'WALK')) ...
        & isempty(strfind(up.paths.data_save_folder, 'EX'))
    % Load resp sigs
    subj = 2;
    load_path = [strrep(up.paths.data_save_folder, 'rest_and_rec', 'rest'), num2str(subj), up.paths.filenames.respSigs];
    resp_sigs = load(load_path);
    if sum(strcmp(fieldnames(resp_sigs), 'ppg_flt_Wam'))
        % Load raw sig
        load_path = [up.paths.data_save_folder, num2str(subj), up.paths.filenames.int_respSigs];
        int_resp_sigs = load(load_path);
        % Load annotated breaths
        up.paths.root_ann_folder = 'C:\Documents\Data\VORTAL\Manual_breath_annotations\';
        up.paths.observers = {'TB', 'DV'};
        up.paths.ann_folder = '_annotations\';
        obs_no = 1;
        data_folder = [up.paths.root_ann_folder, up.paths.observers{obs_no}, up.paths.ann_folder];
        % find SID
        temp = num2str(subj);
        if length(temp) == 1
            SID = ['00', temp];
        elseif length(temp) == 2
            SID = ['0', temp];
        end
        % Load annotated breaths
        rel_name = ['VORTAL' SID 'rest' up.paths.observers{obs_no} '-paw_an'];
        anns = load([data_folder, rel_name]); t = anns.PKS.t;
        % Load s ref time
        up.paths.s_ref_time_folder = 'C:\Documents\Data\VORTAL\Analysis_files\Processed_Data\';
        loadpath = [up.paths.s_ref_time_folder, SID, 's_con_rest'];
        load(loadpath, 'Sreftime', 'Send', 'Sstart');
        load(up.paths.db_data, 'db_data');
        bst_time = db_data.bst_log(db_data.sid == subj)/(24);
        % find t, measured in seconds since the start of the period
        t = 60*60*24*(t/(60*60*24) - floor( t/(60*60*24) ) - Sreftime + bst_time) - Sstart; % As the times are in seconds since 1970
        % Identify relevant section
        start_t = 92;
        rel_t = [start_t, start_t+up.paramSet.winLeng];
        rel_feat = int_resp_sigs.ppg_FMeam_FPt_PDtIMS_EHF;
        rel_filt = resp_sigs.ppg_flt_Wam;
        rel_sig = int_resp_sigs.ppg_EHF;
        rel_els = rel_feat.t >= rel_t(1) & rel_feat.t <= rel_t(2);
        rel_data.feat.t = rel_feat.t(rel_els);
        rel_data.feat.v = rel_feat.v(rel_els);
        rel_els = rel_filt.t >= rel_t(1) & rel_filt.t <= rel_t(2);
        rel_data.filt.t = rel_filt.t(rel_els);
        rel_data.filt.v = rel_filt.v(rel_els);
        rel_els = rel_sig.t >= rel_t(1) & rel_sig.t <= rel_t(2);
        rel_data.sig.t = rel_sig.t(rel_els);
        rel_data.sig.v = rel_sig.v(rel_els);

        % Make Figure
        h_fig = figure('Position', [200, 200, 600, 300]);

        % Plot
        ftsize = 12; lwidth = 2;
        h1 = plot(rel_data.sig.t-rel_t(1), detrend(rel_data.sig.v), 'b', 'LineWidth',1);
        hold on
        plot(rel_data.filt.t-rel_t(1), detrend(rel_data.filt.v), 'k', 'LineWidth',lwidth+2)
        h2 = plot(rel_data.filt.t-rel_t(1), detrend(rel_data.filt.v), 'c', 'LineWidth',lwidth);
        h3 = plot(rel_data.feat.t-rel_t(1), detrend(rel_data.feat.v), '-r', 'LineWidth',lwidth);
        h4 = plot(t-start_t, -0.05+zeros(length(t),1), '.k','MarkerSize',30);
        plot(rel_data.feat.t-rel_t(1), detrend(rel_data.feat.v), '.r', 'LineWidth',lwidth,'MarkerSize',20)
        xlim(rel_t-rel_t(1))
        temp = range(rel_data.sig.v);
        ylim([min(rel_data.sig.v)-0.05*temp, max(rel_data.sig.v)+0.05*temp])
        xlabel('Time [s]', 'FontSize', ftsize)
        ylabel('PPG', 'FontSize', ftsize)
        legend([h1, h2, h3, h4], {'PPG', 'Filter', 'Feature', 'Breaths'},'Location','northoutside','Orientation','horizontal')
        set(gca, 'FontSize', ftsize)
        set(gca, 'YTick', [])
        % Save
        set(gcf,'PaperUnits','inches');
        set(gcf,'PaperSize', [6, 3]);
        set(gcf,'PaperPosition',[0 0 6 3]);
        save_name = up.paths.filenames.feat_filt_plot;
        savepath = [up.paths.plots_save_folder, save_name];
        print(h_fig,'-depsc',savepath)
        close all
    end
end

if strfind(up.paths.data_save_folder, 'REST_AND_REC_TEMP')
    %% Create plot of improved precision with no of windows
    fprintf('\n--- Plot of improvement in precision with no of windows ');

    %% Load alg names
    load_name = up.paths.filenames.alg_names;
    loadpath = [up.paths.data_save_folder, up.paths.filenames.alg_names, '.mat'];
    load(loadpath, load_name);

    %% Load BA data
    load_name = 'BA_results';
    loadpath = [up.paths.data_save_folder, up.paths.filenames.global_BA, '.mat'];
    load(loadpath, load_name);
    rel_BA_res = BA_results.young;

    rel_els = find(strcmp(alg_names.sigs, 'ECG'));
    no_wins = alg_names.no_wins(rel_els);
    rel_prec = rel_BA_res.prec.val(rel_els);

    % Make Figure
    h_fig = figure('Position', [200, 200, 600, 300]);

    % Plot
    ftsize = 12; lwidth = 2;
    f2 = fit(no_wins,rel_prec,'exp2');
    coeffs = coeffvalues(f2);
    fitexp = ( coeffs(1)*exp(coeffs(2)*no_wins) ) + ( coeffs(3)*exp(coeffs(4)*no_wins) );
    plot(no_wins,rel_prec, 'mx', 'LineWidth',lwidth,'MarkerEdgeColor','k','MarkerFaceColor','k',...
        'MarkerSize',10)
    hold on
    plot(no_wins, fitexp, 'r', 'LineWidth', lwidth)
    ylim([8 12])
    xlim([1 max(no_wins)])
    xlabel('Number of windows used to estimate RR', 'FontSize', ftsize)
    ylabel('LOA interval [bpm]', 'FontSize', ftsize)
    set(gca, 'FontSize', ftsize)
    set(gca, 'YTick', 8:12)
    set(gcf,'PaperUnits','inches');
    set(gcf,'PaperSize', [6, 3]);
    set(gcf,'PaperPosition',[0 0 6 3]);
    save_name = up.paths.filenames.temp_prec_plot;
    savepath = [up.paths.plots_save_folder, save_name];
    print(h_fig,'-depsc',savepath)
    close all
end

fprintf('\n--- Making B-A Plots ');

%% Load data from entire study
load_name = up.paths.filenames.win_data;
loadpath = [up.paths.data_save_folder, up.paths.filenames.win_data, '.mat'];
load(loadpath, load_name);

%% Load algorithms names
load_name = up.paths.filenames.alg_names;
loadpath = [up.paths.data_save_folder, up.paths.filenames.alg_names, '.mat'];
load(loadpath, load_name);

%% Load relevant algorithm els
load_name = 'vortal_results';
loadpath = [up.paths.data_save_folder, up.paths.filenames.vortal_results, '.mat'];
load(loadpath, load_name);

%% Identify the most precise algorithm(s) to make plots for
no_plots_per_sig = 1;
for sig = {'ekg', 'ppg'}
    eval([sig{1,1}, '_els = vortal_results.top_ten.' sig{1,1}, '.alg_nos(1:no_plots_per_sig);']);
    eval([sig{1,1}, '_bias = vortal_results.top_ten.' sig{1,1}, '.bias.val(1:no_plots_per_sig);']);
    eval([sig{1,1}, '_lloa = vortal_results.top_ten.' sig{1,1}, '.lloa.val(1:no_plots_per_sig);']);
    eval([sig{1,1}, '_uloa = vortal_results.top_ten.' sig{1,1}, '.uloa.val(1:no_plots_per_sig);']);
end

rel_els = [ekg_els(:); ppg_els(:)];
rel_bias = [ekg_bias(:); ppg_bias(:)];
rel_lloa = [ekg_lloa(:); ppg_lloa(:)];
rel_uloa = [ekg_uloa(:); ppg_uloa(:)];

rel_names = alg_names.names(rel_els);
rel_sigs = alg_names.sigs(rel_els);

%% Generate plots for each algorithm
for rel_el_no = 1 : length(rel_els)

    alg_no = rel_els(rel_el_no);

    % identify data for this algorithm
    curr_els = win_data.alg_no == alg_no & win_data.snr_log;
    curr_est = win_data.est(curr_els);
    curr_ref = win_data.ref(curr_els);
    curr_bias = rel_bias(rel_el_no);
    curr_lloa = rel_lloa(rel_el_no);
    curr_uloa = rel_uloa(rel_el_no);
    curr_data.ave = nanmean([curr_est(:), curr_ref(:)],2);
    curr_data.error = [curr_est(:) - curr_ref(:)];

    % setup figure
    ftsize = 13;
    min_ave_val = 0;            % xlims
    max_ave_val = 36;
    min_error_val = -10;        % ylims
    max_error_val = 10;
    x_edge_int = 0.2;           % resolution of BA plot
    y_edge_int = 0.2;
    edges1 = [min_ave_val : x_edge_int : max_ave_val];       % locations of individual pixels
    edges2 = [min_error_val : y_edge_int : max_error_val];

    % Make color plot
    h_fig = figure('Position', [200 200 700 350]);
    A2=hist3([curr_data.ave,curr_data.error],'Edges',{edges1 edges2});
    h = fspecial('gaussian', [10 10], 2);
    y = filter2(h, A2');
    y = y./(max(max(y)));
    imagesc(y),
    c_han = colorbar;
    set(c_han,'YTickMode','manual')
    set(c_han, 'YTick',[0,1], 'YTickLabel', {'Min','Max'})

    % mymap = repmat(-1*[-1:0.01:0]', 1,3); colormap(mymap)
    hold on

    % X Ticks
    x_tick_int = 10/x_edge_int;
    x_label_int = (edges1(end)-edges1(1))*x_tick_int/length(edges1);
    xlims = xlim;
    edges1_labels = round( edges1(1) : x_label_int : edges1(end) )';

    x_spec.axis_lims = xlims;
    x_spec.real_lims = [edges1(1), edges1(end)];
    edges1_ticks = convert_real_to_axis_units(edges1_labels, x_spec);

    current_top_of_x_axis = xlims(1) + (0.5*(edges1(2)-edges1(1)));
    % adjust = - current_top_of_x_axis;
    set(gca, 'XTick', edges1_ticks, 'XTickLabel', num2str(edges1_labels))

    % Y Ticks
    y_tick_int = 10/y_edge_int;
    y_label_int = (edges2(end)-edges2(1))*y_tick_int/length(edges2);
    ylims = ylim;
    edges2_labels = round( edges2(1) : y_label_int : edges2(end) )';

    y_spec.axis_lims = ylims;
    y_spec.real_lims = [edges2(1), edges2(end)];
    edges2_ticks = convert_real_to_axis_units(edges2_labels, y_spec);

    current_top_of_y_axis = ylims(1) - (0.5*(edges2(2)-edges2(1)));
    %adjust = - current_top_of_y_axis;
    set(gca, 'YTick', edges2_ticks, 'YTickLabel', num2str(edges2_labels))

    % Axis Labels

    xlabel('Mean: 0.5(RR^{est} + RR^{ref}),  bpm', 'FontSize', ftsize);
    ylabel('Difference:  (RR^{est} - RR^{ref}),  bpm', 'FontSize', ftsize);

    % Bias and LOA Labels

    % xlim([min_ave_val, max_ave_val]), ylim([min_error_val, max_error_val])
    %xlims = xlim;
    %bias_adj = BA_data.bias + adjust;
    %loa_adj = [BA_data.lloa, BA_data.uloa] + adjust;
    axis_bias = convert_real_to_axis_units(curr_bias, y_spec);
    axis_lloa = convert_real_to_axis_units(curr_lloa, y_spec);
    axis_uloa = convert_real_to_axis_units(curr_uloa, y_spec);
    plot(xlims, [axis_bias, axis_bias], 'r')
    plot(xlims, [axis_lloa, axis_lloa], '--r')
    plot(xlims, [axis_uloa, axis_uloa], '--r')
    text(mean(xlims),0.5*axis_lloa,['Lower LOA = ' num2str(curr_lloa,2)],'HorizontalAlignment','center','BackgroundColor',[1 1 1], 'FontSize', ftsize);
    text(mean(xlims),1.2*axis_uloa,['Upper LOA = ' num2str(curr_uloa,2)],'HorizontalAlignment','center','BackgroundColor',[1 1 1], 'FontSize', ftsize);
    text(xlims(2),0.8*axis_bias,['Bias = ' num2str(curr_bias,2)],'HorizontalAlignment','right','BackgroundColor',[1 1 1], 'FontSize', ftsize);
    set(gca, 'FontSize', ftsize)

    set(gcf,'PaperUnits','inches');
    set(gcf,'PaperSize', [6, 3]);
    set(gcf,'PaperPosition',[0 0 6 3]);
    save_name = ['BA_' rel_sigs{rel_el_no}, rel_names{rel_el_no}];
    savepath = [up.paths.plots_save_folder, save_name];
    print(h_fig,'-depsc',savepath)
    close all

end

% %% CDF of abs errors plot
% fprintf('\n--- Making CDF Error Plot');
%
% % Load data (Best alg)
% load_name = up.paths.filenames.win_data;
% loadpath = [up.paths.data_save_folder, up.paths.filenames.win_data, '.mat'];
% load(loadpath, load_name);
% good_els = win_data.sqi & win_data.snr_log & win_data.alg_no == 203 & ~isnan(win_data.est);
% alg.est = win_data.est(good_els);
% alg.ref = win_data.ref(good_els);
% alg.error = alg.est - alg.ref;
%
% % Load data (Moderate alg)
% load_name = up.paths.filenames.win_data;
% loadpath = [up.paths.data_save_folder, up.paths.filenames.win_data, '.mat'];
% load(loadpath, load_name);
% good_els = win_data.sqi & win_data.snr_log & win_data.alg_no == 281 & ~isnan(win_data.est);
% mod_alg.est = win_data.est(good_els);
% mod_alg.ref = win_data.ref(good_els);
% mod_alg.error = mod_alg.est - mod_alg.ref;
%
% % Load data (Imp)
% load_name = up.paths.filenames.win_data;
% loadpath = [up.paths.data_save_folder, up.paths.filenames.win_data_imp, '.mat'];
% load(loadpath, load_name);
% good_els = win_data.sqi & win_data.snr_log & ~isnan(win_data.est) & ~isnan(win_data.est);
% imp.est = win_data.est(good_els);
% imp.ref = win_data.ref(good_els);
% imp.error = imp.est - imp.ref;
%
% % Normal data
% norm.error = normrnd(0,2.5,1,1000);
%
% % Make Figure
% ftsize = 12;
% h_fig = figure('Position', [200, 200, 1200, 550]);
% plot(sort(abs(alg.error)),linspace(0,1,length(alg.error))), hold on
% plot(sort(abs(imp.error)),linspace(0,1,length(imp.error)))
% plot(sort(abs(norm.error)),linspace(0,1,length(norm.error)))
% plot(sort(abs(mod_alg.error)),linspace(0,1,length(mod_alg.error)))
% title('Empirical CDF', 'FontSize', ftsize)
% xlabel('Absolute difference (bpm)', 'FontSize', ftsize)
% ylabel('F(x)', 'FontSize', ftsize)
% xlim([0 40])
% set(gca, 'XTick', [0:10, 15:5:40], 'YTick', [0:0.1:0.9, 0.95, 1.0], 'XTickLabel', {'0','','','','','5','','','','','10','15', '20', '25', '30', '35', '40'});
% legend({'a203', 'impedance', 'normal distribution', 'a281'}, 'Location', 'Best')
% grid on
%
% set(gca, 'FontSize', ftsize)
% save_name = 'Errors CDF';
% savepath = [up.paths.plots_save_folder, save_name];
% savefig(h_fig,savepath)
% close all

fprintf('\n--- Making HR / RR Scatter Plot');

%% Load data from entire study
load_name = up.paths.filenames.win_data;
loadpath = [up.paths.data_save_folder, up.paths.filenames.win_data, '.mat'];
load(loadpath, load_name);
hr = win_data.hr(win_data.comb_log & win_data.ecg_log & win_data.young_log & win_data.alg_no == 1);
rr = win_data.ref(win_data.comb_log & win_data.ecg_log & win_data.young_log & win_data.alg_no == 1);

% Make Figure
h_fig = figure('Position', [200, 200, 900, 400]);

% Plot Histograms
[counts,centers] = hist(rr,20); hold on
counts = counts/max(counts);
scale = 40;
bar(centers,scale*counts, 'c')
[counts,centers] = hist(hr,20);
counts = counts/max(counts);
scale = 5;
barh(centers,scale*counts, 'c')
rr_new = rr; hr_new = hr;

ftsize = 14;
plot(rr_new,hr_new, 'xk')
xlabel('Respiratory Rate [bpm]', 'FontSize', ftsize)
ylabel('Heart Rate [beats per minute]', 'FontSize', ftsize)
set(gca, 'FontSize', ftsize)
set(gca, 'YTick', 0:20:150)
set(gcf,'PaperUnits','inches');
set(gcf,'PaperSize', [9, 4]);
set(gcf,'PaperPosition',[0 0 9 4]);
save_name = up.paths.filenames.hr_rr_scatter;
savepath = [up.paths.plots_save_folder, save_name];
print(h_fig,'-depsc',savepath)
close all

%% Precision and prop of algs using filter / feature

fprintf('\n--- Making Prop of algs, filt/feat plot');

for plot_type = {'est_techs', 'sigs', 'comps'}
    % Load BA data for algs
    if ~strcmp(up.paths.root_data_folder, 'C:\Documents\Data\VORTAL_REST_AND_REC\')
        loadpath = [up.paths.data_save_folder, up.paths.filenames.global_BA, '.mat'];
        load(loadpath);
        rel_res = BA_results.young.prec;
        [~, orders] = sort(rel_res.val);
        rel_res.val = rel_res.val(orders); rel_res.val = rel_res.val(:)';
        rel_res.uci = rel_res.uci(orders); rel_res.uci = rel_res.uci(:)';
        rel_res.lci = rel_res.lci(orders); rel_res.lci = rel_res.lci(:)';
        if strcmp(plot_type{1,1}, 'est_techs')
            rel_els = alg_names.meths.ef(orders)>0;
            rel_res.pos_label = 'Frequency';
            rel_res.neg_label = 'Time';
        elseif strcmp(plot_type{1,1}, 'sigs')
            rel_els = strcmp(alg_names.sigs(orders), 'ECG');
            rel_res.pos_label = 'ECG';
            rel_res.neg_label = 'PPG';
        elseif strcmp(plot_type{1,1}, 'comps')
            rel_res.label1 = 'None';
            rel_res.label2 = 'X_{A1}';
            rel_res.label3 = 'X_{A4}';
            rel_res.label4 = 'E_{F3}';
            rel_els1 = alg_names.meths.xa~= 1 & alg_names.meths.xa~= 4 & alg_names.meths.ef~= 3;
            rel_els2 = alg_names.meths.xa== 1;
            rel_els3 = alg_names.meths.xa== 4;
            rel_els4 = alg_names.meths.ef== 3;
        end

    else
        loadpath = 'C:\Users\pc13\Dropbox\VORTAL\VORTAL_theoret_lims_yhvs\2016_Jan_Submission_to_Phys_Meas\Data\Complete_results_table.csv';
        [num, txt, raw] = xlsread(loadpath);
        headers = raw(1,:);
        % Eliminate IP
        rel_col = find(strcmp(headers, 'Signal'));
        bad_row = find(strcmp(raw(:,rel_col),'IP'));
        raw = raw([1:(bad_row-1), (bad_row+1):length(raw(:,1))], :);
        % Eliminate ones which had a problem with the random effects model (failed to converge)
        rel_col = find(strcmp(headers, 'Problems with Random Effects Model'));
        good_rows = ismember(raw(:,rel_col),'.'); good_rows(1) = 1;
        raw = raw(good_rows,:);
        % Extract relevant data
        rel_col = find(strcmp(headers, 'Overall Rank'));
        ranks = cell2mat(raw(2:end, rel_col));
        [~, rel_res.order] = sort(ranks);
        rel_col = find(strcmp(headers, 'Signal'));
        rel_res.sigs = raw(2:end, rel_col);
        rel_col = find(strcmp(headers, 'Algorithm'));
        rel_res.algs = raw(2:end, rel_col);
        rel_col = find(strcmp(headers, '2SD [bpm]'));
        rel_res.val = cell2mat(raw(2:end, rel_col));
        if strcmp(plot_type{1,1}, 'est_techs')
            rel_els = strfind(rel_res.algs, 'Ef');
            rel_els = not(cellfun('isempty', rel_els));
            rel_res.pos_label = 'Frequency';
            rel_res.neg_label = 'Time';
        elseif strcmp(plot_type{1,1}, 'sigs')
            rel_els = strcmp(rel_res.sigs(rel_res.order), 'ECG');
            rel_res.pos_label = 'ECG';
            rel_res.neg_label = 'PPG';
        elseif strcmp(plot_type{1,1}, 'comps')
            rel_res.label1 = 'None';
            rel_res.label2 = 'X_{A1}';
            rel_res.label3 = 'X_{A4}';
            rel_res.label4 = 'E_{F4}';
            temp = strfind(rel_res.algs, 'Xa1'); rel_els2 = ~cellfun(@isempty,temp);
            temp = strfind(rel_res.algs, 'Xa4'); rel_els3 = ~cellfun(@isempty,temp);
            temp = strfind(rel_res.algs, 'Ef4'); rel_els4 = ~cellfun(@isempty,temp);
            rel_els1 = ~rel_els2 & ~rel_els3 & ~rel_els4;
        end

    end
    orank = 1 : length(rel_res.val); orank = orank(:)';

    % data for hist
    tot = length(orank)+1;
    if strcmp(plot_type{1,1}, 'comps')
        bin_width = (tot/5);
    else
        bin_width = (tot/5);
    end
    bin_ends = 0:bin_width:tot;
    bin_starts = bin_ends(1:(end-1))+1;
    bin_ends = bin_ends(2:end);
    bin_mids = mean([bin_starts(:)'; bin_ends(:)']);
    clear prop*
    if ~strcmp(plot_type{1,1}, 'comps')
        for bin_no = 1 : length(bin_starts)
            prop1(bin_no) = 100*sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no) & rel_els(:))/sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no));
        end
        prop2 = 100 - prop1;
        y_vals = [prop1; prop2];
    else
        for bin_no = 1 : length(bin_starts)
            prop1(bin_no) = 100*sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no) & rel_els1(:))/sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no));
            prop2(bin_no) = 100*sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no) & rel_els2(:))/sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no));
            prop3(bin_no) = 100*sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no) & rel_els3(:))/sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no));
            prop4(bin_no) = 100*sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no) & rel_els4(:))/sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no));
        end
        y_vals = [prop1; prop2; prop3; prop4];
    end

    % setup fig
    h_fig = figure('Position', [200 200 900 550]);
    fontsize = 16;

    % upper plot
    xlims = [min(orank), max(orank)];
    if xlims(2) == 439
        xlims(2) = 440;
    end
    ylims = [0 50];
    h_prec = subplot(2,1,1, 'Position', [0.2 0.61 0.76 0.38]); hold on
    % fill([orank, fliplr(orank)], [rel_res.lci(:)', fliplr(rel_res.uci(:)')], 0.5*[1,1,1]);
    % hold on,
    plot(orank, rel_res.val, 'k', 'LineWidth', 3),
    ylab = ylabel({'2SD', '[bpm]'}, 'FontSize', fontsize, 'Rotation', 0);
    set(ylab, 'Units', 'Normalized', 'Position', [-0.17, 0.3, 0]);
    xlim(xlims)
    ylim(ylims)
    set(gca, 'XTick', [1, 50:50:tot, tot]);
    xlabel('Overall Rank', 'FontSize', fontsize)

    % lower plot (stacked bar)
    h_bar = subplot(2,1,2, 'Position', [0.2 0.10 0.76 0.38]); hold on
    h_bars = bar(bin_mids, y_vals', 'stacked');
    h_bars(1).FaceColor = 0.1*[1,1,1];
    h_bars(2).FaceColor = 0.5*[1,1,1];
    xlim(xlims),
    if ~strcmp(plot_type{1,1}, 'comps')
        ylim([0 100])
    else
        ylim([0 120])
    end
    if strcmp(plot_type{1,1}, 'est_techs')
        ylabel({'% using Frequency- and', 'Time-domain RR estimation'}, 'FontSize', fontsize)
    elseif strcmp(plot_type{1,1}, 'sigs')
        ylabel('% using ECG and PPG', 'FontSize', fontsize)
    elseif strcmp(plot_type{1,1}, 'comps')
        ylab = ylabel({'% using X_{A1},', 'X_{A4}, E_{F4}, or', 'none of these'}, 'FontSize', fontsize, 'Rotation', 0);
        set(ylab, 'Units', 'Normalized', 'Position', [-0.16, 0.33, 0]);
    end
    xlabel('Overall Rank', 'FontSize', fontsize)
    starts = strread(num2str(ceil(bin_starts)),'%s');
    mids = strread(num2str(ceil(bin_mids)),'%s');
    ends = strread(num2str(ceil(bin_ends)),'%s');
    quintiles = strread(num2str(1:length(bin_ends)),'%s');
    for s = 1 : length(ends)
        xtickstr{s} = [starts{s} ' - ' ends{s}];
        %xtickstr{s} = [quintiles{s}, ' (' starts{s} ' - ' ends{s} ')'];
    end
    set(h_bar, 'XTick', bin_mids, 'XTickLabel', xtickstr)

    allAxesInFigure = findall(h_fig,'type','axes');
    set(allAxesInFigure, 'Fontsize', fontsize-4, 'xgrid','on')

    % annotate
    if ~strcmp(plot_type{1,1}, 'comps')
        text(bin_mids(5),15, rel_res.pos_label, 'HorizontalAlignment', 'Center', 'FontSize', fontsize-4, 'Backgroundcolor', 'w')
        text(bin_mids(5),87, rel_res.neg_label, 'HorizontalAlignment', 'Center', 'FontSize', fontsize-4, 'Backgroundcolor', 'w')
    else
        text(bin_mids(1),50, rel_res.label1, 'HorizontalAlignment', 'Center', 'FontSize', fontsize-4, 'Backgroundcolor', 'w')
        text(bin_mids(5),22, rel_res.label2, 'HorizontalAlignment', 'Center', 'FontSize', fontsize-4, 'Backgroundcolor', 'w')
        text(bin_mids(5),62, rel_res.label3, 'HorizontalAlignment', 'Center', 'FontSize', fontsize-4, 'Backgroundcolor', 'w')
        text(bin_mids(5),95, rel_res.label4, 'HorizontalAlignment', 'Center', 'FontSize', fontsize-4, 'Backgroundcolor', 'w')
    end

    % add (a) and (b)
    dim = [.01 .91 .1 .1]; str = '(a)';
    annotation('textbox',dim,'String',str,'FitBoxToText','on','FontSize',fontsize,'LineStyle','none');
    dim = [.01 .43 .1 .1]; str = '(b)';
    annotation('textbox',dim,'String',str,'FitBoxToText','on','FontSize',fontsize,'LineStyle','none');

    set(gcf,'color','w');

    set(gcf,'PaperUnits','inches');
    set(gcf,'PaperSize', [9, 5.5]);
    set(gcf,'PaperPosition',[0 0 9 5.5]);
    save_name = [up.paths.filenames.stacked_bar, '_', plot_type{1,1}];
    savepath = [up.paths.plots_save_folder, save_name];
    print(h_fig,'-depsc',savepath)

    close all

end

%% New joint stacked bar plot

plot_type = {'comps_est_techs'};
% Load BA data for algs
if strcmp(up.paths.root_data_folder, 'C:\Documents\Data\VORTAL_REST_AND_REC\')
    loadpath = 'C:\Users\pc13\Dropbox\VORTAL\VORTAL_theoret_lims_yhvs\2016_Jan_Submission_to_Phys_Meas\Data\Complete_results_table.csv';
    [num, txt, raw] = xlsread(loadpath);
    headers = raw(1,:);
    % Eliminate IP
    rel_col = find(strcmp(headers, 'Signal'));
    bad_row = find(strcmp(raw(:,rel_col),'IP'));
    raw = raw([1:(bad_row-1), (bad_row+1):length(raw(:,1))], :);
    % Eliminate ones which had a problem with the random effects model (failed to converge)
    rel_col = find(strcmp(headers, 'Problems with Random Effects Model'));
    good_rows = ismember(raw(:,rel_col),'.'); good_rows(1) = 1;
    raw = raw(good_rows,:);
    % Extract relevant data
    rel_col = find(strcmp(headers, 'Overall Rank'));
    ranks = cell2mat(raw(2:end, rel_col));
    [~, rel_res.order] = sort(ranks);
    rel_col = find(strcmp(headers, 'Signal'));
    rel_res.sigs = raw(2:end, rel_col);
    rel_col = find(strcmp(headers, 'Algorithm'));
    rel_res.algs = raw(2:end, rel_col);
    rel_col = find(strcmp(headers, '2SD [bpm]'));
    rel_res.val = cell2mat(raw(2:end, rel_col));
    rel_els = strfind(rel_res.algs, 'Ef');
    rel_els = not(cellfun('isempty', rel_els));
    rel_res.pos_label = 'Frequency';
    rel_res.neg_label = 'Time';
    rel_res.label1 = 'None';
    rel_res.label2 = 'X_{A1}';
    rel_res.label3 = 'X_{A4}';
    rel_res.label4 = 'E_{F4}';
    temp = strfind(rel_res.algs, 'Xa1'); rel_els2 = ~cellfun(@isempty,temp);
    temp = strfind(rel_res.algs, 'Xa4'); rel_els3 = ~cellfun(@isempty,temp);
    temp = strfind(rel_res.algs, 'Ef4'); rel_els4 = ~cellfun(@isempty,temp);
    rel_els1 = ~rel_els2 & ~rel_els3 & ~rel_els4;
    orank = 1 : length(rel_res.val); orank = orank(:)';

    % Create first histogram
    tot = length(orank)+1;
    if strcmp(plot_type{1,1}, 'comps')
        bin_width = (tot/5);
    else
        bin_width = (tot/5);
    end
    bin_ends = 0:bin_width:tot;
    bin_starts = bin_ends(1:(end-1))+1;
    bin_ends = bin_ends(2:end);
    bin_mids = mean([bin_starts(:)'; bin_ends(:)']);
    clear prop*
    for bin_no = 1 : length(bin_starts)
        prop1(bin_no) = 100*sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no) & rel_els1(:))/sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no));
        prop2(bin_no) = 100*sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no) & rel_els2(:))/sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no));
        prop3(bin_no) = 100*sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no) & rel_els3(:))/sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no));
        prop4(bin_no) = 100*sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no) & rel_els4(:))/sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no));
    end
    y_vals = [prop1; prop2; prop3; prop4];

    % setup fig
    h_fig = figure('Position', [200 200 900 800]);
    fontsize = 16;

    % upper plot
    xlims = [min(orank), max(orank)];
    if xlims(2) == 439
        xlims(2) = 440;
    end
    ylims = [0 50];
    h_prec = subplot(3,1,1, 'Position', [0.2 0.74 0.76 0.25]); hold on
    plot(orank, rel_res.val, 'k', 'LineWidth', 3),
    ylab = ylabel({'2SD', '[bpm]'}, 'FontSize', fontsize, 'Rotation', 0);
    set(ylab, 'Units', 'Normalized', 'Position', [-0.17, 0.3, 0]);
    xlim(xlims)
    ylim(ylims)
    set(gca, 'XTick', [1, 50:50:tot, tot]);
    xlabel('Overall Rank', 'FontSize', fontsize)

    % mid plot (stacked bar)
    h_bar = subplot(3,1,2, 'Position', [0.2 0.41 0.76 0.25]); hold on
    h_bars = bar(bin_mids, y_vals', 'stacked');
    h_bars(1).FaceColor = 0.1*[1,1,1];
    h_bars(2).FaceColor = 0.5*[1,1,1];
    xlim(xlims),
    ylim([0 120])
    ylab = ylabel({'% using X_{A1},', 'X_{A4}, E_{F4}, or', 'none of these'}, 'FontSize', fontsize, 'Rotation', 0);
    set(ylab, 'Units', 'Normalized', 'Position', [-0.16, 0.33, 0]);
    xlabel('Overall Rank', 'FontSize', fontsize)
    starts = strread(num2str(ceil(bin_starts)),'%s');
    mids = strread(num2str(ceil(bin_mids)),'%s');
    ends = strread(num2str(ceil(bin_ends)),'%s');
    quintiles = strread(num2str(1:length(bin_ends)),'%s');
    for s = 1 : length(ends)
        xtickstr{s} = [starts{s} ' - ' ends{s}];
    end
    set(h_bar, 'XTick', bin_mids, 'XTickLabel', xtickstr)
    % annotate
    text(bin_mids(1),50, rel_res.label1, 'HorizontalAlignment', 'Center', 'FontSize', fontsize-4, 'Backgroundcolor', 'w')
    text(bin_mids(5),25, rel_res.label2, 'HorizontalAlignment', 'Center', 'FontSize', fontsize-4, 'Backgroundcolor', 'w')
    text(bin_mids(5),65, rel_res.label3, 'HorizontalAlignment', 'Center', 'FontSize', fontsize-4, 'Backgroundcolor', 'w')
    text(bin_mids(5),96, rel_res.label4, 'HorizontalAlignment', 'Center', 'FontSize', fontsize-4, 'Backgroundcolor', 'w')

    % lower plot (stacked bar)
    for bin_no = 1 : length(bin_starts)
        prop1(bin_no) = 100*sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no) & rel_els(:))/sum(orank(:)>= bin_starts(bin_no) & orank(:)< bin_ends(bin_no));
    end
    prop2 = 100 - prop1;
    y_vals = [prop1; prop2];
    h_bar = subplot(3,1,3, 'Position', [0.2 0.08 0.76 0.25]); hold on
    h_bars = bar(bin_mids, y_vals', 'stacked');
    h_bars(1).FaceColor = 0.1*[1,1,1];
    h_bars(2).FaceColor = 0.5*[1,1,1];
    xlim(xlims),
    ylim([0 100])
    ylab = ylabel({'% using', 'Frequency- or', 'Time-domain', 'RR estimation'}, 'FontSize', fontsize, 'Rotation', 0);
    set(ylab, 'Units', 'Normalized', 'Position', [-0.16, 0.28, 0]);
    xlabel('Overall Rank', 'FontSize', fontsize)
    starts = strread(num2str(ceil(bin_starts)),'%s');
    mids = strread(num2str(ceil(bin_mids)),'%s');
    ends = strread(num2str(ceil(bin_ends)),'%s');
    quintiles = strread(num2str(1:length(bin_ends)),'%s');
    for s = 1 : length(ends)
        xtickstr{s} = [starts{s} ' - ' ends{s}];
    end
    set(h_bar, 'XTick', bin_mids, 'XTickLabel', xtickstr)
    % annotate
    text(bin_mids(5),15, rel_res.pos_label, 'HorizontalAlignment', 'Center', 'FontSize', fontsize-4, 'Backgroundcolor', 'w')
    text(bin_mids(5),87, rel_res.neg_label, 'HorizontalAlignment', 'Center', 'FontSize', fontsize-4, 'Backgroundcolor', 'w')

    % add (a) and (b) and (c)
    dim = [.01 .91 .1 .1]; str = '(a)';
    annotation('textbox',dim,'String',str,'FitBoxToText','on','FontSize',fontsize,'LineStyle','none');
    dim = [.01 .58 .1 .1]; str = '(b)';
    annotation('textbox',dim,'String',str,'FitBoxToText','on','FontSize',fontsize,'LineStyle','none');
    dim = [.01 .25 .1 .1]; str = '(c)';
    annotation('textbox',dim,'String',str,'FitBoxToText','on','FontSize',fontsize,'LineStyle','none');

    allAxesInFigure = findall(h_fig,'type','axes');
    set(allAxesInFigure, 'Fontsize', fontsize-4, 'xgrid','on')

    set(gcf,'color','w');
    set(gcf,'PaperUnits','inches');
    set(gcf,'PaperSize', [9, 8.0]);
    set(gcf,'PaperPosition',[0 0 9 8.0]);
    save_name = [up.paths.filenames.stacked_bar, '_', plot_type{1,1}];
    savepath = [up.paths.plots_save_folder, save_name];
    print(h_fig,'-depsc',savepath)
    close all

end

end

function axis_units = convert_real_to_axis_units(real_units, spec)

axis_units = spec.axis_lims(1) + ( (real_units - spec.real_lims(1)) * (spec.axis_lims(end) - spec.axis_lims(1))/ (spec.real_lims(end)-spec.real_lims(1)));

end


function test_suite = test_interval_neighborhood()
% tests for cosmo_interval_neighborhood
%
% #   For CoSMoMVPA's copyright information and license terms,   #
% #   see the COPYING file distributed with CoSMoMVPA.           #
    try % assignment of 'localfunctions' is necessary in Matlab >= 2016
        test_functions=localfunctions();
    catch % no problem; early Matlab versions can use initTestSuite fine
    end
    initTestSuite;

function test_interval_neighborhood_basis()
    ds_full=cosmo_synthetic_dataset('type','meeg','size','big');
    ds_full=cosmo_slice(ds_full,ds_full.fa.chan<3,2);
    ds_full=cosmo_dim_prune(ds_full);

    sliceargs={1:7,[1 4 7],[2 6]};
    radii=[0 1 2];
    for k=1:numel(sliceargs)
        slicearg=sliceargs{k};
        narg=numel(slicearg);

        ds=cosmo_slice(ds_full,cosmo_match(ds_full.fa.time,slicearg),2);
        ds=cosmo_dim_prune(ds);
        nf=size(ds.samples,2);
        ds=cosmo_slice(ds,randperm(nf),2);

        for j=1:numel(radii)
            ds=cosmo_slice(ds,randperm(nf),2);
            fa_time=ds.fa.time;

            radius=radii(j);

            nh=cosmo_interval_neighborhood(ds,'time','radius',radius);
            assert(numel(nh.neighbors)==narg);
            assertEqual(nh.fa.time,1:narg);
            assertEqual(nh.a.fdim.values,...
                            {ds_full.a.fdim.values{2}(slicearg)});

            assertEqual(nh.origin.a.fdim,ds.a.fdim);
            assertEqual(nh.origin.fa,ds.fa);

            for m=1:narg
                msk=m-radius<=fa_time & ...
                        fa_time <= m+radius;
                assertEqual(find(msk),nh.neighbors{m});
            end

            % should properly deal with permutations
            ds2=cosmo_slice(ds,randperm(nf),2);
            ds2.a.fdim.values=cellfun(@transpose,ds2.a.fdim.values,...
                                        'UniformOutput',false)';
            nh2=cosmo_interval_neighborhood(ds2,'time','radius',radius);
            assertEqual(nh.fa,nh2.fa);
            assertEqual(nh.a,nh2.a);
            mp=cosmo_align(ds.fa,ds2.fa);
            for m=1:numel(nh.neighbors)
                assertEqual(sort(mp(nh2.neighbors{m})),nh.neighbors{m});
            end
        end
    end

    % test exceptionsclc
    aet=@(x,i)assertExceptionThrown(@()...
                        cosmo_interval_neighborhood(x{:}),i);

    aet({ds},'');
    aet({ds,'time'},'');
    aet({ds,'x',2},'');
    aet({ds,'time',-1},'');
    aet({ds,'time',[2 3]},'');
    aet({ds,'time','radius'},'');
    aet({ds,'time','radius',-1},'');

function test_interval_neighborhood_sa()
    ds=cosmo_synthetic_dataset('type','meeg');
    ds_tr=cosmo_dim_transpose(ds,'time');
    ds_tr=cosmo_slice(ds_tr,randperm(12));
    for radius=0:1
        nbrhood=cosmo_interval_neighborhood(ds_tr,'time','radius',radius);
        unq_time=unique(ds_tr.sa.time);
        for k=1:numel(unq_time)
            msk=abs(ds_tr.sa.time-unq_time(k))<=radius;
            assertEqual(nbrhood.neighbors{k},find(msk)');
        end
    end

function test_interval_neighborhood_fa()
    ds=cosmo_synthetic_dataset('type','meeg','size','big');
    nf=size(ds.samples,2);
    rp=randperm(nf);
    dsp=cosmo_slice(ds,rp,2);

    for radius=0:10
        nhp=cosmo_interval_neighborhood(dsp,'time','radius',radius);
        assertEqual(nhp.a.fdim.values{1},ds.a.fdim.values{2});

        for k=1:numel(nhp.neighbors)
            idx=find(abs(nhp.fa.time(k)-dsp.fa.time)<=radius);
            assertEqual(nhp.neighbors{k},idx);
        end
    end

function test_sparse_interval_neighborhood
    ds=cosmo_synthetic_dataset('size','big');

    % make some holes
    ds=cosmo_slice(ds,ds.fa.i>=4 & ds.fa.i<=16,2);
    ds=cosmo_slice(ds,mod(ds.fa.i,3)<=1,2);

    for radius=0:5
        nh=cosmo_interval_neighborhood(ds,'i','radius',radius);

        n_nbrs=numel(nh.neighbors);

        assert(n_nbrs==numel(ds.a.fdim.values{1}));
        for j=1:n_nbrs
            nbrs=nh.neighbors{j};

            idx=find(j-radius <= ds.fa.i & ds.fa.i <= j+radius);
            assertEqual(nbrs(:),idx(:),sprintf(['not equal with '...
                                        'radius=%d, index=%d'],...
                                        radius,j))
        end
    end


%CODEGENERATOR.GENSLBLOCKFKINE Generate Simulink block for forward kinematics
%
% cGen.genslblockfkine() generates a robot-specific Simulink block to compute
% forward kinematics.
%
% Notes::
% - Is called by CodeGenerator.genfkine if cGen has active flag genslblock.
% - The Simulink blocks are generated and stored in a robot specific block
%   library cGen.slib in the directory cGen.basepath.
% - Blocks are created for intermediate transforms T0, T1 etc. as well.
%
% Author::
%  Joern Malzahn, (joern.malzahn@tu-dortmund.de)
%
% See also CodeGenerator.CodeGenerator, CodeGenerator.genfkine.

% Copyright (C) 2012-2014, by Joern Malzahn
%
% This file is part of The Robotics Toolbox for Matlab (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com
%
% The code generation module emerged during the work on a project funded by
% the German Research Foundation (DFG, BE1569/7-1). The authors gratefully
% acknowledge the financial support.

function genslblockfkine(CGen)

%% Open or create block library
bdclose('all')                                                              % avoid problems with previously loaded libraries
load_system('simulink');
if ~(exist([CGen.slibpath,simulinkext]) == 2)                                  % Create new block library if none exists
 CGen.createnewblocklibrary;
end
open_system(CGen.slibpath);
set_param(CGen.slib,'lock','off');

q = CGen.rob.gencoords;

%% Forward kinematics up to tool center point
CGen.logmsg([datestr(now),'\tGenerating forward kinematics Simulink block up to the end-effector frame']);
symname = 'fkine';
fname = fullfile(CGen.sympath,[symname,'.mat']);

if exist(fname,'file')
    tmpStruct = load(fname);
else
    error ('genslblockfkine:SymbolicsNotFound','Save symbolic expressions to disk first!')
end

blockaddress = [CGen.slib,'/',symname];          % treat intermediate transformations separately
if ~isempty(find_system(CGen.slib,'SearchDepth',1,'Name',symname))                    % Delete previously generated block
    delete_block(blockaddress);
    save_system;
end

symexpr2slblock(blockaddress,tmpStruct.(symname).T,'vars',{q});

CGen.logmsg('\t%s\n',' done!');

%% Individual joint forward kinematics
CGen.logmsg([datestr(now),'\tGenerating forward kinematics Simulink block up to joint']);
for iJoints=1:CGen.rob.n

    CGen.logmsg(' %i ',iJoints);
    symname = ['T0_',num2str(iJoints)];
    fname = fullfile(CGen.sympath,[symname,'.mat']);

    tmpStruct = struct;
    tmpStruct = load(fname);

    funFileName = fullfile(CGen.robjpath,[symname,'.m']);
    q = CGen.rob.gencoords;

    blockaddress = [CGen.slib,'/',symname];          % treat intermediate transformations separately
    if doesblockexist(CGen.slib,symname)
        delete_block(blockaddress);
        save_system;
    end

    symexpr2slblock(blockaddress,tmpStruct.(symname).T,'vars',{q});

end
CGen.logmsg('\t%s\n',' done!');

%% Cleanup
% Arrange blocks
distributeblocks(CGen.slib);

% Lock, save and close library
set_param(CGen.slib,'lock','on');
save_system(CGen.slib,CGen.slibpath);
close_system(CGen.slib);

end