function HDR=bv2biosig_events(EVENT)
% BV2BIOSIG_EVENTS converts VMRK marker information BioSig Event codes.
%  according to biosig/doc/eventcodes.txt.
%  Currently, the convention of the BerlinBCI is implemented and supported.
%
%  HDR = bv2biosig_events(arg1)
%
%  arg1 can be an HDR-struct containg  HDR.EVENT.Desc
%  or a struct containing EVENT.Desc
%  or a cell-array Desc
%  or a char-array Desc
%
%  Warning: Approximately 32 (out of 510) events are currently not supported.
%  For your data, you can check this with this command:
%  HDR.EVENT.Desc(HDR.EVENT.TYP==0)
%
% see also: doc/eventcodes.txt

%	$Id$
%	Copyright (C) 2006,2007 by Alois Schloegl <a.schloegl@ieee.org>
%    	This is part of the BIOSIG-toolbox http://biosig.sf.net/

% This library is free software; you can redistribute it and/or
% modify it under the terms of the GNU Library General Public
% License as published by the Free Software Foundation; either
% Version 2 of the License, or (at your option) any later version.
%
% This library 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
% Library General Public License for more details.
%
% You should have received a copy of the GNU Library General Public
% License along with this library; if not, write to the
% Free Software Foundation, Inc., 59 Temple Place - Suite 330,
% Boston, MA  02111-1307, USA.

HDR.EVENT.Desc = [];
if isfield(EVENT,'EVENT')
	HDR = EVENT;
elseif isfield(EVENT,'Desc')
	HDR.EVENT = EVENT;
elseif iscell(EVENT)
	HDR.EVENT.Desc = EVENT;
elseif ischar(EVENT)
	for k=1:size(EVENT,1),
		HDR.EVENT.Desc{k} = EVENT(k,:);
	end;
else
	error('unknown input argument')
end;

if isfield(HDR.EVENT,'TeegType')
	ix = strmatch('New Segment',HDR.EVENT.TeegType);
	HDR.EVENT.TYP(ix)=hex2dec('7ffe');
end;

if ~isfield(HDR,'NS')
	HDR.NS = NaN;
end;
if ~isfield(HDR,'Label'),
	HDR.Label = repmat({' '},min(HDR.NS,128),1);
end;

FLAG_SEASON2_ARTERAWDATA = 0;
if (HDR.NS==128)
	tmp = strvcat(HDR.Label);
	tmp(55:56,4) = 'f';
	FLAG_SEASON2_ARTERAWDATA = isequal(tmp(1:64,1:end-1),tmp(65:128,2:end)) & all(tmp(65:128,1)=='x');
	FLAG_SEASON2_ARTERAWDATA = FLAG_SEASON2_ARTERAWDATA & strncmp(HDR.FILE.Name,'arte',4);
end;
FLAG_ARTERAWDATA = strncmp(HDR.FILE.Name,'arte',4);

for k1 = 1:length(HDR.EVENT.POS)
	if isfield(HDR.EVENT,'Desc')
		tmp = HDR.EVENT.Desc{k1};
	elseif isfield(HDR.EVENT,'CodeDesc') && (HDR.EVENT.TYP(k1)<=length(HDR.EVENT.CodeDesc))
		tmp = HDR.EVENT.CodeDesc{HDR.EVENT.TYP(k1)};
	else
		continue;
	end;

	if 0,

	elseif strncmp(tmp,'TargetCode',10)
		HDR.EVENT.TYP(k1) = str2double(tmp(11:12))+hex2dec('0300');

	elseif strcmp(tmp,'BeginOfTrial')
		HDR.EVENT.TYP(k1) = hex2dec('0300');

	elseif strcmp(tmp,'hit')
        	HDR.EVENT.TYP(k1) = hex2dec('0381');
        elseif strcmp(tmp,'wrong')
        	HDR.EVENT.TYP(k1) = hex2dec('0382');

% eye movements
        elseif strcmpi(tmp,'augen links')
        	HDR.EVENT.TYP(k1) = hex2dec('0431');
        elseif strcmpi(tmp,'augen rechts')
        	HDR.EVENT.TYP(k1) = hex2dec('0432');
        elseif strcmpi(tmp,'augen hoch') | strcmpi(tmp,'augen oben')
        	HDR.EVENT.TYP(k1) = hex2dec('0433');
        elseif strcmpi(tmp,'augen unten') | strcmpi(tmp,'augen runter')
        	HDR.EVENT.TYP(k1) = hex2dec('0434');
        elseif strcmpi(tmp,'augen offen') | strcmp(tmp,'Augen offen & entspannen')
        	HDR.EVENT.TYP(k1) = hex2dec('0114');
        elseif strcmpi(tmp,'augen zu') | strcmp(tmp,'Augen zu & entspannen')
        	HDR.EVENT.TYP(k1) = hex2dec('0115');
        elseif strcmp(tmp,'blinzeln')
        	HDR.EVENT.TYP(k1) = hex2dec('0439');

% muscle movements
        elseif strcmp(tmp,'EMG links')
        	HDR.EVENT.TYP(k1) = hex2dec('0441');
        elseif strcmp(tmp,'EMG rechts')
        	HDR.EVENT.TYP(k1) = hex2dec('0442');
        elseif strcmpi(tmp,'kopf bewegen')
        	HDR.EVENT.TYP(k1) = hex2dec('0443');
        elseif strcmp(tmp,'zunge an')
        	HDR.EVENT.TYP(k1) = hex2dec('0444');
        elseif strcmp(tmp,'zunge aus')
        	HDR.EVENT.TYP(k1) = hex2dec('8444');
        elseif strcmp(tmp,'Kiefer anspannen')
        	HDR.EVENT.TYP(k1) = hex2dec('0446');
        elseif strcmp(tmp,'beißen') | strcmp(tmp,'beissen') | strcmp(tmp,['bei',223,'en']),
        	HDR.EVENT.TYP(k1) = hex2dec('0446');
        elseif strcmp(tmp,'EMG fuss')
		HDR.EVENT.TYP(k1) = hex2dec('0447');
	elseif strcmp(tmp,'Arme bewegen')
		HDR.EVENT.TYP(k1) = hex2dec('0449');

% encoding der season2-arte* rawdata records
	elseif strncmp(tmp,'S',1) & (FLAG_SEASON2_ARTERAWDATA | FLAG_ARTERAWDATA),
		n = str2double(tmp(2:end));
		if n==11,	% EMG left
			HDR.EVENT.TYP(k1) = hex2dec('0441');
		elseif n==12,	% EMG right
			HDR.EVENT.TYP(k1) = hex2dec('0442');
		elseif n==13,	% EMG (foot)
			HDR.EVENT.TYP(k1) = hex2dec('0447');
		elseif n==1,	% Augen (left)
			HDR.EVENT.TYP(k1) = hex2dec('0431');
		elseif n==2,	% Augen (right)
			HDR.EVENT.TYP(k1) = hex2dec('0432');
		elseif n==3,	% Augen oben
			HDR.EVENT.TYP(k1) = hex2dec('0433');
		elseif n==4,	% Augen unten
			HDR.EVENT.TYP(k1) = hex2dec('0434');
		elseif n==5,	% blinzeln
			HDR.EVENT.TYP(k1) = hex2dec('0439');
		elseif n==6,	% Augen zu & entspannen
			HDR.EVENT.TYP(k1) = hex2dec('0115');
		elseif n==7,	% Augen offen & entspannen
			HDR.EVENT.TYP(k1) = hex2dec('0114');
		elseif n==8,	% beissen
			HDR.EVENT.TYP(k1) = hex2dec('0446');
		elseif n==9,	% kopf bewegen
			HDR.EVENT.TYP(k1) = hex2dec('0443');
		elseif any(n==[10,100])	% ende der aktion
			HDR.EVENT.TYP(k1) = bitxor(hex2dec('8000'),HDR.EVENT.TYP(k1-1));
		else
			HDR.EVENT.TYP(k1) = n;
		end;

% hits and misses, feedback
	elseif strncmp(tmp,'S',1) | strncmp(tmp,'R',1)
		HDR.EVENT.CHN(k1) = (tmp(1)=='R')*64+1;  %%% hack to distinguish Player 1 and 2 in SEASON2 data
		n = str2double(tmp(2:end));
		if n==11,	% hit (left)
		       	HDR.EVENT.TYP(k1) = hex2dec('0381');
		elseif n==12,	% hit (right)
	        	HDR.EVENT.TYP(k1) = hex2dec('0381');
		elseif n==13,	% hit (foot)
	        	HDR.EVENT.TYP(k1) = hex2dec('0381');
        	elseif n==21,	% miss (left)
	        	HDR.EVENT.TYP(k1) = hex2dec('0382');
		elseif n==22,	% miss (right)
	        	HDR.EVENT.TYP(k1) = hex2dec('0382');
		elseif n==23,	% time out
	        	HDR.EVENT.TYP(k1) = hex2dec('830d');
		elseif n==60,	% feedback onset
	        	HDR.EVENT.TYP(k1) = hex2dec('030d');
		elseif any(n==[4,5,7]) %%% ignore these
	        	HDR.EVENT.TYP(k1) = NaN;
        	else
	        	HDR.EVENT.TYP(k1) = n;
		end;

% end of segment
        elseif strcmp(tmp,'s') | strcmp(tmp,'stop') | strcmp(tmp,'stopp'),
        	HDR.EVENT.TYP(k1) = bitxor(hex2dec('8000'),HDR.EVENT.TYP(k1-1));

        elseif ~isempty(tmp)
        	[n,v,s] = str2double(tmp(2:end));
        	if (length(n)==1) & (~v)
        		HDR.EVENT.TYP(k1) = n;
       		end;
        end;
end;
HDR.EVENT.TYP = HDR.EVENT.TYP(:);

if isfield(HDR.EVENT,'POS');
	% remove S4, S5, S7 before computing trial end
	ix = find(HDR.EVENT.TYP(2:end)==hex2dec('7ffe'))+1;
	for k = 1:length(ix),
		if any(HDR.EVENT.TYP(ix(k)-1)==[1:3])
			HDR.EVENT.TYP(ix(k)-1) = NaN;	% if cue before end of segment is 1,2,or 3.
		end;
	end;

       	flag_remove = isnan(HDR.EVENT.TYP);
	HDR.EVENT.TYP = HDR.EVENT.TYP(~flag_remove);
	HDR.EVENT.POS = HDR.EVENT.POS(~flag_remove);
	HDR.EVENT.CHN = HDR.EVENT.CHN(~flag_remove);
	HDR.EVENT.DUR = HDR.EVENT.DUR(~flag_remove);
	if isfield(HDR.EVENT,'TeegType');
		HDR.EVENT.TeegType = HDR.EVENT.TeegType(~flag_remove);
	end;
	if isfield(HDR.EVENT,'Desc')
		HDR.EVENT.Desc = HDR.EVENT.Desc(~flag_remove);
	end;

       	ix1 = find(HDR.EVENT.TYP<10);
       	ix2 = find(HDR.EVENT.TYP==100);
       	if ~isempty(ix2),
		HDR.EVENT.TYP(ix2,1) = HDR.EVENT.TYP(ix2-1) + hex2dec('8000');
	end;
	ix0 = find((HDR.EVENT.TYP>0)&(HDR.EVENT.TYP<10));

	HDR.TRIG = HDR.EVENT.POS(ix0);
	HDR.Classlabel = HDR.EVENT.TYP(ix0);
