function options = drawCbMap(map,options,varargin)
%Draws a map with the specified optional parameters
%
% drawCbMap(map,options)
%
%INPUTS
% map                       COBRA map structure
%
%OPTIONAL INPUTS
% options                  Structure containing optional parameters
%   nodeWeight              Size of primary metabolite nodes
%   nodeWeightSecondary     Size of secondary metabolite nodes
%   nodeColor               Color of metabolite nodes
%   edgeColor               Color of reaction arrows2
%   edgeArrowColor          Color of reaction arrowheads
%   edgeWeight              Width of reaction arrows
%   textSize                Font size of metabolite text
%   textColor               Text color for metaboltes
%   rxnTextSize             Font size of reaction text
%   rxnTextColor            Text color for reactions
%   otherTextColor          Color of other text
%   fileName                Name of output file
%
% varargin                  optional parameter name / parameter value pairs
%
%OUTPUT
% Displays map in a matlab figure ('matlab') or target.svg ('svg') file
% depending on value of CB_MAP_OUTPUT.
% options                  Structure containing optional parameters
%
%
% Turner Conrad     6/12/12     Added rxnTextSize default (8) to fix error
%                               in writing reaction texts to .svg

global mapHandle
global CB_MAP_OUTPUT

%check for render output
if ~exist('CB_MAP_OUTPUT', 'var') || isempty(CB_MAP_OUTPUT)
    error('No render target specified.  Call changeCbMapOutput(outputFormat)');
end

if (nargin < 2)
    options = [];
end

if mod(length(varargin),2)==0
    for i=1:2:length(varargin)-1
        switch lower(varargin{i})
            case 'nodeweight', options.nodeWeight = cell2mat(varargin(i+1));
            case 'nodecolor', options.nodeColor = cell2mat(varargin(i+1));
            case 'edgeweight', options.edgeWeight = cell2mat(varargin(i+1));
            case 'edgecolor', options.edgeColor = cell2mat(varargin(i+1));
            case 'edgearrowcolor', options.edgeArrowColor = cell2mat(varargin(i+1));
            case 'textsize', options.textSize = cell2mat(varargin(i+1));
            case 'textcolor', options.textColor = cell2mat(varargin(i+1));
            case 'othertextsize', options.otherTextSize = cell2mat(varargin(i+1));
            case 'othertextcolor', options.otherTextColor = cell2mat(varargin(i+1));
            case 'filename', options.fileName = varargin{i+1};
            otherwise, options.(varargin{i}) = varargin{i+1};
        end
    end
else
    error('Invalid number of parameters/values');
end

%%%% Compelete the missing parts of the option
nNodes = size(map.molName,1);
nEdges = size(map.connection,1);
%Node size
if ~isfield(options,'nodeWeight')
    options.nodeWeight = ones(nNodes,1)*15;
    if strcmp(CB_MAP_OUTPUT,'svg')
        options.nodeWeight = ones(nNodes,1)*25;
    end
end

if ~isfield(options,'nodeWeightSecondary')
    options.nodeWeightSecondary = ones(nNodes,1)*10;
    if strcmp(CB_MAP_OUTPUT,'svg')
        options.nodeWeightSecondary = ones(nNodes,1)*15;
    end
end
%Node color
if ~isfield(options,'nodeColor')
    options.nodeColor = repmat([255,160,128],nNodes,1);
end
%Edge color
if ~isfield(options,'edgeColor')
    options.edgeColor = repmat([0,191,255],nEdges,1);
end
%Arrowhead color
if ~isfield(options,'edgeArrowColor')
    options.edgeArrowColor = repmat([0,0,255],nEdges,1);
end
%Edge thickness
if ~isfield(options,'edgeWeight')
    options.edgeWeight = ones(nEdges,1)*2;
    if strcmp(CB_MAP_OUTPUT,'svg')
        options.edgeWeight = ones(nEdges,1)*4;
    end
end
%Font Size
if ~isfield(options,'textSize')
    options.textSize = ones(max(nNodes,nEdges),1)*12;
    if strcmp(CB_MAP_OUTPUT,'svg')
        options.textSize = ones(max(nNodes,nEdges),1)*10;
    end
end
%Font Color
if ~isfield(options,'textColor')
    options.textColor = zeros(nNodes,3);
end

% if ~isfield(options,'otherTextSize')
%     options.otherTextSize = ones(size(map.text,1),1)*12;
%     if strcmp(CB_MAP_OUTPUT,'svg')
%         options.otherTextSize = ones(size(map.text,1),1)*135;
%     end
% end

if ~isfield(options,'otherTextColor')
    options.otherTextColor= zeros(size(map.text,1),3);
end

nodeWeight = options.nodeWeightSecondary;
nodeWeight(strcmp(map.molPrime,'Y')) = options.nodeWeight(strcmp(map.molPrime,'Y'));

if ~isfield(options,'fileName')
    options.fileName = 'target.svg';
end

if ~isfield(options,'rxnDir')
    options.rxnDir = zeros(size(map.connectionAbb,1),1);
end

if ~isfield(options,'rxnDirMultiplier')
    options.rxnDirMultiplier = 2;
end

%%%%%%%% initialization
if strcmp(CB_MAP_OUTPUT,'matlab')    % use matlab to draw the map
    clf; % this was in line 41 before
    % setting the color bar
    figure(1);colormap(cool(100))
    colorbar('location','southoutside');
    axis equal;
    hold on
elseif strcmp(CB_MAP_OUTPUT, 'java')
    % use Java/OpenGL to draw the map
    plotcbmap;
    % send the transformation coordinates
    R=map.molPosition';
    R=sort(R);
    a=max(R);
    b=min(R);
    xmax=a(1,1);
    xmin=b(1,1);
    ymax=a(1,2);
    ymin=b(1,2);
    settrans(mapHandle,xmax,xmin,ymax,ymin);
elseif strcmp(CB_MAP_OUTPUT, 'svg')
    %check fileName extension
    if isempty(regexp(lower(options.fileName),'.svg$'))
        options.fileName = strcat(options.fileName,'.svg');
    end
    textPos = (map.textPos);
    x1 = min(map.molPosition(1,:));
    if min(textPos(:,1))<x1
        x1 = min(textPos(:,1));
    end
    y1 = min(map.molPosition(2,:));
    if min(textPos(:,2))<y1
        y1 = min(textPos(:,2));
    end
    x2 = max(map.molPosition(1,:));
    if max(textPos(:,1))>x2
        x2 = max(textPos(:,1));
    end
    y2 = max(map.molPosition(2,:));
    if max(textPos(:,2))>y2
        y2 = max(textPos(:,2));
    end
    if isfield(options,'colorScale')
        numColorBins = size(options.colorScale,1);
        colorScaleWidth = 0.25*(x2-x1);
        binWidth = colorScaleWidth/numColorBins;
        colorScaleHeight = 0.05*colorScaleWidth;
        colorScaleBuffer = colorScaleHeight*1.5;
        y2 = y2+colorScaleBuffer; %add buffer for scale
    end
    if isfield(options,'fluxVarColor')
        colorScaleHeight = 0.0125*(x2-x1);
        colorScaleBuffer = colorScaleHeight*1.5;
        colorWidth = 0.025*(x2-x1);
        y2 = y2+colorScaleBuffer;
    end
    [x1,y1,x2,y2] = deal(x1-200, y1-200, x2+200, y2+200); % add buffer
    SF = .25;
    mapHandle = fopen(options.fileName, 'w');
    fprintf(mapHandle, '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n');
    fprintf(mapHandle,'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\n');
    fprintf(mapHandle,'<svg height="%+.2f" width="%+.2f" viewBox="%+.2f %+.2f %+.2f %+.2f" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">\n',(y2-y1+20)*SF,(x2-x1+20)*SF,(x1-10)*SF,(y1-10)*SF,(x2-x1+0)*SF,(y2-y1+20)*SF);
    fprintf(mapHandle,'<g transform="scale(%5.3f)">\n',SF);

    %Add Scale
    if isfield(options,'overlayType')
        for i=1:numColorBins
            color = strcat('rgb(',num2str(options.colorScale(i,1)),',',num2str(options.colorScale(i,2)),',',num2str(options.colorScale(i,3)),')');
            fprintf(mapHandle,'<g style="stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 20; fill: %s; ">\n',color);
            fprintf(mapHandle,'<rect x="%.2f" y="%.2f" width="%.2f" height="%.2f" />\n</g>\n',x2-colorScaleWidth-200*2+(binWidth*(i-1)),y2-colorScaleHeight*1.25,binWidth,colorScaleHeight);
        end
        fprintf(mapHandle, '<g style="font-family: sans; stroke: none; text-anchor:end">\n');
        fprintf(mapHandle,'<text style="fill: rgb(0,0,0); text-rendering: optimizeLegibility;" x="%.2f" y="%.2f" font-size="%dpx">%s</text>\n</g>\n',x2-colorScaleWidth-200*2-0.25*colorScaleHeight,y2-colorScaleHeight*.4,colorScaleHeight,['Scale: ' options.scaleTypeLabel '    ' options.overlayType ': ' options.overlayLB]);
        fprintf(mapHandle, '<g style="font-family: sans; stroke: none; text-anchor:start">\n');
        fprintf(mapHandle,'<text style="fill: rgb(0,0,0); text-rendering: optimizeLegibility;" x="%.2f" y="%.2f" font-size="%dpx">%s</text>\n</g>\n',x2-200*2+0.25*colorScaleHeight,y2-colorScaleHeight*.4,colorScaleHeight,[options.overlayUB]);
    end
    if isfield(options,'fluxVarColor')
        colorTextLabel = {'Bidirectional / reversible:', 'Unidirectional / reversible forward:', 'Unidirectional / reversible reverse:', 'Unidirectional / irreversible:'};
        color{1} = strcat('rgb(',num2str(options.fluxVarColor.biDirColor(1)),',',num2str(options.fluxVarColor.biDirColor(2)),',',num2str(options.fluxVarColor.biDirColor(3)),')');
        color{2} = strcat('rgb(',num2str(options.fluxVarColor.uniDirFwdColor(1)),',',num2str(options.fluxVarColor.uniDirFwdColor(2)),',',num2str(options.fluxVarColor.uniDirFwdColor(3)),')');
        color{3} = strcat('rgb(',num2str(options.fluxVarColor.uniDirRevColor(1)),',',num2str(options.fluxVarColor.uniDirRevColor(2)),',',num2str(options.fluxVarColor.uniDirRevColor(3)),')');
        color{4} = strcat('rgb(',num2str(options.fluxVarColor.uniDirIrrColor(1)),',',num2str(options.fluxVarColor.uniDirIrrColor(2)),',',num2str(options.fluxVarColor.uniDirIrrColor(3)),')');
        for i=2:3:11
            fprintf(mapHandle, '<g style="font-family: sans; stroke: none; text-anchor:end">\n');
            fprintf(mapHandle,'<text style="fill: rgb(0,0,0); text-rendering: optimizeLegibility;" x="%.2f" y="%.2f" font-size="%dpx">%s</text>\n</g>\n',i*(x2-x1)/12,y2-colorScaleHeight*.4,colorScaleHeight,colorTextLabel{ceil(i/3)});
            fprintf(mapHandle,'<g style="stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 20; fill: %s; ">\n',color{ceil(i/3)});
            fprintf(mapHandle,'<rect x="%.2f" y="%.2f" width="%.2f" height="%.2f" />\n</g>\n',i*(x2-x1)/12,y2-colorScaleHeight*1.25,colorWidth,colorScaleHeight);
        end
    end
