function c = mrdivide(a,b)
% MRDIVIDE implements a/b, where either a or b is an adiff object.
% It is mapped to a./b where possible (i.e. when b has length 1), and
% yields an error otherwise.

if prod(size(b))==1
   c = times(a,1./b);
else
   error('Cannot use / for adiff objects when denominator is nonscalar');
end


function state = initstate(nvars,options,n,itr)
% Initialize swarm condition. Called by PSO.

% Initial particle velocities
state.Velocities = zeros(n,nvars) ;

% Initialize particle positions
state.Population = ...
    repmat(options.PopInitRange(1,:),n,1).*ones(n,nvars) + ...
    repmat((options.PopInitRange(2,:) - options.PopInitRange(1,:)),n,1) ...
    .*rand(n,nvars) ;

% Initialize the global and local fitness to the worst possible
state.fGlobalBest = ones(itr,1)*inf; % Global best fitness score
state.fLocalBests = ones(n,1)*inf ; % Individual best fitness score

% Initialize global and local best positions
state.xGlobalBest = ones(1,nvars)*inf ;
state.xLocalBests = ones(n,nvars)*inf ;


function [bndinfo, pbim, gconf, bndinfo_all] =  processIm2Occlusion(im, varargin)

%% Set parameters

%% Read image

if max(size(im))>640
  fprintf('Warning, this image is pretty big...\n');
  %im = imresize(im, 640/max(size(im)), 'bilinear');
end

%% Get occlusion info
[bndinfo, pbim, gconf, bndinfo_all] = im2boundariesTopLevel(im);
gconf = single(gconf);
pbim = single(pbim);

%save(outname, 'bndinfo', 'pbim', 'gconf', 'bndinfo_all');