end;

if any(HDR.EVENT.DUR~=1)
	warning('Duration is not 1')
end;

% convert from Type1 into Type3 table.
if 1, % ~isfield(HDR.EVENT,'CHN') & ~isfield(HDR.EVENT,'DUR'),
	% HDR.EVENT.CHN = zeros(size(HDR.EVENT.POS));
	HDR.EVENT.DUR = zeros(size(HDR.EVENT.POS));

	% convert EVENT.Version 1 to 3, currently used by GDF, BDF and alpha
	flag_remove = zeros(size(HDR.EVENT.TYP));
	types  = unique(HDR.EVENT.TYP);
	for k1 = find(bitand(types(:)',hex2dec('8000')));
	        TYP0 = bitand(types(k1),hex2dec('7fff'));
	        TYP1 = types(k1);
	        ix0  = (HDR.EVENT.TYP==TYP0);
	        ix1  = (HDR.EVENT.TYP==TYP1);

	        if sum(ix0)==sum(ix1),
	                HDR.EVENT.DUR(ix0) = HDR.EVENT.POS(ix1) - HDR.EVENT.POS(ix0);
	                flag_remove = flag_remove | (HDR.EVENT.TYP==TYP1);
                elseif 0,

                else
	                fprintf(2,'Warning BV2BIOSIG_EVENT: number of event onset (TYP=%s) and event offset (TYP=%s) differ (%i-%i) in %s\n',dec2hex(double(TYP0)),dec2hex(double(TYP1)),sum(ix0),sum(ix1),HDR.FileName);
                        %% double(.) operator needed because Matlab6.5 can not fix(uint16(..))
	        end;
	end;
	if any(HDR.EVENT.DUR<0)
	        fprintf(2,'Warning SOPEN: EVENT ONSET later than EVENT OFFSET\n',dec2hex(TYP0),dec2hex(TYP1));
	        %HDR.EVENT.DUR(:) = 0
	end;
	HDR.EVENT.TYP = HDR.EVENT.TYP(~flag_remove);
	HDR.EVENT.POS = HDR.EVENT.POS(~flag_remove);
	HDR.EVENT.CHN = HDR.EVENT.CHN(~flag_remove);
	HDR.EVENT.DUR = HDR.EVENT.DUR(~flag_remove);
	if isfield(HDR.EVENT,'TeegType');
		HDR.EVENT.TeegType = HDR.EVENT.TeegType(~flag_remove);
	end;
	%HDR.EVENT.TeegType = HDR.EVENT.TeegType(~flag_remove);
	if isfield(HDR.EVENT,'Desc')
		HDR.EVENT.Desc = HDR.EVENT.Desc(~flag_remove);
	end;
end;


function solve(acados_ocp)

% solve
acados_ocp.solve();


classdef TestBoxFilter
    %TestBoxFilter

    properties (Constant)
        im = fullfile(mexopencv.root(),'test','fruits.jpg');
    end

    methods (Static)
        function test_1
            img = imread(TestBoxFilter.im);
            out = cv.boxFilter(img);
            validateattributes(out, {class(img)}, {'size',size(img)});
        end

        function test_2
            img = imread(TestBoxFilter.im);
            out = cv.boxFilter(img, 'DDepth',-1, ...
                'KSize',[5 5], 'Anchor',[-1 -1], 'BorderType','Default');
            validateattributes(out, {class(img)}, {'size',size(img)});
        end

        function test_3
            img = imread(TestBoxFilter.im);
            out = cv.boxFilter(img, 'Normalize',false);
            validateattributes(out, {class(img)}, {'size',size(img)});
        end

        function test_error_argnum
            try
                cv.boxFilter();
                throw('UnitTest:Fail');
            catch e
                assert(strcmp(e.identifier,'mexopencv:error'));
            end
        end
    end

end


function plot_events(wevent, filepattern, figureOutDirectory)
numEvents = numel(wevent);
for eventNumber=1:numEvents
    fprintf('- plotting event %d of %d\n',eventNumber,numEvents );
    plot_panels(wevent{eventNumber});
    ah=get(gcf,'Children');
    title(ah(7),sprintf('Event %d',eventNumber));
    outfile = sprintf('%s/%s%03d.png',figureOutDirectory, filepattern, eventNumber);
    feval('print', '-dpng', outfile);
    close
end


function X = real(X)
%REAL (overloaded)

X.basis = real(X.basis);
X = clean(X);
if isa(X,'sdpvar')
    X.conicinfo = [0 0];
end


function [states] = tapas_vlinear_init_states(data, model, inference)
%%
%
% aponteeduardo@gmail.com
% copyright (C) 2016
%

states = cell(inference.niter, 1);

end


function [annolist_flat,single_person_flat] = flatten_annolist(annolist,single_person)

annolist_flat = struct('image',[],'annorect',[]);

n = 0;
single_person_flat = [];
for imgidx = 1:length(annolist)
    rect_gt = annolist(imgidx).annorect;
    for ridx = 1:length(rect_gt)
        if (isfield(rect_gt(ridx),'objpos') && ~isempty(rect_gt(ridx).objpos))
            n = n + 1;
            annolist_flat(n).image.name = annolist(imgidx).image.name;
            annolist_flat(n).annorect = rect_gt(ridx);
            single_person_flat(n) = ismember(ridx,single_person{imgidx});
        end
    end
end

end


function Tim = createTime(Time)

% CREATETIME  Create Tim structure.
%   CREATETIME(Time) returns a structure with the fields
%       .dt             sampling time
%       .firstFrame     first frame to be processed
%       .lastFrame      last frame to be processed
%   from the fields in input structure Time.

%   Copyright 2008-2009 Joan Sola @ LAAS-CNRS.

Tim = Time;

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

%---------------------------------------------------------------------
%
%   This file is part of SLAMTB, a SLAM toolbox for Matlab.
%
%   SLAMTB 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.
%
%   SLAMTB 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 SLAMTB.  If not, see <http://www.gnu.org/licenses/>.
%
%---------------------------------------------------------------------

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE


%computes an array of DetectionResults (which contain arrays of labeled events: goodEvents, missedEvents, badEvents) per
%file
classdef DetectionResultsComputer < handle
    properties (Access = public)
        tolerance = 10;
    end

    methods (Access = public)
        function obj = DetectionResultsComputer()
        end

        %returns an array of DetectionResults (one for each cell)
        function detectionResults = computeDetectionResults(obj,eventsCellArray,annotationsArray)

            nCells = length(eventsCellArray);
            detectionResults = repmat(DetectionResult,1,nCells);
            for i = 1 : nCells
                annotationSet = annotationsArray(i);
                detectedEvents = eventsCellArray{i};
                detectionResults(i) = obj.computeDetectionResult(detectedEvents,annotationSet.eventAnnotations);
            end
        end
    end

    methods (Access = private)
        function r = isRelevantEvents(obj,detectedEvents)
            if isempty(detectedEvents)
                r = [];
            else
                labels = [detectedEvents.label];
                nLabels = length(labels);
                r = false(1,nLabels);
                for i = 1 : nLabels
                    r(i) = obj.isRelevantLabel(labels(i));
                end
            end
        end

        function b = isRelevantLabel(~,label)
            b = label > 0;
        end

        function detectionResult = computeDetectionResult(obj,detectedEvents,eventAnnotations)

            isGoodEvent = obj.isRelevantEvents(detectedEvents);
            goodEvents = obj.computeGoodEvents(detectedEvents,isGoodEvent);
            badEvents = obj.computeBadEvents(detectedEvents,isGoodEvent);

            eventAnnotations = obj.removeIgnoredAnnotations(eventAnnotations);

            missedEvents = obj.computeMissedEventAnnotations(detectedEvents,eventAnnotations);
            detectionResult = DetectionResult(goodEvents,missedEvents,badEvents);
        end

        function eventAnnotations = removeIgnoredAnnotations(~, eventAnnotations)
            isValidLabel = ~Labeling.ShouldIgnoreLabels([eventAnnotations.label]);
            eventAnnotations = eventAnnotations(isValidLabel);
        end

        function goodEvents = computeGoodEvents(~,detectedEvents, isGoodEvent)
            nGoodEvents = sum(isGoodEvent);
            goodEvents = [];
            if nGoodEvents > 0
                goodEvents = repmat(Event(),1,nGoodEvents);
                goodEventCount = 1;
                for i = 1 : length(detectedEvents)
                    if isGoodEvent(i)
                        goodEvents(goodEventCount) = detectedEvents(i);
                        goodEventCount = goodEventCount + 1;
                    end
                end
            end
        end

        function badEvents = computeBadEvents(~,detectedEvents,isGoodEvent)
            nBadEvents = sum(~isGoodEvent);
            badEvents = [];
            if nBadEvents > 0
                badEvents = repmat(Event(),1,nBadEvents);
                eventCount = 1;
                for i = 1 : length(detectedEvents)
                    if ~isGoodEvent(i)
                        badEvents(eventCount) = detectedEvents(i);
                        eventCount = eventCount + 1;
                    end
                end
            end
        end

        function missedEvents = computeMissedEventAnnotations(obj,detectedEvents,eventAnnotations)
            didMissEvent = obj.computeDidMissEvent(detectedEvents,eventAnnotations);
            missedEvents = [];
            nMissedEvents = sum(didMissEvent);
            if nMissedEvents > 0
                missedEvents = repmat(EventAnnotation,1,nMissedEvents);
                missedEventCounter = 1;
                for i = 1 : length(didMissEvent)
                    if didMissEvent(i)
                        missedEvents(missedEventCounter) = eventAnnotations(i);
                        missedEventCounter = missedEventCounter + 1;
                    end
                end
            end
        end

        function didMissEvent = computeDidMissEvent(obj,detectedEvents,annotations)
            nEvents = length(annotations);
            if isempty(detectedEvents)
                didMissEvent = true(1,nEvents);
            else

                didMissEvent = false(1,nEvents);

                detectedEventLocations = [detectedEvents.sample];

                segmentStartings = detectedEventLocations - obj.tolerance;
                segmentEndings = detectedEventLocations + obj.tolerance;

                for i = 1 : length(annotations)
                    if obj.isRelevantLabel(annotations(i).label)
                        eventLocation = annotations(i).sample;
                        contained = DetectionResultsComputer.IsPointContainedInSegments(eventLocation,segmentStartings,segmentEndings);
                        if ~contained
                            didMissEvent(i) = true;
                        end
                    end
                end
            end
        end
    end

    methods (Access = private, Static)
        %returns true if an event value is contained within a range
        function b = IsPointContainedInSegment(point, segmentStarting, segmentEnding)
            b = (point <= segmentEnding && point >= segmentStarting);
        end

        %segments and points should be sorted
        function contained = IsPointContainedInSegments(point,segmentStartings,segmentEndings)
            contained = false;
            for i = 1 : length(segmentStartings)
                segmentStarting = segmentStartings(i);
                segmentEnding = segmentEndings(i);
                if DetectionResultsComputer.IsPointContainedInSegment(point,segmentStarting,segmentEnding)
                    contained = true;
                end
                if point < segmentStarting
                    break;
                end
            end
        end
    end

end


function title = p19_title ( )

%*****************************************************************************80
%
%% P19_TITLE returns the title of problem P19.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 February 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, string TITLE, the title of the problem.
%
  title = 'Problem 19, Enright and Pryce #D4';

  return
end


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

function test_naive_bayes_classifier_searchlight_tiny
    ds=cosmo_synthetic_dataset('ntargets',25,'nchunks',4,'size','small');
    nh=cosmo_spherical_neighborhood(ds,'radius',1,'progress',false);

    nh.neighbors={1:size(ds.samples,2)};
    nh.fa=cosmo_slice(nh.fa,1,2,'struct');

    opt=struct();
    opt.partitions=cosmo_nfold_partitioner(ds);
    opt.output='winner_predictions';
    opt.progress=false;

    x=cosmo_naive_bayes_classifier_searchlight(ds,nh,opt);
    assertEqual(x.fa,nh.fa);
    assertEqual(x.a,nh.a);

    nfolds=numel(opt.partitions.train_indices);
    for fold=1:nfolds
        tr=opt.partitions.train_indices{fold};
        te=opt.partitions.test_indices{fold};

        pred=cosmo_classify_naive_bayes(ds.samples(tr,:),...
                                            ds.sa.targets(tr),...
                                            ds.samples(te,:));
        y=x.samples(te,:);
        assertEqual(y,pred);

    end
    % compare with standard searchlight
    assert_same_output_as_classifical_searchlight(ds,nh,opt);

function test_naive_bayes_classifier_searchlight_basics
    ds=cosmo_synthetic_dataset('ntargets',25,'nchunks',4,'size','small');
    nh=cosmo_spherical_neighborhood(ds,'radius',1,'progress',false);

    nh.neighbors={1:size(ds.samples,2)};
    nh.fa=cosmo_slice(nh.fa,1,2,'struct');

    opt=struct();
    opt.partitions=cosmo_nfold_partitioner(ds);
    opt.output='winner_predictions';
    opt.progress=false;

    x=cosmo_naive_bayes_classifier_searchlight(ds,nh,opt);
    assertEqual(x.fa,nh.fa);
    assertEqual(x.a,nh.a);

    % compare with standard searchlight
    assert_same_output_as_classifical_searchlight(ds,nh,opt);

    opt.output='accuracy';
    xacc=cosmo_naive_bayes_classifier_searchlight(ds,nh,opt);
    assertEqual(xacc.samples,mean(bsxfun(@eq,x.samples,x.sa.targets)));
    assert_same_output_as_classifical_searchlight(ds,nh,opt);

function test_naive_bayes_classifier_searchlight_multiple_pred
    ds=cosmo_synthetic_dataset('ntargets',25,'nchunks',5,'size','small');
    nh=cosmo_spherical_neighborhood(ds,'radius',1,'progress',false);

    opt=struct();
    % multiple predictions per fold
    opt.partitions=cosmo_nchoosek_partitioner(ds,2);
    opt.output='winner_predictions';
    opt.progress=false;

    x=cosmo_naive_bayes_classifier_searchlight(ds,nh,opt);
    assertEqual(x.fa,nh.fa);
    assertEqual(x.a,nh.a);

    % compare with standard searchlight
    assert_same_output_as_classifical_searchlight(ds,nh,opt);

    opt.output='accuracy';
    assert_same_output_as_classifical_searchlight(ds,nh,opt);

function assert_same_output_as_classifical_searchlight(ds,nh,opt)
    opt.progress=false;
    x=cosmo_naive_bayes_classifier_searchlight(ds,nh,opt);

    opt.classifier=@cosmo_classify_naive_bayes;
    y=cosmo_searchlight(ds,nh,@cosmo_crossvalidation_measure,opt);

    sx=x.samples;
    sy=y.samples;
    assertElementsAlmostEqual(sx,sy);

    x=rmfield(x,'samples');
    y=rmfield(y,'samples');
    assertEqual(x,y);

function test_naive_bayes_classifier_searchlight_exceptions
    aet=@(varargin)assertExceptionThrown(@()...
                cosmo_naive_bayes_classifier_searchlight(varargin{:}),'');

    ds=cosmo_synthetic_dataset('size','small','nchunks',4);
    nh=cosmo_spherical_neighborhood(ds,'radius',1,'progress',false);

    opt=struct();
    opt.progress=false;
    opt.partitions=cosmo_nchoosek_partitioner(ds,2);

    opt.output='foo';
    aet(ds,nh,opt);

    % missing samples, so illegal partitions
    opt.output='winner_predictions';
    ds=cosmo_slice(ds,ds.sa.chunks<=2);
    opt.partitions=cosmo_nfold_partitioner(ds);
    aet(ds,nh,opt);

    % unsupported output
    opt.output='fold_predictions';
    ds_bad=ds;
    ds_bad=cosmo_slice(ds_bad,ds_bad.sa.chunks<=2);
    opt.partitions=cosmo_nfold_partitioner(ds_bad);
    aet(ds,nh,opt);

function test_naive_bayes_classifier_searchlight_deprecations
    ds=cosmo_synthetic_dataset('size','small','nchunks',4);
    nh=cosmo_spherical_neighborhood(ds,'radius',1,'progress',false);

    %
    opt=struct();
    opt.progress=false;
    opt.partitions=cosmo_nchoosek_partitioner(ds,2);
    opt.output='predictions';

    orig_warning_state=cosmo_warning();
    cleaner=onCleanup(@()cosmo_warning(orig_warning_state));
    cosmo_warning('reset');
    cosmo_warning('off');

    % no warnings
    w=cosmo_warning();
    assertEqual(numel(w.shown_warnings),0);

    % output='predictions' is deprecated, so expect a warning
    cosmo_naive_bayes_classifier_searchlight(ds,nh,opt);

    w=cosmo_warning();
    assertEqual(numel(w.shown_warnings),1);

function test_naive_bayes_classifier_searchlight_partial_partitions
    nchunks=4;
    ds=cosmo_synthetic_dataset('ntargets',5,'nchunks',nchunks,...
                        'size','small');
    nh=cosmo_spherical_neighborhood(ds,'radius',1,'progress',false);

    partitions=cosmo_nfold_partitioner(ds);
    nsamples=size(ds.samples,1);
    prediction_count=zeros(nsamples,1);
    for k=1:nchunks
        with_missing=partitions.test_indices{k}(2:end);
        partitions.test_indices{k}=with_missing;
        prediction_count(with_missing)=prediction_count(with_missing)+1;
    end

    opt=struct();
    opt.progress=false;
    opt.partitions=partitions;
    opt.output='winner_predictions';

    res=cosmo_naive_bayes_classifier_searchlight(ds,nh,opt);

    ds_sa=rmfield(ds.sa,'chunks');
    assertEqual(res.sa,ds_sa);
    cosmo_check_dataset(res);

    assert_same_output_as_classifical_searchlight(ds,nh,opt);


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

%%
clear; close all; clc;

%% Syntax
% |[Vm]=rigidTransformVertices(V,T,v);|

%% 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/>.


classdef Blob < handle
  % Wrapper class of caffe::Blob in matlab

  properties (Access = private)
    hBlob_self
  end

  methods
    function self = Blob(hBlob_blob)
      CHECK(is_valid_handle(hBlob_blob), 'invalid Blob handle');

      % setup self handle
      self.hBlob_self = hBlob_blob;
    end
    function shape = shape(self)
      shape = caffe_('blob_get_shape', self.hBlob_self);
    end
    function reshape(self, shape)
      shape = self.check_and_preprocess_shape(shape);
      caffe_('blob_reshape', self.hBlob_self, shape);
    end
    function data = get_data(self)
      data = caffe_('blob_get_data', self.hBlob_self);
    end
    function set_data(self, data)
      data = self.check_and_preprocess_data(data);
      caffe_('blob_set_data', self.hBlob_self, data);
    end
    function diff = get_diff(self)
      diff = caffe_('blob_get_diff', self.hBlob_self);
    end
    function set_diff(self, diff)
      diff = self.check_and_preprocess_data(diff);
      caffe_('blob_set_diff', self.hBlob_self, diff);
    end
  end

  methods (Access = private)
    function shape = check_and_preprocess_shape(~, shape)
      CHECK(isempty(shape) || (isnumeric(shape) && isrow(shape)), ...
        'shape must be a integer row vector');
      shape = double(shape);
    end
    function data = check_and_preprocess_data(self, data)
      CHECK(isnumeric(data), 'data or diff must be numeric types');
      self.check_data_size_matches(data);
      if ~isa(data, 'single')
        data = single(data);
      end
    end
    function check_data_size_matches(self, data)
      % check whether size of data matches shape of this blob
      % note: matlab arrays always have at least 2 dimensions. To compare
      % shape between size of data and shape of this blob, extend shape of
      % this blob to have at least 2 dimensions
      self_shape_extended = self.shape;
      if isempty(self_shape_extended)
        % target blob is a scalar (0 dim)
        self_shape_extended = [1, 1];
      elseif isscalar(self_shape_extended)
        % target blob is a vector (1 dim)
        self_shape_extended = [self_shape_extended, 1];
      end
      % Also, matlab cannot have tailing dimension 1 for ndim > 2, so you
      % cannot create 20 x 10 x 1 x 1 array in matlab as it becomes 20 x 10
      % Extend matlab arrays to have tailing dimension 1 during shape match
      data_size_extended = ...
        [size(data), ones(1, length(self_shape_extended) - ndims(data))];
      is_matched = ...
        (length(self_shape_extended) == length(data_size_extended)) ...
        && all(self_shape_extended == data_size_extended);
      CHECK(is_matched, ...
        sprintf('%s, input data/diff size: [ %s] vs target blob shape: [ %s]', ...
        'input data/diff size does not match target blob shape', ...
        sprintf('%d ', data_size_extended), sprintf('%d ', self_shape_extended)));
    end
  end
end


function Z = conj(Y)
%CONJ (overloaded)

Z = Y;
Z.basis = conj(Z.basis);
% Reset info about conic terms
Z.conicinfo = [0 0];


function [s,it]=display(a,tab,it)

  global display_tree_depth;
  if isempty(display_tree_depth) display_tree_depth=100; end;
  global display_tree_tab_step;
  if isempty(display_tree_tab_step) display_tree_tab_step=3; end;
  global display_tree_show_brackets;
  if isempty(display_tree_show_brackets) display_tree_show_brackets=1; end;

  % ----- tabulation stuff ----------
  print=0;  if nargin==1  tab=0; print=1; it=[]; end;
  tab_step=display_tree_tab_step;
  % ------ display tree ------------
  [s,it]=display(a.algorithm,tab,it);
  if  display_tree_show_brackets
    s=[s ones(1,tab+min(2,tab_step))*32 '{\n' ];
  end
  tab=tab+tab_step;
  i=length(it); v=it{i}; v=[v 1]; it{i}=v; %% add 1 to last row
  for i=1:length(a.child)
     [st it]=display(a.child{i},tab,it);
     if length(it{length(it)})<display_tree_depth
      s =[s ones(1,tab)*32 st];
     end

     j=length(it); v=it{j}; v(length(v))=v(length(v))+1;
     it{j}=v; %% increment last row
  end
  if  display_tree_show_brackets
    if  length(it{length(it)})>=display_tree_depth
     s=[s ones(1,tab)*32 '...\n'];
    end
    s =[s ones(1,tab-tab_step+min(2,tab_step))*32 '}\n' ];
  end
  tab=tab-tab_step;
  %% pop index of last item
  i=length(it); v=it{length(it)}; v=v(1:length(v)-1); it{i}=v;
  if print
   s=s(1:length(s)-2); % remove last carriage return
   it=deal(it(1:length(it)-1)); % remove last index to tree
   disp(sprintf(char(s)));
  end


function [ path ] = full_path( db,enterie )
%FULL_PATH Summary of this function goes here
%   Detailed explanation goes here
   path=[db.path '/'];
   for ii=1:length(db.metaNames)
       path = [path enterie.(db.metaNames{ii}),'/'];
   end
   path =[path(1:end-1),'.',db.format];
end


function saveTightFigure(h,outfilename)
% SAVETIGHTFIGURE(H,OUTFILENAME) Saves figure H in file OUTFILENAME without
%   the white space around it.
%
% by ``a grad student"
% http://tipstrickshowtos.blogspot.com/2010/08/how-to-get-rid-of-white-margin-in.html

% get the current axes
ax = get(h, 'CurrentAxes');

% make it tight
ti = get(ax,'TightInset');
set(ax,'Position',[ti(1) ti(2) 1-ti(3)-ti(1) 1-ti(4)-ti(2)]);

% adjust the papersize
set(ax,'units','centimeters');
pos = get(ax,'Position');
ti = get(ax,'TightInset');
set(h, 'PaperUnits','centimeters');
set(h, 'PaperSize', [pos(3)+ti(1)+ti(3) pos(4)+ti(2)+ti(4)]);
set(h, 'PaperPositionMode', 'manual');
set(h, 'PaperPosition',[0 0  pos(3)+ti(1)+ti(3) pos(4)+ti(2)+ti(4)]);

% save it
saveas(h,outfilename);

% Copyright (c) 2011, Emre Akbas
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
%
%     * Redistributions of source code must retain the above copyright
%       notice, this list of conditions and the following disclaimer.
%     * 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 OWNER 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.


function [err, Info] = Info_1D(v, fname)
%
% [err, Info] = Info_1D(M, name);
% an Info structure for a 1D file. To use with WriteBrik
%
% Specify name if you want Info.RootName and Info.Extension_1D to be filled out
% otherwise, you can do that on your own later.
%
% see also Read_1D, BrikLoad, and BrikInfo
%     Ziad S. Saad saadz@mail.nih.gov, SSCC/NIMH/NIH/USA

FuncName = 'Info_1D';
err = 1;
Info = [];

if (isempty(v)),
   fprintf(2,'Error %s:\nEmpty M.\n', FuncName);
   return;
end

%some fake Info stuff
if (nargin == 2),
   [Info.RootName, Info.Extension_1D] = Remove1DExtension(fname);
else
   fname = '';
   Info.RootName = '';
   Info.Extension_1D = '';
end

Info.TypeName = '';
Info.TypeBytes = 0;
Info.Orientation = '';
Info.ByteOrder = '';
Info.FileFormat = '1D';
Info.DATASET_DIMENSIONS = [size(v, 1) 1 1 0 0];
Info.DATASET_RANK = [3 size(v,2) 0 0 0 0 0 0];
Info.BRICK_TYPES = [];
Info.BRICK_STATS = [];
Info.BRICK_FLOAT_FACS = '';
Info.BYTEORDER_STRING = '';
Info.ORIENT_SPECIFIC = [];
Info.ORIGIN = [0.0 0.0 0.0];
Info.DELTA = [1 1 1];
Info.BRICK_LABS = '';
Info.BRICK_KEYWORDS = '';
Info.SCENE_DATA = [];
Info.TYPESTRING = '';
Info.IDCODE_STRING = '';
Info.IDCODE_DATE = '';
Info.BRICK_STATAUX = [];
Info.STAT_AUX = [];
Info.HISTORY_NOTE = [];
Info.IDCODE_ANAT_PARENT = '';

err = 0;
return;


function [dat] = read_neuralynx_cds(filename, hdr, begsample, endsample, chanindx);

% READ_NEURALYNX_CDS reads selected samples and channels from a  combined Neuralynx dataset with seperate subdirectories for the LFP, MUA and spike channels
%
% Use as
%    hdr = read_neuralynx_cds(parentdir)
%    dat = read_neuralynx_cds(parentdir, hdr, begsample, endsample, chanindx)

% Copyright (C) 2006, 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: read_neuralynx_cds.m 945 2010-04-21 17:41:20Z roboos $

needhdr = (nargin==1);
needdat = (nargin>=2);

dirlist = dir(filename);
haslfp   = any(filetype_check_extension({dirlist.name}, 'lfp'));
hasmua   = any(filetype_check_extension({dirlist.name}, 'mua'));
hasspike = any(filetype_check_extension({dirlist.name}, 'spike'));
%hasttl  = any(filetype_check_extension({dirlist.name}, 'ttl'));   % seperate file with original Parallel_in
%hastsl  = any(filetype_check_extension({dirlist.name}, 'tsl'));   % seperate file with original TimeStampLow
%hastsh  = any(filetype_check_extension({dirlist.name}, 'tsh'));   % seperate file with original TimeStampHi

if needhdr
  % read the header from the LFP dataset
  if haslfp
    lfpdir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'lfp'))).name);
    lfphdr = read_header(lfpdir);
    lfpfil = lfphdr.filename;
    for i=1:lfphdr.nChans
      lfplab{i} = sprintf('lfp_%s', lfphdr.label{i});
    end
  else
    lfphdr = [];
    lfpfil = {};
    lfplab = {};
  end

  % read the header from the MUA dataset
  if hasmua
    muadir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'mua'))).name);
    muahdr = read_header(muadir);
    muafil = muahdr.filename;
    for i=1:muahdr.nChans
      mualab{i} = sprintf('mua_%s', muahdr.label{i});
    end
  else
    muahdr = [];
    muafil = {};
    mualab = {};
  end

  % read the header from the SPIKE dataset
  if hasspike
    spikedir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'spike'))).name);
    spikehdr = read_header(spikedir);
    spikefil = spikehdr.filename;
    for i=1:spikehdr.nChans
      spikelab{i} = sprintf('spike_%s', spikehdr.label{i});
    end
  else
    spikehdr = [];
    spikefil = {};
    spikelab = {};
  end

  if haslfp
    % assume that the LFP header describes the MUA and the spikes as well
    hdr = lfphdr;
  else hasmua
    % assume that the MUA header describes the spikes as well
    hdr = muahdr;
  end

  % concatenate the lfp/mua/spike channels, they have already been renamed
  hdr.label    = cat(1, lfplab(:), mualab(:), spikelab(:));
  hdr.filename = cat(1, lfpfil(:), muafil(:), spikefil(:));
  hdr.nChans = length(hdr.label);
  % remember the original header details
  hdr.orig    = {};
  hdr.orig{1} = lfphdr;
  hdr.orig{2} = muahdr;
  hdr.orig{3} = spikehdr;

  % return the header
  dat = hdr;
