%{
MIT License

Copyright (c) 2018 ZjxRS

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
%}
% This is lifted from https://github.com/ZjxRS/ImageProcess/tree/master/Matlab/ENVI_ReadAndWrite

function info = envihdrread(hdrfile)
% ENVIHDRREAD Reads header of ENVI image.
%   INFO = ENVIHDRREAD('HDR_FILE') reads the ASCII ENVI-generated image
%   header file and returns all the information in a structure of
%   parameters.
%
%   Example:
%   >> info = envihdrread('my_envi_image.hdr')
%   info =
%          description: [1x101 char]
%              samples: 658
%                lines: 749
%                bands: 3
%        header_offset: 0
%            file_type: 'ENVI Standard'
%            data_type: 4
%           interleave: 'bsq'
%          sensor_type: 'Unknown'
%           byte_order: 0
%             map_info: [1x1 struct]
%      projection_info: [1x102 char]
%     wavelength_units: 'Unknown'
%           pixel_size: [1x1 struct]
%           band_names: [1x154 char]
%
%   NOTE: This function is used by ENVIREAD to import data.

% Ian M. Howat, Applied Physics Lab, University of Washington
% ihowat@apl.washington.edu
% Version 1: 19-Jul-2007 00:50:57
% Modified by Felix Totir
%