classdef Violin < handle
    % Violin creates violin plots for some data
    %   A violin plot is an easy to read substitute for a box plot
    %   that replaces the box shape with a kernel density estimate of
    %   the data, and optionally overlays the data points itself.
    %   It is also possible to provide two sets of data which are supposed
    %   to be compared by plotting each column of the two datasets together
    %   on each side of the violin.
    %
    %   Additional constructor parameters include the width of the
    %   plot, the bandwidth of the kernel density estimation, the
    %   X-axis position of the violin plot, and the categories.
    %
    %   Use violinplot for a
    %   boxplot-like wrapper for
    %   interactive plotting.
    %
    %   See for more information on Violin Plots:
    %   J. L. Hintze and R. D. Nelson, "Violin plots: a box
    %   plot-density trace synergism," The American Statistician, vol.
    %   52, no. 2, pp. 181-184, 1998.
    %
    % Violin Properties:
    %    ViolinColor    - Fill color of the violin area and data points.
    %                     Can be either a matrix nx3 or an array of up to two
    %                     cells containing nx3 matrices.
    %                     Defaults to the next default color cycle.
    %    ViolinAlpha    - Transparency of the violin area and data points.
    %                     Can be either a single scalar value or an array of
    %                     up to two cells containing scalar values.
    %                     Defaults to 0.3.
    %    EdgeColor      - Color of the violin area outline.
    %                     Defaults to [0.5 0.5 0.5]
    %    BoxColor       - Color of the box, whiskers, and the outlines of
    %                     the median point and the notch indicators.
    %                     Defaults to [0.5 0.5 0.5]
    %    MedianColor    - Fill color of the median and notch indicators.
    %                     Defaults to [1 1 1]
    %    ShowData       - Whether to show data points.
    %                     Defaults to true
    %    ShowNotches    - Whether to show notch indicators.
    %                     Defaults to false
    %    ShowMean       - Whether to show mean indicator.
    %                     Defaults to false
    %    ShowBox        - Whether to show the box.
    %                     Defaults to true
    %    ShowMedian     - Whether to show the median indicator.
    %                     Defaults to true
    %    ShowWhiskers   - Whether to show the whiskers
    %                     Defaults to true
    %    HalfViolin     - Whether to do a half violin(left, right side) or
    %                     full. Defaults to full.
    %    QuartileStyle - Option on how to display quartiles, with a
    %                     boxplot, shadow or none. Defaults to boxplot.
    %    DataStyle      - Defines the style to show the data points. Opts:
    %                     'scatter', 'histogram' or 'none'. Default is 'scatter'.
    %
    %
    % Violin Children:
    %    ScatterPlot    - scatter plot of the data points
    %    ScatterPlot2   - scatter second plot of the data points
    %    ViolinPlot     - fill plot of the kernel density estimate
    %    ViolinPlot2    - fill second plot of the kernel density estimate
    %    BoxPlot        - fill plot of the box between the quartiles
    %    WhiskerPlot    - line plot between the whisker ends
    %    MedianPlot     - scatter plot of the median (one point)
    %    NotchPlots     - scatter plots for the notch indicators
    %    MeanPlot       - line plot at mean value

    % Copyright (c) 2016, Bastian Bechtold
    % This code is released under the terms of the BSD 3-clause license

    properties (Access=public)
        ScatterPlot     % scatter plot of the data points
        ScatterPlot2    % comparison scatter plot of the data points
        ViolinPlot      % fill plot of the kernel density estimate
        ViolinPlot2     % comparison fill plot of the kernel density estimate
        BoxPlot         % fill plot of the box between the quartiles
        WhiskerPlot     % line plot between the whisker ends
        MedianPlot      % scatter plot of the median (one point)
        NotchPlots      % scatter plots for the notch indicators
        MeanPlot        % line plot of the mean (horizontal line)
        HistogramPlot   % histogram of the data
        ViolinPlotQ     % fill plot of the Quartiles as shadow
    end

    properties (Dependent=true)
        ViolinColor         % fill color of the violin area and data points
        ViolinAlpha         % transparency of the violin area and data points
        MarkerSize          % marker size for the data dots
        MedianMarkerSize    % marker size for the median dot
        LineWidth           % linewidth of the median plot
        EdgeColor           % color of the violin area outline
        BoxColor            % color of box, whiskers, and median/notch edges
        BoxWidth            % width of box between the quartiles in axis space (default 10% of Violin plot width, 0.03)
        MedianColor         % fill color of median and notches
        ShowData            % whether to show data points
        ShowNotches         % whether to show notch indicators
        ShowMean            % whether to show mean indicator
        ShowBox             % whether to show the box
        ShowMedian          % whether to show the median line
        ShowWhiskers        % whether to show the whiskers
        HalfViolin          % whether to do a half violin(left, right side) or full
    end

    methods
        function obj = Violin(data, pos, varargin)
            %Violin plots a violin plot of some data at pos
            %   VIOLIN(DATA, POS) plots a violin at x-position POS for
            %   a vector of DATA points.
            %
            %   VIOLIN(..., 'PARAM1', val1, 'PARAM2', val2, ...)
            %   specifies optional name/value pairs:
            %     'Width'        Width of the violin in axis space.
            %                    Defaults to 0.3
            %     'Bandwidth'    Bandwidth of the kernel density
            %                    estimate. Should be between 10% and
            %                    40% of the data range.
            %     'ViolinColor'  Fill color of the violin area
            %                    and data points.Can be either a matrix
            %                    nx3 or an array of up to two cells
            %                    containing nx3 matrices.
            %     'ViolinAlpha'  Transparency of the violin area and data
            %                    points. Can be either a single scalar
            %                    value or an array of up to two cells
            %                    containing scalar values. Defaults to 0.3.
            %     'MarkerSize'   Size of the data points, if shown.
            %                    Defaults to 24
            % 'MedianMarkerSize' Size of the median indicator, if shown.
            %                    Defaults to 36
            %     'EdgeColor'    Color of the violin area outline.
            %                    Defaults to [0.5 0.5 0.5]
            %     'BoxColor'     Color of the box, whiskers, and the
            %                    outlines of the median point and the
            %                    notch indicators. Defaults to
            %                    [0.5 0.5 0.5]
            %     'MedianColor'  Fill color of the median and notch
            %                    indicators. Defaults to [1 1 1]
            %     'ShowData'     Whether to show data points.
            %                    Defaults to true
            %     'ShowNotches'  Whether to show notch indicators.
            %                    Defaults to false
            %     'ShowMean'     Whether to show mean indicator.
            %                    Defaults to false
            %     'ShowBox'      Whether to show the box
            %                    Defaults to true
            %     'ShowMedian'   Whether to show the median line
            %                    Defaults to true
            %     'ShowWhiskers' Whether to show the whiskers
            %                    Defaults to true
            %     'HalfViolin'   Whether to do a half violin(left, right side) or
            %                    full. Defaults to full.
            %   'QuartileStyle'  Option on how to display quartiles, with a
            %                    boxplot or as a shadow. Defaults to boxplot.
            %     'DataStyle'    Defines the style to show the data points. Opts:
            %                   'scatter', 'histogram' or 'none'. Default is 'Scatter'.

            st = dbstack; % get the calling function for reporting errors
            namefun = st.name;
            args = obj.checkInputs(data, pos, varargin{:});

            if length(data)==1
                data2 = [];
                data = data{1};

            else
                data2 = data{2};
                data = data{1};
            end

            if isempty(args.ViolinColor)
                Release= strsplit(version('-release'), {'a','b'}); %Check release
                if str2num(Release{1})> 2019 || strcmp(version('-release'), '2019b')
                     C = colororder;
                else
                     C = lines;
                end

                if pos > length(C)
                    C = lines;
                end
                args.ViolinColor = {repmat(C,ceil(size(data,2)/length(C)),1)};
            end

            data = data(not(isnan(data)));
            data2 = data2(not(isnan(data2)));
            if numel(data) == 1
                obj.MedianPlot = scatter(pos, data, 'filled');
                obj.MedianColor = args.MedianColor;
                obj.MedianPlot.MarkerEdgeColor = args.EdgeColor;
                return
            end

            hold('on');

            %% Calculate kernel density estimation for the violin
            [density, value, width] = obj.calcKernelDensity(data, args.Bandwidth, args.Width);

            % also calculate the kernel density of the comparison data if
            % provided
            if ~isempty(data2)
                [densityC, valueC, widthC] = obj.calcKernelDensity(data2, args.Bandwidth, args.Width);
            end

            %% Plot the data points within the violin area
            if length(density) > 1
                [~, unique_idx] = unique(value);
                jitterstrength = interp1(value(unique_idx), density(unique_idx)*width, data, 'linear','extrap');
            else % all data is identical:
                jitterstrength = density*width;
            end
            if isempty(data2) % if no comparison data
                jitter = 2*(rand(size(data))-0.5); % both sides
            else
                jitter = rand(size(data)); % only right side
            end
            switch args.HalfViolin % this is more modular
                case 'left'
                    jitter = -1*(rand(size(data))); %left
                case 'right'
                    jitter = 1*(rand(size(data))); %right
                case 'full'
                    jitter = 2*(rand(size(data))-0.5);
            end
            % Make scatter plot
            switch args.DataStyle
                case 'scatter'
                    if ~isempty(data2)
                        jitter = 1*(rand(size(data))); %right
                        obj.ScatterPlot = ...
                            scatter(pos + jitter.*jitterstrength, data, args.MarkerSize, 'filled');
                        % plot the data points within the violin area
                        if length(densityC) > 1
                            jitterstrength = interp1(valueC, densityC*widthC, data2);
                        else % all data is identical:
                            jitterstrength = densityC*widthC;
                        end
                        jitter = -1*rand(size(data2));% left
                        obj.ScatterPlot2 = ...
                            scatter(pos + jitter.*jitterstrength, data2, args.MarkerSize, 'filled');
                    else
                        obj.ScatterPlot = ...
                            scatter(pos + jitter.*jitterstrength, data, args.MarkerSize, 'filled');

                    end
                case 'histogram'
                    [counts,edges] = histcounts(data, size(unique(data),1));
                    switch args.HalfViolin
                        case 'right'
                            obj.HistogramPlot= plot([pos-((counts')/max(counts))*max(jitterstrength)*2, pos*ones(size(counts,2),1)]',...
                                [edges(1:end-1)+max(diff(edges))/2; edges(1:end-1)+max(diff(edges))/2],'-','LineWidth',1, 'Color', 'k');
                        case 'left'
                            obj.HistogramPlot= plot([pos*ones(size(counts,2),1), pos+((counts')/max(counts))*max(jitterstrength)*2]',...
                                [edges(1:end-1)+max(diff(edges))/2; edges(1:end-1)+max(diff(edges))/2],'-','LineWidth',1, 'Color', 'k');
                        otherwise
                            fprintf([namefun, ' No histogram/bar plot option available for full violins, as it would look overcrowded.\n'])
                    end
                case 'none'
            end

            %% Plot the violin
            halfViol= ones(1, size(density,2));
            if isempty(data2) % if no comparison data
                switch args.HalfViolin
                    case 'right'
                        obj.ViolinPlot =  ... % plot color will be overwritten later
                            fill([pos+density*width halfViol*pos], ...
                            [value value(end:-1:1)], [1 1 1]);
                    case 'left'
                        obj.ViolinPlot =  ... % plot color will be overwritten later
                            fill([halfViol*pos pos-density(end:-1:1)*width], ...
                            [value value(end:-1:1)], [1 1 1]);
                    case 'full'
                        obj.ViolinPlot =  ... % plot color will be overwritten later
                            fill([pos+density*width pos-density(end:-1:1)*width], ...
                            [value value(end:-1:1)], [1 1 1]);
                end
            else
                % plot right half of the violin
                obj.ViolinPlot =  ...
                    fill([pos+density*width pos-density(1)*width], ...
                    [value value(1)], [1 1 1]);
                % plot left half of the violin
                obj.ViolinPlot2 =  ...
                    fill([pos-densityC(end)*widthC pos-densityC(end:-1:1)*widthC], ...
                    [valueC(end) valueC(end:-1:1)], [1 1 1]);
            end

            %% Plot the quartiles within the violin
            quartiles = quantile(data, [0.25, 0.5, 0.75]);
            flat= [halfViol*pos halfViol*pos];
            switch args.QuartileStyle
                case 'shadow'
                    switch args.HalfViolin
                        case 'right'
                            w = [pos+density*width halfViol*pos];
                            h= [value value(end:-1:1)];
                        case 'left'
                            w = [halfViol*pos pos-density(end:-1:1)*width];
                            h= [value value(end:-1:1)];
                        case 'full'
                            w = [pos+density*width pos-density(end:-1:1)*width];
                            h= [value value(end:-1:1)];
                    end
                    w(h<quartiles(1))=flat(h<quartiles(1));
                    w(h>quartiles(3))=flat((h>quartiles(3)));
                    obj.ViolinPlotQ =  ... % plot color will be overwritten later
                        fill(w, ...
                        h, [1 1 1]);
                case 'boxplot'
                    obj.BoxPlot = ... % plot color will be overwritten later
                        fill(pos+[-1,1,1,-1]*args.BoxWidth, ...
                        [quartiles(1) quartiles(1) quartiles(3) quartiles(3)], ...
                        [1 1 1]);
                case 'none'
            end

            %% Plot the data mean
            meanValue = mean(data);
            if length(density) > 1
                [~, unique_idx] = unique(value);
                meanDensityWidth = interp1(value(unique_idx), density(unique_idx), meanValue, 'linear','extrap')*width;
            else % all data is identical:
                meanDensityWidth = density*width;
            end
            if meanDensityWidth<args.BoxWidth/2
                meanDensityWidth=args.BoxWidth/2;
            end
            switch args.HalfViolin
                case 'right'
                    obj.MeanPlot = plot(pos+[0,1].*meanDensityWidth, ...
                        [meanValue, meanValue]);
                case 'left'
                    obj.MeanPlot = plot(pos+[-1,0].*meanDensityWidth, ...
                        [meanValue, meanValue]);
                case 'full'
                    obj.MeanPlot = plot(pos+[-1,1].*meanDensityWidth, ...
                        [meanValue, meanValue]);
            end
            obj.MeanPlot.LineWidth = 1;

            %% Plot the median, notch, and whiskers
            IQR = quartiles(3) - quartiles(1);
            lowhisker = quartiles(1) - 1.5*IQR;
            lowhisker = max(lowhisker, min(data(data > lowhisker)));
            hiwhisker = quartiles(3) + 1.5*IQR;
            hiwhisker = min(hiwhisker, max(data(data < hiwhisker)));
            if ~isempty(lowhisker) && ~isempty(hiwhisker)
                obj.WhiskerPlot = plot([pos pos], [lowhisker hiwhisker]);
            end

            % Median
            obj.MedianPlot = scatter(pos, quartiles(2), args.MedianMarkerSize, [1 1 1], 'filled');

            % Notches
            obj.NotchPlots = ...
                scatter(pos, quartiles(2)-1.57*IQR/sqrt(length(data)), ...
                [], [1 1 1], 'filled', '^');
            obj.NotchPlots(2) = ...
                scatter(pos, quartiles(2)+1.57*IQR/sqrt(length(data)), ...
                [], [1 1 1], 'filled', 'v');

            %% Set graphical preferences
            obj.EdgeColor = args.EdgeColor;
            obj.MedianPlot.LineWidth = args.LineWidth;
            obj.BoxColor = args.BoxColor;
            obj.BoxWidth = args.BoxWidth;
            obj.MedianColor = args.MedianColor;
            obj.ShowData = args.ShowData;
            obj.ShowNotches = args.ShowNotches;
            obj.ShowMean = args.ShowMean;
            obj.ShowBox = args.ShowBox;
            obj.ShowMedian = args.ShowMedian;
            obj.ShowWhiskers = args.ShowWhiskers;

            if not(isempty(args.ViolinColor))
                if size(args.ViolinColor{1},1) > 1
                    ViolinColor{1} = args.ViolinColor{1}(pos,:);
                else
                    ViolinColor{1} = args.ViolinColor{1};
                end
                if length(args.ViolinColor)==2
                    if size(args.ViolinColor{2},1) > 1
                        ViolinColor{2} = args.ViolinColor{2}(pos,:);
                    else
                        ViolinColor{2} = args.ViolinColor{2};
                    end
                else
                    ViolinColor{2} = ViolinColor{1};
                end
            else
                % defaults
                if args.scpltBool
                    ViolinColor{1} = obj.ScatterPlot.CData;
                else
                    ViolinColor{1} = [0 0 0];
                end
                ViolinColor{2} = [0 0 0];
            end
            obj.ViolinColor = ViolinColor;

            if not(isempty(args.ViolinAlpha))
                if length(args.ViolinAlpha{1})>1
                    error('Only scalar values are accepted for the alpha color channel');
                else
                    ViolinAlpha{1} = args.ViolinAlpha{1};
                end
                if length(args.ViolinAlpha)==2
                    if length(args.ViolinAlpha{2})>1
                        error('Only scalar values are accepted for the alpha color channel');
                    else
                        ViolinAlpha{2} = args.ViolinAlpha{2};
                    end
                else
                    ViolinAlpha{2} = ViolinAlpha{1}/2;  % default unless specified
                end
            else
                % default
                ViolinAlpha = {1,1};
            end
            obj.ViolinAlpha = ViolinAlpha;

        end

        %% SET METHODS
        function set.EdgeColor(obj, color)
            if ~isempty(obj.ViolinPlot)
                obj.ViolinPlot.EdgeColor = color;
                obj.ViolinPlotQ.EdgeColor = color;
                if ~isempty(obj.ViolinPlot2)
                    obj.ViolinPlot2.EdgeColor = color;
                end
            end
        end

        function color = get.EdgeColor(obj)
            if ~isempty(obj.ViolinPlot)
                color = obj.ViolinPlot.EdgeColor;
            end
        end

        function set.MedianColor(obj, color)
            obj.MedianPlot.MarkerFaceColor = color;
            if ~isempty(obj.NotchPlots)
                obj.NotchPlots(1).MarkerFaceColor = color;
                obj.NotchPlots(2).MarkerFaceColor = color;
            end
        end

        function color = get.MedianColor(obj)
            color = obj.MedianPlot.MarkerFaceColor;
        end

        function set.BoxColor(obj, color)
            if ~isempty(obj.BoxPlot)
                obj.BoxPlot.FaceColor = color;
                obj.BoxPlot.EdgeColor = color;
                obj.WhiskerPlot.Color = color;
                obj.MedianPlot.MarkerEdgeColor = color;
                obj.NotchPlots(1).MarkerFaceColor = color;
                obj.NotchPlots(2).MarkerFaceColor = color;
            elseif  ~isempty(obj.ViolinPlotQ)
                obj.WhiskerPlot.Color = color;
                obj.MedianPlot.MarkerEdgeColor = color;
                obj.NotchPlots(1).MarkerFaceColor = color;
                obj.NotchPlots(2).MarkerFaceColor = color;
            end
        end

        function color = get.BoxColor(obj)
            if ~isempty(obj.BoxPlot)
                color = obj.BoxPlot.FaceColor;
            end
        end

        function set.BoxWidth(obj,width)
            if ~isempty(obj.BoxPlot)
                pos=mean(obj.BoxPlot.XData);
                obj.BoxPlot.XData=pos+[-1,1,1,-1]*width;
            end
        end

        function width = get.BoxWidth(obj)
            width=max(obj.BoxPlot.XData)-min(obj.BoxPlot.XData);
        end

        function set.ViolinColor(obj, color)
            obj.ViolinPlot.FaceColor = color{1};
            obj.ScatterPlot.MarkerFaceColor = color{1};
            obj.MeanPlot.Color = color{1};
            if ~isempty(obj.ViolinPlot2)
                obj.ViolinPlot2.FaceColor = color{2};
                obj.ScatterPlot2.MarkerFaceColor = color{2};
            end
            if  ~isempty(obj.ViolinPlotQ)
                obj.ViolinPlotQ.FaceColor = color{1};
            end
            for idx = 1: size(obj.HistogramPlot,1)
                obj.HistogramPlot(idx).Color = color{1};
            end
        end

        function color = get.ViolinColor(obj)
            color{1} = obj.ViolinPlot.FaceColor;
            if ~isempty(obj.ViolinPlot2)
                color{2} = obj.ViolinPlot2.FaceColor;
            end
        end

        function set.ViolinAlpha(obj, alpha)
            obj.ViolinPlotQ.FaceAlpha = .65;
            obj.ViolinPlot.FaceAlpha = alpha{1};
            obj.ScatterPlot.MarkerFaceAlpha = 1;
            if ~isempty(obj.ViolinPlot2)
                obj.ViolinPlot2.FaceAlpha = alpha{2};
                obj.ScatterPlot2.MarkerFaceAlpha = 1;
            end
        end

        function alpha = get.ViolinAlpha(obj)
            alpha{1} = obj.ViolinPlot.FaceAlpha;
            if ~isempty(obj.ViolinPlot2)
                alpha{2} = obj.ViolinPlot2.FaceAlpha;
            end
        end

        function set.ShowData(obj, yesno)
            if yesno
                obj.ScatterPlot.Visible = 'on';
                for idx = 1: size(obj.HistogramPlot,1)
                    obj.HistogramPlot(idx).Visible = 'on';
                end
            else
                obj.ScatterPlot.Visible = 'off';
                for idx = 1: size(obj.HistogramPlot,1)
                    obj.HistogramPlot(idx).Visible = 'off';
                end
            end
            if ~isempty(obj.ScatterPlot2)
                obj.ScatterPlot2.Visible = obj.ScatterPlot.Visible;
            end

        end

        function yesno = get.ShowData(obj)
            if ~isempty(obj.ScatterPlot)
                yesno = strcmp(obj.ScatterPlot.Visible, 'on');
            end
        end

        function set.ShowNotches(obj, yesno)
            if ~isempty(obj.NotchPlots)
                if yesno
                    obj.NotchPlots(1).Visible = 'on';
                    obj.NotchPlots(2).Visible = 'on';
                else
                    obj.NotchPlots(1).Visible = 'off';
                    obj.NotchPlots(2).Visible = 'off';
                end
            end
        end

        function yesno = get.ShowNotches(obj)
            if ~isempty(obj.NotchPlots)
                yesno = strcmp(obj.NotchPlots(1).Visible, 'on');
            end
        end

        function set.ShowMean(obj, yesno)
            if ~isempty(obj.MeanPlot)
                if yesno
                    obj.MeanPlot.Visible = 'on';
                else
                    obj.MeanPlot.Visible = 'off';
                end
            end
        end

        function yesno = get.ShowMean(obj)
            if ~isempty(obj.BoxPlot)
                yesno = strcmp(obj.BoxPlot.Visible, 'on');
            end
        end

        function set.ShowBox(obj, yesno)
            if ~isempty(obj.BoxPlot)
                if yesno
                    obj.BoxPlot.Visible = 'on';
                else
                    obj.BoxPlot.Visible = 'off';
                end
            end
        end

        function yesno = get.ShowBox(obj)
            if ~isempty(obj.BoxPlot)
                yesno = strcmp(obj.BoxPlot.Visible, 'on');
            end
        end

        function set.ShowMedian(obj, yesno)
            if ~isempty(obj.MedianPlot)
                if yesno
                    obj.MedianPlot.Visible = 'on';
                else
                    obj.MedianPlot.Visible = 'off';
                end
            end
        end

        function yesno = get.ShowMedian(obj)
            if ~isempty(obj.MedianPlot)
                yesno = strcmp(obj.MedianPlot.Visible, 'on');
            end
        end

        function set.ShowWhiskers(obj, yesno)
            if ~isempty(obj.WhiskerPlot)
                if yesno
                    obj.WhiskerPlot.Visible = 'on';
                else
                    obj.WhiskerPlot.Visible = 'off';
                end
            end
        end

        function yesno = get.ShowWhiskers(obj)
            if ~isempty(obj.WhiskerPlot)
                yesno = strcmp(obj.WhiskerPlot.Visible, 'on');
            end
        end

    end

    methods (Access=private)
        function results = checkInputs(~, data, pos, varargin)
            isscalarnumber = @(x) (isnumeric(x) & isscalar(x));
            p = inputParser();
            p.addRequired('Data', @(x)isnumeric(vertcat(x{:})));
            p.addRequired('Pos', isscalarnumber);
            p.addParameter('Width', 0.3, isscalarnumber);
            p.addParameter('Bandwidth', [], isscalarnumber);
            iscolor = @(x) (isnumeric(x) & size(x,2) == 3);
            p.addParameter('ViolinColor', [], @(x)iscolor(vertcat(x{:})));
            p.addParameter('MarkerSize', 24, @isnumeric);
            p.addParameter('MedianMarkerSize', 36, @isnumeric);
            p.addParameter('LineWidth', 0.75, @isnumeric);
            p.addParameter('BoxColor', [0.5 0.5 0.5], iscolor);
            p.addParameter('BoxWidth', 0.01, isscalarnumber);
            p.addParameter('EdgeColor', [0.5 0.5 0.5], iscolor);
            p.addParameter('MedianColor', [1 1 1], iscolor);
            p.addParameter('ViolinAlpha', {0.3,0.15}, @(x)isnumeric(vertcat(x{:})));
            isscalarlogical = @(x) (islogical(x) & isscalar(x));
            p.addParameter('ShowData', true, isscalarlogical);
            p.addParameter('ShowNotches', false, isscalarlogical);
            p.addParameter('ShowMean', false, isscalarlogical);
            p.addParameter('ShowBox', true, isscalarlogical);
            p.addParameter('ShowMedian', true, isscalarlogical);
            p.addParameter('ShowWhiskers', true, isscalarlogical);
            validSides={'full', 'right', 'left'};
            checkSide = @(x) any(validatestring(x, validSides));
            p.addParameter('HalfViolin', 'full', checkSide);
            validQuartileStyles={'boxplot', 'shadow', 'none'};
            checkQuartile = @(x)any(validatestring(x, validQuartileStyles));
            p.addParameter('QuartileStyle', 'boxplot', checkQuartile);
            validDataStyles = {'scatter', 'histogram', 'none'};
            checkStyle = @(x)any(validatestring(x, validDataStyles));
            p.addParameter('DataStyle', 'scatter', checkStyle);

            p.parse(data, pos, varargin{:});
            results = p.Results;
        end
    end

    methods (Static)
        function [density, value, width] = calcKernelDensity(data, bandwidth, width)
            if isempty(data)
                error('Empty input data');
            end
            [density, value] = ksdensity(data, 'bandwidth', bandwidth);
            density = density(value >= min(data) & value <= max(data));
            value = value(value >= min(data) & value <= max(data));
            value(1) = min(data);
            value(end) = max(data);
            value = [value(1)*(1-1E-5), value, value(end)*(1+1E-5)];
            density = [0, density, 0];

            % all data is identical
            if min(data) == max(data)
                density = 1;
                value= mean(value);
            end

            width = width/max(density);
        end
    end
end


function valstr = m2json(val)
    if isstruct(val)
        valstr = struct2json(val);
    elseif iscell(val)
        valstr = cell2json(val);
    elseif isa(val, 'numeric')
        sz = size(val);
        if length(find(sz>1))>1 % 2D or higher array
            valstr = '';
            for i = 1:sz(1)
                valsubstr = [sprintf('%.15g, ', val(i,:))];
                valsubstr = valsubstr(1:(end-2));
                valstr = [valstr ', [' valsubstr ']'];
            end
            valstr = valstr(3:end); % trail leading commas
        else
            valstr = [sprintf('%.15g, ', val)];
            valstr = valstr(1:(end-2));
        end
        if length(val)>1
            valstr = ['[' valstr ']'];
        elseif length(val) == 0
            valstr = '[]';
        end
        valstr = strrep(valstr, 'Inf', 'null');
        valstr = strrep(valstr, 'NaN', 'null');
    elseif ischar(val)
        if size(val, 1) > 1
            valstr = cell2json(cellstr(val));
        else
            val = checkescape(val); %add escape characters
            valstr = ['"' val '"'];
        end
    elseif islogical(val)
        if val
            valstr = 'true';
        else
            valstr = 'false';
        end
    else
        valstr = ''; % wtf is it?
    end


function [img1_2,img1_4,img1_8,img2_2,img2_4,img2_8,img2mask_2,img2mask_4,img2mask_8]=GPReduceAll(img1,img2,img2mask,levels,displayflag)
%
% [img1_2,img1_4,img1_8,img2_2,img2_4,img2_8]=GPReduceAll(img1,img2,levels)
%

global Gimg1 Gimg2 Gimg2mask Gimg1_2 Gimg1_4 Gimg1_8 Gimg2_2 Gimg2_4 Gimg2_8 Gimg2mask_2 Gimg2mask_4 Gimg2mask_8;

if ~isequal(img1,Gimg1) || isempty(Gimg1_2)
	disp('Down sampling image #1 for step 2...');
% 	if( size(img1,3) > size(img2,3) & size(img2,3)==16 )
% 		Gimg1_2 = GPReduce2(img1,16,displayflag);
% 	else
		Gimg1_2 = GPReduce(img1,displayflag);
% 	end
end

if ~isequal(img2,Gimg2) || isempty(Gimg2_2)
	disp('Down sampling image #2 for step 2...');
	Gimg2_2 = GPReduce(img2,displayflag);
end

if ~isequal(img2mask,Gimg2mask) || isempty(Gimg2mask_2)
	if isempty(img2mask)
		Gimg2mask_2 = [];
	else
		disp('Down sampling image #2 mask for step 2...');
		Gimg2mask_2 = GPReduce(img2mask,displayflag);
	end
end

if levels > 2
	if ~isequal(img1,Gimg1) || isempty(Gimg1_4)
		disp('Down sampling image #1 for step 3...');
% 		if( size(img1,3) > size(img2,3) & size(img2,3)==16 )
% 			Gimg1_4 = GPReduce2(Gimg1_2,8,displayflag);
% 		else
			Gimg1_4 = GPReduce(Gimg1_2,displayflag);
% 		end
	end

	if ~isequal(img2,Gimg2) || isempty(Gimg2_4)
		disp('Down sampling image #2 for step 3...');
		Gimg2_4 = GPReduce(Gimg2_2,displayflag);
	end

	if ~isequal(img2mask,Gimg2mask) || isempty(Gimg2mask_4)
		if isempty(img2mask)
			Gimg2mask_4 = [];
		else
			disp('Down sampling image #2 mask for step 3...');
			Gimg2mask_4 = GPReduce(Gimg2mask_2,displayflag);
		end
	end
end

if levels > 3
	if ~isequal(img1,Gimg1) || isempty(Gimg1_8)
		disp('Down sampling image #1 for step 4...');
% 		if( size(img1,3) > size(img2,3) & size(img2,3)==16 )
% 			Gimg1_8 = GPReduce2(Gimg1_4,4,displayflag);
% 		else
			Gimg1_8 = GPReduce(Gimg1_4,displayflag);
% 		end
	end

	if ~isequal(img2,Gimg2) || isempty(Gimg2_8)
		disp('Down sampling image #2 for step 4...');
		Gimg2_8 = GPReduce(Gimg2_4,displayflag);
	end

	if ~isequal(img2mask,Gimg2mask) || isempty(Gimg2mask_8)
		if isempty(img2mask)
			Gimg2mask_8 = [];
		else
			disp('Down sampling image #2 mask for step 4...');
			Gimg2mask_8 = GPReduce(Gimg2mask_4,displayflag);
		end
	end
end

Gimg1 = img1;
Gimg2 = img2;
Gimg2mask = img2mask;

img1_2 = Gimg1_2;
img1_4 = Gimg1_4;
img1_8 = Gimg1_8;
img2_2 = Gimg2_2;
img2_4 = Gimg2_4;
img2_8 = Gimg2_8;
img2mask_2 = Gimg2mask_2;
img2mask_4 = Gimg2mask_4;
img2mask_8 = Gimg2mask_8;

clear global Gimg1 Gimg2 Gimg2mask Gimg1_2 Gimg1_4 Gimg1_8 Gimg2_2 Gimg2_4 Gimg2_8 Gimg2mask_2 Gimg2mask_4 Gimg2mask_8;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Spherical Harmonic Modeling and Analysis Toolkit (SPHARM-MAT) is a 3D
% shape modeling and analysis toolkit.
% It is a software package developed at Shenlab in Center for Neuroimaging,
% Indiana University (SpharmMat@gmail.com, http://www.iupui.edu/~shenlab/)
% It is available to the scientific community as copyright freeware
% under the terms of the GNU General Public Licence.
%
% Copyright 2009, 2010, ShenLab, Center for Neuroimaging, Indiana University
%
% This file is part of SPHARM-MAT.
%
% SPHARM-MAT 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.
%
% SPHARM-MAT 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 SPHARM-MAT. If not, see <http://www.gnu.org/licenses/>.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [vertices, faces] = readSTL(filename)

[fs, vs, cout] = stlreadASCII(filename);

[v,I,J] = unique(vs,'rows');

vertices = vs(sort(I),:);
faces = zeros(size(fs));
for i = 1:size(fs,2)
    vf = vs(fs(:,i), :);
    [tf, lc] = ismember(vf,vertices, 'rows');
    faces(:,i) = lc;
end

faces = unique(faces,'rows');
dif1 = faces(:,1)-faces(:,2); dif2=faces(:,2)-faces(:,3); dif3=faces(:,3)-faces(:,1);
indDif1 = find(dif1 == 0);
indDif2 = find(dif2 == 0);
indDif3 = find(dif3 == 0);
indDif = union(indDif1, indDif2, indDif3);

ufIDX = setdiff([1:size(faces,1)], indDif);
faces = faces(ufIDX,:);

return;


addpath(genpath('D:\GitHub\KiloSort2')) % path to kilosort folder
addpath('D:\GitHub\npy-matlab')

pathToYourConfigFile = 'D:\GitHub\KiloSort2\configFiles'; % take from Github folder and put it somewhere else (together with the master_file)
run(fullfile(pathToYourConfigFile, 'configFile384.m'))

ops.chanMap  = 'D:\GitHub\KiloSort2\configFiles\neuropixPhase3B2_kilosortChanMap.mat';

% common options for every probe
ops.NchanTOT    = 384;% total number of channels in your recording
ops.trange      =[0 Inf];% TIME RANGE IN SECONDS TO PROCESS

% find the binary file in this folder
rootZ = 'H:\DATA\Spikes\Allen\recording1';
fs = [dir(fullfile(rootZ, '*.dat')) dir(fullfile(rootZ, '*.bin'))];
fname = fs(1).name;
ops.fbinary     = fullfile(rootZ,  fname);

% path to whitened, filtered proc file (on a fast SSD)
rootH = 'H:\DATA\Spikes\temp\';
ops.fproc       = fullfile(rootH, 'temp_wh.dat'); % proc file on a fast SSD

% preprocess data to create temp_wh.dat
rez = preprocessDataSub(ops);

%%
% pre-clustering to re-order batches by depth
% rez = clusterSingleBatches(rez);
clusterSingleBatches2;

%%
% main optimization
rez = learnAndSolve8(rez);

% this does splits
rez    = splitAllClusters(rez);

% this saves to Phy
rezToPhy(rez, rootZ);

fname = fullfile(rootZ, 'rez.mat');
save(fname, 'rez', '-v7.3');


function volCoords = functional2volXformCoords(inplane, gray, preserveExactValues)
% Return coords from Volume view that correspond to coords in
% mrVista functional inplane coords
%
%  volCoords = functional2volXformCoords(inplane, gray, preserveExactValues)
%
% We first get a 3xn matrix of functional view coordinates, then find the
% corresponding inplane anatomical coordinates, and finally find the
% corresponding volume  coordinates. We use this transform when
% we want to convert functional data (e.g., a parameter map, coranal, or
% time series) from the volume view to the inplane view.
%
% INPUTS
%   inplane: mrVista view structure (must be an inplane view)
%   gray: mrVista view structure (must be a gray view)
%   preserveExactValues: boolean. If false, return integer coordinates. If
%                   true, return the calculated (non-integer values). If
%                   non-integer values are returned, then the parent
%                   function will have to deal with these, e.g., via
%                   interpolation.
% OUTPUTS
%   volCoords: 3xn matrix of coordinates in Volume space
%                   corresponding to 3xn matrix of inplane functional  coords
%
% Example:
%   volCoords = ip2volXformCoords(inplane, gray)
%
%
% CO & JW 2016.01.14

% Don't do this unless inplane is really an inplane and volume is really a volume
if ~strcmp(viewGet(inplane, 'viewType'),'Inplane')
    myErrorDlg('ip2volParMap can only be used to transform from inplane to volume/gray.');
end
if ~strcmp(viewGet(gray, 'viewType'),'Volume') &&~strcmp(viewGet(gray, 'viewType'),'Gray')
    myErrorDlg('ip2volParMap can only be used to transform from inplane to volume/gray.');
end

% check inputs
if ~exist('preserveExactValues', 'var'), preserveExactValues = false; end

% we need mrSESSION for the alignment matrix
mrGlobals;

% The gray coords are the integer-valued (y,x,z) volume
% coordinates that correspond to the inplanes.  Convert to
% homogeneous form by adding a row of ones.
preserveCoords = true;
functionalCoords  = ip2functionalCoords(inplane,    viewGet(inplane, 'coords'), ...
    [], preserveCoords, preserveExactValues);
nVoxels = size(functionalCoords, 2);
functionalCoords  = double([functionalCoords; ones(1,nVoxels)]);

% inplane2VolXform is the 4x4 homogeneous transform matrix that
% takes inplane (y',x',z',1) coordinates into Volume (y,x,z,1)
% coordinates.
inplane2VolXform = sessionGet(mrSESSION,'alignment');

% We don't care about the last coordinate in (y,x,z,1), so we
% toss the fourth row of Xform.  Then our outputs will be (y,x,z).
%
inplane2VolXform = inplane2VolXform(1:3,:);

% Transform coord positions to the volume.  Hence, grayCoords
% contains the volume position of each of the inplane  voxels.  These
% will generally not fall on integer-valued coordinates, rather they will
% fall between voxels.  Other functions that rely on the output of this
% function will require interpolation to get the data at these
% between-voxel positions.
%
volCoords = inplane2VolXform*functionalCoords;

% % Convert coords from inplane anatomical space to inplane functional space.
% % We do this because the anatomical inplane is often higher resolution than
% % the functional data.  We preserve the number of coords so that the number
% % of output functional voxels is identical to the number of gray or volume
% % voxels. If requested, we preserve the exact (non-integer) values, which
% % means that the functional coordinates will lie in locations between the
% % actual functional data points.
% preserveCoords = true;
% volCoords   = ip2functionalCoords(inplane, ipAnatomicalCoords, ...
%     [], preserveCoords, preserveExactValues);

% Some confusion about zeros in the output coordinates. It seems best to
% leave the calculations as they are unless there is a problem that someone
% understands. See below.

% HH, 6/16/2012: If we use the code below, we elimintate some voxels
% and then nVoxels is different from the size of ipCoords, leading to a
% mismatch in the size of the expected time series (tSeries) and the
% size of interpolated tSeries, causing an error in  the line,
%  tSeries(frame,:) = interp3(subData, ...
%                                   ipFuncCoords(2,:), ...
%                                   ipFuncCoords(1,:), ...
%                                   ipFuncCoords(3,:), ...
%                                   method);
%
% Hence we comment out the lines below. Leaving in the values with 0
% did not produce an error, at least for the function we tested it on,
% ip2volTSeries.
%
% % ras 12/20/04:
% % occasionally the xformed grayCoords will include a 0
% % coordinate. While it seems this should not happen,
% % I'm applying this band-aid for the time being:
% [badRows badCols] = find(ipFuncCoords==0); %#ok<ASGLU>
% goodCols = setdiff(1:nVoxels, badCols);
% ipFuncCoords = ipFuncCoords(:,goodCols);
% if length(badCols)>1
%     fprintf('%i voxels mapped to slice 0...\n',length(badCols));
% end

return


function k = kernDiagGradX(kern, x)

% KERNDIAGGRADX Compute the gradient of the  kernel wrt X.
% FORMAT
% DESC computes the gradient of the diagonal of the kernel matrix
% with respect to the elements of the design matrix given in X.
% ARG kern : the kernel structure for which gradients are being computed.
% ARG X : the input data in the form of a design matrix.
% RETURN gX : the gradients of the diagonal with respect to each
% element of X. The returned matrix has the same dimensions as X.
%
% SEEALSO : kernDiagGradX, kernGradX

% KERN

fhandle = str2func([kern.type 'KernDiagGradX']);
k = fhandle(kern, x);


function lfmVisualise(model, visualiseFunction, visualiseModify, varargin)

% LFMVISUALISE Visualise the outputs in a latent force model
% FORMAT
% DESC visualises a latent force model with two latent forces as inputs
% ARG model :  the model to visualise.
% ARG visualiseFunction : the function that draws the visualisation (in
% data space) when the graphs are first drawn.
% ARG visualiseModify : the function that modifies the visualisation as
% you create the latent function.
% ARG arg1, arg2, arg3, ... : various additional arguments to be passed to the
% visualisation commands.
%
%
% COPYRIGHT : Mauricio Alvarez and Neil D. Lawrence, 2008

% MLTOOLS

global visualiseInfo
kernType = model.kernType(1:3);
if ~strcmpi(kernType, 'lfm')
  error('This function is only implemented for "LFM" kernels');
else
  if length(varargin)~=4,
    error('Include the skeleton, the initial position and two posteriors for the outputs')
  end
end
range = 1.1*max(max(abs([varargin{3}{1} varargin{3}{2}])));
figure(1)
set(gcf, 'Position', [19 202 582 527]);
clf
% Create a black panel as background
f1 = linspace(-range, range, 200);
f2 = linspace(-range, range, 200);
ax = axes('position', [0.15 0.15 0.75 0.75]);
f1Lim = [min(f1) max(f1)];
f2Lim = [min(f2) max(f2)];
set(ax, 'xLim', f1Lim);
set(ax, 'yLim', f2Lim);
set(ax, 'fontname', 'arial');
set(ax, 'fontsize', 15);
set(ax, 'TickLength', [0 0]);

plot(varargin{3}{1}, varargin{3}{2}, 'b.', 'markersize', 20, 'LineWidth', 2)
hold on
plot(varargin{4}{1}, varargin{4}{2}, 'r.', 'markersize', 20, 'LineWidth', 2)
for i = 2:length(varargin{3}{1})
  arrow([varargin{3}{1}(i-1) varargin{3}{1}(i)], ...
        [varargin{3}{2}(i-1) varargin{3}{2}(i)], [], 'b', 2);
end
for i = 2:length(varargin{4}{1})
  arrow([varargin{4}{1}(i-1) varargin{4}{1}(i)], ...
        [varargin{4}{2}(i-1) varargin{4}{2}(i)], [], 'r', 2);
end
a = text(varargin{3}{1}(1), varargin{3}{2}(1), ' Motion 18');
set(a, 'horizontalalignment', 'left', 'color', [0 0 1], 'fontsize', 16)
a = text(varargin{4}{1}(1), varargin{4}{2}(1), 'Motion 19 ');
set(a, 'horizontalalignment', 'right', 'color', [1 0 0], 'fontsize', 16)
xlabel('f_1(t)')
ylabel('f_2(t)')
title('Latent Forces')
grid on
hold off
%
visualiseInfo.plotAxes = ax;

if verLessThan('matlab', 'R2014a')
  visualiseInfo.latentHandle = line(varargin{3}{1}(1), varargin{3}{2}(1), ...
                                    'markersize', 20, ...
                                    'color', [0.5 0.5 0.5], 'marker', ...
                                    '.', 'visible', ...
                                    'on', 'erasemode', 'xor');
else
  visualiseInfo.latentHandle = line(varargin{3}{1}(1), varargin{3}{2}(1), ...
                                    'markersize', 20, ...
                                    'color', [0.5 0.5 0.5], 'marker', ...
                                    '.', 'visible', ...
                                    'on');
end
visualiseInfo.latentLine = [];
visualiseInfo.clicked = 0;
visualiseInfo.digitAxes = [];
visualiseInfo.digitIndex = [];

% visualiseInfo.dynamicsSlider = ...
%     uicontrol('Style', 'slider', ...
%               'String', 'Time', ...
%               'sliderStep', [0.01, 0.1], ...
%               'units', 'normalized', ...
%               'position', [0 0.95 1 0.05], ...
%               'callback', 'lfmClassVisualise(''dynamicsSliderChange'')');

% set(visualiseInfo.dynamicsSlider, 'visible', 'off');
set(gcf, 'WindowButtonMotionFcn', 'lfmClassVisualise(''move'')')
set(gcf, 'WindowButtonDownFcn', 'lfmClassVisualise(''click'')')

visualiseInfo.timer.series = 0;
visualiseInfo.timer.stepTime = 0.03;

%figure(2)
%set(gcf,'Position',[418 332 445 395]);
%clf
%subplot(2,1,1);
%visualiseInfo.f1.handle = plot(0,1.5, 'LineWidth', 2);
%title('f_1(t)','FontSize', 15, 'FontName', 'arial')
%set(gca, 'yLim', [-range range]);
%set(gca, 'fontname', 'arial');
%set(gca, 'fontsize', 15);
visualiseInfo.f1.series = 0;
%subplot(2,1,2);
%visualiseInfo.f2.handle = plot(0,1.5,'LineWidth', 2);
%title('f_2(t)','FontSize', 15, 'FontName', 'arial')
%set(gca, 'yLim', [-range range]);
%set(gca, 'fontname', 'arial');
%set(gca, 'fontsize', 15);
visualiseInfo.f2.series = 0;

figure(2)
set(gcf,'Position',[635 201 582 527]);
clf
visualiseInfo.visualiseFunction = str2func(visualiseFunction);
visHandle = visualiseInfo.visualiseFunction(varargin{1:2});
%set(gca, 'xlim', [-8  18], ...
%         'ylim', [-2 15], ...
%         'zlim', [0 35]);
set(gca, 'xlim', [-20 10], ...
         'ylim', [-20 20], ...
         'zlim', [0 32]);
title('Synthetic Motion', 'FontSize', 15);

% Pass the data to visualiseInfo
visualiseInfo.model = model;
visualiseInfo.varargin = varargin;
visualiseInfo.visualiseModify = str2func(visualiseModify);
visualiseInfo.visHandle = visHandle;

% figure(4)
% clf
% set(gcf,'Position',[418 30 445 395]);
% visualiseInfo.fPos = plot(0,1.5,'LineWidth', 2);
% %set(gca, 'xLim', [-2*range 2*range]);
% %set(gca, 'yLim', [-2*range 2*range]);
% xlabel('f_1(t)')
% ylabel('f_2(t)')
% set(gca, 'fontname', 'arial');
% set(gca, 'fontsize', 15);


function p = extractBounds(p)
if ~isempty(p.F_struc)
    [lb,ub,used_rows_eq,used_rows_lp] = find_lp_bounds(p.F_struc,p.K);
    if ~isempty(used_rows_lp)
        used_rows_lp = used_rows_lp(~any((p.F_struc(p.K.f + used_rows_lp,1+p.nonlinear)),2));
        if ~isempty(used_rows_lp)
            lower_defined = find(~isinf(lb));
            if ~isempty(lower_defined)
                p.lb(lower_defined) = max(p.lb(lower_defined),lb(lower_defined));
            end
            upper_defined = find(~isinf(ub));
            if ~isempty(upper_defined)
                p.ub(upper_defined) = min(p.ub(upper_defined),ub(upper_defined));
            end
            p.F_struc(p.K.f + used_rows_lp,:)=[];
            p.K.l = p.K.l - length(used_rows_lp);
        end
    end
    if ~isempty(used_rows_eq)
        used_rows_eq = used_rows_eq(~any(full(p.F_struc(used_rows_eq,1+p.nonlinear)),2));
        if ~isempty(used_rows_eq)
            lower_defined = find(~isinf(lb));
            if ~isempty(lower_defined)
                p.lb(lower_defined) = max(p.lb(lower_defined),lb(lower_defined));
            end
            upper_defined = find(~isinf(ub));
            if ~isempty(upper_defined)
                p.ub(upper_defined) = min(p.ub(upper_defined),ub(upper_defined));
            end
            p.F_struc(used_rows_eq,:)=[];
            p.K.f = p.K.f - length(used_rows_eq);
        end
    end
end


function Y=repmat(varargin)
%REPMAT (overloaded)

try
  X = varargin{1};
  Y = X;
  Y.basis = [];
  n = Y.dim(1);
  m = Y.dim(2);
  for i = 1:length(Y.lmi_variables)+1
    temp = repmatfixed(reshape(X.basis(:,i),n,m),varargin{2:end});
    Y.basis(:,i) = temp(:);
  end
  Y.dim(1) = size(temp,1);
  Y.dim(2) = size(temp,2);
  % Reset info about conic terms
  Y.conicinfo = [0 0];
catch
  error(lasterr)
end

function B = repmatfixed(A,M,N)

if nargin < 2
    error('MATLAB:repmat:NotEnoughInputs', 'Requires at least 2 inputs.')
end

if nargin == 2
    if isscalar(M)
        siz = [M M];
    else
        siz = M;
    end
else
    siz = [M N];
end

if isscalar(A)
    nelems = prod(siz);
    if nelems>0
        % Since B doesn't exist, the first statement creates a B with
        % the right size and type.  Then use scalar expansion to
        % fill the array. Finally reshape to the specified size.
        B = spalloc(nelems,1,nnz(A));
        B(nelems) = A;
        if ~isequal(B(1), B(nelems)) | ~(isnumeric(A) | islogical(A))
            % if B(1) is the same as B(nelems), then the default value filled in for
            % B(1:end-1) is already A, so we don't need to waste time redoing
            % this operation. (This optimizes the case that A is a scalar zero of
            % some class.)
            B(:) = A;
        end
        B = reshape(B,siz);
    else
        B = A(ones(siz));
    end
elseif ndims(A) == 2 & numel(siz) == 2
    [m,n] = size(A);

    if (m == 1 & siz(2) == 1)
        B = A(ones(siz(1), 1), :);
    elseif (n == 1 & siz(1) == 1)
        B = A(:, ones(siz(2), 1));
    else
        mind = (1:m)';
        nind = (1:n)';
        mind = mind(:,ones(1,siz(1)));
        nind = nind(:,ones(1,siz(2)));
        B = A(mind,nind);
    end
else
    Asiz = size(A);
    Asiz = [Asiz ones(1,length(siz)-length(Asiz))];
    siz = [siz ones(1,length(Asiz)-length(siz))];
    for i=length(Asiz):-1:1
        ind = (1:Asiz(i))';
        subs{i} = ind(:,ones(1,siz(i)));
    end
    B = A(subs{:});
end

function a = isscalar(b)
[n,m] = size(b);
a = (n*m == 1);


% DEMCLASSIFICATIONSVARGPLVM2
% COPYRIGHT Andreas C. Damianou, 2012
% SEEALSO: demClassificationSvargplvm, demClassificationSvargplvm3,  demClassificationSvargplvm4
% VARGPLVM

% Like demClassificationSvargplvm but we train
% with RANDOM subsets of the training data and in the end we take the mean.

% Fix seeds

if ~exist('onlyTest'), onlyTest = false; end
if ~exist('doPredictions'),    doPredictions = false; end
if ~exist('testDataPerClass'), testDataPerClass = -1; end %%% All data
if ~exist('printPlots'), printPlots = true; end

dataPerClass = -1; %%%% ALL data

addpath(genpath('../../bc-vargplvm/matlab'));
addpath(genpath('../../vargplvm/matlab'));

% This script initialises the options structure 'globalOpt'.
svargplvm_init;

if onlyTest
    load(['demOilSvargplvm' num2str(experimentNo)]);
    globalOpt = model.globalOpt;
end

globalOpt.dataSetNames = {'oilData', 'oilLabels'};
globalOpt.dataSetName = 'oil';
globalOpt.dataToKeep = -1; %%

if exist('timeStamps')
    [globalOpt, YtrAll] = bc_loadData(globalOpt, timeStamps);
else
    [globalOpt, YtrAll] = bc_loadData(globalOpt);
end
Yall{1} = YtrAll.Y;
lblsTrain = YtrAll.lbls;
labelsTrain = transformLabels(lblsTrain);
% ---- We want labels with -1 and 1, not 0 and 1 (anti-correlation)
YtrAll.lbls(YtrAll.lbls == 0) = -1;
Yall{2} = YtrAll.lbls;

globalOptTest = globalOpt;
globalOptTest.dataPerClass = testDataPerClass;
globalOptTest.dataSetName = 'oilTest';
if exist('timeStamps')
    [globalOptTest, YtsAll] = bc_loadData(globalOptTest, timeStamps);
else
    [globalOptTest, YtsAll] = bc_loadData(globalOptTest);
end
lblsTest = YtsAll.lbls;
labelsTest = transformLabels(lblsTest);
Yts{1} = YtsAll.Y;
YtsAll.lbls(YtsAll.lbls == 0) = -1;
Yts{2} = YtsAll.lbls;

if isfield(globalOpt, 'normaliseData') && globalOpt.normaliseData
    Yall{1} = utils_normaliseData(Yall{1});
    Yts{1} = utils_normaliseData(Yts{1});
end

%%%%%%%%%%
indTemp = randperm(size(Yall{1},1));
indTrial = indTemp(1:dataToKeep);
Yall{1} = Yall{1}(indTrial,:);
Yall{2} = Yall{2}(indTrial,:);
lblsTrain = lblsTrain(indTrial,:);
labelsTrain = labelsTrain(indTrial);
%%%%%%%%%%%

if onlyTest
    model = svargplvmRestorePrunedModel(model, Yall);
end

numberOfDatasets = length(Yall);

% globalOpt.baseKern = {'rbfardjit', 'linard2'};

%globalOpt.baseKern = {'rbfardjit', 'rbfardjit'};

globalOpt.indPoints = min(globalOpt.indPoints, size(Yall{1},1));

%-- Load datasets
for i=1:numberOfDatasets
    Y = Yall{i};
    dims{i} = size(Y,2);
    N{i} = size(Y,1);
    indTr = globalOpt.indTr;
    if indTr == -1
        indTr = 1:N{i};
    end
    if ~exist('Yts')
        indTs = setdiff(1:size(Y,1), indTr);
        Yts{i} = Y(indTs,:);
    end
    Ytr{i} = Y(indTr,:);

    t{i} = linspace(0, 2*pi, size(Y, 1)+1)'; t{i} = t{i}(1:end-1, 1);
    timeStampsTraining{i} = t{i}(indTr,1); %timeStampsTest = t(indTs,1);
end

for i=2:numberOfDatasets
    if N{i} ~= N{i-1}
        error('The number of observations in each dataset must be the same!');
    end
end

%%
if ~onlyTest
    % Free up some memory
    clear('Y')

    options = svargplvmOptions(Ytr, globalOpt, labelsTrain);

    if ~isempty(globalOpt.dynamicsConstrainType)
        for i=1:numberOfDatasets
            % Set up dynamcis (i.e. back-constraints) model
            optionsDyn{i}.type = 'vargpTime';
            optionsDyn{i}.inverseWidth=30;
            %   optionsDyn.vardistCovars = vardistCovarsMult;
            optionsDyn{i}.initX = globalOpt.initX;
            optionsDyn{i}.constrainType = globalOpt.dynamicsConstrainType;

            if exist('timeStampsTraining')
                optionsDyn{i}.t = timeStampsTraining;
            end
            if exist('labelsTrain') && ~isempty(labelsTrain)
                optionsDyn{i}.labels = labelsTrain;
            end
        end
    else
        optionsDyn= [];
    end

    model = svargplvmModelCreate(Ytr, globalOpt, options, optionsDyn);
    if exist('diaryFile')
        model.diaryFile = diaryFile;
    end

    model.globalOpt = globalOpt;
    model.options = options;

    %-- Define what level of parallelism to use (w.r.t submodels or/and w.r.t
    % datapoints).
    %{
fprintf('# Parallel computations w.r.t the submodels!\n');
model.parallel = 1;
model = svargplvmPropagateField(model,'parallel', 1);
%
fprintf('# Parallel computations w.r.t the datapoints!\n');
model.vardist.parallel = 1;
for i=1:model.numModels
    model.comp{i}.vardist.parallel = 1;
end
    %}

            %%%% TEMP
    if exist('whiteVar')
        fprintf('aaa\n\n\n')
        model.dynamics.kern.comp{2}.variance = whiteVar;
    end
    %%%%

    % Force kernel computations
    params = svargplvmExtractParam(model);
    model = svargplvmExpandParam(model, params);

    %%
    fprintf('# Median of vardist. covars: %d \n',median(median(model.vardist.covars)));
    fprintf('# Min of vardist. covars: %d \n',min(min(model.vardist.covars)));
    fprintf('# Max of vardist. covars: %d \n',max(max(model.vardist.covars)));

    model = svargplvmOptimiseModel(model);

    svargplvmShowScales(model)
    figure
end

%%
    capName = model.globalOpt.dataSetName;
    capName(1) = upper(capName(1));
    errors = fgplvmNearestNeighbour(model.comp{1}, lblsTrain);
    model2 = vargplvmReduceModel(model.comp{1}, 2);
    errors2 = fgplvmNearestNeighbour(model2, lblsTrain);
    fprintf('# Visualisation errors in all dims/in 2D:  %d / %d\n', errors, errors2)
    if printPlots
        vargplvmPrintPlot(model2, lblsTrain, [capName 'Vargplvm'], model.globalOpt.experimentNo);

        %%
        % For 3D plots:
        % labels = model.options{1}.labels; dims = [1 3 5];
        % plot3k({model.X(:,dims(1)) model.X(:,dims(2)) model.X(:,dims(3))}, 'ColorData', labels, 'Marker', {'x',6});
    end

%%
obsMod = 1; % one of the involved sub-models (the one for which we have the data)
infMod = setdiff(1:2, obsMod);

sharedDims = svargplvmFindSharedDims(model);

%---------------------------- PREDICTIONS ---------------
if ~doPredictions
    return
end

%%

if ~exist('testOnTraining')
    testOnTraining=0;
end

%--------------------%
svargplvmPredictions %---- Script returning: ZpredMuAll and mini(the indices for NN)
%--------------------%

%--- For classification we are interested in labels
ZpredMuAll(ZpredMuAll > 0) = 1;
ZpredMuAll(ZpredMuAll < 0) = -1;
NNpred = Ytr{infMod}(mini,:);
realLabels = lblsTest(testInd,:);

% Find the error in the labels ------------
[labelErrors, labelSharingErrors, wrongIndices] = findLabelErrors(realLabels, ZpredMuAll);
[labelErrorsNN, void, wrongIndicesNN] = findLabelErrors(realLabels,NNpred);

fprintf('# Gplvm label errors: %d\n', labelErrors);
fprintf('# Gplvm label sharing errors: %d\n', labelSharingErrors);
fprintf('# NN label errors:    %d\n', labelErrorsNN);

% Confusion matrix
cmat_a = confMatrix( XpredAll, model.X, labelsTrain, labelsTest, 1);
cmat_rel = cmat_a ./ repmat(sum(cmat_a, 2), 1, length(unique(labelsTrain)));
cmat_rel


% overlay_conc
%
% callback on mouse down event on spm_image figure
% should display concentration maps on mri
%
% INPUTS:
% in: CSI object
% met: metabolite array
% X: (1,2) vector with the first and last index of x coordinates
% Y: (1,2) vector with the first and last of y coordinates

function overlayConcMapOverMRI
    %call global variable from spm
    global st;
    %default value of 1 for coilNum
    spmFigure = st.fig;

    [metabolitePlot, xIndexBounds, yIndexBounds, voxels] = getCurrentUserDataValues(spmFigure);

    if(isempty(metabolitePlot))
        return
    end
    % cursorPosition in the dimensions (l-r,a-p,s-i)
    cursorPosition = st.centre;
    %dimension size of the MRI
    dimensionSize = st.vols{1}.dim;
    %resolution of MRI (in mm)(not used, might be useful)
    resolution = (st.bb(2,:) - st.bb(1,:) + 1)/dimensionSize(:)';

    [sagital_voxels, coronal_voxels, transverse_voxels] = findIntersectingVoxels(voxels, cursorPosition);

    %3D bounding box of the MRI scan in mm. ie the coordinates where the MRI is
    %plotted onto.
    mriBoundingBox = st.bb;

    deleteCurrentConcentrationMap(st);
    %(needs to be modified if 3D MRSI is to be done)
    voxelIntersectionPositions = {};
    counter = 1;
    metabolitesToPlotVectorized = zeros(1, numel(transverse_voxels));
    for i = 1:numel(transverse_voxels)
        xIndex = transverse_voxels(i).fid_aIndex(1) - xIndexBounds(1) + 1;
        yIndex = transverse_voxels(i).fid_aIndex(2) - yIndexBounds(1) + 1;
        if (xIndex > 0 && yIndex > 0 && xIndex <= size(metabolitePlot, 1) && yIndex <= size(metabolitePlot, 2))
            transverseIntersection = transverse_voxels(i).findIntersection('axial', cursorPosition(3));
            voxelIntersectionPositions{counter} = transverseIntersection(1:2, :) - mriBoundingBox(1,1:2)';
            metabolitesToPlotVectorized(counter) = metabolitePlot(xIndex, yIndex);
            counter = counter + 1;
        end
    end

    for i = 1:length(voxelIntersectionPositions)
        currentCoordiante = voxelIntersectionPositions{i};
        patch(st.vols{1}.ax{4}.ax, currentCoordiante(1, :), ...
            currentCoordiante(2, :), metabolitesToPlotVectorized(i), ...
            'Tag', 'trans_plot');
    end
    %PLOTTING IN THE SAGITAL PLANE
    plotVoxelsOnMRIPlane(st.vols{1}.ax{3}.ax, sagital_voxels, 'sagital', cursorPosition);

    %PLOTTING ON THE CORONAL PLANE
    plotVoxelsOnMRIPlane(st.vols{1}.ax{2}.ax, coronal_voxels, 'coronal', cursorPosition);
end

function [metabolitePlot, xIndexBounds, yIndexBounds, voxels] = getCurrentUserDataValues(spmFigure)
    figureUserData = spmFigure.UserData;
    metabolitePlot = figureUserData.metabolitePlot;
    xIndexBounds = figureUserData.xIndexBounds;
    yIndexBounds = figureUserData.yIndexBounds;
    voxels = figureUserData.voxels;
end

function deleteCurrentConcentrationMap(st)
    concentrationMap = findobj(st.vols{1}.ax{4}.ax,'Tag','trans_plot');
    delete(concentrationMap);
end


function RRest(period)
% RRest runs RR algorithms on ECG and PPG signals using each possible
% combination of options, as specified in "setup_universal_params.m".
%
%               RRest('mimic')
%
%	Inputs:
%		data            data files should be stored in the specified format
%                       in the directory specified in
%                       "setup_universal_params.m". Data can be downloaded
%                       using the "
%       period          this string specifies the dataset to be analysed.
%                       Only the 'mimic' dataset has been used with this
%                       version of the toolbox.
%
%	Outputs:
%       for each subject, N, the following files are made:
%           N_int_respSigs      intermediate respiratory signals,
%           N_respSigs          final respiratory signals
%           N_rrEsts            RR estimates
%           N_rrRef             Reference RR values
%           N_sqi               Signal Quality Index values
%       for the entire dataset, the following files are made:
%           alg_names           Names of RR algorithms tested
%           win_data            Data for every algorithm tested, every
%                               window, and every subject.
%
%   Context:    This is the main file used to run the algorithms. It calls
%               lots of other functions, contained in separate files.
%
%   Further Information:
%       This version of the RRest is provided to facilitate reproduction of
%       the analysis performed in:
%           Charlton P.H. et al., "Waveform Analysis to Estimate
%           Respiratory Rate" [In Press]
%       Further information on this study can be obtained at:
%           http://peterhcharlton.github.io/RRest/waveform_analysis.html
%       In addition, further information on RRest, including future
%       versions, can be obtained at:
%           http://peterhcharlton.github.io/RRest
%
%   Comments, Questions, Criticisms, Feedback, Contributions:
%       See: http://peterhcharlton.github.io/RRest/contributions.html
%
%   Version:
%       v.1 - published on 23rd Feb 2016 by Peter Charlton
%
%   Licence:
%       please see the accompanying file named "LICENSE"
%

%% Setup Universal Parameters
% The universal parameters are used throughout the algorithms
up = setup_universal_params(period);

if up.analysis.run_analysis

    %% Estimate RRs from ECG and PPG
    % Carry out processing for each stage of the algorithms
    for key_comp_no = 1 : length(up.al.key_components)
        feval(up.al.key_components{key_comp_no}, up);
    end

    %% Conduct Signal Quality Assessment of Signals
    % Each window of ECG and PPG is quality assessed
    calculate_sqi(up);

    %% Estimate Reference RRs
    estimate_ref_rr(up);

end

%% Statistical Analysis
calc_stats(up);
create_table_of_algorithms(up);

end


function [outdata,outstate] = asr_process(data,srate,state,windowlen,lookahead,stepsize,maxdims,chunklen,usegpu)
% Processing function for the Artifact Subspace Reconstruction (ASR) method.
% [Data,State] = asr_process(Data,SamplingRate,State,WindowLength,LookAhead,StepSize,MaxDimensions,ChunkLength,UseGPU)
%
% This function is used to clean multi-channel signal using the ASR method. The required inputs are
% the data matrix, the sampling rate of the data, and the filter state (as initialized by
% asr_calibrate). If the data is used on successive chunks of data, the output state of the previous
% call to asr_process should be passed in.
%
% In:
%   Data : Chunk of data to process [#channels x #samples]. This is a chunk of data, assumed to be
%          a continuation of the data that was passed in during the last call to asr_process (if
%          any). The data should be *zero-mean* (e.g., high-pass filtered the same way as for
%          asr_calibrate).
%
%   SamplingRate : sampling rate of the data in Hz (e.g., 250.0)
%
%   State : initial filter state (determined by asr_calibrate or from previous call to asr_process)
%
%   WindowLength : Length of the statistcs window, in seconds (e.g., 0.5). This should not be much
%                  longer than the time scale over which artifacts persist, but the number of samples
%                  in the window should not be smaller than 1.5x the number of channels. Default: 0.5
%
%   LookAhead : Amount of look-ahead that the algorithm should use. Since the processing is causal,
%               the output signal will be delayed by this amount. This value is in seconds and should
%               be between 0 (no lookahead) and WindowLength/2 (optimal lookahead). The recommended
%               value is WindowLength/2. Default: WindowLength/2
%
%   StepSize : The statistics will be updated every this many samples. The larger this is, the faster
%              the algorithm will be. The value must not be larger than WindowLength*SamplingRate.
%              The minimum value is 1 (update for every sample) while a good value is 1/3 of a second.
%              Note that an update is always performed also on the first and last sample of the data
%              chunk. Default: 32
%
%   MaxDimensions : Maximum dimensionality of artifacts to remove. Up to this many dimensions (or up
%                   to this fraction of dimensions) can be removed for a given data segment. If the
%                   algorithm needs to tolerate extreme artifacts a higher value than the default
%                   may be used (the maximum fraction is 1.0). Default 0.66
%
%   ChunkLength : The length of the chunks to process, in samples. Larger chunks require more
%                 memory. Default: 50000
%
%   UseGPU : Whether to run on the GPU. This makes sense for offline processing if you have a a card
%            with enough memory and good double-precision performance (e.g., NVIDIA GTX Titan or
%            K20). Note that for this to work you need to have the Parallel Computing toolbox.
%            Default: false
%
% Out:
%   Data : cleaned data chunk (same length as input but delayed by LookAhead samples)
%
%   State : final filter state (can be passed in for subsequent calls)
%
%                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                2012-08-31

% UC Copyright Notice
% This software is Copyright (C) 2013 The Regents of the University of California. All Rights Reserved.
%
% Permission to copy, modify, and distribute this software and its documentation for educational,
% research and non-profit purposes, without fee, and without a written agreement is hereby granted,
% provided that the above copyright notice, this paragraph and the following three paragraphs appear
% in all copies.
%
% Permission to make commercial use of this software may be obtained by contacting:
% Technology Transfer Office
% 9500 Gilman Drive, Mail Code 0910
% University of California
% La Jolla, CA 92093-0910
% (858) 534-5815
% invent@ucsd.edu
%
% This software program and documentation are copyrighted by The Regents of the University of
% California. The software program and documentation are supplied "as is", without any accompanying
% services from The Regents. The Regents does not warrant that the operation of the program will be
% uninterrupted or error-free. The end-user understands that the program was developed for research
% purposes and is advised not to rely exclusively on the program for any reason.
%
% IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
% SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
% THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
% PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
% CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
% MODIFICATIONS.

if nargin < 4 || isempty(windowlen)
    windowlen = 0.5; end
windowlen = max(windowlen,1.5*size(data,1)/srate);
if nargin < 5 || isempty(lookahead)
    lookahead = windowlen/2; end
if nargin < 6 || isempty(stepsize)
    stepsize = 32; end
if nargin < 7 || isempty(maxdims)
    maxdims = 0.66; end
if nargin < 9 || isempty(usegpu)
    usegpu = false; end
if nargin < 8 || isempty(chunklen)
    chunklen = 50000; end
if maxdims < 1
    maxdims = round(size(data,1)*maxdims); end
if isempty(data)
    outdata = data; outstate = state; return; end

[C,S] = size(data);
N = round(windowlen*srate);
P = round(lookahead*srate);
[T,M,A,B] = deal(state.T,state.M,state.A,state.B);

% initialize prior filter state by extrapolating available data into the past (if necessary)
if isempty(state.carry)
    state.carry = repmat(2*data(:,1),1,P) - data(:,1+mod(((P+1):-1:2)-1,S)); end

data = [state.carry data];
data(~isfinite(data(:))) = 0;

% split up the total sample range into k chunks
splits = ceil(S/chunklen);
if splits > 1
    fprintf('Now cleaning data in %i blocks',splits); end

for i=1:splits
    range = 1+floor((i-1)*S/splits) : min(S,floor(i*S/splits));
    if ~isempty(range)
        % get spectrally shaped data X for statistics computation (range shifted by lookahead)
        X = double(data(:,range+P));
        if isempty(state.SOS)
            [X,state.iir] = filter(B,A,double(X),state.iir,2);
        else
            for s = 1:size(state.SOS,1)
                [X,state.Zi{s}] = filter(state.SOS(s,1:3),state.SOS(s,4:6),double(X),state.Zi{s},2); end
            X = X*state.G;
        end

        % move it to the GPU if applicable
        if usegpu && length(range) > 1000
            try X = gpuArray(X); catch,end; end
        % compute running mean covariance (assuming a zero-mean signal)
        [Xcov,state.cov] = moving_average(N,reshape(bsxfun(@times,reshape(X,1,C,[]),reshape(X,C,1,[])),C*C,[]),state.cov);
        % extract the subset of time points at which we intend to update
        update_at = min(stepsize:stepsize:(size(Xcov,2)+stepsize-1),size(Xcov,2));
        % if there is no previous R (from the end of the last chunk), we estimate it right at the first sample
        if isempty(state.last_R)
            update_at = [1 update_at];  %#ok<AGROW>
            state.last_R = eye(C);
        end
        Xcov = reshape(Xcov(:,update_at),C,C,[]);
        if usegpu
            Xcov = gather(Xcov); end
        % do the reconstruction in intervals of length stepsize (or shorter if at the end of a chunk)
        last_n = 0;
        for j=1:length(update_at)
            % do a PCA to find potential artifact components
            [V,D] = eig(Xcov(:,:,j));
            [D,order] = sort(reshape(diag(D),1,C)); V = V(:,order);
            % determine which components to keep (variance below directional threshold or not admissible for rejection)
            keep = D<sum((T*V).^2) | (1:C)<(C-maxdims);
            trivial = all(keep);
            % update the reconstruction matrix R (reconstruct artifact components using the mixing matrix)
            if ~trivial
                R = real(M*pinv(bsxfun(@times,keep',V'*M))*V');
            else
                R = eye(C);
            end
            % apply the reconstruction to intermediate samples (using raised-cosine blending)
            n = update_at(j);
            if ~trivial || ~state.last_trivial
                subrange = range((last_n+1):n);
                blend = (1-cos(pi*(1:(n-last_n))/(n-last_n)))/2;
                data(:,subrange) = bsxfun(@times,blend,R*data(:,subrange)) + bsxfun(@times,1-blend,state.last_R*data(:,subrange));
            end
            [last_n,state.last_R,state.last_trivial] = deal(n,R,trivial);
        end
    end
    if splits > 1
        fprintf('.'); end
end
if splits > 1
    fprintf('\n'); end

% carry the look-ahead portion of the data over to the state (for successive calls)
state.carry = [state.carry data(:,(end-P+1):end)];
state.carry = state.carry(:,(end-P+1):end);

% finalize outputs
outdata = data(:,1:(end-P));
if usegpu
    state.iir = gather(state.iir);
    state.cov = gather(state.cov);
end
outstate = state;

function [X,Zf] = moving_average(N,X,Zi)
% Run a moving-average filter along the second dimension of the data.
% [X,Zf] = moving_average(N,X,Zi)
%
% In:
%   N : filter length in samples
%   X : data matrix [#Channels x #Samples]
%   Zi : initial filter conditions (default: [])
%
% Out:
%   X : the filtered data
%   Zf : final filter conditions
%
%                           Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                           2012-01-10

if nargin <= 2 || isempty(Zi)
    Zi = zeros(size(X,1),N); end

% pre-pend initial state & get dimensions
Y = [Zi X]; M = size(Y,2);
% get alternating index vector (for additions & subtractions)
I = [1:M-N; 1+N:M];
% get sign vector (also alternating, and includes the scaling)
S = [-ones(1,M-N); ones(1,M-N)]/N;
% run moving average
X = cumsum(bsxfun(@times,Y(:,I(:)),S(:)'),2);
% read out result
X = X(:,2:2:end);

if nargout > 1
    Zf = [-(X(:,end)*N-Y(:,end-N+1)) Y(:,end-N+2:end)]; end


function [sensor, crash] = checkCrash(car, obstacle_polygon, obstacle_circle)

    %% ----- Initialization

    A = get(car(1),'Vertices');     %Get vertices of the vehicle
    dist_crash = 1.5;               %Sensor distance (1.5 = 15cm) for crash
    obs_crash = false;              %Obstacle crash
    sens_crash = false;             %Crash sensor values are below 1.5.
    status = true;                  %Help variable

    %% ----- Check collision between the vehicle and obstacles

    n_polygons = length(obstacle_polygon);
    n_circles = length(obstacle_circle);
    for i = 1:n_polygons

        B = get(obstacle_polygon(i),'Vertices');

        obs_crash = obstacleCrash(A, B, 'polygon');

        if(obs_crash)
            status = false;
            break;
        end

    end

    if(status)

        for i = 1:n_circles

            C = get(obstacle_circle(i),'Vertices');

            obs_crash = obstacleCrash(A, C, 'circle');

            if(obs_crash)
                break;
            end
        end
    end

    %% ----- Check collision with sensors

    n_sensors = length(car(2:end));
    sensor = zeros(1, n_sensors);

    % Loop through the sensors
    for i = 1:n_sensors

        % Get vertices of the sensors
        D = get(car(i+1),'Vertices');
        sensor_temp = 0;

        % For each sensor, check collision with all the obstacles
        for j = 1:n_circles

            C = get(obstacle_circle(j), 'Vertices');

            % Store all the sensor values in a vector
            [sensor_temp(j), crash] = sensorValues(D, C, 'circle', dist_crash);

            % Check collision
            if(crash)
                sens_crash = true;
                break;
            end
        end

        if( ~sens_crash )

            for k = (j+1):(j + n_polygons)

                B = get(obstacle_polygon(k-j), 'Vertices');

                [sensor_temp(k), crash] = sensorValues(D, B, 'polygon', dist_crash);

                if(crash)

                    sens_crash = true;
                end
            end
        end

        % store the lowest sensor value
        sensor(i) = min(sensor_temp);

    end

    %sensor = round(10.*sensor);
    sensor = 10.*sensor;                % Scale the sensor values with 10
    crash = [obs_crash, sens_crash];    % Store the results in a vector
end


%% Example
% An example script, it is used to show how to use the arcs
% functions of the KUKA iiwa matlab toolbox
% First run the following script in Matlab
% Then start the client on the KUKA iiwa controller

% Mohammad SAFEEA, 24th of April 2018

close all,clear all;clc;
warning('off');
ip='172.31.1.147'; % The IP of the controller
% start a connection with the server
global t_Kuka;
t_Kuka=net_establishConnection( ip );

if ~exist('t_Kuka','var') || isempty(t_Kuka) || strcmp(t_Kuka.Status,'closed')
  warning('Connection could not be establised, script aborted');
  return;
else

      %% Go to initial configuration
      relVel=0.25; % over ride relative joint velocities

      pos={0, -pi / 180 * 10, 0, -pi / 180 * 100, pi / 180 * 90,pi / 180 * 90, 0};   % initial cofiguration

      movePTPJointSpace( t_Kuka , pos, relVel); % go to home position
      %% Move in an arc, the orientation of EEF changes while performing the motion,
      % The function utilized (movePTPCirc1OrintationInter)
      % f2 is the final frame, at which the arc motion ends
      % f1 is an intermidiate frame, through wich the robot passes while
      % performing the motion.

      f1=getEEFPos( t_Kuka );
      f2=f1;
      r=75;
      f1{2}=f1{2}+r;
      f1{3}=f1{3}-r;
      f1{6}=f1{6}+pi/8;

      f2{3}=f2{3}-2*r;
      f2{6}=f2{6}+pi/2;

      vel=150; % linear velocity of end-effector mm/sec
      movePTPCirc1OrintationInter( t_Kuka , f1,f2, vel)

          %% Move robot in joint space to some initial configuration
pinit={0,pi*20/180,0,-pi*70/180,0,pi*90/180,0}; % joint angles of initial confuguration
relVel=0.15; % the relative velocity
movePTPJointSpace( t_Kuka , pinit, relVel); % point to point motion in joint space

%% Move EEF -100 mm in Z direction
deltaX=0.0;deltaY=0;deltaZ=-100.; % relative displacemnets of end-effector
Pos{1}=deltaX;
Pos{2}=deltaY;
Pos{3}=deltaZ;
movePTPLineEefRelBase( t_Kuka , Pos, vel);

%% Store the current position in the memory
Cen=getEEFPos(t_Kuka); % Concider the current position as the center of the arcs

%% Move EEF 50mm in X direction
deltaX=100;deltaY=0;deltaZ=0.;
Pos{1}=deltaX;
Pos{2}=deltaY;
Pos{3}=deltaZ;
movePTPLineEefRelBase( t_Kuka , Pos, vel);
%% Store the current position in the memory
circle_Starting_Point=getEEFPos( t_Kuka ); % Consider the current point as circle starting point

%% Move in an arc, the arc is drawn on an incliend plane
% using the function ((movePTPArc_AC))
theta=pi/2; % the angle subtended by the arc at the center ((c))
k=[1;1;1]; % normal vector of the plane, on which the circle is drawn
c=[Cen{1};Cen{2};Cen{3}]; % the center of the arc
vel=100; % the motion velocity mm/sec
movePTPArc_AC(t_Kuka,theta,c,k,vel)

%% Go back to ((circle_Starting_Point)) coordinates
vel=150;
movePTPLineEEF( t_Kuka , circle_Starting_Point, vel);
%% Move in an arc, the arc is drawn in XY plane
% using the function ((movePTPArcXY_AC))
theta=1.98*pi; % the angle subtended by the arc at the center ((c))
c=[Cen{1};Cen{2}]; % the XY coordinate of the center of the arc
vel=150; % the motion velocity mm/sec
movePTPArcXY_AC(t_Kuka,theta,c,vel)

      %% turn off the server
       net_turnOffServer( t_Kuka );

       fclose(t_Kuka);
end

warning('on');


function [avg_runtime, plug_events] = get_average_runtime_from_plug_data(appliance_name, training_days, setup)

    appliance_id = getApplianceID(appliance_name);
    global caching;
    if caching == 1
        if exist('cache_plugs_training.mat') == 2
            load('cache_plugs_training');
        else
            appliance_consumption_training = read_plug_data(setup.dataset, setup.household, appliance_id, training_days, setup.granularity);
            save('cache_plugs_training', 'appliance_consumption_training');
        end
    else
        appliance_consumption_training = read_plug_data(setup.dataset, setup.household, appliance_id, training_days, setup.granularity);
    end

    if strcmp(appliance_name, 'TV') == 1 ...
            || strcmp(appliance_name, 'Stereo') == 1 ...
            || strcmp(appliance_name, 'Fridge') == 1 ...
            || strcmp(appliance_name, 'Freezer') == 1

        on_events = [];
        off_events = [];
        cons = appliance_consumption_training;
        for i = 1:length(cons)-1
            % on events
            if cons(i) < 20 && cons(i+1) >= 20
                on_events = [on_events; i, i+1, 1, 1];
            elseif cons(i) >= 20 && cons(i+1) < 20
                if length(on_events) == 0
                    continue;
                end
                off_events = [off_events; i, i+1, -1, 1];
            end
        end

        if length(off_events) > length(on_events)
            off_events(end) = [];
        end

        avg_runtime = mean(off_events(:,1) - on_events(:,1));
        plug_events = {off_events, on_events};

    else
        error('Not implemented for appliance %s', appliance_name);
    end
end


% snirfDownsample()
%
% A utility that let's you pick fNIRS files in a file dialog box that
% are then decimated to the specified frequency using a low pass filter as
% implemented by the matlab 'downsample' command.
%
% Note that original copies of the fNIRS files are not preserved. It is
% advised that you create a back up of your fNIRS files in case you want to
% recover the higher sample rate date.
% Modified from resample code
% Fixed the problem with edges
% Fixed the problem with s vector - Meryem Oct 2016
% Add code to allow non-integer downsampling factor - Meryem Oct 2018
% Code refined for Homer3 and fNIRS files

% Homer3 Note
% Downsample tool does not work for a flat file structure

function snirfDownsample()

global maingui;
if isempty(maingui)
    [files, pathnm] = uigetfile( '*.snirf', 'Pick the .snirf file', 'multiselect','on');
else
    fpath = [maingui.dataTree.currElem.path maingui.dataTree.currElem.name];
    [files, pathnm] = uigetfile( '*.snirf', 'Pick files to downsample', fpath, 'multiselect','on');
end

if ~iscell(files)
    if files==0
        return;
    end
end

[~,name,~] = fileparts(files);

fsn = inputdlg( 'Decrease the sampling rate of a sequence by a factor of', 'Downsample SNIRF files', 1 );
if isempty(fsn)
    return
end
fsn = str2num(fsn{1});

wd = cd;
cd(pathnm)

if ~iscell(files)
    foo{1} = files;
    files = foo;
end

for iFile = 1:length(files)
    snirfData = SnirfClass(files{iFile});
%     varLst = whos();

%     fs = 1/(snirfData.data.time(2)-snirfData.data.time(1));

    if floor(fsn) == fsn % integer check

        snirfData.data.dataTimeSeries = downsample(snirfData.data.dataTimeSeries,fsn);
        if ~isempty(snirfData.aux)
            for iAux = 1:length(snirfData.aux)
                snirfData.aux(iAux).dataTimeSeries = downsample(snirfData.aux(iAux).dataTimeSeries,fsn);
                snirfData.aux(iAux).time = downsample(snirfData.aux(iAux).time,fsn);
            end
        end
        snirfData.data.time = downsample(snirfData.data.time,fsn);
%         s_sampled = zeros(size(snirfData.data.time,1),length(snirfData.aux));
%         for j=1:size(snirfData.stim,2)
%             lst_1 = snirfData.stim(j).data(:,3) == 1;
% %             lst_1 = round(lst_1/fsn);
%             s_sampled(lst_1,j) = 1;
%             lst_2 = snirfData.stim(j).data(:,3) == -1;
% %             lst_2 = round(lst_2/fsn);
%             s_sampled(lst_2,j) = -1;
%             snirfData.stim(j).data = s_sampled(:,j);
%         end
    else  % if downsample factor is not an integer (first upsample then downsample)
        t_new = linspace(1, size(snirfData.data.dataTimeSeries,1), 10*size(snirfData.data.dataTimeSeries,1));
        snirfData.data.dataTimeSeries = interp1(snirfData.data.dataTimeSeries, t_new);
        snirfData.data.dataTimeSeries = downsample(snirfData.data.dataTimeSeries,round(fsn*10));

        if ~isempty(snirfData.aux)
            for iAux = 1:length(snirfData.aux)
                snirfData.aux(iAux).dataTimeSeries = interp1(snirfData.aux(iAux).dataTimeSeries,t_new);
                snirfData.aux(iAux).dataTimeSeries = downsample(snirfData.aux(iAux).dataTimeSeries,round(fsn*10))';
                snirfData.aux(iAux).time = interp1(snirfData.aux(iAux).time,t_new);
                snirfData.aux(iAux).time = downsample(snirfData.aux(iAux).time,round(fsn*10))';
            end
        end

        snirfData.data.time = interp1(snirfData.data.time, t_new);
        snirfData.data.time = downsample(snirfData.data.time,round(fsn*10))';

%         s_sampled = zeros(size(snirfData.data.time,1),length(snirfData.aux));
%         for j=1:size(snirfData.stim,2)
%             lst_1 = snirfData.stim(j).data(:,3) == 1;
% %             lst_1 = round(lst_1/fsn);
%             s_sampled(lst_1,j) = 1;
%             lst_2 = snirfData.stim(j).data(:,3) == -1;
% %             lst_2 = round(lst_2/fsn);
%             s_sampled(lst_2,j) = -1;
%             snirfData.stim(j).data = s_sampled(:,j);
%         end

    end

    snirfName = sprintf([name '_downsample_' num2str(fsn) '.snirf']);
    snirfData.Save(snirfName);
    msgbox(['File created with name' snirfName]);
end

new_name = [files{1} '.orig'];
movefile (files{1}, new_name);

cd(wd);


function [mask,xmesh_new,ymesh_new] = dicomrt_trimZ(slice,voiref,inpmatrix,dose_xmesh,dose_ymesh,voi,voiselect)
% dicomrt_trimZ(slice,voiref,inpmatrix,dose_xmesh,dose_ymesh,voi,voiselect)
%
% Trim a matrix to min and max boundaries in the selected voi along X and Y.
%
% slice is the number of the section (relative to voiref) to be trimmed.
%   Slice is used to locate the matrix along Z and to match matrix with the corresponding contour in voiselect.
% inpmatrix is a 2D matrix.
% dose_xmesh, dose_ymesh, are the coordinates of the center of the pixel for eval and ref.
% voi and voiselect are the vois' cell array and the # of the voi to be used for the gamma calculation respectively.
%   They have to be specified together. Both matrices will be masked and reduced in size accordingly with the selected
%   voi's dimensions.
%
% NOTE: Use dicomrt_mask if you want to zeroes all the voxel data outside the voi of interest, without altering the
%       dimensions of the dose matrix.
%       This function leave unchanged matrix values outside the voi of interest: no mask is performed.
%       This functions changes the X, and Y dimensions of the input matrix to fit as close as possible
%       to the max and min contour position in x and y direction.
%
% Example:
%
% [trimdose,new_xmesh,new_ymesh]=dicomrt_trimZ(15,1,dose(:,:,15),dose_xmesh,dose_ymesh,VOI,4);
%
% calculates the position of the maximum and minimum contour for VOI number 4 in x and y and cut from "dose" all
% the voxels positioned outside these boundaries. Returns the new matrix in trimdose, and the new xmesh, ymesh
% in new_xmesh and new_ymesh. Here slice number 15 is defined in voiref 1.
%
% See also dicomrt_loadmcdose, dicomrt_dosediff
%
% Copyright (C) 2002 Emiliano Spezi (emiliano.spezi@physics.org)

% Check case and set-up some parameters and variables
[matrix_temp,type,label,PatientPosition]=dicomrt_checkinput(inpmatrix,1);
matrix=dicomrt_varfilter(matrix_temp);
[voi_temp,type,label]=dicomrt_checkinput(voi);
voi=dicomrt_varfilter(voi_temp);

[locate_voi_min_x,locate_voi_max_x,locate_voi_min_y,locate_voi_max_y] = ...
    dicomrt_voiboundariesZ(slice,voiref,dose_xmesh,dose_ymesh,voi_temp,voiselect,PatientPosition);

mask=matrix(locate_voi_min_y:locate_voi_max_y,locate_voi_min_x:locate_voi_max_x);

xmesh_new=dose_xmesh(locate_voi_min_x:locate_voi_max_x);
ymesh_new=dose_ymesh(locate_voi_min_y:locate_voi_max_y);

% Restore original variable format
[mask]=dicomrt_restorevarformat(matrix_temp,mask);


function plot_his_map(groundTruthFile, expMapFile)
%     NeuroSLAM System Copyright (C) 2018-2019
%     NeuroSLAM: A Brain inspired SLAM System for 3D Environments
%
%     Fangwen Yu (www.yufangwen.com), Jianga Shang, Youjian Hu, Michael Milford(www.michaelmilford.com)
%
%     The NeuroSLAM V1.0 (MATLAB) was developed based on the OpenRatSLAM (David et al. 2013).
%     The RatSLAM V0.3 (MATLAB) developed by David Ball, Michael Milford and Gordon Wyeth in 2008.
%
%     Reference:
%     Ball, David, Scott Heath, Janet Wiles, Gordon Wyeth, Peter Corke, and Michael Milford.
%     "OpenRatSLAM: an open source brain-based SLAM system." Autonomous Robots 34, no. 3 (2013): 149-176.
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.

    % load ground truth data
    [frameId, gt_x, gt_y, gt_z, gt_rx, gt_ry, gt_rz] = load_ground_truth_data(groundTruthFile);

    % load experience map data
    [expId, exp_x, exp_y, exp_z, exp_yaw, exp_pitch] = load_exp_map_data(expMapFile);

    hold on
    plot3(exp_x*1*(100), exp_y*100, exp_z*(-200), '.b');
    plot3((gt_x - gt_x(1))*100, (gt_y - gt_y(1))*100, (gt_z - gt_z(1))*(100), '.r');
    hold off;
    % grid on
    view(3)
    xl = xlabel('exp-x');
    yl = ylabel('exp-y');
    zlabel('exp-z');
    set(xl,'Rotation',15);
    set(yl,'Rotation',-30);
    title('3D Experience Map');
    %                     legend('Result','Truth' ,'1');
    % axis([-10 20 -10 20 -10 20]);
    %                     axis equal
    % axis on
    rotate3d on

end


%%generate data config
param.split_data_num=1;
param.file_path_cam1=fullfile(fileparts(pwd),'prid_2011','multi_shot','cam_a');
param.file_path_cam2=fullfile(fileparts(pwd),'prid_2011','multi_shot','cam_b');
param.save_traindata_filename='train_data_Prid';
param.save_testdata_filename='test_data_Prid';
%% generate ten split train/test data
for split_num_start=1:param.split_data_num
    if ~exist(strcat(param.save_traindata_filename,num2str(split_num_start)),'file')
        mkdir(strcat(param.save_traindata_filename,num2str(split_num_start)));
    end
    if ~exist(strcat(param.save_testdata_filename,num2str(split_num_start)),'file')
        mkdir(strcat(param.save_testdata_filename,num2str(split_num_start)));
    end
    subdir_cam1=dir(param.file_path_cam1);
    subdir_cam2=dir(param.file_path_cam2);
    %% select images >27 frame
    person_file_cam1=[];
    person_file_cam2=[];
    for i=3:202
        image_path_a=fullfile(param.file_path_cam1,subdir_cam1(i).name,'/');
        image_list_a=dir(image_path_a);
        len=length(image_list_a);
        if len<29
            continue;
        else
            person_file_cam1=[person_file_cam1;i-2];
        end
    end
    for i=3:202
        image_path_b=fullfile(param.file_path_cam2,subdir_cam2(i).name,'/');
        image_list_b=dir(image_path_b);
        len=length(image_list_b);
        if len<29
            continue;
        else
            person_file_cam2=[person_file_cam2;i-2];
        end
    end
    %%
    person_num=intersect(person_file_cam1,person_file_cam2);
    select_list_len=size(person_num,1);
    train_data_select=randperm(select_list_len,select_list_len/2);
    train_data_index=person_num(train_data_select);
    test_data_index=setdiff(person_num,train_data_index);
    %generate train data
    train_data_cam1=[];
    label_train_cam1=[];
    train_image_name_cam1={};
    train_data_cam2=[];
    label_train_cam2=[];
    train_image_name_cam2={};
    for i=1:(length(train_data_index))
        fprintf('process train data:%d/%d\n',i,(length(train_data_index)));
        index=train_data_index(i);
        image_path_cam1=fullfile(param.file_path_cam1,subdir_cam1(index+2).name,'/');
        image_list_cam1=dir(image_path_cam1);
        for j=3:length(image_list_cam1);
            image_name=strcat(image_path_cam1,image_list_cam1(j).name);
            image_data=imread(image_name);
            train_data_cam1=[train_data_cam1;reshape(image_data,1,64*128*3)];
            label_train_cam1=[label_train_cam1;i];
            train_image_name_cam1=[train_image_name_cam1,image_name];
        end
        image_path_cam2=fullfile(param.file_path_cam2,subdir_cam2(index+2).name,'/');
        image_list_cam2=dir(image_path_cam2);
        for j=3:length(image_list_cam2);
            image_name=strcat(image_path_cam2,image_list_cam2(j).name);
            image_data=imread(image_name);
            train_data_cam2=[train_data_cam2;reshape(image_data,1,64*128*3)];
            label_train_cam2=[label_train_cam2;i];
            train_image_name_cam2=[train_image_name_cam2,image_name];
        end
    end
    save(strcat(param.save_traindata_filename,num2str(split_num_start),'/train_data.mat'),'train_data_cam1','train_data_cam2','label_train_cam1','label_train_cam2','train_image_name_cam1','train_image_name_cam2');
    %% generate test data
    test_data_cam1=[];
    label_test_cam1=[];
    test_image_name_cam1={};
    test_data_cam2=[];
    label_test_cam2=[];
    test_image_name_cam2={};
    for i=1:(length(test_data_index))
        fprintf('process test data:%d/%d\n',i,(length(test_data_index)));
        index=test_data_index(i);
        image_path_cam1=fullfile(param.file_path_cam1,subdir_cam1(index+2).name,'/');
        image_list_cam1=dir(image_path_cam1);
        for j=3:length(image_list_cam1);
            image_name=strcat(image_path_cam1,image_list_cam1(j).name);
            image_data=imread(image_name);
            test_data_cam1=[test_data_cam1;reshape(image_data,1,64*128*3)];
            label_test_cam1=[label_test_cam1;i+89];
            test_image_name_cam1=[test_image_name_cam1,image_name];
        end
        image_path_cam2=fullfile(param.file_path_cam2,subdir_cam2(index+2).name,'/');
        image_list_cam2=dir(image_path_cam2);
        for j=3:length(image_list_cam2);
            image_name=strcat(image_path_cam2,image_list_cam2(j).name);
            image_data=imread(image_name);
            test_data_cam2=[test_data_cam2;reshape(image_data,1,64*128*3)];
            label_test_cam2=[label_test_cam2;i+89];
            test_image_name_cam2=[test_image_name_cam2,image_name];
        end
    end
    save(strcat(param.save_testdata_filename,num2str(split_num_start),'/test_data.mat'),'test_data_cam1','test_data_cam2','label_test_cam1','label_test_cam2','test_image_name_cam1','test_image_name_cam2');
end