else

  % use the original header details
  lfphdr   = hdr.orig{1};
  muahdr   = hdr.orig{2};
  spikehdr = hdr.orig{3};
  % the spike header does not contain these, but requires them from the LFP or MUA
  spikehdr.FirstTimeStamp     = hdr.FirstTimeStamp;
  spikehdr.TimeStampPerSample = hdr.TimeStampPerSample;

  if ~isempty(lfphdr)
    Nlfp = lfphdr.nChans;
  else
    Nlfp = 0;
  end

  if ~isempty(muahdr)
    Nmua = muahdr.nChans;
  else
    Nmua = 0;
  end

  if ~isempty(spikehdr)
    Nspike = spikehdr.nChans;
  else
    Nspike = 0;
  end

  % determine which files should be read from each respective dataset
  selchan = zeros(hdr.nChans,1);
  selchan(chanindx) = 1;
  sellfp   = find(selchan(1:Nlfp));
  selmua   = find(selchan((Nlfp+1):(Nlfp+Nmua)));
  selspike = find(selchan((Nlfp+Nmua+1):(Nlfp+Nmua+Nspike)));

  if haslfp
    % the header contains the relevant file names
    lfpdat = read_neuralynx_ds([], lfphdr, begsample, endsample, sellfp);
  else
    lfpdat = [];
  end

  if hasmua
    % the header contains the relevant file names
    muadat = read_neuralynx_ds([], muahdr, begsample, endsample, selmua);
  else
    muadat = [];
  end

  if hasspike
    % the header contains the relevant file names
    spikedat = read_neuralynx_ds([], spikehdr, begsample, endsample, selspike);
  else
    spikedat = [];
  end

  % combine all data into a single array
  dat = cat(1, lfpdat, muadat, spikedat);