end

%%%%% actual map drawing code
% draw other shapes
if isfield(map,'shapeThickness')
    for i = 1:size((map.shapeThickness),1)
        drawShape(map.shapeType(i,1),map.shapePos(i,1:2),map.shapeSize(i,1:2),map.shapeColor(i,1:3),map.shapeThickness(i,1),map.shapeStyle(i,1));
    end
end
% draw the connection segments traversing through the connection matrix
for i = 1:(size((map.connection),1))
    drawLine(map.connection(i,1),map.connection(i,2),map,options.edgeColor(i,:),options.edgeArrowColor(i,:),options.edgeWeight(i),nodeWeight,options.rxnDir(i),options.rxnDirMultiplier);
end
% draw the circles representing molecules
for i = 1:size((map.molPosition),2)
    drawCircle(map.molPosition(:,i),nodeWeight(i),options.nodeColor(i,:));
end
% draw texts
for i = 1:length(map.text)
    textFont =map.textFont{i};
    if regexp(textFont,'@')
        [textFont, textSize] = strtok(textFont,'@');
        textSize = str2num(regexprep(textSize,'@',''));
    elseif(map.textSize(i) >= 60)
        textSize = 60;
    else
        textSize = map.textSize(i);
    end
    if find(regexp(textFont,'Italic'))
        textStyle = 'italic;';
    else
        textStyle = '';
    end
    %textFont
    % if find(regexp(textFont,' B')) || find(regexp(textFont(end),'B'))
    if (find(regexp(textFont,'B')))
        textWeight = 'bold';
        textFont = regexprep(textFont,' B','');
    else
        textWeight = '';
    end
    if isfield(options,'otherTextSize'), textSize = options.otherTextSize(i); end
    drawText(map.textPos(i,1),map.textPos(i,2),map.text{i,1},textSize,textStyle,options.otherTextColor(i,:),lower(textFont),textWeight,true);
end
% Write Metabolite Label
for i = 1:size((map.molPosition),2)
    % write the labels for molecules
    if(options.textSize(i) ~= 0)
        drawText(map.molLabelPos(i,1),map.molLabelPos(i,2),map.molAbbreviation{i},options.textSize(i),'',options.textColor(i,:));
    end
end
% Write Reaction Label
for i = 1:size(map.rxnLabelPosition,2)
    if ~any(isnan(map.rxnLabelPosition(:,i)))
      if isfield(options, 'rxnTextSize')
        drawText(map.rxnLabelPosition(1,i),map.rxnLabelPosition(2,i),map.connectionAbb{find(map.rxnIndex(i)==map.connection,1)},options.rxnTextSize(i),'italic');
      else
        drawText(map.rxnLabelPosition(1,i),map.rxnLabelPosition(2,i),map.connectionAbb{find(map.rxnIndex(i)==map.connection,1)},10,'italic');
      end
    end
end

if strcmp(CB_MAP_OUTPUT,'matlab')
    hold off;
elseif strcmp(CB_MAP_OUTPUT,'java')

elseif strcmp(CB_MAP_OUTPUT,'svg')

    fprintf(mapHandle,'</g>\n');
    fprintf(mapHandle,'</svg>\n');
    fclose(mapHandle);
    display('Document Written')
end


% std_moveoutlier()  - Commandline function, to reassign specified outlier component(s)
%                            from a cluster to its outlier cluster.
% Usage:
%                   >> STUDY = std_moveoutlier(STUDY, ALLEEG, from_cluster, comps);
% Inputs:
%   STUDY         - EEGLAB STUDY set comprising some or all of the EEG datasets in ALLEEG.
%   ALLEEG        - global EEGLAB vector of EEG structures for the dataset(s) included in the STUDY.
%                       ALLEEG for a STUDY set is typically created using load_ALLEEG().
%   from_cluster - cluster number, the cluster outlier components are moved from.
%   comps          - [numeric vector] component indices in the from_cluster to move.
%
% Outputs:
%   STUDY    - the input STUDY set structure modified with the components reassignment.
%
%   Example:
%                         >> from_cluster = 10; comps = [2 7];
%                         >> STUDY = std_movecomp(STUDY,ALLEEG, from_cluster, to_cluster, comps);
%                    Components 2 and 7 of cluster 10 are moved to the its outlier cluster ('Outliers Cls 10').
%
%  See also  pop_clustedit
%
% Authors:  Hilit Serby, Arnaud Delorme, Scott Makeig, SCCN, INC, UCSD, June, 2005

% Copyright (C) Hilit Serby, SCCN, INC, UCSD, June 07, 2005, hilit@sccn.ucsd.edu
%
% 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 2 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, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function STUDY = std_moveoutlier(STUDY, ALLEEG, old_clus, comps)

% Cannot move components if the cluster is either a 'Notclust' or
% 'Outliers' cluster
if strncmpi('Notclust',STUDY.cluster(old_clus).name,8) | strncmpi('Outliers',STUDY.cluster(old_clus).name,8)
    warndlg2('std_moveoutlier: cannot move components from Notclust or Outliers cluster');
    return;
end

% Cannot move components if clusters have children clusters
if ~isempty(STUDY.cluster(old_clus).child)
    warndlg2('Cannot move components if cluster has children clusters!' , 'Aborting remove outliers');
    return;
end

outlier_clust = std_findoutlierclust(STUDY,old_clus); %find the outlier cluster for this cluster
if outlier_clust == 0 %no such cluster exist
    STUDY = std_createclust(STUDY, ALLEEG, ['Outliers ' STUDY.cluster(old_clus).name]); %create an outlier cluster
    outlier_clust = length(STUDY.cluster);
end

%move the compnents to the outliers cluster
STUDY = std_movecomp(STUDY, ALLEEG, old_clus, outlier_clust, comps);


function res = nchannels(this)
% returns number of channels
% FORMAT res = nchannels(this)
% _______________________________________________________________________
% Copyright (C) 2008-2012 Wellcome Trust Centre for Neuroimaging

% Vladimir Litvak
% $Id: nchannels.m 5025 2012-10-31 14:44:13Z vladimir $

if this.montage.Mind==0
    res = length(this.channels);
else
    res = length(this.montage.M(this.montage.Mind).channels);
end


function [joints, parts] = util_get_parts24()

parts = [];
joints = [];

parts.id    = 0;   parts.pos    = [0 0];     parts.xaxis    = [1 0];
parts(2).id = 1;   parts(2).pos = [0 1];     parts(2).xaxis = [1 0];
parts(3).id = 2;   parts(3).pos = [1 1];     parts(3).xaxis = [1 0];
parts(4).id = 3;   parts(4).pos = [1 2];     parts(4).xaxis = [2 1];
parts(5).id = 4;   parts(5).pos = [2 2];     parts(5).xaxis = [2 1];
parts(6).id = 5;   parts(6).pos = [3 3];     parts(6).xaxis = [3 4];
parts(7).id = 6;   parts(7).pos = [3 4];     parts(7).xaxis = [3 4];
parts(8).id = 7;   parts(8).pos = [4 4];     parts(8).xaxis = [4 5];
parts(9).id = 8;   parts(9).pos = [4 5];     parts(9).xaxis = [4 5];
parts(10).id = 9;  parts(10).pos = [5 5];    parts(10).xaxis = [4 5];
parts(11).id = 10; parts(11).pos = [6 7];    parts(11).xaxis = [7 6];
parts(12).id = 11; parts(12).pos = [8 9];    parts(12).xaxis = [9 8];
parts(13).id = 12; parts(13).pos = [10 10];  parts(13).xaxis = [11 10];
parts(14).id = 13; parts(14).pos = [11 10];  parts(14).xaxis = [11 10];
parts(15).id = 14; parts(15).pos = [11 11];  parts(15).xaxis = [11 10];
parts(16).id = 15; parts(16).pos = [12 11];  parts(16).xaxis = [12 11];
parts(17).id = 16; parts(17).pos = [12 12];  parts(17).xaxis = [12 11];
parts(18).id = 17; parts(18).pos = [13 13];  parts(18).xaxis = [13 14];
parts(19).id = 18; parts(19).pos = [13 14];  parts(19).xaxis = [13 14];
parts(20).id = 19; parts(20).pos = [14 14];  parts(20).xaxis = [14 15];
parts(21).id = 20; parts(21).pos = [14 15];  parts(21).xaxis = [14 15];
parts(22).id = 21; parts(22).pos = [15 15];  parts(22).xaxis = [14 15];
parts(23).id = 22; parts(23).pos = [8 8];  parts(23).xaxis = [9 8];
parts(24).id = 23; parts(24).pos = [9 9];  parts(24).xaxis = [9 8];