fid = fopen(hdrfile);
while true
    line = fgetl(fid);
    if line == -1
        break
    else
        eqsn = findstr(line,'=');
        if ~isempty(eqsn)
            param = strtrim(line(1:eqsn-1));
            param(findstr(param,' ')) = '_';
            value = strtrim(line(eqsn+1:end));
            if isempty(str2num(value))
                if ~isempty(findstr(value,'{')) && isempty(findstr(value,'}'))
                    while isempty(findstr(value,'}'))
                        line = fgetl(fid);

                        %for polSARpro
                        if line == -1
                            break;
                        end
                        value = [value,strtrim(line)];
                    end
                end
                eval(['info.',param,' = ''',value,''';'])
            else
                eval(['info.',param,' = ',value,';'])
            end
        end
    end
end
fclose(fid);

if isfield(info,'map_info')
    line = info.map_info;
    line(line == '{' | line == '}') = [];

    %originally: line = strtrim(split(line,','));
    %replaced by
    line=textscan(line,'%s', 'Delimiter',','); %behavior is not quite the same if "line" ends in ','
    line=line{:};
    line=strtrim(line);
    %

    info.map_info = [];
    info.map_info.projection = line{1};
    info.map_info.image_coords = [str2num(line{2}),str2num(line{3})];
    info.map_info.mapx = str2num(line{4});
    info.map_info.mapy = str2num(line{5});
    info.map_info.dx  = str2num(line{6});
    info.map_info.dy  = str2num(line{7});
    if length(line) == 9
        info.map_info.datum  = line{8};
        info.map_info.units  = line{9}(7:end);
    elseif length(line) == 11
        info.map_info.zone  = str2num(line{8});
        info.map_info.hemi  = line{9};
        info.map_info.datum  = line{10};
        info.map_info.units  = line{11}(7:end);
    end

    %part below comes form the original enviread
    %% Make geo-location vectors
    %     xi = info.map_info.image_coords(1);
    %     yi = info.map_info.image_coords(2);
    %     xm = info.map_info.mapx;
    %     ym = info.map_info.mapy;
    %     %adjust points to corner (1.5,1.5)
    %     if yi > 1.5
    %         ym =  ym + ((yi*info.map_info.dy)-info.map_info.dy);
    %     end
    %     if xi > 1.5
    %         xm = xm - ((xi*info.map_info.dy)-info.map_info.dx);
    %     end
    %
    %     info.x= xm + ((0:info.samples-1).*info.map_info.dx);
    %     info.y = ym - ((0:info.lines-1).*info.map_info.dy);
end

if isfield(info,'coordinate_system_string')
    line = info.coordinate_system_string;
    line(line == '{' | line == '}' | line == '"' | line == '[' ...
        | line == ']') = [];

    %originally: line = strtrim(split(line,','));
    %replaced by
    line=textscan(line,'%s', 'Delimiter',','); %behavior is not quite the same if "line" ends in ','
    line=line{:};
    line=strtrim(line);
    %

    info.coordinate_system = [];

    if contains(line{1},'UTM')
        info.coordinate_system.PROJCS = extractAfter(line{1},6);

        info.coordinate_system.GEOGCS = extractAfter(line{2},6);
        info.coordinate_system.DATUM = extractAfter(line{3},5);
        info.coordinate_system.SPHEROID = [];
        info.coordinate_system.SPHEROID.datum = extractAfter(line{4},8);
        info.coordinate_system.SPHEROID.a  = line{5};
        info.coordinate_system.SPHEROID.e  = line{6};
        info.coordinate_system.PRIMEM = extractAfter(line{7},6);
        info.coordinate_system.PMlongToGreenwich = line{8};
        info.coordinate_system.UNITGeo = extractAfter(line{9},4);
        info.coordinate_system.UNITGeo_value = line{10};

        info.coordinate_system.PROJECTION = extractAfter(line{11},10);
        info.coordinate_system.PARAMETER1 = extractAfter(line{12},9);
        info.coordinate_system.PARAMETER1_value = line{13};
        info.coordinate_system.PARAMETER2 = extractAfter(line{14},9);
        info.coordinate_system.PARAMETER2_value = line{15};
        info.coordinate_system.PARAMETER3 = extractAfter(line{16},9);
        info.coordinate_system.PARAMETER3_value = line{17};
        info.coordinate_system.PARAMETER4 = extractAfter(line{18},9);
        info.coordinate_system.PARAMETER4_value = line{19};
        info.coordinate_system.PARAMETER5 = extractAfter(line{20},9);
        info.coordinate_system.PARAMETER5_value = line{21};
        info.coordinate_system.UNITPro = extractAfter(line{22},4);
        info.coordinate_system.UNITPro_value = line{23};

    elseif strcmp(info.map_info.projection, 'Geographic Lat/Lon')
        info.coordinate_system.GEOGCS = extractAfter(line{1},6);
        info.coordinate_system.DATUM = extractAfter(line{2},5);
        info.coordinate_system.SPHEROID = [];
        info.coordinate_system.SPHEROID.datum = extractAfter(line{3},8);
        info.coordinate_system.SPHEROID.a  = line{4};
        info.coordinate_system.SPHEROID.e  = line{5};
        info.coordinate_system.PRIMEM = extractAfter(line{6},6);
        info.coordinate_system.PMlongToGreenwich = line{7};
        info.coordinate_system.UNITGeo = extractAfter(line{8},4);
        info.coordinate_system.UNITGeo_value = line{9};
    end

end

if isfield(info,'pixel_size')
    line = info.pixel_size;
    line(line == '{' | line == '}') = [];

    %originally: line = strtrim(split(line,','));
    %replaced by:
    line=textscan(line,'%s','Delimiter',','); %behavior is not quite the same if "line" ends in ','
    line=line{:};
    line=strtrim(line);

    info.pixel_size = [];
    info.pixel_size.x = str2num(line{1});
    info.pixel_size.y = str2num(line{2});
    info.pixel_size.units = line{3}(7:end);
end

% function split is only used when replacements above do not work
% function A = split(s,d)
%This function by Gerald Dalley (dalleyg@mit.edu), 2004
% A = {};
% while (~isempty(s))
%     [t,s] = strtok(s,d);
%     A = {A{:}, t};
% end


function res = exp_rule(match,repl)
% Create a substitution rule, which to replace a Pattern in an expression.
% Rule = exp_rule(Pattern,Replacement)
%
% In:
%   Pattern     : An expression; may contain blanks (see exp_blank()), named sub-expressions (see
%                 exp_pattern()) or generally any structure (see exp_symbol()).
%   Replacement : a replacement expression; may contain symbols and/or named patterns that reference
%                 parts inside Pattern.
%
% Out:
%   Rule        : a replacement rule
%
%                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                2010-04-23

res = struct('head',{@Rule},'parts',{{match,repl}});


classdef PTKGetContextForSegment < PTKPlugin
    % PTKGetContextForSegment. Plugin for finding the region of interest for a segment.
    %
    %     This is a plugin for the Pulmonary Toolkit. Plugins can be run using
    %     the gui, or through the interfaces provided by the Pulmonary Toolkit.
    %     See PTKPlugin.m for more information on how to run plugins.
    %
    %     Plugins should not be run directly from your code.
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2013.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    properties
        ButtonText = 'Segment<BR>ROI'
        ToolTip = 'Fetches the ROI for a segment context'
        Category = 'Context'

        AllowResultsToBeCached = true
        AlwaysRunPlugin = false
        Context = PTKContextSet.Segment
        PluginType = 'ReplaceImage'
        HidePluginInDisplay = true
        FlattenPreviewImage = false
        PTKVersion = '2'
        ButtonWidth = 6
        ButtonHeight = 2
        GeneratePreview = true

        MemoryCachePolicy = 'Permanent'
        DiskCachePolicy = 'Permanent'
    end

    methods (Static)
        function results = RunPlugin(dataset, context, reporting)
            segment_mask = dataset.GetResult('PTKPulmonarySegments', PTKContext.LungROI);
            results = PTKGetSegmentROI(segment_mask, context, reporting);
        end
    end
end


function NewFiles = import_raw_to_db( DataFile )
% IMPORT_RAW_TO_DB: Import in the database some blocks of recordings from a continuous file already linked to the database.
%
% USAGE:  NewFiles = import_raw_to_db( DataFile )

% @=============================================================================
% 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: Francois Tadel, 2011-2022

% ===== GET FILE INFO =====
% Get study description
[sStudy, iStudy, iData] = bst_get('DataFile', DataFile);
if isempty(sStudy)
    error('File is not registered in the database.');
end
% Is it a "link to raw file" or not
isRaw = strcmpi(sStudy.Data(iData).DataType, 'raw');
% Get subject index
[sSubject, iSubject] = bst_get('Subject', sStudy.BrainStormSubject);
% Progress bar
bst_progress('start', 'Import raw file', 'Processing file header...');
% Read file descriptor
DataMat = in_bst_data(DataFile);
% Read channel file
ChannelFile = bst_get('ChannelFileForStudy', DataFile);
ChannelMat = in_bst_channel(ChannelFile);
% Get sFile structure
if isRaw
    sFile = DataMat.F;
else
    sFile = in_fopen(DataFile, 'BST-DATA');
end
% Import file
[NewFiles, iStudyImport] = import_data(sFile, ChannelMat, sFile.format, [], iSubject, [], sStudy.DateOfStudy);

% If only one file imported: Copy linked videos in destination folder
if (length(NewFiles) == 1) && ~isempty(sStudy.Image)
    process_import_data_event('CopyVideoLinks', NewFiles{1}, sStudy);
end

% Copy noise covariance, if any
if ~isempty(iStudyImport) && ~isempty(sStudy.NoiseCov) && ~isempty(sStudy.NoiseCov(1).FileName)
    iStudyCopy = unique(iStudyImport);
    for i = 1:length(iStudyCopy)
        sStudyCopy = bst_get('Study', iStudyCopy(i));
        if isempty(sStudyCopy.NoiseCov) || isempty(sStudyCopy.NoiseCov(1).FileName)
            db_set_noisecov(iStudy, iStudyCopy(i), 0, 0);
        end
    end
end

% Save database
db_save();


function cellInfo = AirSpeed_Bus(varargin)
% AIRSPEED_BUS returns a cell array containing bus object information
%
% Optional Input: 'false' will suppress a call to Simulink.Bus.cellToObject
%                 when the MATLAB file is executed.
% The order of bus element attributes is as follows:
%   ElementName, Dimensions, DataType, SampleTime, Complexity, SamplingMode, DimensionsMode, Min, Max, DocUnits, Description

suppressObject = false;
if nargin == 1 && islogical(varargin{1}) && varargin{1} == false
    suppressObject = true;
elseif nargin > 1
    error('Invalid input argument(s) encountered');
end

cellInfo = { ...
  { ...
    'AirSpeed_Bus', ...
    '', ...
    '', ...
    'Auto', ...
    '-1', {...
{'timestamp', 1, 'uint32', -1, 'real', 'Sample', 'Fixed', [], [], sprintf('ms'), ''}; ...
{'diff_pressure', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], sprintf('Pa'), ''}; ...
{'temperature', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], sprintf('degC'), ''}; ...
    } ...
  } ...
}';

if ~suppressObject
    % Create bus objects in the MATLAB base workspace
    Simulink.Bus.cellToObject(cellInfo)
end


function test_bug472

% MEM 2gb
% WALLTIME 00:13:01
% DEPENDENCY buffer.mexa64 buffer.mexmaci buffer.mexw64 buffer.mexglx buffer.mexmaci64 buffer.mexmac buffer.mexw32

% start without a buffer
ft_destroy_buffer

% number of attempts
cnt = 1;

% use default url
url = 'buffer://localhost:1972';

% dummy header
hdr.Fs = 256;
hdr.nChans = 100;

stopwatch = tic;
% run the test for 10 minutes
% after a few attempts, MATLAB crashes
while (toc(stopwatch)<600)
    disp(['counter: ' num2str(cnt)]); cnt = cnt + 1;
    ft_create_buffer(1972);
    ft_write_data(url,rand(hdr.nChans,10000), 'header', hdr, 'dataformat', 'fcdc_buffer', 'append', false);
    ft_read_header(url)
    ft_destroy_buffer
    pause(0.1); % probably meaningless
end

disp('the test completed without detected problems');


function res = utl_aggregate_results(varargin)
% Internal. Aggregate the given results (in any format allowed for ml_predict) into a single array.
% In:
%   Results... : results as produced by ml_predict
%
% Out:
%   Aggregate : all results concatenated into a single array
%
% See also:
%   ml_predict
%
%                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                2010-04-07

if isnumeric(varargin{1})
    try
        res = vertcat(varargin{:});
    catch e
        sizes = cellfun(@size,varargin,'UniformOutput',false);
        error('Failed to concatenate numeric prediction arrays -- make sure that the dimensionality of your predictions (%s) matches in each array; error message: %s.',hlp_tostring(sizes),e.message);
    end
elseif iscell(varargin{1}) && length(varargin{1}) > 1
    % make sure that the result formats are all equal
    v1 = varargin{1}([1 3:end]);
    for i=2:length(varargin)
        if ~isequal(v1,varargin{i}([1 3:end]))
            error('The formats of all prediction arrays to concatenate need to be identical.'); end
    end
    % grab the actual parameters
    params = cellfun(@(x)x{2},varargin,'UniformOutput',false);
    if isnumeric(varargin{1}{2})
        % numeric parameters are vertically concatenated
        try
            res = {varargin{1}{1} vertcat(params{:}) varargin{1}{3:end}};
        catch e
            sizes = cellfun(@size,params,'UniformOutput',false);
            error('Failed to concatenate prediction arrays -- make sure that the dimensionality of your distributions (%s) matches in each array; error message: %s.',hlp_tostring(sizes),e.message);
        end
    elseif iscell(varargin{1}{2})
        % cell parameters are horizontally concatenated
        try
            res = {varargin{1}{1} horzcat(params{:}) varargin{1}{3:end}};
        catch e
            sizes = cellfun(@size,params,'UniformOutput',false);
            error('Failed to concatenate prediction arrays -- make sure that the dimensionality of your distributions (%s) matches in each array; error message: %s.',hlp_tostring(sizes),e.message);
        end
    else
        error('This function can only concatenate prediction arrays of the form {X,Y, ...} where Y is either numeric or a cell array.');
    end
else
    error('This function can only concatenate arrays of predictions that are either all numeric or in the cell array form described in ml_predict.');
end


classdef mme_xfmr3p_opf < mp.mme_xfmr3p

%   MATPOWER
%   Copyright (c) 2022, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

%     properties
%     end

    methods
        function x0 = interior_x0(obj, mm, nm, dm, x0)
        end
    end     %% methods
end         %% classdef


%% ndet
% Below is a demonstration of the features of the |ndet| function

%%
clear; close all; clc;

%% Syntax
% |DET=ndet(N1,N2,N3);|

%% Description
% UNDOCUMENTED
%% Examples
%
%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>
%%
% _*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 gui_check_cell(edithandle,resetstr)
% check whether the the given edit field contains a valid cell array; warn and reset if not
if ~exist('resetstr','var')
    resetstr = ''; end
try
    data = evalin('base',get(edithandle,'String'));
    assert(iscell(data),'Error!');
catch
    errordlg2(sprintf('This field must be a cell array.\nExample: {''test'',3,[4,5], ...}'));
    set(edithandle,'String',resetstr);
end


%Copyright 2008-2009  Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
%Copyright 2008-2009  David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
%
%THE BSD LICENSE
%
%Redistribution and use in source and binary forms, with or without
%modification, are permitted provided that the following conditions
%are met:
%
%1. Redistributions of source code must retain the above copyright
%   notice, this list of conditions and the following disclaimer.
%2. Redistributions in binary form must reproduce the above copyright
%   notice, this list of conditions and the following disclaimer in the
%   documentation and/or other materials provided with the distribution.
%
%THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
%IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
%OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
%IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
%INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
%NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
%DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
%THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
%(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
%THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

function [indices, dists] = flann_search(data, testset, n, search_params)
%NN_SEARCH  Fast approximate nearest neighbors search
%
% Performs a fast approximate nearest neighbor search using an
% index constructed using flann_build_index or directly a
% dataset.

% Marius Muja, January 2008

    algos = struct( 'linear', 0, 'kdtree', 1, 'kmeans', 2, 'composite', 3, 'saved', 254, 'autotuned', 255 );
    center_algos = struct('random', 0, 'gonzales', 1, 'kmeanspp', 2 );
    log_levels = struct('none', 0, 'fatal', 1, 'error', 2, 'warning', 3, 'info', 4);

    default_params = struct('algorithm', 'kdtree' ,'checks', 32, 'eps', 0.0, 'sorted', 1, 'max_neighbors', -1, 'cores', 1, 'trees', 4, 'branching', 32, 'iterations', 5, 'centers_init', 'random', 'cb_index', 0.4, 'target_precision', 0.9,'build_weight', 0.01, 'memory_weight', 0, 'sample_fraction', 0.1, 'log_level', 'warning', 'random_seed', 0);

    if ~isstruct(search_params)
        error('The "search_params" argument must be a structure');
    end

    params = default_params;
    fn = fieldnames(search_params);
    for ii = 1:length(fn),
        name = cell2mat(fn(ii));
        params.(name) = search_params.(name);
    end
    if ~isnumeric(params.algorithm),
        params.algorithm = value2id(algos,params.algorithm);
    end
    if ~isnumeric(params.centers_init),
        params.centers_init = value2id(center_algos,params.centers_init);
    end
    if ~isnumeric(params.log_level),
        params.log_level = value2id(log_levels,params.log_level);
    end

    if (size(data,1)==1 && size(data,2)==1)
        % we already have an index
        [indices,dists] = nearest_neighbors('index_find_nn', data, testset, n, params);
    else
        % create the index and search
        [indices,dists] = nearest_neighbors('find_nn', data, testset, n, params);
    end
end

function id = value2id(map,value)
    id = map.(value);
end

function value = id2value(map, id)
    fields = fieldnames(map);
    for ii = 1:length(fields),
        val = cell2mat(fields(ii));
        if map.(val) == id
            value = val;
            break;
        end
    end
end


function [seed_sets] = generate_graph_seeds(graph_seed_gen_method, ...
                                            graph_seed_params, seg_obj)
% returns an NxS seed_sets logical matrix, where each column defines a
% seed. A value of 1 in a row indicates that that pixel/superpixel is
% included in the seed specified by the column.
%
% @authors:     Ahmad Humayun
% @contact:     ahumayun@cc.gatech.edu
% @affiliation: Georgia Institute of Technology
% @date:        Fall 2013 - Summer 2014

    if strcmpi(graph_seed_gen_method, 'sp_img_grid')
        [seed_sets] = gen_sp_img_grid(graph_seed_params, seg_obj);
    elseif strcmpi(graph_seed_gen_method, 'sp_all')
        [seed_sets] = gen_sp_all_seeds(graph_seed_params, seg_obj);
    elseif strcmpi(graph_seed_gen_method, 'sp_clr_seeds')
        [seed_sets] = gen_sp_clr_seeds(graph_seed_params, seg_obj);
    elseif strcmpi(graph_seed_gen_method, 'sp_seed_sampling')
        [seed_sets] = AbstractGraph.gen_sp_seed_sampling(graph_seed_params, seg_obj);
    elseif strcmpi(graph_seed_gen_method, 'gen_user_seeds')
        [seed_sets] = gen_user_seeds(graph_seed_params, seg_obj);
    else
        error('AbstractGraph:generate_graph_seeds', ...
              '''%s'' invalid seed generation methos', ...
              graph_seed_gen_method);
    end

    % this function ensures no seeds overlap
    [seed_sets] = no_overlapping_seeds(seed_sets, seg_obj);
end

function [seed_sets] = gen_sp_img_grid(graph_seed_params, seg_obj)
% generates seeds by a grid over the image. The first array in
% graph_seed_params specifies how many seeds are needed. The second array
% specifies the extent of the seed pixels around each seed grid location

    graph_num_seed_locs = graph_seed_params{1};
    graph_seed_sz = graph_seed_params{2};
    % generate the offsets from the central grid pixel
    [rect_coords] = ...
        generate_seeds_funcs('generate_rectangle_coords', ...
                             graph_seed_sz);
    % generate the seed sets over a grid (each column gives
    % pixels/superpixels selected for that seed)
    seed_sets = generate_seeds_funcs('generate_sp_img_grid', ...
                                     seg_obj.sp_data.sp_seg, ...
                                     rect_coords, ...
                                     graph_num_seed_locs, ...
                                     seg_obj.sp_data.sp_seg_szs, 0);
end

function [seed_sets] = gen_sp_all_seeds(graph_seed_params, seg_obj)
% generates seeds by choosing all sps. The single parameter in
% graph_seed_params indicate how many sps to skip when choosing a sp as a
% seed

    subsample_sps = graph_seed_params{1} + 1;

    % initially each sp is a seed
    seed_sets = logical(eye(seg_obj.sp_data.num_spx, 'int8'));

    % now subsample the seeds
    seed_sets = seed_sets(:,1:subsample_sps:end);
end

function [seed_sets] = gen_sp_clr_seeds(graph_seed_params, seg_obj)
% generates seeds by finding superpixels locations which are closest to a
% grid over the image. The first array in graph_seed_params specifies how
% many seeds are needed. The second array specifies the extent of the seed
% pixels around each seed grid location. The third argument is a string
% specifying what superpixel method to use. 'sp_seeds_caller' uses the
% superpixels already generated in seg_obj.sp_data;
% 'felzenszwalb_seeds_caller' uses FelzHutten superpixels.

    graph_num_seed_locs = graph_seed_params{1};
    graph_seed_sz = graph_seed_params{2};
    superpixel_method = graph_seed_params{3};
    % generate the offsets from the central grid pixel
    [rect_coords] = ...
        generate_seeds_funcs('generate_rectangle_coords', ...
                             graph_seed_sz);
    % generate the seed sets over a grid (each column gives
    % pixels/superpixels selected for that seed)
    seed_sets = generate_seeds_funcs('generate_sp_seeds_superpixels', ...
                                     seg_obj.sp_data, seg_obj.I, ...
                                     superpixel_method, 0, ...
                                     rect_coords, graph_num_seed_locs);
end

function [seed_sets] = gen_user_seeds(graph_seed_params, seg_obj)
    graph_seed_sz = graph_seed_params{1};
    user_centers = graph_seed_params{2};
    [rect_coords] = ...
        generate_seeds_funcs('generate_rectangle_coords', ...
                             graph_seed_sz);
    seed_sets = generate_seeds_funcs('generate_sp_user', ...
                                     seg_obj.sp_data.sp_seg, ...
                                     rect_coords, user_centers, ...
                                     seg_obj.sp_data.sp_seg_szs, 0);
end

function [seed_sets] = no_overlapping_seeds(seed_sets, seg_obj)
% this function ensures that no seeds overlap i.e. no superpixels are the
% same in two seeds

    % find number of overlapping superpixels across seeds
    ss = single(seed_sets);
    num_overlap_sps = ss' * ss;
    num_overlap_sps = triu(num_overlap_sps, 1);
    [s1,s2,os] = find(num_overlap_sps);
    num_overlap_sps = [s1, s2, os];

    num_sps_per_seed = sum(seed_sets);

    % remove overlapping superpixel for each seed pair contention (note,
    % superpixels removed from a seed in a pervious iteration, would no
    % longer be taken into consideration in later iterations - hence,
    % correctly ignoring superpixels which no longer belong to a seed)
    for idx = 1:size(num_overlap_sps,1)
        s1 = num_overlap_sps(idx,1);
        s2 = num_overlap_sps(idx,2);
        n1 = num_sps_per_seed(s1);
        n2 = num_sps_per_seed(s2);

        % find the sps which overlap
        overlap_sps = all(seed_sets(:,[s1 s2]), 2);

        % if seed1 has more superpixels, then remove overlapping sp from
        % seed1. Otherwise remove superpixel from seed2
        if n1 > n2
            seed_sets(overlap_sps,s1) = 0;
        else
            seed_sets(overlap_sps,s2) = 0;
        end
    end

    % discard any seeds which have no superpixels anymore
    num_sps_per_seed = sum(seed_sets);
    seed_sets(:,num_sps_per_seed == 0) = [];
end


%{
    Copyright (C) Cambridge Electronic Design Limited 2014
    Author: James Thompson
    Web: www.ced.co.uk email: james@ced.co.uk, softhelp@ced.co.uk

    This file is part of CEDS64ML, a MATLAB interface to the SON64 library.

    CEDS64ML 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.

    CEDS64ML 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 CEDS64ML.  If not, see <http://www.gnu.org/licenses/>.
%}

function [ i64Div ] = CEDS64ChanDiv( fhand, iChan )
%CEDS64CHANDIV The sample interval in Ticks
%   [ i64Div ] = CEDS64ChanDiv( fhand, iChan )
%   Inputs
%   fhand - Integer file handle
%   iChan - Channel number
%   Outputs
%   i64Div - The sample interval in Ticks or a negative error code
if(nargin == 2)
    i64Div = calllib('ceds64int', 'S64ChanDivide', fhand, iChan);
else
    i64Div = -22;
end
end


function [groupTable,out_no_group] = arrangerules(system,intTable)
%   Arranges the rules into groups function
%
%
%
%   Neelamugilan Gobalakrishnan
%   2006
%   $Revision:1.0 $ $Date: 15/03/2006 $

if size(system.output, 2) == 1
    out_no_group = 1;
else
    out_no_group = input('Enter the output number which is used to group the integer table : ');
end

row = 1;
for i=1:size(system.output(out_no_group).mf, 2)
    for j=1:size(intTable, 1)
        if intTable(j,size(system.input, 2)+out_no_group) == i
            grouped_intTable(row,1:size(system.input, 2))=intTable(j,1:size(system.input, 2));
            grouped_intTable(row,size(system.input, 2)+1)=intTable(j,size(system.input, 2)+out_no_group);
            row = row + 1;
        end
    end
end

%===========================================================
%   Display grouped integer tables with choosen output number.
%===========================================================

fprintf('\n');
disp('-------------------------------------------------------------');
fprintf(' ');
disp('                    Grouped integer table                    ');
fprintf(' ');
disp('-------------------------------------------------------------');

fprintf('\n');
disp('-------------------------------------------------------------');
fprintf(' ');

for i=1:size(system.input, 2)
    fprintf('Input%d ', i);
end

fprintf('Output%d ', out_no_group);

fprintf('\n');
disp('-------------------------------------------------------------');
fprintf('\n');
disp(grouped_intTable);
disp('-------------------------------------------------------------');

fprintf('\n\n');

groupTable = grouped_intTable;


function isloaded = loadGlobalNamespace()
   % loadGlobalNamespace handles the global variables and routines used within
   % wavefrom.
   %

   %global mep2dep dep2mep

   global WAVEFORM_HISTORY
   WAVEFORM_HISTORY = true; %keep track of waveform modifications

   %time converter functions
   % matlab date (# days since 0 JAN 0000)
   %mep2dep = inline ('(matepoch - 719529) * 24 * 3600','matepoch');
   % antelope epoch( # secs since 1 JAN 1970 )
   %dep2mep = inline ('(dep / 86400 + 719529)', 'dep');

   %default period for envelopes
   global DEFAULT_PERIOD
   DEFAULT_PERIOD = 10; %seconds

   global SECONDS_IN_DAY
   SECONDS_IN_DAY = 24 * 60 * 60;

   isloaded = true;
end


% POP_PROP - plot the properties of a channel or of an independent
%              component.
% Usage:
%   >> pop_prop( EEG);           % pops up a query window
%   >> pop_prop( EEG, typecomp); % pops up a query window
%   >> pop_prop( EEG, typecomp, chanorcomp, winhandle,spectopo_options);
%
% Inputs:
%   EEG        - EEGLAB dataset structure (see EEGGLOBAL)
%
% Optional inputs:
%   typecomp   - [0|1] 1 -> display channel properties
%                0 -> component properties {default: 1 = channel}
%   chanorcomp - channel or component number[s] to display {default: 1}
%
%   winhandle  - if this parameter is present or non-NaN, buttons
%                allowing the rejection of the component are drawn.
%                If non-zero, this parameter is used to back-propagate
%                the color of the rejection button.
%   spectopo_options - [cell array] optional cell array of options for
%                the SPECTOPO function.
%                For example { 'freqrange' [2 50] }
%
% Note: Type "set(gcf, ''renderer'', ''painter'')" before saving the figure
% in postscript (epsc) or jpg format
%
% Author: Arnaud Delorme, CNL / Salk Institute, 2001
%
% See also: POP_RUNICA, EEGLAB

% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

% hidden parameter winhandle

% 01-25-02 reformated help & license -ad
% 02-17-02 removed event index option -ad
% 03-17-02 debugging -ad & sm
% 03-18-02 text settings -ad & sm
% 03-18-02 added title -ad & sm

function com = pop_prop(EEG, typecomp, chanorcomp, winhandle, spec_opt)

com = '';
if nargin < 1
	help pop_prop;
	return;
end
if nargin < 5
	spec_opt = {};
end
if nargin == 1
	typecomp = 1;    % defaults
        chanorcomp = 1;
end
if typecomp == 0 && isempty(EEG.icaweights)
   error('No ICA weights recorded for this dataset -- first run ICA on it');
end
chanoristr = '';
if nargin == 2
    commandchan = 'tmpchanlocs = EEG(1).chanlocs; [tmp tmpval] = pop_chansel({tmpchanlocs.labels}, ''withindex'', ''on'', ''selectionmode'', ''single''); set(findobj(gcbf, ''tag'', ''chan''), ''string'',tmpval); clear tmp tmpchanlocs tmpval';

    uitext = { { 'style' 'text' 'string' fastif(typecomp,'Channel index(ices) to plot:','Component index(ices) to plot:') } ...
               { 'style' 'edit' 'string' '1', 'tag', 'chan' } ...
               { 'style' 'pushbutton' 'string'  '...', 'enable' fastif(~isempty(EEG(1).chanlocs) && typecomp, 'on', 'off') 'callback' commandchan } ...
               { 'style' 'text' 'string' 'Spectral options (see spectopo() help):' } ...
               { 'style' 'edit' 'string' '''freqrange'', [2 50]' } {} };
    uigeom = { [2 1 0.5 ] [2 1 0.5] };
    result = inputgui('geometry', uigeom, 'uilist', uitext, 'helpcom', 'pophelp(''pop_prop'');', ...
							 'title', fastif( typecomp, 'Channel properties - pop_prop()', 'Component properties - pop_prop()'));
	if size( result, 1 ) == 0 return; end

    chanoristr = result{1};
    chanorcomp   = eeg_decodechan(EEG.chanlocs, result{1} );
    spec_opt     = eval( [ '{' result{2} '}' ] );
end

if ischar(chanorcomp)
    chanoristr = chanorcomp;
    chanorcomp = eeg_decodechan(EEG.chanlocs, chanorcomp );
elseif isempty(chanoristr)
    chanoristr = int2str(chanorcomp);
end

% plotting several component properties
% -------------------------------------
if length(chanorcomp) > 1
    for index = chanorcomp
        pop_prop(EEG, typecomp, index, 0, spec_opt);  % call recursively for each chanorcomp
    end
	com = sprintf('pop_prop( EEG, %d, [%s], NaN, %s);',...
                  typecomp, int2str(chanorcomp), vararg2str( { spec_opt } ));
    return;
end

% should test for > number of components ??? -sm.
% yes (max num components is not necessarily same as nbchan). -jri
if typecomp == 1
  maxChanorcomp = EEG.nbchan;
else
  maxChanorcomp = size(EEG.icaweights, 1);
end

if chanorcomp < 1 || chanorcomp > maxChanorcomp
   error('Component index out of range');
end

% assumed input is chanorcomp
% -------------------------
try
    icadefs;
catch
	BACKCOLOR = [0.8 0.8 0.8];
	GUIBUTTONCOLOR   = [0.8 0.8 0.8];
end
basename = [fastif(typecomp,'Channel ', 'Component ') chanoristr ];

fhandle = figure('name', ['pop_prop() - ' basename ' properties'], 'color', BACKCOLOR, 'numbertitle', 'off', 'visible', 'off');
pos     = get(fhandle,'Position');
set(fhandle,'Position', [pos(1) pos(2)-500+pos(4) 500 500], 'visible', 'on');
hh = axes('parent',fhandle);
pos      = get(hh,'position'); % plot relative to current axes
q = [pos(1) pos(2) 0 0];
s = [pos(3) pos(4) pos(3) pos(4)]./100;
axis(hh,'off');

% plotting topoplot
% -----------------
h = axes('parent',fhandle,'Units','Normalized', 'Position',[-10 60 40 42].*s+q);

%topoplot( EEG.icawinv(:,chanorcomp), EEG.chanlocs); axis square;

if isfield(EEG.chanlocs, 'theta')
    if typecomp == 1 % plot single channel locations
        topoplot( chanorcomp, EEG.chanlocs, 'chaninfo', EEG.chaninfo, ...
                 'electrodes','off', 'style', 'blank', 'emarkersize1chan', 12); axis square;
    else             % plot component map
        topoplot( EEG.icawinv(:,chanorcomp), EEG.chanlocs, 'chaninfo', EEG.chaninfo, ...
                 'shading', 'interp', 'numcontour', 3); axis square;
    end
else
    axis(h,'off');
end
basename = [fastif(typecomp,'Channel ', 'IC') chanoristr ];
% title([ basename fastif(typecomp, ' location', ' map')], 'fontsize', 14);
title(basename, 'fontsize', 14);

% plotting erpimage
% -----------------
hhh = axes('Parent', fhandle,'Units','Normalized', 'Position',[45 62 48 38].*s+q);
eeglab_options;
if EEG.trials > 1
    % put title at top of erpimage
    axis(hhh,'off');
    hh = axes('Parent', fhandle,'Units','Normalized', 'Position',[45 62 48 38].*s+q);
    EEG.times = linspace(EEG.xmin, EEG.xmax, EEG.pnts);
    if EEG.trials < 6
      ei_smooth = 1;
    else
      ei_smooth = 3;
    end
    if typecomp == 1 % plot channel
         offset = nan_mean(EEG.data(chanorcomp,:));
         erp=nan_mean(squeeze(EEG.data(chanorcomp,:,:))')-offset;
         erp_limits=get_era_limits(erp);
         erpimage( EEG.data(chanorcomp,:)-offset, ones(1,EEG.trials)*10000, EEG.times*1000, ...
                       '', ei_smooth, 1, 'caxis', 2/3, 'cbar','erp','erp_vltg_ticks',erp_limits);
    else % plot component
         icaacttmp  = eeg_getdatact(EEG, 'component', chanorcomp);
         offset     = nan_mean(icaacttmp(:));
         era        = nan_mean(squeeze(icaacttmp)')-offset;
         era_limits = get_era_limits(era);
         erpimage( icaacttmp-offset, ones(1,EEG.trials)*10000, EEG.times*1000, ...
                       '', ei_smooth, 1, 'caxis', 2/3, 'cbar','erp', 'yerplabel', '','erp_vltg_ticks',era_limits);
    end
    axes(hhh);
    title(sprintf('%s activity \\fontsize{10}(global offset %3.3f)', basename, offset), 'fontsize', 14);
else
    % put title at top of erpimage
    EI_TITLE = 'Continous data';
    axis(hhh,'off');
    hh = axes('Parent', fhandle,'Units','Normalized', 'Position',[45 62 48 38].*s+q);
    ERPIMAGELINES = 200; % show 200-line erpimage
    while size(EEG.data,2) < ERPIMAGELINES*EEG.srate
       ERPIMAGELINES = 0.9 * ERPIMAGELINES;
    end
    ERPIMAGELINES = round(ERPIMAGELINES);
    if ERPIMAGELINES > 2   % give up if data too small
        if ERPIMAGELINES < 10
            ei_smooth = 1;
        else
            ei_smooth = 3;
        end
      erpimageframes = floor(size(EEG.data,2)/ERPIMAGELINES);
      erpimageframestot = erpimageframes*ERPIMAGELINES;
      eegtimes = linspace(0, erpimageframes-1, length(erpimageframes)); % 05/27/2014 Ramon: length(erpimageframes) by EEG.srate/1000  in eegtimes = linspace(0, erpimageframes-1, EEG.srate/1000);
      if typecomp == 1 % plot channel
           offset = nan_mean(EEG.data(chanorcomp,:));
           % Note: we don't need to worry about ERP limits, since ERPs
           % aren't visualized for continuous data
           erpimage( reshape(EEG.data(chanorcomp,1:erpimageframestot),erpimageframes,ERPIMAGELINES)-offset, ones(1,ERPIMAGELINES)*10000, eegtimes , ...
                         EI_TITLE, ei_smooth, 1, 'caxis', 2/3, 'cbar');
      else % plot component
         icaacttmp = eeg_getdatact(EEG, 'component', chanorcomp);
         offset = nan_mean(icaacttmp(:));
         erpimage(reshape(icaacttmp(:,1:erpimageframestot),erpimageframes,ERPIMAGELINES)-offset,ones(1,ERPIMAGELINES)*10000, eegtimes , ...
                    EI_TITLE, ei_smooth, 1, 'caxis', 2/3, 'cbar','yerplabel', '');
      end
    else
            axis(hh,'off');
            text(0.1, 0.3, [ 'No erpimage plotted' 10 'for small continuous data']);
    end
    axes(hhh);
end

% plotting spectrum
% -----------------
if ~exist('winhandle')
    winhandle = NaN;
end
if ishandle(winhandle)
	h = axes('Parent', fhandle,'units','normalized', 'position',[5 10 95 35].*s+q);
else
	h = axes('Parent', fhandle,'units','normalized', 'position',[5 0 95 40].*s+q);
end
%h = axes('units','normalized', 'position',[45 5 60 40].*s+q);
try
	eeglab_options;
	if typecomp == 1
		[spectra, freqs] = spectopo( EEG.data(chanorcomp,:), EEG.pnts, EEG.srate, spec_opt{:} );
	else
		if option_computeica
			[spectra, freqs] = spectopo( EEG.icaact(chanorcomp,:), EEG.pnts, EEG.srate, 'mapnorm', EEG.icawinv(:,chanorcomp), spec_opt{:} );
        else
    		icaacttmp = (EEG.icaweights(chanorcomp,:)*EEG.icasphere)*reshape(EEG.data(EEG.icachansind,:,:), length(EEG.icachansind), EEG.trials*EEG.pnts);
			[spectra, freqs] = spectopo( icaacttmp, EEG.pnts, EEG.srate, 'mapnorm', EEG.icawinv(:,chanorcomp), spec_opt{:} );
		end
	end
    % set up new limits
    % -----------------
    %freqslim = 50;
	%set(gca, 'xlim', [0 min(freqslim, EEG.srate/2)]);
    %spectra = spectra(find(freqs <= freqslim));
	%set(gca, 'ylim', [min(spectra) max(spectra)]);

	%tmpy = get(gca, 'ylim');
    %set(gca, 'ylim', [max(tmpy(1),-1) tmpy(2)]);
	set( get(h, 'ylabel'), 'string', 'Power 10*log_{10}(\muV^{2}/Hz)', 'fontsize', 14);
	set( get(h, 'xlabel'), 'string', 'Frequency (Hz)', 'fontsize', 14);
	title('Activity power spectrum', 'fontsize', 14);
catch err
	axis off;
    text(0.1, 0.3, [ 'Error: no spectrum plotted' 10 err.message 10]);
%     lasterror
% 	text(0.1, 0.3, [ 'Error: no spectrum plotted' 10 ' make sure you have the ' 10 'signal processing toolbox']);
end

% display buttons
% ---------------
if ishandle(winhandle)
	COLREJ = '[1 0.6 0.6]';
	COLACC = '[0.75 1 0.75]';
	% CANCEL button
	% -------------
	h  = uicontrol(fhandle, 'Style', 'pushbutton', 'backgroundcolor', GUIBUTTONCOLOR, 'string', 'Cancel', 'Units','Normalized','Position',[-10 -10 15 6].*s+q, 'callback', 'close(gcf);');

	% VALUE button
	% -------------
	hval  = uicontrol(fhandle, 'Style', 'pushbutton', 'backgroundcolor', GUIBUTTONCOLOR, 'string', 'Values', 'Units','Normalized', 'Position', [15 -10 15 6].*s+q);

	% REJECT button
	% -------------
    if ~isempty(EEG.reject.gcompreject)
    	status = EEG.reject.gcompreject(chanorcomp);
    else
        status = 0;
    end
	hr = uicontrol(fhandle, 'Style', 'pushbutton', 'backgroundcolor', eval(fastif(status,COLREJ,COLACC)), ...
				'string', fastif(status, 'REJECT', 'ACCEPT'), 'Units','Normalized', 'Position', [40 -10 15 6].*s+q, 'userdata', status, 'tag', 'rejstatus');
	command = [ 'set(gcbo, ''userdata'', ~get(gcbo, ''userdata''));' ...
				'if get(gcbo, ''userdata''),' ...
				'     set( gcbo, ''backgroundcolor'',' COLREJ ', ''string'', ''REJECT'');' ...
				'else ' ...
				'     set( gcbo, ''backgroundcolor'',' COLACC ', ''string'', ''ACCEPT'');' ...
				'end;' ];
	set(hr, 'callback', command);

	% HELP button
	% -------------
	h  = uicontrol(fhandle, 'Style', 'pushbutton', 'backgroundcolor', GUIBUTTONCOLOR, 'string', 'HELP', 'Units','Normalized', 'Position', [65 -10 15 6].*s+q, 'callback', 'pophelp(''pop_prop'');');

	% OK button
	% ---------
 	command = [ 'global EEG;' ...
 				'tmpstatus = get( findobj(''parent'', gcbf, ''tag'', ''rejstatus''), ''userdata'');' ...
 				'EEG.reject.gcompreject(' num2str(chanorcomp) ') = tmpstatus;' ];
	if winhandle ~= 0
        if VERS < 8.04
            command = [ command ...
                sprintf('if tmpstatus set(%3.15f, ''backgroundcolor'', %s); else set(%3.15f, ''backgroundcolor'', %s); end;', ...
                winhandle, COLREJ, winhandle, COLACC)];
        elseif VERS >= 8.04
            command = [ command ...
                sprintf('if tmpstatus set(findobj(''Tag'', ''%s''), ''backgroundcolor'', %s); else set(findobj(''Tag'',''%s''), ''backgroundcolor'', %s); end;', ...
                winhandle.Tag, COLREJ, winhandle.Tag, COLACC)];
        end
    end
	command = [ command 'close(gcf); clear tmpstatus' ];
	h  = uicontrol(fhandle, 'Style', 'pushbutton', 'string', 'OK', 'backgroundcolor', GUIBUTTONCOLOR, 'Units','Normalized', 'Position',[90 -10 15 6].*s+q, 'callback', command);

	% draw the figure for statistical values
	% --------------------------------------
	index = num2str( chanorcomp );
	command = [ ...
		'figure(''MenuBar'', ''none'', ''name'', ''Statistics of the component'', ''numbertitle'', ''off'');' ...
		'' ...
		'pos = get(gcf,''Position'');' ...
		'set(gcf,''Position'', [pos(1) pos(2) 340 340]);' ...
		'pos = get(gca,''position'');' ...
		'q = [pos(1) pos(2) 0 0];' ...
		's = [pos(3) pos(4) pos(3) pos(4)]./100;' ...
		'axis off;' ...
		''  ...
		'txt1 = sprintf(''(\n' ...
						'Entropy of component activity\t\t%2.2f\n' ...
					    '> Rejection threshold \t\t%2.2f\n\n' ...
					    ' AND                 \t\t\t----\n\n' ...
					    'Kurtosis of component activity\t\t%2.2f\n' ...
					    '> Rejection threshold \t\t%2.2f\n\n' ...
					    ') OR                  \t\t\t----\n\n' ...
					    'Kurtosis distribution \t\t\t%2.2f\n' ...
					    '> Rejection threshold\t\t\t%2.2f\n\n' ...
					    '\n' ...
					    'Current thresholds sujest to %s the component\n\n' ...
					    '(after manually accepting/rejecting the component, you may recalibrate thresholds for future automatic rejection on other datasets)'',' ...
						'EEG.stats.compenta(' index '), EEG.reject.threshentropy, EEG.stats.compkurta(' index '), ' ...
						'EEG.reject.threshkurtact, EEG.stats.compkurtdist(' index '), EEG.reject.threshkurtdist, fastif(EEG.reject.gcompreject(' index '), ''REJECT'', ''ACCEPT''));' ...
		'' ...
		'uicontrol(gcf, ''Units'',''Normalized'', ''Position'',[-11 4 117 100].*s+q, ''Style'', ''frame'' );' ...
		'uicontrol(gcf, ''Units'',''Normalized'', ''Position'',[-5 5 100 95].*s+q, ''String'', txt1, ''Style'',''text'', ''HorizontalAlignment'', ''left'' );' ...
		'h = uicontrol(gcf, ''Style'', ''pushbutton'', ''string'', ''Close'', ''Units'',''Normalized'', ''Position'', [35 -10 25 10].*s+q, ''callback'', ''close(gcf);'');' ...
		'clear txt1 q s h pos;' ];
	set( hval, 'callback', command);
	if isempty( EEG.stats.compenta )
		set(hval, 'enable', 'off');
	end

	com = sprintf('pop_prop( EEG, %d, %d, 0, %s);', typecomp, chanorcomp, vararg2str( { spec_opt } ) );
else
	com = sprintf('pop_prop( EEG, %d, %d, NaN, %s);', typecomp, chanorcomp, vararg2str( { spec_opt } ) );
end
disp('Note: Type "set(gcf, ''renderer'', ''painter'')" before saving the figure in postscript (epsc) or jpg format');

return;

function out = nan_mean(in)

    nans = find(isnan(in));
    in(nans) = 0;
    sums = sum(in);
    nonnans = ones(size(in));
    nonnans(nans) = 0;
    nonnans = sum(nonnans);
    nononnans = find(nonnans==0);
    nonnans(nononnans) = 1;
    out = sum(in)./nonnans;
    out(nononnans) = NaN;

function era_limits=get_era_limits(era)
%function era_limits=get_era_limits(era)
%
% Returns the minimum and maximum value of an event-related
% activation/potential waveform (after rounding according to the order of
% magnitude of the ERA/ERP)
%
% Inputs:
% era - [vector] Event related activation or potential
%
% Output:
% era_limits - [min max] minimum and maximum value of an event-related
% activation/potential waveform (after rounding according to the order of
% magnitude of the ERA/ERP)

mn=min(era);
mx=max(era);
mn=orderofmag(mn)*round(mn/orderofmag(mn));
mx=orderofmag(mx)*round(mx/orderofmag(mx));
era_limits=[mn mx];

function ord=orderofmag(val)
%function ord=orderofmag(val)
%
% Returns the order of magnitude of the value of 'val' in multiples of 10
% (e.g., 10^-1, 10^0, 10^1, 10^2, etc ...)
% used for computing erpimage trial axis tick labels as an alternative for
% plotting sorting variable

val=abs(val);
if val>=1
    ord=1;
    val=floor(val/10);
    while val>=1
        ord=ord*10;
        val=floor(val/10);
    end
    return;
else
    ord=1/10;
    val=val*10;
    while val<1
        ord=ord/10;
        val=val*10;
    end
    return;
end


%% |dirPlus| demo
% The |dirPlus| function recursively collects a list of files or
% subdirectories from a folder tree, allowing you to specify the selection
% criteria for how the list is collected and formatted. For the following
% examples, we'll be using the main MATLAB toolbox path.
%%

rootPath = 'C:\Program Files\MATLAB\R2016b\toolbox\matlab';
format compact

%% The 'FileFilter' option
% By default, |dirPlus| will collect a list of files. We can specify a
% <https://www.mathworks.com/help/matlab/matlab_prog/regular-expressions.html
% regular-expression> pattern to filter the file names on, collecting a
% list of files that match. Here's an example that uses the 'FileFilter'
% option to recursively find every file with a '.m' extension:

fileList = dirPlus(rootPath, 'FileFilter', '\.m$');
fprintf('%d files found.\n', size(fileList, 1));
fprintf('%s\n', fileList{1:5}, '...');

%%
% It's a pretty long list, so I've only shown the first 5 files it finds.
% Notice they are listed with the full path prepended by default.

%%
% If you have multiple match expressions to filter on, you can use
% <https://www.mathworks.com/help/matlab/matlab_prog/regular-expressions.html#f0-42884
% grouping operators> to include them all in one expression. For example,
% this will find every '.jpg', '.bmp', and '.tif' file:

fileList = dirPlus(rootPath, 'FileFilter', '\.(jpg|bmp|tif)$');
fprintf('%d files found.\n', size(fileList, 1));
fprintf('%s\n', fileList{1:5}, '...');

%% The 'ReturnDirs' option
% We can instead collect a list of subdirectories by setting the
% 'ReturnDirs' option to |true|:

dirList = dirPlus(rootPath, 'ReturnDirs', true);
fprintf('%d directories found.\n', size(dirList, 1));
fprintf('%s\n', dirList{1:5}, '...');

%%
% Note that the output list will be ordered by subdirectory depth (i.e. all
% subdirectories at depth 0, followed by all subdirectories at depth 1,
% etc.). Any settings for 'FileFilter' will be ignored.

%% The 'DirFilter' option
% We can filter subdirectories just like we filter files using the
% 'DirFilter' option. This will give us a list of subdirectories containing
% the string |'addons'|:

dirList = dirPlus(rootPath, 'ReturnDirs', true, 'DirFilter', 'addons');
fprintf('%d directories found.\n', size(dirList, 1));
fprintf('%s\n', dirList{:});

%%
% There are 4 subdirectories in our root directory with |'addons'| in the
% name. Let's say we wanted to find any '.m' files in subdirectories with
% |'addons'| in the name. We can use the 'DirFilter' and 'FileFilter'
% options like so:

fileList = dirPlus(rootPath, 'DirFilter', 'addons', 'FileFilter', '\.m$');
fprintf('%d files found.\n', size(fileList, 1));
fprintf('%s\n', fileList{:});

%%
% No files found? We know from the <dirPlus_demo.html#2 *'FileFilter'*>
% example above that there are '.m' files present in
% |rootPath\addons\cef\+matlab\+internal\+addons\|. Shouldn't these show
% up? And for that matter, why didn't '+addons' show up in the list of
% subdirectories containing the string |'addons'|? There's another option
% setting at work here...

%% The 'RecurseInvalid' option
% When a subdirectory doesn't match the 'DirFilter' regular expression
% pattern (marking it as "invalid"), a few things happen:
%
% # That subdirectory is not included in any output lists returned with the
% 'ReturnDirs' option.
% # The file contents of that subdirectory are not included in any output
% lists returned.
% # *By default*, the recursive search does not go any further down the
% folder tree for that subdirectory. This is why the '+addons' folder is
% not found or searched through in the prior examples: it is nested within
% invalid folders (namely, 'cef').
%
% In some cases we'd like the recursive search to continue through
% subdirectories even when their contents are excluded. Setting the
% 'RecurseInvalid' option to |true| accomplishes this:

fileList = dirPlus(rootPath, 'DirFilter', 'addons', 'FileFilter', '\.m$', ...
                             'RecurseInvalid', true);
fprintf('%d files found.\n', size(fileList, 1));
fprintf('%s\n', fileList{:});

%%
% And now we can see those '.m' files in the deeply nested '+addons'
% subdirectory.

%% The 'Struct' option
% Instead of getting the output as a cell array of files/subdirectories, we
% can have |dirPlus| return a structure array of the form returned by the
% <https://www.mathworks.com/help/matlab/ref/dir.html |dir|> function by
% setting the 'Struct' option to |true|:

fileList = dirPlus(rootPath, 'Struct', true, 'FileFilter', '\.m$');
fprintf('%d files found.\n', size(fileList, 1));
display(fileList(1));

%% The 'Depth' option
% If we don't want to search quite so far down the folder tree, we can
% limit the search depth with the 'Depth' option. Let's see how many '.m'
% files are in the root folder:

fileList = dirPlus(rootPath, 'FileFilter', '\.m$', 'Depth', 0);
fprintf('%d files found.\n', size(fileList, 1));

%%
% Looks like none are. They are all contained in subdirectories. Let's see
% how many are located in just the immediate subdirectories of the root
% folder:

fileList = dirPlus(rootPath, 'FileFilter', '\.m$', 'Depth', 1);
fprintf('%d files found.\n', size(fileList, 1));

%% The 'PrependPath' option
% Maybe we just want the file/subdirectory names, but don't care about the
% absolute paths. In this case, we just set the 'PrependPath' option to
% |false|:

fileList = dirPlus(rootPath, 'FileFilter', '\.m$', 'PrependPath', false);
fprintf('%d files found.\n', size(fileList, 1));
fprintf('%s\n', fileList{1:5}, '...');

%% The 'ValidateFileFcn' option
% Sometimes we might want to select files based on a more complicated
% criteria than just what's in their names. In this case, we can use the
% 'ValidateFileFcn' option to specify a function that is to be run on each
% file found. This function should accept as input a structure of the form
% returned by the <https://www.mathworks.com/help/matlab/ref/dir.html
% |dir|> function and return a logical value (|true| to collect it in the
% list, |false| to ignore it). First, let's find all the '.png' files:

fileList = dirPlus(rootPath, 'FileFilter', '\.png$');
fprintf('%d files found.\n', size(fileList, 1));

%%
% Now, we can specify an anonymous function that gets the byte size of each
% file and returns |true| for only those greater than 250KB:

bigFcn = @(s) (s.bytes > 512^2);
fileList = dirPlus(rootPath, 'FileFilter', '\.png$', ...
                             'ValidateFileFcn', bigFcn);
fprintf('%s\n', fileList{:});

%%
% Just the one.

%% The 'ValidateDirFcn' option
% We can apply more complicated validation criteria for subdirectories as
% well using the 'ValidateDirFcn' option. Let's say we want to find all the
% '.m' files that are not contained within a
% <https://www.mathworks.com/help/matlab/matlab_oop/scoping-classes-with-packages.html
% package folder> (i.e. one that starts with '+'). Here's one way to do it:

dirFcn = @(s) ~strcmp(s.name(1), '+');
fileList = dirPlus(rootPath, 'ValidateDirFcn', dirFcn, 'FileFilter', '\.m$');
fprintf('%d files found.\n', size(fileList, 1));
fprintf('%s\n', fileList{1:5}, '...');

%%
% In this case, you could actually do this using a 'DirFilter' regular
% expression as well:

fileList = dirPlus(rootPath, 'DirFilter', '^[^+]', 'FileFilter', '\.m$');
fprintf('%d files found.\n', size(fileList, 1));
fprintf('%s\n', fileList{1:5}, '...');


function [abbox_scores] = recognize_bboxes_of_all_imgs(...
    model, image_paths, all_bbox_proposals, dst_directory, image_set_name, varargin)
% recognize_bboxes_of_all_imgs: given a bounding box recognition model and
% a set of images with their input candidate bounding boxes, for each
% image it assigns a confidence score to each candidate bounding box that
% represents the likelihood to tightly enclose an object of interest.
%
% INPUTS:
% 1) model: (type struct) the bounding box recognition model
% 2) image_paths: NI x 1 cell array with the image paths of the set in the
% form of strings. NI is the number of images.
% 3) all_bbox_proposals: a cell array with the candidate bounding
% boxes that are going to be processed. It can be of two forms:
%   a) (the flag is_per_class must being set to false) a NI x 1 cell array
%   where NI is the number of images. The all_bbox_proposals{i} element
%   contains the candidate bounding boxes of the i-th image in the form of a
%   NB_i x 4 array where NB_i is the number of candidate bounding boxes of
%   the i-th image. The 4 columns of this array contain the bounding box
%   coordinates in the form of [x0,y0,x1,y1] (where the (x0,y0) and (x1,y1)
%   are the top-left and bottom-right corners).
%   b) (the flag is_per_class must being set to true) a C x 1 cell array
%   where C is the number of categories. The all_bbox_proposals{j} element
%   in this case is NI x 1 cell array, where NI is the number of images,
%   with the candidate bounding boxes of the j-th category for each image.
%   The element all_bbox_proposals{j}{i} is a NB_{i,j} x 4 array, where
%   NB_{i,j} is the number candidate bounding box of the i-th
%   image for the j-th category. The 4 columns of this array are the
%   bounding boxes in the form of [x0,y0,x1,y1] (where the (x0,y0) and (x1,y1)
%   are the top-left and bottom-right corners).
% 4) dst_directory: string with the path of the destination directory where
% the results are going to be cached.
% 5) image_set_name: string with the name of the image set that is being
% processed. It will be used on the name of the file where the results will
% be saved.
% 6) The rest input arguments are given in the form of Name,Value pair
% arguments and are:
% 'is_per_class': boolean value that if set to false, then the 3.a) form
% of the all_bbox_proposals input parameter will be expected; otherwise, if set to
% true then the 3.b) form of the all_bbox_proposals input parameter will be
% expected. Default value: false
% 'suffix': string with a suffix that it will be used on the name of the
% file where the results will be saved. Default value: ''
% 'all_bbox_gt': (optional) a NI cell array with the ground truth bounding
% boxes of each image; it will be used (if given) for printing the mAP on
% regular (see param 'checkpoint_step') step during processing the image set
% 'checkpoint_step': scalar value; during processing the NI images, after each
% checkpoint_step number of images the results are cached and the mAP
% results are printed. Default value: 500
%
% This file is part of the code that implements the following paper:
% Title      : "LocNet: Improving Localization Accuracy for Object Detection"
% Authors    : Spyros Gidaris, Nikos Komodakis
% Institution: Universite Paris Est, Ecole des Ponts ParisTech
% ArXiv link : http://arxiv.org/abs/1511.07763
% code       : https://github.com/gidariss/LocNet
%
% AUTORIGHTS
% --------------------------------------------------------
% Copyright (c) 2016 Spyros Gidaris
%
% Title     : "LocNet: Improving Localization Accuracy for Object Detection"
% ArXiv link: http://arxiv.org/abs/1511.07763
% Licensed under The MIT License [see LICENSE for details]
% ---------------------------------------------------------

ip = inputParser;
ip.addParamValue('is_per_class', false, @islogical);
ip.addParamValue('suffix', '', @ischar);
ip.addParamValue('all_bbox_gt', {},     @iscell);
ip.addParamValue('checkpoint_step', 500, @isnumeric);

ip.parse(varargin{:});
opts = ip.Results;

mkdir_if_missing(dst_directory);
filepath_results     = [dst_directory, filesep, 'scores', '_boxes_', opts.suffix, image_set_name, '.mat'];
in_progress_filepath = [dst_directory, filesep, 'scores', '_boxes_', opts.suffix, image_set_name, '_in_progress.mat'];

timestamp       = datestr(datevec(now()), 'yyyymmdd_HHMMSS');
log_file        = fullfile(dst_directory, 'output', ...
    ['log_file_recognition',opts.suffix, image_set_name, '_', timestamp, '.txt']);
mkdir_if_missing(fileparts(log_file));

t_start = tic();
try
    abbox_scores = load_bboxes_scores(filepath_results);
catch
    diary(log_file);
    abbox_scores = process_images(...
        model, image_paths, all_bbox_proposals, opts.all_bbox_gt, ...
        opts.is_per_class, in_progress_filepath, opts.checkpoint_step);
    save_bboxes_scores(filepath_results, abbox_scores);
    diary off;
    delete(in_progress_filepath);
end
fprintf('Recognize bounding box proposals in %.4f minutes.\n', toc(t_start)/60);
end

function save_bboxes_scores(filename, bboxes_scores)
save(filename, 'bboxes_scores', '-v7.3');
end

function bboxes_scores = load_bboxes_scores(filename)
load(filename, 'bboxes_scores');
end

function all_bboxes_out = process_images(...
    model, image_paths, all_bbox_proposals, all_bbox_gt, ...
    is_per_class, in_progress_filepath, checkpoint_step)

num_imgs      = length(image_paths);
nms_iou_thrs  = 0.3;
max_per_set   = 5 * num_imgs;
max_per_image = 100;
num_classes   = length(model.classes);
in_progress_filepath_prev = [in_progress_filepath, '.prev'];

try
    % load (if any) cached subset of results from images that have being
    % already processed from a previous run of the script that was stopped
    % before finish processing all the images.
    try
        [fist_img_idx, aboxes, all_bboxes_out, thresh] = load_progress(in_progress_filepath);
    catch
        [fist_img_idx, aboxes, all_bboxes_out, thresh] = load_progress(in_progress_filepath_prev);
    end
    mAP   = check_progress_on_mAP(aboxes, all_bbox_gt, fist_img_idx-1, model.classes);
    mAP_i = fist_img_idx-1;
catch exception
    fprintf('Exception message %s\n', getReport(exception));
    aboxes = cell(num_classes, 1);

    for i = 1:num_classes, aboxes{i} = cell(num_imgs, 1); end
    if is_per_class
        all_bboxes_out = cell(num_classes,1);
        for i = 1:num_classes, all_bboxes_out{i} = cell(num_imgs, 1); end
    else
        all_bboxes_out = cell(num_imgs,1);
    end
    thresh = -3.5 * ones(num_classes, 1);
    fist_img_idx = 1; mAP = 0; mAP_i = 0;
end

total_el_time = 0;
model.max_rois_num_in_gpu = 1000; %find_max_rois_num_in_gpu(model);
num_chars = 0;
for i = fist_img_idx:num_imgs
    th = tic;
    % get the bounding box proposals of this image
    bbox_proposals = get_this_img_bbox_proposals(all_bbox_proposals, i, is_per_class);
    image          = get_image(image_paths{i}); % read the image
    % score the bounding box proposals with the recognition model
    bboxes_scores  = recognize_bboxes_of_image(model, image, bbox_proposals(:,1:4));
    recognition_time = toc(th);

    th = tic;
    % prepare the candidate boundng box detections of this image
    bbox_cand_dets = prepare_bbox_cand_dets(bbox_proposals, bboxes_scores, num_classes, is_per_class);
    % prepare the output for this image
    all_bboxes_out = prepare_this_img_output(all_bboxes_out, i, is_per_class, bbox_cand_dets);
    % perform the post-processing step of non-max-suppresion on the
    % candidate boundng box detections of this image
    bbox_detections = post_process_candidate_detections(bbox_cand_dets, ...
        'thresholds',thresh, 'nms_iou_thrs',nms_iou_thrs,'use_gpu',true,...
        'max_per_image',max_per_image);

    for j = 1:num_classes, aboxes{j}{i} = bbox_detections{j}; end
    postprocessing_time = toc(th);

    if mod(i, checkpoint_step) == 0
        th = tic;
        for j = 1:num_classes, [aboxes{j}, thresh(j)] = keep_top_k(aboxes{j}, i, max_per_set, thresh(j)); end
        disp(thresh(:)');

        % save the till now progress
        save_progress(aboxes, all_bboxes_out, thresh, i, in_progress_filepath, in_progress_filepath_prev);

        % evaluate the mAP of the images 1 till i
        mAP = check_progress_on_mAP(aboxes, all_bbox_gt, i, model.classes);
        mAP_i = i;
        diary; diary; % flush diary

        checkpoint_time = toc(th);
        fprintf('check_point time %.2fs\n',checkpoint_time)
        num_chars = 0;
    end

    elapsed_time = recognition_time + postprocessing_time;
    [total_el_time, avg_time, est_rem_time] = timing_process(elapsed_time, total_el_time, fist_img_idx, i, num_imgs);
    fprintf(repmat('\b',[1, num_chars]));

    num_chars = fprintf('%s: bbox rec %d/%d:| ET %.3fs + %.3fs | AT: %.3fs | TT %.4fmin | ERT %.4fmin | mAP[%d/%d] = %.4f\n', ...
        procid(), i, num_imgs, recognition_time, postprocessing_time, avg_time, ...
        total_el_time/60, est_rem_time/60, mAP_i, num_imgs, mAP);

end

delete(in_progress_filepath_prev);
end

function [total_el_time, ave_time, est_rem_time] = timing_process(...
    elapsed_time, total_el_time, fist_img_idx, i, num_imgs)

total_el_time   = total_el_time + elapsed_time;
ave_time        = total_el_time / (i-fist_img_idx+1);
est_rem_time    = ave_time * (num_imgs - i);
end

function bbox_proposals = get_this_img_bbox_proposals(all_bboxes_in, img_id, is_per_class)
if is_per_class
    bbox_proposals_per_class = cellfun(@(x) x{img_id}(:,1:4), all_bboxes_in, 'UniformOutput', false);
    num_bbox_per_class = cellfun(@(x) size(x,1), bbox_proposals_per_class,  'UniformOutput', true);
    bbox_proposals = cell2mat(bbox_proposals_per_class(num_bbox_per_class>0));

    class_indices = single([]);
    for c = 1:length(num_bbox_per_class)
        class_indices = [class_indices; ones(num_bbox_per_class(c),1,'single')*c];
    end

    bbox_proposals = single([bbox_proposals, class_indices]);
    if isempty(bbox_proposals), bbox_proposals = zeros(0,5,'single'); end
else
    bbox_proposals = all_bboxes_in{img_id}(:,1:4);
end
end

function bbox_cand_dets = prepare_bbox_cand_dets(bbox_proposals, bbox_scores, num_classes, is_per_class)
if is_per_class
    class_indices  = bbox_proposals(:,5);
    bbox_cand_dets = cell(num_classes,1);
    for c = 1:num_classes
        this_cls_mask = class_indices==c;
        bbox_cand_dets{c} = single([bbox_proposals(this_cls_mask,1:4),bbox_scores(this_cls_mask,c)]);
        if isempty(bbox_cand_dets{c}), bbox_cand_dets{c} = zeros(0,5,'single'); end
    end
else
    bbox_cand_dets = single([bbox_proposals(:,1:4), bbox_scores]);
end
end

function all_bboxes_out = prepare_this_img_output(all_bboxes_out, img_idx, is_per_class, bbox_this_img)
if is_per_class
    for j = 1:length(bbox_this_img), all_bboxes_out{j}{img_idx} = bbox_this_img{j}; end
else
    all_bboxes_out{img_idx} = bbox_this_img;
end
end

function [fist_img_idx, aboxes, abbox_scores, thresh] = load_progress(in_progress_filepath)
ld = load(in_progress_filepath);
fist_img_idx = ld.progress_state.img_idx + 1;
aboxes       = ld.progress_state.aboxes;
abbox_scores = ld.progress_state.abbox_scores;
thresh       = ld.progress_state.thresh;
end

function save_progress(aboxes, abbox_scores, thresh, img_idx, in_progress_filepath, in_progress_filepath_prev)
progress_state              = struct;
progress_state.img_idx      = img_idx;
progress_state.aboxes       = aboxes;
progress_state.abbox_scores = abbox_scores;
progress_state.thresh       = thresh;

if exist(in_progress_filepath, 'file')
    % in case it crash during updating the in_progress_filepath file
    copyfile(in_progress_filepath, in_progress_filepath_prev);
end
save(in_progress_filepath, 'progress_state', '-v7.3');
end

function mAP = check_progress_on_mAP(aboxes, all_bbox_gt, img_idx, classes)
mAP = 0;
if ~isempty(all_bbox_gt)
    aboxes      = cellfun(@(x) x(1:img_idx), aboxes, 'UniformOutput', false);
    mAP_result  = evaluate_average_precision_pascal( all_bbox_gt(1:img_idx), aboxes, classes );
    printAPResults(classes, mAP_result);
    mAP = mean([mAP_result(:).ap]');
end
end

function [boxes, thresh] = keep_top_k(boxes, end_at, top_k, thresh)
% ------------------------------------------------------------------------
% Keep top K
X = cat(1, boxes{1:end_at});
if isempty(X), return; end

scores = sort(X(:,end), 'descend');
thresh = scores(min(length(scores), top_k));
for image_index = 1:end_at
    bbox = boxes{image_index};
    keep = find(bbox(:,end) >= thresh);
    boxes{image_index} = bbox(keep,:);
end

end


% This is a script to run a mesh unfold from the console. It It really an
% example of how such a script should work - it is not particularly
% beautiful. Or big. Or clever.
% ARW 021701

% Basically, we just collect all the date we need to pass to
% unfoldMeshFromGUI. The busyHandle and statusHandle are zero

% Test assignToNearest

saveExtra=1;
showFigures=1;
truePerimDist=1;
busyHandle=0;
statusHandle=0;
scaleFactor=[240/256 240/256 1.2];
perimDist=input('Unfold size: ');
startCoords=input('Start position: ');
fprintf('Browsing for input mesh file:');
[whiteFileName,whitePathName]=uigetfile('*.class','Select class file:');
whiteFileName=[whitePathName,whiteFileName];
[grayFileName,grayPathName]=uigetfile('*.gray','Select gray file:');
grayFileName=[grayPathName,grayFileName];
[flatFileName,flatPathName]=uiputfile('*.mat','Select output file:');
flatFileName=[flatPathName,flatFileName];

dummy=unfoldMeshFromGUI(whiteFileName,grayFileName,flatFileName,startCoords,scaleFactor,perimDist,statusHandle,busyHandle,showFigures,saveExtra,truePerimDist);


function testResults = runTestsOnModel(model, microbeID, inputDataFolder)
% Part of the DEMETER pipeline. This function performs all quality
% control/quality assurance tests on a model.
%
% USAGE:
%
%   testResults = runTestsOnModel(model, microbeID, inputDataFolder)
%
% INPUTS
% modelFolder           Folder with COBRA models (draft or refined
%                       reconstructions) to analyze
% inputDataFolder       Folder with experimental data and database files
%                       to load
%
% OUTPUT
% testResults           Structure with results of the test run
%
% .. Author:
%   - Almut Heinken, 03/2021

fields = {
    'Mass_imbalanced'
    'Charge_imbalanced'
    'Mets_without_formulas'
    'Leaking_metabolites'
    'ATP_from_O2'
    'Blocked_reactions'
    'RefinedReactionsCarryingFlux'
    'BlockedRefinedReactions'
    'Incorrect_Gene_Rules'
    'Incorrect_Compartments'
    'Carbon_sources_TruePositives'
    'Carbon_sources_FalseNegatives'
    'Fermentation_products_TruePositives'
    'Fermentation_products_FalseNegatives'
    'growsOnDefinedMedium'
    'growthOnKnownCarbonSources'
    'Biomass_precursor_biosynthesis_TruePositives'
    'Biomass_precursor_biosynthesis_FalseNegatives'
    'Metabolite_uptake_TruePositives'
    'Metabolite_uptake_FalseNegatives'
    'Secretion_products_TruePositives'
    'Secretion_products_FalseNegatives'
    'Bile_acid_biosynthesis_TruePositives'
    'Bile_acid_biosynthesis_FalseNegatives'
    'Drug_metabolism_TruePositives'
    'Drug_metabolism_FalseNegatives'
    'PutrefactionPathways_TruePositives'
    'PutrefactionPathways_FalseNegatives'
    'AromaticAminoAcidDegradation_TruePositives'
    'AromaticAminoAcidDegradation_FalseNegatives'
    };

testResults=struct();
% iterate over the field
for k=1:length(fields)
    testResults.(fields{k}){1, 1} = microbeID;
end

% Load reaction and metabolite database
database=loadVMHDatabase;
try
biomassReaction = model.rxns{strncmp('bio', model.rxns, 3)};

%
%% relax enforced uptake of some vitamins-causes infeasibility problems
relaxConstraints=model.rxns(find(model.lb>0));
model=changeRxnBounds(model,relaxConstraints,0,'l');

%% Mass and charge balance
% Tests whether the reactions in the reconstruction are mass and charge balanced.
% The function will report any reactions that have imbalanced mass or charge,
% along with their reaction formulas and imbalanced elements. The function will
% also report the metabolite formulas of all metabolites that occur in any imbalanced
% reactions. Finally, any metabolites without metabolite formulas are reported.
%
% *Inputs:*
%
% * *model*: COBRA model structure
% * *excludeExchanges*: Exclude exchange reactions when reporting imblanced
% reactions (default: true).
% * *biomassReaction*: Give biomass reaction abbreviation to exclude biomass
% reaction from analysis
%
% *Outputs:*
%
% * *massImbalancedRxns*: Cell array listing (col 1) all mass imbalanced reactions
% in the model, (col 2) the reaction formulas, and (col 3) the imbalanced elements.
% * *chargeImbalancedRxns*: Cell array listing (col 1) all charge imbalanced
% reactions in the model, (col 2) the reaction formulas, and (col 3) the imblanced
% elements.
% * *imbalancedRxnMets*: Cell array listing (col 1) all metabolites involved
% in any mass or charge imblanced reaction, (col 2) the metabolite name, (col
% 3) the metabolite formula, and (col 4) the metabolite charge.
% * *metsMissingFormulas*: Cell array listing (col 1) all metabolites that do
% not have metabolite formulas and (col 2) the metabolite names.
try
[massImbalancedRxns, chargeImbalancedRxns, ~, metsMissingFormulas] = testModelMassChargeBalance(model, true, biomassReaction);
testResults.Mass_imbalanced(1, 2:size(massImbalancedRxns,1)) =massImbalancedRxns(2:end,1);
testResults.Charge_imbalanced(1, 2:size(chargeImbalancedRxns,1))= chargeImbalancedRxns(2:end,1);
testResults.Mets_without_formulas(1, 2:length(metsMissingFormulas)) = metsMissingFormulas(2:end,1);
catch
    warning('Mass and charge balance could not be tested for draft reconstructions!')
end
%%
% A metabolic reconstruction should contain no mass or charge imbalanced
% reactions. However, some reactions will always be imbalanced by definition (exchange,
% demand, sink, and biomass reactions), and some reactions will be imbalanced
% when formulas of participating metabolites are not known.
%% Leaking metabolites
% Tests whether the model can produce any metabolites when no mass enters the
% model (all exchange and sink reactions blocked).
%
% *Inputs:*
%
% * *model*: COBRA model structure
%
% *Outputs:*
%
% * *leakingMets*: Cell array listing any metabolites that can be be produced
% from nothing and any reactions that are active in the simulation (along with
% reaction formula and flux value).

leakingMets = testLeakingMetabolites(model);
testResults.Leaking_metabolites(1, 2:length(leakingMets)+1) = leakingMets;

% The model should not leak any metabolites. Leaking metabolites require
% manual refinement.

%% ATP from oxygen
% Tests if models can produce ATP and carbon just from water,
% phosphate, and oxygen without an energy source. This is
% thermodynamically infeasible and should not happen.
basicCompounds={
    'EX_h2o(e)' '-100'
    'EX_h(e)' '-100'
    'EX_pi(e)' '-10'
    'EX_o2(e)' '-10'
    };
modelTest = useDiet(model,basicCompounds);
modelTest.lb(find(strncmp(modelTest.rxns,'sink_',5)))=0;
try
    modelTest=changeObjective(modelTest,'DM_atp_c_');
catch
    modelTest = addReaction(modelTest,'DM_atp_c','atp[c] + h2o[c] -> adp[c] + h[c] + pi[c]');
end
FBA=optimizeCbModel(modelTest);
testResults.ATP_from_O2{1, 2} = FBA.f;

%% Blocked reactions
% Computes all reactions in the reconstruction that can never carry flux.
% set "unlimited" constraints
model = changeRxnBounds(model, model.rxns(strncmp('EX_', model.rxns, 3)), -1000, 'l');
model = changeRxnBounds(model, model.rxns(strncmp('EX_', model.rxns, 3)), 1000, 'u');
BlockedRxns = identifyFastBlockedRxns(model);
testResults.Blocked_reactions(1, 2:length(BlockedRxns)+1) = BlockedRxns;

%% Test whether reactions added through refinement of gene annotations carry flux
[RefinedReactionsCarryingFlux, BlockedRefinedReactions] = testRefinedReactions(microbeID, BlockedRxns);
testResults.RefinedReactionsCarryingFlux(1, 2:length(RefinedReactionsCarryingFlux)+1) = RefinedReactionsCarryingFlux;
testResults.BlockedRefinedReactions(1, 2:length(BlockedRefinedReactions)+1) = BlockedRefinedReactions;

%% Entries in gene rules that have incorrect nomenclature
incorrectGeneRules = testGeneRules(model);
testResults.Incorrect_Gene_Rules(1, 2:length(incorrectGeneRules)+1) = incorrectGeneRules;

%% Reactions and metabolites with non-microbial compartments
[incorrectRxns,incorrectMets] = validateCompartments(model);
testResults.Incorrect_Compartments(1, 2:length(incorrectRxns)+1) = incorrectRxns;
testResults.Incorrect_Compartments(1, 2:length(incorrectMets)+1) = incorrectMets;

%% Carbon sources
% Tests which carbon sources that are reported in _in vitro_ data can be taken
% up by the model. The test requires a low flux through the biomass objective
% function.
% *Note:* Because we do not have data on carbon sources that should _not_
% be taken up by the model, we can only compare those that are known to be taken
% up by the microbe. Therefore, it is not possible to evaluate true negatives
% and false positives.

[TruePositives, FalseNegatives] = testCarbonSources(model, microbeID, biomassReaction, database, inputDataFolder);
testResults.Carbon_sources_TruePositives(1, 2:length(TruePositives)+1) = TruePositives;
testResults.Carbon_sources_FalseNegatives(1, 2:length(FalseNegatives)+1) = FalseNegatives;
%%
% The function |*carbonSourceGapfill|* aims to enable to uptake of all _in
% vitro_ reported carbon sources. In the case of any false negatives, the reconstruction
% needs to be manually refined to make sure that uptaken carbon source can enter
% an active metabolic pathway within the reconstruction.
%% Fermentation pathways
% Tests which fermentation pathways that are reported in _in vitro_ data are
% active in the model. The test requires a low flux through the biomass objective
% function.
% *Note:* Because we do not have data on carbon sources that should _not_
% be taken up by the model, we can only compare those that are known to be taken
% up by the microbe. Therefore, it is not possible to evaluate true negatives
% and false positives.

[TruePositives, FalseNegatives] = testFermentationProducts(model, microbeID, biomassReaction, database, inputDataFolder);
testResults.Fermentation_products_TruePositives(1, 2:length(TruePositives)+1) = TruePositives;
testResults.Fermentation_products_FalseNegatives(1, 2:length(FalseNegatives)+1) = FalseNegatives;
%%
% The function |*fermentationPathwayGapfill|* aims to enable to secretion
% of all _in vitro_ reported fermentation productions. In the case of any false
% negatives, the reconstruction needs to be manually refined to make sure that
% fermentation pathways are active within the reconstruction.

%% test the defined media according to literature
[growsOnDefinedMedium,constrainedModel,growthOnKnownCarbonSources] = testGrowthOnDefinedMedia(model, microbeID, biomassReaction, inputDataFolder);
testResults.growsOnDefinedMedium{1, 2} = growsOnDefinedMedium;
testResults.growthOnKnownCarbonSources{1, 2} = growthOnKnownCarbonSources;

% In the case of any false negatives, the reconstruction needs to be manually
% refined to make sure that essential metabolites cannot be synthesized _de novo_
% by the model or that non-essential metabolites are not required in the growth
% media.

%% Metabolite consumption
% Performs an FVA and reports those metabolites (exchange reactions)
% that can be taken up by the model and should be taken up according to
% data (true positives) and those metabolites that cannot be taken up by
% the model but should be taken up according to in vitro data (false
% negatives).
% Based on literature search of reported vitamin-secreting probiotics
% performed 11/2017, and a compendium of uptake and secretion products
% (PMID:28585563)

[TruePositives, FalseNegatives] = testMetaboliteUptake(model, microbeID, biomassReaction, database, inputDataFolder);
testResults.Metabolite_uptake_TruePositives(1, 2:length(TruePositives)+1) = TruePositives;
testResults.Metabolite_uptake_FalseNegatives(1, 2:length(FalseNegatives)+1) = FalseNegatives;

%% Metabolite secretion
% Performs an FVA and reports those secretion products (exchange reactions)
% that can be secreted by the model and should be secreted according to
% data (true positives) and those secretion products that cannot be secreted by
% the model but should be secreted according to in vitro data (false
% negatives).
% Based on literature search of reported vitamin-secreting probiotics
% performed 11/2017, and a compendium of uptake and secretion products
% (PMID:28585563)

[TruePositives, FalseNegatives] = testSecretionProducts(model, microbeID, biomassReaction, database, inputDataFolder);
testResults.Secretion_products_TruePositives(1, 2:length(TruePositives)+1) = TruePositives;
testResults.Secretion_products_FalseNegatives(1, 2:length(FalseNegatives)+1) = FalseNegatives;

%% Bile acid biotransformation
% Performs an FVA and reports those bile acid metabolites (exchange reactions)
% that can be secreted by the model and should be secreted according to
% data (true positives) and those bile acid metabolites that cannot be secreted by
% the model but should be secreted according to in vitro data (false
% negatives).

[TruePositives, FalseNegatives] = testBileAcidBiosynthesis(model, microbeID, biomassReaction, database);
testResults.Bile_acid_biosynthesis_TruePositives(1, 2:length(TruePositives)+1) = TruePositives;
testResults.Bile_acid_biosynthesis_FalseNegatives(1, 2:length(FalseNegatives)+1) = FalseNegatives;
%% Drug biotransformation
% Performs an FVA and reports those drug metabolites (exchange reactions)
% that can be secreted by the model and should be taken up and/or secreted according to
% data (true positives) and those drug metabolites that cannot be secreted by
% the model but should be secreted according to in vitro data (false
% negatives).

if exist('drugTable.txt','File')==2
    [TruePositives, FalseNegatives] = testDrugMetabolism(model, microbeID, biomassReaction, database);
    testResults.Drug_metabolism_TruePositives(1, 2:length(TruePositives)+1) = TruePositives;
    testResults.Drug_metabolism_FalseNegatives(1, 2:length(FalseNegatives)+1) = FalseNegatives;
end
%% Putrefaction pathways
% Performs an FVA and reports those putrefaction pathway end reactions (exchange reactions)
% that can carry flux in the model and should carry flux according to
% data (true positives) and those putrefaction pathway end reactions that
% cannot carry flux in the model but should be secreted according to in
% vitro data (false negatives).

[TruePositives, FalseNegatives] = testPutrefactionPathways(model, microbeID, biomassReaction, database);
testResults.PutrefactionPathways_TruePositives(1, 2:length(TruePositives)+1) = TruePositives;
testResults.PutrefactionPathways_FalseNegatives(1, 2:length(FalseNegatives)+1) = FalseNegatives;
%% Aromatic amino acid degradation
% Performs an FVA and reports those AromaticAA pathway end reactions (exchange reactions)
% that can carry flux in the model and should carry flux according to
% data (true positives) and those AromaticAA pathway end reactions that
% cannot carry flux in the model but should be secreted according to in
% vitro data (false negatives).
%
% INPUT
% model             COBRA model structure
% microbeID         Microbe ID in carbon source data file
% biomassReaction   Biomass objective functions (low flux through BOF
%                   required in analysis)
%
% OUTPUT
% TruePositives     Cell array of strings listing all aromatic amino acid
% degradation products
% that can be secreted by the model and in comnparative genomic data.
% FalseNegatives    Cell array of strings listing all aromatic amino acid
% degradation products
% that cannot be secreted by the model but should be secreted according to comparative genomic data.

[TruePositives, FalseNegatives] = testAromaticAADegradation(model, microbeID, biomassReaction, database);
testResults.AromaticAminoAcidDegradation_TruePositives(1, 2:length(TruePositives)+1) = TruePositives;
testResults.AromaticAminoAcidDegradation_FalseNegatives(1, 2:length(FalseNegatives)+1) = FalseNegatives;
end
end


function pix_hdr = GE_readHeaderPixel(fid, byte_align)
%
% pix_hdr = read_pixel_header(fid, byte_align)
%
% Loads the pixel header from the file with filed id fid
% and returns it as a structure.
% if byte_align = 1 then 32-bit alignment (SGI, LX2 format)
% if byte_align = 0 then 16-bit alignment (Sun, 5.X format)
%
% Souheil J. Inati
% Dartmouth College
% May 2000
% souheil.inati@dartmouth.edu
%

% define the structure and read
pix_hdr = struct('img_magic', fread(fid,1,'int32'));
pix_hdr = setfield(pix_hdr, 'img_hdr_length', fread(fid,1,'int32'));% length of total header in bytes and
                                                                    % a byte displacement to the 'pixel data area'
pix_hdr = setfield(pix_hdr, 'img_width', fread(fid,1,'int32'));  % width (pixels) of image
pix_hdr = setfield(pix_hdr, 'img_height', fread(fid,1,'int32')); % height (pixels) of image
pix_hdr = setfield(pix_hdr, 'img_depth', fread(fid,1,'int32'));  % depth (1, 8, 16, or 24 bits) of pixel
pix_hdr = setfield(pix_hdr, 'img_compress', fread(fid,1,'int32'));   % type of compression; see IC_* below
pix_hdr = setfield(pix_hdr, 'img_dwindow', fread(fid,1,'int32'));    % default window setting
pix_hdr = setfield(pix_hdr, 'img_dlevel', fread(fid,1,'int32')); % default level setting
pix_hdr = setfield(pix_hdr, 'img_bgshade', fread(fid,1,'int32'));    % background shade to use for non-image
pix_hdr = setfield(pix_hdr, 'img_ovrflow', fread(fid,1,'int32'));    % overflow value
pix_hdr = setfield(pix_hdr, 'img_undflow', fread(fid,1,'int32'));    % underflow value
pix_hdr = setfield(pix_hdr, 'img_top_offset', fread(fid,1,'int32')); % number of blank lines at image top
pix_hdr = setfield(pix_hdr, 'img_bot_offset', fread(fid,1,'int32')); % number of blank lines at image bottom
pix_hdr = setfield(pix_hdr, 'img_version', fread(fid,1,'int16'));    % version of the header structure
if byte_align, fseek(fid,2,0); end % 32-bit alignment
pix_hdr = setfield(pix_hdr, 'img_checksum', fread(fid,1,'uint16')); % 16 bit end_around_carry sum of pixels
pix_hdr = setfield(pix_hdr, 'img_p_id', fread(fid,1,'int32'));   % a byte disp to unique image identifier
pix_hdr = setfield(pix_hdr, 'img_l_id', fread(fid,1,'int32'));   % byte length of unique image identifier
pix_hdr = setfield(pix_hdr, 'img_p_unpack', fread(fid,1,'int32'));   % a byte disp to 'unpack control'
pix_hdr = setfield(pix_hdr, 'img_l_unpack', fread(fid,1,'int32'));   % byte length of 'unpack control'
pix_hdr = setfield(pix_hdr, 'img_p_compress', fread(fid,1,'int32')); % a byte disp to 'compression control'
pix_hdr = setfield(pix_hdr, 'img_l_compress', fread(fid,1,'int32')); % byte length of 'compression control'
pix_hdr = setfield(pix_hdr, 'img_p_histo', fread(fid,1,'int32'));    % a byte disp to 'histogram control'
pix_hdr = setfield(pix_hdr, 'img_l_histo', fread(fid,1,'int32'));    % byte length of 'histogram control'
pix_hdr = setfield(pix_hdr, 'img_p_text', fread(fid,1,'int32')); % a byte disp to 'text plane data'
pix_hdr = setfield(pix_hdr, 'img_l_text', fread(fid,1,'int32')); % byte length of 'text plane data'
pix_hdr = setfield(pix_hdr, 'img_p_graphics', fread(fid,1,'int32')); % a byte disp to 'graphics plane data'
pix_hdr = setfield(pix_hdr, 'img_l_graphics', fread(fid,1,'int32')); % byte length of 'graphics plane data'
pix_hdr = setfield(pix_hdr, 'img_p_dbHdr', fread(fid,1,'int32'));    % a byte disp to 'data base header data'
pix_hdr = setfield(pix_hdr, 'img_l_dbHdr', fread(fid,1,'int32'));    % byte length of 'data base header data'
pix_hdr = setfield(pix_hdr, 'img_levelOffset', fread(fid,1,'int32'));% value to add to stored Pixel Data values
                                                                     % to get the correct presentation value
pix_hdr = setfield(pix_hdr, 'img_p_user', fread(fid,1,'int32')); % byte displacement to user defined data
pix_hdr = setfield(pix_hdr, 'img_l_user', fread(fid,1,'int32')); % byte length of user defined data

return


function [doAlign, doResamp] = dtiInitAlign(dwParams,dwDir,doResamp)
%
%  doAlign = dtiInitAlign(dwParams,dwDir)
%
% Based on user selected params decide if we align the raw dwi data to a
% reference image (t1).
%
% WEB resources:
%   https://github.com/vistalab/vistasoft/wiki/DWI-Initialization
%   vistaBrowseGit('dtiInitAlign');
%
% (C) Stanford VISTA, 8/2011 [lmp]
%

%%
doAlign  = false;

% If we are overwriting or an alignment file does not exist then we signal
% to align and resample.
if dwParams.clobber == 1 || ~exist(dwDir.acpcFile,'file')
    doAlign  = true;
    doResamp = true;
else
    % Prompt the user to overwrite if clobber = 'ask'
    if dwParams.clobber == 0
        resp = questdlg([dwDir.acpcFile ' exists- would you like to overwrite it?'],...
            'Clobber AcPc','Overwrite','Use Existing File','Abort','Use Existing File');
        if(strcmpi(resp,'Abort')), error('User aborted.'); end
        if(strcmpi(resp,'Overwrite'))
            doAlign  = true;
            doResamp = true;
        end
    end
end

end