end


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

function test_check_external_nifti()
    % nifti comes with CoSMoMVPA, so should always be available if the path
    % is set properly

    warning_state=cosmo_warning();
    orig_path=path();

    warning_state_resetter=onCleanup(@()cosmo_warning(warning_state));
    path_resetter=onCleanup(@()path(orig_path));

    % ensure path is set; disable warnings by cosmo_set_path
    cosmo_warning('off');
    cosmo_set_path();

    assertTrue(cosmo_check_external('nifti'))
    assertEqual(cosmo_check_external({'nifti','nifti'}),[true;true]);

    % test list
    externals=cosmo_check_external('-list');
    assert(~isempty(strmatch('nifti',externals,'exact')));

    % test tic/toc
    cosmo_check_external('-tic');
    assert(isempty(cosmo_check_external('-toc')));

    % must cite CoSMoMVPA, but not NIFTI
    c=cosmo_check_external('-cite');
    assert(~isempty(findstr(c,'N. N. Oosterhof')));
    assert(~isempty(findstr(c,'CoSMoMVPA')));
    assert(isempty(findstr(c,'NIFTI toolbox')));

    % after checking for nifti it must be present
    cosmo_check_external('nifti');
    assertEqual(cosmo_check_external('-toc'),{'nifti'});
    c=cosmo_check_external('-cite');
    assert(~isempty(findstr(c,'NIFTI toolbox')));

    % removing nifti from the path makes it absent
    rmpath(fileparts(which('load_nii')));
    assertFalse(cosmo_check_external('nifti',false));

    % throws exception when second argument is true or absent
    assertExceptionThrown(@()cosmo_check_external('nifti',true),'');
    assertExceptionThrown(@()cosmo_check_external('nifti'),'');