joints.id    = 0;   joints.child    = parts(1);   joints.parent    = parts(2);   joints.pos    = 0;
joints(2).id = 1;   joints(2).child = parts(2);   joints(2).parent = parts(3);   joints(2).pos = 1;
joints(3).id = 2;   joints(3).child = parts(3);   joints(3).parent = parts(4);  joints(3).pos = 1;
joints(4).id = 3;   joints(4).child = parts(4);   joints(4).parent = parts(5);   joints(4).pos = 2;
joints(5).id = 4;   joints(5).child = parts(5);   joints(5).parent = parts(11);  joints(5).pos = 2;

joints(6).id = 5;   joints(6).child = parts(6);   joints(6).parent = parts(11);  joints(6).pos = 3;
joints(7).id = 6;   joints(7).child = parts(7);   joints(7).parent = parts(6);   joints(7).pos = 3;
joints(8).id = 7;   joints(8).child = parts(8);   joints(8).parent = parts(7);   joints(8).pos = 4;
joints(9).id = 8;   joints(9).child = parts(9);   joints(9).parent = parts(8);  joints(9).pos = 4;
joints(10).id = 9;  joints(10).child = parts(10);  joints(10).parent = parts(9);  joints(10).pos = 4;

joints(11).id = 10; joints(11).child = parts(12); joints(11).parent = parts(11);  joints(11).pos = 7;

joints(12).id = 11; joints(12).child = parts(13); joints(12).parent = parts(14);  joints(12).pos = 10;
joints(13).id = 12; joints(13).child = parts(14); joints(13).parent = parts(15); joints(13).pos = 11;
joints(14).id = 13; joints(14).child = parts(15); joints(14).parent = parts(16); joints(14).pos = 11;
joints(15).id = 14; joints(15).child = parts(16); joints(15).parent = parts(17); joints(15).pos = 12;
joints(16).id = 15; joints(16).child = parts(17); joints(16).parent = parts(11); joints(16).pos = 12;

joints(17).id = 16; joints(17).child = parts(18); joints(17).parent = parts(11);  joints(17).pos = 13;
joints(18).id = 17; joints(18).child = parts(19); joints(18).parent = parts(18); joints(18).pos = 13;
joints(19).id = 18; joints(19).child = parts(20); joints(19).parent = parts(19); joints(19).pos = 14;
joints(20).id = 19; joints(20).child = parts(21); joints(20).parent = parts(20); joints(20).pos = 14;
joints(21).id = 20; joints(21).child = parts(22); joints(21).parent = parts(21); joints(21).pos = 15;
joints(22).id = 21; joints(22).child = parts(24); joints(22).parent = parts(23); joints(22).pos = 8;

end


% Copyright (C) 2017-2018 Titus Cieslewski, RPG, University of Zurich,
%   Switzerland
%   You can contact the author at <titus at ifi dot uzh dot ch>
% Copyright (C) 2017-2018 Siddharth Choudhary, College of Computing,
%   Georgia Institute of Technology, Atlanta, GA, USA
% Copyright (C) 2017-2018 Davide Scaramuzza, RPG, University of Zurich,
%   Switzerland
%
% This file is part of dslam_open.
%
% dslam_open 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.
%
% dslam_open 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 dslam_open. If not, see <http://www.gnu.org/licenses/>.

%% Prep: Do once, writes to files
%% Generate NetVLAD vectors for dataset
getNetVladFeats(dataset_path, sequence_id);
%% Parse VO and merge with NetVLAD
% Prereq: Run C++ executable dataset_to_vo
parseAllData(dataset_path, sequence_id);
%% Split full dataset into n robots
splitAndSave(dataset_path, sequence_id, num_robots);
%% Generate verification requests.
generateVerificationRequests(dataset_path, sequence_id, num_robots);
%% Parse verification response
% Prereq: Run C++ exec process_verification_request
parseVerificationResponse(dataset_path, sequence_id, num_robots);

%% Load vanilla
root = [dataset_path '/' sequence_id '/'];
dpath = [root 'dslam/'];
load([dpath 'robot_data_' num2str(num_robots) '.mat']);
%% Plot vanilla
plotGeoverError(robot_data, [1], 'vanilla');

%% Create prototype
proto_data = robot_data;
%%
consistency_range = 20;
position_tolerance = 4;

for robot_i = 1:numel(proto_data)
    r_i_data = proto_data{robot_i};
    % For each robot, keep track of last seen rel pose that is floating or
    % accepted. Floating: rel pose that is neither accepted or rejected.
    last_floating = cell(num_robots, 1);
    last_accepted = cell(num_robots, 1);
    match_accepted = false(numel(r_i_data.place_matches), 1);
    for query_i = 1:numel(r_i_data.place_matches)
        match = r_i_data.place_matches{query_i};
        if (numel(match) > 0)
            this.frame_i = query_i;
            this.match = match;
            % Case there is a last accepted rel pose
            if (numel(last_accepted{match.robot_i}) > 0)
                assert(numel(last_floating{match.robot_i}) == 0);
                % If they are within range, accept if consistent.
                if areFramesWithinRange(r_i_data, ...
                        last_accepted{match.robot_i}.frame_i, query_i, ...
                        consistency_range)
                    if areMatchesConsistent(proto_data, robot_i, ...
                            last_accepted{match.robot_i}, this, ...
                            position_tolerance)
                        match_accepted(query_i) = true;
                        last_accepted{match.robot_i} = this;
                        disp('Acc consistent acc');
                        continue;
                    else
                        match_accepted(query_i) = false;
                        disp('Rej inconsistent acc');
                        continue;
                    end
                else % Frames are not within range: Forget last_accepted.
                    last_accepted{match.robot_i} = [];
                    % Will drop to case no previous floating.
                end
            end
            % Case there is a last floating rel pose
            if (numel(last_floating{match.robot_i}) > 0)
                % If they are within range, accept both if consistent.
                if areFramesWithinRange(r_i_data, ...
                        last_floating{match.robot_i}.frame_i, query_i, ...
                        consistency_range)
                    if areMatchesConsistent(proto_data, robot_i, ...
                            last_floating{match.robot_i}, this, ...
                            position_tolerance)
                        match_accepted(...
                            last_floating{match.robot_i}.frame_i) = true;
                        match_accepted(query_i) = true;
                        last_floating{match.robot_i} = [];
                        last_accepted{match.robot_i} = this;
                        disp('Acc consistent float');
                        continue;
                    % If not consistent, replace floating with this.
                    else
                        match_accepted(...
                            last_floating{match.robot_i}.frame_i) = false;
                        last_floating{match.robot_i} = this;
                        disp('Rej inconsistent float');
                        continue;
                    end
                else % Frames are not within range: Replace last_floating.
                    match_accepted(...
                        last_floating{match.robot_i}.frame_i) = false;
                    last_floating{match.robot_i} = this;
                    disp('Reinit float');
                    continue;
                end
            % Case there is neither a last accepted nor last floating.
            else
                % Set floating to this.
                last_floating{match.robot_i} = this;
                disp('Init float');
            end
        end
    end
    % Eliminate non-accepted matches.
    proto_data{robot_i}.place_matches(~match_accepted) = {[]};
    disp(['Accepted ' num2str(nnz(match_accepted)) ' of ' ...
        num2str(numel(match_accepted)) ' matches!']);
end

%%
plotGeoverError(proto_data, [2], 'robustified');


%
% In order to obtain a simple and effective source code for
% Fingerprint Recognition System please visit
% http://utenti.lycos.it/matlab/beginner.htm
%
% There you will be able to make a small donation
% ( just 2 Euros, less than 2.8 US Dollars ) using
% the secure connection to PayPal.
%
% The source code implements FingerCode-based fingerprint
% verification.
%
% References:
%
%   A. K. Jain, S. Prabhakar, and S. Pankanti, "A Filterbank-based Representation for
%   Classification and Matching of Fingerprints", International Joint Conference on
%   Neural Networks (IJCNN), pp. 3284-3285, Washington DC, July 10-16, 1999.
%   http://www.cse.msu.edu/~prabhaka/publications.html
%
%   "Fingerprint Classification and Matching Using a Filterbank", Salil Prabhakar
%   A DISSERTATION Submitted to Michigan State University in partial fulfillment
%   of the requirements for the degree of DOCTOR OF PHILOSOPHY, Computer
%   Science & Engineering, 2001
%   http://biometrics.cse.msu.edu/SalilThesis.pdf
%
% For any question please email me luigi.rosa@tiscali.it
%
% Luigi ROSA
% Via Centrale 35
% 67042 Civita Di Bagno
% L'Aquila - ITALY
% mobile +39 3207214179
% email luigi.rosa@tiscali.it
%
%
%


function write_mrtrix (image, filename)

% function: write_mrtrix (image, filename)
%
% write the data contained in the structure 'image' in the MRtrix
% format image 'filename' (i.e. files with the extension '.mif' or '.mih').
%
% 'image' is either a N-dimensional array (N <= 16), or a structure containing
% the following fields:
%    image.data:            a N-dimensional array (N <= 16)
%    image.vox:             N-vector of voxel sizes (in mm) (default: { 2 }) [optional]
%    image.comments:        a cell array of strings [optional]
%    image.datatype:        the datatype specifier (default: float32) [optional]
%    image.mrtrix_version:  a character array [optional]
%    image.transform:       a 4x4 matrix [optional]
%    image.dw_scheme:       a NDWx4 matrix of gradient directions [optional]

fid = fopen (filename, 'w');
assert(fid ~= -1, 'error opening %s', filename);
fprintf (fid, 'mrtrix image\ndim: ');

if isstruct(image)
  dim = size(image.data);
else
  dim = size(image);
end

while prod(size(dim)) < 3
  dim(end+1) = 1;
end

fprintf (fid, '%d', dim(1));
fprintf (fid, ',%d', dim(2:end));

fprintf (fid, '\nvox: ');
if isstruct (image) && isfield (image, 'vox')
  fprintf (fid, '%.3f', image.vox(1));
  fprintf (fid, ',%.3f', image.vox(2:end));
else
  fprintf(fid, '2');
  fprintf(fid, ',%d', 2*ones(1,size(dim,2)-1));
end

fprintf (fid, '\nlayout: +0');
fprintf (fid, ',+%d', 1:(size(dim,2)-1));