function test_check_external_mocov()
    has_mocov=~isempty(which('mocov'));
    assertEqual(has_mocov,cosmo_check_external('mocov',false));

function test_check_external_command()
    commands={'foo','basdfds','disp'};
    n=numel(commands);
    for k=1:n
        command=commands{k};
        has_command=~isempty(which(command));

        arg=['!' command];
        if has_command
            assertTrue(cosmo_check_external(arg));
            assertTrue(cosmo_check_external(arg,true));
            assertTrue(cosmo_check_external(arg,false));
        else
            assertExceptionThrown(@()cosmo_check_external(arg),'');
            assertExceptionThrown(@()cosmo_check_external(arg,true),'');
            assertFalse(cosmo_check_external(arg,false));
        end
    end

function test_check_external_exceptions()
    aet=@(varargin)assertExceptionThrown(@()...
                    cosmo_check_external(varargin{:}),'');
    aet('unknown package');


function [parsed_update,annotedText] = writeCD(parsed,fname_out)
% Write the parsed CD model structure to a CD-compatible XML file.
%
% USAGE:
%
%    [parsed_update, annotedText] = writeCD(fname, parsed, fname_out)
%
% INPUTS:
%    fname:            The original XML file
%    parsed:           A parsed model structure generated by `parseCD` function.
%    fanme_out:        The name of the output XML file.
%
% OUTPUTS:
%    parsed_update:    An updated version of the parsed
%    annotedText:      A matlab variable storing the all the XML lines
%
% EXAMPLE:
%
%    aaa = writeXML('PD_140620_1.xml', parsePD,'text.html')
%
% .. Author: - Longfei Mao Oct/2014

if nargin<2 || isempty(fname_out)

    [fname_out, fpath]=uiputfile('*.xml','CellDesigner SBML Source File');
    if(fname_out==0)
        return;
    end
    f_out=fopen([fpath,fname_out],'w');
else
    f_out=fopen(fname_out,'w');
end

if isfield(parsed.r_info,'XMLtext');
    text=parsed.r_info.XMLtext;
else
    errordlg('The XMLtext doesn''t exit in the parsed model structure');
end

%%%%%%%%%%%%%%%%%%%%%%%%  modify

ref=readCD(parsed); %% read the the list of the reactions and associated information.
% ref=parsed.r_info;

r_c=size(ref.number)

%while ~feof(f_id);

%numOfLine=0;
%rem=fgets(f_id);numOfLine=numOfLine+1;

items={'width','color'};

for r=1:r_c(1,1); % the row number; the reaction number.

    for c=1:r_c(1,2); % the column number
        % numOfLine=numOfLine+1;
        %disp(numOfLine);

        if isnumeric(ref.number(r,c))&&ref.number(r,c)>0;
            num=ref.number(r,c) % the pre-identified row number
            %%% <read>

            %%
            for i=1:length(items); % the first round sets 'width'; the second round sets 'color'.

                subText=ref.(items{i})(r,c);
                %%% <write>
                reText=cellstr(text(num).str)
                %%% find location and replace it

             ToBeRplaced=position(reText,items{i})
                %%%
                %try
                if ~isstr(subText{1})  % test if subText{1} contains a string
                   warning('OK');
                   disp(subText{1});
                   subText{1}=num2str(subText{1}) % convert the double type into string type
                end

                text(num).str=strrep(text(num).str,ToBeRplaced,subText{1}) %% or subText{1}, exchangeable here.
                %catch

                disp(subText{1});

              % end

                % disp([numOfLine,subText,ToBeRplaced,text(numOfLine).str]);

                %disp(text(num).str);
                %disp(subText);
            end

        end
    end
end

annotedText=text;
parsed_update=parsed;
parsed_update.r_info=ref; % update r_info structure
parsed_update.r_info.XMLtext=text; % update XMLtext

%%%%%%%%%%%%%%%%%%%%%%%%  write to the file

for d=1:length(text);

    fprintf(f_out,'%s\n',char(text(d).str));

end

fclose(f_out);

end


function [D, names, counts] = LMcreateObjectIndexField(D)
%
% [D, names] = LMcreateObjectIndexField(D);
%
% This function adds a new field to the LabelMe index that provides a
% numeric index into the object class.
%
% The new field is:
%    annotation.object.namendx
% and this is a pointer into 'names'

% Create list of objects:
[names, counts, imagendx, objectndx, objclass_ndx] = LMobjectnames(D, 'name');
% add new field
for k = 1:length(objclass_ndx)
    D(imagendx(k)).annotation.object(objectndx(k)).namendx = objclass_ndx(k);
end


% Ini_Manager(fileName, raw_data)
%
% =========================================================================
%   OBJECT Ini_Manager
% =========================================================================
%
% DESCRIPTION:
%   Object to create / read / modify an ini file
%
% EXTENDS: Ini_Reader
%
% INI EXAMPLE:
%   [Section 1]
%       array = [1 2 3]
%       string = "I'm a string"
%       stringCellArray = ["I" "am" "a string cell" "array"]
%   ; I'm a comment
%   # I'm also a comment
%   [Section 2]
%       number = 10
%   [Section n]     # comment
%       double = 10.4
%
% REQUIRES:
%   log:     Logger Class
%   cprintf:    http://www.mathworks.com/matlabcentral/fileexchange/24093-cprintf-display-formatted-colored-text-in-the-command-window
%

%--------------------------------------------------------------------------
%               ___ ___ ___
%     __ _ ___ / __| _ | __|
%    / _` / _ \ (_ |  _|__ \
%    \__, \___/\___|_| |___/
%    |___/                    v 1.0RC1
%
%--------------------------------------------------------------------------
%  Copyright (C) 2021 Geomatics Research & Development srl (GReD)
%  Written by:        Andrea Gatti
%  Contributors:      Andrea Gatti, ...
%  A list of all the historical goGPS contributors is in CREDITS.nfo
%--------------------------------------------------------------------------
%
%    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/>.
%
%--------------------------------------------------------------------------
% 01100111 01101111 01000111 01010000 01010011
%--------------------------------------------------------------------------

classdef Ini_Manager < handle

    properties (Constant, GetAccess = 'private')
        STD_COMMENT  = '#';       % Character Identifying the start of a comments
    end

    properties (GetAccess = 'private', SetAccess = 'private')
        log = Logger.getInstance();        % Handler to the log object
        raw_data = {};                 % Cell array containing the file, each cell is a line
    end

    properties (GetAccess = 'public', SetAccess = 'protected')
        c_comment  = [';', Ini_Manager.STD_COMMENT];  % Character Identifying the start of a comments
        file_name = 'config.ini';         % Name (and full path) of the ini
        fid = 0;                          % Handle of the ini file
        rw = 'r';                         % File access mode (r/w)
        read_status = false;              % Flag of reading status

        % Structure containing the data: section -> name / ( key -> (name / data )
        section = {};
        %section{1}.name = 'Section Name';
        %section{1}.key = {};
        %section{1}.key{1}.name = 'Key name';
        %section{1}.key{1}.data = 100;
    end

    % =========================================================================
    %    STANDARD METHODS
    % =========================================================================
    methods

        % Creator ---------------------------------------------------------
        function this = Ini_Manager(file_name, raw_data)
        % Creator of the class
        % SYNTAX:  Ini_Manager(<file_name>, <raw_data>) creator
            if (nargin == 0)
                file_name = '';
            end
            if isempty(file_name)
                file_name = '';
            end

            if (nargin == 1) && iscell(file_name) % ---------------- Parse RAW but do not save it
                this.setFileName('');
                this.raw_data = file_name;
                this.setRW('w');
                this.cleanRaw();
                this.parseData();
                this.setReadStatus(true)
                this.raw_data = {};
            elseif (nargin == 2) % --------------------------------- Parse and save RAW
                this.setFileName(file_name);
                this.raw_data = raw_data;
                this.setRW('w');
                this.writeFile();
                this.cleanRaw();
                this.parseData();
                this.setReadStatus(true)
                this.raw_data = {};
            else
                this.setFileName(file_name);
            end
        end

        % Destructor ------------------------------------------------------
        function delete(this) %#ok<INUSD>
            % Empty Destructor
        end

        % Cleaner ---------------------------------------------------------
        function clearAll(this)
            % Reset the object
            this.fid = 0;
            this.rw = 'r';
            this.file_name = 'config.ini';
            this.raw_data = {};
            this.section = {};
        end

    end

    % =========================================================================
    %  FILE
    % =========================================================================
    methods

        % Set file name ---------------------------------------------------
        function setFileName(this, file_name)
            % Set the complete path of the ini file
            this.file_name = file_name;
        end

        % Get file name ---------------------------------------------------
        function file_name = getFileName(this)
            % Get the complete path of the ini file
            file_name = this.file_name;
        end

    end

    % =========================================================================
    %  INI SYNTAX
    % =========================================================================
    methods

        % Set Comment Character -------------------------------------------
        function setCommentChar(this, character)
            % define the characters that define comment lines
            this.c_comment = unique([character this.STD_COMMENT]);
        end

        % Get Comment Character -------------------------------------------
        function characters = getCommentChar(this)
            % Get the characters that define comment lines
            characters = this.c_comment;
        end

    end

    % =========================================================================
    %  R/W MODES OF THE FILE
    % =========================================================================
    methods

        % Set RW mode -----------------------------------------------------
        function setRW(this,rwMode)
            % Set mode for open the ini file
            if ( ~this.readMode() && ~writeMode())
                this.rw = 'r';
            else
                this.rw = rwMode;
            end
        end

        % Get RW mode -----------------------------------------------------
        function rwMode = getRW(this)
            % Get the current mode of the file
            rwMode = this.rw;
        end

        % Read mode? ------------------------------------------------------
        function bool = readMode(this)
            % Is it in read mode?
            if ((this.rw(1)=='r'))
                bool = true;
            else
                bool = false;
            end
        end

        % Write mode? -----------------------------------------------------
        function bool = writeMode(this)
            % Is it in write mode?
            if ((this.rw(1)=='w'))
                bool = true;
            else
                bool = false;
            end
        end

        % Get read status mode --------------------------------------------
        function bool = getReadStatus(this)
            % Return if the file has been already parsed
            bool = this.read_status;
        end

        % Read File -------------------------------------------------------
        function status = readFile(this)
            % Force reading of the File
            status = true;
            % If the object already contains data - clean it
            if (this.getReadStatus())
                this.raw_data = {};
            end
            if ~exist(this.getFileName(),'file')
                this.log.addError(sprintf('INI reading of file "%s" failed', this.getFileName()))
                status = false;
            else
                this.fid = fopen(this.getFileName(), this.getRW());

                if (this.fid ~= -1)   % If reading is ok
                    this.raw_data = textscan(this.fid, '%s', 'delimiter', '\n', 'endOfLine', '\r\n');
                    fclose(this.fid);

                    this.read_status = true;
                    this.raw_data = this.raw_data{1};

                    this.log.addStatusOk('The INI file has been parsed correctly.', 15);

                    this.cleanRaw();      % Strip comments and spaces
                    this.parseData();     % Parse file
                    this.raw_data = {};   % clean RAW temp data
                else
                    this.log.addError(['INI file read failed:' ferror(this.fid)]);
                    this.setReadStatus(false);
                    this.raw_data = {};
                end
            end
        end

        % Write File ------------------------------------------------------
        function errStatus = writeFile(this)
            % Force reading of the File
            errStatus = false;
            if isempty(this.getFileName())
                this.log.addError(sprintf('INI writing  of file "%s" failed', this.getFileName()));
                errStatus = true;
            else
                if (this.fid ~= -1)   % If file access is ok
                    try
                        this.fid = fopen(this.getFileName(), this.getRW());
                        % Convert raw data to string
                        tmp_str = '';
                        for i = 1 : numel(this.raw_data)
                            tmp_str = [tmp_str this.raw_data{i} 10]; %#ok<AGROW>
                        end
                        fwrite(this.fid, tmp_str);
                        fclose(this.fid);
                    catch ex
                        errStatus = true;
                        this.log.addError(['INI file cannot be written (' this.file_name '): ' ex.message]);
                    end

                    this.log.addStatusOk('The INI file has been writted correctly', 10);
                else
                    this.log.addError(['INI file write failed:' ferror(this.fid)]);
                end
            end
        end

        % Update File (when needed) ---------------------------------------
        function reloaded = update(this, file_name, force_read)
            % Update the object when needed:
            %  - file_name changed
            %  - force flag == 1
            %  - INI not yet read
            if nargin == 2
                force_read = 0;
            end
            reloaded = 0;
            if (~strcmp(file_name,this.getFileName) || (force_read == 1) || ~this.getReadStatus())
                this.setFileName(file_name);
                this.readFile();
                reloaded = 1;
            end
        end

    end

    % =========================================================================
    %  SEARCH FUNCTIONS
    % =========================================================================
    methods

        % Search a section in the object Ini_Manager ----------------------
        function isPresent = containsSection(this, section)
            % Search a section in the object Ini_Manager
            s = 1;
            while ((s<=length(this.section)) && (s ~= 0))
                if (strcmp(this.section{s}.name,section))
                    s = 0;
                else
                    s = s + 1;    % go on with the search of the section
                end
            end
            if (s == 0)
                isPresent = true;
            else
                isPresent = false;
            end
        end

        % Search a key in the object Ini_Manager --------------------------
        function isPresent = containsKey(this, section, key)
            % Search a key in the object Ini_Manager
            s = 1;
            while ((s<=length(this.section)) && (s ~= 0))
                if (strcmp(this.section{s}.name,section))
                    while ((k<=length(this.section{s}.key)) && (k ~= 0))
                        if (strcmp(this.section{s}.key{k}.name,key))
                            k = 0;
                        else
                            k = k + 1;
                        end
                    end
                    s = 0;
                else
                    s = s + 1;    % go on with the search of the section
                end
            end
            if (k == 0)
                isPresent = true;
            else
                isPresent = false;
            end
        end

    end

    % =========================================================================
    %  GETTER OF THE PARAMETERS
    % =========================================================================
    methods

        % Get the list of sections present in the file --------------------
        function section_list = getSections(this)
            % Get the list of available sections
            if (~this.getReadStatus())
                %this.printWarning('File not yet read!\n');
                this.readFile();
            end

            section_list = cell(length(this.section),1);
            for s=1:length(this.section)
                section_list{s} = this.section{s}.name;
            end
        end

        % Return the presence of a section --------------------------------
        function isS = isSection(this, section)
            % Get the presence of a section
            s = 1;
            while ((s<=length(this.section)) && (s ~= 0))
                if (strcmp(this.section{s}.name,section))
                    s = 0;      % Stop searching
                else
                    s = s+1;    % go on with the search of the section
                end
            end
           isS = s == 0;
        end

        % Return the presence of a key ------------------------------------
        function isK = isKey(this, section, key)
            % Get the presence of a key
            s = 1;
            k = 1;
            while ((s<=length(this.section)) && (s ~= 0))
                if (strcmp(this.section{s}.name,section))
                    k = 1;
                    while ((k<=length(this.section{s}.key)) && (k ~= 0))
                        if (strcmp(this.section{s}.key{k}.name,key))
                            k = 0;
                        else
                            k = k + 1;
                        end
                    end
                    s = 0;
                else
                    s = s + 1;    % go on with the search of the section
                end
            end
            isK = k == 0;
        end

        % Get the list of keys present in the file ------------------------
        function key_list = getKeys(this, section)
            % Get the list of the keys available
            if (nargin == 1)
                section = 0;
            end

            if (~this.getReadStatus())
                %this.printWarning('File not yet read!\n');
                this.readFile();
            end

            key_list = {};
            l = 1;
            if (section == 0)
                for s = 1:length(this.section)
                    for p = 1 : length(this.section{s}.key)
                        key_list{l} = this.section{s}.key{p}.name; %#ok<AGROW>
                        l = l+1;
                    end
                end
            else
                s = 1;
                while ((s<=length(this.section)) && (s ~= 0))
                    if (strcmp(this.section{s}.name,section))
                        for p = 1:length(this.section{s}.key)
                            key_list{l} = this.section{s}.key{p}.name; %#ok<AGROW>
                            l = l+1;
                        end
                        s = 0;      % Stop searching
                    else
                        s = s+1;    % go on with the search of the section
                    end
                end
            end
        end

        % Get data --------------------------------------------------------
        function data = getData(this, section, key)
            % Get the value of a specified key
            if (~this.getReadStatus() && isempty(this.section))
               %this.printWarning('File not yet read!\n');
               this.readFile();
            end
            found = false;
            data = [];
            if (nargin == 2)
                key = section;
                % Search the key among all the sections
                s = 1;
                while ((s<=length(this.section)) && (s > 0))
                    p = 1;
                    while ((p <= length(this.section{s}.key)) && (p ~= 0))
                        if (strcmp(this.section{s}.key{p}.name,key))
                            data = this.section{s}.key{p}.data;
                            found = true;
                            p = 0;      % Stop searching key
                        else
                            p = p+1;    % go on with the search of the key
                        end
                    end
                    if (p == 0)
                        s = 0;     % Stop searching section
                    else
                        s = s+1;   % go on with the search of the section
                    end
                end
                if ~found
                    this.log.addWarning(['Key "' key '" not found while reading: "' this.file_name '"'], 10);
                    data = [];
                end
            else
                % Search the key of a specific section
                s = 1;
                while ((s<=length(this.section)) && (s > 0))
                    if (strcmp(this.section{s}.name,section))
                        p = 1;
                        while ((p <= length(this.section{s}.key)) && (p ~= 0))
                            if (strcmp(this.section{s}.key{p}.name,key))
                                data = this.section{s}.key{p}.data;
                                found = true;
                                p = 0; % Stop searching key
                            else
                                p = p+1;    % go on with the search of the key
                            end
                        end
                        s = 0;      % Stop searching section
                    else
                        s = s+1;    % go on with the search of the section
                    end
                end
                if ~found
                    this.log.addWarning(['Key "' key '" not found in section "' section '" while reading: "' this.file_name '"'], 100);
                    data = [];
                end
            end

        end

    end

    % =========================================================================
    %  MODIFIER FUNCTIONS
    % =========================================================================
    methods

        % Add a new section to the object ---------------------------------
        function addSection(this, new_section)
            % Add a new section to the object
            if ~this.isSection(new_section)
                newId = length(this.section)+1;
                this.section{newId}.name = new_section;
                this.section{newId}.key = {};
            end
        end

        % Add a new keys to the object ------------------------------------
        function addKey(this, section, key, data)
            % Add a new key to the object if the section exist
            if this.isKey(section, key)
                this.editKey(section, key, data);
            else
                s = 1;
                while ((s<=length(this.section)) && (s ~= 0))
                    if (strcmp(this.section{s}.name,section))
                        newId = length(this.section{s}.key)+1;
                        this.section{s}.key{newId}.name = key;
                        this.section{s}.key{newId}.data = data;
                        s = 0;
                    else
                        s = s+1;    % go on with the search of the section
                    end
                end
                if (s ~= 0)
                    this.printError(['Section "' section '" not found!\n']);
                end
            end
        end

        % Add a data to the object giving key and section -----------------
        function addData(this, section, key, data)
            % Add a data to the object an eventually create the section and key to store it
            this.addSection(section)
            this.addKey(section, key, data)
        end

        % Remove a section from the object Ini_Manager --------------------
        function rmSection(this, section)
            % Remove a section from the object Ini_Manager
            s = 1;
            while ((s<=length(this.section)) && (s ~= 0))
                if (strcmp(this.section{s}.name,section))
                    this.section(s) = [];
                    s = 0;
                else
                    s = s+1;    % go on with the search of the section
                end
            end
            if (s ~= 0)
                this.printError(['Section "' section '" not found!\n']);
            end
        end

        % Remove a key from the object Ini_Manager ------------------------
        function rmKey(this, section, key)
            % Remove a key from the object Ini_Manager
            s = 1;
            k = 1;
            while ((s<=length(this.section)) && (s ~= 0))
                if (strcmp(this.section{s}.name,section))
                    k = 1;
                    while ((k<=length(this.section{s}.key)) && (k ~= 0))
                        if (strcmp(this.section{s}.key{k}.name,key))
                            this.section{s}.key(k) = [];
                            k = 0;
                        else
                            k = k + 1;
                        end
                    end
                    s = 0;
                else
                    s = s + 1;    % go on with the search of the section
                end
            end
            if (k ~= 0)
                this.printError(['Key "' key '" not found!\n']);
            end
        end

        % Edit a key in the object Ini_Manager ----------------------------
        function editKey(this, section, key, data)
            this.setData(section, key, data)
        end

        function setData(this, section, key, data)
            % Edit a key in the object Ini_Manager
            s = 1;
            k = 1;
            if (nargin == 3)
                data  = key;
                key = section;
                % Search the key among all the sections
                while ((s<=length(this.section)) && (s > 0))
                    p = 1;
                    while ((p <= length(this.section{s}.key)) && (p ~= 0))
                        if (strcmp(this.section{s}.key{p}.name,key))
                            this.section{s}.key{p}.data = data;
                            p = 0;      % Stop searching key
                        else
                            p = p+1;    % go on with the search of the key
                        end
                    end
                    if (p == 0)
                        s = 0;     % Stop searching section
                    else
                        s = s+1;   % go on with the search of the section
                    end
                end
                if (isempty(data))
                    this.log.addWarning(['Key "' key '" not found while reading: "' this.file_name '"'], 10);
                end
            else
                while ((s<=length(this.section)) && (s ~= 0))
                    if (strcmp(this.section{s}.name,section))
                        k = 1;
                        while ((k<=length(this.section{s}.key)) && (k ~= 0))
                            if (strcmp(this.section{s}.key{k}.name,key))
                                this.section{s}.key{k}.data = data;
                                k = 0;
                            else
                                k = k + 1;
                            end
                        end
                        s = 0;
                    else
                        s = s + 1;    % go on with the search of the section
                    end
                end
                if (k ~= 0)
                    this.log.addWarning(['Key "' key '" not found while reading: "' this.file_name '"'], 10);
                end
            end
        end

    end

    % =========================================================================
    %  VISUALIZATION FUNCTIONS (not using LOGGER) - for DEBUG
    % =========================================================================
    methods

        % List Sections ---------------------------------------------------
        function listSections(this, color_mode)
            % List the list of available sections
            if (nargin == 1)
                color_mode = this.log.getColorMode();
            end

            if (~this.getReadStatus())
                %this.printWarning('File not yet read!\n');

                this.readFile();
            end

            fprintf('        List of sections:\n')
            for s=1:length(this.section)
                this.printSection(this.section{s}.name, color_mode);
            end
        end

        % List Key --------------------------------------------------------
        function listKeys(this, section, color_mode)
            % List the list of the keys available
            if (nargin == 1)
                section = 0;
                color_mode = this.log.getColorMode();
            end
            if (nargin == 2)
                if (ischar(section))
                    color_mode = this.log.getColorMode();
                else
                    color_mode = section;
                    section = 0;
                end
            end

            if (~this.getReadStatus() && isempty(this.section))
                %this.printWarning('File not yet read!\n');
                this.readFile();
            end

            if (section == 0)
                fprintf('        List of all the keys:\n')
                for s = 1:length(this.section)
                    this.printSection(this.section{s}.name, color_mode);
                    for p = 1:length(this.section{s}.key)
                        this.printData(this.section{s}.key{p}.name, this.section{s}.key{p}.data, color_mode)
                    end
                end
            else
                fprintf('        List of all the keys in section "%s":\n', section)
                s = 1;
                while ((s<=length(this.section)) && (s ~= 0))
                    if (strcmp(this.section{s}.name,section))
                        this.printSection(this.section{s}.name, color_mode);
                        for p = 1:length(this.section{s}.key)
                            this.printData(this.section{s}.key{p}.name, this.section{s}.key{p}.data, color_mode)
                        end
                        s = 0;      % Stop searching
                    else
                        s = s+1;    % go on with the search of the section
                    end
                end
            end
        end

        % Show data -------------------------------------------------------
        function showData(this, section, color_mode)
            % List the data contained in the ini
            if (nargin == 1)
                section = 0;
                color_mode = this.log.getColorMode();
            end
            if (nargin == 2)
                if (ischar(section))
                    color_mode = this.log.getColorMode();
                else
                    color_mode = section;
                    section = 0;
                end
            end

            if (~this.getReadStatus())
                %this.printWarning('File not yet read')
                this.readFile();
            end

            if (section == 0)
                fprintf('        List of all the key values:\n')
                for s = 1:length(this.section)
                    this.printSection(this.section{s}.name, color_mode);
                    for p = 1:length(this.section{s}.key)
                        this.printData(this.section{s}.key{p}.name, this.section{s}.key{p}.data, color_mode)
                    end
                end
            else
                fprintf('        List of all the key values in section "%s":\n', section)
                s = 1;
                while ((s <= length(this.section)) && (s ~= 0))
                    if (strcmp(this.section{s}.name,section))
                        this.printSection(this.section{s}.name, color_mode);
                        for p = 1:length(this.section{s}.key)
                            this.printData(this.section{s}.key{p}.name, this.section{s}.key{p}.data, color_mode)
                        end
                        s = 0;      % Stop searching
                    else
                        s = s+1;    % go on with the search of the section
                    end
                end
            end
        end

    end

    % =========================================================================
    %   CUSTOM DISPLAY UTILITIES (not using LOGGER) - for DEBUG
    % =========================================================================

    methods (Access = 'protected')

        % Display a Section -----------------------------------------------
        function printSection(this, section, color_mode)
            % Display a sections on a tree
            if (nargin == 2)
                color_mode = this.color_mode;
            end
            if (color_mode)
                cprintf('blue','         - ');
                cprintf('text', '"%s"\n', section);
            else
                fprintf('         - "%s"\n', section);
            end
        end

        % Display a Key ---------------------------------------------------
        function printKey(this, key, color_mode)
            % Display a key on a tree
            if (nargin == 2)
                color_mode = this.color_mode;
            end
            if (color_mode)
                cprintf('blue','             |- ');
                cprintf('text', '"%s"\n', key);
            else
                fprintf('             |- "%s"\n', key);
            end
        end

        % Display a Key ---------------------------------------------------
        function printData(this, key, data, color_mode)
            % Display the data of a key
            if (nargin == 3)
                color_mode = this.color_mode;
            end
            if (color_mode)
                cprintf('blue','             |- ');
                tmpData = data;
                if (iscell(tmpData))    % The only dataset that can be a cell array is an array of strings
                    cprintf('text','"%s" = [', key);
                    for l = 1:size(tmpData,2)
                        cprintf('text', ' "%s"', tmpData{l});
                    end
                    cprintf('text', ' ]\n');
                else
                    % if it is not an array of string...
                    if (ischar(tmpData))
                        cprintf('text','"%s" = "%s"\n',key, tmpData);
                    else
                        cprintf('text','"%s" = %s\n',key, num2str(tmpData));
                    end
                end
            else
                tmpData = data;
                if (iscell(tmpData))    % The only dataset that can be a cell array is an array of strings
                    fprintf('             |- "%s" = [', key);
                    for l = 1:size(tmpData,2)
                        fprintf(' "%s"', tmpData{l});
                    end
                    fprintf(' ]\n');
                else
                    % if it iks not an array of string...
                    if (ischar(tmpData))
                        fprintf('             |- "%s" = "%s"\n',key, num2str(tmpData));
                    else
                        fprintf('             |- "%s" = %s\n',key, num2str(tmpData));
                    end
                end
            end
        end

    end

    % =========================================================================
    %    PRIVATE UTILITIES
    % =========================================================================
    methods (Access = 'private')

        % Strip empty/comment lines ---------------------------------------
        function cleanRaw(this)
            % Strip empty lines
            this.raw_data((cellfun(@length, this.raw_data)==0)) = [];
            % Strip commented lines
            r = 1;
            while (r <= length(this.raw_data))
                if ismember(this.raw_data{r}(1), this.c_comment)
                    this.raw_data(r) = [];
                else
                    r = r + 1;
                end
            end

            for r=1:length(this.raw_data)
                % Strip inline comments

                start = regexp(this.raw_data{r}, ['([' this.c_comment ']).*'], 'start');
                if (~isempty(start))
                    this.raw_data{r}(start:end) = [];
                end

                start = regexp(this.raw_data{r}, ' *$', 'start');
                if (~isempty(start))
                    this.raw_data{r}(start:end) = [];
                end
            end
        end

        % Parse the file (cleaned) ----------------------------------------
        function parseData(this)
            p = 0;
            s = 0;
            this.section = {};
            for r=1:length(this.raw_data)
                section_name = regexp(this.raw_data{r}, '(?<=^\[).*(?=\])', 'match');
                if (~isempty(section_name))
                    % we have a new SECTION!
                    s = s+1;
                    p = 0;
                    this.section{s}.name = section_name{1};
                    this.section{s}.key = [];
                else
                    % maybe this line contains a key, let's check
                    par_name = regexp(this.raw_data{r}, '^(.*(?=\s\=))', 'match');
                    if (isempty(par_name))
                        par_name = regexp(this.raw_data{r}, '^(.*(?=\=))', 'match');
                    end
                    if (~isempty(par_name))
                        % we have a PARAMETER!
                        p = p+1;
                        if (s == 0)
                            s = s + 1;
                            this.section{s}.name = 'Section';
                            this.section{s}.key = [];
                        end
                        this.section{s}.key{p}.name = par_name{1};
                        this.section{s}.key{p}.data = Ini_Manager.str2value(this.raw_data{r});
                    end
                end
            end
        end

        % Set read status -------------------------------------------------
        function setReadStatus(this, bool)
            this.read_status = bool;
        end
    end

    % =========================================================================
    %  STATIC STRING GENERATION FROM INI TO STR
    % =========================================================================

    methods (Static)

        % str2value -------------------------------------------------------
        function value = str2value(raw_data)
            % Get the DATA!
            str_data = regexp(raw_data, '(?<=\=).*', 'match');
            if (isempty(str_data))
                value = [];
            else
                tmpData = str2num(str_data{1}); %#ok<ST2NM>
                if (~isempty(tmpData) && isnumeric(tmpData))   % It's a number!
                    value = tmpData;
                else
                    % It's a string!
                    % If it is a string properly formatted "string data"
                    tmpData = regexp(str_data{1}, '(?<=\")[^"]*(?=\")', 'match');
                    if (~isempty(tmpData))
                        if (size(tmpData,2) == 1)
                            value = tmpData{1};
                        else
                            % Strip empty cells
                            tmpData((cellfun(@length, tmpData)==0)) = [];
                            % Strip space only cells
                            for c=size(tmpData,2):-1:1
                                if isempty(regexp(tmpData{c}, '[^ ]*', 'match'))
                                    tmpData(c) = [];
                                end
                            end
                            value = tmpData;
                        end
                    else
                        % If it appears to be an empty string
                        value = '';
                    end
                end
            end
        end

        % cellStringtoString ----------------------------------------------
        function str = strCell2Str(value)
            % Converta cell of string to string
            % SYNTAX:
            %   str = strCell2Str(value)
            if ~isempty(value)
                if ~iscell(value)
                    value = {value};
                end
                str = strcat('"', value{1}, '"');
                for i = 2 : numel(value)
                    str = strcat(str, ' "', value{i}, '"');
                end
            else
                str = '[]';
            end
        end

        % toIniString -----------------------------------------------------
        function cell_str = toIniString(variable_name, value, format, cell_str)
            % Convert any variable to ini string format
            % SYNTAX:
            %   cell_str = toIniString(variable_name, value)
            %   cell_str = toIniString(variable_name, value, format)
            %   cell_str = toIniString(variable_name, value, cell_str)
            %   cell_str = toIniString(variable_name, value, format, cell_str)
            switch nargin
                case 1
                    error('Error in Ini_Manager.toIniString, too few parameters');
                case 2

                    format = '';
                    cell_str = {};
                case 3
                    if iscellstr(format)
                        cell_str = format;
                        format = '%g';
                    else
                        cell_str = {};
                    end
                case 4
                    % ok
            end

            if ischar(value) % is string
                cell_str{numel(cell_str) + 1} = [variable_name ' = "' value(:)' '"'];
            elseif isnumeric(value)
                if isempty(format)
                    format = '%g';
                else
                    format = strtrim(format);
                end
                if numel(value) > 1 % it's an array of values
                    format = [format ' '];
                    tmp = sprintf(format,value);
                    cell_str{numel(cell_str) + 1} = [variable_name ' = [' tmp(1:end-1) ']'];
                    clear tmp;
                else
                    cell_str{numel(cell_str) + 1} = [variable_name ' = ' sprintf(format,value)];
                end
            else % generic converter (may not work properly)
                toString = @(var) strtrim(regexprep(evalc('disp(var)'), '\n', ''));
                if iscell(value)
                    if ~isempty(value) && ischar(value{1})
                        cell_str{numel(cell_str) + 1} = [variable_name ' = [' Ini_Manager.strCell2Str(value) ']'];
                    else
                        cell_str{numel(cell_str) + 1} = [variable_name ' = [' toString(value) ']'];
                    end
                else
                    cell_str{numel(cell_str) + 1} = [variable_name ' = ' toString(value)];
                end
            end

            % I want a column array
            if size(cell_str,1) < size(cell_str,2)
                cell_str = cell_str';
            end
        end

        % toIniString Section ---------------------------------------------
        function cell_str = toIniStringSection(section_name, cell_str)
            % Add a section in ini string format
            % SYNTAX:
            %   cell_str = toIniStringSection(section_name, cell_str)
            if (nargin == 1)
                cell_str = {};
            end

            cell_str{numel(cell_str) + 1} = [Ini_Manager.STD_COMMENT '----------------------------------------------------------------------------------'];
            cell_str{numel(cell_str) + 1} = ['[' section_name ']'];
            cell_str{numel(cell_str) + 1} = [Ini_Manager.STD_COMMENT '----------------------------------------------------------------------------------'];

            % I want a column array
            if size(cell_str,1) < size(cell_str,2)
                cell_str = cell_str';
            end
        end

        % toIniString Comment ---------------------------------------------
        function cell_str = toIniStringComment(comment, cell_str)
            % Add a comment in ini string format
            % SYNTAX:
            %   cell_str = toIniStringComment(comment, cell_str)
            if (nargin == 1)
                cell_str = {};
            end
            line_lim = strfind(comment, 10);
            line_lim = [[1; line_lim'] [line_lim'; numel(comment)]];
            for i = 1 : size(line_lim, 1)
                cell_str{numel(cell_str) + 1} = [ Ini_Manager.STD_COMMENT ' ' strrep(comment(line_lim(i, 1) : line_lim(i, 2)), char(10), '')];
            end

            % I want a column array
            if size(cell_str,1) < size(cell_str,2)
                cell_str = cell_str';
            end
        end

        % toIniString New Line --------------------------------------------
        function cell_str = toIniStringNewLine(cell_str)
            % Add a new line in ini string format
            % SYNTAX:
            %   cell_str = toIniStringSection(section_name, cell_str)
            if (nargin == 0)
                cell_str = {};
            end
            cell_str{numel(cell_str) + 1} = '';

            % I want a column array
            if size(cell_str,1) < size(cell_str,2)
                cell_str = cell_str';
            end
        end
    end
end


% CREATE_SRC Create a source of files & objects
%
% Usage
%    src = CREATE_SRC(directory, objects_fun)
%
% Input
%    directory (char): The directory in which the files are found.
%    objects_fun (function handle): Given a filename, objects_fun returns its
%       constituent objects and their respective classes.
%
% Output
%    src (struct): The source corresponding to all data files (.jpg, .wav,
%       .au) contained in directory and their objects as defined by
%       objects_fun.
%
% See also
%    PREPARE_DATABASE

function src = create_src(directory,objects_fun)
	if nargin < 1
		error('Must specify directory!');
	end

	if nargin < 2
		objects_fun = @default_objects_fun;
	end

	files = find_files(directory);

	if isempty(files)
		error('No data files found in the specified directory!');
	end

	objects = [];
	classes = [];

	for ind = 1:length(files)

		[file_objects,file_classes] = objects_fun(files{ind});

		if ~isempty(file_objects)
			file_objects = arrayfun(@(s)(setfield(s,'ind',ind)),file_objects);
		end

		objects = [objects file_objects];
		classes = [classes file_classes];
	end

	file_inds = [objects.ind];

	[file_inds,I,J] = unique(file_inds);

	J = num2cell(J);

	[objects.ind] = J{:};

	files = files(file_inds);

	fields = fieldnames(objects)';
	fields(strmatch('ind',fields)) = [];
	fields(strmatch('u1',fields)) = [];
	fields(strmatch('u2',fields)) = [];

	objects = orderfields(objects,[{'ind','u1','u2'} fields]);

	[classes,temp,obj_class] = unique(classes);

	obj_class = num2cell(obj_class);

	[objects.class] = obj_class{:};

	src.classes = classes;
	src.files = files;
	src.objects = objects;
end

function files = find_files(directory)
	extensions = {'au','wav','jpg','png'};

	dir_list = dir(directory);

	files = {};

	for k = 1:length(dir_list)
		name = dir_list(k).name;

		% Hidden file or current/upper directory? Skip.
		if name(1) == '.'
			continue;
		end

		% Depending on file type, recurse or add audio file.
		if dir_list(k).isdir
			files = [files find_files(fullfile(directory,name))];
		else
			found = 0;
			for l = 1:length(extensions)
				len = length(extensions{l});
				if length(name) > len+1 && ...
				   strcmpi(name(end-len:end),['.' extensions{l}])
					found = l;
					break;
				end
			end
			if found > 0
				files = [files fullfile(directory,name)];
			end
		end
	end
end


function index = end(X,position,numindices)
%END (overloaded)

if nargin == 2
    index = X.dim(position);
else
    if numindices == 1
        index = prod(X.dim);
    elseif numindices == length(X.dim)
        index = X.dim(position);
    else
        error('Indexing logic not supported yet');
    end
end


%DIPIMAGECHECK  Check whether the DIP_IMAGE toolbox is in the path

function dipimagecheck

	if exist('dip_image','file') ~= 3
		error([newline 'The DIPIMAGE package is needed and not found.' ...
      newline 'Please download and install it from http://www.diplib.org/'])
	end


function c = diff(c)
   % DIFF differentiate each trace.
   %
   % C = DIFF(C) differentiate each trace through a call to WAVEFORM/DIFF.
   % See WAVEFORM/DIFF for details

   % Author: Michael West, Geophysical Institute, Univ. of Alaska Fairbanks
   % $Date$
   % $Revision$

   c.traces = diff(c.traces);
end


function [datapt, unitStr] = lvd_ExtremaTasks(stateLogEntry, subTask, extremum)
%lvd_ExtremaTasks Summary of this function goes here
%   Detailed explanation goes here

    switch subTask
        case 'extremumValue'
            extremaStates = stateLogEntry.getAllExtremaStates();
            extremaState = extremaStates([extremaStates.extrema] == extremum);

            if(not(isempty(extremaState)))
                extremaState = extremaState(1);
                datapt = extremaState.value;

                if(isempty(datapt))
                    datapt = -1;
                end

                unitStr = extremaState.extrema.unitStr;
            else
                datapt = -1;
            end
    end
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 [ iRead, fVals, i64Time ] = CEDS64ReadWaveF( fhand, iChan, iN, i64From, i64To, maskh )
%CEDS64READWAVE32 Reads wave data from a waveform or realwave channel as singles (32-bit floats).
%   [ iRead, fVals, i64Time ] = CEDS64ReadWaveF( fhand, iChan, iN, i64From {, i64To {, maskh} } )
%   Inputs
%   fhand - An integer handle to an open file
%   iChan - A channel number for a Waveform or Realwave channel
%   iN - The maximum number of data points  to copy
%   i64From - The time in ticks of the earliest time you want to read
%   i64To - (Optional) The time in ticks of the latest time you want to
%   read. If not set or set to -1, read to the end of the channel
%   maskh - (Optional) An integer handle to a marker mask (only used when reading wavemarkers)
%   Outputs
%   iRead - The number of data points read
%   fVals - An array of floats conatining the data points
%   i64Time - The time in ticks of the first data point

if (nargin < 4)
    iRead = -22;
    return;
end

outwavepointer = zeros(iN,1, 'single');
outtimepointer = zeros(1,1,'int64');

if (nargin < 5)
    i64To = -1;
end

if (nargin < 6)
    maskcode = -1;
else
    maskcode = maskh;
end

[iRead, fVals, i64Time] = calllib('ceds64int', 'S64ReadWaveF', fhand, iChan, outwavepointer, iN, i64From, i64To, outtimepointer, maskcode);

if iRead > 0
    fVals(iRead+1:end) = [];
else
    fVals = [];
end
end


classdef deLaValleePoussinKernel
% This class is obsolet since MTEX 5.9. Use the class @SO3DeLaValleePoussinKernel
% instead. Anyway the class is preserved, so that the kernels of saved
% unimodal @ODFs can be loaded.

methods (Hidden = true)

  function psi = deLaValleePoussinKernel(varargin)

    warning(['The syntax "deLaValleePoussinKernel" is obsolete. ' ...
      'Please use "SO3DeLaValleePoussinKernel" instead.'])

    psi = SO3DeLaValleePoussinKernel(varargin{:});

  end
end

methods (Static = true, Hidden=true)
  function psi = loadobj(s)
    psi = SO3DeLaValleePoussinKernel(s.kappa);
  end
end

end