[computerType, maxSize, endian] = computer;
if isstruct (image) && isfield (image, 'datatype')
  datatype = lower(image.datatype);
  byteorder = datatype(end-1:end);

  if strcmp (byteorder, 'le')
    precision = datatype(1:end-2);
    byteorder = 'l';
  elseif strcmp(byteorder, 'be')
    precision = datatype(1:end-2);
    byteorder = 'b';
  else
    if strcmp(datatype, 'bit')
      precision = 'bit1';
      byteorder = 'n';
    elseif strcmp (datatype, 'int8') || strcmp (datatype, 'uint8')
      precision = datatype;
      byteorder = 'n';
      if endian == 'L'
        datatype(end+1:end+3) = 'le';
      else
        datatype(end+1:end+3) = 'be';
      end
    end
  end
else
  if endian == 'L'
    datatype = 'float32le';
  else
    datatype = 'float32be';
  end
  precision = 'float32';
  byteorder = 'n';
end
fprintf (fid, [ '\ndatatype: ' datatype ]);

fprintf (fid, '\nmrtrix_version: %s', 'matlab');

if isstruct (image) && isfield (image, 'transform')
  fprintf (fid, '\ntransform: %.6f', image.transform(1,1));
  fprintf (fid, ',%.6f', image.transform(1,2:4));
  fprintf (fid, '\ntransform: %6f', image.transform(2,1));
  fprintf (fid, ',%.6f', image.transform(2,2:4));
  fprintf (fid, '\ntransform: %.6f', image.transform(3,1));
  fprintf (fid, ',%.6f', image.transform(3,2:4));
end

if isstruct (image) && isfield (image, 'dw_scheme')
  for i=1:size(image.dw_scheme,1)
    fprintf (fid, '\ndw_scheme: %.6f', image.dw_scheme(i,1));
    fprintf (fid, ',%.6f', image.dw_scheme(i,2:4));
   end
end

% write out any other fields:
if isstruct (image)
  f = fieldnames(image);
  % don't worry about fields that have already been dealt with:
  f(strcmp(f,'dim')) = [];
  f(strcmp(f,'vox')) = [];
  f(strcmp(f,'layout')) = [];
  f(strcmp(f,'datatype')) = [];
  f(strcmp(f,'transform')) = [];
  f(strcmp(f,'dw_scheme')) = [];
  f(strcmp(f,'data')) = [];

  % write out contents of the remainging fields:
  for n = 1:numel(f)
    val = getfield (image, f{n});
    if iscell (val)
      for i=1:numel(val)
        fprintf (fid, '\n%s: %s', f{n}, val{i});
      end
    else
      fprintf (fid, '\n%s: %s', f{n}, val);
    end
  end
end

if strcmp(filename(end-3:end), '.mif')
  datafile = filename;
  dataoffset = ftell (fid) + 24;
  fprintf (fid, '\nfile: . %d\nEND\n                         ', dataoffset);
elseif strcmp(filename(end-3:end), '.mih')
  datafile = [ filename(end-3:end) '.dat' ];
  dataoffset = 0;
  fprintf (fid, '\nfile: %s %d\nEND\n', datafile, dataoffset);
else
  fclose(fid);
  error('unknown file suffix - aborting');
end

fclose(fid);

fid = fopen (datafile, 'r+', byteorder);
fseek (fid, dataoffset, -1);

if isstruct(image)
  fwrite (fid, image.data, precision);
else
  fwrite (fid, image, precision);
end
fclose (fid);


function imdb = os_get_database(osDir)

load(fullfile(osDir, 'imdb/imdb.mat'), 'imdb') ;
imdb.imageDir512 = fullfile(osDir, imdb.imageDir512) ;
imdb.imageDir1024 = fullfile(osDir, imdb.imageDir1024) ;
imdb.maskDir512 = fullfile(osDir, imdb.maskDir512) ;
imdb.maskDir1024 = fullfile(osDir, imdb.maskDir1024) ;

% use these by default
imdb.imageDir = imdb.imageDir512 ;
imdb.maskDir = imdb.maskDir512 ;
imdb.segmDir = fullfile(osDir, 'segm/512') ;

% split images in train, val, test
n = numel(imdb.images.id) ;
m = round(n/3) ;
sets = [1 * ones(1,m), 2 * ones(1,m), 3 * ones(1,n-2*m)] ;
rng(0) ;
imdb.images.set = sets(randperm(n)) ;
[~,i] = ismember(imdb.segments.imageId, imdb.images.id) ;
imdb.segments.set = imdb.images.set(i) ;
imdb.segments.label = imdb.segments.materialClass ;

% now remove all the segments that belong to classes that are not in use
ok = logical(imdb.meta.inUse(imdb.segments.label)) ;
imdb.segments = soaSubsRef(imdb.segments, ok) ;

% finally, merge the background classes
% bkg = [18 25]
imdb.segments.label(imdb.segments.label == 25) = 18 ;
imdb.meta.inUse(25) = false ;
imdb.meta.classes{18} = 'other' ;
imdb.meta.classes{25} = 'other' ;

% no difficult regions by default
imdb.segments.difficult = false(1, numel(imdb.segments.id)) ;


function drawlayers(varargin)
%*************************************************
%DATE: 11/8/2007 (created); 	11/8/2007 (modified)
%FUNCTION:	draw layers according to Layerstructure
%INPUTS:	layer structure matrix
%OUTPUTS:	NULL
%muwn.gu@gmail.com
%*************************************************
global Layerprofile;
global layerMatrix;
global layerColor;
layerNrm =  max(max(layerMatrix));
matrixSize =  size(layerMatrix);
lineNrm   =  matrixSize(1,1);
lineLength=  matrixSize(1,2);

for lineIndex = 1: lineNrm	% for layers

	for realLayerIndex = 1 : layerNrm    % for different layers

		if (layerMatrix(lineIndex, 1) == realLayerIndex)
			seg.from = 0;
		end

		for pointIndex = 1 : (lineLength-1)	% for point in one layer

			if (~(layerMatrix(lineIndex, pointIndex) == realLayerIndex)) & (layerMatrix(lineIndex, pointIndex + 1) == realLayerIndex)
			seg.from = (pointIndex)/(lineLength);
			end

			if (layerMatrix(lineIndex, pointIndex) == realLayerIndex) & (~(layerMatrix(lineIndex, pointIndex + 1) == realLayerIndex))
			seg.end = (pointIndex)/(lineLength);
			fillColor	= getlayercolor (realLayerIndex);
			drawsegment (seg, fillColor);
			end
		end

		if (layerMatrix(lineIndex, lineLength) == realLayerIndex)
			seg.end = 1;
			fillColor	= getlayercolor (realLayerIndex);
			drawsegment (seg, fillColor);
		end
	end
			Layerprofile.currentY = Layerprofile.currentY + Layerprofile.lineWidth;
end

Layerprofile.currentY =  Layerprofile.currentY + Layerprofile.stepSpace;

function drawsegment(seg, fillcolor)
%*************************************************
%DATE: 11/8/2007 (created); 	11/8/2007 (modified)
%FUNCTION:
%INPUTS:
%OUTPUTS:
%*************************************************
global Layerprofile;
			xfrom 	= Layerprofile.diameter * seg.from;
			xrange 	= Layerprofile.diameter * seg.end - xfrom;
			rectangle('Position',[Layerprofile.origin.x + xfrom, Layerprofile.currentY, xrange , Layerprofile.lineWidth], 'FaceColor', fillcolor, 'LineStyle', 'none')

function fillColor = getlayercolor(layerIndex)
%*************************************************
%FUNCTION:
%INPUTS:
%OUTPUTS:
%*************************************************
global 	Layerprofile;
switch	layerIndex
	case 1
		fillColor =  Layerprofile.color.silicon;
	case 2
		fillColor =  Layerprofile.color.sidioxi;
	case 3
		fillColor =  Layerprofile.color.metal;
	case 4
		fillColor =  Layerprofile.color.sini;
	case 5
		fillColor =  Layerprofile.color.posi;
	case 9
		fillColor =  Layerprofile.color.phore;
	otherwise
		fillColor = [1, 1, 1];
end


function output = rdivide(input1, input2)

if ~iscell(input1)
  input1 = repmat({input1}, size(input2));
end
if ~iscell(input2)
  input2 = repmat({input2}, size(input1));
end
output = cellfun(@rdivide, input1, input2, 'uniformoutput', false);


function h = ldivide( f, g )
%.\   Pointwise SEPARABLEAPPROX left array divide.
%   F.\G if G is a SEPARABLEAPPROX and F is a double this returns (1/F)*G
%
%   F.\G if G is a double and F is a SEPARABLEAPPROX this returns G\F, but this does
%   not work if F becomes numerically close to zero.
%
%   F.\G we do not allow F and G to both be SEPARABLEAPPROX objects.
%
%   F.\G is the same as the command ldivide(F,G)

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

h = rdivide( g, f );

end


function ind = meegchannels(this, modality)
% Return indices of M/EEG channels
% FORMAT ind = meegchannels(this, modality)
%
%  this      - MEEG object
%  modality  - one of EEG, LFP, MEG (excluding planar), MEGPLANAR [optional]
%
%  ind       - row vector of M/EEG channels
%
% See also eogchannels, ecgchannels, emgchannels
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Stefan Kiebel
% $Id: meegchannels.m 5045 2012-11-09 15:53:23Z vladimir $

type = chantype(this);

if nargin == 1
    ind = find(ismember(upper(type), ...
        {'EEG', 'MEG', 'MEGMAG', 'MEGGRAD', 'MEGPLANAR', 'REF', 'REFMAG', 'REFGRAD', 'LFP'}));
else
    switch modality
        case 'EEG'
            ind = find(ismember(upper(type), {'EEG'}));
        case 'LFP'
            ind = find(ismember(upper(type), {'LFP'}));
        case 'MEG'
            ind = find(ismember(upper(type), {'MEG', 'MEGMAG', 'MEGGRAD'}));
        case 'MEGMAG'
            ind = find(ismember(upper(type), {'MEGMAG'}));
        case 'MEGPLANAR'
            ind = find(ismember(upper(type), {'MEGPLANAR'}));
        case 'MEGGRAD'
            ind = find(ismember(upper(type), {'MEGGRAD'}));
        case 'MEEG'
            ind = find(ismember(upper(type), {'EEG', 'MEG', 'MEGMAG', 'MEGGRAD', 'MEGPLANAR'}));
        otherwise
            error('Unsupported modality.');
    end
end

ind = ind(:)'; % must be row to allow to use it as loop indices


%FASTNLMEANSDENOISINGCOLORED  Modification of fastNlMeansDenoising function for colored images
%
%     dst = cv.fastNlMeansDenoisingColored(src)
%     dst = cv.fastNlMeansDenoisingColored(src, 'OptionName',optionValue, ...)
%
% ## Input
% * __src__ Input 8-bit 3-channel or 4-channel image.
%
% ## Output
% * __dst__ Output image with the same size and type as `src`.
%
% ## Options
% * __H__ Parameter regulating filter strength for luminance component. Bigger
%   `H` value perfectly removes noise but also removes image details, smaller
%   `H` value preserves details but also preserves some noise. default 3
% * __HColor__ The same as `H` but for color components. For most images value
%   equals 10 will be enough to remove colored noise and do not distort
%   colors. default 3
% * __TemplateWindowSize__ Size in pixels of the template patch that is used
%   to compute weights. Should be odd. Recommended value 7 pixels. default 7
% * __SearchWindowSize__ Size in pixels of the window that is used to compute
%   weighted average for given pixel. Should be odd. Affect performance
%   linearly: greater `SearchWindowsSize` - greater denoising time.
%   Recommended value 21 pixels. default 21
% * __FlipChannels__ whether to flip the order of color channels in input
%   `src` and output `dst`, between MATLAB's RGB/RGBA order and OpenCV's
%   BGR/BGRA (input: RGB/RGBA->BGR/BGRA, output: BGR/BGRA->RGB/RGBA).
%   default false
%
% The function converts image to CIELAB colorspace and then separately denoise
% L and AB components with given `H` parameters using cv.fastNlMeansDenoising
% function.
%
% See also: cv.fastNlMeansDenoising, cv.fastNlMeansDenoisingMulti,
%  cv.fastNlMeansDenoisingColoredMulti
%


function cMap=kwJet(varargin)

switch nargin
    case 0
        n=250;
    case 1
        n=varargin{1};
end

cMap=[0 0 0; gjet(4); 1 1 1];

[cMap]=resampleColormap(cMap,n);

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% 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/>.


function [text] = writeTXT(para,fname_out)
% Write a txt file for online PD map to highlight specific reaction nodes.
%
% USAGE:
%
%    [text] = writeTXT(para, fname_out)
%
% INPUTS:
%    para:           A variable that stores two columns: the first column
%                    contains a list of reaction names,whereas the second
%                    column contains a corresponding list of the colours (Hex
%                    triplet, e.g.,
%                    https://closedxml.codeplex.com/wikipage?title=Excel%20Indexed%20Colors)
%    fanme_out:      The name of the output text file name.
%
% OPTIONAL OUTPUT:
%    text:           The lines of the text file
%
% .. Author: - Longfei Mao Oct/2014

if nargin<2 || isempty(fname_out)

    [fname_out, fpath]=uiputfile('*.txt','for Online PD map');
    if(fname_out==0)
        return;
    end
    f_out=fopen([fpath,fname_out],'w');
else
    f_out=fopen(fname_out,'w');
end

%%%%%%%%%%%% read

% blank={' '}
[r,c]=size(para)

if c==1;
    para(:,2)={'#FF0000FF'}; % By default, the colour hex code is set to be red.
end

if ~isempty(strfind(para{1,2},'#'))||~isempty(strfind(para{1,2},'FF'))
    r=r+1;
    s=2;
    text{1,1}=['name', ' ', 'color']; % add title row;
else
    s=1;r=r+1;
end

for rr=s:r; % content rows + one title row
    name=para{rr-1,1};

    if ~isempty(para{rr-1,2});
        color=para{rr-1,2};

        if length(color)>6;
            st=strfind(color,'FF');  % remove 'FF' necessary for CellDesigner files
            if ~isempty(st)
                color=color(st+2:end);
            end
            if isempty(strfind(color,'#'));  % add # in front of the color code.
                color=['#',color];
                %errordlg('The format of the colour code is not correct');
            end

        end

    end

    %     if rr==s;
    %         text{1,1}=['name',' ', 'color'];
    %
    %     else
    text{rr,1}=[name,' ',color];

end

%%%%%%% Write to the file %%%%

for d=1:length(text);

    fprintf(f_out,'%s\n',text{d});

end

fclose(f_out);

end


% preproc_vbm_simplified - preprocessing for voxel-based morphometry
%
% Need to specify:
% * Structural images for all subjects
%__________________________________________________________________________
% Copyright (C) 2014 Wellcome Trust Centre for Neuroimaging

% Ged Ridgway
% $Id: preproc_vbm_simplified.m 6177 2014-09-16 10:44:55Z guillaume $

if exist('preproc_vbm_simplified', 'file') && ~isdeployed
    help preproc_vbm_simplified
end
matlabbatch = {};

%% Segmentation
iSeg = 1;
ngaus  = [1 1 2 3 4 2];
native = [
    1 0 0 0 0 0
    1 1 0 0 0 0];
for c = 1:6 % tissue class c
    matlabbatch{iSeg}.spm.spatial.preproc.tissue(c).tpm = {
        fullfile(spm('dir'), 'tpm', sprintf('TPM.nii,%d', c))};
    matlabbatch{iSeg}.spm.spatial.preproc.tissue(c).ngaus = ngaus(c);
    matlabbatch{iSeg}.spm.spatial.preproc.tissue(c).native = native(:, c)';
    matlabbatch{iSeg}.spm.spatial.preproc.tissue(c).warped = [0 0];
end

%%
iDar = 2;
matlabbatch{iDar}.spm.tools.dartel.warp.images{1}(1) = ...
    cfg_dep('Segment: rc1 Images', substruct('.','val', '{}',{iSeg}, ...
    '.','val', '{}',{1}, '.','val', '{}',{1}), ...
    substruct('.','tiss', '()',{1}, '.','rc', '()',{':'}));
matlabbatch{iDar}.spm.tools.dartel.warp.images{2}(1) = ...
    cfg_dep('Segment: rc2 Images', substruct('.','val', '{}',{iSeg}, ...
    '.','val', '{}',{1}, '.','val', '{}',{1}), ...
    substruct('.','tiss', '()',{2}, '.','rc', '()',{':'}));

%% Normalise segmentations to MNI space
iNS = 3;
matlabbatch{iNS}.spm.tools.dartel.mni_norm.template(1) = ...
    cfg_dep('Run Dartel (create Templates): Template (Iteration 6)', ...
    substruct('.','val', '{}',{iDar}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), ...
    substruct('.','template', '()',{7}));
matlabbatch{iNS}.spm.tools.dartel.mni_norm.data.subjs.flowfields(1) = ...
    cfg_dep('Run Dartel (create Templates): Flow Fields', ...
    substruct('.','val', '{}',{iDar}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), ...
    substruct('.','files', '()',{':'}));
matlabbatch{iNS}.spm.tools.dartel.mni_norm.data.subjs.images{1}(1) = ...
    cfg_dep('Segment: c1 Images', ...
    substruct('.','val', '{}',{iSeg}, '.','val', '{}',{1}, '.','val', '{}',{1}), ...
    substruct('.','tiss', '()',{1}, '.','c', '()',{':'}));
matlabbatch{iNS}.spm.tools.dartel.mni_norm.preserve = 1;
matlabbatch{iNS}.spm.tools.dartel.mni_norm.fwhm = [8 8 8];

%% If run as script, open matlabbatch GUI
% NB mfilename is cfg_load_jobs if loaded from matlabbatch GUI
if strcmp(mfilename, 'preproc_vbm_simplified')
    spm_jobman('interactive', matlabbatch)
end


function aux_movingwindow(params, hParentFigure)
% function aux_FMD(params, hParentFigure);
%-------------------------------------------
%
% Incoming variables:
% params        : all variables
% hParentFigure : Handle of the parent figure
%
% Thomas van Stiphout, thomas@sed.ethz.ch
% last update: 7.9.2005

report_this_filefun(mfilename('fullpath'));

fStartTime_ = params(1).fStartTime;
fTimeCut_   = params(1).fTimeCut;
vTimeCut_=[params(1).fStartTime+params(1).fTwLength:1:params(1).fTimeCut]
for i = 1:1:length(vTimeCut_)
    params(i).fTimeCut = vTimeCut_(i);
    params(i)=sr_calcZ(params(i))
    % Add parameter to params.sComment
     params(i).sComment = [params(i).rContainer ' Time Cut ' num2str(params(i).fTimeCut) ...
                   ', Time period ' num2str(params(i).fTwLength) ' yrs'];
    if i<length(vTimeCut_)
        params=[params;params(1)]
    end
end
gui_result(params(:))
clear fStartTime_ fTimeCut_ vTimeCut_ i


function [sFile, ChannelMat] = in_fopen_smr(DataFile)
% IN_FOPEN_SMR: Open a Cambridge Electronic Design Spike2 file (.smr/.son).

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors:  Malcolm Lidierth, 2006-2007, King's College London
%           Adapted by Francois Tadel for Brainstorm, 2017-2021

%% ===== READ HEADER =====
% Get file type
[fPath, fBase, fExt]=fileparts(DataFile);
if strcmpi(fExt,'.smr') || strcmpi(fExt,'.smrx')
    byteorder = 'l';  % Spike2 for Windows source file: little-endian
elseif strcmpi(fExt,'.son')
    byteorder = 'b';  % Spike2 for Mac file: Big-endian
else
    error('Not a Spike2 file.');
end
% Open file
fid = fopen(DataFile, 'r', byteorder);
if (fid == -1)
    error('Could not open file.');
end

% Get file header
hdr = SONFileHeader(fid);
% Get list of channels
iChan = 0;
iMarkerChan = [];
for i = 1:hdr.channels
    bst_progress('text', sprintf('Reading channel info... [%d%%]', round(i/hdr.channels*100)));
    % Read channel information
    c = SONChannelInfo(fid, i);
    % Check type of the channel
    switch c.kind
        % ADC channels: read as signals
        case {1,9}
            iChan = iChan + 1;
            hdr.chaninfo(iChan).number    = i;
            hdr.chaninfo(iChan).kind      = c.kind;
            hdr.chaninfo(iChan).title     = c.title;
            hdr.chaninfo(iChan).comment   = c.comment;
            hdr.chaninfo(iChan).phyChan   = c.phyChan;
            hdr.chaninfo(iChan).idealRate = c.idealRate;
            % Read blocks
            hdr.chaninfo(iChan).blocks = SONGetBlockHeaders(fid, i);
        % Markers and events
        case {2,3,4,5,6,7,8}
        	iMarkerChan(end+1) = i;
    end
end
hdr.num_channels = length(hdr.chaninfo);
% Get maximum sampling rate
[sfreq, chMax] = max([hdr.chaninfo.idealRate]);

%% ===== FILL STRUCTURE =====
% Initialize returned file structure
sFile = db_template('sfile');
% Add information read from header
sFile.byteorder    = byteorder;
sFile.filename     = DataFile;
sFile.format       = 'EEG-SMR';
sFile.prop.sfreq   = sfreq;
sFile.prop.times   = [0, sum(hdr.chaninfo(chMax).blocks(5,:)) - 2] ./ sFile.prop.sfreq;
sFile.prop.nAvg    = 1;
sFile.channelflag  = ones(hdr.num_channels,1);
sFile.device       = 'CED Spike2';
sFile.header       = hdr;
% Comment: short filename
[fPath, fBase, fExt] = bst_fileparts(DataFile);
sFile.comment = fBase;

%% ===== CREATE EMPTY CHANNEL FILE =====
ChannelMat = db_template('channelmat');
ChannelMat.Comment = [sFile.device ' channels'];
ChannelMat.Channel = repmat(db_template('channeldesc'), [1, hdr.num_channels]);
% For each channel
for iChan = 1:hdr.num_channels
    ChannelMat.Channel(iChan).Type = 'EEG';
    ChannelMat.Channel(iChan).Name = hdr.chaninfo(iChan).title;
end

%% ===== READ MARKER INFORMATION =====
iChanMissing = [];
for iChan = 1:length(iMarkerChan)
    % Read channel
    try
        [d,header] = SONGetChannel(fid, iMarkerChan(iChan));
    catch
        iChanMissing = [iChanMissing, iMarkerChan(iChan)];
        continue;
    end
    if isempty(d) || isempty(header)
        continue;
    end
    % Get timing
    switch (header.kind)
        case {2,3,4}
            timeEvt = d(:)';
        case {5,6,7,8}
            timeEvt = d.timings(:)';
    end
    % Create event structure
    iEvt = length(sFile.events) + 1;
    if ~isempty(header.title)
        sFile.events(iEvt).label = header.title;
    else
        sFile.events(iEvt).label = sprintf('unknown_%02d', iEvt);
    end
    sFile.events(iEvt).times    = round(double(timeEvt).* sFile.prop.sfreq) ./ sFile.prop.sfreq;
    sFile.events(iEvt).epochs   = ones(size(sFile.events(iEvt).times));
    sFile.events(iEvt).select   = 1;
    sFile.events(iEvt).channels = [];
    sFile.events(iEvt).notes    = [];
end
% Display missing channels
if ~isempty(iChanMissing)
    disp(['SON> Missing channels: ' sprintf('%d ', iChanMissing)]);
end

% Close file
fclose(fid);


function T1 = uminus(T1)
% unary minus

T1.M = -T1.M;


% This package contains code for the "CRF-RNN" semantic image segmentation method, published in the
% ICCV 2015 paper Conditional Random Fields as Recurrent Neural Networks. Our software is built on
% top of the Caffe deep learning library.
%
% Contact:
% Shuai Zheng (szheng@robots.ox.ac.uk), Sadeep Jayasumana (sadeep@robots.ox.ac.uk), Bernardino Romera-Paredes (bernard@robots.ox.ac.uk)
%
% Supervisor:
% Philip Torr (philip.torr@eng.ox.ac.uk)
%
% For more information about CRF-RNN please vist the project website http://crfasrnn.torr.vision.
%

caffe_path = '../caffe/';

model_def_file = 'TVG_CRFRNN_new_deploy.prototxt';
model_file = 'TVG_CRFRNN_COCO_VOC.caffemodel';

if exist(model_file, 'file') ~= 2
    error('You need a network model file. Please download our default model by running ./download_trained_model.sh');
end

use_gpu = 1; % Set this to 0 if you don't have a GPU.
gpu_id = 0;% which gpu device id you are using?

addpath(fullfile(caffe_path, 'matlab'));

caffe.reset_all();

net = tvg_matcaffe_init(use_gpu, gpu_id, model_def_file, model_file);

im = imread('input.jpg');

[h, w, d] = size(im);

if (d ~= 3)
   error('Error! Wrong depth.\n');
end

if (h > 500 || w > 500)
   error('Error! Wrong image size.\n');
end

prepared_im = tvg_prepare_image_fixed(im);

inputData = {prepared_im};
scores = net.forward(inputData);

Q = scores{1};

[dumb, pred] = max(Q, [], 3);
pred = pred';
pred = pred(1:h, 1:w);

load map.mat
imwrite(pred, map, 'output.png', 'png');


classdef ImageProcessingComputer < handle

    properties (Access = public)
        computation
        variables
    end

    properties (Access = private)
        testName
        imageProblem
    end

    methods (Access = public)
        function obj = ImageProcessingComputer(cParams)
            obj.testName = cParams.testName;
        end

        function compute(obj)
            problemName  = obj.testName;
            sLoader      = SettingsLoader(problemName);
            settings     = sLoader.settings;
            imProblem = DenoisingProblem(settings);
            imProblem.solve();
            obj.imageProblem = imProblem;
            obj.variables = imProblem;
            obj.computation = obj;
        end
    end
end


function dip = fixdipole(dip)

% FIXDIPOLE ensures that the dipole position and moment are
% consistently represented throughout FieldTrip functions.

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

[m, n] = size(dip.pos);

if n==3
  % the input representation is Nx3, which is what we want
elseif m==3
  % it is possible to translate it into a Nx3 unambiguously
  warning('input dipole positions should be specified as Nx3 matrix');
  dip.pos = dip.pos';
elseif m==1
  % it is possible to translate it into a Nx3 unambiguously
  warning('input dipole positions should be specified as Nx3 matrix');
  dip.pos = reshape(dip.pos, 3, n/3)';
else
  % it is not clear how to convert to a Nx3 matrix
  error('input dipole positions should be specified as Nx3 matrix');
end

if isfield(dip, 'mom')
  ndip = size(dip.pos,1);
  if numel(dip.mom)==ndip*3
    ntime = 1;
  else
    ntime = numel(dip.mom)/(ndip*3);
  end
  dip.mom = reshape(dip.mom, ndip*3, ntime);
end


function Do_clustering(input, varargin)

% PROGRAM Do_clustering.
% Does clustering on all files in Files.txt
% Runs after Get_spikes, which prepares '*_spikes.mat' files.
%
% function Do_clustering(input, par_input)
% Saves spikes, spike times (in ms), coefficients used (inspk), used
% parameters, random spikes selected for clustering (ipermut) and
% results (cluster_class).
%
%input must be:
%               A .txt file with the names of the '*_spikes.mat' files to use.
%               A matlab cell with the names of the '*_spikes.mat' files to use.
%               A vector with channel numbers. In this case the function
%                   will proccess all the '*_spikes.mat' files located in
%                   the folder with those channel numbers (e.g., CSC1_spikes.mat or NSX4_spikes.mat)
%               'all', in this case the functions will process all the
%                   '*_spikes.mat' files in the folder.
%               A string with a filename ended in '_spikes.mat'
% optional argument 'par' and the next input must be a struct with some of
%       the SPC parameters (the detection parameters are taken from the
%       XXX_spikes file or the set_parameters file. All the parameters included
%       in the structure par will overwrite the parameters loaded from set_parameters()
% optional argument 'parallel' : true for use parallel computing.
% optional argument 'make_times': true for computing the sorting from the XXX_spikes files.
% optional argument 'make_plots': true for plotting the results based on the save XXX_times files.
% optional argument 'resolution': resolution string used by the plots (default: '-r150').
% optional argument 'save_spikes': false for disable saving all the spikes
% waveforms on the times* file.
% See also
% Get_spikes

% Example
% param.min_clus = 60;
% param.max_spk = 50000;
% par.maxtemp = 0.251;
% Do_clustering(1:16,'parallel',true,'par',param)
%
% If the times were created but something went wrong with the plots. Then, the
% code can be called again just to create the plots:
% Do_clustering(1:16,'make_times',false,'par',param)
%
%
% Similarly, for don't create the plots:
% Do_clustering(1:16,'make_plots',false,'par',param)
%

min_spikes4SPC = 16; % if are less that this number of spikes, clustering won't be made.

%default config
par_input = struct;
parallel = false;
make_times = true;
make_plots = true;
resolution = '-r150';
save_spikes = true;
%search for optional inputs
nvar = length(varargin);
for v = 1:nvar
    if strcmp(varargin{v},'par')
        if (nvar>=v+1) && isstruct(varargin{v+1})
            par_input = varargin{v+1};
        else
            error('Error in ''par'' optional input.')
        end
    elseif strcmp(varargin{v},'parallel')
        if (nvar>=v+1) && islogical(varargin{v+1})
            parallel = varargin{v+1};
        else
            error('Error in ''parallel'' optional input.')
        end
    elseif strcmp(varargin{v},'make_times')
        if (nvar>=v+1) && islogical(varargin{v+1})
            make_times = varargin{v+1};
        else
            error('Error in ''make_times'' optional input.')
        end
    elseif strcmp(varargin{v},'make_plots')
        if (nvar>=v+1) && islogical(varargin{v+1})
            make_plots = varargin{v+1};
        else
            error('Error in ''make_plots'' optional input.')
        end
    elseif strcmp(varargin{v},'resolution')
        if (nvar>=v+1) && ischar(varargin{v+1})
            resolution = varargin{v+1};
        else
            error('Error in ''resolution'' optional input.')
        end
    elseif strcmp(varargin{v},'save_spikes')
        if (nvar>=v+1) && islogical(varargin{v+1})
            save_spikes = varargin{v+1};
        else
            error('Error in ''save_spikes'' optional input.')
        end

    end
end

run_par_for = parallel;

% get a cell of filenames from the input
if isnumeric(input) || any(strcmp(input,'all'))  %cases for numeric or 'all' input
    filenames = {};
    dirnames = dir();
    dirnames = {dirnames.name};

    for i = 1:length(dirnames)
        fname = dirnames{i};

        if length(fname) < 12
            continue
        end
        if ~ strcmp(fname(end-10:end),'_spikes.mat')
            continue
        end
        if strcmp(input,'all')
            filenames = [filenames {fname}];
        else
            aux = regexp(fname, '\d+', 'match');
            if ~isempty(aux) && ismember(str2num(aux{1}),input)
                filenames = [filenames {fname}];
            end
        end
    end

elseif ischar(input) && length(input) > 4
    if  strcmp (input(end-3:end),'.txt')   %case for .txt input
        filenames =  textread(input,'%s');
    else
        filenames = {input};               %case for cell input
    end

elseif iscellstr(input)
    filenames = input;
else
    ME = MException('MyComponent:noValidInput', 'Invalid input arguments');
    throw(ME)
end

tic
par_file = set_parameters();
if make_times
% open parallel pool, if parallel input is true
    if parallel == true
        if exist('matlabpool','file')
            try
                matlabpool('open');
            catch
                parallel = false;
            end
        else
            poolobj = gcp('nocreate'); % If no pool, do not create new one.
            if isempty(poolobj)
                parpool
            else
                parallel = false;
            end
        end
    end

    initial_date = now;
    Nfiles = length(filenames);
    if run_par_for == true
        parfor fnum = 1:Nfiles
            filename = filenames{fnum};
            do_clustering_single(filename,min_spikes4SPC, par_file, par_input,fnum,save_spikes);
            disp(sprintf('%d of %d ''times'' files finished.',count_new_times(initial_date, filenames),Nfiles))
        end
    else
        for fnum = 1:length(filenames)
            filename = filenames{fnum};
            do_clustering_single(filename,min_spikes4SPC, par_file, par_input,fnum,save_spikes);
            disp(sprintf('%d of %d ''times'' files finished.',count_new_times(initial_date, filenames),Nfiles))
        end
    end
    if parallel == true
        if exist('matlabpool','file')
            matlabpool('close')
        else
            poolobj = gcp('nocreate');
            delete(poolobj);
        end
    end

	log_name = 'spc_log.txt';
	f = fopen(log_name, 'w');
	for fnum = 1:length(filenames)
        filename = filenames{fnum};
        log_name = [filename 'spc_log.txt'];
        if exist(log_name, 'file')
			fi = fopen(log_name,'r');
			result = fread(fi);
			fwrite(f,result);
			fclose(fi);
			delete(log_name);
		end
    end
	fclose(f);

	tocaux = toc;
    disp(['Computations Done (' num2str(tocaux,'%2.2f') 's).'])
end

if make_plots
    disp('Creating figures...')
    numfigs = length(filenames);
    curr_fig = figure('Visible','Off');
    curr_fig2 = figure('Visible','Off');
    set(curr_fig, 'PaperUnits', 'inches', 'PaperType', 'A4', 'PaperPositionMode', 'auto','units','normalized','outerposition',[0 0 1 1],'RendererMode','manual','Renderer','painters')
    set(curr_fig2, 'PaperUnits', 'inches', 'PaperType', 'A4', 'PaperPositionMode', 'auto','units','normalized','outerposition',[0 0 1 1],'RendererMode','manual','Renderer','painters')
    if isfield(get(curr_fig),'GraphicsSmoothing')
        set(curr_fig,'GraphicsSmoothing','off');
        set(curr_fig2,'GraphicsSmoothing','off');
    end

    for fnum = 1:numfigs
        clf(curr_fig2)
        clf(curr_fig)
        set(0, 'CurrentFigure', curr_fig)
        filename = filenames{fnum};
        par = struct;
        par.filename = filename;

        par.cont_segment = true;  %maybe true and save the sample in spikes

        data_handler = readInData(par);
        par = data_handler.update_par(par);

        par = update_parameters(par,par_file,'batch_plot');
        par = update_parameters(par,par_input,'batch_plot');

        if ~data_handler.with_wc_spikes       			%data should have spikes
            continue
        end
        filename = data_handler.nick_name;

        file_pos_names = {'','a','b','c','d','e','f'};
        for i=1:length(file_pos_names)
            new_file_name = ['fig2print_' filename file_pos_names{i} '.png'];
            if exist(new_file_name, 'file')==2
                delete(new_file_name);
            end
        end

        subplot(3,1,1)
        if par.cont_segment && data_handler.with_psegment
            box off; hold on
            %these lines are for plotting continuous data
            [xd_sub, sr_sub] = data_handler.get_signal_sample();
            lx = length(xd_sub);
            plot((1:lx)/sr_sub,xd_sub)
            noise_std_detect = median(abs(xd_sub))/0.6745;
            xlim([0 lx/sr_sub])
            thr = par.stdmin * noise_std_detect;
            plotmax = 15 * noise_std_detect; %thr*par.stdmax/par.stdmin;

            if strcmp(par.detection,'pos')
                line([0 length(xd_sub)/sr_sub],[thr thr],'color','r')
                ylim([-plotmax/2 plotmax])
            elseif strcmp(par.detection,'neg')
                line([0 length(xd_sub)/sr_sub],[-thr -thr],'color','r')
                ylim([-plotmax plotmax/2])
            else
                line([0 length(xd_sub)/sr_sub],[thr thr],'color','r')
                line([0 length(xd_sub)/sr_sub],[-thr -thr],'color','r')
                ylim([-plotmax plotmax])
            end
        end
        title([pwd '/' filename],'Interpreter','none','Fontsize',14)

        if ~data_handler.with_spc
            print2file = par_file.print2file;
            if isfield(par_input,'print2file')
                print2file = par_input.print2file;
            end
            if print2file
                print(curr_fig,'-dpng',['fig2print_' filename '.png'],resolution);
            else
                print(curr_fig)
            end
            clear print2file
            fprintf('%d figs Done. ',fnum);
            continue
        end

        % LOAD SPIKES
        [clu, tree, spikes, index, inspk, ipermut, classes, forced,temp] = data_handler.load_results();
        nspk = size(spikes,1);
        Mclasses = max(classes);
        auto_sort_info = [];
        if data_handler.with_gui_status
            [original_classes, current_temp, auto_sort_info] = data_handler.get_gui_status();
            temperature = par.mintemp+current_temp*par.tempstep;
            org_class = zeros(1,Mclasses);
            for i = 1:Mclasses
                org_class(i) = original_classes(find(classes==i,1,'first'));
            end
        else
            [temp] = find_temp_old(tree,par);
            temp = ones(max(classes),1)*temp;
            org_class = 1:max(classes);
            temperature = par.mintemp+temp*par.tempstep;
        end

        %PLOTS
        clus_pop = [];
        ylimit = [];
        subplot(3,5,11)

        color = [[0.0 0.0 1.0];[1.0 0.0 0.0];[0.0 0.5 0.0];[0.620690 0.0 0.0];[0.413793 0.0 0.758621];[0.965517 0.517241 0.034483];
        [0.448276 0.379310 0.241379];[1.0 0.103448 0.724138];[0.545 0.545 0.545];[0.586207 0.827586 0.310345];
        [0.965517 0.620690 0.862069];[0.620690 0.758621 1.]];
        maxc = size(color,1);

        hold on
        num_temp = floor((par.maxtemp -par.mintemp)/par.tempstep);     % total number of temperatures
        switch par.temp_plot
                case 'lin'
                   if ~isempty(auto_sort_info)
                        [xp, yp] = find(auto_sort_info.peaks);
                        ptemps = par.mintemp+(xp)*par.tempstep;
                        psize = tree(sub2ind(size(tree), xp,yp+4));
                        plot(ptemps,psize,'xk','MarkerSize',7,'LineWidth',0.9);
                        area(par.mintemp+par.tempstep.*[auto_sort_info.elbow,num_temp],max(ylim).*[1 1],'LineStyle','none','FaceColor',[0.9 0.9 0.9]);
                    end
                    plot([par.mintemp par.maxtemp-par.tempstep], ...
                    [par.min_clus par.min_clus],'k:',...
                    par.mintemp+(1:num_temp)*par.tempstep, ...
                    tree(1:num_temp,5:size(tree,2)),[temperature temperature],[1 tree(1,5)],'k:')
                    for i=1:Mclasses
                        tree_clus = tree(temp(i),4+org_class(i));
                        tree_temp = tree(temp(i)+1,2);
                        plot(tree_temp,tree_clus,'.','color',color(mod(i-1,maxc)+1,:),'MarkerSize',20);
                    end
                case 'log'
                    set(gca,'yscale','log');
                    if ~isempty(auto_sort_info)
                        [xp, yp] = find(auto_sort_info.peaks);
                        ptemps = par.mintemp+(xp)*par.tempstep;
                        psize = tree(sub2ind(size(tree), xp,yp+4));
                        semilogy(ptemps,psize,'xk','MarkerSize',7,'LineWidth',0.9);
                        area(par.mintemp+par.tempstep.*[auto_sort_info.elbow,num_temp],max(ylim).*[1 1],'LineStyle','none','FaceColor',[0.9 0.9 0.9],'basevalue',1);
                    end
                    semilogy([par.mintemp par.maxtemp-par.tempstep], ...
                    [par.min_clus par.min_clus],'k:',...
                    par.mintemp+(1:num_temp)*par.tempstep, ...
                    tree(1:num_temp,5:size(tree,2)),[temperature temperature],[1 tree(1,5)],'k:')

                    for i=1:Mclasses
                        tree_clus = tree(temp(i),4+org_class(i));
                        tree_temp = tree(temp(i)+1,2);
                        semilogy(tree_temp,tree_clus,'.','color',color(mod(i-1,maxc)+1,:),'MarkerSize',20);
                    end
        end
        xlim([par.mintemp, par.maxtemp])
        subplot(3,5,6)
        hold on

        class0 = find(classes==0);
            max_spikes=min(length(class0),par.max_spikes_plot);
            plot(spikes(class0(1:max_spikes),:)','k');
            xlim([1 size(spikes,2)]);
        subplot(3,5,10);
            hold on
            plot(spikes(class0(1:max_spikes),:)','k');
            plot(mean(spikes(class0,:),1),'c','linewidth',2)
            xlim([1 size(spikes,2)]);
            title(['Cluster 0: # ' num2str(length(class0))],'Fontweight','bold')
        subplot(3,5,15)
            xa=diff(index(class0));
            [n,c]=hist(xa,0:1:100);
            bar(c(1:end-1),n(1:end-1))
            xlim([0 100])
            xlabel('ISI (ms)');
            title([num2str(nnz(xa<3)) ' in < 3ms']);

        for i = 1:max(classes)
            set(0, 'CurrentFigure', curr_fig)
            class = find(classes==i);
            subplot(3,5,6);
            max_spikes=min(length(class),par.max_spikes_plot);
            plot(spikes(class(1:max_spikes),:)','color',color(mod(i-1,maxc)+1,:));
            xlim([1 size(spikes,2)]);

            if i<=3
                subplot(3,5,6+i);
                hold on
                plot(spikes(class(1:max_spikes),:)','color',color(mod(i-1,maxc)+1,:));
                plot(mean(spikes(class,:),1),'k','linewidth',2)
                xlim([1 size(spikes,2)]);
                title(['Cluster ' num2str(i) ': # ' num2str(length(class)) ' (' num2str(nnz(classes(:)==i & ~forced(:))) ')'],'Fontweight','bold')
                ylimit = [ylimit;ylim];
                subplot(3,5,11+i)
                xa=diff(index(class));
                [n,c]=hist(xa,0:1:100);
                bar(c(1:end-1),n(1:end-1))
                xlim([0 100])
                xlabel('ISI (ms)');
                title([num2str(nnz(xa<3)) ' in < 3ms']);

            elseif i<=8
            	  set(0, 'CurrentFigure', curr_fig2)
                subplot(3,5,2+i);
                hold on
                plot(spikes(class(1:max_spikes),:)','color',color(mod(i-1,maxc)+1,:));
                plot(mean(spikes(class,:),1),'k','linewidth',2)
                xlim([1 size(spikes,2)]);
                title(['Cluster ' num2str(i) ': # ' num2str(length(class)) ' (' num2str(nnz(classes(:)==i & ~forced(:))) ')'],'Fontweight','bold')
                ylimit = [ylimit;ylim];
                subplot(3,5,7+i)
                xa=diff(index(class));
                [n,c]=hist(xa,0:1:100);
                bar(c(1:end-1),n(1:end-1))
                xlim([0 100])
                xlabel('ISI (ms)');
                title([num2str(nnz(xa<3)) ' in < 3ms']);
            end
        end
        numclus = max(classes);
        % Rescale spike's axis
        if ~isempty(ylimit)
            ymin = min(ylimit(:,1));
            ymax = max(ylimit(:,2));
            set(0, 'CurrentFigure', curr_fig)
            for i = 1:min(3,numclus)
               subplot(3,5,6+i); ylim([ymin ymax]);
            end
            set(0, 'CurrentFigure', curr_fig2)
            for i = 4:min(8,numclus)
               subplot(3,5,2+i); ylim([ymin ymax]);
            end

        end

        features_name = par.features;

        outfileclus='cluster_results.txt';
        fout=fopen(outfileclus,'at+');
        if isfield(par,'stdmin')
            stdmin = par.stdmin;
        else
            stdmin = NaN;
        end
        fprintf(fout,'%s\t %s\t %g\t %d\t %g\t', char(filename), features_name, temperature, numclus, stdmin);
        for ii=0:numclus
            fprintf(fout,'%d\t',nnz(classes==ii));
        end
        fclose(fout);

        if par.print2file
            print(curr_fig,'-dpng',['fig2print_' filename '.png'],resolution);
            if numclus>3
                print(curr_fig2,'-dpng',['fig2print_' filename 'a.png'],resolution);
            end
        else
            print(curr_fig)
            if numclus>3
                print(curr_fig2);
            end
        end
        fprintf('%d ',fnum);
    end
    close(curr_fig)
    close(curr_fig2)
    disp(' ')
end

toc

end

function do_clustering_single(filename,min_spikes4SPC, par_file, par_input,fnum,save_spikes)

    par = struct;
    par = update_parameters(par,par_file,'clus');
    par = update_parameters(par,par_file,'batch_plot');
    par = update_parameters(par,par_input,'clus');
    par = update_parameters(par,par_input,'batch_plot');

    par.filename = filename;
    par.reset_results = true;

    data_handler = readInData(par);
    par = data_handler.par;
    check_WC_params(par)
%     if isfield(par,'channels') && ~isnan(par.channels)
%         par.max_inputs = par.max_inputs * par.channels;
%     end

    par.fname_in = ['tmp_data_wc' num2str(fnum)];                       % temporary filename used as input for SPC
    par.fname = ['data_' data_handler.nick_name];
    par.nick_name = data_handler.nick_name;
    par.fnamespc = ['data_wc' num2str(fnum)];

    if data_handler.with_spikes            			%data have some time of _spikes files
        [spikes, index] = data_handler.load_spikes();
    else
        warning('MyComponent:noValidInput', 'File: %s doesn''t include spikes', filename);
        return
    end

    % LOAD SPIKES
    nspk = size(spikes,1);
    naux = min(par.max_spk,size(spikes,1));

    if nspk < min_spikes4SPC
        warning('MyComponent:noValidInput', 'Not enough spikes in the file');
        return
    end

    % CALCULATES INPUTS TO THE CLUSTERING ALGORITHM.
    inspk = wave_features(spikes,par);     %takes wavelet coefficients.
    par.inputs = size(inspk,2);                       % number of inputs to the clustering

	if par.permut == 'n'
        % GOES FOR TEMPLATE MATCHING IF TOO MANY SPIKES.
        if size(spikes,1)> par.max_spk;
            % take first 'par.max_spk' spikes as an input for SPC
            inspk_aux = inspk(1:naux,:);
        else
            inspk_aux = inspk;
        end
	else
        % GOES FOR TEMPLATE MATCHING IF TOO MANY SPIKES.
        if size(spikes,1)> par.max_spk;
            % random selection of spikes for SPC
            ipermut = randperm(length(inspk));
            ipermut(naux+1:end) = [];
            inspk_aux = inspk(ipermut,:);
        else
            ipermut = randperm(size(inspk,1));
            inspk_aux = inspk(ipermut,:);
        end
	end
    %INTERACTION WITH SPC
    save(par.fname_in,'inspk_aux','-ascii');
    try
        [clu, tree] = run_cluster(par,true);
		if exist([par.fnamespc '.dg_01.lab'],'file')
			movefile([par.fnamespc '.dg_01.lab'], [par.fname '.dg_01.lab'], 'f');
			movefile([par.fnamespc '.dg_01'], [par.fname '.dg_01'], 'f');
		end
    catch
        warning('MyComponent:ERROR_SPC', 'Error in SPC');
        return
    end

    [clust_num temp auto_sort] = find_temp(tree,clu,par);

    if par.permut == 'y'
        clu_aux = zeros(size(clu,1),2 + size(spikes,1)) -1;  %when update classes from clu, not selected elements go to cluster 0
        clu_aux(:,ipermut+2) = clu(:,(1:length(ipermut))+2);
        clu_aux(:,1:2) = clu(:,1:2);
        clu = clu_aux;
        clear clu_aux
    end

    classes = zeros(1,size(clu,2)-2);
    for c =1: length(clust_num)
        aux = clu(temp(c),3:end) +1 == clust_num(c);
        classes(aux) = c;
    end

    if par.permut == 'n'
        classes = [classes zeros(1,max(size(spikes,1)-par.max_spk,0))];
    end

    Temp = [];
    % Classes should be consecutive numbers
    classes_names = nonzeros(sort(unique(classes)));
    for i= 1:length(classes_names)
       c = classes_names(i);
       if c~= i
           classes(classes == c) = i;
       end
       Temp(i) = temp(i);
    end

    % IF TEMPLATE MATCHING WAS DONE, THEN FORCE
    if (size(spikes,1)> par.max_spk || ...
            (par.force_auto))
        f_in  = spikes(classes~=0,:);
        f_out = spikes(classes==0,:);
        class_in = classes(classes~=0);
        class_out = force_membership_wc(f_in, class_in, f_out, par);
        forced = classes==0;
        classes(classes==0) = class_out;
        forced(classes==0) = 0;
    else
        forced = zeros(1, size(spikes,1));
    end

    gui_status = struct();
    gui_status.current_temp =  max(temp);
    gui_status.auto_sort_info = auto_sort;
    gui_status.original_classes = zeros(size(classes));

    for i=1:max(classes)
        gui_status.original_classes(classes==i) = clust_num(i);
    end

    current_par = par;
    par = struct;
    par = update_parameters(par, current_par, 'relevant');
    par = update_parameters(par,current_par,'batch_plot');

    par.sorting_date = datestr(now);
    cluster_class = zeros(nspk,2);
    cluster_class(:,2)= index';
    cluster_class(:,1)= classes';

    vars = {'cluster_class', 'par','inspk','forced','Temp','gui_status'};
    if exist('ipermut','var')
        vars{end+1} = 'ipermut';
    end
    if save_spikes
        vars{end+1} = 'spikes';
    else
        spikes_file = filename;
        vars{end+1} = 'spikes_file';
    end

    try
      save(['times_' data_handler.nick_name],vars{:});
    catch
      save(['times_' data_handler.nick_name],vars{:},'-v7.3');
    end

end

function counter = count_new_times(initial_date, filenames)
counter = 0;
for i = 1:length(filenames)
    fname = filenames{i};
    FileInfo = dir(['times_' fname(1:end-11) '.mat']);
    if length(FileInfo)==1 && (FileInfo.datenum > initial_date)
        counter = counter + 1;
    end
end
end